Message ID | 1390013297-23462-2-git-send-email-jiang.liu@linux.intel.com (mailing list archive) |
---|---|
State | New, archived |
Delegated to: | Bjorn Helgaas |
Headers | show |
On Fri, Jan 17, 2014 at 6:48 PM, Jiang Liu <jiang.liu@linux.intel.com> wrote: > Reuse ACPI hotplug framework to support PCI host bridge hotplug, this > makes PCI host bridge hotplug implementation simpler and more clear. > > It also fixes a bug in support of PCI host bridge hot-addition. > Currently pci_root driver fails to install notification handler for > PCI host bridge absent at boot time because acpi_is_root_bridge() > returns false if no ACPI device created for handle. So PCI host > bridge hot-addition event will just be ignored by system. > > Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com> is the same as commit 3338db0057ed9f554050bd06863731c515d79672 Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Date: Fri Nov 22 21:55:20 2013 +0100 ACPI / hotplug: Make ACPI PCI root hotplug use common hotplug code in rafael tree pm/linux-next for 3.14? > --- > drivers/acpi/internal.h | 1 - > drivers/acpi/pci_root.c | 117 +++++++---------------------------------------- > drivers/acpi/scan.c | 2 - > 3 files changed, 17 insertions(+), 103 deletions(-) > > diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h > index a29739c..03efa56 100644 > --- a/drivers/acpi/internal.h > +++ b/drivers/acpi/internal.h > @@ -28,7 +28,6 @@ int init_acpi_device_notify(void); > int acpi_scan_init(void); > void acpi_pci_root_init(void); > void acpi_pci_link_init(void); > -void acpi_pci_root_hp_init(void); > void acpi_processor_init(void); > void acpi_platform_init(void); > int acpi_sysfs_init(void); > diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c > index 20360e4..6f6e6c1 100644 > --- a/drivers/acpi/pci_root.c > +++ b/drivers/acpi/pci_root.c > @@ -50,6 +50,7 @@ ACPI_MODULE_NAME("pci_root"); > static int acpi_pci_root_add(struct acpi_device *device, > const struct acpi_device_id *not_used); > static void acpi_pci_root_remove(struct acpi_device *device); > +static int handle_hotplug_event_root(acpi_handle handle, u32 type, void *ctx); > > #define ACPI_PCIE_REQ_SUPPORT (OSC_PCI_EXT_CONFIG_SUPPORT \ > | OSC_PCI_ASPM_SUPPORT \ > @@ -61,12 +62,14 @@ static const struct acpi_device_id root_device_ids[] = { > {"", 0}, > }; > > + > static struct acpi_scan_handler pci_root_handler = { > .ids = root_device_ids, > + .prepare = handle_hotplug_event_root, > .attach = acpi_pci_root_add, > .detach = acpi_pci_root_remove, > .hotplug = { > - .ignore = true, > + .enabled = true, > }, > }; > > @@ -627,113 +630,27 @@ void __init acpi_pci_root_init(void) > > if (!acpi_pci_disabled) { > pci_acpi_crs_quirks(); > - acpi_scan_add_handler(&pci_root_handler); > - } > -} > -/* Support root bridge hotplug */ > - > -static void handle_root_bridge_insertion(acpi_handle handle) > -{ > - struct acpi_device *device; > - > - if (!acpi_bus_get_device(handle, &device)) { > - dev_printk(KERN_DEBUG, &device->dev, > - "acpi device already exists; ignoring notify\n"); > - return; > + acpi_scan_add_handler_with_hotplug(&pci_root_handler, > + "pci_hostbridge"); > } > - > - if (acpi_bus_scan(handle)) > - acpi_handle_err(handle, "cannot add bridge to acpi list\n"); > } > > -static void hotplug_event_root(void *data, u32 type) > +static int handle_hotplug_event_root(acpi_handle handle, u32 type, void *ctx) > { > - acpi_handle handle = data; > + int ret = NOTIFY_OK; > struct acpi_pci_root *root; > > - acpi_scan_lock_acquire(); > - > - root = acpi_pci_find_root(handle); > - > - switch (type) { > - case ACPI_NOTIFY_BUS_CHECK: > - /* bus enumerate */ > - acpi_handle_printk(KERN_DEBUG, handle, > - "Bus check notify on %s\n", __func__); > - if (root) > + if (type == ACPI_NOTIFY_BUS_CHECK) { > + acpi_scan_lock_acquire(); > + root = acpi_pci_find_root(handle); > + if (root) { > + acpi_handle_printk(KERN_DEBUG, handle, > + "Bus check notify on %s\n", __func__); > acpiphp_check_host_bridge(handle); > - else > - handle_root_bridge_insertion(handle); > - > - break; > - > - case ACPI_NOTIFY_DEVICE_CHECK: > - /* device check */ > - acpi_handle_printk(KERN_DEBUG, handle, > - "Device check notify on %s\n", __func__); > - if (!root) > - handle_root_bridge_insertion(handle); > - break; > - > - case ACPI_NOTIFY_EJECT_REQUEST: > - /* request device eject */ > - acpi_handle_printk(KERN_DEBUG, handle, > - "Device eject notify on %s\n", __func__); > - if (!root) > - break; > - > - get_device(&root->device->dev); > - > + ret = NOTIFY_STOP; > + } > acpi_scan_lock_release(); > - > - acpi_bus_device_eject(root->device, ACPI_NOTIFY_EJECT_REQUEST); > - return; > - default: > - acpi_handle_warn(handle, > - "notify_handler: unknown event type 0x%x\n", > - type); > - break; > } > > - acpi_scan_lock_release(); > -} > - > -static void handle_hotplug_event_root(acpi_handle handle, u32 type, > - void *context) > -{ > - acpi_hotplug_execute(hotplug_event_root, handle, type); > -} > - > -static acpi_status __init > -find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) > -{ > - acpi_status status; > - int *count = (int *)context; > - > - if (!acpi_is_root_bridge(handle)) > - return AE_OK; > - > - (*count)++; > - > - status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, > - handle_hotplug_event_root, NULL); > - if (ACPI_FAILURE(status)) > - acpi_handle_printk(KERN_DEBUG, handle, > - "notify handler is not installed, exit status: %u\n", > - (unsigned int)status); > - else > - acpi_handle_printk(KERN_DEBUG, handle, > - "notify handler is installed\n"); > - > - return AE_OK; > -} > - > -void __init acpi_pci_root_hp_init(void) > -{ > - int num = 0; > - > - acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, > - ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL); > - > - printk(KERN_DEBUG "Found %d acpi root devices\n", num); > + return ret; > } > diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c > index 6b0f419..d83e0ff 100644 > --- a/drivers/acpi/scan.c > +++ b/drivers/acpi/scan.c > @@ -2057,8 +2057,6 @@ int __init acpi_scan_init(void) > > acpi_update_all_gpes(); > > - acpi_pci_root_hp_init(); > - > out: > mutex_unlock(&acpi_scan_lock); > return result; > -- > 1.7.10.4 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-acpi" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi yinghai,
Sorry for the noise. I didn't noticed Rafael's work,
so I generated this patchset when encountered this issue
during testing PCI host bridge hotplug. It should achieve
the same goal.
Thanks!
Gerry
On 2014/1/18 11:23, Yinghai Lu wrote:
> ACPI / hotplug: Make ACPI PCI root hotplug use common hotplug code
--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index a29739c..03efa56 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -28,7 +28,6 @@ int init_acpi_device_notify(void); int acpi_scan_init(void); void acpi_pci_root_init(void); void acpi_pci_link_init(void); -void acpi_pci_root_hp_init(void); void acpi_processor_init(void); void acpi_platform_init(void); int acpi_sysfs_init(void); diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 20360e4..6f6e6c1 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -50,6 +50,7 @@ ACPI_MODULE_NAME("pci_root"); static int acpi_pci_root_add(struct acpi_device *device, const struct acpi_device_id *not_used); static void acpi_pci_root_remove(struct acpi_device *device); +static int handle_hotplug_event_root(acpi_handle handle, u32 type, void *ctx); #define ACPI_PCIE_REQ_SUPPORT (OSC_PCI_EXT_CONFIG_SUPPORT \ | OSC_PCI_ASPM_SUPPORT \ @@ -61,12 +62,14 @@ static const struct acpi_device_id root_device_ids[] = { {"", 0}, }; + static struct acpi_scan_handler pci_root_handler = { .ids = root_device_ids, + .prepare = handle_hotplug_event_root, .attach = acpi_pci_root_add, .detach = acpi_pci_root_remove, .hotplug = { - .ignore = true, + .enabled = true, }, }; @@ -627,113 +630,27 @@ void __init acpi_pci_root_init(void) if (!acpi_pci_disabled) { pci_acpi_crs_quirks(); - acpi_scan_add_handler(&pci_root_handler); - } -} -/* Support root bridge hotplug */ - -static void handle_root_bridge_insertion(acpi_handle handle) -{ - struct acpi_device *device; - - if (!acpi_bus_get_device(handle, &device)) { - dev_printk(KERN_DEBUG, &device->dev, - "acpi device already exists; ignoring notify\n"); - return; + acpi_scan_add_handler_with_hotplug(&pci_root_handler, + "pci_hostbridge"); } - - if (acpi_bus_scan(handle)) - acpi_handle_err(handle, "cannot add bridge to acpi list\n"); } -static void hotplug_event_root(void *data, u32 type) +static int handle_hotplug_event_root(acpi_handle handle, u32 type, void *ctx) { - acpi_handle handle = data; + int ret = NOTIFY_OK; struct acpi_pci_root *root; - acpi_scan_lock_acquire(); - - root = acpi_pci_find_root(handle); - - switch (type) { - case ACPI_NOTIFY_BUS_CHECK: - /* bus enumerate */ - acpi_handle_printk(KERN_DEBUG, handle, - "Bus check notify on %s\n", __func__); - if (root) + if (type == ACPI_NOTIFY_BUS_CHECK) { + acpi_scan_lock_acquire(); + root = acpi_pci_find_root(handle); + if (root) { + acpi_handle_printk(KERN_DEBUG, handle, + "Bus check notify on %s\n", __func__); acpiphp_check_host_bridge(handle); - else - handle_root_bridge_insertion(handle); - - break; - - case ACPI_NOTIFY_DEVICE_CHECK: - /* device check */ - acpi_handle_printk(KERN_DEBUG, handle, - "Device check notify on %s\n", __func__); - if (!root) - handle_root_bridge_insertion(handle); - break; - - case ACPI_NOTIFY_EJECT_REQUEST: - /* request device eject */ - acpi_handle_printk(KERN_DEBUG, handle, - "Device eject notify on %s\n", __func__); - if (!root) - break; - - get_device(&root->device->dev); - + ret = NOTIFY_STOP; + } acpi_scan_lock_release(); - - acpi_bus_device_eject(root->device, ACPI_NOTIFY_EJECT_REQUEST); - return; - default: - acpi_handle_warn(handle, - "notify_handler: unknown event type 0x%x\n", - type); - break; } - acpi_scan_lock_release(); -} - -static void handle_hotplug_event_root(acpi_handle handle, u32 type, - void *context) -{ - acpi_hotplug_execute(hotplug_event_root, handle, type); -} - -static acpi_status __init -find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) -{ - acpi_status status; - int *count = (int *)context; - - if (!acpi_is_root_bridge(handle)) - return AE_OK; - - (*count)++; - - status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, - handle_hotplug_event_root, NULL); - if (ACPI_FAILURE(status)) - acpi_handle_printk(KERN_DEBUG, handle, - "notify handler is not installed, exit status: %u\n", - (unsigned int)status); - else - acpi_handle_printk(KERN_DEBUG, handle, - "notify handler is installed\n"); - - return AE_OK; -} - -void __init acpi_pci_root_hp_init(void) -{ - int num = 0; - - acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL); - - printk(KERN_DEBUG "Found %d acpi root devices\n", num); + return ret; } diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 6b0f419..d83e0ff 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -2057,8 +2057,6 @@ int __init acpi_scan_init(void) acpi_update_all_gpes(); - acpi_pci_root_hp_init(); - out: mutex_unlock(&acpi_scan_lock); return result;
Reuse ACPI hotplug framework to support PCI host bridge hotplug, this makes PCI host bridge hotplug implementation simpler and more clear. It also fixes a bug in support of PCI host bridge hot-addition. Currently pci_root driver fails to install notification handler for PCI host bridge absent at boot time because acpi_is_root_bridge() returns false if no ACPI device created for handle. So PCI host bridge hot-addition event will just be ignored by system. Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com> --- drivers/acpi/internal.h | 1 - drivers/acpi/pci_root.c | 117 +++++++---------------------------------------- drivers/acpi/scan.c | 2 - 3 files changed, 17 insertions(+), 103 deletions(-)