From 1778794031aae75d4464904319d320edc3e77d39 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 30 Oct 2012 14:31:10 -0600 Subject: PCI: Separate out pci_assign_unassigned_bus_resources() It is main portion of pci_rescan_bus(). Separate it out and prepare to use it for PCI root bus hot add later. Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/setup-bus.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 1e808ca338f8..f64c071d6923 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1550,25 +1550,12 @@ enable_all: } EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources); -#ifdef CONFIG_HOTPLUG -/** - * pci_rescan_bus - scan a PCI bus for devices. - * @bus: PCI bus to scan - * - * Scan a PCI bus and child buses for new devices, adds them, - * and enables them. - * - * Returns the max number of subordinate bus discovered. - */ -unsigned int __ref pci_rescan_bus(struct pci_bus *bus) +void pci_assign_unassigned_bus_resources(struct pci_bus *bus) { - unsigned int max; struct pci_dev *dev; LIST_HEAD(add_list); /* list of resources that want additional resources */ - max = pci_scan_child_bus(bus); - down_read(&pci_bus_sem); list_for_each_entry(dev, &bus->devices, bus_list) if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || @@ -1581,6 +1568,24 @@ unsigned int __ref pci_rescan_bus(struct pci_bus *bus) BUG_ON(!list_empty(&add_list)); pci_enable_bridges(bus); +} + +#ifdef CONFIG_HOTPLUG +/** + * pci_rescan_bus - scan a PCI bus for devices. + * @bus: PCI bus to scan + * + * Scan a PCI bus and child buses for new devices, adds them, + * and enables them. + * + * Returns the max number of subordinate bus discovered. + */ +unsigned int __ref pci_rescan_bus(struct pci_bus *bus) +{ + unsigned int max; + + max = pci_scan_child_bus(bus); + pci_assign_unassigned_bus_resources(bus); pci_bus_add_devices(bus); return max; -- cgit v1.2.3 From a5213a3194f73cd29c68128d1540ce81f03ba7b9 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 30 Oct 2012 14:31:21 -0600 Subject: PCI: Move pci_rescan_bus() back to probe.c We have pci_assign_unassigned_bus_resources() in as global function now. Move pci_rescan_bus() back to probe.c where it should be. Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/probe.c | 21 +++++++++++++++++++++ drivers/pci/setup-bus.c | 23 ----------------------- 2 files changed, 21 insertions(+), 23 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index ec909afa90b6..65f62e353719 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1890,6 +1890,27 @@ unsigned int __ref pci_rescan_bus_bridge_resize(struct pci_dev *bridge) return max; } +/** + * pci_rescan_bus - scan a PCI bus for devices. + * @bus: PCI bus to scan + * + * Scan a PCI bus and child buses for new devices, adds them, + * and enables them. + * + * Returns the max number of subordinate bus discovered. + */ +unsigned int __ref pci_rescan_bus(struct pci_bus *bus) +{ + unsigned int max; + + max = pci_scan_child_bus(bus); + pci_assign_unassigned_bus_resources(bus); + pci_bus_add_devices(bus); + + return max; +} +EXPORT_SYMBOL_GPL(pci_rescan_bus); + EXPORT_SYMBOL(pci_add_new_bus); EXPORT_SYMBOL(pci_scan_slot); EXPORT_SYMBOL(pci_scan_bridge); diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index f64c071d6923..59e6c55c6d25 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1569,26 +1569,3 @@ void pci_assign_unassigned_bus_resources(struct pci_bus *bus) pci_enable_bridges(bus); } - -#ifdef CONFIG_HOTPLUG -/** - * pci_rescan_bus - scan a PCI bus for devices. - * @bus: PCI bus to scan - * - * Scan a PCI bus and child buses for new devices, adds them, - * and enables them. - * - * Returns the max number of subordinate bus discovered. - */ -unsigned int __ref pci_rescan_bus(struct pci_bus *bus) -{ - unsigned int max; - - max = pci_scan_child_bus(bus); - pci_assign_unassigned_bus_resources(bus); - pci_bus_add_devices(bus); - - return max; -} -EXPORT_SYMBOL_GPL(pci_rescan_bus); -#endif -- cgit v1.2.3 From e164f658f209b85566732bd85c62009237be0909 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 30 Oct 2012 14:31:26 -0600 Subject: PCI: Move out pci_enable_bridges out of assign_unsigned_bus_res So could use assign_unassigned_bus_res pci root bus add Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/probe.c | 1 + drivers/pci/setup-bus.c | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 65f62e353719..59cf1ba34936 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1905,6 +1905,7 @@ unsigned int __ref pci_rescan_bus(struct pci_bus *bus) max = pci_scan_child_bus(bus); pci_assign_unassigned_bus_resources(bus); + pci_enable_bridges(bus); pci_bus_add_devices(bus); return max; diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 59e6c55c6d25..6d3591d57ea0 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1566,6 +1566,4 @@ void pci_assign_unassigned_bus_resources(struct pci_bus *bus) up_read(&pci_bus_sem); __pci_bus_assign_resources(bus, &add_list, NULL); BUG_ON(!list_empty(&add_list)); - - pci_enable_bridges(bus); } -- cgit v1.2.3 From cdfcc572be0a8b423cecfb4ab5fd735fafe9c54a Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 30 Oct 2012 14:31:38 -0600 Subject: PCI: Add pci_stop_and_remove_root_bus() It supports both PCI root bus and PCI bus under PCI bridge. Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/remove.c | 36 ++++++++++++++++++++++++++++++++++++ include/linux/pci.h | 2 ++ 2 files changed, 38 insertions(+) (limited to 'drivers/pci') 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) pci_remove_bus_device(dev); } EXPORT_SYMBOL(pci_stop_and_remove_bus_device); + +void pci_stop_root_bus(struct pci_bus *bus) +{ + struct pci_dev *child, *tmp; + struct pci_host_bridge *host_bridge; + + if (!pci_is_root_bus(bus)) + return; + + host_bridge = to_pci_host_bridge(bus->bridge); + list_for_each_entry_safe_reverse(child, tmp, + &bus->devices, bus_list) + pci_stop_bus_device(child); + + /* stop the host bridge */ + device_del(&host_bridge->dev); +} + +void pci_remove_root_bus(struct pci_bus *bus) +{ + struct pci_dev *child, *tmp; + struct pci_host_bridge *host_bridge; + + if (!pci_is_root_bus(bus)) + return; + + host_bridge = to_pci_host_bridge(bus->bridge); + list_for_each_entry_safe(child, tmp, + &bus->devices, bus_list) + pci_remove_bus_device(child); + pci_remove_bus(bus); + host_bridge->bus = NULL; + + /* remove the host bridge */ + put_device(&host_bridge->dev); +} diff --git a/include/linux/pci.h b/include/linux/pci.h index f543eb3b1c0c..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); extern void pci_dev_put(struct pci_dev *dev); extern void pci_remove_bus(struct pci_bus *b); extern void pci_stop_and_remove_bus_device(struct pci_dev *dev); +void pci_stop_root_bus(struct pci_bus *bus); +void pci_remove_root_bus(struct pci_bus *bus); void pci_setup_cardbus(struct pci_bus *bus); extern void pci_sort_breadthfirst(void); #define dev_is_pci(d) ((d)->bus == &pci_bus_type) -- cgit v1.2.3