Merge branch 'master'
authorJeff Garzik <jeff@garzik.org>
Wed, 22 Mar 2006 11:09:31 +0000 (06:09 -0500)
committerJeff Garzik <jeff@garzik.org>
Wed, 22 Mar 2006 11:09:31 +0000 (06:09 -0500)
38 files changed:
arch/ia64/Kconfig
arch/ia64/configs/tiger_defconfig
arch/ia64/kernel/acpi.c
arch/ia64/kernel/entry.S
arch/ia64/kernel/iosapic.c
arch/ia64/kernel/irq.c
arch/ia64/kernel/mca.c
arch/ia64/kernel/perfmon.c
arch/ia64/kernel/signal.c
arch/ia64/kernel/smpboot.c
arch/ia64/kernel/time.c
arch/ia64/kernel/topology.c
arch/ia64/mm/contig.c
arch/ia64/mm/discontig.c
arch/ia64/sn/kernel/Makefile
arch/ia64/sn/kernel/pio_phys.S [new file with mode: 0644]
arch/ia64/sn/kernel/setup.c
arch/ia64/sn/kernel/sn2/sn2_smp.c
arch/ia64/sn/kernel/xpc_channel.c
arch/ia64/sn/kernel/xpc_main.c
arch/ia64/sn/kernel/xpc_partition.c
arch/ia64/sn/pci/tioce_provider.c
drivers/char/snsc.h
drivers/char/snsc_event.c
drivers/sn/ioc4.c
include/asm-ia64/intel_intrin.h
include/asm-ia64/machvec.h
include/asm-ia64/machvec_sn2.h
include/asm-ia64/mca.h
include/asm-ia64/mutex.h
include/asm-ia64/processor.h
include/asm-ia64/signal.h
include/asm-ia64/sn/addrs.h
include/asm-ia64/sn/rw_mmr.h
include/asm-ia64/sn/tioce.h
include/asm-ia64/sn/xpc.h
include/asm-ia64/system.h
include/asm-ia64/thread_info.h

index a85ea9d37f056de90e4eaecf5124404ef51ce767..ff7ae6b664e8af12509a0f5d19f0231ce34dd14d 100644 (file)
@@ -271,6 +271,25 @@ config SCHED_SMT
          Intel IA64 chips with MultiThreading at a cost of slightly increased
          overhead in some places. If unsure say N here.
 
+config PERMIT_BSP_REMOVE
+       bool "Support removal of Bootstrap Processor"
+       depends on HOTPLUG_CPU
+       default n
+       ---help---
+       Say Y here if your platform SAL will support removal of BSP with HOTPLUG_CPU
+       support. 
+
+config FORCE_CPEI_RETARGET
+       bool "Force assumption that CPEI can be re-targetted"
+       depends on PERMIT_BSP_REMOVE
+       default n
+       ---help---
+       Say Y if you need to force the assumption that CPEI can be re-targetted to
+       any cpu in the system. This hint is available via ACPI 3.0 specifications.
+       Tiger4 systems are capable of re-directing CPEI to any CPU other than BSP.
+       This option it useful to enable this feature on older BIOS's as well.
+       You can also enable this by using boot command line option force_cpei=1.
+
 config PREEMPT
        bool "Preemptible Kernel"
         help
index 125568118b847b97dbe217c5367d1a1871444699..766bf495543249e44bfd69d92a31ebd3a69b47cc 100644 (file)
@@ -116,6 +116,8 @@ CONFIG_FORCE_MAX_ZONEORDER=17
 CONFIG_SMP=y
 CONFIG_NR_CPUS=4
 CONFIG_HOTPLUG_CPU=y
+CONFIG_PERMIT_BSP_REMOVE=y
+CONFIG_FORCE_CPEI_RETARGET=y
 # CONFIG_SCHED_SMT is not set
 # CONFIG_PREEMPT is not set
 CONFIG_SELECT_MEMORY_MODEL=y
index ecd44bdc8394fee371fc944af433163d0adb3952..4722ec51c70c6583ca38729f181d3779ad2e5146 100644 (file)
@@ -284,19 +284,24 @@ acpi_parse_plat_int_src(acpi_table_entry_header * header,
        return 0;
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
 unsigned int can_cpei_retarget(void)
 {
        extern int cpe_vector;
+       extern unsigned int force_cpei_retarget;
 
        /*
         * Only if CPEI is supported and the override flag
         * is present, otherwise return that its re-targettable
         * if we are in polling mode.
         */
-       if (cpe_vector > 0 && !acpi_cpei_override)
-               return 0;
-       else
-               return 1;
+       if (cpe_vector > 0) {
+               if (acpi_cpei_override || force_cpei_retarget)
+                       return 1;
+               else
+                       return 0;
+       }
+       return 1;
 }
 
 unsigned int is_cpu_cpei_target(unsigned int cpu)
@@ -315,6 +320,7 @@ void set_cpei_target_cpu(unsigned int cpu)
 {
        acpi_cpei_phys_cpuid = cpu_physical_id(cpu);
 }
+#endif
 
 unsigned int get_cpei_target_cpu(void)
 {
index 930fdfca6ddb610092a92f692419469fe4cab39d..0e3eda99e5494eb21187894dae2556717d37f6f0 100644 (file)
@@ -1102,9 +1102,6 @@ skip_rbs_switch:
        st8 [r2]=r8
        st8 [r3]=r10
 .work_pending:
-       tbit.nz p6,p0=r31,TIF_SIGDELAYED                // signal delayed from  MCA/INIT/NMI/PMI context?
-(p6)   br.cond.sptk.few .sigdelayed
-       ;;
        tbit.z p6,p0=r31,TIF_NEED_RESCHED               // current_thread_info()->need_resched==0?
 (p6)   br.cond.sptk.few .notify
 #ifdef CONFIG_PREEMPT
@@ -1131,17 +1128,6 @@ skip_rbs_switch:
 (pLvSys)br.cond.sptk.few  .work_pending_syscall_end
        br.cond.sptk.many .work_processed_kernel        // don't re-check
 
-// There is a delayed signal that was detected in MCA/INIT/NMI/PMI context where
-// it could not be delivered.  Deliver it now.  The signal might be for us and
-// may set TIF_SIGPENDING, so redrive ia64_leave_* after processing the delayed
-// signal.
-
-.sigdelayed:
-       br.call.sptk.many rp=do_sigdelayed
-       cmp.eq p6,p0=r0,r0                              // p6 <- 1, always re-check
-(pLvSys)br.cond.sptk.few  .work_pending_syscall_end
-       br.cond.sptk.many .work_processed_kernel        // re-check
-
 .work_pending_syscall_end:
        adds r2=PT(R8)+16,r12
        adds r3=PT(R10)+16,r12
index 574084f343fad79b32406c6e8b354c23554594bf..8832c553230ae1681e051858afd6912cb6a289f7 100644 (file)
@@ -631,6 +631,7 @@ get_target_cpu (unsigned int gsi, int vector)
 {
 #ifdef CONFIG_SMP
        static int cpu = -1;
+       extern int cpe_vector;
 
        /*
         * In case of vector shared by multiple RTEs, all RTEs that
@@ -653,6 +654,11 @@ get_target_cpu (unsigned int gsi, int vector)
        if (!cpu_online(smp_processor_id()))
                return cpu_physical_id(smp_processor_id());
 
+#ifdef CONFIG_ACPI
+       if (cpe_vector > 0 && vector == IA64_CPEP_VECTOR)
+               return get_cpei_target_cpu();
+#endif
+
 #ifdef CONFIG_NUMA
        {
                int num_cpus, cpu_index, iosapic_index, numa_cpu, i = 0;
index d33244c3275914f8ecdfeb769c1a9aad92710eff..5ce908ef9c9585f5f0350503fa39caf0e3e732bf 100644 (file)
@@ -163,8 +163,19 @@ void fixup_irqs(void)
 {
        unsigned int irq;
        extern void ia64_process_pending_intr(void);
+       extern void ia64_disable_timer(void);
+       extern volatile int time_keeper_id;
+
+       ia64_disable_timer();
+
+       /*
+        * Find a new timesync master
+        */
+       if (smp_processor_id() == time_keeper_id) {
+               time_keeper_id = first_cpu(cpu_online_map);
+               printk ("CPU %d is now promoted to time-keeper master\n", time_keeper_id);
+       }
 
-       ia64_set_itv(1<<16);
        /*
         * Phase 1: Locate irq's bound to this cpu and
         * relocate them for cpu removal.
index ee7eec9ee57648cee03a84aeacea97651577131d..b57e723f194c782aa6bc639717dcd57d5db0a947 100644 (file)
@@ -281,14 +281,10 @@ ia64_mca_log_sal_error_record(int sal_info_type)
                ia64_sal_clear_state_info(sal_info_type);
 }
 
-/*
- * platform dependent error handling
- */
-#ifndef PLATFORM_MCA_HANDLERS
-
 #ifdef CONFIG_ACPI
 
 int cpe_vector = -1;
+int ia64_cpe_irq = -1;
 
 static irqreturn_t
 ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs)
@@ -377,8 +373,6 @@ ia64_mca_register_cpev (int cpev)
 }
 #endif /* CONFIG_ACPI */
 
-#endif /* PLATFORM_MCA_HANDLERS */
-
 /*
  * ia64_mca_cmc_vector_setup
  *
@@ -630,6 +624,32 @@ copy_reg(const u64 *fr, u64 fnat, u64 *tr, u64 *tnat)
        *tnat |= (nat << tslot);
 }
 
+/* Change the comm field on the MCA/INT task to include the pid that
+ * was interrupted, it makes for easier debugging.  If that pid was 0
+ * (swapper or nested MCA/INIT) then use the start of the previous comm
+ * field suffixed with its cpu.
+ */
+
+static void
+ia64_mca_modify_comm(const task_t *previous_current)
+{
+       char *p, comm[sizeof(current->comm)];
+       if (previous_current->pid)
+               snprintf(comm, sizeof(comm), "%s %d",
+                       current->comm, previous_current->pid);
+       else {
+               int l;
+               if ((p = strchr(previous_current->comm, ' ')))
+                       l = p - previous_current->comm;
+               else
+                       l = strlen(previous_current->comm);
+               snprintf(comm, sizeof(comm), "%s %*s %d",
+                       current->comm, l, previous_current->comm,
+                       task_thread_info(previous_current)->cpu);
+       }
+       memcpy(current->comm, comm, sizeof(current->comm));
+}
+
 /* On entry to this routine, we are running on the per cpu stack, see
  * mca_asm.h.  The original stack has not been touched by this event.  Some of
  * the original stack's registers will be in the RBS on this stack.  This stack
@@ -648,7 +668,7 @@ ia64_mca_modify_original_stack(struct pt_regs *regs,
                struct ia64_sal_os_state *sos,
                const char *type)
 {
-       char *p, comm[sizeof(current->comm)];
+       char *p;
        ia64_va va;
        extern char ia64_leave_kernel[];        /* Need asm address, not function descriptor */
        const pal_min_state_area_t *ms = sos->pal_min_state;
@@ -721,6 +741,10 @@ ia64_mca_modify_original_stack(struct pt_regs *regs,
        /* Verify the previous stack state before we change it */
        if (user_mode(regs)) {
                msg = "occurred in user space";
+               /* previous_current is guaranteed to be valid when the task was
+                * in user space, so ...
+                */
+               ia64_mca_modify_comm(previous_current);
                goto no_mod;
        }
        if (r13 != sos->prev_IA64_KR_CURRENT) {
@@ -750,25 +774,7 @@ ia64_mca_modify_original_stack(struct pt_regs *regs,
                goto no_mod;
        }
 
-       /* Change the comm field on the MCA/INT task to include the pid that
-        * was interrupted, it makes for easier debugging.  If that pid was 0
-        * (swapper or nested MCA/INIT) then use the start of the previous comm
-        * field suffixed with its cpu.
-        */
-       if (previous_current->pid)
-               snprintf(comm, sizeof(comm), "%s %d",
-                       current->comm, previous_current->pid);
-       else {
-               int l;
-               if ((p = strchr(previous_current->comm, ' ')))
-                       l = p - previous_current->comm;
-               else
-                       l = strlen(previous_current->comm);
-               snprintf(comm, sizeof(comm), "%s %*s %d",
-                       current->comm, l, previous_current->comm,
-                       task_thread_info(previous_current)->cpu);
-       }
-       memcpy(current->comm, comm, sizeof(current->comm));
+       ia64_mca_modify_comm(previous_current);
 
        /* Make the original task look blocked.  First stack a struct pt_regs,
         * describing the state at the time of interrupt.  mca_asm.S built a
@@ -908,7 +914,7 @@ no_mod:
 static void
 ia64_wait_for_slaves(int monarch)
 {
-       int c, wait = 0;
+       int c, wait = 0, missing = 0;
        for_each_online_cpu(c) {
                if (c == monarch)
                        continue;
@@ -919,15 +925,32 @@ ia64_wait_for_slaves(int monarch)
                }
        }
        if (!wait)
-               return;
+               goto all_in;
        for_each_online_cpu(c) {
                if (c == monarch)
                        continue;
                if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE) {
                        udelay(5*1000000);      /* wait 5 seconds for slaves (arbitrary) */
+                       if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE)
+                               missing = 1;
                        break;
                }
        }
