aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2008-10-27 15:48:41 -0400
committerPaul Mackerras <paulus@samba.org>2008-11-05 17:25:15 -0500
commit57b066ff4ec53a0ac7cbf7fb363bb670cf58ddae (patch)
treedb3ad5a9f4bff3851990043828ea96c7496e91c6
parent8b8da35804bb89eee23f9bcd5638e1f754bd4c91 (diff)
powerpc/eeh: Make EEH device add/remove more robust
To properly fix PCI hotplug, it's useful to be able to make the fixup passes on all devices whether they were just hot plugged or already there. The EEH code however used to not be very friendly with calling eeh_add_device_late() multiple time, and not very rebust in the way it generally tests whether a device is in the expected state vs. the EEH code. This improves it, along with cleaning up a couple of debug printk's. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c44
1 files changed, 24 insertions, 20 deletions
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 54816d75b578..989d6462c154 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -21,6 +21,8 @@
21 * Please address comments and feedback to Linas Vepstas <linas@austin.ibm.com> 21 * Please address comments and feedback to Linas Vepstas <linas@austin.ibm.com>
22 */ 22 */
23 23
24#undef DEBUG
25
24#include <linux/delay.h> 26#include <linux/delay.h>
25#include <linux/init.h> 27#include <linux/init.h>
26#include <linux/list.h> 28#include <linux/list.h>
@@ -488,10 +490,8 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
488 if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) || 490 if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) ||
489 pdn->eeh_mode & EEH_MODE_NOCHECK) { 491 pdn->eeh_mode & EEH_MODE_NOCHECK) {
490 ignored_check++; 492 ignored_check++;
491#ifdef DEBUG 493 pr_debug("EEH: Ignored check (%x) for %s %s\n",
492 printk ("EEH:ignored check (%x) for %s %s\n", 494 pdn->eeh_mode, pci_name (dev), dn->full_name);
493 pdn->eeh_mode, pci_name (dev), dn->full_name);
494#endif
495 return 0; 495 return 0;
496 } 496 }
497 497
@@ -1014,10 +1014,9 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
1014 eeh_subsystem_enabled = 1; 1014 eeh_subsystem_enabled = 1;
1015 pdn->eeh_mode |= EEH_MODE_SUPPORTED; 1015 pdn->eeh_mode |= EEH_MODE_SUPPORTED;
1016 1016
1017#ifdef DEBUG 1017 pr_debug("EEH: %s: eeh enabled, config=%x pe_config=%x\n",
1018 printk(KERN_DEBUG "EEH: %s: eeh enabled, config=%x pe_config=%x\n", 1018 dn->full_name, pdn->eeh_config_addr,
1019 dn->full_name, pdn->eeh_config_addr, pdn->eeh_pe_config_addr); 1019 pdn->eeh_pe_config_addr);
1020#endif
1021 } else { 1020 } else {
1022 1021
1023 /* This device doesn't support EEH, but it may have an 1022 /* This device doesn't support EEH, but it may have an
@@ -1161,13 +1160,17 @@ static void eeh_add_device_late(struct pci_dev *dev)
1161 if (!dev || !eeh_subsystem_enabled) 1160 if (!dev || !eeh_subsystem_enabled)
1162 return; 1161 return;
1163 1162
1164#ifdef DEBUG 1163 pr_debug("EEH: Adding device %s\n", pci_name(dev));
1165 printk(KERN_DEBUG "EEH: adding device %s\n", pci_name(dev));
1166#endif
1167 1164
1168 pci_dev_get (dev);
1169 dn = pci_device_to_OF_node(dev); 1165 dn = pci_device_to_OF_node(dev);
1170 pdn = PCI_DN(dn); 1166 pdn = PCI_DN(dn);
1167 if (pdn->pcidev == dev) {
1168 pr_debug("EEH: Already referenced !\n");
1169 return;
1170 }
1171 WARN_ON(pdn->pcidev);
1172
1173 pci_dev_get (dev);
1171 pdn->pcidev = dev; 1174 pdn->pcidev = dev;
1172 1175
1173 pci_addr_cache_insert_device(dev); 1176 pci_addr_cache_insert_device(dev);
@@ -1206,17 +1209,18 @@ static void eeh_remove_device(struct pci_dev *dev)
1206 return; 1209 return;
1207 1210
1208 /* Unregister the device with the EEH/PCI address search system */ 1211 /* Unregister the device with the EEH/PCI address search system */
1209#ifdef DEBUG 1212 pr_debug("EEH: Removing device %s\n", pci_name(dev));
1210 printk(KERN_DEBUG "EEH: remove device %s\n", pci_name(dev));
1211#endif
1212 pci_addr_cache_remove_device(dev);
1213 eeh_sysfs_remove_device(dev);
1214 1213
1215 dn = pci_device_to_OF_node(dev); 1214 dn = pci_device_to_OF_node(dev);
1216 if (PCI_DN(dn)->pcidev) { 1215 if (PCI_DN(dn)->pcidev == NULL) {
1217 PCI_DN(dn)->pcidev = NULL; 1216 pr_debug("EEH: Not referenced !\n");
1218 pci_dev_put (dev); 1217 return;
1219 } 1218 }
1219 PCI_DN(dn)->pcidev = NULL;
1220 pci_dev_put (dev);
1221
1222 pci_addr_cache_remove_device(dev);
1223 eeh_sysfs_remove_device(dev);
1220} 1224}
1221 1225
1222void eeh_remove_bus_device(struct pci_dev *dev) 1226void eeh_remove_bus_device(struct pci_dev *dev)