diff options
Diffstat (limited to 'drivers/pci/hotplug/acpiphp_glue.c')
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 48 |
1 files changed, 23 insertions, 25 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 22d0f1cf1362..dbfdac63cb49 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -128,8 +128,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
128 | acpi_handle tmp; | 128 | acpi_handle tmp; |
129 | acpi_status status = AE_OK; | 129 | acpi_status status = AE_OK; |
130 | unsigned long adr, sun; | 130 | unsigned long adr, sun; |
131 | int device, function; | 131 | int device, function, retval; |
132 | static int num_slots = 0; /* XXX if we support I/O node hotplug... */ | ||
133 | 132 | ||
134 | status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); | 133 | status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); |
135 | 134 | ||
@@ -198,7 +197,6 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
198 | 197 | ||
199 | memset(slot, 0, sizeof(struct acpiphp_slot)); | 198 | memset(slot, 0, sizeof(struct acpiphp_slot)); |
200 | slot->bridge = bridge; | 199 | slot->bridge = bridge; |
201 | slot->id = num_slots++; | ||
202 | slot->device = device; | 200 | slot->device = device; |
203 | slot->sun = sun; | 201 | slot->sun = sun; |
204 | INIT_LIST_HEAD(&slot->funcs); | 202 | INIT_LIST_HEAD(&slot->funcs); |
@@ -212,6 +210,11 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
212 | dbg("found ACPI PCI Hotplug slot %d at PCI %04x:%02x:%02x\n", | 210 | dbg("found ACPI PCI Hotplug slot %d at PCI %04x:%02x:%02x\n", |
213 | slot->sun, pci_domain_nr(bridge->pci_bus), | 211 | slot->sun, pci_domain_nr(bridge->pci_bus), |
214 | bridge->pci_bus->number, slot->device); | 212 | bridge->pci_bus->number, slot->device); |
213 | retval = acpiphp_register_hotplug_slot(slot); | ||
214 | if (retval) { | ||
215 | warn("acpiphp_register_hotplug_slot failed(err code = 0x%x)\n", retval); | ||
216 | goto err_exit; | ||
217 | } | ||
215 | } | 218 | } |
216 | 219 | ||
217 | newfunc->slot = slot; | 220 | newfunc->slot = slot; |
@@ -253,6 +256,14 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
253 | status = AE_OK; | 256 | status = AE_OK; |
254 | 257 | ||
255 | return status; | 258 | return status; |
259 | |||
260 | err_exit: | ||
261 | bridge->nr_slots--; | ||
262 | bridge->slots = slot->next; | ||
263 | kfree(slot); | ||
264 | kfree(newfunc); | ||
265 | |||
266 | return AE_OK; | ||
256 | } | 267 | } |
257 | 268 | ||
258 | 269 | ||
@@ -335,9 +346,16 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge) | |||
335 | /* decode ACPI 2.0 _HPP (hot plug parameters) */ | 346 | /* decode ACPI 2.0 _HPP (hot plug parameters) */ |
336 | decode_hpp(bridge); | 347 | decode_hpp(bridge); |
337 | 348 | ||
349 | /* must be added to the list prior to calling register_slot */ | ||
350 | list_add(&bridge->list, &bridge_list); | ||
351 | |||
338 | /* register all slot objects under this bridge */ | 352 | /* register all slot objects under this bridge */ |
339 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1, | 353 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1, |
340 | register_slot, bridge, NULL); | 354 | register_slot, bridge, NULL); |
355 | if (ACPI_FAILURE(status)) { | ||
356 | list_del(&bridge->list); | ||
357 | return; | ||
358 | } | ||
341 | 359 | ||
342 | /* install notify handler */ | 360 | /* install notify handler */ |
343 | if (bridge->type != BRIDGE_TYPE_HOST) { | 361 | if (bridge->type != BRIDGE_TYPE_HOST) { |
@@ -350,8 +368,6 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge) | |||
350 | err("failed to register interrupt notify handler\n"); | 368 | err("failed to register interrupt notify handler\n"); |
351 | } | 369 | } |
352 | } | 370 | } |
353 | |||
354 | list_add(&bridge->list, &bridge_list); | ||
355 | } | 371 | } |
356 | 372 | ||
357 | 373 | ||
@@ -555,6 +571,8 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) | |||
555 | list_del(list); | 571 | list_del(list); |
556 | kfree(func); | 572 | kfree(func); |
557 | } | 573 | } |
574 | acpiphp_unregister_hotplug_slot(slot); | ||
575 | list_del(&slot->funcs); | ||
558 | kfree(slot); | 576 | kfree(slot); |
559 | slot = next; | 577 | slot = next; |
560 | } | 578 | } |
@@ -1521,26 +1539,6 @@ static int acpiphp_for_each_slot(acpiphp_callback fn, void *data) | |||
1521 | } | 1539 | } |
1522 | #endif | 1540 | #endif |
1523 | 1541 | ||
1524 | /* search matching slot from id */ | ||
1525 | struct acpiphp_slot *get_slot_from_id(int id) | ||
1526 | { | ||
1527 | struct list_head *node; | ||
1528 | struct acpiphp_bridge *bridge; | ||
1529 | struct acpiphp_slot *slot; | ||
1530 | |||
1531 | list_for_each (node, &bridge_list) { | ||
1532 | bridge = (struct acpiphp_bridge *)node; | ||
1533 | for (slot = bridge->slots; slot; slot = slot->next) | ||
1534 | if (slot->id == id) | ||
1535 | return slot; | ||
1536 | } | ||
1537 | |||
1538 | /* should never happen! */ | ||
1539 | err("%s: no object for id %d\n", __FUNCTION__, id); | ||
1540 | WARN_ON(1); | ||
1541 | return NULL; | ||
1542 | } | ||
1543 | |||
1544 | 1542 | ||
1545 | /** | 1543 | /** |
1546 | * acpiphp_enable_slot - power on slot | 1544 | * acpiphp_enable_slot - power on slot |