diff options
Diffstat (limited to 'arch/powerpc/kernel/eeh_pe.c')
| -rw-r--r-- | arch/powerpc/kernel/eeh_pe.c | 47 |
1 files changed, 40 insertions, 7 deletions
diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c index f0c353fa655a..995c2a284630 100644 --- a/arch/powerpc/kernel/eeh_pe.c +++ b/arch/powerpc/kernel/eeh_pe.c | |||
| @@ -503,13 +503,17 @@ static void *__eeh_pe_state_mark(void *data, void *flag) | |||
| 503 | struct eeh_dev *edev, *tmp; | 503 | struct eeh_dev *edev, *tmp; |
| 504 | struct pci_dev *pdev; | 504 | struct pci_dev *pdev; |
| 505 | 505 | ||
| 506 | /* | 506 | /* Keep the state of permanently removed PE intact */ |
| 507 | * Mark the PE with the indicated state. Also, | 507 | if ((pe->freeze_count > EEH_MAX_ALLOWED_FREEZES) && |
| 508 | * the associated PCI device will be put into | 508 | (state & (EEH_PE_ISOLATED | EEH_PE_RECOVERING))) |
| 509 | * I/O frozen state to avoid I/O accesses from | 509 | return NULL; |
| 510 | * the PCI device driver. | 510 | |
| 511 | */ | ||
| 512 | pe->state |= state; | 511 | pe->state |= state; |
| 512 | |||
| 513 | /* Offline PCI devices if applicable */ | ||
| 514 | if (state != EEH_PE_ISOLATED) | ||
| 515 | return NULL; | ||
| 516 | |||
| 513 | eeh_pe_for_each_dev(pe, edev, tmp) { | 517 | eeh_pe_for_each_dev(pe, edev, tmp) { |
| 514 | pdev = eeh_dev_to_pci_dev(edev); | 518 | pdev = eeh_dev_to_pci_dev(edev); |
| 515 | if (pdev) | 519 | if (pdev) |
| @@ -532,6 +536,27 @@ void eeh_pe_state_mark(struct eeh_pe *pe, int state) | |||
| 532 | eeh_pe_traverse(pe, __eeh_pe_state_mark, &state); | 536 | eeh_pe_traverse(pe, __eeh_pe_state_mark, &state); |
| 533 | } | 537 | } |
| 534 | 538 | ||
| 539 | static void *__eeh_pe_dev_mode_mark(void *data, void *flag) | ||
| 540 | { | ||
| 541 | struct eeh_dev *edev = data; | ||
| 542 | int mode = *((int *)flag); | ||
| 543 | |||
| 544 | edev->mode |= mode; | ||
| 545 | |||
| 546 | return NULL; | ||
| 547 | } | ||
| 548 | |||
| 549 | /** | ||
| 550 | * eeh_pe_dev_state_mark - Mark state for all device under the PE | ||
| 551 | * @pe: EEH PE | ||
| 552 | * | ||
| 553 | * Mark specific state for all child devices of the PE. | ||
| 554 | */ | ||
| 555 | void eeh_pe_dev_mode_mark(struct eeh_pe *pe, int mode) | ||
| 556 | { | ||
| 557 | eeh_pe_dev_traverse(pe, __eeh_pe_dev_mode_mark, &mode); | ||
| 558 | } | ||
| 559 | |||
| 535 | /** | 560 | /** |
| 536 | * __eeh_pe_state_clear - Clear state for the PE | 561 | * __eeh_pe_state_clear - Clear state for the PE |
| 537 | * @data: EEH PE | 562 | * @data: EEH PE |
| @@ -546,8 +571,16 @@ static void *__eeh_pe_state_clear(void *data, void *flag) | |||
| 546 | struct eeh_pe *pe = (struct eeh_pe *)data; | 571 | struct eeh_pe *pe = (struct eeh_pe *)data; |
| 547 | int state = *((int *)flag); | 572 | int state = *((int *)flag); |
| 548 | 573 | ||
| 574 | /* Keep the state of permanently removed PE intact */ | ||
| 575 | if ((pe->freeze_count > EEH_MAX_ALLOWED_FREEZES) && | ||
| 576 | (state & EEH_PE_ISOLATED)) | ||
| 577 | return NULL; | ||
| 578 | |||
| 549 | pe->state &= ~state; | 579 | pe->state &= ~state; |
| 550 | pe->check_count = 0; | 580 | |
| 581 | /* Clear check count since last isolation */ | ||
| 582 | if (state & EEH_PE_ISOLATED) | ||
| 583 | pe->check_count = 0; | ||
| 551 | 584 | ||
| 552 | return NULL; | 585 | return NULL; |
| 553 | } | 586 | } |
