To ease future refactoring, extract calls to eeh_enable_irq() and eeh_disable_irq() from the various report functions. This makes the report functions initial sequences more similar, as well as making the IRQ changes visible when reading eeh_handle_normal_event().
Signed-off-by: Sam Bobroff <sbobr...@linux.ibm.com> --- ====== v1 -> v2: ====== * Reorganised eeh_set_irq_state() to reduce nesting depth. arch/powerpc/kernel/eeh_driver.c | 52 ++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c index 76951ca701b2..8dd2a33424a1 100644 --- a/arch/powerpc/kernel/eeh_driver.c +++ b/arch/powerpc/kernel/eeh_driver.c @@ -118,22 +118,20 @@ static inline void eeh_pcid_put(struct pci_dev *pdev) * do real work because EEH should freeze DMA transfers for those PCI * devices encountering EEH errors, which includes MSI or MSI-X. */ -static void eeh_disable_irq(struct pci_dev *dev) +static void eeh_disable_irq(struct eeh_dev *edev) { - struct eeh_dev *edev = pci_dev_to_eeh_dev(dev); - /* Don't disable MSI and MSI-X interrupts. They are * effectively disabled by the DMA Stopped state * when an EEH error occurs. */ - if (dev->msi_enabled || dev->msix_enabled) + if (edev->pdev->msi_enabled || edev->pdev->msix_enabled) return; - if (!irq_has_action(dev->irq)) + if (!irq_has_action(edev->pdev->irq)) return; edev->mode |= EEH_DEV_IRQ_DISABLED; - disable_irq_nosync(dev->irq); + disable_irq_nosync(edev->pdev->irq); } /** @@ -143,10 +141,8 @@ static void eeh_disable_irq(struct pci_dev *dev) * This routine must be called to enable interrupt while failed * device could be resumed. */ -static void eeh_enable_irq(struct pci_dev *dev) +static void eeh_enable_irq(struct eeh_dev *edev) { - struct eeh_dev *edev = pci_dev_to_eeh_dev(dev); - if ((edev->mode) & EEH_DEV_IRQ_DISABLED) { edev->mode &= ~EEH_DEV_IRQ_DISABLED; /* @@ -169,8 +165,8 @@ static void eeh_enable_irq(struct pci_dev *dev) * * tglx */ - if (irqd_irq_disabled(irq_get_irq_data(dev->irq))) - enable_irq(dev->irq); + if (irqd_irq_disabled(irq_get_irq_data(edev->pdev->irq))) + enable_irq(edev->pdev->irq); } } @@ -210,6 +206,29 @@ static void eeh_set_channel_state(struct eeh_pe *root, enum pci_channel_state s) edev->pdev->error_state = s; } +static void eeh_set_irq_state(struct eeh_pe *root, bool enable) +{ + struct eeh_pe *pe; + struct eeh_dev *edev, *tmp; + + eeh_for_each_pe(root, pe) { + eeh_pe_for_each_dev(pe, edev, tmp) { + if (!eeh_edev_actionable(edev)) + continue; + + if (!eeh_pcid_get(edev->pdev)) + continue; + + if (enable) + eeh_enable_irq(edev); + else + eeh_disable_irq(edev); + + eeh_pcid_put(edev->pdev); + } + } +} + /** * eeh_report_error - Report pci error to each device driver * @data: eeh device @@ -233,8 +252,6 @@ static void *eeh_report_error(struct eeh_dev *edev, void *userdata) driver = eeh_pcid_get(dev); if (!driver) goto out_no_dev; - eeh_disable_irq(dev); - if (!driver->err_handler || !driver->err_handler->error_detected) goto out; @@ -315,8 +332,6 @@ static void *eeh_report_reset(struct eeh_dev *edev, void *userdata) driver = eeh_pcid_get(dev); if (!driver) goto out_no_dev; - eeh_enable_irq(dev); - if (!driver->err_handler || !driver->err_handler->slot_reset || (edev->mode & EEH_DEV_NO_HANDLER) || @@ -386,7 +401,6 @@ static void *eeh_report_resume(struct eeh_dev *edev, void *userdata) was_in_error = edev->in_error; edev->in_error = false; - eeh_enable_irq(dev); if (!driver->err_handler || !driver->err_handler->resume || @@ -431,8 +445,6 @@ static void *eeh_report_failure(struct eeh_dev *edev, void *userdata) driver = eeh_pcid_get(dev); if (!driver) goto out_no_dev; - eeh_disable_irq(dev); - if (!driver->err_handler || !driver->err_handler->error_detected) goto out; @@ -804,6 +816,7 @@ void eeh_handle_normal_event(struct eeh_pe *pe) */ pr_info("EEH: Notify device drivers to shutdown\n"); eeh_set_channel_state(pe, pci_channel_io_frozen); + eeh_set_irq_state(pe, false); eeh_pe_dev_traverse(pe, eeh_report_error, &result); if ((pe->type & EEH_PE_PHB) && result != PCI_ERS_RESULT_NONE && @@ -895,6 +908,7 @@ void eeh_handle_normal_event(struct eeh_pe *pe) "the completion of reset\n"); result = PCI_ERS_RESULT_NONE; eeh_set_channel_state(pe, pci_channel_io_normal); + eeh_set_irq_state(pe, true); eeh_pe_dev_traverse(pe, eeh_report_reset, &result); } @@ -917,6 +931,7 @@ void eeh_handle_normal_event(struct eeh_pe *pe) /* Tell all device drivers that they can resume operations */ pr_info("EEH: Notify device driver to resume\n"); eeh_set_channel_state(pe, pci_channel_io_normal); + eeh_set_irq_state(pe, true); eeh_pe_dev_traverse(pe, eeh_report_resume, NULL); pr_info("EEH: Recovery successful.\n"); @@ -936,6 +951,7 @@ void eeh_handle_normal_event(struct eeh_pe *pe) /* Notify all devices that they're about to go down. */ eeh_set_channel_state(pe, pci_channel_io_perm_failure); + eeh_set_irq_state(pe, false); eeh_pe_dev_traverse(pe, eeh_report_failure, NULL); /* Mark the PE to be removed permanently */ -- 2.16.1.74.g9b0b1f47b