diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-13 15:14:47 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-13 15:14:47 -0500 |
commit | 193c0d682525987db59ac3a24531a77e4947aa95 (patch) | |
tree | 7b58346171c4d07e2c2ee6c3c469c325495149a4 /drivers/acpi | |
parent | 8b0cab14951fbf8126795ab301835a8f8126a988 (diff) | |
parent | 1cb73f8c479e66541fefd3f7fa547b1fa56cdc54 (diff) |
Merge tag 'for-3.8' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI update from Bjorn Helgaas:
"Host bridge hotplug:
- Untangle _PRT from struct pci_bus (Bjorn Helgaas)
- Request _OSC control before scanning root bus (Taku Izumi)
- Assign resources when adding host bridge (Yinghai Lu)
- Remove root bus when removing host bridge (Yinghai Lu)
- Remove _PRT during hot remove (Yinghai Lu)
SRIOV
- Add sysfs knobs to control numVFs (Don Dutile)
Power management
- Notify devices when power resource turned on (Huang Ying)
Bug fixes
- Work around broken _SEG on HP xw9300 (Bjorn Helgaas)
- Keep runtime PM enabled for unbound PCI devices (Huang Ying)
- Fix Optimus dual-GPU runtime D3 suspend issue (Dave Airlie)
- Fix xen frontend shutdown issue (David Vrabel)
- Work around PLX PCI 9050 BAR alignment erratum (Ian Abbott)
Miscellaneous
- Add GPL license for drivers/pci/ioapic (Andrew Cooks)
- Add standard PCI-X, PCIe ASPM register #defines (Bjorn Helgaas)
- NumaChip remote PCI support (Daniel Blueman)
- Fix PCIe Link Capabilities Supported Link Speed definition (Jingoo
Han)
- Convert dev_printk() to dev_info(), etc (Joe Perches)
- Add support for non PCI BAR ROM data (Matthew Garrett)
- Add x86 support for host bridge translation offset (Mike Yoknis)
- Report success only when every driver supports AER (Vijay
Pandarathil)"
Fix up trivial conflicts.
* tag 'for-3.8' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (48 commits)
PCI: Use phys_addr_t for physical ROM address
x86/PCI: Add NumaChip remote PCI support
ath9k: Use standard #defines for PCIe Capability ASPM fields
iwlwifi: Use standard #defines for PCIe Capability ASPM fields
iwlwifi: collapse wrapper for pcie_capability_read_word()
iwlegacy: Use standard #defines for PCIe Capability ASPM fields
iwlegacy: collapse wrapper for pcie_capability_read_word()
cxgb3: Use standard #defines for PCIe Capability ASPM fields
PCI: Add standard PCIe Capability Link ASPM field names
PCI/portdrv: Use PCI Express Capability accessors
PCI: Use standard PCIe Capability Link register field names
x86: Use PCI setup data
PCI: Add support for non-BAR ROMs
PCI: Add pcibios_add_device
EFI: Stash ROMs if they're not in the PCI BAR
PCI: Add and use standard PCI-X Capability register names
PCI/PM: Keep runtime PM enabled for unbound PCI devices
xen-pcifront: Handle backend CLOSED without CLOSING
PCI: SRIOV control and status via sysfs (documentation)
PCI/AER: Report success only when every device has AER-aware driver
...
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/pci_bind.c | 12 | ||||
-rw-r--r-- | drivers/acpi/pci_irq.c | 17 | ||||
-rw-r--r-- | drivers/acpi/pci_root.c | 165 |
3 files changed, 110 insertions, 84 deletions
diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c index 2ef04098cc1d..a1dee29beed3 100644 --- a/drivers/acpi/pci_bind.c +++ b/drivers/acpi/pci_bind.c | |||
@@ -45,11 +45,12 @@ static int acpi_pci_unbind(struct acpi_device *device) | |||
45 | 45 | ||
46 | device_set_run_wake(&dev->dev, false); | 46 | device_set_run_wake(&dev->dev, false); |
47 | pci_acpi_remove_pm_notifier(device); | 47 | pci_acpi_remove_pm_notifier(device); |
48 | acpi_power_resource_unregister_device(&dev->dev, device->handle); | ||
48 | 49 | ||
49 | if (!dev->subordinate) | 50 | if (!dev->subordinate) |
50 | goto out; | 51 | goto out; |
51 | 52 | ||
52 | acpi_pci_irq_del_prt(dev->subordinate); | 53 | acpi_pci_irq_del_prt(pci_domain_nr(dev->bus), dev->subordinate->number); |
53 | 54 | ||
54 | device->ops.bind = NULL; | 55 | device->ops.bind = NULL; |
55 | device->ops.unbind = NULL; | 56 | device->ops.unbind = NULL; |
@@ -63,7 +64,7 @@ static int acpi_pci_bind(struct acpi_device *device) | |||
63 | { | 64 | { |
64 | acpi_status status; | 65 | acpi_status status; |
65 | acpi_handle handle; | 66 | acpi_handle handle; |
66 | struct pci_bus *bus; | 67 | unsigned char bus; |
67 | struct pci_dev *dev; | 68 | struct pci_dev *dev; |
68 | 69 | ||
69 | dev = acpi_get_pci_dev(device->handle); | 70 | dev = acpi_get_pci_dev(device->handle); |
@@ -71,6 +72,7 @@ static int acpi_pci_bind(struct acpi_device *device) | |||
71 | return 0; | 72 | return 0; |
72 | 73 | ||
73 | pci_acpi_add_pm_notifier(device, dev); | 74 | pci_acpi_add_pm_notifier(device, dev); |
75 | acpi_power_resource_register_device(&dev->dev, device->handle); | ||
74 | if (device->wakeup.flags.run_wake) | 76 | if (device->wakeup.flags.run_wake) |
75 | device_set_run_wake(&dev->dev, true); | 77 | device_set_run_wake(&dev->dev, true); |
76 | 78 | ||
@@ -100,11 +102,11 @@ static int acpi_pci_bind(struct acpi_device *device) | |||
100 | goto out; | 102 | goto out; |
101 | 103 | ||
102 | if (dev->subordinate) | 104 | if (dev->subordinate) |
103 | bus = dev->subordinate; | 105 | bus = dev->subordinate->number; |
104 | else | 106 | else |
105 | bus = dev->bus; | 107 | bus = dev->bus->number; |
106 | 108 | ||
107 | acpi_pci_irq_add_prt(device->handle, bus); | 109 | acpi_pci_irq_add_prt(device->handle, pci_domain_nr(dev->bus), bus); |
108 | 110 | ||
109 | out: | 111 | out: |
110 | pci_dev_put(dev); | 112 | pci_dev_put(dev); |
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 23a032490130..68a921d03247 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c | |||
@@ -184,7 +184,7 @@ static void do_prt_fixups(struct acpi_prt_entry *entry, | |||
184 | } | 184 | } |
185 | } | 185 | } |
186 | 186 | ||
187 | static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus, | 187 | static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus, |
188 | struct acpi_pci_routing_table *prt) | 188 | struct acpi_pci_routing_table *prt) |
189 | { | 189 | { |
190 | struct acpi_prt_entry *entry; | 190 | struct acpi_prt_entry *entry; |
@@ -198,8 +198,8 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus, | |||
198 | * 1=INTA, 2=INTB. We use the PCI encoding throughout, so convert | 198 | * 1=INTA, 2=INTB. We use the PCI encoding throughout, so convert |
199 | * it here. | 199 | * it here. |
200 | */ | 200 | */ |
201 | entry->id.segment = pci_domain_nr(bus); | 201 | entry->id.segment = segment; |
202 | entry->id.bus = bus->number; | 202 | entry->id.bus = bus; |
203 | entry->id.device = (prt->address >> 16) & 0xFFFF; | 203 | entry->id.device = (prt->address >> 16) & 0xFFFF; |
204 | entry->pin = prt->pin + 1; | 204 | entry->pin = prt->pin + 1; |
205 | 205 | ||
@@ -244,7 +244,7 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus, | |||
244 | return 0; | 244 | return 0; |
245 | } | 245 | } |
246 | 246 | ||
247 | int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus) | 247 | int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus) |
248 | { | 248 | { |
249 | acpi_status status; | 249 | acpi_status status; |
250 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 250 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
@@ -273,7 +273,7 @@ int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus) | |||
273 | 273 | ||
274 | entry = buffer.pointer; | 274 | entry = buffer.pointer; |
275 | while (entry && (entry->length > 0)) { | 275 | while (entry && (entry->length > 0)) { |
276 | acpi_pci_irq_add_entry(handle, bus, entry); | 276 | acpi_pci_irq_add_entry(handle, segment, bus, entry); |
277 | entry = (struct acpi_pci_routing_table *) | 277 | entry = (struct acpi_pci_routing_table *) |
278 | ((unsigned long)entry + entry->length); | 278 | ((unsigned long)entry + entry->length); |
279 | } | 279 | } |
@@ -282,17 +282,16 @@ int acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus) | |||
282 | return 0; | 282 | return 0; |
283 | } | 283 | } |
284 | 284 | ||
285 | void acpi_pci_irq_del_prt(struct pci_bus *bus) | 285 | void acpi_pci_irq_del_prt(int segment, int bus) |
286 | { | 286 | { |
287 | struct acpi_prt_entry *entry, *tmp; | 287 | struct acpi_prt_entry *entry, *tmp; |
288 | 288 | ||
289 | printk(KERN_DEBUG | 289 | printk(KERN_DEBUG |
290 | "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n", | 290 | "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n", |
291 | pci_domain_nr(bus), bus->number); | 291 | segment, bus); |
292 | spin_lock(&acpi_prt_lock); | 292 | spin_lock(&acpi_prt_lock); |
293 | list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) { | 293 | list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) { |
294 | if (pci_domain_nr(bus) == entry->id.segment | 294 | if (segment == entry->id.segment && bus == entry->id.bus) { |
295 | && bus->number == entry->id.bus) { | ||
296 | list_del(&entry->list); | 295 | list_del(&entry->list); |
297 | kfree(entry); | 296 | kfree(entry); |
298 | } | 297 | } |
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index f70b9e5fc1b5..7928d4dc7056 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -454,6 +454,7 @@ static int acpi_pci_root_add(struct acpi_device *device) | |||
454 | acpi_handle handle; | 454 | acpi_handle handle; |
455 | struct acpi_device *child; | 455 | struct acpi_device *child; |
456 | u32 flags, base_flags; | 456 | u32 flags, base_flags; |
457 | bool is_osc_granted = false; | ||
457 | 458 | ||
458 | root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); | 459 | root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); |
459 | if (!root) | 460 | if (!root) |
@@ -501,85 +502,47 @@ static int acpi_pci_root_add(struct acpi_device *device) | |||
501 | strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); | 502 | strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); |
502 | device->driver_data = root; | 503 | device->driver_data = root; |
503 | 504 | ||
504 | root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle); | ||
505 | |||
506 | /* | ||
507 | * All supported architectures that use ACPI have support for | ||
508 | * PCI domains, so we indicate this in _OSC support capabilities. | ||
509 | */ | ||
510 | flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; | ||
511 | acpi_pci_osc_support(root, flags); | ||
512 | |||
513 | /* | ||
514 | * TBD: Need PCI interface for enumeration/configuration of roots. | ||
515 | */ | ||
516 | |||
517 | mutex_lock(&acpi_pci_root_lock); | ||
518 | list_add_tail(&root->node, &acpi_pci_roots); | ||
519 | mutex_unlock(&acpi_pci_root_lock); | ||
520 | |||
521 | printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n", | 505 | printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n", |
522 | acpi_device_name(device), acpi_device_bid(device), | 506 | acpi_device_name(device), acpi_device_bid(device), |
523 | root->segment, &root->secondary); | 507 | root->segment, &root->secondary); |
524 | 508 | ||
525 | /* | 509 | /* |
526 | * Scan the Root Bridge | ||
527 | * -------------------- | ||
528 | * Must do this prior to any attempt to bind the root device, as the | ||
529 | * PCI namespace does not get created until this call is made (and | ||
530 | * thus the root bridge's pci_dev does not exist). | ||
531 | */ | ||
532 | root->bus = pci_acpi_scan_root(root); | ||
533 | if (!root->bus) { | ||
534 | printk(KERN_ERR PREFIX | ||
535 | "Bus %04x:%02x not present in PCI namespace\n", | ||
536 | root->segment, (unsigned int)root->secondary.start); | ||
537 | result = -ENODEV; | ||
538 | goto out_del_root; | ||
539 | } | ||
540 | |||
541 | /* | ||
542 | * Attach ACPI-PCI Context | ||
543 | * ----------------------- | ||
544 | * Thus binding the ACPI and PCI devices. | ||
545 | */ | ||
546 | result = acpi_pci_bind_root(device); | ||
547 | if (result) | ||
548 | goto out_del_root; | ||
549 | |||
550 | /* | ||
551 | * PCI Routing Table | 510 | * PCI Routing Table |
552 | * ----------------- | 511 | * ----------------- |
553 | * Evaluate and parse _PRT, if exists. | 512 | * Evaluate and parse _PRT, if exists. |
554 | */ | 513 | */ |
555 | status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); | 514 | status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); |
556 | if (ACPI_SUCCESS(status)) | 515 | if (ACPI_SUCCESS(status)) |
557 | result = acpi_pci_irq_add_prt(device->handle, root->bus); | 516 | result = acpi_pci_irq_add_prt(device->handle, root->segment, |
517 | root->secondary.start); | ||
518 | |||
519 | root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle); | ||
558 | 520 | ||
559 | /* | 521 | /* |
560 | * Scan and bind all _ADR-Based Devices | 522 | * All supported architectures that use ACPI have support for |
523 | * PCI domains, so we indicate this in _OSC support capabilities. | ||
561 | */ | 524 | */ |
562 | list_for_each_entry(child, &device->children, node) | 525 | flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; |
563 | acpi_pci_bridge_scan(child); | 526 | acpi_pci_osc_support(root, flags); |
564 | 527 | ||
565 | /* Indicate support for various _OSC capabilities. */ | 528 | /* Indicate support for various _OSC capabilities. */ |
566 | if (pci_ext_cfg_avail(root->bus->self)) | 529 | if (pci_ext_cfg_avail()) |
567 | flags |= OSC_EXT_PCI_CONFIG_SUPPORT; | 530 | flags |= OSC_EXT_PCI_CONFIG_SUPPORT; |
568 | if (pcie_aspm_support_enabled()) | 531 | if (pcie_aspm_support_enabled()) { |
569 | flags |= OSC_ACTIVE_STATE_PWR_SUPPORT | | 532 | flags |= OSC_ACTIVE_STATE_PWR_SUPPORT | |
570 | OSC_CLOCK_PWR_CAPABILITY_SUPPORT; | 533 | OSC_CLOCK_PWR_CAPABILITY_SUPPORT; |
534 | } | ||
571 | if (pci_msi_enabled()) | 535 | if (pci_msi_enabled()) |
572 | flags |= OSC_MSI_SUPPORT; | 536 | flags |= OSC_MSI_SUPPORT; |
573 | if (flags != base_flags) { | 537 | if (flags != base_flags) { |
574 | status = acpi_pci_osc_support(root, flags); | 538 | status = acpi_pci_osc_support(root, flags); |
575 | if (ACPI_FAILURE(status)) { | 539 | if (ACPI_FAILURE(status)) { |
576 | dev_info(root->bus->bridge, "ACPI _OSC support " | 540 | dev_info(&device->dev, "ACPI _OSC support " |
577 | "notification failed, disabling PCIe ASPM\n"); | 541 | "notification failed, disabling PCIe ASPM\n"); |
578 | pcie_no_aspm(); | 542 | pcie_no_aspm(); |
579 | flags = base_flags; | 543 | flags = base_flags; |
580 | } | 544 | } |
581 | } | 545 | } |
582 | |||
583 | if (!pcie_ports_disabled | 546 | if (!pcie_ports_disabled |
584 | && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) { | 547 | && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) { |
585 | flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL | 548 | flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL |
@@ -588,40 +551,81 @@ static int acpi_pci_root_add(struct acpi_device *device) | |||
588 | 551 | ||
589 | if (pci_aer_available()) { | 552 | if (pci_aer_available()) { |
590 | if (aer_acpi_firmware_first()) | 553 | if (aer_acpi_firmware_first()) |
591 | dev_dbg(root->bus->bridge, | 554 | dev_dbg(&device->dev, |
592 | "PCIe errors handled by BIOS.\n"); | 555 | "PCIe errors handled by BIOS.\n"); |
593 | else | 556 | else |
594 | flags |= OSC_PCI_EXPRESS_AER_CONTROL; | 557 | flags |= OSC_PCI_EXPRESS_AER_CONTROL; |
595 | } | 558 | } |
596 | 559 | ||
597 | dev_info(root->bus->bridge, | 560 | dev_info(&device->dev, |
598 | "Requesting ACPI _OSC control (0x%02x)\n", flags); | 561 | "Requesting ACPI _OSC control (0x%02x)\n", flags); |
599 | 562 | ||
600 | status = acpi_pci_osc_control_set(device->handle, &flags, | 563 | status = acpi_pci_osc_control_set(device->handle, &flags, |
601 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); | 564 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); |
602 | if (ACPI_SUCCESS(status)) { | 565 | if (ACPI_SUCCESS(status)) { |
603 | dev_info(root->bus->bridge, | 566 | is_osc_granted = true; |
567 | dev_info(&device->dev, | ||
604 | "ACPI _OSC control (0x%02x) granted\n", flags); | 568 | "ACPI _OSC control (0x%02x) granted\n", flags); |
605 | if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { | ||
606 | /* | ||
607 | * We have ASPM control, but the FADT indicates | ||
608 | * that it's unsupported. Clear it. | ||
609 | */ | ||
610 | pcie_clear_aspm(root->bus); | ||
611 | } | ||
612 | } else { | 569 | } else { |
613 | dev_info(root->bus->bridge, | 570 | is_osc_granted = false; |
571 | dev_info(&device->dev, | ||
614 | "ACPI _OSC request failed (%s), " | 572 | "ACPI _OSC request failed (%s), " |
615 | "returned control mask: 0x%02x\n", | 573 | "returned control mask: 0x%02x\n", |
616 | acpi_format_exception(status), flags); | 574 | acpi_format_exception(status), flags); |
617 | pr_info("ACPI _OSC control for PCIe not granted, " | ||
618 | "disabling ASPM\n"); | ||
619 | pcie_no_aspm(); | ||
620 | } | 575 | } |
621 | } else { | 576 | } else { |
622 | dev_info(root->bus->bridge, | 577 | dev_info(&device->dev, |
623 | "Unable to request _OSC control " | 578 | "Unable to request _OSC control " |
624 | "(_OSC support mask: 0x%02x)\n", flags); | 579 | "(_OSC support mask: 0x%02x)\n", flags); |
580 | } | ||
581 | |||
582 | /* | ||
583 | * TBD: Need PCI interface for enumeration/configuration of roots. | ||
584 | */ | ||
585 | |||
586 | mutex_lock(&acpi_pci_root_lock); | ||
587 | list_add_tail(&root->node, &acpi_pci_roots); | ||
588 | mutex_unlock(&acpi_pci_root_lock); | ||
589 | |||
590 | /* | ||
591 | * Scan the Root Bridge | ||
592 | * -------------------- | ||
593 | * Must do this prior to any attempt to bind the root device, as the | ||
594 | * PCI namespace does not get created until this call is made (and | ||
595 | * thus the root bridge's pci_dev does not exist). | ||
596 | */ | ||
597 | root->bus = pci_acpi_scan_root(root); | ||
598 | if (!root->bus) { | ||
599 | printk(KERN_ERR PREFIX | ||
600 | "Bus %04x:%02x not present in PCI namespace\n", | ||
601 | root->segment, (unsigned int)root->secondary.start); | ||
602 | result = -ENODEV; | ||
603 | goto out_del_root; | ||
604 | } | ||
605 | |||
606 | /* | ||
607 | * Attach ACPI-PCI Context | ||
608 | * ----------------------- | ||
609 | * Thus binding the ACPI and PCI devices. | ||
610 | */ | ||
611 | result = acpi_pci_bind_root(device); | ||
612 | if (result) | ||
613 | goto out_del_root; | ||
614 | |||
615 | /* | ||
616 | * Scan and bind all _ADR-Based Devices | ||
617 | */ | ||
618 | list_for_each_entry(child, &device->children, node) | ||
619 | acpi_pci_bridge_scan(child); | ||
620 | |||
621 | /* ASPM setting */ | ||
622 | if (is_osc_granted) { | ||
623 | if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) | ||
624 | pcie_clear_aspm(root->bus); | ||
625 | } else { | ||
626 | pr_info("ACPI _OSC control for PCIe not granted, " | ||
627 | "disabling ASPM\n"); | ||
628 | pcie_no_aspm(); | ||
625 | } | 629 | } |
626 | 630 | ||
627 | pci_acpi_add_bus_pm_notifier(device, root->bus); | 631 | pci_acpi_add_bus_pm_notifier(device, root->bus); |
@@ -634,6 +638,8 @@ out_del_root: | |||
634 | mutex_lock(&acpi_pci_root_lock); | 638 | mutex_lock(&acpi_pci_root_lock); |
635 | list_del(&root->node); | 639 | list_del(&root->node); |
636 | mutex_unlock(&acpi_pci_root_lock); | 640 | mutex_unlock(&acpi_pci_root_lock); |
641 | |||
642 | acpi_pci_irq_del_prt(root->segment, root->secondary.start); | ||
637 | end: | 643 | end: |
638 | kfree(root); | 644 | kfree(root); |
639 | return result; | 645 | return result; |
@@ -644,12 +650,19 @@ static int acpi_pci_root_start(struct acpi_device *device) | |||
644 | struct acpi_pci_root *root = acpi_driver_data(device); | 650 | struct acpi_pci_root *root = acpi_driver_data(device); |
645 | struct acpi_pci_driver *driver; | 651 | struct acpi_pci_driver *driver; |
646 | 652 | ||
653 | if (system_state != SYSTEM_BOOTING) | ||
654 | pci_assign_unassigned_bus_resources(root->bus); | ||
655 | |||
647 | mutex_lock(&acpi_pci_root_lock); | 656 | mutex_lock(&acpi_pci_root_lock); |
648 | list_for_each_entry(driver, &acpi_pci_drivers, node) | 657 | list_for_each_entry(driver, &acpi_pci_drivers, node) |
649 | if (driver->add) | 658 | if (driver->add) |
650 | driver->add(root); | 659 | driver->add(root); |
651 | mutex_unlock(&acpi_pci_root_lock); | 660 | mutex_unlock(&acpi_pci_root_lock); |
652 | 661 | ||
662 | /* need to after hot-added ioapic is registered */ | ||
663 | if (system_state != SYSTEM_BOOTING) | ||
664 | pci_enable_bridges(root->bus); | ||
665 | |||
653 | pci_bus_add_devices(root->bus); | 666 | pci_bus_add_devices(root->bus); |
654 | 667 | ||
655 | return 0; | 668 | return 0; |
@@ -657,17 +670,29 @@ static int acpi_pci_root_start(struct acpi_device *device) | |||
657 | 670 | ||
658 | static int acpi_pci_root_remove(struct acpi_device *device, int type) | 671 | static int acpi_pci_root_remove(struct acpi_device *device, int type) |
659 | { | 672 | { |
673 | acpi_status status; | ||
674 | acpi_handle handle; | ||
660 | struct acpi_pci_root *root = acpi_driver_data(device); | 675 | struct acpi_pci_root *root = acpi_driver_data(device); |
661 | struct acpi_pci_driver *driver; | 676 | struct acpi_pci_driver *driver; |
662 | 677 | ||
678 | pci_stop_root_bus(root->bus); | ||
679 | |||
663 | mutex_lock(&acpi_pci_root_lock); | 680 | mutex_lock(&acpi_pci_root_lock); |
664 | list_for_each_entry(driver, &acpi_pci_drivers, node) | 681 | list_for_each_entry_reverse(driver, &acpi_pci_drivers, node) |
665 | if (driver->remove) | 682 | if (driver->remove) |
666 | driver->remove(root); | 683 | driver->remove(root); |
684 | mutex_unlock(&acpi_pci_root_lock); | ||
667 | 685 | ||
668 | device_set_run_wake(root->bus->bridge, false); | 686 | device_set_run_wake(root->bus->bridge, false); |
669 | pci_acpi_remove_bus_pm_notifier(device); | 687 | pci_acpi_remove_bus_pm_notifier(device); |
670 | 688 | ||
689 | status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); | ||
690 | if (ACPI_SUCCESS(status)) | ||
691 | acpi_pci_irq_del_prt(root->segment, root->secondary.start); | ||
692 | |||
693 | pci_remove_root_bus(root->bus); | ||
694 | |||
695 | mutex_lock(&acpi_pci_root_lock); | ||
671 | list_del(&root->node); | 696 | list_del(&root->node); |
672 | mutex_unlock(&acpi_pci_root_lock); | 697 | mutex_unlock(&acpi_pci_root_lock); |
673 | kfree(root); | 698 | kfree(root); |