linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / arch / powerpc / platforms / pseries / eeh_event.c
index 45ccc68..9a9961f 100644 (file)
  * Copyright (c) 2005 Linas Vepstas <linas@linas.org>
  */
 
-#include <linux/delay.h>
 #include <linux/list.h>
-#include <linux/mutex.h>
 #include <linux/pci.h>
-#include <linux/workqueue.h>
 #include <asm/eeh_event.h>
 #include <asm/ppc-pci.h>
 
  */
 
 /* EEH event workqueue setup. */
-static DEFINE_SPINLOCK(eeh_eventlist_lock);
+static spinlock_t eeh_eventlist_lock = SPIN_LOCK_UNLOCKED;
 LIST_HEAD(eeh_eventlist);
 static void eeh_thread_launcher(void *);
 DECLARE_WORK(eeh_event_wq, eeh_thread_launcher, NULL);
 
-/* Serialize reset sequences for a given pci device */
-DEFINE_MUTEX(eeh_event_mutex);
-
 /**
- * eeh_event_handler - dispatch EEH events.
- * @dummy - unused
+ * eeh_event_handler - dispatch EEH events.  The detection of a frozen
+ * slot can occur inside an interrupt, where it can be hard to do
+ * anything about it.  The goal of this routine is to pull these
+ * detection events out of the context of the interrupt handler, and
+ * re-dispatch them for processing at a later time in a normal context.
  *
- * The detection of a frozen slot can occur inside an interrupt,
- * where it can be hard to do anything about it.  The goal of this
- * routine is to pull these detection events out of the context
- * of the interrupt handler, and re-dispatch them for processing
- * at a later time in a normal context.
+ * @dummy - unused
  */
 static int eeh_event_handler(void * dummy)
 {
        unsigned long flags;
        struct eeh_event        *event;
-       struct pci_dn *pdn;
 
        daemonize ("eehd");
-       set_current_state(TASK_INTERRUPTIBLE);
 
-       spin_lock_irqsave(&eeh_eventlist_lock, flags);
-       event = NULL;
+       while (1) {
+               set_current_state(TASK_INTERRUPTIBLE);
 
-       /* Unqueue the event, get ready to process. */
-       if (!list_empty(&eeh_eventlist)) {
-               event = list_entry(eeh_eventlist.next, struct eeh_event, list);
-               list_del(&event->list);
-       }
-       spin_unlock_irqrestore(&eeh_eventlist_lock, flags);
+               spin_lock_irqsave(&eeh_eventlist_lock, flags);
+               event = NULL;
 
-       if (event == NULL)
-               return 0;
+               /* Unqueue the event, get ready to process. */
+               if (!list_empty(&eeh_eventlist)) {
+                       event = list_entry(eeh_eventlist.next, struct eeh_event, list);
+                       list_del(&event->list);
+               }
+               
+               if (event)
+                       eeh_mark_slot(event->dn, EEH_MODE_RECOVERING);
 
-       /* Serialize processing of EEH events */
-       mutex_lock(&eeh_event_mutex);
-       eeh_mark_slot(event->dn, EEH_MODE_RECOVERING);
+               spin_unlock_irqrestore(&eeh_eventlist_lock, flags);
+               if (event == NULL)
+                       break;
 
-       printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n",
-              pci_name(event->dev));
+               printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n",
+                      pci_name(event->dev));
 
-       pdn = handle_eeh_events(event);
+               handle_eeh_events(event);
 
-       eeh_clear_slot(event->dn, EEH_MODE_RECOVERING);
-       pci_dev_put(event->dev);
-       kfree(event);
-       mutex_unlock(&eeh_event_mutex);
+               eeh_clear_slot(event->dn, EEH_MODE_RECOVERING);
 
-       /* If there are no new errors after an hour, clear the counter. */
-       if (pdn && pdn->eeh_freeze_count>0) {
-               msleep_interruptible (3600*1000);
-               if (pdn->eeh_freeze_count>0)
-                       pdn->eeh_freeze_count--;
+               pci_dev_put(event->dev);
+               kfree(event);
        }
 
        return 0;
@@ -101,6 +88,7 @@ static int eeh_event_handler(void * dummy)
 
 /**
  * eeh_thread_launcher
+ *
  * @dummy - unused
  */
 static void eeh_thread_launcher(void *dummy)
@@ -124,15 +112,7 @@ int eeh_send_failure_event (struct device_node *dn,
 {
        unsigned long flags;
        struct eeh_event *event;
-       char *location;
 
-       if (!mem_init_done) {
-               printk(KERN_ERR "EEH: event during early boot not handled\n");
-               location = (char *) get_property(dn, "ibm,loc-code", NULL);
-               printk(KERN_ERR "EEH: device node = %s\n", dn->full_name);
-               printk(KERN_ERR "EEH: PCI location = %s\n", location);
-               return 1;
-       }
        event = kmalloc(sizeof(*event), GFP_ATOMIC);
        if (event == NULL) {
                printk (KERN_ERR "EEH: out of memory, event not handled\n");