+       if (!missing)
+               goto all_in;
+       printk(KERN_INFO "OS MCA slave did not rendezvous on cpu");
+       for_each_online_cpu(c) {
+               if (c == monarch)
+                       continue;
+               if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE)
+                       printk(" %d", c);
+       }
+       printk("\n");
+       return;
+
+all_in:
+       printk(KERN_INFO "All OS MCA slaves have reached rendezvous\n");
+       return;
 }
 
 /*
@@ -953,6 +976,10 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
        task_t *previous_current;
 
        oops_in_progress = 1;   /* FIXME: make printk NMI/MCA/INIT safe */
+       console_loglevel = 15;  /* make sure printks make it to console */
+       printk(KERN_INFO "Entered OS MCA handler. PSP=%lx cpu=%d monarch=%ld\n",
+               sos->proc_state_param, cpu, sos->monarch);
+
        previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA");
        monarch_cpu = cpu;
        if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, 0, 0, 0)
@@ -1444,11 +1471,13 @@ void __devinit
 ia64_mca_cpu_init(void *cpu_data)
 {
        void *pal_vaddr;
+       static int first_time = 1;
 
-       if (smp_processor_id() == 0) {
+       if (first_time) {
                void *mca_data;
                int cpu;
 
+               first_time = 0;
                mca_data = alloc_bootmem(sizeof(struct ia64_mca_cpu)
                                         * NR_CPUS + KERNEL_STACK_SIZE);
                mca_data = (void *)(((unsigned long)mca_data +
@@ -1704,6 +1733,7 @@ ia64_mca_late_init(void)
                                        desc = irq_descp(irq);
                                        desc->status |= IRQ_PER_CPU;
                                        setup_irq(irq, &mca_cpe_irqaction);
+                                       ia64_cpe_irq = irq;
                                }
                        ia64_mca_register_cpev(cpe_vector);
                        IA64_MCA_DEBUG("%s: CPEI/P setup and enabled.\n", __FUNCTION__);
index 9c5194b385dab33ce122152ee665306fe2cbf761..077f21216b654cc433cb58c2104b11c7954b8b19 100644 (file)
@@ -6722,6 +6722,7 @@ __initcall(pfm_init);
 void
 pfm_init_percpu (void)
 {
+       static int first_time=1;
        /*
         * make sure no measurement is active
         * (may inherit programmed PMCs from EFI).
@@ -6734,8 +6735,10 @@ pfm_init_percpu (void)
         */
        pfm_unfreeze_pmu();
 
-       if (smp_processor_id() == 0)
+       if (first_time) {
                register_percpu_irq(IA64_PERFMON_VECTOR, &perfmon_irqaction);
+               first_time=0;
+       }
 
        ia64_setreg(_IA64_REG_CR_PMV, IA64_PERFMON_VECTOR);
        ia64_srlz_d();
index 463f6bb44d07880993b0f13e282352100dd05cff..1d7903ee2126ec08183aa569bb4d8d8ef8f472dc 100644 (file)
@@ -588,104 +588,3 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
        }
        return 0;
 }
-
-/* Set a delayed signal that was detected in MCA/INIT/NMI/PMI context where it
- * could not be delivered.  It is important that the target process is not
- * allowed to do any more work in user space.  Possible cases for the target
- * process:
- *
- * - It is sleeping and will wake up soon.  Store the data in the current task,
- *   the signal will be sent when the current task returns from the next
- *   interrupt.
- *
- * - It is running in user context.  Store the data in the current task, the
- *   signal will be sent when the current task returns from the next interrupt.
- *
- * - It is running in kernel context on this or another cpu and will return to
- *   user context.  Store the data in the target task, the signal will be sent
- *   to itself when the target task returns to user space.
- *
- * - It is running in kernel context on this cpu and will sleep before
- *   returning to user context.  Because this is also the current task, the
- *   signal will not get delivered and the task could sleep indefinitely.
- *   Store the data in the idle task for this cpu, the signal will be sent
- *   after the idle task processes its next interrupt.
- *
- * To cover all cases, store the data in the target task, the current task and
- * the idle task on this cpu.  Whatever happens, the signal will be delivered
- * to the target task before it can do any useful user space work.  Multiple
- * deliveries have no unwanted side effects.
- *
- * Note: This code is executed in MCA/INIT/NMI/PMI context, with interrupts
- * disabled.  It must not take any locks nor use kernel structures or services
- * that require locks.
- */
-
-/* To ensure that we get the right pid, check its start time.  To avoid extra
- * include files in thread_info.h, convert the task start_time to unsigned long,
- * giving us a cycle time of > 580 years.
- */
-static inline unsigned long
-start_time_ul(const struct task_struct *t)
-{
-       return t->start_time.tv_sec * NSEC_PER_SEC + t->start_time.tv_nsec;
-}
-
-void
-set_sigdelayed(pid_t pid, int signo, int code, void __user *addr)
-{
-       struct task_struct *t;
-       unsigned long start_time =  0;
-       int i;
-
-       for (i = 1; i <= 3; ++i) {
-               switch (i) {
-               case 1:
-                       t = find_task_by_pid(pid);
-                       if (t)
-                               start_time = start_time_ul(t);
-                       break;
-               case 2:
-                       t = current;
-                       break;
-               default:
-                       t = idle_task(smp_processor_id());
-                       break;
-               }
-
-               if (!t)
-                       return;
-               task_thread_info(t)->sigdelayed.signo = signo;
-               task_thread_info(t)->sigdelayed.code = code;
-               task_thread_info(t)->sigdelayed.addr = addr;
-               task_thread_info(t)->sigdelayed.start_time = start_time;
-               task_thread_info(t)->sigdelayed.pid = pid;
-               wmb();
-               set_tsk_thread_flag(t, TIF_SIGDELAYED);
-       }
-}
-
-/* Called from entry.S when it detects TIF_SIGDELAYED, a delayed signal that
- * was detected in MCA/INIT/NMI/PMI context where it could not be delivered.
- */
-
-void
-do_sigdelayed(void)
-{
-       struct siginfo siginfo;
-       pid_t pid;
-       struct task_struct *t;
-
-       clear_thread_flag(TIF_SIGDELAYED);
-       memset(&siginfo, 0, sizeof(siginfo));
-       siginfo.si_signo = current_thread_info()->sigdelayed.signo;
-       siginfo.si_code = current_thread_info()->sigdelayed.code;
-       siginfo.si_addr = current_thread_info()->sigdelayed.addr;
-       pid = current_thread_info()->sigdelayed.pid;
-       t = find_task_by_pid(pid);
-       if (!t)
-               return;
-       if (current_thread_info()->sigdelayed.start_time != start_time_ul(t))
-               return;
-       force_sig_info(siginfo.si_signo, &siginfo, t);
-}
index b681ef34a86e13a5ecab3a7e1ec2eb6b7378e847..c4b633b36daba12b16b9ebe650b54f009c349fd9 100644 (file)
 #endif
 
 #ifdef CONFIG_HOTPLUG_CPU
+#ifdef CONFIG_PERMIT_BSP_REMOVE
+#define bsp_remove_ok  1
+#else
+#define bsp_remove_ok  0
+#endif
+
 /*
  * Store all idle threads, this can be reused instead of creating
  * a new thread. Also avoids complicated thread destroy functionality
@@ -104,7 +110,7 @@ struct sal_to_os_boot *sal_state_for_booting_cpu = &sal_boot_rendez_state[0];
 /*
  * ITC synchronization related stuff:
  */
-#define MASTER 0
+#define MASTER (0)
 #define SLAVE  (SMP_CACHE_BYTES/8)
 
 #define NUM_ROUNDS     64      /* magic value */
@@ -151,6 +157,27 @@ char __initdata no_int_routing;
 
 unsigned char smp_int_redirect; /* are INT and IPI redirectable by the chipset? */
 
+#ifdef CONFIG_FORCE_CPEI_RETARGET
+#define CPEI_OVERRIDE_DEFAULT  (1)
+#else
+#define CPEI_OVERRIDE_DEFAULT  (0)
+#endif
+
+unsigned int force_cpei_retarget = CPEI_OVERRIDE_DEFAULT;
+
+static int __init
+cmdl_force_cpei(char *str)
+{
+       int value=0;
+
+       get_option (&str, &value);
+       force_cpei_retarget = value;
+
+       return 1;
+}
+
+__setup("force_cpei=", cmdl_force_cpei);
+
 static int __init
 nointroute (char *str)
 {
@@ -161,6 +188,27 @@ nointroute (char *str)
 
 __setup("nointroute", nointroute);
 
+static void fix_b0_for_bsp(void)
+{
+#ifdef CONFIG_HOTPLUG_CPU
+       int cpuid;
+       static int fix_bsp_b0 = 1;
+
+       cpuid = smp_processor_id();
+
+       /*
+        * Cache the b0 value on the first AP that comes up
+        */
+       if (!(fix_bsp_b0 && cpuid))
+               return;
+
+       sal_boot_rendez_state[0].br[0] = sal_boot_rendez_state[cpuid].br[0];
+       printk ("Fixed BSP b0 value from CPU %d\n", cpuid);
+
+       fix_bsp_b0 = 0;
+#endif
+}
+
 void
 sync_master (void *arg)
 {
@@ -327,8 +375,9 @@ smp_setup_percpu_timer (void)
 static void __devinit
 smp_callin (void)
 {
-       int cpuid, phys_id;
+       int cpuid, phys_id, itc_master;
        extern void ia64_init_itm(void);
+       extern volatile int time_keeper_id;
 
 #ifdef CONFIG_PERFMON
        extern void pfm_init_percpu(void);
@@ -336,6 +385,7 @@ smp_callin (void)
 
        cpuid = smp_processor_id();
        phys_id = hard_smp_processor_id();
+       itc_master = time_keeper_id;
 
        if (cpu_online(cpuid)) {
                printk(KERN_ERR "huh, phys CPU#0x%x, CPU#0x%x already present??\n",
@@ -343,6 +393,8 @@ smp_callin (void)
                BUG();
        }
 
+       fix_b0_for_bsp();
+
        lock_ipi_calllock();
        cpu_set(cpuid, cpu_online_map);
        unlock_ipi_calllock();
@@ -365,8 +417,8 @@ smp_callin (void)
                 * calls spin_unlock_bh(), which calls spin_unlock_bh(), which calls
                 * local_bh_enable(), which bugs out if irqs are not enabled...
                 */
-               Dprintk("Going to syncup ITC with BP.\n");
-               ia64_sync_itc(0);
+               Dprintk("Going to syncup ITC with ITC Master.\n");
+               ia64_sync_itc(itc_master);
        }
 
        /*
@@ -635,6 +687,47 @@ remove_siblinginfo(int cpu)
 }
 
 extern void fixup_irqs(void);
+
+int migrate_platform_irqs(unsigned int cpu)
+{
+       int new_cpei_cpu;
+       irq_desc_t *desc = NULL;
+       cpumask_t       mask;
+       int             retval = 0;
+
+       /*
+        * dont permit CPEI target to removed.
+        */
+       if (cpe_vector > 0 && is_cpu_cpei_target(cpu)) {
+               printk ("CPU (%d) is CPEI Target\n", cpu);
+               if (can_cpei_retarget()) {
+                       /*
+                        * Now re-target the CPEI to a different processor
+                        */
+                       new_cpei_cpu = any_online_cpu(cpu_online_map);
+                       mask = cpumask_of_cpu(new_cpei_cpu);
+                       set_cpei_target_cpu(new_cpei_cpu);
+                       desc = irq_descp(ia64_cpe_irq);
+                       /*
+                        * Switch for now, immediatly, we need to do fake intr
+                        * as other interrupts, but need to study CPEI behaviour with
+                        * polling before making changes.
+                        */
+                       if (desc) {
+                               desc->handler->disable(ia64_cpe_irq);
+                               desc->handler->set_affinity(ia64_cpe_irq, mask);
+                               desc->handler->enable(ia64_cpe_irq);
+                               printk ("Re-targetting CPEI to cpu %d\n", new_cpei_cpu);
+                       }
+               }
+               if (!desc) {
+                       printk ("Unable to retarget CPEI, offline cpu [%d] failed\n", cpu);
+                       retval = -EBUSY;
+               }
+       }
+       return retval;
+}
+
 /* must be called with cpucontrol mutex held */
 int __cpu_disable(void)
 {
@@ -643,8 +736,17 @@ int __cpu_disable(void)
        /*
         * dont permit boot processor for now
         */
-       if (cpu == 0)
-               return -EBUSY;
+       if (cpu == 0 && !bsp_remove_ok) {
+               printk ("Your platform does not support removal of BSP\n");
+               return (-EBUSY);
+       }
+
+       cpu_clear(cpu, cpu_online_map);
+
+       if (migrate_platform_irqs(cpu)) {
+               cpu_set(cpu, cpu_online_map);
+               return (-EBUSY);
+       }
 
        remove_siblinginfo(cpu);
        cpu_clear(cpu, cpu_online_map);
index 307d01e15b2ea359c043d11c5e19a0bc57bd1002..ac167436e9364ffc23fe3bde276019e5fae93d7e 100644 (file)
@@ -32,7 +32,7 @@
 
 extern unsigned long wall_jiffies;
 
-#define TIME_KEEPER_ID 0       /* smp_processor_id() of time-keeper */
+volatile int time_keeper_id = 0; /* smp_processor_id() of time-keeper */
 
 #ifdef CONFIG_IA64_DEBUG_IRQ
 
@@ -71,7 +71,7 @@ timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
 
                new_itm += local_cpu_data->itm_delta;
 
-               if (smp_processor_id() == TIME_KEEPER_ID) {
+               if (smp_processor_id() == time_keeper_id) {
                        /*
                         * Here we are in the timer irq handler. We have irqs locally
                         * disabled, but we don't know if the timer_bh is running on
@@ -236,6 +236,11 @@ static struct irqaction timer_irqaction = {
        .name =         "timer"
 };
 
+void __devinit ia64_disable_timer(void)
+{
+       ia64_set_itv(1 << 16);
+}
+
 void __init
 time_init (void)
 {
index 6e5eea19fa672bb0199f997e0888fc91d98ad77c..3b6fd798c4d68c2a1cbbed752e875286b1d3ff85 100644 (file)
@@ -36,7 +36,7 @@ int arch_register_cpu(int num)
        parent = &sysfs_nodes[cpu_to_node(num)];
 #endif /* CONFIG_NUMA */
 
-#ifdef CONFIG_ACPI
+#if defined (CONFIG_ACPI) && defined (CONFIG_HOTPLUG_CPU)
        /*
         * If CPEI cannot be re-targetted, and this is
         * CPEI target, then dont create the control file
index acaaec4e46811bdf697fdd96bbd37ac9a41dd6b5..9855ba3180944b2d13569dba7e6f7139dcb0e621 100644 (file)
@@ -181,13 +181,15 @@ per_cpu_init (void)
 {
        void *cpu_data;
        int cpu;
+       static int first_time=1;
 
        /*
         * get_free_pages() cannot be used before cpu_init() done.  BSP
         * allocates "NR_CPUS" pages for all CPUs to avoid that AP calls
         * get_zeroed_page().
         */
-       if (smp_processor_id() == 0) {
+       if (first_time) {
+               first_time=0;
                cpu_data = __alloc_bootmem(PERCPU_PAGE_SIZE * NR_CPUS,
                                           PERCPU_PAGE_SIZE, __pa(MAX_DMA_ADDRESS));
                for (cpu = 0; cpu < NR_CPUS; cpu++) {
index c87d6d1d58130411828e2daef886398ced41d93d..573d5cc63e2b927eaf0791833018b8643172d64d 100644 (file)
@@ -528,12 +528,17 @@ void __init find_memory(void)
 void *per_cpu_init(void)
 {
        int cpu;
+       static int first_time = 1;
+
 
        if (smp_processor_id() != 0)
                return __per_cpu_start + __per_cpu_offset[smp_processor_id()];
 
-       for (cpu = 0; cpu < NR_CPUS; cpu++)
-               per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu];
+       if (first_time) {
+               first_time = 0;
+               for (cpu = 0; cpu < NR_CPUS; cpu++)
+                       per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu];
+       }
 
        return __per_cpu_start + __per_cpu_offset[smp_processor_id()];
 }
index 3e9b4eea74185a32d3ea235d040213936996848f..ab9c48c88012916a28deb08d1bcf7749b1ec02af 100644 (file)
@@ -10,7 +10,8 @@
 CPPFLAGS += -I$(srctree)/arch/ia64/sn/include
 
 obj-y                          += setup.o bte.o bte_error.o irq.o mca.o idle.o \
-                                  huberror.o io_init.o iomv.o klconflib.o sn2/
+                                  huberror.o io_init.o iomv.o klconflib.o pio_phys.o \
+                                  sn2/
 obj-$(CONFIG_IA64_GENERIC)      += machvec.o
 obj-$(CONFIG_SGI_TIOCX)                += tiocx.o
 obj-$(CONFIG_IA64_SGI_SN_XP)   += xp.o
diff --git a/arch/ia64/sn/kernel/pio_phys.S b/arch/ia64/sn/kernel/pio_phys.S
new file mode 100644 (file)
index 0000000..3c7d48d
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved.
+ *
+ * This file contains macros used to access MMR registers via
+ * uncached physical addresses.
+ *      pio_phys_read_mmr  - read an MMR
+ *      pio_phys_write_mmr - write an MMR
+ *      pio_atomic_phys_write_mmrs - atomically write 1 or 2 MMRs with psr.ic=0
+ *              Second MMR will be skipped if address is NULL
+ *
+ * Addresses passed to these routines should be uncached physical addresses
+ *     ie., 0x80000....
+ */
+
+
+
+#include <asm/asmmacro.h>
+#include <asm/page.h>
+
+GLOBAL_ENTRY(pio_phys_read_mmr)
+       .prologue
+       .regstk 1,0,0,0
+       .body
+       mov r2=psr
+       rsm psr.i | psr.dt
+       ;;
+       srlz.d
+       ld8.acq r8=[r32]
+       ;;
+       mov psr.l=r2;;
+       srlz.d
+       br.ret.sptk.many rp
+END(pio_phys_read_mmr)
+
+GLOBAL_ENTRY(pio_phys_write_mmr)
+       .prologue
+       .regstk 2,0,0,0
+       .body
+       mov r2=psr
+       rsm psr.i | psr.dt
+       ;;
+       srlz.d
+       st8.rel [r32]=r33
+       ;;
+       mov psr.l=r2;;
+       srlz.d
+       br.ret.sptk.many rp
+END(pio_phys_write_mmr)
+
+GLOBAL_ENTRY(pio_atomic_phys_write_mmrs)
+       .prologue
+       .regstk 4,0,0,0
+       .body
+       mov r2=psr
+       cmp.ne p9,p0=r34,r0;
+       rsm psr.i | psr.dt | psr.ic
+       ;;
+       srlz.d
+       st8.rel [r32]=r33
+(p9)   st8.rel [r34]=r35
+       ;;
+       mov psr.l=r2;;
+       srlz.d
+       br.ret.sptk.many rp
+END(pio_atomic_phys_write_mmrs)
+
+
index 5b84836c2171b1a53c3dddc0cc060055c1433a15..8b6d5c8447089d8523ed807583c9c317cc9caf0b 100644 (file)
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1999,2001-2005 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 1999,2001-2006 Silicon Graphics, Inc. All rights reserved.
  */
 
 #include <linux/config.h>
@@ -498,6 +498,7 @@ void __init sn_setup(char **cmdline_p)
         * for sn.
         */
        pm_power_off = ia64_sn_power_down;
+       current->thread.flags |= IA64_THREAD_MIGRATION;
 }
 
 /**
@@ -660,7 +661,8 @@ void __init sn_cpu_init(void)
                        SH2_PIO_WRITE_STATUS_1, SH2_PIO_WRITE_STATUS_3};
                u64 *pio;
                pio = is_shub1() ? pio1 : pio2;
-               pda->pio_write_status_addr = (volatile unsigned long *) LOCAL_MMR_ADDR(pio[slice]);
+               pda->pio_write_status_addr =
+                  (volatile unsigned long *)GLOBAL_MMR_ADDR(nasid, pio[slice]);
                pda->pio_write_status_val = is_shub1() ? SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK : 0;
        }
 
index b2e1e746b47fca6ebbda649e50077ce56127c2f2..d9d306c79f2d7a1743369380e637c4118d012c22 100644 (file)
@@ -93,6 +93,27 @@ static inline unsigned long wait_piowc(void)
        return (ws & SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK) != 0;
 }
 
+/**
+ * sn_migrate - SN-specific task migration actions
+ * @task: Task being migrated to new CPU
+ *
+ * SN2 PIO writes from separate CPUs are not guaranteed to arrive in order.
+ * Context switching user threads which have memory-mapped MMIO may cause
+ * PIOs to issue from seperate CPUs, thus the PIO writes must be drained
+ * from the previous CPU's Shub before execution resumes on the new CPU.
+ */
+void sn_migrate(struct task_struct *task)
+{
+       pda_t *last_pda = pdacpu(task_thread_info(task)->last_cpu);
+       volatile unsigned long *adr = last_pda->pio_write_status_addr;
+       unsigned long val = last_pda->pio_write_status_val;
+
+       /* Drain PIO writes from old CPU's Shub */
+       while (unlikely((*adr & SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK)
+                       != val))
+               cpu_relax();
+}
+
 void sn_tlb_migrate_finish(struct mm_struct *mm)
 {
        /* flush_tlb_mm is inefficient if more than 1 users of mm */
index cdf6856ce089c07c4344f6150439e1bd4ef29523..d0abddd9ffe682c8dc4d566c6619a33b180567a7 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/sched.h>
 #include <linux/cache.h>
 #include <linux/interrupt.h>
-#include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/completion.h>
 #include <asm/sn/bte.h>
 #include <asm/sn/xpc.h>
 
 
+/*
+ * Guarantee that the kzalloc'd memory is cacheline aligned.
+ */
+static void *
+xpc_kzalloc_cacheline_aligned(size_t size, gfp_t flags, void **base)
+{
+       /* see if kzalloc will give us cachline aligned memory by default */
+       *base = kzalloc(size, flags);
+       if (*base == NULL) {
+               return NULL;
+       }
+       if ((u64) *base == L1_CACHE_ALIGN((u64) *base)) {
+               return *base;
+       }
+       kfree(*base);
+
+       /* nope, we'll have to do it ourselves */
+       *base = kzalloc(size + L1_CACHE_BYTES, flags);
+       if (*base == NULL) {
+               return NULL;
+       }
+       return (void *) L1_CACHE_ALIGN((u64) *base);
+}
+
+
 /*
  * Set up the initial values for the XPartition Communication channels.
  */
@@ -93,20 +117,19 @@ xpc_setup_infrastructure(struct xpc_partition *part)
         * Allocate all of the channel structures as a contiguous chunk of
         * memory.
         */
-       part->channels = kmalloc(sizeof(struct xpc_channel) * XPC_NCHANNELS,
+       part->channels = kzalloc(sizeof(struct xpc_channel) * XPC_NCHANNELS,
                                                                GFP_KERNEL);
        if (part->channels == NULL) {
                dev_err(xpc_chan, "can't get memory for channels\n");
                return xpcNoMemory;
        }
-       memset(part->channels, 0, sizeof(struct xpc_channel) * XPC_NCHANNELS);
 
        part->nchannels = XPC_NCHANNELS;
 
 
        /* allocate all the required GET/PUT values */
 
-       part->local_GPs = xpc_kmalloc_cacheline_aligned(XPC_GP_SIZE,
+       part->local_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE,
                                        GFP_KERNEL, &part->local_GPs_base);
        if (part->local_GPs == NULL) {
                kfree(part->channels);
@@ -115,55 +138,51 @@ xpc_setup_infrastructure(struct xpc_partition *part)
                        "values\n");
                return xpcNoMemory;
        }
-       memset(part->local_GPs, 0, XPC_GP_SIZE);
 
-       part->remote_GPs = xpc_kmalloc_cacheline_aligned(XPC_GP_SIZE,
+       part->remote_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE,
                                        GFP_KERNEL, &part->remote_GPs_base);
        if (part->remote_GPs == NULL) {
-               kfree(part->channels);
-               part->channels = NULL;
-               kfree(part->local_GPs_base);
-               part->local_GPs = NULL;
                dev_err(xpc_chan, "can't get memory for remote get/put "
                        "values\n");
+               kfree(part->local_GPs_base);
+               part->local_GPs = NULL;
+               kfree(part->channels);
+               part->channels = NULL;
                return xpcNoMemory;
        }
-       memset(part->remote_GPs, 0, XPC_GP_SIZE);
 
 
        /* allocate all the required open and close args */
 
-       part->local_openclose_args = xpc_kmalloc_cacheline_aligned(
+       part->local_openclose_args = xpc_kzalloc_cacheline_aligned(
                                        XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL,
                                        &part->local_openclose_args_base);
        if (part->local_openclose_args == NULL) {
-               kfree(part->channels);
-               part->channels = NULL;
-               kfree(part->local_GPs_base);
-               part->local_GPs = NULL;
+               dev_err(xpc_chan, "can't get memory for local connect args\n");
                kfree(part->remote_GPs_base);
                part->remote_GPs = NULL;
-               dev_err(xpc_chan, "can't get memory for local connect args\n");
+               kfree(part->local_GPs_base);
+               part->local_GPs = NULL;
+               kfree(part->channels);
+               part->channels = NULL;
                return xpcNoMemory;
        }
-       memset(part->local_openclose_args, 0, XPC_OPENCLOSE_ARGS_SIZE);
 
-       part->remote_openclose_args = xpc_kmalloc_cacheline_aligned(
+       part->remote_openclose_args = xpc_kzalloc_cacheline_aligned(
                                        XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL,
                                        &part->remote_openclose_args_base);
        if (part->remote_openclose_args == NULL) {
-               kfree(part->channels);
-               part->channels = NULL;
-               kfree(part->local_GPs_base);
-               part->local_GPs = NULL;
-               kfree(part->remote_GPs_base);
-               part->remote_GPs = NULL;
+               dev_err(xpc_chan, "can't get memory for remote connect args\n");
                kfree(part->local_openclose_args_base);
                part->local_openclose_args = NULL;
-               dev_err(xpc_chan, "can't get memory for remote connect args\n");
+               kfree(part->remote_GPs_base);
+               part->remote_GPs = NULL;
+               kfree(part->local_GPs_base);
+               part->local_GPs = NULL;
+               kfree(part->channels);
+               part->channels = NULL;
                return xpcNoMemory;
        }
-       memset(part->remote_openclose_args, 0, XPC_OPENCLOSE_ARGS_SIZE);
 
 
        xpc_initialize_channels(part, partid);
@@ -186,18 +205,18 @@ xpc_setup_infrastructure(struct xpc_partition *part)
        ret = request_irq(SGI_XPC_NOTIFY, xpc_notify_IRQ_handler, SA_SHIRQ,
                                part->IPI_owner, (void *) (u64) partid);
        if (ret != 0) {
-               kfree(part->channels);
-               part->channels = NULL;
-               kfree(part->local_GPs_base);
-               part->local_GPs = NULL;
-               kfree(part->remote_GPs_base);
-               part->remote_GPs = NULL;
-               kfree(part->local_openclose_args_base);
-               part->local_openclose_args = NULL;
-               kfree(part->remote_openclose_args_base);
-               part->remote_openclose_args = NULL;
                dev_err(xpc_chan, "can't register NOTIFY IRQ handler, "
                        "errno=%d\n", -ret);
+               kfree(part->remote_openclose_args_base);
+               part->remote_openclose_args = NULL;
+               kfree(part->local_openclose_args_base);
+               part->local_openclose_args = NULL;
+               kfree(part->remote_GPs_base);
+               part->remote_GPs = NULL;
+               kfree(part->local_GPs_base);
+               part->local_GPs = NULL;
+               kfree(part->channels);
+               part->channels = NULL;
                return xpcLackOfResources;
        }
 
@@ -446,22 +465,20 @@ xpc_allocate_local_msgqueue(struct xpc_channel *ch)
        for (nentries = ch->local_nentries; nentries > 0; nentries--) {
 
                nbytes = nentries * ch->msg_size;
-               ch->local_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes,
+               ch->local_msgqueue = xpc_kzalloc_cacheline_aligned(nbytes,
                                                GFP_KERNEL,
                                                &ch->local_msgqueue_base);
                if (ch->local_msgqueue == NULL) {
                        continue;
                }
-               memset(ch->local_msgqueue, 0, nbytes);
 
                nbytes = nentries * sizeof(struct xpc_notify);
-               ch->notify_queue = kmalloc(nbytes, GFP_KERNEL);
+               ch->notify_queue = kzalloc(nbytes, GFP_KERNEL);
                if (ch->notify_queue == NULL) {
                        kfree(ch->local_msgqueue_base);
                        ch->local_msgqueue = NULL;
                        continue;
                }
-               memset(ch->notify_queue, 0, nbytes);
 
                spin_lock_irqsave(&ch->lock, irq_flags);
                if (nentries < ch->local_nentries) {
@@ -501,13 +518,12 @@ xpc_allocate_remote_msgqueue(struct xpc_channel *ch)
        for (nentries = ch->remote_nentries; nentries > 0; nentries--) {
 
                nbytes = nentries * ch->msg_size;
-               ch->remote_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes,
+               ch->remote_msgqueue = xpc_kzalloc_cacheline_aligned(nbytes,
                                                GFP_KERNEL,
                                                &ch->remote_msgqueue_base);
                if (ch->remote_msgqueue == NULL) {
                        continue;
                }
-               memset(ch->remote_msgqueue, 0, nbytes);
 
                spin_lock_irqsave(&ch->lock, irq_flags);
                if (nentries < ch->remote_nentries) {
index 8cbf164325703048ecd277ebf141efb432e8b075..99b123a6421ad9541288b81f2148dfd9403161a4 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/syscalls.h>
 #include <linux/cache.h>
 #include <linux/interrupt.h>
-#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/reboot.h>
 #include <linux/completion.h>
index 88a730e6cfdbc524e9a867f58c6cddb52e57b086..94211429fd0c0c821b445873c2b51c5edbc0f317 100644 (file)
@@ -80,6 +80,31 @@ char ____cacheline_aligned xpc_remote_copy_buffer[XPC_RP_HEADER_SIZE +
                                                        XP_NASID_MASK_BYTES];
 
 
+/*
+ * Guarantee that the kmalloc'd memory is cacheline aligned.
+ */
+static void *
+xpc_kmalloc_cacheline_aligned(size_t size, gfp_t flags, void **base)
+{
+       /* see if kmalloc will give us cachline aligned memory by default */
+       *base = kmalloc(size, flags);
+       if (*base == NULL) {
+               return NULL;
+       }
+       if ((u64) *base == L1_CACHE_ALIGN((u64) *base)) {
+               return *base;
+       }
+       kfree(*base);
+
+       /* nope, we'll have to do it ourselves */
+       *base = kmalloc(size + L1_CACHE_BYTES, flags);
+       if (*base == NULL) {
+               return NULL;
+       }
+       return (void *) L1_CACHE_ALIGN((u64) *base);
+}
+
+
 /*
  * Given a nasid, get the physical address of the  partition's reserved page
  * for that nasid. This function returns 0 on any error.
@@ -1038,13 +1063,12 @@ xpc_discovery(void)
        remote_vars = (struct xpc_vars *) remote_rp;
 
 
-       discovered_nasids = kmalloc(sizeof(u64) * xp_nasid_mask_words,
+       discovered_nasids = kzalloc(sizeof(u64) * xp_nasid_mask_words,
                                                        GFP_KERNEL);
        if (discovered_nasids == NULL) {
                kfree(remote_rp_base);
                return;
        }
-       memset(discovered_nasids, 0, sizeof(u64) * xp_nasid_mask_words);
 
        rp = (struct xpc_rsvd_page *) xpc_rsvd_page;
 
index e52831ed93ebc646ab599c89f15ffb210cc2461e..fa073cc4b565fc6dbf535cfdbe32fec1e7aa8b28 100644 (file)
 #include <asm/sn/pcidev.h>
 #include <asm/sn/pcibus_provider_defs.h>
 #include <asm/sn/tioce_provider.h>
+#include <asm/sn/sn2/sn_hwperf.h>
+
+/*
+ * 1/26/2006
+ *
+ * WAR for SGI PV 944642.  For revA TIOCE, need to use the following recipe
+ * (taken from the above PV) before and after accessing tioce internal MMR's
+ * to avoid tioce lockups.
+ *
+ * The recipe as taken from the PV:
+ *
+ *     if(mmr address < 0x45000) {
+ *             if(mmr address == 0 or 0x80)
+ *                     mmr wrt or read address 0xc0
+ *             else if(mmr address == 0x148 or 0x200)
+ *                     mmr wrt or read address 0x28
+ *             else
+ *                     mmr wrt or read address 0x158
+ *
+ *             do desired mmr access (rd or wrt)
+ *
+ *             if(mmr address == 0x100)
+ *                     mmr wrt or read address 0x38
+ *             mmr wrt or read address 0xb050
+ *     } else
+ *             do desired mmr access
+ *
+ * According to hw, we can use reads instead of writes to the above addres
+ *
+ * Note this WAR can only to be used for accessing internal MMR's in the
+ * TIOCE Coretalk Address Range 0x0 - 0x07ff_ffff.  This includes the
+ * "Local CE Registers and Memories" and "PCI Compatible Config Space" address
+ * spaces from table 2-1 of the "CE Programmer's Reference Overview" document.
+ *
+ * All registers defined in struct tioce will meet that criteria.
+ */
+
+static void inline
+tioce_mmr_war_pre(struct tioce_kernel *kern, void *mmr_addr)
+{
+       u64 mmr_base;
+       u64 mmr_offset;
+
+       if (kern->ce_common->ce_rev != TIOCE_REV_A)
+               return;
+
+       mmr_base = kern->ce_common->ce_pcibus.bs_base;
+       mmr_offset = (u64)mmr_addr - mmr_base;
+
+       if (mmr_offset < 0x45000) {
+               u64 mmr_war_offset;
+
+               if (mmr_offset == 0 || mmr_offset == 0x80)
+                       mmr_war_offset = 0xc0;
+               else if (mmr_offset == 0x148 || mmr_offset == 0x200)
+                       mmr_war_offset = 0x28;
+               else
+                       mmr_war_offset = 0x158;
+
+               readq_relaxed((void *)(mmr_base + mmr_war_offset));
+       }
+}
+
+static void inline
+tioce_mmr_war_post(struct tioce_kernel *kern, void *mmr_addr)
+{
+       u64 mmr_base;
+       u64 mmr_offset;
+
+       if (kern->ce_common->ce_rev != TIOCE_REV_A)
+               return;
+
+       mmr_base = kern->ce_common->ce_pcibus.bs_base;
+       mmr_offset = (u64)mmr_addr - mmr_base;
+
+       if (mmr_offset < 0x45000) {
+               if (mmr_offset == 0x100)
+                       readq_relaxed((void *)(mmr_base + 0x38));
+               readq_relaxed((void *)(mmr_base + 0xb050));
+       }
+}
+
+/* load mmr contents into a variable */
+#define tioce_mmr_load(kern, mmrp, varp) do {\
+       tioce_mmr_war_pre(kern, mmrp); \
+       *(varp) = readq_relaxed(mmrp); \
+       tioce_mmr_war_post(kern, mmrp); \
+} while (0)
+
+/* store variable contents into mmr */
+#define tioce_mmr_store(kern, mmrp, varp) do {\
+       tioce_mmr_war_pre(kern, mmrp); \
+       writeq(*varp, mmrp); \
+       tioce_mmr_war_post(kern, mmrp); \
+} while (0)
+
+/* store immediate value into mmr */
+#define tioce_mmr_storei(kern, mmrp, val) do {\
+       tioce_mmr_war_pre(kern, mmrp); \
+       writeq(val, mmrp); \
+       tioce_mmr_war_post(kern, mmrp); \
+} while (0)
+
+/* set bits (immediate value) into mmr */
+#define tioce_mmr_seti(kern, mmrp, bits) do {\
+       u64 tmp; \
+       tioce_mmr_load(kern, mmrp, &tmp); \
+       tmp |= (bits); \
+       tioce_mmr_store(kern, mmrp, &tmp); \
+} while (0)
+
+/* clear bits (immediate value) into mmr */
+#define tioce_mmr_clri(kern, mmrp, bits) do { \
+       u64 tmp; \
+       tioce_mmr_load(kern, mmrp, &tmp); \
+       tmp &= ~(bits); \
+       tioce_mmr_store(kern, mmrp, &tmp); \
+} while (0)
 
 /**
  * Bus address ranges for the 5 flavors of TIOCE DMA
 #define TIOCE_ATE_M40  2
 #define TIOCE_ATE_M40S 3
 
-#define KB(x)  ((x) << 10)
-#define MB(x)  ((x) << 20)
-#define GB(x)  ((x) << 30)
+#define KB(x)  ((u64)(x) << 10)
+#define MB(x)  ((u64)(x) << 20)
+#define GB(x)  ((u64)(x) << 30)
 
 /**
  * tioce_dma_d64 - create a DMA mapping using 64-bit direct mode
@@ -151,7 +269,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
        int last;
        int entries;
        int nates;
-       int pagesize;
+       u64 pagesize;
        u64 *ate_shadow;
        u64 *ate_reg;
        u64 addr;
@@ -228,7 +346,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
 
                ate = ATE_MAKE(addr, pagesize);
                ate_shadow[i + j] = ate;
-               writeq(ate, &ate_reg[i + j]);
+               tioce_mmr_storei(ce_kern, &ate_reg[i + j], ate);
                addr += pagesize;
        }
 
@@ -272,7 +390,8 @@ tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr)
                u64 tmp;
 
                ce_kern->ce_port[port].dirmap_shadow = ct_upper;
-               writeq(ct_upper, &ce_mmr->ce_ure_dir_map[port]);
+               tioce_mmr_storei(ce_kern, &ce_mmr->ce_ure_dir_map[port],
+                                ct_upper);
                tmp = ce_mmr->ce_ure_dir_map[port];
                dma_ok = 1;
        } else
@@ -344,7 +463,8 @@ tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir)
        if (TIOCE_D32_ADDR(bus_addr)) {
                if (--ce_kern->ce_port[port].dirmap_refcnt == 0) {
                        ce_kern->ce_port[port].dirmap_shadow = 0;
-                       writeq(0, &ce_mmr->ce_ure_dir_map[port]);
+                       tioce_mmr_storei(ce_kern, &ce_mmr->ce_ure_dir_map[port],
+                                        0);
                }
        } else {
                struct tioce_dmamap *map;
@@ -365,7 +485,7 @@ tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir)
                } else if (--map->refcnt == 0) {
                        for (i = 0; i < map->ate_count; i++) {
                                map->ate_shadow[i] = 0;
-                               map->ate_hw[i] = 0;
+                               tioce_mmr_storei(ce_kern, &map->ate_hw[i], 0);
                        }
 
                        list_del(&map->ce_dmamap_list);
@@ -486,7 +606,7 @@ tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count,
        spin_unlock_irqrestore(&ce_kern->ce_lock, flags);
 
 dma_map_done:
-       if (mapaddr & barrier)
+       if (mapaddr && barrier)
                mapaddr = tioce_dma_barrier(mapaddr, 1);
 
        return mapaddr;
@@ -541,17 +661,61 @@ tioce_error_intr_handler(int irq, void *arg, struct pt_regs *pt)
                        soft->ce_pcibus.bs_persist_segment,
                        soft->ce_pcibus.bs_persist_busnum, 0, 0, 0, 0, 0);
 
+       if (ret_stuff.v0)
+               panic("tioce_error_intr_handler:  Fatal TIOCE error");
+
        return IRQ_HANDLED;
 }
 
+/**
+ * tioce_reserve_m32 - reserve M32 ate's for the indicated address range
+ * @tioce_kernel: TIOCE context to reserve ate's for
+ * @base: starting bus address to reserve
+ * @limit: last bus address to reserve
+ *
+ * If base/limit falls within the range of bus space mapped through the
+ * M32 space, reserve the resources corresponding to the range.
+ */
+static void
+tioce_reserve_m32(struct tioce_kernel *ce_kern, u64 base, u64 limit)
+{
+       int ate_index, last_ate, ps;
+       struct tioce *ce_mmr;
+
+       if (!TIOCE_M32_ADDR(base))
+               return;
+
+       ce_mmr = (struct tioce *)ce_kern->ce_common->ce_pcibus.bs_base;
+       ps = ce_kern->ce_ate3240_pagesize;
+       ate_index = ATE_PAGE(base, ps);
+       last_ate = ate_index + ATE_NPAGES(base, limit-base+1, ps) - 1;
+
+       if (ate_index < 64)
+               ate_index = 64;
+
+       while (ate_index <= last_ate) {
+               u64 ate;
+
+               ate = ATE_MAKE(0xdeadbeef, ps);
+               ce_kern->ce_ate3240_shadow[ate_index] = ate;
+               tioce_mmr_storei(ce_kern, &ce_mmr->ce_ure_ate3240[ate_index],
+                                ate);
+               ate_index++;
+       }
+}
+
 /**
  * tioce_kern_init - init kernel structures related to a given TIOCE
  * @tioce_common: ptr to a cached tioce_common struct that originated in prom
- */ static struct tioce_kernel *
+ */
+static struct tioce_kernel *
 tioce_kern_init(struct tioce_common *tioce_common)
 {
        int i;
+       int ps;
+       int dev;
        u32 tmp;
+       unsigned int seg, bus;
        struct tioce *tioce_mmr;
        struct tioce_kernel *tioce_kern;
 
@@ -572,9 +736,10 @@ tioce_kern_init(struct tioce_common *tioce_common)
         * here to use pci_read_config_xxx() so use the raw_pci_ops vector.
         */
 
-       raw_pci_ops->read(tioce_common->ce_pcibus.bs_persist_segment,
-                         tioce_common->ce_pcibus.bs_persist_busnum,
-                         PCI_DEVFN(2, 0), PCI_SECONDARY_BUS, 1, &tmp);
+       seg = tioce_common->ce_pcibus.bs_persist_segment;
+       bus = tioce_common->ce_pcibus.bs_persist_busnum;
+
+       raw_pci_ops->read(seg, bus, PCI_DEVFN(2, 0), PCI_SECONDARY_BUS, 1,&tmp);
        tioce_kern->ce_port1_secondary = (u8) tmp;
 
        /*
@@ -583,18 +748,76 @@ tioce_kern_init(struct tioce_common *tioce_common)
         */
 
        tioce_mmr = (struct tioce *)tioce_common->ce_pcibus.bs_base;
-       __sn_clrq_relaxed(&tioce_mmr->ce_ure_page_map, CE_URE_PAGESIZE_MASK);
-       __sn_setq_relaxed(&tioce_mmr->ce_ure_page_map, CE_URE_256K_PAGESIZE);
-       tioce_kern->ce_ate3240_pagesize = KB(256);
+       tioce_mmr_clri(tioce_kern, &tioce_mmr->ce_ure_page_map,
+                      CE_URE_PAGESIZE_MASK);
+       tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_ure_page_map,
+                      CE_URE_256K_PAGESIZE);
+       ps = tioce_kern->ce_ate3240_pagesize = KB(256);
 
        for (i = 0; i < TIOCE_NUM_M40_ATES; i++) {
                tioce_kern->ce_ate40_shadow[i] = 0;
-               writeq(0, &tioce_mmr->ce_ure_ate40[i]);
+               tioce_mmr_storei(tioce_kern, &tioce_mmr->ce_ure_ate40[i], 0);
        }
 
        for (i = 0; i < TIOCE_NUM_M3240_ATES; i++) {
                tioce_kern->ce_ate3240_shadow[i] = 0;
-               writeq(0, &tioce_mmr->ce_ure_ate3240[i]);
+               tioce_mmr_storei(tioce_kern, &tioce_mmr->ce_ure_ate3240[i], 0);
+       }
+
+       /*
+        * Reserve ATE's corresponding to reserved address ranges.  These
+        * include:
+        *
+        *      Memory space covered by each PPB mem base/limit register
+        *      Memory space covered by each PPB prefetch base/limit register
+        *
+        * These bus ranges are for pio (downstream) traffic only, and so
+        * cannot be used for DMA.
+        */
+
+       for (dev = 1; dev <= 2; dev++) {
+               u64 base, limit;
+
+               /* mem base/limit */
+
+               raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0),
+                                 PCI_MEMORY_BASE, 2, &tmp);
+               base = (u64)tmp << 16;
+
+               raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0),
+                                 PCI_MEMORY_LIMIT, 2, &tmp);
+               limit = (u64)tmp << 16;
+               limit |= 0xfffffUL;
+
+               if (base < limit)
+                       tioce_reserve_m32(tioce_kern, base, limit);
+
+               /*
+                * prefetch mem base/limit.  The tioce ppb's have 64-bit
+                * decoders, so read the upper portions w/o checking the
+                * attributes.
+                */
+
+               raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0),
+                                 PCI_PREF_MEMORY_BASE, 2, &tmp);
+               base = ((u64)tmp & PCI_PREF_RANGE_MASK) << 16;
+
+               raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0),
+                                 PCI_PREF_BASE_UPPER32, 4, &tmp);
+               base |= (u64)tmp << 32;
+
+               raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0),
+                                 PCI_PREF_MEMORY_LIMIT, 2, &tmp);
+
+               limit = ((u64)tmp & PCI_PREF_RANGE_MASK) << 16;
+               limit |= 0xfffffUL;
+
+               raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0),
+                                 PCI_PREF_LIMIT_UPPER32, 4, &tmp);
+               limit |= (u64)tmp << 32;
+
+               if ((base < limit) && TIOCE_M32_ADDR(base))
+                       tioce_reserve_m32(tioce_kern, base, limit);
        }
 
        return tioce_kern;
