Commit b1801bf0 authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branch 'pci/aspm'

  - Fix ASPM link_state teardown on removal (Lukas Wunner)

  - Fix misleading _OSC ASPM message (Sinan Kaya)

  - Make _OSC optional for PCI (Sinan Kaya)

  - Don't initialize ASPM link state when ACPI_FADT_NO_ASPM is set (Patrick
    Talbert)

* pci/aspm:
  PCI/ASPM: Do not initialize link state when aspm_disabled is set
  PCI/ACPI: Allow _OSC presence to be optional for PCI
  PCI/ACPI: Correct error message for ASPM disabling
  PCI/ASPM: Fix link_state teardown on device removal
parents 7876320f 17c91487
Loading
Loading
Loading
Loading
+13 −4
Original line number Original line Diff line number Diff line
@@ -421,7 +421,8 @@ out:
}
}
EXPORT_SYMBOL(acpi_pci_osc_control_set);
EXPORT_SYMBOL(acpi_pci_osc_control_set);


static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm)
static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm,
				 bool is_pcie)
{
{
	u32 support, control, requested;
	u32 support, control, requested;
	acpi_status status;
	acpi_status status;
@@ -455,9 +456,15 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm)
	decode_osc_support(root, "OS supports", support);
	decode_osc_support(root, "OS supports", support);
	status = acpi_pci_osc_support(root, support);
	status = acpi_pci_osc_support(root, support);
	if (ACPI_FAILURE(status)) {
	if (ACPI_FAILURE(status)) {
		dev_info(&device->dev, "_OSC failed (%s); disabling ASPM\n",
			 acpi_format_exception(status));
		*no_aspm = 1;
		*no_aspm = 1;

		/* _OSC is optional for PCI host bridges */
		if ((status == AE_NOT_FOUND) && !is_pcie)
			return;

		dev_info(&device->dev, "_OSC failed (%s)%s\n",
			 acpi_format_exception(status),
			 pcie_aspm_support_enabled() ? "; disabling ASPM" : "");
		return;
		return;
	}
	}


@@ -533,6 +540,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
	acpi_handle handle = device->handle;
	acpi_handle handle = device->handle;
	int no_aspm = 0;
	int no_aspm = 0;
	bool hotadd = system_state == SYSTEM_RUNNING;
	bool hotadd = system_state == SYSTEM_RUNNING;
	bool is_pcie;


	root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
	root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
	if (!root)
	if (!root)
@@ -590,7 +598,8 @@ static int acpi_pci_root_add(struct acpi_device *device,


	root->mcfg_addr = acpi_pci_root_get_mcfg_addr(handle);
	root->mcfg_addr = acpi_pci_root_get_mcfg_addr(handle);


	negotiate_os_control(root, &no_aspm);
	is_pcie = strcmp(acpi_device_hid(device), "PNP0A08") == 0;
	negotiate_os_control(root, &no_aspm, is_pcie);


	/*
	/*
	 * TBD: Need PCI interface for enumeration/configuration of roots.
	 * TBD: Need PCI interface for enumeration/configuration of roots.
+2 −2
Original line number Original line Diff line number Diff line
@@ -895,7 +895,7 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
	struct pcie_link_state *link;
	struct pcie_link_state *link;
	int blacklist = !!pcie_aspm_sanity_check(pdev);
	int blacklist = !!pcie_aspm_sanity_check(pdev);


	if (!aspm_support_enabled)
	if (!aspm_support_enabled || aspm_disabled)
		return;
		return;


	if (pdev->link_state)
	if (pdev->link_state)
@@ -991,7 +991,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev)
	 * All PCIe functions are in one slot, remove one function will remove
	 * All PCIe functions are in one slot, remove one function will remove
	 * the whole slot, so just wait until we are the last function left.
	 * the whole slot, so just wait until we are the last function left.
	 */
	 */
	if (!list_is_last(&pdev->bus_list, &parent->subordinate->devices))
	if (!list_empty(&parent->subordinate->devices))
		goto out;
		goto out;


	link = parent->link_state;
	link = parent->link_state;
+1 −3
Original line number Original line Diff line number Diff line
@@ -25,9 +25,6 @@ static void pci_stop_dev(struct pci_dev *dev)


		pci_dev_assign_added(dev, false);
		pci_dev_assign_added(dev, false);
	}
	}

	if (dev->bus->self)
		pcie_aspm_exit_link_state(dev);
}
}


static void pci_destroy_dev(struct pci_dev *dev)
static void pci_destroy_dev(struct pci_dev *dev)
@@ -41,6 +38,7 @@ static void pci_destroy_dev(struct pci_dev *dev)
	list_del(&dev->bus_list);
	list_del(&dev->bus_list);
	up_write(&pci_bus_sem);
	up_write(&pci_bus_sem);


	pcie_aspm_exit_link_state(dev);
	pci_bridge_d3_update(dev);
	pci_bridge_d3_update(dev);
	pci_free_resources(dev);
	pci_free_resources(dev);
	put_device(&dev->dev);
	put_device(&dev->dev);