aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2013-01-21 16:20:48 -0500
committerBjorn Helgaas <bhelgaas@google.com>2013-01-25 16:50:36 -0500
commit668192b678201d2fff27c6cc76bb003c1ec4a52a (patch)
treeba04f0cb128c7d9cbe44f2050164608921ec7ee9 /drivers/pci
parent92d8aff3a317fcd6f78ed9ac13dbbaeae8cb11ed (diff)
PCI: acpiphp: Move host bridge hotplug to pci_root.c
The acpiphp driver is confusing because it contains partial support for PCI host bridge hotplug as well as support for hotplug of PCI devices. This patch moves the host bridge hot-add support to pci_root.c and adds hot-remove support in pci_root.c. How to test it: if sci_emu patch is applied, find out root bus number to ACPI root name mapping from dmesg or /sys. To remove root bus: echo "\_SB.PCIB 3" > /sys/kernel/debug/acpi/sci_notify To add back root bus: echo "\_SB.PCIB 1" > /sys/kernel/debug/acpi/sci_notify Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c59
1 files changed, 15 insertions, 44 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index bf338d2ff371..c4a6301009f2 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -543,10 +543,13 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
543 acpi_status status; 543 acpi_status status;
544 acpi_handle handle = bridge->handle; 544 acpi_handle handle = bridge->handle;
545 545
546 status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, 546 if (bridge->type != BRIDGE_TYPE_HOST) {
547 status = acpi_remove_notify_handler(handle,
548 ACPI_SYSTEM_NOTIFY,
547 handle_hotplug_event_bridge); 549 handle_hotplug_event_bridge);
548 if (ACPI_FAILURE(status)) 550 if (ACPI_FAILURE(status))
549 err("failed to remove notify handler\n"); 551 err("failed to remove notify handler\n");
552 }
550 553
551 if ((bridge->type != BRIDGE_TYPE_HOST) && 554 if ((bridge->type != BRIDGE_TYPE_HOST) &&
552 ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func)) { 555 ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func)) {
@@ -630,9 +633,6 @@ static void remove_bridge(struct acpi_pci_root *root)
630 bridge = acpiphp_handle_to_bridge(handle); 633 bridge = acpiphp_handle_to_bridge(handle);
631 if (bridge) 634 if (bridge)
632 cleanup_bridge(bridge); 635 cleanup_bridge(bridge);
633 else
634 acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
635 handle_hotplug_event_bridge);
636} 636}
637 637
638static int power_on_slot(struct acpiphp_slot *slot) 638static int power_on_slot(struct acpiphp_slot *slot)
@@ -1123,18 +1123,12 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus)
1123} 1123}
1124 1124
1125/* Program resources in newly inserted bridge */ 1125/* Program resources in newly inserted bridge */
1126static int acpiphp_configure_bridge (acpi_handle handle) 1126static int acpiphp_configure_p2p_bridge(acpi_handle handle)
1127{ 1127{
1128 struct pci_bus *bus; 1128 struct pci_dev *pdev = acpi_get_pci_dev(handle);
1129 struct pci_bus *bus = pdev->subordinate;
1129 1130
1130 if (acpi_is_root_bridge(handle)) { 1131 pci_dev_put(pdev);
1131 struct acpi_pci_root *root = acpi_pci_find_root(handle);
1132 bus = root->bus;
1133 } else {
1134 struct pci_dev *pdev = acpi_get_pci_dev(handle);
1135 bus = pdev->subordinate;
1136 pci_dev_put(pdev);
1137 }
1138 1132
1139 pci_bus_size_bridges(bus); 1133 pci_bus_size_bridges(bus);
1140 pci_bus_assign_resources(bus); 1134 pci_bus_assign_resources(bus);
@@ -1144,7 +1138,7 @@ static int acpiphp_configure_bridge (acpi_handle handle)
1144 return 0; 1138 return 0;
1145} 1139}
1146 1140
1147static void handle_bridge_insertion(acpi_handle handle, u32 type) 1141static void handle_p2p_bridge_insertion(acpi_handle handle, u32 type)
1148{ 1142{
1149 struct acpi_device *device; 1143 struct acpi_device *device;
1150 1144
@@ -1162,8 +1156,8 @@ static void handle_bridge_insertion(acpi_handle handle, u32 type)
1162 err("ACPI device object missing\n"); 1156 err("ACPI device object missing\n");
1163 return; 1157 return;
1164 } 1158 }
1165 if (!acpiphp_configure_bridge(handle)) 1159 if (!acpiphp_configure_p2p_bridge(handle))
1166 add_bridge(handle); 1160 add_p2p_bridge(handle);
1167 else 1161 else
1168 err("cannot configure and start bridge\n"); 1162 err("cannot configure and start bridge\n");
1169 1163
@@ -1221,7 +1215,7 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)
1221 1215
1222 if (acpi_bus_get_device(handle, &device)) { 1216 if (acpi_bus_get_device(handle, &device)) {
1223 /* This bridge must have just been physically inserted */ 1217 /* This bridge must have just been physically inserted */
1224 handle_bridge_insertion(handle, type); 1218 handle_p2p_bridge_insertion(handle, type);
1225 goto out; 1219 goto out;
1226 } 1220 }
1227 1221
@@ -1396,21 +1390,6 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type,
1396 alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_func); 1390 alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_func);
1397} 1391}
1398 1392
1399static acpi_status
1400find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
1401{
1402 int *count = (int *)context;
1403
1404 if (!acpi_is_root_bridge(handle))
1405 return AE_OK;
1406
1407 (*count)++;
1408 acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
1409 handle_hotplug_event_bridge, NULL);
1410
1411 return AE_OK ;
1412}
1413
1414static struct acpi_pci_driver acpi_pci_hp_driver = { 1393static struct acpi_pci_driver acpi_pci_hp_driver = {
1415 .add = add_bridge, 1394 .add = add_bridge,
1416 .remove = remove_bridge, 1395 .remove = remove_bridge,
@@ -1421,15 +1400,7 @@ static struct acpi_pci_driver acpi_pci_hp_driver = {
1421 */ 1400 */
1422int __init acpiphp_glue_init(void) 1401int __init acpiphp_glue_init(void)
1423{ 1402{
1424 int num = 0; 1403 acpi_pci_register_driver(&acpi_pci_hp_driver);
1425
1426 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
1427 ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL);
1428
1429 if (num <= 0)
1430 return -1;
1431 else
1432 acpi_pci_register_driver(&acpi_pci_hp_driver);
1433 1404
1434 return 0; 1405 return 0;
1435} 1406}