aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2012-11-09 12:00:02 -0500
committerBjorn Helgaas <bhelgaas@google.com>2012-11-09 12:00:02 -0500
commitfa20f6f240e127bc914ca980a4b10c723c55fec9 (patch)
tree1a8267f53240b763a9d555a410341c3d7e432721
parent13a84687092f47a6d67b1b17940eb3127ae888b3 (diff)
parentf426cef3bc58806284e0fee55d29262b10279f9c (diff)
Merge branch 'pci/yinghai-for-pci-root-bus-hotplug' into next
* pci/yinghai-for-pci-root-bus-hotplug: PCI/ACPI: Remove acpi_root_driver in reverse order PCI/ACPI: Delete host bridge _PRT during hot remove path PCI/ACPI: Make acpi_pci_root_remove() stop/remove pci root bus PCI: Add pci_stop_and_remove_root_bus() PCI/ACPI: Assign unassigned resource for hot-added root bus PCI: Move out pci_enable_bridges out of assign_unsigned_bus_res PCI: Move pci_rescan_bus() back to probe.c PCI: Separate out pci_assign_unassigned_bus_resources()
-rw-r--r--drivers/acpi/pci_root.c21
-rw-r--r--drivers/pci/probe.c22
-rw-r--r--drivers/pci/remove.c36
-rw-r--r--drivers/pci/setup-bus.c22
-rw-r--r--include/linux/pci.h3
5 files changed, 82 insertions, 22 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index bce469c0b48a..012f40d1d75d 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -644,12 +644,19 @@ static int acpi_pci_root_start(struct acpi_device *device)
644 struct acpi_pci_root *root = acpi_driver_data(device); 644 struct acpi_pci_root *root = acpi_driver_data(device);
645 struct acpi_pci_driver *driver; 645 struct acpi_pci_driver *driver;
646 646
647 if (system_state != SYSTEM_BOOTING)
648 pci_assign_unassigned_bus_resources(root->bus);
649
647 mutex_lock(&acpi_pci_root_lock); 650 mutex_lock(&acpi_pci_root_lock);
648 list_for_each_entry(driver, &acpi_pci_drivers, node) 651 list_for_each_entry(driver, &acpi_pci_drivers, node)
649 if (driver->add) 652 if (driver->add)
650 driver->add(root); 653 driver->add(root);
651 mutex_unlock(&acpi_pci_root_lock); 654 mutex_unlock(&acpi_pci_root_lock);
652 655
656 /* need to after hot-added ioapic is registered */
657 if (system_state != SYSTEM_BOOTING)
658 pci_enable_bridges(root->bus);
659
653 pci_bus_add_devices(root->bus); 660 pci_bus_add_devices(root->bus);
654 661
655 return 0; 662 return 0;
@@ -657,17 +664,29 @@ static int acpi_pci_root_start(struct acpi_device *device)
657 664
658static int acpi_pci_root_remove(struct acpi_device *device, int type) 665static int acpi_pci_root_remove(struct acpi_device *device, int type)
659{ 666{
667 acpi_status status;
668 acpi_handle handle;
660 struct acpi_pci_root *root = acpi_driver_data(device); 669 struct acpi_pci_root *root = acpi_driver_data(device);
661 struct acpi_pci_driver *driver; 670 struct acpi_pci_driver *driver;
662 671
672 pci_stop_root_bus(root->bus);
673
663 mutex_lock(&acpi_pci_root_lock); 674 mutex_lock(&acpi_pci_root_lock);
664 list_for_each_entry(driver, &acpi_pci_drivers, node) 675 list_for_each_entry_reverse(driver, &acpi_pci_drivers, node)
665 if (driver->remove) 676 if (driver->remove)
666 driver->remove(root); 677 driver->remove(root);
678 mutex_unlock(&acpi_pci_root_lock);
667 679
668 device_set_run_wake(root->bus->bridge, false); 680 device_set_run_wake(root->bus->bridge, false);
669 pci_acpi_remove_bus_pm_notifier(device); 681 pci_acpi_remove_bus_pm_notifier(device);
670 682
683 status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
684 if (ACPI_SUCCESS(status))
685 acpi_pci_irq_del_prt(root->bus);
686
687 pci_remove_root_bus(root->bus);
688
689 mutex_lock(&acpi_pci_root_lock);
671 list_del(&root->node); 690 list_del(&root->node);
672 mutex_unlock(&acpi_pci_root_lock); 691 mutex_unlock(&acpi_pci_root_lock);
673 kfree(root); 692 kfree(root);
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index ec909afa90b6..59cf1ba34936 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1890,6 +1890,28 @@ unsigned int __ref pci_rescan_bus_bridge_resize(struct pci_dev *bridge)
1890 return max; 1890 return max;
1891} 1891}
1892 1892
1893/**
1894 * pci_rescan_bus - scan a PCI bus for devices.
1895 * @bus: PCI bus to scan
1896 *
1897 * Scan a PCI bus and child buses for new devices, adds them,
1898 * and enables them.
1899 *
1900 * Returns the max number of subordinate bus discovered.
1901 */
1902unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
1903{
1904 unsigned int max;
1905
1906 max = pci_scan_child_bus(bus);
1907 pci_assign_unassigned_bus_resources(bus);
1908 pci_enable_bridges(bus);
1909 pci_bus_add_devices(bus);
1910
1911 return max;
1912}
1913EXPORT_SYMBOL_GPL(pci_rescan_bus);
1914
1893EXPORT_SYMBOL(pci_add_new_bus); 1915EXPORT_SYMBOL(pci_add_new_bus);
1894EXPORT_SYMBOL(pci_scan_slot); 1916EXPORT_SYMBOL(pci_scan_slot);
1895EXPORT_SYMBOL(pci_scan_bridge); 1917EXPORT_SYMBOL(pci_scan_bridge);
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 513972f3ed13..7c0fd9252e6f 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -111,3 +111,39 @@ void pci_stop_and_remove_bus_device(struct pci_dev *dev)
111 pci_remove_bus_device(dev); 111 pci_remove_bus_device(dev);
112} 112}
113EXPORT_SYMBOL(pci_stop_and_remove_bus_device); 113EXPORT_SYMBOL(pci_stop_and_remove_bus_device);
114
115void pci_stop_root_bus(struct pci_bus *bus)
116{
117 struct pci_dev *child, *tmp;
118 struct pci_host_bridge *host_bridge;
119
120 if (!pci_is_root_bus(bus))
121 return;
122
123 host_bridge = to_pci_host_bridge(bus->bridge);
124 list_for_each_entry_safe_reverse(child, tmp,
125 &bus->devices, bus_list)
126 pci_stop_bus_device(child);
127
128 /* stop the host bridge */
129 device_del(&host_bridge->dev);
130}
131
132void pci_remove_root_bus(struct pci_bus *bus)
133{
134 struct pci_dev *child, *tmp;
135 struct pci_host_bridge *host_bridge;
136
137 if (!pci_is_root_bus(bus))
138 return;
139
140 host_bridge = to_pci_host_bridge(bus->bridge);
141 list_for_each_entry_safe(child, tmp,
142 &bus->devices, bus_list)
143 pci_remove_bus_device(child);
144 pci_remove_bus(bus);
145 host_bridge->bus = NULL;
146
147 /* remove the host bridge */
148 put_device(&host_bridge->dev);
149}
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 1e808ca338f8..6d3591d57ea0 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1550,25 +1550,12 @@ enable_all:
1550} 1550}
1551EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources); 1551EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources);
1552 1552
1553#ifdef CONFIG_HOTPLUG 1553void pci_assign_unassigned_bus_resources(struct pci_bus *bus)
1554/**
1555 * pci_rescan_bus - scan a PCI bus for devices.
1556 * @bus: PCI bus to scan
1557 *
1558 * Scan a PCI bus and child buses for new devices, adds them,
1559 * and enables them.
1560 *
1561 * Returns the max number of subordinate bus discovered.
1562 */
1563unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
1564{ 1554{
1565 unsigned int max;
1566 struct pci_dev *dev; 1555 struct pci_dev *dev;
1567 LIST_HEAD(add_list); /* list of resources that 1556 LIST_HEAD(add_list); /* list of resources that
1568 want additional resources */ 1557 want additional resources */
1569 1558
1570 max = pci_scan_child_bus(bus);
1571
1572 down_read(&pci_bus_sem); 1559 down_read(&pci_bus_sem);
1573 list_for_each_entry(dev, &bus->devices, bus_list) 1560 list_for_each_entry(dev, &bus->devices, bus_list)
1574 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || 1561 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
@@ -1579,11 +1566,4 @@ unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
1579 up_read(&pci_bus_sem); 1566 up_read(&pci_bus_sem);
1580 __pci_bus_assign_resources(bus, &add_list, NULL); 1567 __pci_bus_assign_resources(bus, &add_list, NULL);
1581 BUG_ON(!list_empty(&add_list)); 1568 BUG_ON(!list_empty(&add_list));
1582
1583 pci_enable_bridges(bus);
1584 pci_bus_add_devices(bus);
1585
1586 return max;
1587} 1569}
1588EXPORT_SYMBOL_GPL(pci_rescan_bus);
1589#endif
diff --git a/include/linux/pci.h b/include/linux/pci.h
index ee2179546c63..786094254d57 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -712,6 +712,8 @@ extern struct pci_dev *pci_dev_get(struct pci_dev *dev);
712extern void pci_dev_put(struct pci_dev *dev); 712extern void pci_dev_put(struct pci_dev *dev);
713extern void pci_remove_bus(struct pci_bus *b); 713extern void pci_remove_bus(struct pci_bus *b);
714extern void pci_stop_and_remove_bus_device(struct pci_dev *dev); 714extern void pci_stop_and_remove_bus_device(struct pci_dev *dev);
715void pci_stop_root_bus(struct pci_bus *bus);
716void pci_remove_root_bus(struct pci_bus *bus);
715void pci_setup_cardbus(struct pci_bus *bus); 717void pci_setup_cardbus(struct pci_bus *bus);
716extern void pci_sort_breadthfirst(void); 718extern void pci_sort_breadthfirst(void);
717#define dev_is_pci(d) ((d)->bus == &pci_bus_type) 719#define dev_is_pci(d) ((d)->bus == &pci_bus_type)
@@ -958,6 +960,7 @@ void pci_bus_size_bridges(struct pci_bus *bus);
958int pci_claim_resource(struct pci_dev *, int); 960int pci_claim_resource(struct pci_dev *, int);
959void pci_assign_unassigned_resources(void); 961void pci_assign_unassigned_resources(void);
960void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge); 962void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge);
963void pci_assign_unassigned_bus_resources(struct pci_bus *bus);
961void pdev_enable_device(struct pci_dev *); 964void pdev_enable_device(struct pci_dev *);
962int pci_enable_resources(struct pci_dev *, int mask); 965int pci_enable_resources(struct pci_dev *, int mask);
963void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *), 966void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *),