Commit 6edd7679 authored by Alex Chiang's avatar Alex Chiang Committed by Jesse Barnes

PCI Hotplug: acpiphp: find bridges the easy way

Instead of constantly evaluating _ADR and _SEG over and over again,
let's simplify our lives by using:

	acpi_pci_find_root() for root bridges
	acpi_get_pci_dev() for p2p bridges

This change eliminates some copy 'n paste code and also allows us
to simplify some internal interfaces.
Reviewed-by: default avatarKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Tested-by: default avatarKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Cc: Bjorn Helgaas <bjorn.helgaas@hp.com>
Signed-off-by: default avatarAlex Chiang <achiang@hp.com>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent 9965976a
...@@ -277,14 +277,15 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) ...@@ -277,14 +277,15 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
/* see if it's worth looking at this bridge */ /* see if it's worth looking at this bridge */
static int detect_ejectable_slots(struct pci_bus *pbus) static int detect_ejectable_slots(acpi_handle handle)
{ {
int found = acpi_pci_detect_ejectable(pbus); int found;
struct pci_bus *pbus;
pbus = pci_bus_from_handle(handle);
found = acpi_pci_detect_ejectable(pbus);
if (!found) { if (!found) {
acpi_handle bridge_handle = acpi_pci_get_bridge_handle(pbus); acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
if (!bridge_handle)
return 0;
acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, (u32)1,
is_pci_dock_device, (void *)&found, NULL); is_pci_dock_device, (void *)&found, NULL);
} }
return found; return found;
...@@ -415,9 +416,10 @@ static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge) ...@@ -415,9 +416,10 @@ static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge)
/* allocate and initialize host bridge data structure */ /* allocate and initialize host bridge data structure */
static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus) static void add_host_bridge(acpi_handle *handle)
{ {
struct acpiphp_bridge *bridge; struct acpiphp_bridge *bridge;
struct acpi_pci_root *root = acpi_pci_find_root(handle);
bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
if (bridge == NULL) if (bridge == NULL)
...@@ -426,7 +428,7 @@ static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus) ...@@ -426,7 +428,7 @@ static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus)
bridge->type = BRIDGE_TYPE_HOST; bridge->type = BRIDGE_TYPE_HOST;
bridge->handle = handle; bridge->handle = handle;
bridge->pci_bus = pci_bus; bridge->pci_bus = root->bus;
spin_lock_init(&bridge->res_lock); spin_lock_init(&bridge->res_lock);
...@@ -435,7 +437,7 @@ static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus) ...@@ -435,7 +437,7 @@ static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus)
/* allocate and initialize PCI-to-PCI bridge data structure */ /* allocate and initialize PCI-to-PCI bridge data structure */
static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev) static void add_p2p_bridge(acpi_handle *handle)
{ {
struct acpiphp_bridge *bridge; struct acpiphp_bridge *bridge;
...@@ -449,8 +451,8 @@ static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev) ...@@ -449,8 +451,8 @@ static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev)
bridge->handle = handle; bridge->handle = handle;
config_p2p_bridge_flags(bridge); config_p2p_bridge_flags(bridge);
bridge->pci_dev = pci_dev_get(pci_dev); bridge->pci_dev = acpi_get_pci_dev(handle);
bridge->pci_bus = pci_dev->subordinate; bridge->pci_bus = bridge->pci_dev->subordinate;
if (!bridge->pci_bus) { if (!bridge->pci_bus) {
err("This is not a PCI-to-PCI bridge!\n"); err("This is not a PCI-to-PCI bridge!\n");
goto err; goto err;
...@@ -467,7 +469,7 @@ static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev) ...@@ -467,7 +469,7 @@ static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev)
init_bridge_misc(bridge); init_bridge_misc(bridge);
return; return;
err: err:
pci_dev_put(pci_dev); pci_dev_put(bridge->pci_dev);
kfree(bridge); kfree(bridge);
return; return;
} }
...@@ -478,39 +480,21 @@ static acpi_status ...@@ -478,39 +480,21 @@ static acpi_status
find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
{ {
acpi_status status; acpi_status status;
acpi_handle dummy_handle;
unsigned long long tmp;
int device, function;
struct pci_dev *dev; struct pci_dev *dev;
struct pci_bus *pci_bus = context;
status = acpi_get_handle(handle, "_ADR", &dummy_handle);
if (ACPI_FAILURE(status))
return AE_OK; /* continue */
status = acpi_evaluate_integer(handle, "_ADR", NULL, &tmp);
if (ACPI_FAILURE(status)) {
dbg("%s: _ADR evaluation failure\n", __func__);
return AE_OK;
}
device = (tmp >> 16) & 0xffff;
function = tmp & 0xffff;
dev = pci_get_slot(pci_bus, PCI_DEVFN(device, function));
dev = acpi_get_pci_dev(handle);
if (!dev || !dev->subordinate) if (!dev || !dev->subordinate)
goto out; goto out;
/* check if this bridge has ejectable slots */ /* check if this bridge has ejectable slots */
if ((detect_ejectable_slots(dev->subordinate) > 0)) { if ((detect_ejectable_slots(handle) > 0)) {
dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev)); dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev));
add_p2p_bridge(handle, dev); add_p2p_bridge(handle);
} }
/* search P2P bridges under this p2p bridge */ /* search P2P bridges under this p2p bridge */
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
find_p2p_bridge, dev->subordinate, NULL); find_p2p_bridge, NULL, NULL);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
warn("find_p2p_bridge failed (error code = 0x%x)\n", status); warn("find_p2p_bridge failed (error code = 0x%x)\n", status);
...@@ -525,9 +509,7 @@ static int add_bridge(acpi_handle handle) ...@@ -525,9 +509,7 @@ static int add_bridge(acpi_handle handle)
{ {
acpi_status status; acpi_status status;
unsigned long long tmp; unsigned long long tmp;
int seg, bus;
acpi_handle dummy_handle; acpi_handle dummy_handle;
struct pci_bus *pci_bus;
/* if the bridge doesn't have _STA, we assume it is always there */ /* if the bridge doesn't have _STA, we assume it is always there */
status = acpi_get_handle(handle, "_STA", &dummy_handle); status = acpi_get_handle(handle, "_STA", &dummy_handle);
...@@ -542,36 +524,15 @@ static int add_bridge(acpi_handle handle) ...@@ -542,36 +524,15 @@ static int add_bridge(acpi_handle handle)
return 0; return 0;
} }
/* get PCI segment number */
status = acpi_evaluate_integer(handle, "_SEG", NULL, &tmp);
seg = ACPI_SUCCESS(status) ? tmp : 0;
/* get PCI bus number */
status = acpi_evaluate_integer(handle, "_BBN", NULL, &tmp);
if (ACPI_SUCCESS(status)) {
bus = tmp;
} else {
warn("can't get bus number, assuming 0\n");
bus = 0;
}
pci_bus = pci_find_bus(seg, bus);
if (!pci_bus) {
err("Can't find bus %04x:%02x\n", seg, bus);
return 0;
}
/* check if this bridge has ejectable slots */ /* check if this bridge has ejectable slots */
if (detect_ejectable_slots(pci_bus) > 0) { if (detect_ejectable_slots(handle) > 0) {
dbg("found PCI host-bus bridge with hot-pluggable slots\n"); dbg("found PCI host-bus bridge with hot-pluggable slots\n");
add_host_bridge(handle, pci_bus); add_host_bridge(handle);
} }
/* search P2P bridges under this host bridge */ /* search P2P bridges under this host bridge */
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
find_p2p_bridge, pci_bus, NULL); find_p2p_bridge, NULL, NULL);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
warn("find_p2p_bridge failed (error code = 0x%x)\n", status); warn("find_p2p_bridge failed (error code = 0x%x)\n", status);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment