When a PCI host bridge device receives a Bus Check notification, we must re-enumerate starting with the bridge to discover changes (devices that have been added or removed). Prior to 668192b678 ("PCI: acpiphp: Move host bridge hotplug to pci_root.c"), this happened in _handle_hotplug_event_bridge(). After that commit, _handle_hotplug_event_bridge() is not installed for host bridges, and the host bridge notify handler, _handle_hotplug_event_root() did not re-enumerate. This patch adds re-enumeration to _handle_hotplug_event_root(). This fixes cases where we don't notice the addition or removal of PCI devices, e.g., the PCI-to-USB ExpressCard in the bugzilla below. -v1: Backport of 3f327e39b4 to v3.9 by Bjorn Helgaas <bhelgaas@xxxxxxxxxx> -v2: use request_module("acpiphp") for acpiphp is as module instead of built-in by Yinghai. [bhelgaas: changelog, references] Reference: https://lkml.kernel.org/r/CAAh6nkmbKR3HTqm5ommevsBwhL_u0N8Rk7Wsms_LfP=nBgKNew@xxxxxxxxxxxxxx Reference: https://bugzilla.kernel.org/show_bug.cgi?id=57961 Reported-by: Gavin Guo <tuffkidtt@xxxxxxxxx> Tested-by: Gavin Guo <tuffkidtt@xxxxxxxxx> Signed-off-by: Yinghai Lu <yinghai@xxxxxxxxxx> Signed-off-by: Bjorn Helgaas <bhelgaas@xxxxxxxxxx> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@xxxxxxxxx> CC: stable@xxxxxxxxxxxxxxx # v3.9+ --- drivers/acpi/pci_root.c | 7 ++++++- drivers/pci/hotplug/acpiphp_glue.c | 14 ++++++++++++++ include/linux/pci-acpi.h | 2 ++ 3 files changed, 22 insertions(+), 1 deletion(-) Index: linux-3.9.4/drivers/acpi/pci_root.c =================================================================== --- linux-3.9.4.orig/drivers/acpi/pci_root.c +++ linux-3.9.4/drivers/acpi/pci_root.c @@ -665,6 +665,7 @@ static void handle_root_bridge_removal(s kfree(ej_event); } +void (*acpiphp_check_host_bridge)(acpi_handle handle); static void _handle_hotplug_event_root(struct work_struct *work) { struct acpi_pci_root *root; @@ -687,7 +688,11 @@ static void _handle_hotplug_event_root(s /* bus enumerate */ printk(KERN_DEBUG "%s: Bus check notify on %s\n", __func__, (char *)buffer.pointer); - if (!root) + if (root) { + request_module("acpiphp"); + if (acpiphp_check_host_bridge) + acpiphp_check_host_bridge(handle); + } else handle_root_bridge_insertion(handle); break; Index: linux-3.9.4/drivers/pci/hotplug/acpiphp_glue.c =================================================================== --- linux-3.9.4.orig/drivers/pci/hotplug/acpiphp_glue.c +++ linux-3.9.4/drivers/pci/hotplug/acpiphp_glue.c @@ -1122,6 +1122,18 @@ check_sub_bridges(acpi_handle handle, u3 return AE_OK ; } +static void __acpiphp_check_host_bridge(acpi_handle handle) +{ + struct acpiphp_bridge *bridge; + + bridge = acpiphp_handle_to_bridge(handle); + if (bridge) + acpiphp_check_bridge(bridge); + + acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, + ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL); +} + static void _handle_hotplug_event_bridge(struct work_struct *work) { struct acpiphp_bridge *bridge; @@ -1305,6 +1317,7 @@ static struct acpi_pci_driver acpi_pci_h int __init acpiphp_glue_init(void) { acpi_pci_register_driver(&acpi_pci_hp_driver); + acpiphp_check_host_bridge = __acpiphp_check_host_bridge; return 0; } @@ -1317,6 +1330,7 @@ int __init acpiphp_glue_init(void) */ void acpiphp_glue_exit(void) { + acpiphp_check_host_bridge = NULL; acpi_pci_unregister_driver(&acpi_pci_hp_driver); } Index: linux-3.9.4/include/linux/pci-acpi.h =================================================================== --- linux-3.9.4.orig/include/linux/pci-acpi.h +++ linux-3.9.4/include/linux/pci-acpi.h @@ -43,6 +43,8 @@ static inline acpi_handle acpi_pci_get_b } #endif +extern void (*acpiphp_check_host_bridge)(acpi_handle handle); + #ifdef CONFIG_ACPI_APEI extern bool aer_acpi_firmware_first(void); #else -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html