@@ -614,6 +837,7 @@ tioce_force_interrupt(struct sn_irq_info *sn_irq_info)
 {
        struct pcidev_info *pcidev_info;
        struct tioce_common *ce_common;
+       struct tioce_kernel *ce_kern;
        struct tioce *ce_mmr;
        u64 force_int_val;
 
@@ -629,6 +853,29 @@ tioce_force_interrupt(struct sn_irq_info *sn_irq_info)
 
        ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info;
        ce_mmr = (struct tioce *)ce_common->ce_pcibus.bs_base;
+       ce_kern = (struct tioce_kernel *)ce_common->ce_kernel_private;
+
+       /*
+        * TIOCE Rev A workaround (PV 945826), force an interrupt by writing
+        * the TIO_INTx register directly (1/26/2006)
+        */
+       if (ce_common->ce_rev == TIOCE_REV_A) {
+               u64 int_bit_mask = (1ULL << sn_irq_info->irq_int_bit);
+               u64 status;
+
+               tioce_mmr_load(ce_kern, &ce_mmr->ce_adm_int_status, &status);
+               if (status & int_bit_mask) {
+                       u64 force_irq = (1 << 8) | sn_irq_info->irq_irq;
+                       u64 ctalk = sn_irq_info->irq_xtalkaddr;
+                       u64 nasid, offset;
+
+                       nasid = (ctalk & CTALK_NASID_MASK) >> CTALK_NASID_SHFT;
+                       offset = (ctalk & CTALK_NODE_OFFSET);
+                       HUB_S(TIO_IOSPACE_ADDR(nasid, offset), force_irq);
+               }
+
+               return;
+       }
 
        /*
         * irq_int_bit is originally set up by prom, and holds the interrupt
@@ -666,7 +913,7 @@ tioce_force_interrupt(struct sn_irq_info *sn_irq_info)
        default:
                return;
        }
-       writeq(force_int_val, &ce_mmr->ce_adm_force_int);
+       tioce_mmr_storei(ce_kern, &ce_mmr->ce_adm_force_int, force_int_val);
 }
 
 /**
@@ -685,6 +932,7 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info)
 {
        struct pcidev_info *pcidev_info;
        struct tioce_common *ce_common;
+       struct tioce_kernel *ce_kern;
        struct tioce *ce_mmr;
        int bit;
        u64 vector;
@@ -695,14 +943,15 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info)
 
        ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info;
        ce_mmr = (struct tioce *)ce_common->ce_pcibus.bs_base;
+       ce_kern = (struct tioce_kernel *)ce_common->ce_kernel_private;
 
        bit = sn_irq_info->irq_int_bit;
 
-       __sn_setq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit));
+       tioce_mmr_seti(ce_kern, &ce_mmr->ce_adm_int_mask, (1UL << bit));
        vector = (u64)sn_irq_info->irq_irq << INTR_VECTOR_SHFT;
        vector |= sn_irq_info->irq_xtalkaddr;
-       writeq(vector, &ce_mmr->ce_adm_int_dest[bit]);
-       __sn_clrq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit));
+       tioce_mmr_storei(ce_kern, &ce_mmr->ce_adm_int_dest[bit], vector);
+       tioce_mmr_clri(ce_kern, &ce_mmr->ce_adm_int_mask, (1UL << bit));
 
        tioce_force_interrupt(sn_irq_info);
 }
@@ -721,7 +970,11 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info)
 static void *
 tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller)
 {
+       int my_nasid;
+       cnodeid_t my_cnode, mem_cnode;
        struct tioce_common *tioce_common;
+       struct tioce_kernel *tioce_kern;
+       struct tioce *tioce_mmr;
 
        /*
         * Allocate kernel bus soft and copy from prom.
@@ -734,11 +987,23 @@ tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
        memcpy(tioce_common, prom_bussoft, sizeof(struct tioce_common));
        tioce_common->ce_pcibus.bs_base |= __IA64_UNCACHED_OFFSET;
 
-       if (tioce_kern_init(tioce_common) == NULL) {
+       tioce_kern = tioce_kern_init(tioce_common);
+       if (tioce_kern == NULL) {
                kfree(tioce_common);
                return NULL;
        }
 
+       /*
+        * Clear out any transient errors before registering the error
+        * interrupt handler.
+        */
+
+       tioce_mmr = (struct tioce *)tioce_common->ce_pcibus.bs_base;
+       tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_adm_int_status_alias, ~0ULL);
+       tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_adm_error_summary_alias,
+                      ~0ULL);
+       tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_dre_comp_err_addr, ~0ULL);
+
        if (request_irq(SGI_PCIASIC_ERROR,
                        tioce_error_intr_handler,
                        SA_SHIRQ, "TIOCE error", (void *)tioce_common))
