]> git.karo-electronics.de Git - linux-beck.git/blobdiff - arch/powerpc/platforms/pseries/eeh_driver.c
[PATCH] powerpc/pseries: clear PCI failure counter if no new failures
[linux-beck.git] / arch / powerpc / platforms / pseries / eeh_driver.c
index cc2495a0cdd58754db004f3d34fe353c4dc65981..2a9eb26307306fa2b447f18cdde1ea2399de7d4e 100644 (file)
@@ -23,9 +23,8 @@
  *
  */
 #include <linux/delay.h>
-#include <linux/irq.h>
 #include <linux/interrupt.h>
-#include <linux/notifier.h>
+#include <linux/irq.h>
 #include <linux/pci.h>
 #include <asm/eeh.h>
 #include <asm/eeh_event.h>
@@ -250,7 +249,7 @@ static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus)
  */
 #define MAX_WAIT_FOR_RECOVERY 15
 
-void handle_eeh_events (struct eeh_event *event)
+struct pci_dn * handle_eeh_events (struct eeh_event *event)
 {
        struct device_node *frozen_dn;
        struct pci_dn *frozen_pdn;
@@ -265,7 +264,7 @@ void handle_eeh_events (struct eeh_event *event)
        if (!frozen_dn) {
                printk(KERN_ERR "EEH: Error: Cannot find partition endpoint for %s\n",
                        pci_name(event->dev));
-               return;
+               return NULL;
        }
 
        /* There are two different styles for coming up with the PE.
@@ -280,7 +279,7 @@ void handle_eeh_events (struct eeh_event *event)
        if (!frozen_bus) {
                printk(KERN_ERR "EEH: Cannot find PCI bus for %s\n",
                        frozen_dn->full_name);
-               return;
+               return NULL;
        }
 
 #if 0
@@ -293,15 +292,16 @@ void handle_eeh_events (struct eeh_event *event)
        frozen_pdn = PCI_DN(frozen_dn);
        frozen_pdn->eeh_freeze_count++;
 
-       pci_str = pci_name (frozen_pdn->pcidev);
-       drv_str = pcid_name (frozen_pdn->pcidev);
-       if (!pci_str) {
+       if (frozen_pdn->pcidev) {
+               pci_str = pci_name (frozen_pdn->pcidev);
+               drv_str = pcid_name (frozen_pdn->pcidev);
+       } else {
                pci_str = pci_name (event->dev);
                drv_str = pcid_name (event->dev);
        }
        
        if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES)
-               goto hard_fail;
+               goto excess_failures;
 
        /* If the reset state is a '5' and the time to reset is 0 (infinity)
         * or is more then 15 seconds, then mark this as a permanent failure.
@@ -354,9 +354,9 @@ void handle_eeh_events (struct eeh_event *event)
        /* Tell all device drivers that they can resume operations */
        pci_walk_bus(frozen_bus, eeh_report_resume, NULL);
 
-       return;
+       return frozen_pdn;
        
-hard_fail:
+excess_failures:
        /*
         * About 90% of all real-life EEH failures in the field
         * are due to poorly seated PCI cards. Only 10% or so are
@@ -367,7 +367,15 @@ hard_fail:
           "and has been permanently disabled.  Please try reseating\n"
           "this device or replacing it.\n",
                drv_str, pci_str, frozen_pdn->eeh_freeze_count);
+       goto perm_error;
 
+hard_fail:
+       printk(KERN_ERR
+          "EEH: Unable to recover from failure of PCI device %s - %s\n"
+          "Please try reseating this device or replacing it.\n",
+               drv_str, pci_str);
+
+perm_error:
        eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */);
 
        /* Notify all devices that they're about to go down. */
@@ -375,6 +383,8 @@ hard_fail:
 
        /* Shut down the device drivers for good. */
        pcibios_remove_pci_devices(frozen_bus);
+
+       return NULL;
 }
 
 /* ---------- end of file ---------- */