diff options
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r-- | arch/powerpc/kernel/eeh.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index 7051ea3101b9..c25064b7d667 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c | |||
@@ -358,10 +358,11 @@ out: | |||
358 | int eeh_dev_check_failure(struct eeh_dev *edev) | 358 | int eeh_dev_check_failure(struct eeh_dev *edev) |
359 | { | 359 | { |
360 | int ret; | 360 | int ret; |
361 | int active_flags = (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE); | ||
361 | unsigned long flags; | 362 | unsigned long flags; |
362 | struct device_node *dn; | 363 | struct device_node *dn; |
363 | struct pci_dev *dev; | 364 | struct pci_dev *dev; |
364 | struct eeh_pe *pe; | 365 | struct eeh_pe *pe, *parent_pe; |
365 | int rc = 0; | 366 | int rc = 0; |
366 | const char *location; | 367 | const char *location; |
367 | 368 | ||
@@ -439,14 +440,34 @@ int eeh_dev_check_failure(struct eeh_dev *edev) | |||
439 | */ | 440 | */ |
440 | if ((ret < 0) || | 441 | if ((ret < 0) || |
441 | (ret == EEH_STATE_NOT_SUPPORT) || | 442 | (ret == EEH_STATE_NOT_SUPPORT) || |
442 | (ret & (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) == | 443 | ((ret & active_flags) == active_flags)) { |
443 | (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) { | ||
444 | eeh_stats.false_positives++; | 444 | eeh_stats.false_positives++; |
445 | pe->false_positives++; | 445 | pe->false_positives++; |
446 | rc = 0; | 446 | rc = 0; |
447 | goto dn_unlock; | 447 | goto dn_unlock; |
448 | } | 448 | } |
449 | 449 | ||
450 | /* | ||
451 | * It should be corner case that the parent PE has been | ||
452 | * put into frozen state as well. We should take care | ||
453 | * that at first. | ||
454 | */ | ||
455 | parent_pe = pe->parent; | ||
456 | while (parent_pe) { | ||
457 | /* Hit the ceiling ? */ | ||
458 | if (parent_pe->type & EEH_PE_PHB) | ||
459 | break; | ||
460 | |||
461 | /* Frozen parent PE ? */ | ||
462 | ret = eeh_ops->get_state(parent_pe, NULL); | ||
463 | if (ret > 0 && | ||
464 | (ret & active_flags) != active_flags) | ||
465 | pe = parent_pe; | ||
466 | |||
467 | /* Next parent level */ | ||
468 | parent_pe = parent_pe->parent; | ||
469 | } | ||
470 | |||
450 | eeh_stats.slot_resets++; | 471 | eeh_stats.slot_resets++; |
451 | 472 | ||
452 | /* Avoid repeated reports of this failure, including problems | 473 | /* Avoid repeated reports of this failure, including problems |