@@ -750,6 +1015,21 @@ tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
                       tioce_common->ce_pcibus.bs_persist_segment,
                       tioce_common->ce_pcibus.bs_persist_busnum);
 
+       /*
+        * identify closest nasid for memory allocations
+        */
+
+       my_nasid = NASID_GET(tioce_common->ce_pcibus.bs_base);
+       my_cnode = nasid_to_cnodeid(my_nasid);
+
+       if (sn_hwperf_get_nearest_node(my_cnode, &mem_cnode, NULL) < 0) {
+               printk(KERN_WARNING "tioce_bus_fixup: failed to find "
+                      "closest node with MEM to TIO node %d\n", my_cnode);
+               mem_cnode = (cnodeid_t)-1; /* use any node */
+       }
+
+       controller->node = mem_cnode;
+
        return tioce_common;
 }
 
index a9efc13cc8583e127070b8b19394773e4fecedbc..8a98169b60c1ad42cb240bf71202f30d1f4f1e33 100644 (file)
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Silicon Graphics, Inc. All rights reserved.
  */
 
 /*
@@ -70,6 +70,9 @@ struct sysctl_data_s {
 #define EV_CLASS_TEST_WARNING  0x6000ul
 #define EV_CLASS_PWRD_NOTIFY   0x8000ul
 
+/* ENV class codes */
+#define ENV_PWRDN_PEND         0x4101ul
+
 #define EV_SEVERITY_POWER_STABLE       0x0000ul
 #define EV_SEVERITY_POWER_LOW_WARNING  0x0100ul
 #define EV_SEVERITY_POWER_HIGH_WARNING 0x0200ul
