diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-05-29 20:09:39 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-05-29 20:09:39 -0400 |
commit | aaa20fc23341be3df7b17810e330f12244abcf29 (patch) | |
tree | 2c637d9ef87a6595beacc8ff556705db7bf071b7 | |
parent | 1be44e234b672eadbf1d96eb172ef21f5ff6a2c9 (diff) | |
parent | dc4fdaf0e4839109169d8261814813816951c75f (diff) |
Merge tag 'acpi-pci-4.1-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
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
-rw-r--r-- | arch/ia64/pci/pci.c | 13 | ||||
-rw-r--r-- | arch/x86/pci/acpi.c | 13 |
2 files changed, 20 insertions, 6 deletions
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index d4e162d35b34..7cc3be9fa7c6 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c | |||
@@ -478,9 +478,16 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) | |||
478 | 478 | ||
479 | int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) | 479 | int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) |
480 | { | 480 | { |
481 | struct pci_controller *controller = bridge->bus->sysdata; | 481 | /* |
482 | 482 | * We pass NULL as parent to pci_create_root_bus(), so if it is not NULL | |
483 | ACPI_COMPANION_SET(&bridge->dev, controller->companion); | 483 | * here, pci_create_root_bus() has been called by someone else and |
484 | * sysdata is likely to be different from what we expect. Let it go in | ||
485 | * that case. | ||
486 | */ | ||
487 | if (!bridge->dev.parent) { | ||
488 | struct pci_controller *controller = bridge->bus->sysdata; | ||
489 | ACPI_COMPANION_SET(&bridge->dev, controller->companion); | ||
490 | } | ||
484 | return 0; | 491 | return 0; |
485 | } | 492 | } |
486 | 493 | ||
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index d93963340c3c..14a63ed6fe09 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c | |||
@@ -482,9 +482,16 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) | |||
482 | 482 | ||
483 | int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) | 483 | int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) |
484 | { | 484 | { |
485 | struct pci_sysdata *sd = bridge->bus->sysdata; | 485 | /* |
486 | 486 | * We pass NULL as parent to pci_create_root_bus(), so if it is not NULL | |
487 | ACPI_COMPANION_SET(&bridge->dev, sd->companion); | 487 | * here, pci_create_root_bus() has been called by someone else and |
488 | * sysdata is likely to be different from what we expect. Let it go in | ||
489 | * that case. | ||
490 | */ | ||
491 | if (!bridge->dev.parent) { | ||
492 | struct pci_sysdata *sd = bridge->bus->sysdata; | ||
493 | ACPI_COMPANION_SET(&bridge->dev, sd->companion); | ||
494 | } | ||
488 | return 0; | 495 | return 0; |
489 | } | 496 | } |
490 | 497 | ||