Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aaa20fc2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull PCI / ACPI fix from Rafael Wysocki:
 "This fixes a bug uncovered by a recent driver core change that
  modified the implementation of the ACPI_COMPANION_SET() macro to
  strictly rely on its second argument to be either NULL or a valid
  pointer to struct acpi_device.

  As it turns out, pcibios_root_bridge_prepare() on x86 and ia64 works
  with the assumption that the only code path calling pci_create_root_bus()
  is pci_acpi_scan_root() and therefore the sysdata argument passed to
  it will always match the expectations of pcibios_root_bridge_prepare().

  That need not be the case, however, and in particular it is not the
  case for the Xen pcifront driver that passes a pointer to its own
  private data strcture as sysdata to pci_scan_bus_parented() which then
  passes it to pci_create_root_bus() and it ends up being used incorrectly
  by pcibios_root_bridge_prepare()"

* tag 'acpi-pci-4.1-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  PCI / ACPI: Do not set ACPI companions for host bridges with parents
parents 1be44e23 dc4fdaf0
Loading
Loading
Loading
Loading
+10 −3
Original line number Diff line number Diff line
@@ -478,9 +478,16 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)

int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
{
	/*
	 * We pass NULL as parent to pci_create_root_bus(), so if it is not NULL
	 * here, pci_create_root_bus() has been called by someone else and
	 * sysdata is likely to be different from what we expect.  Let it go in
	 * that case.
	 */
	if (!bridge->dev.parent) {
		struct pci_controller *controller = bridge->bus->sysdata;

		ACPI_COMPANION_SET(&bridge->dev, controller->companion);
	}
	return 0;
}

+10 −3
Original line number Diff line number Diff line
@@ -482,9 +482,16 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)

int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
{
	/*
	 * We pass NULL as parent to pci_create_root_bus(), so if it is not NULL
	 * here, pci_create_root_bus() has been called by someone else and
	 * sysdata is likely to be different from what we expect.  Let it go in
	 * that case.
	 */
	if (!bridge->dev.parent) {
		struct pci_sysdata *sd = bridge->bus->sysdata;

		ACPI_COMPANION_SET(&bridge->dev, sd->companion);
	}
	return 0;
}