index baaa365285fa973776beddcb0ae5c09389ffbe65..a4fa507eed9e451824541891bf7e4f83920c49d2 100644 (file)
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Silicon Graphics, Inc. All rights reserved.
  */
 
 /*
@@ -187,7 +187,8 @@ scdrv_event_severity(int code)
 static void
 scdrv_dispatch_event(char *event, int len)
 {
-       int code, esp_code, src;
+       static int snsc_shutting_down = 0;
+       int code, esp_code, src, class;
        char desc[CHUNKSIZE];
        char *severity;
 
@@ -199,9 +200,25 @@ scdrv_dispatch_event(char *event, int len)
        /* how urgent is the message? */
        severity = scdrv_event_severity(code);
 
-       if ((code & EV_CLASS_MASK) == EV_CLASS_PWRD_NOTIFY) {
+       class = (code & EV_CLASS_MASK);
+
+       if (class == EV_CLASS_PWRD_NOTIFY || code == ENV_PWRDN_PEND) {
                struct task_struct *p;
 
+               if (snsc_shutting_down)
+                       return;
+
+               snsc_shutting_down = 1;
+
+               /* give a message for each type of event */
+               if (class == EV_CLASS_PWRD_NOTIFY)
+                       printk(KERN_NOTICE "Power off indication received."
+                              " Sending SIGPWR to init...\n");
+               else if (code == ENV_PWRDN_PEND)
+                       printk(KERN_CRIT "WARNING: Shutting down the system"
+                              " due to a critical environmental condition."
+                              " Sending SIGPWR to init...\n");
+
                /* give a SIGPWR signal to init proc */
 
                /* first find init's task */
@@ -210,12 +227,11 @@ scdrv_dispatch_event(char *event, int len)
                        if (p->pid == 1)
                                break;
                }
-               if (p) { /* we found init's task */
-                       printk(KERN_EMERG "Power off indication received. Initiating power fail sequence...\n");
+               if (p) {
                        force_sig(SIGPWR, p);
-               } else { /* failed to find init's task - just give message(s) */
-                       printk(KERN_WARNING "Failed to find init proc to handle power off!\n");
-                       printk("%s|$(0x%x)%s\n", severity, esp_code, desc);
+               } else {
+                       printk(KERN_ERR "Failed to signal init!\n");
+                       snsc_shutting_down = 0; /* so can try again (?) */
                }
                read_unlock(&tasklist_lock);
        } else {
index ea75b3d0612b596819fba49a6d17c8e24939e941..67140a5804f574b97eb6a8823f3affb3b2088830 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/ioc4.h>
 #include <linux/mmtimer.h>
 #include <linux/rtc.h>
-#include <linux/rwsem.h>
+#include <linux/mutex.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/clksupport.h>
 #include <asm/sn/shub_mmr.h>
  * Submodule management *
  ************************/
 
-static LIST_HEAD(ioc4_devices);
-static DECLARE_RWSEM(ioc4_devices_rwsem);
+static DEFINE_MUTEX(ioc4_mutex);
 
+static LIST_HEAD(ioc4_devices);
 static LIST_HEAD(ioc4_submodules);
-static DECLARE_RWSEM(ioc4_submodules_rwsem);
 
 /* Register an IOC4 submodule */
 int
@@ -66,15 +65,13 @@ ioc4_register_submodule(struct ioc4_submodule *is)
 {
        struct ioc4_driver_data *idd;
 
-       down_write(&ioc4_submodules_rwsem);
+       mutex_lock(&ioc4_mutex);
        list_add(&is->is_list, &ioc4_submodules);
-       up_write(&ioc4_submodules_rwsem);
 
        /* Initialize submodule for each IOC4 */
        if (!is->is_probe)
-               return 0;
+               goto out;
 
-       down_read(&ioc4_devices_rwsem);
        list_for_each_entry(idd, &ioc4_devices, idd_list) {
                if (is->is_probe(idd)) {
                        printk(KERN_WARNING
@@ -84,8 +81,8 @@ ioc4_register_submodule(struct ioc4_submodule *is)
                               pci_name(idd->idd_pdev));
                }
        }
-       up_read(&ioc4_devices_rwsem);
-
+ out:
+       mutex_unlock(&ioc4_mutex);
        return 0;
 }
 
@@ -95,15 +92,13 @@ ioc4_unregister_submodule(struct ioc4_submodule *is)
 {
        struct ioc4_driver_data *idd;
 
-       down_write(&ioc4_submodules_rwsem);
+       mutex_lock(&ioc4_mutex);
        list_del(&is->is_list);
-       up_write(&ioc4_submodules_rwsem);
 
        /* Remove submodule for each IOC4 */
        if (!is->is_remove)
-               return;
+               goto out;
 
-       down_read(&ioc4_devices_rwsem);
        list_for_each_entry(idd, &ioc4_devices, idd_list) {
                if (is->is_remove(idd)) {
                        printk(KERN_WARNING
@@ -113,7 +108,8 @@ ioc4_unregister_submodule(struct ioc4_submodule *is)
                               pci_name(idd->idd_pdev));
                }
        }
-       up_read(&ioc4_devices_rwsem);
+ out:
+       mutex_unlock(&ioc4_mutex);
 }
 
 /*********************
@@ -312,12 +308,11 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
        /* Track PCI-device specific data */
        idd->idd_serial_data = NULL;
        pci_set_drvdata(idd->idd_pdev, idd);
-       down_write(&ioc4_devices_rwsem);
+
+       mutex_lock(&ioc4_mutex);
        list_add(&idd->idd_list, &ioc4_devices);
-       up_write(&ioc4_devices_rwsem);
 
        /* Add this IOC4 to all submodules */
-       down_read(&ioc4_submodules_rwsem);
        list_for_each_entry(is, &ioc4_submodules, is_list) {
                if (is->is_probe && is->is_probe(idd)) {
                        printk(KERN_WARNING
@@ -327,7 +322,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
                               pci_name(idd->idd_pdev));
                }
        }
-       up_read(&ioc4_submodules_rwsem);
+       mutex_unlock(&ioc4_mutex);
 
        return 0;
 
@@ -351,7 +346,7 @@ ioc4_remove(struct pci_dev *pdev)
        idd = pci_get_drvdata(pdev);
 
        /* Remove this IOC4 from all submodules */
-       down_read(&ioc4_submodules_rwsem);
+       mutex_lock(&ioc4_mutex);
        list_for_each_entry(is, &ioc4_submodules, is_list) {
                if (is->is_remove && is->is_remove(idd)) {
                        printk(KERN_WARNING
@@ -361,7 +356,7 @@ ioc4_remove(struct pci_dev *pdev)
                               pci_name(idd->idd_pdev));
                }
        }
-       up_read(&ioc4_submodules_rwsem);
+       mutex_unlock(&ioc4_mutex);
 
        /* Release resources */
        iounmap(idd->idd_misc_regs);
@@ -377,9 +372,9 @@ ioc4_remove(struct pci_dev *pdev)
        pci_disable_device(pdev);
 
        /* Remove and free driver data */
-       down_write(&ioc4_devices_rwsem);
+       mutex_lock(&ioc4_mutex);
        list_del(&idd->idd_list);
-       up_write(&ioc4_devices_rwsem);
+       mutex_unlock(&ioc4_mutex);
        kfree(idd);
 }
 
index a7122d850177e32329fca606349f1a41f8025be3..d069b6acddce1e82838001f739fee3de431195be 100644 (file)
  *
  * Copyright (C) 2002,2003 Jun Nakajima <jun.nakajima@intel.com>
  * Copyright (C) 2002,2003 Suresh Siddha <suresh.b.siddha@intel.com>
+ * Copyright (C) 2005,2006 Hongjiu Lu <hongjiu.lu@intel.com>
  *
  */
-#include <asm/types.h>
-
-void  __lfetch(int lfhint, void *y);
-void  __lfetch_excl(int lfhint, void *y);
-void  __lfetch_fault(int lfhint, void *y);
-void  __lfetch_fault_excl(int lfhint, void *y);
-
-/* In the following, whichFloatReg should be an integer from 0-127 */
-void  __ldfs(const int whichFloatReg, void *src);
-void  __ldfd(const int whichFloatReg, void *src);
-void  __ldfe(const int whichFloatReg, void *src);
-void  __ldf8(const int whichFloatReg, void *src);
-void  __ldf_fill(const int whichFloatReg, void *src);
-void  __stfs(void *dst, const int whichFloatReg);
-void  __stfd(void *dst, const int whichFloatReg);
-void  __stfe(void *dst, const int whichFloatReg);
-void  __stf8(void *dst, const int whichFloatReg);
-void  __stf_spill(void *dst, const int whichFloatReg);
-
-void  __st1_rel(void *dst, const __s8  value);
-void  __st2_rel(void *dst, const __s16 value);
-void  __st4_rel(void *dst, const __s32 value);
-void  __st8_rel(void *dst, const __s64 value);
-__u8  __ld1_acq(void *src);
-__u16 __ld2_acq(void *src);
-__u32 __ld4_acq(void *src);
-__u64 __ld8_acq(void *src);
-
-__u64 __fetchadd4_acq(__u32 *addend, const int increment);
-__u64 __fetchadd4_rel(__u32 *addend, const int increment);
-__u64 __fetchadd8_acq(__u64 *addend, const int increment);
-__u64 __fetchadd8_rel(__u64 *addend, const int increment);
-
-__u64 __getf_exp(double d);
-
-/* OS Related Itanium(R) Intrinsics  */
-
-/* The names to use for whichReg and whichIndReg below come from
-   the include file asm/ia64regs.h */
-
-__u64 __getIndReg(const int whichIndReg, __s64 index);
-__u64 __getReg(const int whichReg);
-
-void  __setIndReg(const int whichIndReg, __s64 index, __u64 value);
-void  __setReg(const int whichReg, __u64 value);
-
-void  __mf(void);
-void  __mfa(void);
-void  __synci(void);
-void  __itcd(__s64 pa);
-void  __itci(__s64 pa);
-void  __itrd(__s64 whichTransReg, __s64 pa);
-void  __itri(__s64 whichTransReg, __s64 pa);
-void  __ptce(__s64 va);
-void  __ptcl(__s64 va, __s64 pagesz);
-void  __ptcg(__s64 va, __s64 pagesz);
-void  __ptcga(__s64 va, __s64 pagesz);
-void  __ptri(__s64 va, __s64 pagesz);
-void  __ptrd(__s64 va, __s64 pagesz);
-void  __invala (void);
-void  __invala_gr(const int whichGeneralReg /* 0-127 */ );
-void  __invala_fr(const int whichFloatReg /* 0-127 */ );
-void  __nop(const int);
-void  __fc(__u64 *addr);
-void  __sum(int mask);
-void  __rum(int mask);
-void  __ssm(int mask);
-void  __rsm(int mask);
-__u64 __thash(__s64);
-__u64 __ttag(__s64);
-__s64 __tpa(__s64);
-
-/* Intrinsics for implementing get/put_user macros */
-void __st_user(const char *tableName, __u64 addr, char size, char relocType, __u64 val);
-void __ld_user(const char *tableName, __u64 addr, char size, char relocType);
-
-/* This intrinsic does not generate code, it creates a barrier across which
- * the compiler will not schedule data access instructions.
- */
-void __memory_barrier(void);
-
-void __isrlz(void);
-void __dsrlz(void);
-
-__u64  _m64_mux1(__u64 a, const int n);
-__u64  __thash(__u64);
-
-/* Lock and Atomic Operation Related Intrinsics */
-__u64 _InterlockedExchange8(volatile __u8 *trgt, __u8 value);
-__u64 _InterlockedExchange16(volatile __u16 *trgt, __u16 value);
-__s64 _InterlockedExchange(volatile __u32 *trgt, __u32 value);
-__s64 _InterlockedExchange64(volatile __u64 *trgt, __u64 value);
-
-__u64 _InterlockedCompareExchange8_rel(volatile __u8 *dest, __u64 xchg, __u64 comp);
-__u64 _InterlockedCompareExchange8_acq(volatile __u8 *dest, __u64 xchg, __u64 comp);
-__u64 _InterlockedCompareExchange16_rel(volatile __u16 *dest, __u64 xchg, __u64 comp);
-__u64 _InterlockedCompareExchange16_acq(volatile __u16 *dest, __u64 xchg, __u64 comp);
-__u64 _InterlockedCompareExchange_rel(volatile __u32 *dest, __u64 xchg, __u64 comp);
-__u64 _InterlockedCompareExchange_acq(volatile __u32 *dest, __u64 xchg, __u64 comp);
-__u64 _InterlockedCompareExchange64_rel(volatile __u64 *dest, __u64 xchg, __u64 comp);
-__u64 _InterlockedCompareExchange64_acq(volatile __u64 *dest, __u64 xchg, __u64 comp);
-
-__s64 _m64_dep_mi(const int v, __s64 s, const int p, const int len);
-__s64 _m64_shrp(__s64 a, __s64 b, const int count);
-__s64 _m64_popcnt(__s64 a);
+#include <ia64intrin.h>
 
 #define ia64_barrier()         __memory_barrier()
 
@@ -122,15 +19,16 @@ __s64 _m64_popcnt(__s64 a);
 #define ia64_getreg            __getReg
 #define ia64_setreg            __setReg
 
-#define ia64_hint(x)
+#define ia64_hint              __hint
+#define ia64_hint_pause                __hint_pause
 
-#define ia64_mux1_brcst         0
-#define ia64_mux1_mix           8
-#define ia64_mux1_shuf          9
-#define ia64_mux1_alt          10
-#define ia64_mux1_rev          11
+#define ia64_mux1_brcst                _m64_mux1_brcst
+#define ia64_mux1_mix          _m64_mux1_mix
+#define ia64_mux1_shuf         _m64_mux1_shuf
+#define ia64_mux1_alt          _m64_mux1_alt
+#define ia64_mux1_rev          _m64_mux1_rev
 
-#define ia64_mux1              _m64_mux1
+#define ia64_mux1(x,v)         _m_to_int64(_m64_mux1(_m_from_int64(x), (v)))
 #define ia64_popcnt            _m64_popcnt
 #define ia64_getf_exp          __getf_exp
 #define ia64_shrp              _m64_shrp
@@ -158,7 +56,7 @@ __s64 _m64_popcnt(__s64 a);
 #define ia64_stf8              __stf8
 #define ia64_stf_spill         __stf_spill
 
-#define ia64_mf                __mf
+#define ia64_mf                        __mf
 #define ia64_mfa               __mfa
 
 #define ia64_fetchadd4_acq     __fetchadd4_acq
@@ -234,10 +132,10 @@ __s64 _m64_popcnt(__s64 a);
 
 /* Values for lfhint in __lfetch and __lfetch_fault */
 
-#define ia64_lfhint_none       0
-#define ia64_lfhint_nt1        1
-#define ia64_lfhint_nt2        2
-#define ia64_lfhint_nta        3
+#define ia64_lfhint_none       __lfhint_none
+#define ia64_lfhint_nt1                __lfhint_nt1
+#define ia64_lfhint_nt2                __lfhint_nt2
+#define ia64_lfhint_nta                __lfhint_nta
 
 #define ia64_lfetch            __lfetch
 #define ia64_lfetch_excl       __lfetch_excl
@@ -254,4 +152,6 @@ do {                                                        \
        }                                               \
 } while (0)
 
