diff options
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 81 |
1 files changed, 21 insertions, 60 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 2e5f25969e11..e72e0adc0681 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -277,14 +277,15 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
277 | 277 | ||
278 | 278 | ||
279 | /* see if it's worth looking at this bridge */ | 279 | /* see if it's worth looking at this bridge */ |
280 | static int detect_ejectable_slots(struct pci_bus *pbus) | 280 | static int detect_ejectable_slots(acpi_handle handle) |
281 | { | 281 | { |
282 | int found = acpi_pci_detect_ejectable(pbus); | 282 | int found; |
283 | struct pci_bus *pbus; | ||
284 | |||
285 | pbus = pci_bus_from_handle(handle); | ||
286 | found = acpi_pci_detect_ejectable(pbus); | ||
283 | if (!found) { | 287 | if (!found) { |
284 | acpi_handle bridge_handle = acpi_pci_get_bridge_handle(pbus); | 288 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, |
285 | if (!bridge_handle) | ||
286 | return 0; | ||
287 | acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, (u32)1, | ||
288 | is_pci_dock_device, (void *)&found, NULL); | 289 | is_pci_dock_device, (void *)&found, NULL); |
289 | } | 290 | } |
290 | return found; | 291 | return found; |
@@ -415,9 +416,10 @@ static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge) | |||
415 | 416 | ||
416 | 417 | ||
417 | /* allocate and initialize host bridge data structure */ | 418 | /* allocate and initialize host bridge data structure */ |
418 | static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus) | 419 | static void add_host_bridge(acpi_handle *handle) |
419 | { | 420 | { |
420 | struct acpiphp_bridge *bridge; | 421 | struct acpiphp_bridge *bridge; |
422 | struct acpi_pci_root *root = acpi_pci_find_root(handle); | ||
421 | 423 | ||
422 | bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); | 424 | bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); |
423 | if (bridge == NULL) | 425 | if (bridge == NULL) |
@@ -426,7 +428,7 @@ static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus) | |||
426 | bridge->type = BRIDGE_TYPE_HOST; | 428 | bridge->type = BRIDGE_TYPE_HOST; |
427 | bridge->handle = handle; | 429 | bridge->handle = handle; |
428 | 430 | ||
429 | bridge->pci_bus = pci_bus; | 431 | bridge->pci_bus = root->bus; |
430 | 432 | ||
431 | spin_lock_init(&bridge->res_lock); | 433 | spin_lock_init(&bridge->res_lock); |
432 | 434 | ||
@@ -435,7 +437,7 @@ static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus) | |||
435 | 437 | ||
436 | 438 | ||
437 | /* allocate and initialize PCI-to-PCI bridge data structure */ | 439 | /* allocate and initialize PCI-to-PCI bridge data structure */ |
438 | static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev) | 440 | static void add_p2p_bridge(acpi_handle *handle) |
439 | { | 441 | { |
440 | struct acpiphp_bridge *bridge; | 442 | struct acpiphp_bridge *bridge; |
441 | 443 | ||
@@ -449,8 +451,8 @@ static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev) | |||
449 | bridge->handle = handle; | 451 | bridge->handle = handle; |
450 | config_p2p_bridge_flags(bridge); | 452 | config_p2p_bridge_flags(bridge); |
451 | 453 | ||
452 | bridge->pci_dev = pci_dev_get(pci_dev); | 454 | bridge->pci_dev = acpi_get_pci_dev(handle); |
453 | bridge->pci_bus = pci_dev->subordinate; | 455 | bridge->pci_bus = bridge->pci_dev->subordinate; |
454 | if (!bridge->pci_bus) { | 456 | if (!bridge->pci_bus) { |
455 | err("This is not a PCI-to-PCI bridge!\n"); | 457 | err("This is not a PCI-to-PCI bridge!\n"); |
456 | goto err; | 458 | goto err; |
@@ -467,7 +469,7 @@ static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev) | |||
467 | init_bridge_misc(bridge); | 469 | init_bridge_misc(bridge); |
468 | return; | 470 | return; |
469 | err: | 471 | err: |
470 | pci_dev_put(pci_dev); | 472 | pci_dev_put(bridge->pci_dev); |
471 | kfree(bridge); | 473 | kfree(bridge); |
472 | return; | 474 | return; |
473 | } | 475 | } |
@@ -478,39 +480,21 @@ static acpi_status | |||
478 | find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) | 480 | find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) |
479 | { | 481 | { |
480 | acpi_status status; | 482 | acpi_status status; |
481 | acpi_handle dummy_handle; | ||
482 | unsigned long long tmp; | ||
483 | int device, function; | ||
484 | struct pci_dev *dev; | 483 | struct pci_dev *dev; |
485 | struct pci_bus *pci_bus = context; | ||
486 | |||
487 | status = acpi_get_handle(handle, "_ADR", &dummy_handle); | ||
488 | if (ACPI_FAILURE(status)) | ||
489 | return AE_OK; /* continue */ | ||
490 | |||
491 | status = acpi_evaluate_integer(handle, "_ADR", NULL, &tmp); | ||
492 | if (ACPI_FAILURE(status)) { | ||
493 | dbg("%s: _ADR evaluation failure\n", __func__); | ||
494 | return AE_OK; | ||
495 | } | ||
496 | |||
497 | device = (tmp >> 16) & 0xffff; | ||
498 | function = tmp & 0xffff; | ||
499 | |||
500 | dev = pci_get_slot(pci_bus, PCI_DEVFN(device, function)); | ||
501 | 484 | ||
485 | dev = acpi_get_pci_dev(handle); | ||
502 | if (!dev || !dev->subordinate) | 486 | if (!dev || !dev->subordinate) |
503 | goto out; | 487 | goto out; |
504 | 488 | ||
505 | /* check if this bridge has ejectable slots */ | 489 | /* check if this bridge has ejectable slots */ |
506 | if ((detect_ejectable_slots(dev->subordinate) > 0)) { | 490 | if ((detect_ejectable_slots(handle) > 0)) { |
507 | dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev)); | 491 | dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev)); |
508 | add_p2p_bridge(handle, dev); | 492 | add_p2p_bridge(handle); |
509 | } | 493 | } |
510 | 494 | ||
511 | /* search P2P bridges under this p2p bridge */ | 495 | /* search P2P bridges under this p2p bridge */ |
512 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, | 496 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, |
513 | find_p2p_bridge, dev->subordinate, NULL); | 497 | find_p2p_bridge, NULL, NULL); |
514 | if (ACPI_FAILURE(status)) | 498 | if (ACPI_FAILURE(status)) |
515 | warn("find_p2p_bridge failed (error code = 0x%x)\n", status); | 499 | warn("find_p2p_bridge failed (error code = 0x%x)\n", status); |
516 | 500 | ||
@@ -525,9 +509,7 @@ static int add_bridge(acpi_handle handle) | |||
525 | { | 509 | { |
526 | acpi_status status; | 510 | acpi_status status; |
527 | unsigned long long tmp; | 511 | unsigned long long tmp; |
528 | int seg, bus; | ||
529 | acpi_handle dummy_handle; | 512 | acpi_handle dummy_handle; |
530 | struct pci_bus *pci_bus; | ||
531 | 513 | ||
532 | /* if the bridge doesn't have _STA, we assume it is always there */ | 514 | /* if the bridge doesn't have _STA, we assume it is always there */ |
533 | status = acpi_get_handle(handle, "_STA", &dummy_handle); | 515 | status = acpi_get_handle(handle, "_STA", &dummy_handle); |
@@ -542,36 +524,15 @@ static int add_bridge(acpi_handle handle) | |||
542 | return 0; | 524 | return 0; |
543 | } | 525 | } |
544 | 526 | ||
545 | /* get PCI segment number */ | ||
546 | status = acpi_evaluate_integer(handle, "_SEG", NULL, &tmp); | ||
547 | |||
548 | seg = ACPI_SUCCESS(status) ? tmp : 0; | ||
549 | |||
550 | /* get PCI bus number */ | ||
551 | status = acpi_evaluate_integer(handle, "_BBN", NULL, &tmp); | ||
552 | |||
553 | if (ACPI_SUCCESS(status)) { | ||
554 | bus = tmp; | ||
555 | } else { | ||
556 | warn("can't get bus number, assuming 0\n"); | ||
557 | bus = 0; | ||
558 | } | ||
559 | |||
560 | pci_bus = pci_find_bus(seg, bus); | ||
561 | if (!pci_bus) { | ||
562 | err("Can't find bus %04x:%02x\n", seg, bus); | ||
563 | return 0; | ||
564 | } | ||
565 | |||
566 | /* check if this bridge has ejectable slots */ | 527 | /* check if this bridge has ejectable slots */ |
567 | if (detect_ejectable_slots(pci_bus) > 0) { | 528 | if (detect_ejectable_slots(handle) > 0) { |
568 | dbg("found PCI host-bus bridge with hot-pluggable slots\n"); | 529 | dbg("found PCI host-bus bridge with hot-pluggable slots\n"); |
569 | add_host_bridge(handle, pci_bus); | 530 | add_host_bridge(handle); |
570 | } | 531 | } |
571 | 532 | ||
572 | /* search P2P bridges under this host bridge */ | 533 | /* search P2P bridges under this host bridge */ |
573 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, | 534 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, |
574 | find_p2p_bridge, pci_bus, NULL); | 535 | find_p2p_bridge, NULL, NULL); |
575 | 536 | ||
576 | if (ACPI_FAILURE(status)) | 537 | if (ACPI_FAILURE(status)) |
577 | warn("find_p2p_bridge failed (error code = 0x%x)\n", status); | 538 | warn("find_p2p_bridge failed (error code = 0x%x)\n", status); |