Exemplo n.º 1
0
/**
 * aer_osc_setup - run ACPI _OSC method
 * @pciedev: pcie_device which AER is being enabled on
 *
 * @return: Zero on success. Nonzero otherwise.
 *
 * Invoked when PCIE bus loads AER service driver. To avoid conflict with
 * BIOS AER support requires BIOS to yield AER control to OS native driver.
 **/
int aer_osc_setup(struct pcie_device *pciedev)
{
    acpi_status status = AE_NOT_FOUND;
    struct pci_dev *pdev = pciedev->port;
    acpi_handle handle = NULL;

    if (acpi_pci_disabled)
        return -1;

    /* Find root host bridge */
    while (pdev->bus->self)
        pdev = pdev->bus->self;
    handle = acpi_get_pci_rootbridge_handle(
        pci_domain_nr(pdev->bus), pdev->bus->number);

    if (handle) {
        pcie_osc_support_set(OSC_EXT_PCI_CONFIG_SUPPORT);
        status = pci_osc_control_set(handle,
                    OSC_PCI_EXPRESS_AER_CONTROL |
                    OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
    }

    if (ACPI_FAILURE(status)) {
        printk(KERN_DEBUG "AER service couldn't init device %s - %s\n",
            pciedev->device.bus_id,
            (status == AE_SUPPORT || status == AE_NOT_FOUND) ?
            "no _OSC support" : "Run ACPI _OSC fails");
        return -1;
    }

    return 0;
}
int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
{
	acpi_status status;
	acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
	struct pci_dev *pdev = dev;
	u8 *path_name;
	/*
	 * Per PCI firmware specification, we should run the ACPI _OSC
	 * method to get control of hotplug hardware before using it.
	 * If an _OSC is missing, we look for an OSHP to do the same thing.
	 * To handle different BIOS behavior, we look for _OSC and OSHP
	 * within the scope of the hotplug controller and its parents, upto
	 * the host bridge under which this controller exists.
	 */
	while (!handle) {
		/*
		 * This hotplug controller was not listed in the ACPI name
		 * space at all. Try to get acpi handle of parent pci bus.
		 */
		if (!pdev || !pdev->bus->parent)
			break;
		dbg("Could not find %s in acpi namespace, trying parent\n",
				pci_name(pdev));
		if (!pdev->bus->parent->self)
			/* Parent must be a host bridge */
			handle = acpi_get_pci_rootbridge_handle(
					pci_domain_nr(pdev->bus->parent),
					pdev->bus->parent->number);
		else
			handle = DEVICE_ACPI_HANDLE(
					&(pdev->bus->parent->self->dev));
		pdev = pdev->bus->parent->self;
	}

	while (handle) {
		path_name = acpi_path_name(handle);
		dbg("Trying to get hotplug control for %s \n", path_name);
		status = pci_osc_control_set(handle,
				OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
		if (status == AE_NOT_FOUND)
			status = acpi_run_oshp(handle);
		if (ACPI_SUCCESS(status)) {
			dbg("Gained control for hotplug HW for pci %s (%s)\n",
				pci_name(dev), path_name);
			return 0;
		}
		if (is_root_bridge(handle))
			break;
		chandle = handle;
		status = acpi_get_parent(chandle, &handle);
		if (ACPI_FAILURE(status))
			break;
	}

	err("Cannot get control of hotplug hardware for pci %s\n",
			pci_name(dev));
	return -1;
}