+#define __builtin_trap()       __break(0);
+
 #endif /* _ASM_IA64_INTEL_INTRIN_H */
index ca5ea994d68872998302e20f6a2566e143b3e1cc..c3e4ed8a3e1753c197f0d21be7b084ec3c9a37d0 100644 (file)
@@ -20,6 +20,7 @@ struct scatterlist;
 struct page;
 struct mm_struct;
 struct pci_bus;
+struct task_struct;
 
 typedef void ia64_mv_setup_t (char **);
 typedef void ia64_mv_cpu_init_t (void);
@@ -34,6 +35,7 @@ typedef int ia64_mv_pci_legacy_read_t (struct pci_bus *, u16 port, u32 *val,
                                       u8 size);
 typedef int ia64_mv_pci_legacy_write_t (struct pci_bus *, u16 port, u32 val,
                                        u8 size);
+typedef void ia64_mv_migrate_t(struct task_struct * task);
 
 /* DMA-mapping interface: */
 typedef void ia64_mv_dma_init (void);
@@ -85,6 +87,11 @@ machvec_noop_mm (struct mm_struct *mm)
 {
 }
 
+static inline void
+machvec_noop_task (struct task_struct *task)
+{
+}
+
 extern void machvec_setup (char **);
 extern void machvec_timer_interrupt (int, void *, struct pt_regs *);
 extern void machvec_dma_sync_single (struct device *, dma_addr_t, size_t, int);
