static void eeh_report_error(struct pci_dev *dev, void *userdata) { enum pci_ers_result rc, *res = userdata; struct pci_driver *driver = dev->driver; dev->error_state = pci_channel_io_frozen; if (!driver) return; if (irq_in_use (dev->irq)) { struct device_node *dn = pci_device_to_OF_node(dev); PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED; disable_irq_nosync(dev->irq); } if (!driver->err_handler || !driver->err_handler->error_detected) return; rc = driver->err_handler->error_detected (dev, pci_channel_io_frozen); /* A driver that needs a reset trumps all others */ if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; if (*res == PCI_ERS_RESULT_NONE) *res = rc; }
/** * eeh_disable_irq - disable interrupt for the recovering device */ static void eeh_disable_irq(struct pci_dev *dev) { struct device_node *dn = pci_device_to_OF_node(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) return; if (!irq_in_use(dev->irq)) return; PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED; disable_irq_nosync(dev->irq); }
static void eeh_report_failure(struct pci_dev *dev, void *userdata) { struct pci_driver *driver = dev->driver; dev->error_state = pci_channel_io_perm_failure; if (!driver) return; if (irq_in_use (dev->irq)) { struct device_node *dn = pci_device_to_OF_node(dev); PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED; disable_irq_nosync(dev->irq); } if (!driver->err_handler) return; if (!driver->err_handler->error_detected) return; driver->err_handler->error_detected(dev, pci_channel_io_perm_failure); }