static pci_ers_result_t reset_link(struct pcie_device *aerdev, struct pci_dev *dev) { struct pci_dev *udev; pci_ers_result_t status; struct pcie_port_service_driver *driver; if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) { /* Reset this port for all subordinates */ udev = dev; } else { /* Reset the upstream component (likely downstream port) */ udev = dev->bus->self; } /* Use the aer driver of the component firstly */ driver = find_aer_service(udev); if (driver && driver->reset_link) { status = driver->reset_link(udev); } else if (udev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) { status = default_downstream_reset_link(udev); } else { #ifdef CONFIG_DEBUG_PRINTK dev_printk(KERN_DEBUG, &dev->dev, "no link-reset support at upstream device %s\n", pci_name(udev)); #else dev_; #endif return PCI_ERS_RESULT_DISCONNECT; } if (status != PCI_ERS_RESULT_RECOVERED) { #ifdef CONFIG_DEBUG_PRINTK dev_printk(KERN_DEBUG, &dev->dev, "link reset at upstream device %s failed\n", pci_name(udev)); #else dev_; #endif return PCI_ERS_RESULT_DISCONNECT; } return status; }
static pci_ers_result_t reset_link(struct pcie_device *aerdev, struct pci_dev *dev) { struct pci_dev *udev; pci_ers_result_t status; struct find_aer_service_data data; if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) udev = dev; else udev= dev->bus->self; data.is_downstream = 0; data.aer_driver = NULL; find_aer_service(udev, &data); /* * Use the aer driver of the error agent firstly. * If it hasn't the aer driver, use the root port's */ if (!data.aer_driver || !data.aer_driver->reset_link) { if (data.is_downstream && aerdev->device.driver && to_service_driver(aerdev->device.driver)->reset_link) { data.aer_driver = to_service_driver(aerdev->device.driver); } else { printk(KERN_DEBUG "No link-reset support to Device ID" "[%s]\n", dev->dev.bus_id); return PCI_ERS_RESULT_DISCONNECT; } } status = data.aer_driver->reset_link(udev); if (status != PCI_ERS_RESULT_RECOVERED) { printk(KERN_DEBUG "Link reset at upstream Device ID" "[%s] failed\n", udev->dev.bus_id); return PCI_ERS_RESULT_DISCONNECT; } return status; }
static pci_ers_result_t reset_link(struct pcie_device *aerdev, struct pci_dev *dev) { struct pci_dev *udev; pci_ers_result_t status; struct find_aer_service_data data; if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) udev = dev; else udev = dev->bus->self; data.is_downstream = 0; data.aer_driver = NULL; find_aer_service(udev, &data); if (!data.aer_driver || !data.aer_driver->reset_link) { if (data.is_downstream && aerdev->device.driver && to_service_driver(aerdev->device.driver)->reset_link) { data.aer_driver = to_service_driver(aerdev->device.driver); } else { dev_printk(KERN_DEBUG, &dev->dev, "no link-reset " "support\n"); return PCI_ERS_RESULT_DISCONNECT; } } status = data.aer_driver->reset_link(udev); if (status != PCI_ERS_RESULT_RECOVERED) { dev_printk(KERN_DEBUG, &dev->dev, "link reset at upstream " "device %s failed\n", pci_name(udev)); return PCI_ERS_RESULT_DISCONNECT; } return status; }