@@ -146,6 +153,7 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *);
 #  define platform_readw_relaxed        ia64_mv.readw_relaxed
 #  define platform_readl_relaxed        ia64_mv.readl_relaxed
 #  define platform_readq_relaxed        ia64_mv.readq_relaxed
+#  define platform_migrate             ia64_mv.migrate
 # endif
 
 /* __attribute__((__aligned__(16))) is required to make size of the
@@ -194,6 +202,7 @@ struct ia64_machine_vector {
        ia64_mv_readw_relaxed_t *readw_relaxed;
        ia64_mv_readl_relaxed_t *readl_relaxed;
        ia64_mv_readq_relaxed_t *readq_relaxed;
+       ia64_mv_migrate_t *migrate;
 } __attribute__((__aligned__(16))); /* align attrib? see above comment */
 
 #define MACHVEC_INIT(name)                     \
@@ -238,6 +247,7 @@ struct ia64_machine_vector {
        platform_readw_relaxed,                 \
        platform_readl_relaxed,                 \
        platform_readq_relaxed,                 \
+       platform_migrate,                       \
 }
 
 extern struct ia64_machine_vector ia64_mv;
@@ -386,5 +396,8 @@ extern ia64_mv_dma_supported                swiotlb_dma_supported;
 #ifndef platform_readq_relaxed
 # define platform_readq_relaxed        __ia64_readq_relaxed
 #endif
+#ifndef platform_migrate
+# define platform_migrate machvec_noop_task
+#endif
 
 #endif /* _ASM_IA64_MACHVEC_H */
index 03d00faf03b5c414a473b8a28d4e793a9e63787b..da1d43755afea2de3730c40dbda81b09d41eda8e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2003, 2006 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2002-2003,2006 Silicon Graphics, Inc.  All Rights Reserved.
  * 
  * This program is free software; you can redistribute it and/or modify it 
  * under the terms of version 2 of the GNU General Public License 
@@ -66,6 +66,7 @@ extern ia64_mv_dma_sync_single_for_device sn_dma_sync_single_for_device;
 extern ia64_mv_dma_sync_sg_for_device  sn_dma_sync_sg_for_device;
 extern ia64_mv_dma_mapping_error       sn_dma_mapping_error;
 extern ia64_mv_dma_supported           sn_dma_supported;
+extern ia64_mv_migrate_t               sn_migrate;
 
 /*
  * This stuff has dual use!
@@ -115,6 +116,7 @@ extern ia64_mv_dma_supported                sn_dma_supported;
 #define platform_dma_sync_sg_for_device        sn_dma_sync_sg_for_device
 #define platform_dma_mapping_error             sn_dma_mapping_error
 #define platform_dma_supported         sn_dma_supported
+#define platform_migrate               sn_migrate
 
 #include <asm/sn/io.h>
 
index c7d9c9ed38baa518392cf9adcded3b90a299551e..bfbbb8da79c7b9e577bed354ce15145f0db34582 100644 (file)
@@ -131,6 +131,8 @@ struct ia64_mca_cpu {
 /* Array of physical addresses of each CPU's MCA area.  */
 extern unsigned long __per_cpu_mca[NR_CPUS];
 
+extern int cpe_vector;
+extern int ia64_cpe_irq;
 extern void ia64_mca_init(void);
 extern void ia64_mca_cpu_init(void *);
 extern void ia64_os_mca_dispatch(void);
index 458c1f7fbc1808d48982aa0c5fe89bfe3df2098c..5a3224f6af380aaa89aeb71f081ff6909304d9de 100644 (file)
@@ -1,9 +1,92 @@
 /*
- * Pull in the generic implementation for the mutex fastpath.
+ * ia64 implementation of the mutex fastpath.
  *
- * TODO: implement optimized primitives instead, or leave the generic
- * implementation in place, or pick the atomic_xchg() based generic
- * implementation. (see asm-generic/mutex-xchg.h for details)
+ * Copyright (C) 2006 Ken Chen <kenneth.w.chen@intel.com>
+ *
+ */
+
+#ifndef _ASM_MUTEX_H
+#define _ASM_MUTEX_H
+
+/**
+ *  __mutex_fastpath_lock - try to take the lock by moving the count
+ *                          from 1 to a 0 value
+ *  @count: pointer of type atomic_t
+ *  @fail_fn: function to call if the original value was not 1
+ *
+ * Change the count from 1 to a value lower than 1, and call <fail_fn> if
+ * it wasn't 1 originally. This function MUST leave the value lower than
+ * 1 even when the "1" assertion wasn't true.
+ */
+static inline void
+__mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
+{
+       if (unlikely(ia64_fetchadd4_acq(count, -1) != 1))
+               fail_fn(count);
+}
+
+/**
+ *  __mutex_fastpath_lock_retval - try to take the lock by moving the count
+ *                                 from 1 to a 0 value
+ *  @count: pointer of type atomic_t
+ *  @fail_fn: function to call if the original value was not 1
+ *
+ * Change the count from 1 to a value lower than 1, and call <fail_fn> if
+ * it wasn't 1 originally. This function returns 0 if the fastpath succeeds,
+ * or anything the slow path function returns.
+ */
+static inline int
+__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
+{
+       if (unlikely(ia64_fetchadd4_acq(count, -1) != 1))
+               return fail_fn(count);
+       return 0;
+}
+
+/**
+ *  __mutex_fastpath_unlock - try to promote the count from 0 to 1
+ *  @count: pointer of type atomic_t
+ *  @fail_fn: function to call if the original value was not 0
+ *
+ * Try to promote the count from 0 to 1. If it wasn't 0, call <fail_fn>.
+ * In the failure case, this function is allowed to either set the value to
+ * 1, or to set it to a value lower than 1.
+ *
+ * If the implementation sets it to a value of lower than 1, then the
+ * __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs
+ * to return 0 otherwise.
+ */
+static inline void
+__mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
+{
+       int ret = ia64_fetchadd4_rel(count, 1);
+       if (unlikely(ret < 0))
+               fail_fn(count);
+}
+
+#define __mutex_slowpath_needs_to_unlock()             1
+
+/**
+ * __mutex_fastpath_trylock - try to acquire the mutex, without waiting
+ *
+ *  @count: pointer of type atomic_t
+ *  @fail_fn: fallback function
+ *
+ * Change the count from 1 to a value lower than 1, and return 0 (failure)
+ * if it wasn't 1 originally, or return 1 (success) otherwise. This function
+ * MUST leave the value lower than 1 even when the "1" assertion wasn't true.
+ * Additionally, if the value was < 0 originally, this function must not leave
+ * it to 0 on failure.
+ *
+ * If the architecture has no effective trylock variant, it should call the
+ * <fail_fn> spinlock-based trylock variant unconditionally.
  */
+static inline int
+__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
+{
+       if (likely(cmpxchg_acq(count, 1, 0)) == 1)
+               return 1;
+       return 0;
+}
 
-#include <asm-generic/mutex-dec.h>
+#endif
index 23c8e1be1911873ec0efd3441f6216eff536e401..128fefd8056fc6c308c3b33b2459bd12a4e7dfad 100644 (file)
@@ -50,7 +50,8 @@
 #define IA64_THREAD_PM_VALID   (__IA64_UL(1) << 2)     /* performance registers valid? */
 #define IA64_THREAD_UAC_NOPRINT        (__IA64_UL(1) << 3)     /* don't log unaligned accesses */
 #define IA64_THREAD_UAC_SIGBUS (__IA64_UL(1) << 4)     /* generate SIGBUS on unaligned acc. */
-                                                       /* bit 5 is currently unused */
+#define IA64_THREAD_MIGRATION  (__IA64_UL(1) << 5)     /* require migration
+                                                          sync at ctx sw */
 #define IA64_THREAD_FPEMU_NOPRINT (__IA64_UL(1) << 6)  /* don't log any fpswa faults */
 #define IA64_THREAD_FPEMU_SIGFPE  (__IA64_UL(1) << 7)  /* send a SIGFPE for fpswa faults */
 
