diff options
author | Alex Chiang <achiang@hp.com> | 2009-07-23 19:03:05 -0400 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-09-09 16:29:23 -0400 |
commit | 5228a828ee044834d78abdf25306bf46b19dcc4d (patch) | |
tree | b64bab920f7b2b8704ac6df4eaa389e3aa99064e | |
parent | 76d56de57ae60c6be383e48e7068fd973d5fb08a (diff) |
PCI Hotplug: acpiphp: get pci_bus from acpi handle correctly
We cannot simply call acpi_get_pci_dev() on any random ACPI handle
and hope that it works, because a PCI root bridge may not have
an associated struct pci_dev.
This is allowed per the PCI specification, and is referred to as a
non-materialized bridge.
So, depending on the type of PCI bridge that the handle points to,
use the appropriate interface to return the struct pci_bus correctly.
Reviewed-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Signed-off-by: Alex Chiang <achiang@hp.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 28 |
1 files changed, 17 insertions, 11 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 0cb0f830a993..2e5f25969e11 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -62,6 +62,22 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus); | |||
62 | static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus); | 62 | static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus); |
63 | static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context); | 63 | static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context); |
64 | 64 | ||
65 | static struct pci_bus *pci_bus_from_handle(acpi_handle handle) | ||
66 | { | ||
67 | struct pci_bus *pbus; | ||
68 | struct acpi_pci_root *root; | ||
69 | |||
70 | root = acpi_pci_find_root(handle); | ||
71 | if (root) | ||
72 | pbus = root->bus; | ||
73 | else { | ||
74 | struct pci_dev *pdev = acpi_get_pci_dev(handle); | ||
75 | pbus = pdev->subordinate; | ||
76 | pci_dev_put(pdev); | ||
77 | } | ||
78 | return pbus; | ||
79 | } | ||
80 | |||
65 | /* callback routine to check for the existence of a pci dock device */ | 81 | /* callback routine to check for the existence of a pci dock device */ |
66 | static acpi_status | 82 | static acpi_status |
67 | is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv) | 83 | is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv) |
@@ -1387,16 +1403,7 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus) | |||
1387 | /* Program resources in newly inserted bridge */ | 1403 | /* Program resources in newly inserted bridge */ |
1388 | static int acpiphp_configure_bridge (acpi_handle handle) | 1404 | static int acpiphp_configure_bridge (acpi_handle handle) |
1389 | { | 1405 | { |
1390 | struct pci_dev *dev; | 1406 | struct pci_bus *bus = pci_bus_from_handle(handle); |
1391 | struct pci_bus *bus; | ||
1392 | |||
1393 | dev = acpi_get_pci_dev(handle); | ||
1394 | if (!dev) { | ||
1395 | err("cannot get PCI domain and bus number for bridge\n"); | ||
1396 | return -EINVAL; | ||
1397 | } | ||
1398 | |||
1399 | bus = dev->bus; | ||
1400 | 1407 | ||
1401 | pci_bus_size_bridges(bus); | 1408 | pci_bus_size_bridges(bus); |
1402 | pci_bus_assign_resources(bus); | 1409 | pci_bus_assign_resources(bus); |
@@ -1404,7 +1411,6 @@ static int acpiphp_configure_bridge (acpi_handle handle) | |||
1404 | acpiphp_set_hpp_values(handle, bus); | 1411 | acpiphp_set_hpp_values(handle, bus); |
1405 | pci_enable_bridges(bus); | 1412 | pci_enable_bridges(bus); |
1406 | acpiphp_configure_ioapics(handle); | 1413 | acpiphp_configure_ioapics(handle); |
1407 | pci_dev_put(dev); | ||
1408 | return 0; | 1414 | return 0; |
1409 | } | 1415 | } |
1410 | 1416 | ||