예제 #1
0
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;
}
예제 #2
0
파일: aerdrv_core.c 프로젝트: cilynx/dd-wrt
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;
}
예제 #3
0
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;
}