Pull mca-cleanup into release branch
authorTony Luck <tony.luck@intel.com>
Tue, 21 Mar 2006 16:22:39 +0000 (08:22 -0800)
committerTony Luck <tony.luck@intel.com>
Tue, 21 Mar 2006 16:22:39 +0000 (08:22 -0800)
1  2 
arch/ia64/kernel/mca.c

diff --combined arch/ia64/kernel/mca.c
index 87fb7cecead00422e2aaf19671b4dfbaf99bf2a4,909fed2c24999fbe54e784e050cf97fb8533e847..b57e723f194c782aa6bc639717dcd57d5db0a947
@@@ -281,15 -281,9 +281,10 @@@ ia64_mca_log_sal_error_record(int sal_i
                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)
@@@ -378,8 -372,6 +373,6 @@@ ia64_mca_register_cpev (int cpev
  }
  #endif /* CONFIG_ACPI */
  
- #endif /* PLATFORM_MCA_HANDLERS */
  /*
   * ia64_mca_cmc_vector_setup
   *
@@@ -631,6 -623,32 +624,32 @@@ copy_reg(const u64 *fr, u64 fnat, u64 *
        *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
@@@ -649,7 -667,7 +668,7 @@@ ia64_mca_modify_original_stack(struct p
                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;
        /* 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) {
                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
@@@ -909,7 -913,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;
                }
        }
        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;
  }
  
  /*
@@@ -954,6 -975,10 +976,10 @@@ ia64_mca_handler(struct pt_regs *regs, 
        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)
@@@ -1445,13 -1470,11 +1471,13 @@@ void __devini
  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 +
@@@ -1707,7 -1730,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__);