Merge tag 's390-5.10-5' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
[linux-2.6-microblaze.git] / arch / powerpc / kernel / eeh_event.c
index 64cfbe4..a7a8dc1 100644 (file)
@@ -40,7 +40,6 @@ static int eeh_event_handler(void * dummy)
 {
        unsigned long flags;
        struct eeh_event *event;
-       struct eeh_pe *pe;
 
        while (!kthread_should_stop()) {
                if (wait_for_completion_interruptible(&eeh_eventlist_event))
@@ -59,19 +58,10 @@ static int eeh_event_handler(void * dummy)
                        continue;
 
                /* We might have event without binding PE */
-               pe = event->pe;
-               if (pe) {
-                       if (pe->type & EEH_PE_PHB)
-                               pr_info("EEH: Detected error on PHB#%x\n",
-                                        pe->phb->global_number);
-                       else
-                               pr_info("EEH: Detected PCI bus error on "
-                                       "PHB#%x-PE#%x\n",
-                                       pe->phb->global_number, pe->addr);
-                       eeh_handle_normal_event(pe);
-               } else {
+               if (event->pe)
+                       eeh_handle_normal_event(event->pe);
+               else
                        eeh_handle_special_event();
-               }
 
                kfree(event);
        }
@@ -121,6 +111,24 @@ int __eeh_send_failure_event(struct eeh_pe *pe)
        }
        event->pe = pe;
 
+       /*
+        * Mark the PE as recovering before inserting it in the queue.
+        * This prevents the PE from being free()ed by a hotplug driver
+        * while the PE is sitting in the event queue.
+        */
+       if (pe) {
+#ifdef CONFIG_STACKTRACE
+               /*
+                * Save the current stack trace so we can dump it from the
+                * event handler thread.
+                */
+               pe->trace_entries = stack_trace_save(pe->stack_trace,
+                                        ARRAY_SIZE(pe->stack_trace), 0);
+#endif /* CONFIG_STACKTRACE */
+
+               eeh_pe_state_mark(pe, EEH_PE_RECOVERING);
+       }
+
        /* We may or may not be called in an interrupt context */
        spin_lock_irqsave(&eeh_eventlist_lock, flags);
        list_add(&event->list, &eeh_eventlist);