diff options
Diffstat (limited to 'arch/powerpc/platforms/pseries/eeh.c')
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh.c | 46 |
1 files changed, 23 insertions, 23 deletions
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index fb3d636e088b..9eb539ee5f9a 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #include <linux/rbtree.h> | 29 | #include <linux/rbtree.h> |
30 | #include <linux/seq_file.h> | 30 | #include <linux/seq_file.h> |
31 | #include <linux/spinlock.h> | 31 | #include <linux/spinlock.h> |
32 | #include <linux/of.h> | ||
33 | |||
32 | #include <asm/atomic.h> | 34 | #include <asm/atomic.h> |
33 | #include <asm/eeh.h> | 35 | #include <asm/eeh.h> |
34 | #include <asm/eeh_event.h> | 36 | #include <asm/eeh_event.h> |
@@ -169,7 +171,6 @@ static void rtas_slot_error_detail(struct pci_dn *pdn, int severity, | |||
169 | */ | 171 | */ |
170 | static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len) | 172 | static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len) |
171 | { | 173 | { |
172 | struct device_node *dn; | ||
173 | struct pci_dev *dev = pdn->pcidev; | 174 | struct pci_dev *dev = pdn->pcidev; |
174 | u32 cfg; | 175 | u32 cfg; |
175 | int cap, i; | 176 | int cap, i; |
@@ -243,12 +244,12 @@ static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len) | |||
243 | 244 | ||
244 | /* Gather status on devices under the bridge */ | 245 | /* Gather status on devices under the bridge */ |
245 | if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) { | 246 | if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) { |
246 | dn = pdn->node->child; | 247 | struct device_node *dn; |
247 | while (dn) { | 248 | |
249 | for_each_child_of_node(pdn->node, dn) { | ||
248 | pdn = PCI_DN(dn); | 250 | pdn = PCI_DN(dn); |
249 | if (pdn) | 251 | if (pdn) |
250 | n += gather_pci_data(pdn, buf+n, len-n); | 252 | n += gather_pci_data(pdn, buf+n, len-n); |
251 | dn = dn->sibling; | ||
252 | } | 253 | } |
253 | } | 254 | } |
254 | 255 | ||
@@ -372,7 +373,7 @@ struct device_node * find_device_pe(struct device_node *dn) | |||
372 | return dn; | 373 | return dn; |
373 | } | 374 | } |
374 | 375 | ||
375 | /** Mark all devices that are peers of this device as failed. | 376 | /** Mark all devices that are children of this device as failed. |
376 | * Mark the device driver too, so that it can see the failure | 377 | * Mark the device driver too, so that it can see the failure |
377 | * immediately; this is critical, since some drivers poll | 378 | * immediately; this is critical, since some drivers poll |
378 | * status registers in interrupts ... If a driver is polling, | 379 | * status registers in interrupts ... If a driver is polling, |
@@ -380,9 +381,11 @@ struct device_node * find_device_pe(struct device_node *dn) | |||
380 | * an interrupt context, which is bad. | 381 | * an interrupt context, which is bad. |
381 | */ | 382 | */ |
382 | 383 | ||
383 | static void __eeh_mark_slot (struct device_node *dn, int mode_flag) | 384 | static void __eeh_mark_slot(struct device_node *parent, int mode_flag) |
384 | { | 385 | { |
385 | while (dn) { | 386 | struct device_node *dn; |
387 | |||
388 | for_each_child_of_node(parent, dn) { | ||
386 | if (PCI_DN(dn)) { | 389 | if (PCI_DN(dn)) { |
387 | /* Mark the pci device driver too */ | 390 | /* Mark the pci device driver too */ |
388 | struct pci_dev *dev = PCI_DN(dn)->pcidev; | 391 | struct pci_dev *dev = PCI_DN(dn)->pcidev; |
@@ -392,10 +395,8 @@ static void __eeh_mark_slot (struct device_node *dn, int mode_flag) | |||
392 | if (dev && dev->driver) | 395 | if (dev && dev->driver) |
393 | dev->error_state = pci_channel_io_frozen; | 396 | dev->error_state = pci_channel_io_frozen; |
394 | 397 | ||
395 | if (dn->child) | 398 | __eeh_mark_slot(dn, mode_flag); |
396 | __eeh_mark_slot (dn->child, mode_flag); | ||
397 | } | 399 | } |
398 | dn = dn->sibling; | ||
399 | } | 400 | } |
400 | } | 401 | } |
401 | 402 | ||
@@ -415,19 +416,19 @@ void eeh_mark_slot (struct device_node *dn, int mode_flag) | |||
415 | if (dev) | 416 | if (dev) |
416 | dev->error_state = pci_channel_io_frozen; | 417 | dev->error_state = pci_channel_io_frozen; |
417 | 418 | ||
418 | __eeh_mark_slot (dn->child, mode_flag); | 419 | __eeh_mark_slot(dn, mode_flag); |
419 | } | 420 | } |
420 | 421 | ||
421 | static void __eeh_clear_slot (struct device_node *dn, int mode_flag) | 422 | static void __eeh_clear_slot(struct device_node *parent, int mode_flag) |
422 | { | 423 | { |
423 | while (dn) { | 424 | struct device_node *dn; |
425 | |||
426 | for_each_child_of_node(parent, dn) { | ||
424 | if (PCI_DN(dn)) { | 427 | if (PCI_DN(dn)) { |
425 | PCI_DN(dn)->eeh_mode &= ~mode_flag; | 428 | PCI_DN(dn)->eeh_mode &= ~mode_flag; |
426 | PCI_DN(dn)->eeh_check_count = 0; | 429 | PCI_DN(dn)->eeh_check_count = 0; |
427 | if (dn->child) | 430 | __eeh_clear_slot(dn, mode_flag); |
428 | __eeh_clear_slot (dn->child, mode_flag); | ||
429 | } | 431 | } |
430 | dn = dn->sibling; | ||
431 | } | 432 | } |
432 | } | 433 | } |
433 | 434 | ||
@@ -444,7 +445,7 @@ void eeh_clear_slot (struct device_node *dn, int mode_flag) | |||
444 | 445 | ||
445 | PCI_DN(dn)->eeh_mode &= ~mode_flag; | 446 | PCI_DN(dn)->eeh_mode &= ~mode_flag; |
446 | PCI_DN(dn)->eeh_check_count = 0; | 447 | PCI_DN(dn)->eeh_check_count = 0; |
447 | __eeh_clear_slot (dn->child, mode_flag); | 448 | __eeh_clear_slot(dn, mode_flag); |
448 | spin_unlock_irqrestore(&confirm_error_lock, flags); | 449 | spin_unlock_irqrestore(&confirm_error_lock, flags); |
449 | } | 450 | } |
450 | 451 | ||
@@ -480,6 +481,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
480 | no_dn++; | 481 | no_dn++; |
481 | return 0; | 482 | return 0; |
482 | } | 483 | } |
484 | dn = find_device_pe(dn); | ||
483 | pdn = PCI_DN(dn); | 485 | pdn = PCI_DN(dn); |
484 | 486 | ||
485 | /* Access to IO BARs might get this far and still not want checking. */ | 487 | /* Access to IO BARs might get this far and still not want checking. */ |
@@ -545,7 +547,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
545 | 547 | ||
546 | /* Note that config-io to empty slots may fail; | 548 | /* Note that config-io to empty slots may fail; |
547 | * they are empty when they don't have children. */ | 549 | * they are empty when they don't have children. */ |
548 | if ((rets[0] == 5) && (dn->child == NULL)) { | 550 | if ((rets[0] == 5) && (rets[2] == 0) && (dn->child == NULL)) { |
549 | false_positives++; | 551 | false_positives++; |
550 | pdn->eeh_false_positives ++; | 552 | pdn->eeh_false_positives ++; |
551 | rc = 0; | 553 | rc = 0; |
@@ -848,11 +850,8 @@ void eeh_restore_bars(struct pci_dn *pdn) | |||
848 | if ((pdn->eeh_mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(pdn->class_code)) | 850 | if ((pdn->eeh_mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(pdn->class_code)) |
849 | __restore_bars (pdn); | 851 | __restore_bars (pdn); |
850 | 852 | ||
851 | dn = pdn->node->child; | 853 | for_each_child_of_node(pdn->node, dn) |
852 | while (dn) { | ||
853 | eeh_restore_bars (PCI_DN(dn)); | 854 | eeh_restore_bars (PCI_DN(dn)); |
854 | dn = dn->sibling; | ||
855 | } | ||
856 | } | 855 | } |
857 | 856 | ||
858 | /** | 857 | /** |
@@ -1130,7 +1129,8 @@ static void eeh_add_device_early(struct device_node *dn) | |||
1130 | void eeh_add_device_tree_early(struct device_node *dn) | 1129 | void eeh_add_device_tree_early(struct device_node *dn) |
1131 | { | 1130 | { |
1132 | struct device_node *sib; | 1131 | struct device_node *sib; |
1133 | for (sib = dn->child; sib; sib = sib->sibling) | 1132 | |
1133 | for_each_child_of_node(dn, sib) | ||
1134 | eeh_add_device_tree_early(sib); | 1134 | eeh_add_device_tree_early(sib); |
1135 | eeh_add_device_early(dn); | 1135 | eeh_add_device_early(dn); |
1136 | } | 1136 | } |