Esempio 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;
}
Esempio n. 3
0
static int pci_acpi_find_root_bridge(struct device *dev, acpi_handle *handle)
{
	int num;
	unsigned int seg, bus;

	/*
	 * The string should be the same as root bridge's name
	 * Please look at 'pci_scan_bus_parented'
	 */
	num = sscanf(dev->bus_id, "pci%04x:%02x", &seg, &bus);
	if (num != 2)
		return -ENODEV;
	*handle = acpi_get_pci_rootbridge_handle(seg, bus);
	if (!*handle)
		return -ENODEV;
	return 0;
}
Esempio n. 4
0
/* acpi_get_hp_params_from_firmware
 *
 * @bus - the pci_bus of the bus on which the device is newly added
 * @hpp - allocated by the caller
 */
acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus,
        struct hotplug_params *hpp)
{
    acpi_status status = AE_NOT_FOUND;
    acpi_handle handle, phandle;
    struct pci_bus *pbus = bus;
    struct pci_dev *pdev;

    do {
        pdev = pbus->self;
        if (!pdev) {
            handle = acpi_get_pci_rootbridge_handle(
                pci_domain_nr(pbus), pbus->number);
            break;
        }
        handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
        pbus = pbus->parent;
    } while (!handle);

    /*
     * _HPP settings apply to all child buses, until another _HPP is
     * encountered. If we don't find an _HPP for the input pci dev,
     * look for it in the parent device scope since that would apply to
     * this pci dev. If we don't find any _HPP, use hardcoded defaults
     */
    while (handle) {
        status = acpi_run_hpx(handle, hpp);
        if (ACPI_SUCCESS(status))
            break;
        status = acpi_run_hpp(handle, hpp);
        if (ACPI_SUCCESS(status))
            break;
        if (acpi_root_bridge(handle))
            break;
        status = acpi_get_parent(handle, &phandle);
        if (ACPI_FAILURE(status))
            break;
        handle = phandle;
    }
    return status;
}