index 608168d713d374293847753114173622ff0853c1..5e328ed5d01d5f33b55d80e2be3575759f817b18 100644 (file)
@@ -158,8 +158,6 @@ struct k_sigaction {
 
 #define ptrace_signal_deliver(regs, cookie) do { } while (0)
 
-void set_sigdelayed(pid_t pid, int signo, int code, void __user *addr);
-
 #endif /* __KERNEL__ */
 
 # endif /* !__ASSEMBLY__ */
index 2c32e4b77b54051e1237fb99a55825555c8b71cf..1d9efe541662927819dc2c70220da507ea6f98dd 100644 (file)
 #define REMOTE_HUB_L(n, a)             HUB_L(REMOTE_HUB_ADDR((n), (a)))
 #define REMOTE_HUB_S(n, a, d)          HUB_S(REMOTE_HUB_ADDR((n), (a)), (d))
 
+/*
+ * Coretalk address breakdown
+ */
+#define CTALK_NASID_SHFT               40
+#define CTALK_NASID_MASK               (0x3FFFULL << CTALK_NASID_SHFT)
+#define CTALK_CID_SHFT                 38
+#define CTALK_CID_MASK                 (0x3ULL << CTALK_CID_SHFT)
+#define CTALK_NODE_OFFSET              0x3FFFFFFFFF
 
 #endif /* _ASM_IA64_SN_ADDRS_H */
index f40fd1a5510d9a58d5937b4d4ae043048cecfb47..2d78f4c5a45e216a3218616c4287625ae37eef73 100644 (file)
@@ -3,15 +3,14 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2002-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (C) 2002-2006 Silicon Graphics, Inc.  All Rights Reserved.
  */
 #ifndef _ASM_IA64_SN_RW_MMR_H
 #define _ASM_IA64_SN_RW_MMR_H
 
 
 /*
- * This file contains macros used to access MMR registers via
- * uncached physical addresses.
+ * This file that access MMRs via uncached physical addresses.
  *     pio_phys_read_mmr  - read an MMR
  *     pio_phys_write_mmr - write an MMR
  *     pio_atomic_phys_write_mmrs - atomically write 1 or 2 MMRs with psr.ic=0
  */
 
 
-extern inline long
-pio_phys_read_mmr(volatile long *mmr) 
-{
-       long val;
-        asm volatile
-            ("mov r2=psr;;"
-             "rsm psr.i | psr.dt;;"
-             "srlz.i;;"
-             "ld8.acq %0=[%1];;"
-             "mov psr.l=r2;;"
-             "srlz.i;;"
-             : "=r"(val)
-             : "r"(mmr)
-            : "r2");
-        return val;
-}
-
-
-
-extern inline void
-pio_phys_write_mmr(volatile long *mmr, long val) 
-{
-        asm volatile
-            ("mov r2=psr;;"
-             "rsm psr.i | psr.dt;;"
-             "srlz.i;;"
-             "st8.rel [%0]=%1;;"
-             "mov psr.l=r2;;"
-             "srlz.i;;"
-            :: "r"(mmr), "r"(val)
-             : "r2", "memory");
-}            
-
-extern inline void
-pio_atomic_phys_write_mmrs(volatile long *mmr1, long val1, volatile long *mmr2, long val2) 
-{
-        asm volatile
-            ("mov r2=psr;;"
-             "rsm psr.i | psr.dt | psr.ic;;"
-            "cmp.ne p9,p0=%2,r0;"
-             "srlz.i;;"
-             "st8.rel [%0]=%1;"
-             "(p9) st8.rel [%2]=%3;;"
-             "mov psr.l=r2;;"
-             "srlz.i;;"
-            :: "r"(mmr1), "r"(val1), "r"(mmr2), "r"(val2)
-             : "p9", "r2", "memory");
-}            
+extern long pio_phys_read_mmr(volatile long *mmr); 
+extern void pio_phys_write_mmr(volatile long *mmr, long val);
+extern void pio_atomic_phys_write_mmrs(volatile long *mmr1, long val1, volatile long *mmr2, long val2); 
 
 #endif /* _ASM_IA64_SN_RW_MMR_H */
index d4c990712eacd38a76113149156c7d00d502bfb5..893468e1b41b7f4214a9f1057f6387015c7dd671 100644 (file)
@@ -11,7 +11,7 @@
 
 /* CE ASIC part & mfgr information  */
 #define TIOCE_PART_NUM                 0xCE00
-#define TIOCE_MFGR_NUM                 0x36
+#define TIOCE_SRC_ID                   0x01
 #define TIOCE_REV_A                    0x1
 
 /* CE Virtual PPB Vendor/Device IDs */
@@ -20,7 +20,7 @@
 
 /* CE Host Bridge Vendor/Device IDs */
 #define CE_HOST_BRIDGE_VENDOR_ID       0x10a9
-#define CE_HOST_BRIDGE_DEVICE_ID       0x4003
+#define CE_HOST_BRIDGE_DEVICE_ID       0x4001
 
 
 #define TIOCE_NUM_M40_ATES             4096
@@ -463,6 +463,25 @@ typedef volatile struct tioce {
        u64     ce_end_of_struct;                       /* 0x044400 */
 } tioce_t;
 
+/* ce_lsiX_gb_cfg1 register bit masks & shifts */
+#define CE_LSI_GB_CFG1_RXL0S_THS_SHFT  0
+#define CE_LSI_GB_CFG1_RXL0S_THS_MASK  (0xffULL << 0)
+#define CE_LSI_GB_CFG1_RXL0S_SMP_SHFT  8
+#define CE_LSI_GB_CFG1_RXL0S_SMP_MASK  (0xfULL << 8);
+#define CE_LSI_GB_CFG1_RXL0S_ADJ_SHFT  12
+#define CE_LSI_GB_CFG1_RXL0S_ADJ_MASK  (0x7ULL << 12)
+#define CE_LSI_GB_CFG1_RXL0S_FLT_SHFT  15
+#define CE_LSI_GB_CFG1_RXL0S_FLT_MASK  (0x1ULL << 15)
+#define CE_LSI_GB_CFG1_LPBK_SEL_SHFT   16
+#define CE_LSI_GB_CFG1_LPBK_SEL_MASK   (0x3ULL << 16)
+#define CE_LSI_GB_CFG1_LPBK_EN_SHFT    18
+#define CE_LSI_GB_CFG1_LPBK_EN_MASK    (0x1ULL << 18)
+#define CE_LSI_GB_CFG1_RVRS_LB_SHFT    19
+#define CE_LSI_GB_CFG1_RVRS_LB_MASK    (0x1ULL << 19)
+#define CE_LSI_GB_CFG1_RVRS_CLK_SHFT   20
+#define CE_LSI_GB_CFG1_RVRS_CLK_MASK   (0x3ULL << 20)
+#define CE_LSI_GB_CFG1_SLF_TS_SHFT     24
+#define CE_LSI_GB_CFG1_SLF_TS_MASK     (0xfULL << 24)
 
 /* ce_adm_int_mask/ce_adm_int_status register bit defines */
 #define CE_ADM_INT_CE_ERROR_SHFT               0
@@ -592,6 +611,11 @@ typedef volatile struct tioce {
 #define CE_URE_RD_MRG_ENABLE           (0x1ULL << 0)
 #define CE_URE_WRT_MRG_ENABLE1         (0x1ULL << 4)
 #define CE_URE_WRT_MRG_ENABLE2         (0x1ULL << 5)
+#define CE_URE_WRT_MRG_TIMER_SHFT      12
+#define CE_URE_WRT_MRG_TIMER_MASK      (0x7FFULL << CE_URE_WRT_MRG_TIMER_SHFT)
+#define CE_URE_WRT_MRG_TIMER(x)                (((u64)(x) << \
+                                         CE_URE_WRT_MRG_TIMER_SHFT) & \
+                                        CE_URE_WRT_MRG_TIMER_MASK)
 #define CE_URE_RSPQ_BYPASS_DISABLE     (0x1ULL << 24)
 #define CE_URE_UPS_DAT1_PAR_DISABLE    (0x1ULL << 32)
 #define CE_URE_UPS_HDR1_PAR_DISABLE    (0x1ULL << 33)
@@ -653,8 +677,12 @@ typedef volatile struct tioce {
 #define CE_URE_SI                      (0x1ULL << 0)
 #define CE_URE_ELAL_SHFT               4
 #define CE_URE_ELAL_MASK               (0x7ULL << CE_URE_ELAL_SHFT)
+#define CE_URE_ELAL_SET(n)             (((u64)(n) << CE_URE_ELAL_SHFT) & \
+                                        CE_URE_ELAL_MASK)
 #define CE_URE_ELAL1_SHFT              8
 #define CE_URE_ELAL1_MASK              (0x7ULL << CE_URE_ELAL1_SHFT)
+#define CE_URE_ELAL1_SET(n)            (((u64)(n) << CE_URE_ELAL1_SHFT) & \
+                                        CE_URE_ELAL1_MASK)
 #define CE_URE_SCC                     (0x1ULL << 12)
 #define CE_URE_PN1_SHFT                        16
 #define CE_URE_PN1_MASK                        (0xFFULL << CE_URE_PN1_SHFT)
@@ -675,8 +703,12 @@ typedef volatile struct tioce {
 #define CE_URE_HPC                     (0x1ULL << 6)
 #define CE_URE_SPLV_SHFT               7
 #define CE_URE_SPLV_MASK               (0xFFULL << CE_URE_SPLV_SHFT)
+#define CE_URE_SPLV_SET(n)             (((u64)(n) << CE_URE_SPLV_SHFT) & \
+                                        CE_URE_SPLV_MASK)
 #define CE_URE_SPLS_SHFT               15
 #define CE_URE_SPLS_MASK               (0x3ULL << CE_URE_SPLS_SHFT)
+#define CE_URE_SPLS_SET(n)             (((u64)(n) << CE_URE_SPLS_SHFT) & \
+                                        CE_URE_SPLS_MASK)
 #define CE_URE_PSN1_SHFT               19
 #define CE_URE_PSN1_MASK               (0x1FFFULL << CE_URE_PSN1_SHFT)
 #define CE_URE_PSN2_SHFT               32
index df7f5f4f3cde2d7e68f8360ca771554c0039227e..aa3b8ace90308f7ec6004e2990a395da07885b64 100644 (file)
@@ -1227,28 +1227,6 @@ xpc_map_bte_errors(bte_result_t error)
 
 
 
-static inline void *
-xpc_kmalloc_cacheline_aligned(size_t size, gfp_t flags, void **base)
-{
-       /* see if kmalloc will give us cachline aligned memory by default */
-       *base = kmalloc(size, flags);
-       if (*base == NULL) {
-               return NULL;
-       }
-       if ((u64) *base == L1_CACHE_ALIGN((u64) *base)) {
-               return *base;
-       }
-       kfree(*base);
-
-       /* nope, we'll have to do it ourselves */
-       *base = kmalloc(size + L1_CACHE_BYTES, flags);
-       if (*base == NULL) {
-               return NULL;
-       }
-       return (void *) L1_CACHE_ALIGN((u64) *base);
-}
-
-
 /*
  * Check to see if there is any channel activity to/from the specified
  * partition.
index 06253871562303b223a9cbfef4ba017ed2f44f32..cd4233d66f15ba1746f0ee94049ded722a887114 100644 (file)
@@ -244,6 +244,13 @@ extern void ia64_load_extra (struct task_struct *task);
                __ia64_save_fpu((prev)->thread.fph);                            \
        }                                                                       \
        __switch_to(prev, next, last);                                          \
+       /* "next" in old context is "current" in new context */                 \
+       if (unlikely((current->thread.flags & IA64_THREAD_MIGRATION) &&        \
+                    (task_cpu(current) !=                                     \
+                                     task_thread_info(current)->last_cpu))) { \
+               platform_migrate(current);                                     \
+               task_thread_info(current)->last_cpu = task_cpu(current);       \
+       }                                                                      \
 } while (0)
 #else
 # define switch_to(prev,next,last)     __switch_to(prev, next, last)
index 1d6518fe1f024ddcaf7a563904af38149dc10e8b..56394a2c7055daed97e57b1fb3966e2acfd19622 100644 (file)
@@ -26,16 +26,10 @@ struct thread_info {
        struct exec_domain *exec_domain;/* execution domain */
        __u32 flags;                    /* thread_info flags (see TIF_*) */
        __u32 cpu;                      /* current CPU */
+       __u32 last_cpu;                 /* Last CPU thread ran on */
        mm_segment_t addr_limit;        /* user-level address space limit */
        int preempt_count;              /* 0=premptable, <0=BUG; will also serve as bh-counter */
        struct restart_block restart_block;
-       struct {
-               int signo;
-               int code;
-               void __user *addr;
-               unsigned long start_time;
-               pid_t pid;
-       } sigdelayed;                   /* Saved information for TIF_SIGDELAYED */
 };
 
 #define THREAD_SIZE                    KERNEL_STACK_SIZE
@@ -89,7 +83,6 @@ struct thread_info {
 #define TIF_NEED_RESCHED       2       /* rescheduling necessary */
 #define TIF_SYSCALL_TRACE      3       /* syscall trace active */
 #define TIF_SYSCALL_AUDIT      4       /* syscall auditing active */
-#define TIF_SIGDELAYED         5       /* signal delayed from MCA/INIT/NMI/PMI context */
 #define TIF_POLLING_NRFLAG     16      /* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE             17
 #define TIF_MCA_INIT           18      /* this task is processing MCA or INIT */
@@ -101,13 +94,12 @@ struct thread_info {
 #define _TIF_NOTIFY_RESUME     (1 << TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING                (1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
-#define _TIF_SIGDELAYED                (1 << TIF_SIGDELAYED)
 #define _TIF_POLLING_NRFLAG    (1 << TIF_POLLING_NRFLAG)
 #define _TIF_MCA_INIT          (1 << TIF_MCA_INIT)
 #define _TIF_DB_DISABLED       (1 << TIF_DB_DISABLED)
 
 /* "work to do on user-return" bits */
-#define TIF_ALLWORK_MASK       (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SIGDELAYED)
+#define TIF_ALLWORK_MASK       (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
 /* like TIF_ALLWORK_BITS but sans TIF_SYSCALL_TRACE or TIF_SYSCALL_AUDIT */
 #define TIF_WORK_MASK          (TIF_ALLWORK_MASK&~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT))