* [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering @ 2012-12-09 22:58 Rafael J. Wysocki 2012-12-09 23:00 ` [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki ` (7 more replies) 0 siblings, 8 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-09 22:58 UTC (permalink / raw) To: Bjorn Helgaas Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe Hi, The following patches change the ordering of the ACPI namespace scanning code so that all struct acpi_device objects in the given scope are registered before ACPI drivers are probed against them. They also do some simplifications and clarifications of the code made possible by this main change. This is done for three basic reasons. First, we need the boot ACPI namespace scanning code to be as similar as reasonably possible to the hot-plug ACPI namespace scanning code. Second, the ordering of PCI devices enumeration versus ACPI-backed platform devices registration needs to be such that the PCI devices in the given scope are all registered first. Finally, when we start to actually manage ACPI device resources as appropriate (e.g. resolve resource conflicts properly) we'll need all struct acpi_device nodes to be registered before any "companion" physical nodes or ACPI drivers are bound to them. The patches have been tested on Toshiba Portege R500 without breaking stuff (I used some additional debug code to verify that the ordering of device discovery had not been modified by them), but if you see any problems with them regarding hot-plug, please let me know. [1/6] - Separate adding ACPI device objects from probing ACPI drivers. [2/6] - Change the ordering of PCI root bridge driver registration. [3/6] - Make acpi_bus_add() and acpi_bus_start() visibly different. [4/6] - Reduce the usage of struct acpi_bus_ops [5/6] - Replace struct acpi_bus_ops with an enum type [6/6] - Change the ordering of acpi_bus_check_add() to avoid unnecessary checks. Thanks, Rafael -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-09 22:58 [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Rafael J. Wysocki @ 2012-12-09 23:00 ` Rafael J. Wysocki 2012-12-12 15:50 ` Jiang Liu ` (2 more replies) 2012-12-09 23:00 ` [PATCH 2/6] ACPI: Change the ordering of PCI root bridge driver registrarion Rafael J. Wysocki ` (6 subsequent siblings) 7 siblings, 3 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-09 23:00 UTC (permalink / raw) To: Bjorn Helgaas Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Currently, as soon as an ACPI device node object (struct acpi_device) is created, the driver core attempts to probe ACPI drivers against it. That leads to some unpleasant side effects, like the fact that the boot code path for ACPI namespace scanning is different from the analogous hot-plug code path (during boot ACPI drivers are not present when ACPI device node objects are registered, so they are guaranteed not to be probed, which is not the case during hot-plug). That, in turn, leads to unnecessary complications in the PCI enumeration algorithm. Reduce the differences between the boot and hot-plug cases by splitting the ACPI namespace scanning for devices into two passes, such that struct acpi_device objects are registerd in the first patch without probing ACPI drivers and the drivers are probed against them directly in the second pass. This way ACPI drivers can assume that all of the ACPI device node objects in the given scope will be registered when their .add() routines run and the hot-plug case becomes the same as the boot case from their perspective. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> --- drivers/acpi/scan.c | 96 +++++++++++++++++++++++++++++++++--------------- include/acpi/acpi_bus.h | 1 2 files changed, 68 insertions(+), 29 deletions(-) Index: linux/include/acpi/acpi_bus.h =================================================================== --- linux.orig/include/acpi/acpi_bus.h +++ linux/include/acpi/acpi_bus.h @@ -98,6 +98,7 @@ typedef void (*acpi_op_notify) (struct a struct acpi_bus_ops { u32 acpi_op_add:1; u32 acpi_op_start:1; + u32 acpi_op_match:1; }; struct acpi_device_ops { Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -494,7 +494,8 @@ static int acpi_bus_match(struct device struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_driver *acpi_drv = to_acpi_driver(drv); - return !acpi_match_device_ids(acpi_dev, acpi_drv->ids); + return acpi_dev->bus_ops.acpi_op_match + && !acpi_match_device_ids(acpi_dev, acpi_drv->ids); } static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) @@ -1418,6 +1419,17 @@ static int acpi_bus_remove(struct acpi_d return 0; } +/* + * acpi_hot_add_bind - Bind _ADR-based devices on hot-add. + * @device: ACPI device node to bind. + */ +static void acpi_hot_add_bind(struct acpi_device *device) +{ + if (device->flags.bus_address + && device->parent && device->parent->ops.bind) + device->parent->ops.bind(device); +} + static int acpi_add_single_object(struct acpi_device **child, acpi_handle handle, int type, unsigned long long sta, @@ -1490,13 +1502,8 @@ static int acpi_add_single_object(struct result = acpi_device_register(device); - /* - * Bind _ADR-Based Devices when hot add - */ - if (device->flags.bus_address) { - if (device->parent && device->parent->ops.bind) - device->parent->ops.bind(device); - } + if (device->bus_ops.acpi_op_match) + acpi_hot_add_bind(device); end: if (!result) { @@ -1522,6 +1529,7 @@ static void acpi_bus_add_power_resource( struct acpi_bus_ops ops = { .acpi_op_add = 1, .acpi_op_start = 1, + .acpi_op_match = 1, }; struct acpi_device *device = NULL; @@ -1574,9 +1582,9 @@ static acpi_status acpi_bus_check_add(ac void *context, void **return_value) { struct acpi_bus_ops *ops = context; + struct acpi_device *device = NULL; int type; unsigned long long sta; - struct acpi_device *device; acpi_status status; int result; @@ -1600,48 +1608,77 @@ static acpi_status acpi_bus_check_add(ac * We may already have an acpi_device from a previous enumeration. If * so, we needn't add it again, but we may still have to start it. */ - device = NULL; acpi_bus_get_device(handle, &device); if (ops->acpi_op_add && !device) { - acpi_add_single_object(&device, handle, type, sta, ops); - /* Is the device a known good platform device? */ - if (device - && !acpi_match_device_ids(device, acpi_platform_device_ids)) - acpi_create_platform_device(device); - } + struct acpi_bus_ops add_ops = *ops; - if (!device) - return AE_CTRL_DEPTH; - - if (ops->acpi_op_start && !(ops->acpi_op_add)) { - status = acpi_start_single_object(device); - if (ACPI_FAILURE(status)) + add_ops.acpi_op_match = 0; + acpi_add_single_object(&device, handle, type, sta, &add_ops); + if (!device) return AE_CTRL_DEPTH; + + device->bus_ops.acpi_op_match = 1; } if (!*return_value) *return_value = device; + return AE_OK; } +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl, + void *context, void **not_used) +{ + struct acpi_bus_ops *ops = context; + struct acpi_device *device; + acpi_status status = AE_OK; + + if (acpi_bus_get_device(handle, &device)) + return AE_CTRL_DEPTH; + + if (ops->acpi_op_add) { + if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { + /* This is a known good platform device. */ + acpi_create_platform_device(device); + } else { + int ret = device_attach(&device->dev); + acpi_hot_add_bind(device); + if (ret) + status = AE_CTRL_DEPTH; + } + } else if (ops->acpi_op_start) { + if (ACPI_FAILURE(acpi_start_single_object(device))) + status = AE_CTRL_DEPTH; + } + return status; +} + static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops, struct acpi_device **child) { - acpi_status status; void *device = NULL; + acpi_status status; + int ret = 0; status = acpi_bus_check_add(handle, 0, ops, &device); - if (ACPI_SUCCESS(status)) + if (ACPI_FAILURE(status)) { + ret = -ENODEV; + goto out; + } + + acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, + acpi_bus_check_add, NULL, ops, &device); + if (device) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - acpi_bus_check_add, NULL, ops, &device); + acpi_bus_probe_start, NULL, ops, NULL); + else + ret = -ENODEV; + out: if (child) *child = device; - if (device) - return 0; - else - return -ENODEV; + return ret; } /* @@ -1752,6 +1789,7 @@ static int acpi_bus_scan_fixed(void) memset(&ops, 0, sizeof(ops)); ops.acpi_op_add = 1; ops.acpi_op_start = 1; + ops.acpi_op_match = 1; /* * Enumerate all fixed-feature devices. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-09 23:00 ` [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki @ 2012-12-12 15:50 ` Jiang Liu 2012-12-12 22:34 ` Rafael J. Wysocki 2012-12-12 16:38 ` Jiang Liu 2012-12-13 1:00 ` Bjorn Helgaas 2 siblings, 1 reply; 88+ messages in thread From: Jiang Liu @ 2012-12-12 15:50 UTC (permalink / raw) To: Rafael J. Wysocki, Yinghai Lu Cc: Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci, Toshi Kani, Myron Stowe On 12/10/2012 07:00 AM, Rafael J. Wysocki wrote: > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > Currently, as soon as an ACPI device node object (struct acpi_device) > is created, the driver core attempts to probe ACPI drivers against > it. That leads to some unpleasant side effects, like the fact that > the boot code path for ACPI namespace scanning is different from the > analogous hot-plug code path (during boot ACPI drivers are not > present when ACPI device node objects are registered, so they are > guaranteed not to be probed, which is not the case during hot-plug). > That, in turn, leads to unnecessary complications in the PCI > enumeration algorithm. > > Reduce the differences between the boot and hot-plug cases by > splitting the ACPI namespace scanning for devices into two passes, > such that struct acpi_device objects are registerd in the first > patch without probing ACPI drivers and the drivers are probed > against them directly in the second pass. This way ACPI drivers > can assume that all of the ACPI device node objects in the given > scope will be registered when their .add() routines run and the > hot-plug case becomes the same as the boot case from their > perspective. > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > --- > drivers/acpi/scan.c | 96 +++++++++++++++++++++++++++++++++--------------- > include/acpi/acpi_bus.h | 1 > 2 files changed, 68 insertions(+), 29 deletions(-) > > Index: linux/include/acpi/acpi_bus.h > =================================================================== > --- linux.orig/include/acpi/acpi_bus.h > +++ linux/include/acpi/acpi_bus.h > @@ -98,6 +98,7 @@ typedef void (*acpi_op_notify) (struct a > struct acpi_bus_ops { > u32 acpi_op_add:1; > u32 acpi_op_start:1; > + u32 acpi_op_match:1; > }; > > struct acpi_device_ops { > Index: linux/drivers/acpi/scan.c > =================================================================== > --- linux.orig/drivers/acpi/scan.c > +++ linux/drivers/acpi/scan.c > @@ -494,7 +494,8 @@ static int acpi_bus_match(struct device > struct acpi_device *acpi_dev = to_acpi_device(dev); > struct acpi_driver *acpi_drv = to_acpi_driver(drv); > > - return !acpi_match_device_ids(acpi_dev, acpi_drv->ids); > + return acpi_dev->bus_ops.acpi_op_match > + && !acpi_match_device_ids(acpi_dev, acpi_drv->ids); > } Hi Rafael, PCI host bridge hotplug has the same requirement to separate device enumeration from device driver binding. And VFIO has a similar requirement too. Yinghai and I have implemented two different solutions for PCI host bridge hotplug but all rejected by Greg. So it would be great if we could promote a common mechanism to the device core to temporarily disable binding drivers to devices, which could used to support ACPI hotplug, PCI hotplug and VFIO. Regards! Gerry ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-12 15:50 ` Jiang Liu @ 2012-12-12 22:34 ` Rafael J. Wysocki 0 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-12 22:34 UTC (permalink / raw) To: Jiang Liu Cc: Yinghai Lu, Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci, Toshi Kani, Myron Stowe On Wednesday, December 12, 2012 11:50:06 PM Jiang Liu wrote: > On 12/10/2012 07:00 AM, Rafael J. Wysocki wrote: > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > > > Currently, as soon as an ACPI device node object (struct acpi_device) > > is created, the driver core attempts to probe ACPI drivers against > > it. That leads to some unpleasant side effects, like the fact that > > the boot code path for ACPI namespace scanning is different from the > > analogous hot-plug code path (during boot ACPI drivers are not > > present when ACPI device node objects are registered, so they are > > guaranteed not to be probed, which is not the case during hot-plug). > > That, in turn, leads to unnecessary complications in the PCI > > enumeration algorithm. > > > > Reduce the differences between the boot and hot-plug cases by > > splitting the ACPI namespace scanning for devices into two passes, > > such that struct acpi_device objects are registerd in the first > > patch without probing ACPI drivers and the drivers are probed > > against them directly in the second pass. This way ACPI drivers > > can assume that all of the ACPI device node objects in the given > > scope will be registered when their .add() routines run and the > > hot-plug case becomes the same as the boot case from their > > perspective. > > > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > --- > > drivers/acpi/scan.c | 96 +++++++++++++++++++++++++++++++++--------------- > > include/acpi/acpi_bus.h | 1 > > 2 files changed, 68 insertions(+), 29 deletions(-) > > > > Index: linux/include/acpi/acpi_bus.h > > =================================================================== > > --- linux.orig/include/acpi/acpi_bus.h > > +++ linux/include/acpi/acpi_bus.h > > @@ -98,6 +98,7 @@ typedef void (*acpi_op_notify) (struct a > > struct acpi_bus_ops { > > u32 acpi_op_add:1; > > u32 acpi_op_start:1; > > + u32 acpi_op_match:1; > > }; > > > > struct acpi_device_ops { > > Index: linux/drivers/acpi/scan.c > > =================================================================== > > --- linux.orig/drivers/acpi/scan.c > > +++ linux/drivers/acpi/scan.c > > @@ -494,7 +494,8 @@ static int acpi_bus_match(struct device > > struct acpi_device *acpi_dev = to_acpi_device(dev); > > struct acpi_driver *acpi_drv = to_acpi_driver(drv); > > > > - return !acpi_match_device_ids(acpi_dev, acpi_drv->ids); > > + return acpi_dev->bus_ops.acpi_op_match > > + && !acpi_match_device_ids(acpi_dev, acpi_drv->ids); > > } > Hi Rafael, > PCI host bridge hotplug has the same requirement to separate device > enumeration from device driver binding. And VFIO has a similar requirement too. > Yinghai and I have implemented two different solutions for PCI host bridge > hotplug but all rejected by Greg. So it would be great if we could promote > a common mechanism to the device core to temporarily disable binding drivers > to devices, which could used to support ACPI hotplug, PCI hotplug and VFIO. OK, but let's first have a good common use case, I think. I mean, let's implement it in each of these subsystems separately and then show that it leads to simpler code if we move it up to the driver core. Thanks, Rafael -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-09 23:00 ` [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki 2012-12-12 15:50 ` Jiang Liu @ 2012-12-12 16:38 ` Jiang Liu 2012-12-12 22:32 ` Rafael J. Wysocki 2012-12-13 1:00 ` Bjorn Helgaas 2 siblings, 1 reply; 88+ messages in thread From: Jiang Liu @ 2012-12-12 16:38 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe On 12/10/2012 07:00 AM, Rafael J. Wysocki wrote: > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > Currently, as soon as an ACPI device node object (struct acpi_device) snip > @@ -1600,48 +1608,77 @@ static acpi_status acpi_bus_check_add(ac > * We may already have an acpi_device from a previous enumeration. If > * so, we needn't add it again, but we may still have to start it. > */ > - device = NULL; > acpi_bus_get_device(handle, &device); > if (ops->acpi_op_add && !device) { > - acpi_add_single_object(&device, handle, type, sta, ops); > - /* Is the device a known good platform device? */ > - if (device > - && !acpi_match_device_ids(device, acpi_platform_device_ids)) > - acpi_create_platform_device(device); > - } > + struct acpi_bus_ops add_ops = *ops; > > - if (!device) > - return AE_CTRL_DEPTH; > - > - if (ops->acpi_op_start && !(ops->acpi_op_add)) { > - status = acpi_start_single_object(device); > - if (ACPI_FAILURE(status)) > + add_ops.acpi_op_match = 0; > + acpi_add_single_object(&device, handle, type, sta, &add_ops); > + if (!device) > return AE_CTRL_DEPTH; > + > + device->bus_ops.acpi_op_match = 1; > } > > if (!*return_value) > *return_value = device; > + > return AE_OK; > } > > +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl, > + void *context, void **not_used) > +{ > + struct acpi_bus_ops *ops = context; > + struct acpi_device *device; > + acpi_status status = AE_OK; > + > + if (acpi_bus_get_device(handle, &device)) > + return AE_CTRL_DEPTH; > + > + if (ops->acpi_op_add) { > + if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { > + /* This is a known good platform device. */ > + acpi_create_platform_device(device); > + } else { > + int ret = device_attach(&device->dev); > + acpi_hot_add_bind(device); > + if (ret) > + status = AE_CTRL_DEPTH; > + } > + } else if (ops->acpi_op_start) { > + if (ACPI_FAILURE(acpi_start_single_object(device))) > + status = AE_CTRL_DEPTH; > + } > + return status; > +} > + > static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops, > struct acpi_device **child) > { > - acpi_status status; > void *device = NULL; > + acpi_status status; > + int ret = 0; > > status = acpi_bus_check_add(handle, 0, ops, &device); > - if (ACPI_SUCCESS(status)) > + if (ACPI_FAILURE(status)) { > + ret = -ENODEV; > + goto out; > + } > + > + acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, > + acpi_bus_check_add, NULL, ops, &device); > + if (device) > acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, > - acpi_bus_check_add, NULL, ops, &device); > + acpi_bus_probe_start, NULL, ops, NULL); Hi Rafael, Should we call acpi_bus_probe_start for the top device corresponding to "handle" too here? > + else > + ret = -ENODEV; > > + out: > if (child) > *child = device; > > - if (device) > - return 0; > - else > - return -ENODEV; > + return ret; > } > > /* > @@ -1752,6 +1789,7 @@ static int acpi_bus_scan_fixed(void) > memset(&ops, 0, sizeof(ops)); > ops.acpi_op_add = 1; > ops.acpi_op_start = 1; > + ops.acpi_op_match = 1; > > /* > * Enumerate all fixed-feature devices. > > -- > 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 > ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-12 16:38 ` Jiang Liu @ 2012-12-12 22:32 ` Rafael J. Wysocki 2012-12-12 23:43 ` [update][PATCH " Rafael J. Wysocki 2012-12-13 13:05 ` [PATCH " Jiang Liu 0 siblings, 2 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-12 22:32 UTC (permalink / raw) To: Jiang Liu Cc: Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe On Thursday, December 13, 2012 12:38:01 AM Jiang Liu wrote: > On 12/10/2012 07:00 AM, Rafael J. Wysocki wrote: > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > > > Currently, as soon as an ACPI device node object (struct acpi_device) > snip > > > @@ -1600,48 +1608,77 @@ static acpi_status acpi_bus_check_add(ac > > * We may already have an acpi_device from a previous enumeration. If > > * so, we needn't add it again, but we may still have to start it. > > */ > > - device = NULL; > > acpi_bus_get_device(handle, &device); > > if (ops->acpi_op_add && !device) { > > - acpi_add_single_object(&device, handle, type, sta, ops); > > - /* Is the device a known good platform device? */ > > - if (device > > - && !acpi_match_device_ids(device, acpi_platform_device_ids)) > > - acpi_create_platform_device(device); > > - } > > + struct acpi_bus_ops add_ops = *ops; > > > > - if (!device) > > - return AE_CTRL_DEPTH; > > - > > - if (ops->acpi_op_start && !(ops->acpi_op_add)) { > > - status = acpi_start_single_object(device); > > - if (ACPI_FAILURE(status)) > > + add_ops.acpi_op_match = 0; > > + acpi_add_single_object(&device, handle, type, sta, &add_ops); > > + if (!device) > > return AE_CTRL_DEPTH; > > + > > + device->bus_ops.acpi_op_match = 1; > > } > > > > if (!*return_value) > > *return_value = device; > > + > > return AE_OK; > > } > > > > +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl, > > + void *context, void **not_used) > > +{ > > + struct acpi_bus_ops *ops = context; > > + struct acpi_device *device; > > + acpi_status status = AE_OK; > > + > > + if (acpi_bus_get_device(handle, &device)) > > + return AE_CTRL_DEPTH; > > + > > + if (ops->acpi_op_add) { > > + if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { > > + /* This is a known good platform device. */ > > + acpi_create_platform_device(device); > > + } else { > > + int ret = device_attach(&device->dev); > > + acpi_hot_add_bind(device); > > + if (ret) > > + status = AE_CTRL_DEPTH; > > + } > > + } else if (ops->acpi_op_start) { > > + if (ACPI_FAILURE(acpi_start_single_object(device))) > > + status = AE_CTRL_DEPTH; > > + } > > + return status; > > +} > > + > > static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops, > > struct acpi_device **child) > > { > > - acpi_status status; > > void *device = NULL; > > + acpi_status status; > > + int ret = 0; > > > > status = acpi_bus_check_add(handle, 0, ops, &device); > > - if (ACPI_SUCCESS(status)) > > + if (ACPI_FAILURE(status)) { > > + ret = -ENODEV; > > + goto out; > > + } > > + > > + acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, > > + acpi_bus_check_add, NULL, ops, &device); > > + if (device) > > acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, > > - acpi_bus_check_add, NULL, ops, &device); > > + acpi_bus_probe_start, NULL, ops, NULL); > Hi Rafael, > Should we call acpi_bus_probe_start for the top device corresponding to > "handle" too here? Do you mean separately? I don't think so. It will be covered by the namespace walking, won't it? Rafael -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* [update][PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-12 22:32 ` Rafael J. Wysocki @ 2012-12-12 23:43 ` Rafael J. Wysocki 2012-12-13 13:05 ` [PATCH " Jiang Liu 1 sibling, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-12 23:43 UTC (permalink / raw) To: Jiang Liu Cc: Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe On Wednesday, December 12, 2012 11:32:57 PM Rafael J. Wysocki wrote: > On Thursday, December 13, 2012 12:38:01 AM Jiang Liu wrote: > > On 12/10/2012 07:00 AM, Rafael J. Wysocki wrote: > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > > [...] > > > static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops, > > > struct acpi_device **child) > > > { > > > - acpi_status status; > > > void *device = NULL; > > > + acpi_status status; > > > + int ret = 0; > > > > > > status = acpi_bus_check_add(handle, 0, ops, &device); > > > - if (ACPI_SUCCESS(status)) > > > + if (ACPI_FAILURE(status)) { > > > + ret = -ENODEV; > > > + goto out; > > > + } > > > + > > > + acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, > > > + acpi_bus_check_add, NULL, ops, &device); > > > + if (device) > > > acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, > > > - acpi_bus_check_add, NULL, ops, &device); > > > + acpi_bus_probe_start, NULL, ops, NULL); > > Hi Rafael, > > Should we call acpi_bus_probe_start for the top device corresponding to > > "handle" too here? > > Do you mean separately? I don't think so. It will be covered by the namespace > walking, won't it? There is one pitfall I didn't notice here, though. acpi_bus_probe_start() has to ignore errors from acpi_bus_type_and_status(), like acpi_bus_check_add() does, because otherwise the namespace walk may be terminated too early. Updated patch is below and I'll need to change some other patches in the series to take that into account. Thanks, Rafael --- From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Subject: ACPI: Separate adding ACPI device objects from probing ACPI drivers Currently, as soon as an ACPI device node object (struct acpi_device) is created, the driver core attempts to probe ACPI drivers against it. That leads to some unpleasant side effects, like the fact that the boot code path for ACPI namespace scanning is different from the analogous hot-plug code path (during boot ACPI drivers are not present when ACPI device node objects are registered, so they are guaranteed not to be probed, which is not the case during hot-plug). That, in turn, leads to unnecessary complications in the PCI enumeration algorithm. Reduce the differences between the boot and hot-plug cases by splitting the ACPI namespace scanning for devices into two passes, such that struct acpi_device objects are registerd in the first patch without probing ACPI drivers and the drivers are probed against them directly in the second pass. This way ACPI drivers can assume that all of the ACPI device node objects in the given scope will be registered when their .add() routines run and the hot-plug case becomes the same as the boot case from their perspective. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> --- drivers/acpi/scan.c | 105 ++++++++++++++++++++++++++++++++++-------------- include/acpi/acpi_bus.h | 1 2 files changed, 77 insertions(+), 29 deletions(-) Index: linux/include/acpi/acpi_bus.h =================================================================== --- linux.orig/include/acpi/acpi_bus.h +++ linux/include/acpi/acpi_bus.h @@ -98,6 +98,7 @@ typedef void (*acpi_op_notify) (struct a struct acpi_bus_ops { u32 acpi_op_add:1; u32 acpi_op_start:1; + u32 acpi_op_match:1; }; struct acpi_device_ops { Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -494,7 +494,8 @@ static int acpi_bus_match(struct device struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_driver *acpi_drv = to_acpi_driver(drv); - return !acpi_match_device_ids(acpi_dev, acpi_drv->ids); + return acpi_dev->bus_ops.acpi_op_match + && !acpi_match_device_ids(acpi_dev, acpi_drv->ids); } static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) @@ -1418,6 +1419,17 @@ static int acpi_bus_remove(struct acpi_d return 0; } +/* + * acpi_hot_add_bind - Bind _ADR-based devices on hot-add. + * @device: ACPI device node to bind. + */ +static void acpi_hot_add_bind(struct acpi_device *device) +{ + if (device->flags.bus_address + && device->parent && device->parent->ops.bind) + device->parent->ops.bind(device); +} + static int acpi_add_single_object(struct acpi_device **child, acpi_handle handle, int type, unsigned long long sta, @@ -1490,13 +1502,8 @@ static int acpi_add_single_object(struct result = acpi_device_register(device); - /* - * Bind _ADR-Based Devices when hot add - */ - if (device->flags.bus_address) { - if (device->parent && device->parent->ops.bind) - device->parent->ops.bind(device); - } + if (device->bus_ops.acpi_op_match) + acpi_hot_add_bind(device); end: if (!result) { @@ -1522,6 +1529,7 @@ static void acpi_bus_add_power_resource( struct acpi_bus_ops ops = { .acpi_op_add = 1, .acpi_op_start = 1, + .acpi_op_match = 1, }; struct acpi_device *device = NULL; @@ -1574,9 +1582,9 @@ static acpi_status acpi_bus_check_add(ac void *context, void **return_value) { struct acpi_bus_ops *ops = context; + struct acpi_device *device = NULL; int type; unsigned long long sta; - struct acpi_device *device; acpi_status status; int result; @@ -1600,48 +1608,86 @@ static acpi_status acpi_bus_check_add(ac * We may already have an acpi_device from a previous enumeration. If * so, we needn't add it again, but we may still have to start it. */ - device = NULL; acpi_bus_get_device(handle, &device); if (ops->acpi_op_add && !device) { - acpi_add_single_object(&device, handle, type, sta, ops); - /* Is the device a known good platform device? */ - if (device - && !acpi_match_device_ids(device, acpi_platform_device_ids)) - acpi_create_platform_device(device); - } + struct acpi_bus_ops add_ops = *ops; - if (!device) - return AE_CTRL_DEPTH; - - if (ops->acpi_op_start && !(ops->acpi_op_add)) { - status = acpi_start_single_object(device); - if (ACPI_FAILURE(status)) + add_ops.acpi_op_match = 0; + acpi_add_single_object(&device, handle, type, sta, &add_ops); + if (!device) return AE_CTRL_DEPTH; + + device->bus_ops.acpi_op_match = 1; } if (!*return_value) *return_value = device; + return AE_OK; } +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl, + void *context, void **not_used) +{ + struct acpi_bus_ops *ops = context; + acpi_status status = AE_OK; + struct acpi_device *device; + unsigned long long sta_not_used; + int type_not_used; + + /* + * We need to ignore errors ignored by acpi_bus_check_add() to avoid + * terminating namespace walks prematurely. + */ + if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used)) + return AE_OK; + + if (acpi_bus_get_device(handle, &device)) + return AE_CTRL_DEPTH; + + if (ops->acpi_op_add) { + if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { + /* This is a known good platform device. */ + acpi_create_platform_device(device); + } else { + int ret = device_attach(&device->dev); + acpi_hot_add_bind(device); + if (ret) + status = AE_CTRL_DEPTH; + } + } else if (ops->acpi_op_start) { + if (ACPI_FAILURE(acpi_start_single_object(device))) + status = AE_CTRL_DEPTH; + } + return status; +} + static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops, struct acpi_device **child) { - acpi_status status; void *device = NULL; + acpi_status status; + int ret = 0; status = acpi_bus_check_add(handle, 0, ops, &device); - if (ACPI_SUCCESS(status)) + if (ACPI_FAILURE(status)) { + ret = -ENODEV; + goto out; + } + + acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, + acpi_bus_check_add, NULL, ops, &device); + if (device) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - acpi_bus_check_add, NULL, ops, &device); + acpi_bus_probe_start, NULL, ops, NULL); + else + ret = -ENODEV; + out: if (child) *child = device; - if (device) - return 0; - else - return -ENODEV; + return ret; } /* @@ -1752,6 +1798,7 @@ static int acpi_bus_scan_fixed(void) memset(&ops, 0, sizeof(ops)); ops.acpi_op_add = 1; ops.acpi_op_start = 1; + ops.acpi_op_match = 1; /* * Enumerate all fixed-feature devices. -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-12 22:32 ` Rafael J. Wysocki 2012-12-12 23:43 ` [update][PATCH " Rafael J. Wysocki @ 2012-12-13 13:05 ` Jiang Liu 2012-12-13 19:40 ` Rafael J. Wysocki 1 sibling, 1 reply; 88+ messages in thread From: Jiang Liu @ 2012-12-13 13:05 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe On 12/13/2012 06:32 AM, Rafael J. Wysocki wrote: > On Thursday, December 13, 2012 12:38:01 AM Jiang Liu wrote: >> On 12/10/2012 07:00 AM, Rafael J. Wysocki wrote: >>> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> >>> >>> Currently, as soon as an ACPI device node object (struct acpi_device) >> snip >> >>> @@ -1600,48 +1608,77 @@ static acpi_status acpi_bus_check_add(ac >>> * We may already have an acpi_device from a previous enumeration. If >>> * so, we needn't add it again, but we may still have to start it. >>> */ >>> - device = NULL; >>> acpi_bus_get_device(handle, &device); >>> if (ops->acpi_op_add && !device) { >>> - acpi_add_single_object(&device, handle, type, sta, ops); >>> - /* Is the device a known good platform device? */ >>> - if (device >>> - && !acpi_match_device_ids(device, acpi_platform_device_ids)) >>> - acpi_create_platform_device(device); >>> - } >>> + struct acpi_bus_ops add_ops = *ops; >>> >>> - if (!device) >>> - return AE_CTRL_DEPTH; >>> - >>> - if (ops->acpi_op_start && !(ops->acpi_op_add)) { >>> - status = acpi_start_single_object(device); >>> - if (ACPI_FAILURE(status)) >>> + add_ops.acpi_op_match = 0; >>> + acpi_add_single_object(&device, handle, type, sta, &add_ops); >>> + if (!device) >>> return AE_CTRL_DEPTH; >>> + >>> + device->bus_ops.acpi_op_match = 1; >>> } >>> >>> if (!*return_value) >>> *return_value = device; >>> + >>> return AE_OK; >>> } >>> >>> +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl, >>> + void *context, void **not_used) >>> +{ >>> + struct acpi_bus_ops *ops = context; >>> + struct acpi_device *device; >>> + acpi_status status = AE_OK; >>> + >>> + if (acpi_bus_get_device(handle, &device)) >>> + return AE_CTRL_DEPTH; >>> + >>> + if (ops->acpi_op_add) { >>> + if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { >>> + /* This is a known good platform device. */ >>> + acpi_create_platform_device(device); >>> + } else { >>> + int ret = device_attach(&device->dev); >>> + acpi_hot_add_bind(device); >>> + if (ret) >>> + status = AE_CTRL_DEPTH; >>> + } >>> + } else if (ops->acpi_op_start) { >>> + if (ACPI_FAILURE(acpi_start_single_object(device))) >>> + status = AE_CTRL_DEPTH; >>> + } >>> + return status; >>> +} >>> + >>> static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops, >>> struct acpi_device **child) >>> { >>> - acpi_status status; >>> void *device = NULL; >>> + acpi_status status; >>> + int ret = 0; >>> >>> status = acpi_bus_check_add(handle, 0, ops, &device); >>> - if (ACPI_SUCCESS(status)) >>> + if (ACPI_FAILURE(status)) { >>> + ret = -ENODEV; >>> + goto out; >>> + } >>> + >>> + acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, >>> + acpi_bus_check_add, NULL, ops, &device); >>> + if (device) >>> acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, >>> - acpi_bus_check_add, NULL, ops, &device); >>> + acpi_bus_probe_start, NULL, ops, NULL); >> Hi Rafael, >> Should we call acpi_bus_probe_start for the top device corresponding to >> "handle" too here? > > Do you mean separately? I don't think so. It will be covered by the namespace > walking, won't it? Hi Rafael, According to test results from Yijing, we do need to call acpi_bus_probe_start for the top device corresponding to "handle". Comments for acpi_walk_namespace says: /******************************************************************************* * * FUNCTION: acpi_walk_namespace * * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, * starting (and ending) at the object specified by start_handle. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * The callback function is called whenever an object that matches * the type parameter is found. If the callback function returns * a non-zero value, the search is terminated immediately and this * value is returned to the caller. * * The point of this procedure is to provide a generic namespace * a non-zero value, the search is terminated immediately and this * value is returned to the caller. * * The point of this procedure is to provide a generic namespace * walk routine that can be called from multiple places to * provide multiple services; the callback function(s) can be * tailored to each task, whether it is a print function, * a compare function, etc. * ******************************************************************************/ But acpi_ns_walk_namespace() doesn't really call the pre_order_visit and post_order_visit for the start_handle. That means acpi_walk_namespace won't call the callback for the top handle. acpi_ns_walk_namespace(acpi_object_type type, acpi_handle start_node, u32 max_depth, u32 flags, acpi_walk_callback pre_order_visit, acpi_walk_callback post_order_visit, void *context, void **return_value) { ......................................... parent_node = start_node; child_node = acpi_ns_get_next_node(parent_node, NULL); child_type = ACPI_TYPE_ANY; level = 1; /* * Traverse the tree of nodes until we bubble back up to where we * started. When Level is zero, the loop is done because we have * bubbled up to (and passed) the original parent handle (start_entry) */ while (level > 0 && child_node) { ........................................... } > > Rafael > > ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-13 13:05 ` [PATCH " Jiang Liu @ 2012-12-13 19:40 ` Rafael J. Wysocki 0 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-13 19:40 UTC (permalink / raw) To: Jiang Liu Cc: Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe On Thursday, December 13, 2012 09:05:35 PM Jiang Liu wrote: > On 12/13/2012 06:32 AM, Rafael J. Wysocki wrote: > > On Thursday, December 13, 2012 12:38:01 AM Jiang Liu wrote: > >> On 12/10/2012 07:00 AM, Rafael J. Wysocki wrote: > >>> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > >>> > >>> Currently, as soon as an ACPI device node object (struct acpi_device) > >> snip > >> > >>> @@ -1600,48 +1608,77 @@ static acpi_status acpi_bus_check_add(ac > >>> * We may already have an acpi_device from a previous enumeration. If > >>> * so, we needn't add it again, but we may still have to start it. > >>> */ > >>> - device = NULL; > >>> acpi_bus_get_device(handle, &device); > >>> if (ops->acpi_op_add && !device) { > >>> - acpi_add_single_object(&device, handle, type, sta, ops); > >>> - /* Is the device a known good platform device? */ > >>> - if (device > >>> - && !acpi_match_device_ids(device, acpi_platform_device_ids)) > >>> - acpi_create_platform_device(device); > >>> - } > >>> + struct acpi_bus_ops add_ops = *ops; > >>> > >>> - if (!device) > >>> - return AE_CTRL_DEPTH; > >>> - > >>> - if (ops->acpi_op_start && !(ops->acpi_op_add)) { > >>> - status = acpi_start_single_object(device); > >>> - if (ACPI_FAILURE(status)) > >>> + add_ops.acpi_op_match = 0; > >>> + acpi_add_single_object(&device, handle, type, sta, &add_ops); > >>> + if (!device) > >>> return AE_CTRL_DEPTH; > >>> + > >>> + device->bus_ops.acpi_op_match = 1; > >>> } > >>> > >>> if (!*return_value) > >>> *return_value = device; > >>> + > >>> return AE_OK; > >>> } > >>> > >>> +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl, > >>> + void *context, void **not_used) > >>> +{ > >>> + struct acpi_bus_ops *ops = context; > >>> + struct acpi_device *device; > >>> + acpi_status status = AE_OK; > >>> + > >>> + if (acpi_bus_get_device(handle, &device)) > >>> + return AE_CTRL_DEPTH; > >>> + > >>> + if (ops->acpi_op_add) { > >>> + if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { > >>> + /* This is a known good platform device. */ > >>> + acpi_create_platform_device(device); > >>> + } else { > >>> + int ret = device_attach(&device->dev); > >>> + acpi_hot_add_bind(device); > >>> + if (ret) > >>> + status = AE_CTRL_DEPTH; > >>> + } > >>> + } else if (ops->acpi_op_start) { > >>> + if (ACPI_FAILURE(acpi_start_single_object(device))) > >>> + status = AE_CTRL_DEPTH; > >>> + } > >>> + return status; > >>> +} > >>> + > >>> static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops, > >>> struct acpi_device **child) > >>> { > >>> - acpi_status status; > >>> void *device = NULL; > >>> + acpi_status status; > >>> + int ret = 0; > >>> > >>> status = acpi_bus_check_add(handle, 0, ops, &device); > >>> - if (ACPI_SUCCESS(status)) > >>> + if (ACPI_FAILURE(status)) { > >>> + ret = -ENODEV; > >>> + goto out; > >>> + } > >>> + > >>> + acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, > >>> + acpi_bus_check_add, NULL, ops, &device); > >>> + if (device) > >>> acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, > >>> - acpi_bus_check_add, NULL, ops, &device); > >>> + acpi_bus_probe_start, NULL, ops, NULL); > >> Hi Rafael, > >> Should we call acpi_bus_probe_start for the top device corresponding to > >> "handle" too here? > > > > Do you mean separately? I don't think so. It will be covered by the namespace > > walking, won't it? > Hi Rafael, > According to test results from Yijing, we do need to call acpi_bus_probe_start > for the top device corresponding to "handle". > Comments for acpi_walk_namespace says: > /******************************************************************************* > * > * FUNCTION: acpi_walk_namespace > * > * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, > * starting (and ending) at the object specified by start_handle. > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > * The callback function is called whenever an object that matches > * the type parameter is found. If the callback function returns > * a non-zero value, the search is terminated immediately and this > * value is returned to the caller. > * > * The point of this procedure is to provide a generic namespace > * a non-zero value, the search is terminated immediately and this > * value is returned to the caller. > * > * The point of this procedure is to provide a generic namespace > * walk routine that can be called from multiple places to > * provide multiple services; the callback function(s) can be > * tailored to each task, whether it is a print function, > * a compare function, etc. > * > ******************************************************************************/ > > But acpi_ns_walk_namespace() doesn't really call the pre_order_visit and post_order_visit > for the start_handle. That means acpi_walk_namespace won't call the callback for the top > handle. You are right. I'll fix that and send updated series. It looks like Bjorn wants me to rework the changelogs anyway. :-) Thanks, Rafael -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-09 23:00 ` [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki 2012-12-12 15:50 ` Jiang Liu 2012-12-12 16:38 ` Jiang Liu @ 2012-12-13 1:00 ` Bjorn Helgaas 2012-12-13 11:41 ` Rafael J. Wysocki 2 siblings, 1 reply; 88+ messages in thread From: Bjorn Helgaas @ 2012-12-13 1:00 UTC (permalink / raw) To: Rafael J. Wysocki Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe On Sun, Dec 9, 2012 at 4:00 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > Currently, as soon as an ACPI device node object (struct acpi_device) > is created, the driver core attempts to probe ACPI drivers against > it. That leads to some unpleasant side effects, like the fact that > the boot code path for ACPI namespace scanning is different from the > analogous hot-plug code path (during boot ACPI drivers are not > present when ACPI device node objects are registered, so they are > guaranteed not to be probed, which is not the case during hot-plug). > That, in turn, leads to unnecessary complications in the PCI > enumeration algorithm. Can you elaborate a bit on the complications in PCI enumeration? Hopefully this will lead to some simplification in PCI enumeration, but these patches don't go that far (yet). > Reduce the differences between the boot and hot-plug cases by > splitting the ACPI namespace scanning for devices into two passes, > such that struct acpi_device objects are registerd in the first > patch without probing ACPI drivers and the drivers are probed > against them directly in the second pass. This way ACPI drivers > can assume that all of the ACPI device node objects in the given > scope will be registered when their .add() routines run and the > hot-plug case becomes the same as the boot case from their > perspective. If I understand correctly, you're talking about a hierarchical topology where a device, e.g., a bridge, can have subordinate devices below it. In general terms, if a driver claims X, and the driver's add() method can assume that every device below X has already been registered, I guess that means any bridge drivers must be integrated into the core, so the core can enumerate things below the bridge without the driver's help. The PCI core effectively has the P2P bridge driver integrated into it, so that's the way it is already for PCI. I can imagine scenarios, e.g., NTBs, where it's not practical to integrate the bridge driver, so I'm not 100% comfortable with this assumption. But I admit that's a totally hypothetical situation, and there are lots of other obstacles to non-integrated bridge drivers, like the fact that we can't do dynamic resource assignment. s/registerd/registered/ above > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > --- > drivers/acpi/scan.c | 96 +++++++++++++++++++++++++++++++++--------------- > include/acpi/acpi_bus.h | 1 > 2 files changed, 68 insertions(+), 29 deletions(-) > > Index: linux/include/acpi/acpi_bus.h > =================================================================== > --- linux.orig/include/acpi/acpi_bus.h > +++ linux/include/acpi/acpi_bus.h > @@ -98,6 +98,7 @@ typedef void (*acpi_op_notify) (struct a > struct acpi_bus_ops { > u32 acpi_op_add:1; > u32 acpi_op_start:1; > + u32 acpi_op_match:1; > }; > > struct acpi_device_ops { > Index: linux/drivers/acpi/scan.c > =================================================================== > --- linux.orig/drivers/acpi/scan.c > +++ linux/drivers/acpi/scan.c > @@ -494,7 +494,8 @@ static int acpi_bus_match(struct device > struct acpi_device *acpi_dev = to_acpi_device(dev); > struct acpi_driver *acpi_drv = to_acpi_driver(drv); > > - return !acpi_match_device_ids(acpi_dev, acpi_drv->ids); > + return acpi_dev->bus_ops.acpi_op_match > + && !acpi_match_device_ids(acpi_dev, acpi_drv->ids); > } > > static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) > @@ -1418,6 +1419,17 @@ static int acpi_bus_remove(struct acpi_d > return 0; > } > > +/* > + * acpi_hot_add_bind - Bind _ADR-based devices on hot-add. > + * @device: ACPI device node to bind. > + */ > +static void acpi_hot_add_bind(struct acpi_device *device) > +{ > + if (device->flags.bus_address > + && device->parent && device->parent->ops.bind) > + device->parent->ops.bind(device); > +} > + > static int acpi_add_single_object(struct acpi_device **child, > acpi_handle handle, int type, > unsigned long long sta, > @@ -1490,13 +1502,8 @@ static int acpi_add_single_object(struct > > result = acpi_device_register(device); > > - /* > - * Bind _ADR-Based Devices when hot add > - */ > - if (device->flags.bus_address) { > - if (device->parent && device->parent->ops.bind) > - device->parent->ops.bind(device); > - } > + if (device->bus_ops.acpi_op_match) > + acpi_hot_add_bind(device); > > end: > if (!result) { > @@ -1522,6 +1529,7 @@ static void acpi_bus_add_power_resource( > struct acpi_bus_ops ops = { > .acpi_op_add = 1, > .acpi_op_start = 1, > + .acpi_op_match = 1, > }; > struct acpi_device *device = NULL; > > @@ -1574,9 +1582,9 @@ static acpi_status acpi_bus_check_add(ac > void *context, void **return_value) > { > struct acpi_bus_ops *ops = context; > + struct acpi_device *device = NULL; > int type; > unsigned long long sta; > - struct acpi_device *device; > acpi_status status; > int result; > > @@ -1600,48 +1608,77 @@ static acpi_status acpi_bus_check_add(ac > * We may already have an acpi_device from a previous enumeration. If > * so, we needn't add it again, but we may still have to start it. > */ > - device = NULL; > acpi_bus_get_device(handle, &device); > if (ops->acpi_op_add && !device) { > - acpi_add_single_object(&device, handle, type, sta, ops); > - /* Is the device a known good platform device? */ > - if (device > - && !acpi_match_device_ids(device, acpi_platform_device_ids)) > - acpi_create_platform_device(device); > - } > + struct acpi_bus_ops add_ops = *ops; > > - if (!device) > - return AE_CTRL_DEPTH; > - > - if (ops->acpi_op_start && !(ops->acpi_op_add)) { > - status = acpi_start_single_object(device); > - if (ACPI_FAILURE(status)) > + add_ops.acpi_op_match = 0; > + acpi_add_single_object(&device, handle, type, sta, &add_ops); > + if (!device) > return AE_CTRL_DEPTH; > + > + device->bus_ops.acpi_op_match = 1; > } > > if (!*return_value) > *return_value = device; > + > return AE_OK; > } > > +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl, > + void *context, void **not_used) > +{ > + struct acpi_bus_ops *ops = context; > + struct acpi_device *device; > + acpi_status status = AE_OK; > + > + if (acpi_bus_get_device(handle, &device)) > + return AE_CTRL_DEPTH; > + > + if (ops->acpi_op_add) { > + if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { > + /* This is a known good platform device. */ > + acpi_create_platform_device(device); > + } else { > + int ret = device_attach(&device->dev); > + acpi_hot_add_bind(device); > + if (ret) > + status = AE_CTRL_DEPTH; > + } > + } else if (ops->acpi_op_start) { > + if (ACPI_FAILURE(acpi_start_single_object(device))) > + status = AE_CTRL_DEPTH; > + } > + return status; > +} > + > static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops, > struct acpi_device **child) > { > - acpi_status status; > void *device = NULL; > + acpi_status status; > + int ret = 0; > > status = acpi_bus_check_add(handle, 0, ops, &device); > - if (ACPI_SUCCESS(status)) > + if (ACPI_FAILURE(status)) { > + ret = -ENODEV; > + goto out; > + } > + > + acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, > + acpi_bus_check_add, NULL, ops, &device); > + if (device) > acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, > - acpi_bus_check_add, NULL, ops, &device); > + acpi_bus_probe_start, NULL, ops, NULL); > + else > + ret = -ENODEV; > > + out: > if (child) > *child = device; > > - if (device) > - return 0; > - else > - return -ENODEV; > + return ret; > } > > /* > @@ -1752,6 +1789,7 @@ static int acpi_bus_scan_fixed(void) > memset(&ops, 0, sizeof(ops)); > ops.acpi_op_add = 1; > ops.acpi_op_start = 1; > + ops.acpi_op_match = 1; > > /* > * Enumerate all fixed-feature devices. > ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-13 1:00 ` Bjorn Helgaas @ 2012-12-13 11:41 ` Rafael J. Wysocki 0 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-13 11:41 UTC (permalink / raw) To: Bjorn Helgaas Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe On Wednesday, December 12, 2012 06:00:03 PM Bjorn Helgaas wrote: > On Sun, Dec 9, 2012 at 4:00 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > > > Currently, as soon as an ACPI device node object (struct acpi_device) > > is created, the driver core attempts to probe ACPI drivers against > > it. That leads to some unpleasant side effects, like the fact that > > the boot code path for ACPI namespace scanning is different from the > > analogous hot-plug code path (during boot ACPI drivers are not > > present when ACPI device node objects are registered, so they are > > guaranteed not to be probed, which is not the case during hot-plug). > > That, in turn, leads to unnecessary complications in the PCI > > enumeration algorithm. > > Can you elaborate a bit on the complications in PCI enumeration? > Hopefully this will lead to some simplification in PCI enumeration, > but these patches don't go that far (yet). For example, in the hotplug case it is not guaranteed that companion struct acpi_device objects have been created already when struct pci_dev objects are created during acpi_pci_root_add(). This forces us to use acpi_get_pci_dev() in acpi_pci_bind(), which we could avoid otherwise. Moreover, if we knew that the companion struct acpi_device objects existed as soon as in pci_scan_device(), we could just populate the ACPI handle of the struct pci_dev in there and that would allow acpi_platform_notify() later on to skip the bus browsing (due to recent changes just merged in). I suppose we could even get rid of acpi_pci_bind()/acpi_pci_unbind() by integrating that code directly into the initialization/removal code paths. > > Reduce the differences between the boot and hot-plug cases by > > splitting the ACPI namespace scanning for devices into two passes, > > such that struct acpi_device objects are registerd in the first > > patch without probing ACPI drivers and the drivers are probed > > against them directly in the second pass. This way ACPI drivers > > can assume that all of the ACPI device node objects in the given > > scope will be registered when their .add() routines run and the > > hot-plug case becomes the same as the boot case from their > > perspective. > > If I understand correctly, you're talking about a hierarchical > topology where a device, e.g., a bridge, can have subordinate devices > below it. > > In general terms, if a driver claims X, and the driver's add() method > can assume that every device below X has already been registered, I > guess that means any bridge drivers must be integrated into the core, > so the core can enumerate things below the bridge without the driver's > help. Well, I don't quite understand. Do you have an example? We're registering only struct acpi_device things kind of in advance here. I would assume that device drivers would operate on device structures of other types (like struct pci_dev) and those struct acpi_device objects would only be companions of the "physical" device nodes. IOW what we do here is to extract some information from ACPI tables and put it into a number of objects in the device hierarchy (the fact that they are in the device hierarchy allows us to export some of their properties via sysfs easily), but that's about it. How buses/drivers use that information is up to them. And by the way, I think that binding drivers to struct acpi_device objects directly is too much of a shortcut and it leads to more problems than it solves. I'd like to get rid of that eventually. > The PCI core effectively has the P2P bridge driver integrated > into it, so that's the way it is already for PCI. I can imagine > scenarios, e.g., NTBs, where it's not practical to integrate the > bridge driver, so I'm not 100% comfortable with this assumption. But > I admit that's a totally hypothetical situation, and there are lots of > other obstacles to non-integrated bridge drivers, like the fact that > we can't do dynamic resource assignment. Well, precisely. :-) > s/registerd/registered/ above Yup, thanks! Thanks a lot for having a look. :-) Rafael > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > --- > > drivers/acpi/scan.c | 96 +++++++++++++++++++++++++++++++++--------------- > > include/acpi/acpi_bus.h | 1 > > 2 files changed, 68 insertions(+), 29 deletions(-) > > > > Index: linux/include/acpi/acpi_bus.h > > =================================================================== > > --- linux.orig/include/acpi/acpi_bus.h > > +++ linux/include/acpi/acpi_bus.h > > @@ -98,6 +98,7 @@ typedef void (*acpi_op_notify) (struct a > > struct acpi_bus_ops { > > u32 acpi_op_add:1; > > u32 acpi_op_start:1; > > + u32 acpi_op_match:1; > > }; > > > > struct acpi_device_ops { > > Index: linux/drivers/acpi/scan.c > > =================================================================== > > --- linux.orig/drivers/acpi/scan.c > > +++ linux/drivers/acpi/scan.c > > @@ -494,7 +494,8 @@ static int acpi_bus_match(struct device > > struct acpi_device *acpi_dev = to_acpi_device(dev); > > struct acpi_driver *acpi_drv = to_acpi_driver(drv); > > > > - return !acpi_match_device_ids(acpi_dev, acpi_drv->ids); > > + return acpi_dev->bus_ops.acpi_op_match > > + && !acpi_match_device_ids(acpi_dev, acpi_drv->ids); > > } > > > > static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) > > @@ -1418,6 +1419,17 @@ static int acpi_bus_remove(struct acpi_d > > return 0; > > } > > > > +/* > > + * acpi_hot_add_bind - Bind _ADR-based devices on hot-add. > > + * @device: ACPI device node to bind. > > + */ > > +static void acpi_hot_add_bind(struct acpi_device *device) > > +{ > > + if (device->flags.bus_address > > + && device->parent && device->parent->ops.bind) > > + device->parent->ops.bind(device); > > +} > > + > > static int acpi_add_single_object(struct acpi_device **child, > > acpi_handle handle, int type, > > unsigned long long sta, > > @@ -1490,13 +1502,8 @@ static int acpi_add_single_object(struct > > > > result = acpi_device_register(device); > > > > - /* > > - * Bind _ADR-Based Devices when hot add > > - */ > > - if (device->flags.bus_address) { > > - if (device->parent && device->parent->ops.bind) > > - device->parent->ops.bind(device); > > - } > > + if (device->bus_ops.acpi_op_match) > > + acpi_hot_add_bind(device); > > > > end: > > if (!result) { > > @@ -1522,6 +1529,7 @@ static void acpi_bus_add_power_resource( > > struct acpi_bus_ops ops = { > > .acpi_op_add = 1, > > .acpi_op_start = 1, > > + .acpi_op_match = 1, > > }; > > struct acpi_device *device = NULL; > > > > @@ -1574,9 +1582,9 @@ static acpi_status acpi_bus_check_add(ac > > void *context, void **return_value) > > { > > struct acpi_bus_ops *ops = context; > > + struct acpi_device *device = NULL; > > int type; > > unsigned long long sta; > > - struct acpi_device *device; > > acpi_status status; > > int result; > > > > @@ -1600,48 +1608,77 @@ static acpi_status acpi_bus_check_add(ac > > * We may already have an acpi_device from a previous enumeration. If > > * so, we needn't add it again, but we may still have to start it. > > */ > > - device = NULL; > > acpi_bus_get_device(handle, &device); > > if (ops->acpi_op_add && !device) { > > - acpi_add_single_object(&device, handle, type, sta, ops); > > - /* Is the device a known good platform device? */ > > - if (device > > - && !acpi_match_device_ids(device, acpi_platform_device_ids)) > > - acpi_create_platform_device(device); > > - } > > + struct acpi_bus_ops add_ops = *ops; > > > > - if (!device) > > - return AE_CTRL_DEPTH; > > - > > - if (ops->acpi_op_start && !(ops->acpi_op_add)) { > > - status = acpi_start_single_object(device); > > - if (ACPI_FAILURE(status)) > > + add_ops.acpi_op_match = 0; > > + acpi_add_single_object(&device, handle, type, sta, &add_ops); > > + if (!device) > > return AE_CTRL_DEPTH; > > + > > + device->bus_ops.acpi_op_match = 1; > > } > > > > if (!*return_value) > > *return_value = device; > > + > > return AE_OK; > > } > > > > +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl, > > + void *context, void **not_used) > > +{ > > + struct acpi_bus_ops *ops = context; > > + struct acpi_device *device; > > + acpi_status status = AE_OK; > > + > > + if (acpi_bus_get_device(handle, &device)) > > + return AE_CTRL_DEPTH; > > + > > + if (ops->acpi_op_add) { > > + if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { > > + /* This is a known good platform device. */ > > + acpi_create_platform_device(device); > > + } else { > > + int ret = device_attach(&device->dev); > > + acpi_hot_add_bind(device); > > + if (ret) > > + status = AE_CTRL_DEPTH; > > + } > > + } else if (ops->acpi_op_start) { > > + if (ACPI_FAILURE(acpi_start_single_object(device))) > > + status = AE_CTRL_DEPTH; > > + } > > + return status; > > +} > > + > > static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops, > > struct acpi_device **child) > > { > > - acpi_status status; > > void *device = NULL; > > + acpi_status status; > > + int ret = 0; > > > > status = acpi_bus_check_add(handle, 0, ops, &device); > > - if (ACPI_SUCCESS(status)) > > + if (ACPI_FAILURE(status)) { > > + ret = -ENODEV; > > + goto out; > > + } > > + > > + acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, > > + acpi_bus_check_add, NULL, ops, &device); > > + if (device) > > acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, > > - acpi_bus_check_add, NULL, ops, &device); > > + acpi_bus_probe_start, NULL, ops, NULL); > > + else > > + ret = -ENODEV; > > > > + out: > > if (child) > > *child = device; > > > > - if (device) > > - return 0; > > - else > > - return -ENODEV; > > + return ret; > > } > > > > /* > > @@ -1752,6 +1789,7 @@ static int acpi_bus_scan_fixed(void) > > memset(&ops, 0, sizeof(ops)); > > ops.acpi_op_add = 1; > > ops.acpi_op_start = 1; > > + ops.acpi_op_match = 1; > > > > /* > > * Enumerate all fixed-feature devices. > > -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH 2/6] ACPI: Change the ordering of PCI root bridge driver registrarion 2012-12-09 22:58 [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Rafael J. Wysocki 2012-12-09 23:00 ` [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki @ 2012-12-09 23:00 ` Rafael J. Wysocki 2012-12-13 1:00 ` Bjorn Helgaas 2012-12-09 23:01 ` [PATCH 3/6] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different Rafael J. Wysocki ` (5 subsequent siblings) 7 siblings, 1 reply; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-09 23:00 UTC (permalink / raw) To: Bjorn Helgaas Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Devices created by acpi_create_platform_device() sometimes may need to be added to the device hierarchy as children of PCI bridges. For this purpose, however, the struct pci_dev objects representing those bridges need to exist before the platform devices in question are added, but this is only possible if the PCI root bridge driver is registered before the initial scanning of the ACPI namespace (that driver's .add() routine creates the required struct pci_dev objects). For this reason, call acpi_pci_root_init() from acpi_scan_init() before scanning the ACPI namespace for the first time instead of running it from a separate subsys initcall. Since the previous patch has changed the ACPI namespace scanning algorithm, this change does not affect the PCI root bridge driver's functionality during boot. It also makes the situation during boot more similar to the situation during hot-plug (in which the PCI root bridge driver is always present) and so it helps to reduce arbitary differences between the hot-plug and boot PCI root bridge code. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> --- drivers/acpi/internal.h | 1 + drivers/acpi/pci_root.c | 4 +--- drivers/acpi/scan.c | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) Index: linux/drivers/acpi/internal.h =================================================================== --- linux.orig/drivers/acpi/internal.h +++ linux/drivers/acpi/internal.h @@ -67,6 +67,7 @@ struct acpi_ec { extern struct acpi_ec *first_ec; +int acpi_pci_root_init(void); int acpi_ec_init(void); int acpi_ec_ecdt_probe(void); int acpi_boot_ec_enable(void); Index: linux/drivers/acpi/pci_root.c =================================================================== --- linux.orig/drivers/acpi/pci_root.c +++ linux/drivers/acpi/pci_root.c @@ -674,7 +674,7 @@ static int acpi_pci_root_remove(struct a return 0; } -static int __init acpi_pci_root_init(void) +int __init acpi_pci_root_init(void) { acpi_hest_init(); @@ -687,5 +687,3 @@ static int __init acpi_pci_root_init(voi return 0; } - -subsys_initcall(acpi_pci_root_init); Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -1828,6 +1828,7 @@ int __init acpi_scan_init(void) } acpi_power_init(); + acpi_pci_root_init(); /* * Enumerate devices in the ACPI namespace. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 2/6] ACPI: Change the ordering of PCI root bridge driver registrarion 2012-12-09 23:00 ` [PATCH 2/6] ACPI: Change the ordering of PCI root bridge driver registrarion Rafael J. Wysocki @ 2012-12-13 1:00 ` Bjorn Helgaas 2012-12-13 12:19 ` Rafael J. Wysocki 0 siblings, 1 reply; 88+ messages in thread From: Bjorn Helgaas @ 2012-12-13 1:00 UTC (permalink / raw) To: Rafael J. Wysocki Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe On Sun, Dec 9, 2012 at 4:00 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > Devices created by acpi_create_platform_device() sometimes may need > to be added to the device hierarchy as children of PCI bridges. An example of this hierarchy would help to understand it. > For > this purpose, however, the struct pci_dev objects representing those > bridges need to exist before the platform devices in question are > added, but this is only possible if the PCI root bridge driver is > registered before the initial scanning of the ACPI namespace > (that driver's .add() routine creates the required struct pci_dev > objects). The previous patch (1/6) registers all acpi_device objects in the first pass, then calls driver .add() methods in the second pass. And here you're saying the .add() method has to run before platform devices are added. So I guess the acpi_device objects are added first, then the .add() methods called, then the platform devices added? I think the call sequence looks like this: acpi_bus_scan acpi_walk_namespace acpi_bus_check_add acpi_add_single_object device = kzalloc(sizeof(struct acpi_device, ...) # (1) acpi_devices created here acpi_walk_namespace acpi_bus_match_device if (acpi_match_device_ids(device, acpi_platform_device_ids)) acpi_create_platform_device # (3) platform device added here else device_attach # (2) driver .add() called here acpi_hot_add_bind (1) happens first because it's in the first acpi_walk_namespace(). (2) happens before (3) because acpi_walk_namespace() calls acpi_bus_match_device() in preorder (node visited before its children) It always seems like a bit of a hack when we have to call out a driver specifically like this. Are these special platform devices unique to PCI? What would happen with these platform devices that are children of PCI bridges if we booted a kernel without a PCI host bridge driver? You would hope that the PCI host bridge and everything under it would just be ignored, and I assume that in that case, these platform devices should be ignored, too. I know we can't build ACPI without PCI today, but AFAIK that's mostly to reduce the configuration/testing matrix, not a design restriction. So I guess I'm trying to figure out whether the ACPI core should be made smart enough to deal with these PCI-related platform devices (as you're doing in these patches), or whether there should be something in the PCI host bridge driver that deals with them. > For this reason, call acpi_pci_root_init() from acpi_scan_init() > before scanning the ACPI namespace for the first time instead of > running it from a separate subsys initcall. Since the previous patch > has changed the ACPI namespace scanning algorithm, this change does > not affect the PCI root bridge driver's functionality during boot. > It also makes the situation during boot more similar to the situation > during hot-plug (in which the PCI root bridge driver is always > present) and so it helps to reduce arbitary differences between > the hot-plug and boot PCI root bridge code. > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > --- > drivers/acpi/internal.h | 1 + > drivers/acpi/pci_root.c | 4 +--- > drivers/acpi/scan.c | 1 + > 3 files changed, 3 insertions(+), 3 deletions(-) > > Index: linux/drivers/acpi/internal.h > =================================================================== > --- linux.orig/drivers/acpi/internal.h > +++ linux/drivers/acpi/internal.h > @@ -67,6 +67,7 @@ struct acpi_ec { > > extern struct acpi_ec *first_ec; > > +int acpi_pci_root_init(void); > int acpi_ec_init(void); > int acpi_ec_ecdt_probe(void); > int acpi_boot_ec_enable(void); > Index: linux/drivers/acpi/pci_root.c > =================================================================== > --- linux.orig/drivers/acpi/pci_root.c > +++ linux/drivers/acpi/pci_root.c > @@ -674,7 +674,7 @@ static int acpi_pci_root_remove(struct a > return 0; > } > > -static int __init acpi_pci_root_init(void) > +int __init acpi_pci_root_init(void) > { > acpi_hest_init(); > > @@ -687,5 +687,3 @@ static int __init acpi_pci_root_init(voi > > return 0; > } > - > -subsys_initcall(acpi_pci_root_init); > Index: linux/drivers/acpi/scan.c > =================================================================== > --- linux.orig/drivers/acpi/scan.c > +++ linux/drivers/acpi/scan.c > @@ -1828,6 +1828,7 @@ int __init acpi_scan_init(void) > } > > acpi_power_init(); > + acpi_pci_root_init(); > > /* > * Enumerate devices in the ACPI namespace. > ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 2/6] ACPI: Change the ordering of PCI root bridge driver registrarion 2012-12-13 1:00 ` Bjorn Helgaas @ 2012-12-13 12:19 ` Rafael J. Wysocki 0 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-13 12:19 UTC (permalink / raw) To: Bjorn Helgaas Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe On Wednesday, December 12, 2012 06:00:19 PM Bjorn Helgaas wrote: > On Sun, Dec 9, 2012 at 4:00 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > > > Devices created by acpi_create_platform_device() sometimes may need > > to be added to the device hierarchy as children of PCI bridges. > > An example of this hierarchy would help to understand it. Well, that's only hypothetical, but it goes like this. There's a PCIe root complex with root ports. Some devices are connected to those root ports, but for whatever (the heck) the reason they are not visible to the kernel as PCI devices (ie. their config spaces are unavailable by any usual means). They are, however, listed in the ACPI namespace and their MMIO ranges can be extracted through _CRS. Still, the root ports themselves are visible to the kernel as normal PCIe devices (I know, that's silly). So, in order to maintain (for example) the correct runtime suspend ordering, we need to represent those "hidden" devices as device nodes being the children of the PCIe root ports' device nodes. > > > For this purpose, however, the struct pci_dev objects representing those > > bridges need to exist before the platform devices in question are > > added, but this is only possible if the PCI root bridge driver is > > registered before the initial scanning of the ACPI namespace > > (that driver's .add() routine creates the required struct pci_dev > > objects). > > The previous patch (1/6) registers all acpi_device objects in the > first pass, then calls driver .add() methods in the second pass. And > here you're saying the .add() method has to run before platform > devices are added. So I guess the acpi_device objects are added > first, then the .add() methods called, then the platform devices > added? No, the platform devices are added in the same pass in which the .add() methods are called, because we know that we won't call an .add() method for any struct acpi_device that we'll be creating a platform device for. These things are mutually exclusive. Of course, we could add a separate pass for adding the platform devices, but then we'd need to teach ACPI PNP that it shouldn't create PNP device objects for the ACPI devices we'll be creating platform devices for. > I think the call sequence looks like this: > > acpi_bus_scan > acpi_walk_namespace > acpi_bus_check_add > acpi_add_single_object > device = kzalloc(sizeof(struct acpi_device, ...) # (1) > acpi_devices created here > acpi_walk_namespace > acpi_bus_match_device > if (acpi_match_device_ids(device, acpi_platform_device_ids)) > acpi_create_platform_device # (3) platform device added here > else > device_attach # (2) driver .add() called here > acpi_hot_add_bind > > (1) happens first because it's in the first acpi_walk_namespace(). Yes. > (2) happens before (3) because acpi_walk_namespace() calls > acpi_bus_match_device() in preorder (node visited before its children) Yes. > It always seems like a bit of a hack when we have to call out a driver > specifically like this. Are these special platform devices unique to > PCI? I believe so. > What would happen with these platform devices that are children > of PCI bridges if we booted a kernel without a PCI host bridge driver? > You would hope that the PCI host bridge and everything under it would > just be ignored, and I assume that in that case, these platform > devices should be ignored, too. That's a good question and I believe the answer depends on what's there in the ACPI namespace. Namely, if the ACPI namespace lists the PCI parents of those platform devices, we should at least enable them to decode resources for the children (which we should be doing in general for any parents listed in the ACPI namespace). > I know we can't build ACPI without PCI today, but AFAIK that's mostly > to reduce the configuration/testing matrix, not a design restriction. > So I guess I'm trying to figure out whether the ACPI core should be > made smart enough to deal with these PCI-related platform devices (as > you're doing in these patches), or whether there should be something > in the PCI host bridge driver that deals with them. Well, I'm actually not making the ACPI core any smarter. :-) What I'm really doing is just to say "let's register the PCI root bridge driver before walking the namespace, because we may want it to kick in before anything else". And if it doesn't kick in at all, so be it. That also makes the "boot" case be more similar to the "hotplug" case in which the root bridge driver is always present, so I think this is worth doing anyway. And moreover, I think we should register _all_ ACPI drivers (except for modular ones, but those are not really suitable for hotplug anyway) before walking the namespace to make the "boot" and "hotplug" cases look the same. This patch just does this for the root bridge on the "one item at a time" basis, but I don't see a reason why not to do that for other ACPI drivers. Thanks, Rafael > > For this reason, call acpi_pci_root_init() from acpi_scan_init() > > before scanning the ACPI namespace for the first time instead of > > running it from a separate subsys initcall. Since the previous patch > > has changed the ACPI namespace scanning algorithm, this change does > > not affect the PCI root bridge driver's functionality during boot. > > It also makes the situation during boot more similar to the situation > > during hot-plug (in which the PCI root bridge driver is always > > present) and so it helps to reduce arbitary differences between > > the hot-plug and boot PCI root bridge code. > > > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > --- > > drivers/acpi/internal.h | 1 + > > drivers/acpi/pci_root.c | 4 +--- > > drivers/acpi/scan.c | 1 + > > 3 files changed, 3 insertions(+), 3 deletions(-) > > > > Index: linux/drivers/acpi/internal.h > > =================================================================== > > --- linux.orig/drivers/acpi/internal.h > > +++ linux/drivers/acpi/internal.h > > @@ -67,6 +67,7 @@ struct acpi_ec { > > > > extern struct acpi_ec *first_ec; > > > > +int acpi_pci_root_init(void); > > int acpi_ec_init(void); > > int acpi_ec_ecdt_probe(void); > > int acpi_boot_ec_enable(void); > > Index: linux/drivers/acpi/pci_root.c > > =================================================================== > > --- linux.orig/drivers/acpi/pci_root.c > > +++ linux/drivers/acpi/pci_root.c > > @@ -674,7 +674,7 @@ static int acpi_pci_root_remove(struct a > > return 0; > > } > > > > -static int __init acpi_pci_root_init(void) > > +int __init acpi_pci_root_init(void) > > { > > acpi_hest_init(); > > > > @@ -687,5 +687,3 @@ static int __init acpi_pci_root_init(voi > > > > return 0; > > } > > - > > -subsys_initcall(acpi_pci_root_init); > > Index: linux/drivers/acpi/scan.c > > =================================================================== > > --- linux.orig/drivers/acpi/scan.c > > +++ linux/drivers/acpi/scan.c > > @@ -1828,6 +1828,7 @@ int __init acpi_scan_init(void) > > } > > > > acpi_power_init(); > > + acpi_pci_root_init(); > > > > /* > > * Enumerate devices in the ACPI namespace. > > -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH 3/6] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different 2012-12-09 22:58 [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Rafael J. Wysocki 2012-12-09 23:00 ` [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki 2012-12-09 23:00 ` [PATCH 2/6] ACPI: Change the ordering of PCI root bridge driver registrarion Rafael J. Wysocki @ 2012-12-09 23:01 ` Rafael J. Wysocki 2012-12-13 0:11 ` [Update][PATCH " Rafael J. Wysocki 2012-12-09 23:02 ` [PATCH 4/6] ACPI: Reduce the usage of struct acpi_bus_ops Rafael J. Wysocki ` (4 subsequent siblings) 7 siblings, 1 reply; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-09 23:01 UTC (permalink / raw) To: Bjorn Helgaas Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> The current ACPI namespace scanning code suggests that acpi_bus_add() and acpi_bus_start() share some code. In fact, however, they are completely different code paths, so refactor the code to make that distinction visibly clear. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> --- drivers/acpi/scan.c | 57 ++++++++++++++++++++++++---------------------------- 1 file changed, 27 insertions(+), 30 deletions(-) Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -1626,28 +1626,22 @@ static acpi_status acpi_bus_check_add(ac return AE_OK; } -static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl, - void *context, void **not_used) +static acpi_status acpi_bus_match_device(acpi_handle handle, u32 lvl, + void *not_used, void **ret_not_used) { - struct acpi_bus_ops *ops = context; struct acpi_device *device; acpi_status status = AE_OK; if (acpi_bus_get_device(handle, &device)) return AE_CTRL_DEPTH; - if (ops->acpi_op_add) { - if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { - /* This is a known good platform device. */ - acpi_create_platform_device(device); - } else { - int ret = device_attach(&device->dev); - acpi_hot_add_bind(device); - if (ret) - status = AE_CTRL_DEPTH; - } - } else if (ops->acpi_op_start) { - if (ACPI_FAILURE(acpi_start_single_object(device))) + if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { + /* This is a known good platform device. */ + acpi_create_platform_device(device); + } else { + int ret = device_attach(&device->dev); + acpi_hot_add_bind(device); + if (ret) status = AE_CTRL_DEPTH; } return status; @@ -1670,7 +1664,7 @@ static int acpi_bus_scan(acpi_handle han acpi_bus_check_add, NULL, ops, &device); if (device) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - acpi_bus_probe_start, NULL, ops, NULL); + acpi_bus_match_device, NULL, NULL, NULL); else ret = -ENODEV; @@ -1697,31 +1691,34 @@ int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent, acpi_handle handle, int type) { - struct acpi_bus_ops ops; - - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_add = 1; + struct acpi_bus_ops ops = { .acpi_op_add = 1, }; return acpi_bus_scan(handle, &ops, child); } EXPORT_SYMBOL(acpi_bus_add); -int acpi_bus_start(struct acpi_device *device) +static acpi_status acpi_bus_start_device(acpi_handle handle, u32 lvl, + void *not_used, void **ret_not_used) { - struct acpi_bus_ops ops; - int result; + struct acpi_device *device; + acpi_status status; - if (!device) - return -EINVAL; + if (acpi_bus_get_device(handle, &device)) + return AE_CTRL_DEPTH; - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_start = 1; + status = acpi_start_single_object(device); + return ACPI_SUCCESS(status) ? status : AE_CTRL_DEPTH; +} - result = acpi_bus_scan(device->handle, &ops, NULL); +int acpi_bus_start(struct acpi_device *device) +{ + if (!device) + return -EINVAL; + acpi_walk_namespace(ACPI_TYPE_ANY, device->handle, ACPI_UINT32_MAX, + acpi_bus_start_device, NULL, NULL, NULL); acpi_update_all_gpes(); - - return result; + return 0; } EXPORT_SYMBOL(acpi_bus_start); ^ permalink raw reply [flat|nested] 88+ messages in thread
* [Update][PATCH 3/6] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different 2012-12-09 23:01 ` [PATCH 3/6] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different Rafael J. Wysocki @ 2012-12-13 0:11 ` Rafael J. Wysocki 0 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-13 0:11 UTC (permalink / raw) To: Bjorn Helgaas Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Subject: ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different The current ACPI namespace scanning code suggests that acpi_bus_add() and acpi_bus_start() share some code. In fact, however, they are completely different code paths (except for the initial checks), so refactor the code to make that distinction visibly clear. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> --- Update is needed, because of a potential bug found in [1/6], as described here: https://lkml.org/lkml/2012/12/12/460 Thanks, Rafael --- drivers/acpi/scan.c | 66 ++++++++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 30 deletions(-) Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -1626,10 +1626,9 @@ static acpi_status acpi_bus_check_add(ac return AE_OK; } -static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl, - void *context, void **not_used) +static acpi_status acpi_bus_match_device(acpi_handle handle, u32 lvl, + void *not_used, void **ret_not_used) { - struct acpi_bus_ops *ops = context; acpi_status status = AE_OK; struct acpi_device *device; unsigned long long sta_not_used; @@ -1645,18 +1644,13 @@ static acpi_status acpi_bus_probe_start( if (acpi_bus_get_device(handle, &device)) return AE_CTRL_DEPTH; - if (ops->acpi_op_add) { - if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { - /* This is a known good platform device. */ - acpi_create_platform_device(device); - } else { - int ret = device_attach(&device->dev); - acpi_hot_add_bind(device); - if (ret) - status = AE_CTRL_DEPTH; - } - } else if (ops->acpi_op_start) { - if (ACPI_FAILURE(acpi_start_single_object(device))) + if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { + /* This is a known good platform device. */ + acpi_create_platform_device(device); + } else { + int ret = device_attach(&device->dev); + acpi_hot_add_bind(device); + if (ret) status = AE_CTRL_DEPTH; } return status; @@ -1679,7 +1673,7 @@ static int acpi_bus_scan(acpi_handle han acpi_bus_check_add, NULL, ops, &device); if (device) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - acpi_bus_probe_start, NULL, ops, NULL); + acpi_bus_match_device, NULL, NULL, NULL); else ret = -ENODEV; @@ -1706,31 +1700,43 @@ int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent, acpi_handle handle, int type) { - struct acpi_bus_ops ops; - - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_add = 1; + struct acpi_bus_ops ops = { .acpi_op_add = 1, }; return acpi_bus_scan(handle, &ops, child); } EXPORT_SYMBOL(acpi_bus_add); -int acpi_bus_start(struct acpi_device *device) +static acpi_status acpi_bus_start_device(acpi_handle handle, u32 lvl, + void *not_used, void **ret_not_used) { - struct acpi_bus_ops ops; - int result; + struct acpi_device *device; + unsigned long long sta_not_used; + int type_not_used; + acpi_status status; - if (!device) - return -EINVAL; + /* + * Ignore errors ignored by acpi_bus_check_add() to avoid terminating + * namespace walks prematurely. + */ + if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used)) + return AE_OK; - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_start = 1; + if (acpi_bus_get_device(handle, &device)) + return AE_CTRL_DEPTH; - result = acpi_bus_scan(device->handle, &ops, NULL); + status = acpi_start_single_object(device); + return ACPI_SUCCESS(status) ? status : AE_CTRL_DEPTH; +} - acpi_update_all_gpes(); +int acpi_bus_start(struct acpi_device *device) +{ + if (!device) + return -EINVAL; - return result; + acpi_walk_namespace(ACPI_TYPE_ANY, device->handle, ACPI_UINT32_MAX, + acpi_bus_start_device, NULL, NULL, NULL); + acpi_update_all_gpes(); + return 0; } EXPORT_SYMBOL(acpi_bus_start); ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH 4/6] ACPI: Reduce the usage of struct acpi_bus_ops 2012-12-09 22:58 [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Rafael J. Wysocki ` (2 preceding siblings ...) 2012-12-09 23:01 ` [PATCH 3/6] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different Rafael J. Wysocki @ 2012-12-09 23:02 ` Rafael J. Wysocki 2012-12-09 23:03 ` [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type Rafael J. Wysocki ` (3 subsequent siblings) 7 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-09 23:02 UTC (permalink / raw) To: Bjorn Helgaas Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Objects of type struct acpi_bus_ops are currently used to pass information between different parts of the ACPI namespace scanning code, sometimes in quite convoluted ways. It turns out that that is not necessary in some cases, so simplify the code by reducing the utilization of struct acpi_bus_ops objects where clearly possible. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> --- drivers/acpi/scan.c | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -1527,7 +1527,6 @@ end: static void acpi_bus_add_power_resource(acpi_handle handle) { struct acpi_bus_ops ops = { - .acpi_op_add = 1, .acpi_op_start = 1, .acpi_op_match = 1, }; @@ -1581,7 +1580,6 @@ static int acpi_bus_type_and_status(acpi static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl, void *context, void **return_value) { - struct acpi_bus_ops *ops = context; struct acpi_device *device = NULL; int type; unsigned long long sta; @@ -1609,11 +1607,13 @@ static acpi_status acpi_bus_check_add(ac * so, we needn't add it again, but we may still have to start it. */ acpi_bus_get_device(handle, &device); - if (ops->acpi_op_add && !device) { - struct acpi_bus_ops add_ops = *ops; + if (!device) { + struct acpi_bus_ops ops = { + .acpi_op_start = !!context, + .acpi_op_match = 0, + }; - add_ops.acpi_op_match = 0; - acpi_add_single_object(&device, handle, type, sta, &add_ops); + acpi_add_single_object(&device, handle, type, sta, &ops); if (!device) return AE_CTRL_DEPTH; @@ -1647,21 +1647,21 @@ static acpi_status acpi_bus_match_device return status; } -static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops, +static int acpi_bus_scan(acpi_handle handle, bool start, struct acpi_device **child) { void *device = NULL; acpi_status status; int ret = 0; - status = acpi_bus_check_add(handle, 0, ops, &device); + status = acpi_bus_check_add(handle, 0, (void *)start, &device); if (ACPI_FAILURE(status)) { ret = -ENODEV; goto out; } acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - acpi_bus_check_add, NULL, ops, &device); + acpi_bus_check_add, NULL, (void *)start, &device); if (device) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, acpi_bus_match_device, NULL, NULL, NULL); @@ -1691,9 +1691,7 @@ int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent, acpi_handle handle, int type) { - struct acpi_bus_ops ops = { .acpi_op_add = 1, }; - - return acpi_bus_scan(handle, &ops, child); + return acpi_bus_scan(handle, false, child); } EXPORT_SYMBOL(acpi_bus_add); @@ -1781,12 +1779,10 @@ static int acpi_bus_scan_fixed(void) { int result = 0; struct acpi_device *device = NULL; - struct acpi_bus_ops ops; - - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_add = 1; - ops.acpi_op_start = 1; - ops.acpi_op_match = 1; + struct acpi_bus_ops ops = { + .acpi_op_start = 1, + .acpi_op_match = 1, + }; /* * Enumerate all fixed-feature devices. @@ -1812,11 +1808,6 @@ static int acpi_bus_scan_fixed(void) int __init acpi_scan_init(void) { int result; - struct acpi_bus_ops ops; - - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_add = 1; - ops.acpi_op_start = 1; result = bus_register(&acpi_bus_type); if (result) { @@ -1830,7 +1821,7 @@ int __init acpi_scan_init(void) /* * Enumerate devices in the ACPI namespace. */ - result = acpi_bus_scan(ACPI_ROOT_OBJECT, &ops, &acpi_root); + result = acpi_bus_scan(ACPI_ROOT_OBJECT, true, &acpi_root); if (!result) result = acpi_bus_scan_fixed(); ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type 2012-12-09 22:58 [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Rafael J. Wysocki ` (3 preceding siblings ...) 2012-12-09 23:02 ` [PATCH 4/6] ACPI: Reduce the usage of struct acpi_bus_ops Rafael J. Wysocki @ 2012-12-09 23:03 ` Rafael J. Wysocki 2012-12-10 5:34 ` Yinghai Lu 2012-12-09 23:04 ` [PATCH 6/6] ACPI: Change the ordering of acpi_bus_check_add() Rafael J. Wysocki ` (2 subsequent siblings) 7 siblings, 1 reply; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-09 23:03 UTC (permalink / raw) To: Bjorn Helgaas Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Notice that one member of struct acpi_bus_ops, acpi_op_add, is not used anywhere any more and the relationship between its remaining members, acpi_op_match and acpi_op_start, is such that it doesn't make sense to set the latter without setting the former at the same time. Therefore, replace struct acpi_bus_ops with new a enum type, enum acpi_bus_add_type, with three values, ACPI_BUS_ADD_BASIC, ACPI_BUS_ADD_MATCH, ACPI_BUS_ADD_START, corresponding to both acpi_op_match and acpi_op_start unset, acpi_op_match set and acpi_op_start unset, and both acpi_op_match and acpi_op_start set, respectively. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> --- drivers/acpi/scan.c | 35 ++++++++++++----------------------- include/acpi/acpi_bus.h | 15 ++++++++------- 2 files changed, 20 insertions(+), 30 deletions(-) Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -494,7 +494,7 @@ static int acpi_bus_match(struct device struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_driver *acpi_drv = to_acpi_driver(drv); - return acpi_dev->bus_ops.acpi_op_match + return acpi_dev->add_type >= ACPI_BUS_ADD_MATCH && !acpi_match_device_ids(acpi_dev, acpi_drv->ids); } @@ -580,7 +580,7 @@ static int acpi_device_probe(struct devi ret = acpi_bus_driver_init(acpi_dev, acpi_drv); if (!ret) { - if (acpi_dev->bus_ops.acpi_op_start) + if (acpi_dev->add_type == ACPI_BUS_ADD_START) acpi_start_single_object(acpi_dev); if (acpi_drv->ops.notify) { @@ -1433,7 +1433,7 @@ static void acpi_hot_add_bind(struct acp static int acpi_add_single_object(struct acpi_device **child, acpi_handle handle, int type, unsigned long long sta, - struct acpi_bus_ops *ops) + enum acpi_bus_add_type add_type) { int result; struct acpi_device *device; @@ -1449,7 +1449,7 @@ static int acpi_add_single_object(struct device->device_type = type; device->handle = handle; device->parent = acpi_bus_get_parent(handle); - device->bus_ops = *ops; /* workround for not call .start */ + device->add_type = add_type; STRUCT_TO_INT(device->status) = sta; acpi_device_get_busid(device); @@ -1502,7 +1502,7 @@ static int acpi_add_single_object(struct result = acpi_device_register(device); - if (device->bus_ops.acpi_op_match) + if (device->add_type >= ACPI_BUS_ADD_MATCH) acpi_hot_add_bind(device); end: @@ -1526,16 +1526,12 @@ end: static void acpi_bus_add_power_resource(acpi_handle handle) { - struct acpi_bus_ops ops = { - .acpi_op_start = 1, - .acpi_op_match = 1, - }; struct acpi_device *device = NULL; acpi_bus_get_device(handle, &device); if (!device) acpi_add_single_object(&device, handle, ACPI_BUS_TYPE_POWER, - ACPI_STA_DEFAULT, &ops); + ACPI_STA_DEFAULT, ACPI_BUS_ADD_START); } static int acpi_bus_type_and_status(acpi_handle handle, int *type, @@ -1608,16 +1604,13 @@ static acpi_status acpi_bus_check_add(ac */ acpi_bus_get_device(handle, &device); if (!device) { - struct acpi_bus_ops ops = { - .acpi_op_start = !!context, - .acpi_op_match = 0, - }; - - acpi_add_single_object(&device, handle, type, sta, &ops); + acpi_add_single_object(&device, handle, type, sta, + ACPI_BUS_ADD_BASIC); if (!device) return AE_CTRL_DEPTH; - device->bus_ops.acpi_op_match = 1; + device->add_type = context ? + ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH; } if (!*return_value) @@ -1779,10 +1772,6 @@ static int acpi_bus_scan_fixed(void) { int result = 0; struct acpi_device *device = NULL; - struct acpi_bus_ops ops = { - .acpi_op_start = 1, - .acpi_op_match = 1, - }; /* * Enumerate all fixed-feature devices. @@ -1791,7 +1780,7 @@ static int acpi_bus_scan_fixed(void) result = acpi_add_single_object(&device, NULL, ACPI_BUS_TYPE_POWER_BUTTON, ACPI_STA_DEFAULT, - &ops); + ACPI_BUS_ADD_START); device_init_wakeup(&device->dev, true); } @@ -1799,7 +1788,7 @@ static int acpi_bus_scan_fixed(void) result = acpi_add_single_object(&device, NULL, ACPI_BUS_TYPE_SLEEP_BUTTON, ACPI_STA_DEFAULT, - &ops); + ACPI_BUS_ADD_START); } return result; Index: linux/include/acpi/acpi_bus.h =================================================================== --- linux.orig/include/acpi/acpi_bus.h +++ linux/include/acpi/acpi_bus.h @@ -63,6 +63,13 @@ acpi_get_physical_device_location(acpi_h #define ACPI_BUS_FILE_ROOT "acpi" extern struct proc_dir_entry *acpi_root_dir; +enum acpi_bus_add_type { + ACPI_BUS_ADD_BASIC = 0, + ACPI_BUS_ADD_MATCH, + ACPI_BUS_ADD_START, + ACPI_BUS_ADD_TYPE_COUNT +}; + enum acpi_bus_removal_type { ACPI_BUS_REMOVAL_NORMAL = 0, ACPI_BUS_REMOVAL_EJECT, @@ -95,12 +102,6 @@ typedef int (*acpi_op_bind) (struct acpi typedef int (*acpi_op_unbind) (struct acpi_device * device); typedef void (*acpi_op_notify) (struct acpi_device * device, u32 event); -struct acpi_bus_ops { - u32 acpi_op_add:1; - u32 acpi_op_start:1; - u32 acpi_op_match:1; -}; - struct acpi_device_ops { acpi_op_add add; acpi_op_remove remove; @@ -284,7 +285,7 @@ struct acpi_device { struct acpi_driver *driver; void *driver_data; struct device dev; - struct acpi_bus_ops bus_ops; /* workaround for different code path for hotplug */ + enum acpi_bus_add_type add_type; /* how to handle adding */ enum acpi_bus_removal_type removal_type; /* indicate for different removal type */ u8 physical_node_count; struct list_head physical_node_list; ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type 2012-12-09 23:03 ` [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type Rafael J. Wysocki @ 2012-12-10 5:34 ` Yinghai Lu 2012-12-10 14:46 ` Rafael J. Wysocki 0 siblings, 1 reply; 88+ messages in thread From: Yinghai Lu @ 2012-12-10 5:34 UTC (permalink / raw) To: Rafael J. Wysocki, Greg Kroah-Hartman Cc: Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci, Toshi Kani, Myron Stowe On Sun, Dec 9, 2012 at 3:03 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > Notice that one member of struct acpi_bus_ops, acpi_op_add, is not > used anywhere any more and the relationship between its remaining > members, acpi_op_match and acpi_op_start, is such that it doesn't > make sense to set the latter without setting the former at the same > time. Therefore, replace struct acpi_bus_ops with new a enum type, > enum acpi_bus_add_type, with three values, ACPI_BUS_ADD_BASIC, > ACPI_BUS_ADD_MATCH, ACPI_BUS_ADD_START, corresponding to > both acpi_op_match and acpi_op_start unset, acpi_op_match set and > acpi_op_start unset, and both acpi_op_match and acpi_op_start set, > respectively. > Can we expand the BUS_ADD_* concept to other devices instead of just acpi_device? aka we should let struct device has this add_type field. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type 2012-12-10 5:34 ` Yinghai Lu @ 2012-12-10 14:46 ` Rafael J. Wysocki 2012-12-10 17:07 ` Yinghai Lu 0 siblings, 1 reply; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-10 14:46 UTC (permalink / raw) To: Yinghai Lu Cc: Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci, Toshi Kani, Myron Stowe On Sunday, December 09, 2012 09:34:42 PM Yinghai Lu wrote: > On Sun, Dec 9, 2012 at 3:03 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > > > Notice that one member of struct acpi_bus_ops, acpi_op_add, is not > > used anywhere any more and the relationship between its remaining > > members, acpi_op_match and acpi_op_start, is such that it doesn't > > make sense to set the latter without setting the former at the same > > time. Therefore, replace struct acpi_bus_ops with new a enum type, > > enum acpi_bus_add_type, with three values, ACPI_BUS_ADD_BASIC, > > ACPI_BUS_ADD_MATCH, ACPI_BUS_ADD_START, corresponding to > > both acpi_op_match and acpi_op_start unset, acpi_op_match set and > > acpi_op_start unset, and both acpi_op_match and acpi_op_start set, > > respectively. > > > > Can we expand the BUS_ADD_* concept to other devices instead of just > acpi_device? > > aka we should let struct device has this add_type field. Having done that in ACPI to cover our use case here, we can try to move it into struct device if there are use cases beyond ACPI that can't be covered by using deferred driver probing. Thanks, Rafael -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type 2012-12-10 14:46 ` Rafael J. Wysocki @ 2012-12-10 17:07 ` Yinghai Lu 2012-12-10 22:47 ` Rafael J. Wysocki 0 siblings, 1 reply; 88+ messages in thread From: Yinghai Lu @ 2012-12-10 17:07 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci, Toshi Kani, Myron Stowe On Mon, Dec 10, 2012 at 6:46 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > On Sunday, December 09, 2012 09:34:42 PM Yinghai Lu wrote: >> >> Can we expand the BUS_ADD_* concept to other devices instead of just >> acpi_device? >> >> aka we should let struct device has this add_type field. > > Having done that in ACPI to cover our use case here, we can try to move it > into struct device if there are use cases beyond ACPI that can't be covered > by using deferred driver probing. pci device for hotplug have same problem. need to delay driver attach for them too. also BUS_ADD_MATCH and BUS_ADD_START are duplicated. old add are separated to adding all devices to tree and then matching work to load the drivers. so _START is not needed anymore, only user.start in pci_root driver should be removed. code in .start could be moved .add without problem. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type 2012-12-10 17:07 ` Yinghai Lu @ 2012-12-10 22:47 ` Rafael J. Wysocki 2012-12-10 23:09 ` Rafael J. Wysocki 2012-12-10 23:22 ` Yinghai Lu 0 siblings, 2 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-10 22:47 UTC (permalink / raw) To: Yinghai Lu Cc: Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci, Toshi Kani, Myron Stowe On Monday, December 10, 2012 09:07:06 AM Yinghai Lu wrote: > On Mon, Dec 10, 2012 at 6:46 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > > On Sunday, December 09, 2012 09:34:42 PM Yinghai Lu wrote: > >> > >> Can we expand the BUS_ADD_* concept to other devices instead of just > >> acpi_device? > >> > >> aka we should let struct device has this add_type field. > > > > Having done that in ACPI to cover our use case here, we can try to move it > > into struct device if there are use cases beyond ACPI that can't be covered > > by using deferred driver probing. > > pci device for hotplug have same problem. need to delay driver attach > for them too. OK, I'll take a look. Any pointers to speed that up? > also BUS_ADD_MATCH and BUS_ADD_START are duplicated. Not at the moment, they do different things as code goes. > old add are separated to adding all devices to tree and then matching > work to load the drivers. > > so _START is not needed anymore, only user.start in pci_root driver > should be removed. > code in .start could be moved .add without problem. Yes, I'm going to do that as the next step. I didn't want this particular patchset to grow too big. I'll post another one on top of it if people don't have problems with this one. Thanks, Rafael -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type 2012-12-10 22:47 ` Rafael J. Wysocki @ 2012-12-10 23:09 ` Rafael J. Wysocki 2012-12-10 23:14 ` Yinghai Lu 2012-12-10 23:22 ` Yinghai Lu 1 sibling, 1 reply; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-10 23:09 UTC (permalink / raw) To: Yinghai Lu Cc: Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci, Toshi Kani, Myron Stowe On Monday, December 10, 2012 11:47:27 PM Rafael J. Wysocki wrote: > On Monday, December 10, 2012 09:07:06 AM Yinghai Lu wrote: > > On Mon, Dec 10, 2012 at 6:46 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > > > On Sunday, December 09, 2012 09:34:42 PM Yinghai Lu wrote: > > >> > > >> Can we expand the BUS_ADD_* concept to other devices instead of just > > >> acpi_device? > > >> > > >> aka we should let struct device has this add_type field. > > > > > > Having done that in ACPI to cover our use case here, we can try to move it > > > into struct device if there are use cases beyond ACPI that can't be covered > > > by using deferred driver probing. > > > > pci device for hotplug have same problem. need to delay driver attach > > for them too. > > OK, I'll take a look. Any pointers to speed that up? > > > also BUS_ADD_MATCH and BUS_ADD_START are duplicated. > > Not at the moment, they do different things as code goes. > > > old add are separated to adding all devices to tree and then matching > > work to load the drivers. > > > > so _START is not needed anymore, only user.start in pci_root driver > > should be removed. > > code in .start could be moved .add without problem. > > Yes, I'm going to do that as the next step. I didn't want this particular > patchset to grow too big. I'll post another one on top of it if people > don't have problems with this one. By the way, can you please remind me where you wanted to put the pci_bus_add_devices() and why? Rafael -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type 2012-12-10 23:09 ` Rafael J. Wysocki @ 2012-12-10 23:14 ` Yinghai Lu 2012-12-11 1:02 ` Rafael J. Wysocki 0 siblings, 1 reply; 88+ messages in thread From: Yinghai Lu @ 2012-12-10 23:14 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci, Toshi Kani, Myron Stowe On Mon, Dec 10, 2012 at 3:09 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > On Monday, December 10, 2012 11:47:27 PM Rafael J. Wysocki wrote: >> On Monday, December 10, 2012 09:07:06 AM Yinghai Lu wrote: >> > On Mon, Dec 10, 2012 at 6:46 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote: >> > > On Sunday, December 09, 2012 09:34:42 PM Yinghai Lu wrote: >> > >> >> > >> Can we expand the BUS_ADD_* concept to other devices instead of just >> > >> acpi_device? >> > >> >> > >> aka we should let struct device has this add_type field. >> > > >> > > Having done that in ACPI to cover our use case here, we can try to move it >> > > into struct device if there are use cases beyond ACPI that can't be covered >> > > by using deferred driver probing. >> > >> > pci device for hotplug have same problem. need to delay driver attach >> > for them too. >> >> OK, I'll take a look. Any pointers to speed that up? >> >> > also BUS_ADD_MATCH and BUS_ADD_START are duplicated. >> >> Not at the moment, they do different things as code goes. >> >> > old add are separated to adding all devices to tree and then matching >> > work to load the drivers. >> > >> > so _START is not needed anymore, only user.start in pci_root driver >> > should be removed. >> > code in .start could be moved .add without problem. >> >> Yes, I'm going to do that as the next step. I didn't want this particular >> patchset to grow too big. I'll post another one on top of it if people >> don't have problems with this one. > > By the way, can you please remind me where you wanted to put the > pci_bus_add_devices() and why? > please check my for-pci-next branch at http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=shortlog;h=refs/heads/for-pci-next that includes delay loading acpi driver and pci driver. http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=8c031eabbdc83dd4d93933b82d96b55d038bcb64 PCI: prepare to use device drivers_autoprobe to delay attach drivers http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=40a12dc8942a8ed02bfbf75ee1ffbfbdf1511b45 PCI: Use device_add for device and bus early http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=8af9b4c250091c30afedeb2e7f14fca06997c811 ACPI: add drivers_autoprobe in struct acpi_device http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=ae498e157e9dc8794932562b2f885ddc3a1a229a ACPI: use device drivers_autoprobe to delay loading acpi drivers http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=6bee785b563a0b0e311e188321b1160593d5e6ee PCI, ACPI: Remove not used acpi_pci_root_start() http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=f467a1cd18a07a250be8527b94612fd4a654fbd1 ACPI: remove acpi_op_start workaround ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type 2012-12-10 23:14 ` Yinghai Lu @ 2012-12-11 1:02 ` Rafael J. Wysocki 2012-12-11 1:28 ` Rafael J. Wysocki 0 siblings, 1 reply; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-11 1:02 UTC (permalink / raw) To: Yinghai Lu Cc: Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci, Toshi Kani, Myron Stowe On Monday, December 10, 2012 03:14:32 PM Yinghai Lu wrote: > On Mon, Dec 10, 2012 at 3:09 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > > On Monday, December 10, 2012 11:47:27 PM Rafael J. Wysocki wrote: > >> On Monday, December 10, 2012 09:07:06 AM Yinghai Lu wrote: > >> > On Mon, Dec 10, 2012 at 6:46 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > >> > > On Sunday, December 09, 2012 09:34:42 PM Yinghai Lu wrote: > >> > >> > >> > >> Can we expand the BUS_ADD_* concept to other devices instead of just > >> > >> acpi_device? > >> > >> > >> > >> aka we should let struct device has this add_type field. > >> > > > >> > > Having done that in ACPI to cover our use case here, we can try to move it > >> > > into struct device if there are use cases beyond ACPI that can't be covered > >> > > by using deferred driver probing. > >> > > >> > pci device for hotplug have same problem. need to delay driver attach > >> > for them too. > >> > >> OK, I'll take a look. Any pointers to speed that up? > >> > >> > also BUS_ADD_MATCH and BUS_ADD_START are duplicated. > >> > >> Not at the moment, they do different things as code goes. > >> > >> > old add are separated to adding all devices to tree and then matching > >> > work to load the drivers. > >> > > >> > so _START is not needed anymore, only user.start in pci_root driver > >> > should be removed. > >> > code in .start could be moved .add without problem. > >> > >> Yes, I'm going to do that as the next step. I didn't want this particular > >> patchset to grow too big. I'll post another one on top of it if people > >> don't have problems with this one. > > > > By the way, can you please remind me where you wanted to put the > > pci_bus_add_devices() and why? > > > > please check my for-pci-next branch at > http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=shortlog;h=refs/heads/for-pci-next > > that includes delay loading acpi driver and pci driver. > > http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=8c031eabbdc83dd4d93933b82d96b55d038bcb64 > PCI: prepare to use device drivers_autoprobe to delay attach drivers > > http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=40a12dc8942a8ed02bfbf75ee1ffbfbdf1511b45 > PCI: Use device_add for device and bus early > > http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=8af9b4c250091c30afedeb2e7f14fca06997c811 > ACPI: add drivers_autoprobe in struct acpi_device > > http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=ae498e157e9dc8794932562b2f885ddc3a1a229a > ACPI: use device drivers_autoprobe to delay loading acpi drivers > > http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=6bee785b563a0b0e311e188321b1160593d5e6ee > PCI, ACPI: Remove not used acpi_pci_root_start() > > http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=f467a1cd18a07a250be8527b94612fd4a654fbd1 > ACPI: remove acpi_op_start workaround OK, thanks for the pointers. I actually see more differences between our patchsets. For one example, you seem to have left the parent->ops.bind() stuff in acpi_add_single_object() which calls it even drivers_autoprobe is set. Is that the case, or am I missing anything? Rafael -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type 2012-12-11 1:02 ` Rafael J. Wysocki @ 2012-12-11 1:28 ` Rafael J. Wysocki 2012-12-11 2:26 ` Yinghai Lu 0 siblings, 1 reply; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-11 1:28 UTC (permalink / raw) To: Yinghai Lu Cc: Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci, Toshi Kani, Myron Stowe On Tuesday, December 11, 2012 02:02:14 AM Rafael J. Wysocki wrote: > On Monday, December 10, 2012 03:14:32 PM Yinghai Lu wrote: > > On Mon, Dec 10, 2012 at 3:09 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > > > On Monday, December 10, 2012 11:47:27 PM Rafael J. Wysocki wrote: > > >> On Monday, December 10, 2012 09:07:06 AM Yinghai Lu wrote: > > >> > On Mon, Dec 10, 2012 at 6:46 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > > >> > > On Sunday, December 09, 2012 09:34:42 PM Yinghai Lu wrote: > > >> > >> > > >> > >> Can we expand the BUS_ADD_* concept to other devices instead of just > > >> > >> acpi_device? > > >> > >> > > >> > >> aka we should let struct device has this add_type field. > > >> > > > > >> > > Having done that in ACPI to cover our use case here, we can try to move it > > >> > > into struct device if there are use cases beyond ACPI that can't be covered > > >> > > by using deferred driver probing. > > >> > > > >> > pci device for hotplug have same problem. need to delay driver attach > > >> > for them too. > > >> > > >> OK, I'll take a look. Any pointers to speed that up? > > >> > > >> > also BUS_ADD_MATCH and BUS_ADD_START are duplicated. > > >> > > >> Not at the moment, they do different things as code goes. > > >> > > >> > old add are separated to adding all devices to tree and then matching > > >> > work to load the drivers. > > >> > > > >> > so _START is not needed anymore, only user.start in pci_root driver > > >> > should be removed. > > >> > code in .start could be moved .add without problem. > > >> > > >> Yes, I'm going to do that as the next step. I didn't want this particular > > >> patchset to grow too big. I'll post another one on top of it if people > > >> don't have problems with this one. > > > > > > By the way, can you please remind me where you wanted to put the > > > pci_bus_add_devices() and why? > > > > > > > please check my for-pci-next branch at > > http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=shortlog;h=refs/heads/for-pci-next > > > > that includes delay loading acpi driver and pci driver. > > > > http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=8c031eabbdc83dd4d93933b82d96b55d038bcb64 > > PCI: prepare to use device drivers_autoprobe to delay attach drivers > > > > http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=40a12dc8942a8ed02bfbf75ee1ffbfbdf1511b45 > > PCI: Use device_add for device and bus early > > > > http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=8af9b4c250091c30afedeb2e7f14fca06997c811 > > ACPI: add drivers_autoprobe in struct acpi_device > > > > http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=ae498e157e9dc8794932562b2f885ddc3a1a229a > > ACPI: use device drivers_autoprobe to delay loading acpi drivers > > > > http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=6bee785b563a0b0e311e188321b1160593d5e6ee > > PCI, ACPI: Remove not used acpi_pci_root_start() > > > > http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=f467a1cd18a07a250be8527b94612fd4a654fbd1 > > ACPI: remove acpi_op_start workaround > > OK, thanks for the pointers. I actually see more differences between our > patchsets. For one example, you seem to have left the parent->ops.bind() > stuff in acpi_add_single_object() which calls it even drivers_autoprobe is > set. Sorry, that should have been "which calls it even when drivers_autoprobe is not set". I need to be more careful. > Is that the case, or am I missing anything? Thanks, Rafael -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type 2012-12-11 1:28 ` Rafael J. Wysocki @ 2012-12-11 2:26 ` Yinghai Lu 2012-12-11 12:45 ` Rafael J. Wysocki 2012-12-11 15:09 ` Jiang Liu 0 siblings, 2 replies; 88+ messages in thread From: Yinghai Lu @ 2012-12-11 2:26 UTC (permalink / raw) To: Rafael J. Wysocki, Jiang Liu Cc: Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci, Toshi Kani, Myron Stowe On Mon, Dec 10, 2012 at 5:28 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: >> >> OK, thanks for the pointers. I actually see more differences between our >> patchsets. For one example, you seem to have left the parent->ops.bind() >> stuff in acpi_add_single_object() which calls it even drivers_autoprobe is >> set. > > Sorry, that should have been "which calls it even when drivers_autoprobe is > not set". I need to be more careful. > oh, Jiang Liu had one patch to remove that workaround. http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=b40dba80c2b8395570d8357e6b3f417c27c84504 ACPI/pci-bind: remove bind/unbind callbacks from acpi_device_ops Maybe you can review that patches in my for-pci-next2... those are ACPI related anyway. those patches have been there for a while, and Bjorn did not have time to digest them. or you prefer I resend updated version as huge whole patchset? Thanks Yinghai ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type 2012-12-11 2:26 ` Yinghai Lu @ 2012-12-11 12:45 ` Rafael J. Wysocki 2012-12-11 15:09 ` Jiang Liu 1 sibling, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-11 12:45 UTC (permalink / raw) To: Yinghai Lu Cc: Jiang Liu, Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci, Toshi Kani, Myron Stowe On Monday, December 10, 2012 06:26:08 PM Yinghai Lu wrote: > On Mon, Dec 10, 2012 at 5:28 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > >> > >> OK, thanks for the pointers. I actually see more differences between our > >> patchsets. For one example, you seem to have left the parent->ops.bind() > >> stuff in acpi_add_single_object() which calls it even drivers_autoprobe is > >> set. > > > > Sorry, that should have been "which calls it even when drivers_autoprobe is > > not set". I need to be more careful. > > > > oh, Jiang Liu had one patch to remove that workaround. > > http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=b40dba80c2b8395570d8357e6b3f417c27c84504 > > ACPI/pci-bind: remove bind/unbind callbacks from acpi_device_ops OK, so I'm looking at the current code, which for me is the master branch of the linux-pm.git tree (the linux-next branch is the same ATM), and I'm not seeing acpi_pci_unbind_cb() in there. So surely this patch applies to something different, right? In which case I wonder what reason there is for me to look at it at all? Besides, I think it may be done differently and in a more straightforward way. Namely, on top of my current patchset, it is guaranteed that not only struct pci_dev objects will always be registered after the companion struct acpi_device ones, but also they always will be *created* after those companion objects have been registered. So in principle we can populate a new struct pci_dev's ACPI handle as soon as in pci_scan_device(), next to pci_set_of_node(). Then, we can do something like acpi_pci_bind(), although without the whole acpi_get_pci_dev() nonsense, in pci_setup_device(), in which case we won't need to do it anywhere else. As an added benefit, acpi_platform_notify() would then see a populated ACPI handle in that struct pci_dev when finally registering the PCI device, so it wouldn't need to do the whole acpi_find_bridge_device() and type->find_device() dance. > Maybe you can review that patches in my for-pci-next2... > those are ACPI related anyway. I can, provided that (1) they are based on top of my tree or v3.7 and (2) they don't conflict with patches we're currently discussing. > those patches have been there for a while, and Bjorn did not have time > to digest them. Well, Bjorn's review bandwidth is limited and we need to take that into account. > or you prefer I resend updated version as huge whole patchset? No, no huge patchsets, please. Let's take one step at a time, so that everyone involved/interested can understand what's going on, OK? My review capacity also is not unlimited, mind you. I can't promise I'll have the time to review more than a few patches a day (where "a few" is rather less than "several"). Thanks, Rafael -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type 2012-12-11 2:26 ` Yinghai Lu 2012-12-11 12:45 ` Rafael J. Wysocki @ 2012-12-11 15:09 ` Jiang Liu 2012-12-11 18:30 ` Rafael J. Wysocki 1 sibling, 1 reply; 88+ messages in thread From: Jiang Liu @ 2012-12-11 15:09 UTC (permalink / raw) To: Yinghai Lu Cc: Rafael J. Wysocki, Jiang Liu, Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci, Toshi Kani, Myron Stowe Hi Rafael, I have worked out a patch set to clean up ACPI/PCI related notifications, please refer to http://www.spinics.net/lists/linux-pci/msg17822.html The patchset doesn't apply cleanly to Bjorn's latest pci-next tree. I will help to rebase it if needed. Regards! Gerry On 12/11/2012 10:26 AM, Yinghai Lu wrote: > On Mon, Dec 10, 2012 at 5:28 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: >>> >>> OK, thanks for the pointers. I actually see more differences between our >>> patchsets. For one example, you seem to have left the parent->ops.bind() >>> stuff in acpi_add_single_object() which calls it even drivers_autoprobe is >>> set. >> >> Sorry, that should have been "which calls it even when drivers_autoprobe is >> not set". I need to be more careful. >> > > oh, Jiang Liu had one patch to remove that workaround. > > http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=b40dba80c2b8395570d8357e6b3f417c27c84504 > > ACPI/pci-bind: remove bind/unbind callbacks from acpi_device_ops > > Maybe you can review that patches in my for-pci-next2... > those are ACPI related anyway. > > those patches have been there for a while, and Bjorn did not have time > to digest them. > > or you prefer I resend updated version as huge whole patchset? > > Thanks > > Yinghai > -- > 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 > ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type 2012-12-11 15:09 ` Jiang Liu @ 2012-12-11 18:30 ` Rafael J. Wysocki 2012-12-12 14:34 ` Yijing Wang 0 siblings, 1 reply; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-11 18:30 UTC (permalink / raw) To: Jiang Liu Cc: Yinghai Lu, Jiang Liu, Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci, Toshi Kani, Myron Stowe Hi Gerry, On Tuesday, December 11, 2012 11:09:06 PM Jiang Liu wrote: > Hi Rafael, > I have worked out a patch set to clean up ACPI/PCI related notifications, > please refer to > http://www.spinics.net/lists/linux-pci/msg17822.html > The patchset doesn't apply cleanly to Bjorn's latest pci-next tree. I will > help to rebase it if needed. I have reviewed the patches and I think they make sense overall. However, the statement that acpi_pci_bind()/acpi_pci_unbind() are used to maintain PCI-ACPI binding relationships is quite inaccurate, because all what these functions do is to (1) add/remove ACPI PM notifiers to/from PCI devices and (2) retrieve the _PRT information for bridges from ACPI tables. In fact, the *binding* itself is managed by the code in drivers/acpi/glue.c. Also, please have a look at my suggestion in the last reply to Yinghai: http://marc.info/?l=linux-pci&m=135522965707752&w=2 In fact, I think we can go even further than that. Namely, if we populate the ACPI handle of the device in pci_scan_device(), then we can just move the PM notifier and wakeup setup to platform_pci_wakeup_init(), where it should be (we'll also need to add a corresponding _exit() function, then, but that'll be much cleaner anyway). Then, the remaining thing would be to ensure that _PRT entries are parsed as appropriate somewhere around pci_init_capabilities(). Also, I wonder if you can help test the $subject patchset on a system with hardware PCI hotplug (preferably on top of the linux-pm.git/master branch)? Rafael -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type 2012-12-11 18:30 ` Rafael J. Wysocki @ 2012-12-12 14:34 ` Yijing Wang 2012-12-12 15:05 ` Jiang Liu 0 siblings, 1 reply; 88+ messages in thread From: Yijing Wang @ 2012-12-12 14:34 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Jiang Liu, Yinghai Lu, Jiang Liu, Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci, Toshi Kani, Myron Stowe 于 2012-12-12 2:30, Rafael J. Wysocki 写道: > Hi Gerry, > > On Tuesday, December 11, 2012 11:09:06 PM Jiang Liu wrote: >> Hi Rafael, >> I have worked out a patch set to clean up ACPI/PCI related notifications, >> please refer to >> http://www.spinics.net/lists/linux-pci/msg17822.html >> The patchset doesn't apply cleanly to Bjorn's latest pci-next tree. I will >> help to rebase it if needed. > > I have reviewed the patches and I think they make sense overall. However, > the statement that acpi_pci_bind()/acpi_pci_unbind() are used to maintain > PCI-ACPI binding relationships is quite inaccurate, because all what these > functions do is to (1) add/remove ACPI PM notifiers to/from PCI devices and > (2) retrieve the _PRT information for bridges from ACPI tables. In fact, > the *binding* itself is managed by the code in drivers/acpi/glue.c. > > Also, please have a look at my suggestion in the last reply to Yinghai: > > http://marc.info/?l=linux-pci&m=135522965707752&w=2 > > In fact, I think we can go even further than that. Namely, if we populate the > ACPI handle of the device in pci_scan_device(), then we can just move the PM > notifier and wakeup setup to platform_pci_wakeup_init(), where it should be > (we'll also need to add a corresponding _exit() function, then, but that'll be > much cleaner anyway). > > Then, the remaining thing would be to ensure that _PRT entries are parsed > as appropriate somewhere around pci_init_capabilities(). > > Also, I wonder if you can help test the $subject patchset on a system with > hardware PCI hotplug (preferably on top of the linux-pm.git/master branch)? > Hi Rafael, We are doing test for this series patches, I will send out the test result as soon. Thanks! Yijing ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type 2012-12-12 14:34 ` Yijing Wang @ 2012-12-12 15:05 ` Jiang Liu 2012-12-12 22:39 ` Rafael J. Wysocki 0 siblings, 1 reply; 88+ messages in thread From: Jiang Liu @ 2012-12-12 15:05 UTC (permalink / raw) To: Yijing Wang Cc: Rafael J. Wysocki, Yinghai Lu, Jiang Liu, Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci, Toshi Kani, Myron Stowe On 12/12/2012 10:34 PM, Yijing Wang wrote: > 于 2012-12-12 2:30, Rafael J. Wysocki 写道: >> Hi Gerry, >> >> On Tuesday, December 11, 2012 11:09:06 PM Jiang Liu wrote: >>> Hi Rafael, >>> I have worked out a patch set to clean up ACPI/PCI related notifications, >>> please refer to >>> http://www.spinics.net/lists/linux-pci/msg17822.html >>> The patchset doesn't apply cleanly to Bjorn's latest pci-next tree. I will >>> help to rebase it if needed. >> >> I have reviewed the patches and I think they make sense overall. However, >> the statement that acpi_pci_bind()/acpi_pci_unbind() are used to maintain >> PCI-ACPI binding relationships is quite inaccurate, because all what these >> functions do is to (1) add/remove ACPI PM notifiers to/from PCI devices and >> (2) retrieve the _PRT information for bridges from ACPI tables. In fact, >> the *binding* itself is managed by the code in drivers/acpi/glue.c. >> >> Also, please have a look at my suggestion in the last reply to Yinghai: >> >> http://marc.info/?l=linux-pci&m=135522965707752&w=2 >> >> In fact, I think we can go even further than that. Namely, if we populate the >> ACPI handle of the device in pci_scan_device(), then we can just move the PM >> notifier and wakeup setup to platform_pci_wakeup_init(), where it should be >> (we'll also need to add a corresponding _exit() function, then, but that'll be >> much cleaner anyway). >> >> Then, the remaining thing would be to ensure that _PRT entries are parsed >> as appropriate somewhere around pci_init_capabilities(). >> >> Also, I wonder if you can help test the $subject patchset on a system with >> hardware PCI hotplug (preferably on top of the linux-pm.git/master branch)? >> > Hi Rafael, > We are doing test for this series patches, I will send out the test result as soon. Hi Rafael, We have tried to merge your patchset with IOH hotplug patchsets from Yinghai, and obviously it's not a ease task and we have run into panics. We will try to find some ways to test your patchset only next step. Thanks! > > Thanks! > Yijing > > > ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type 2012-12-12 15:05 ` Jiang Liu @ 2012-12-12 22:39 ` Rafael J. Wysocki 0 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-12 22:39 UTC (permalink / raw) To: Jiang Liu Cc: Yijing Wang, Yinghai Lu, Jiang Liu, Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci, Toshi Kani, Myron Stowe On Wednesday, December 12, 2012 11:05:15 PM Jiang Liu wrote: > On 12/12/2012 10:34 PM, Yijing Wang wrote: > > 于 2012-12-12 2:30, Rafael J. Wysocki 写道: > >> Hi Gerry, > >> > >> On Tuesday, December 11, 2012 11:09:06 PM Jiang Liu wrote: > >>> Hi Rafael, > >>> I have worked out a patch set to clean up ACPI/PCI related notifications, > >>> please refer to > >>> http://www.spinics.net/lists/linux-pci/msg17822.html > >>> The patchset doesn't apply cleanly to Bjorn's latest pci-next tree. I will > >>> help to rebase it if needed. > >> > >> I have reviewed the patches and I think they make sense overall. However, > >> the statement that acpi_pci_bind()/acpi_pci_unbind() are used to maintain > >> PCI-ACPI binding relationships is quite inaccurate, because all what these > >> functions do is to (1) add/remove ACPI PM notifiers to/from PCI devices and > >> (2) retrieve the _PRT information for bridges from ACPI tables. In fact, > >> the *binding* itself is managed by the code in drivers/acpi/glue.c. > >> > >> Also, please have a look at my suggestion in the last reply to Yinghai: > >> > >> http://marc.info/?l=linux-pci&m=135522965707752&w=2 > >> > >> In fact, I think we can go even further than that. Namely, if we populate the > >> ACPI handle of the device in pci_scan_device(), then we can just move the PM > >> notifier and wakeup setup to platform_pci_wakeup_init(), where it should be > >> (we'll also need to add a corresponding _exit() function, then, but that'll be > >> much cleaner anyway). > >> > >> Then, the remaining thing would be to ensure that _PRT entries are parsed > >> as appropriate somewhere around pci_init_capabilities(). > >> > >> Also, I wonder if you can help test the $subject patchset on a system with > >> hardware PCI hotplug (preferably on top of the linux-pm.git/master branch)? > >> > > Hi Rafael, > > We are doing test for this series patches, I will send out the test result as soon. > Hi Rafael, > We have tried to merge your patchset with IOH hotplug patchsets from Yinghai, > and obviously it's not a ease task and we have run into panics. We will try to find > some ways to test your patchset only next step. Thanks a lot for doing this, really appreciated! Rafael -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type 2012-12-10 22:47 ` Rafael J. Wysocki 2012-12-10 23:09 ` Rafael J. Wysocki @ 2012-12-10 23:22 ` Yinghai Lu 2012-12-11 0:48 ` Rafael J. Wysocki 1 sibling, 1 reply; 88+ messages in thread From: Yinghai Lu @ 2012-12-10 23:22 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci, Toshi Kani, Myron Stowe On Mon, Dec 10, 2012 at 2:47 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > On Monday, December 10, 2012 09:07:06 AM Yinghai Lu wrote: >> On Mon, Dec 10, 2012 at 6:46 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote: >> > On Sunday, December 09, 2012 09:34:42 PM Yinghai Lu wrote: >> >> >> >> Can we expand the BUS_ADD_* concept to other devices instead of just >> >> acpi_device? >> >> >> >> aka we should let struct device has this add_type field. >> > >> > Having done that in ACPI to cover our use case here, we can try to move it >> > into struct device if there are use cases beyond ACPI that can't be covered >> > by using deferred driver probing. >> >> pci device for hotplug have same problem. need to delay driver attach >> for them too. > > OK, I'll take a look. Any pointers to speed that up? > >> also BUS_ADD_MATCH and BUS_ADD_START are duplicated. > > Not at the moment, they do different things as code goes. I do think that is same problem which is in the driver/base core. it should support delay loading driver for the hotplug case at the first point. that is reason that .start is introduced for acpi driver..to workround the problem in driver core. > >> old add are separated to adding all devices to tree and then matching >> work to load the drivers. >> >> so _START is not needed anymore, only user.start in pci_root driver >> should be removed. >> code in .start could be moved .add without problem. > > Yes, I'm going to do that as the next step. I didn't want this particular after you remove that .start, that will the same as my two patches. except that you patches toggle that per-device add_type for every device. and my patches is only toggle that per device drivers_autoprobe for hot-add devices. > patchset to grow too big. I'll post another one on top of it if people > don't have problems with this one. yesterday, I replace my two acpi driver delay loading patches with your patches. during pci root bus hot remove/add test, got the panic... did not have time to look at it yet. Yinghai ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type 2012-12-10 23:22 ` Yinghai Lu @ 2012-12-11 0:48 ` Rafael J. Wysocki 0 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-11 0:48 UTC (permalink / raw) To: Yinghai Lu Cc: Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci, Toshi Kani, Myron Stowe On Monday, December 10, 2012 03:22:48 PM Yinghai Lu wrote: > On Mon, Dec 10, 2012 at 2:47 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > > On Monday, December 10, 2012 09:07:06 AM Yinghai Lu wrote: > >> On Mon, Dec 10, 2012 at 6:46 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > >> > On Sunday, December 09, 2012 09:34:42 PM Yinghai Lu wrote: > >> >> > >> >> Can we expand the BUS_ADD_* concept to other devices instead of just > >> >> acpi_device? > >> >> > >> >> aka we should let struct device has this add_type field. > >> > > >> > Having done that in ACPI to cover our use case here, we can try to move it > >> > into struct device if there are use cases beyond ACPI that can't be covered > >> > by using deferred driver probing. > >> > >> pci device for hotplug have same problem. need to delay driver attach > >> for them too. > > > > OK, I'll take a look. Any pointers to speed that up? > > > >> also BUS_ADD_MATCH and BUS_ADD_START are duplicated. > > > > Not at the moment, they do different things as code goes. > > I do think that is same problem which is in the driver/base core. > > it should support delay loading driver for the hotplug case at the first point. > that is reason that .start is introduced for acpi driver..to workround > the problem > in driver core. OK, but let's eliminate .start() first and then go make changes to the driver core. That is, let's take one step at a time. :-) > >> old add are separated to adding all devices to tree and then matching > >> work to load the drivers. > >> > >> so _START is not needed anymore, only user.start in pci_root driver > >> should be removed. > >> code in .start could be moved .add without problem. > > > > Yes, I'm going to do that as the next step. I didn't want this particular > > after you remove that .start, that will the same as my two patches. > except that you patches toggle that per-device add_type for every device. > > and my patches is only toggle that per device drivers_autoprobe for > hot-add devices. I'm not 100% sure of that, but quite likely that's the case. I'd like to avoid special-casing hotplug in any way, if possible. Also, I have other reasons to do it for all devices (like the resources management for one example). > > patchset to grow too big. I'll post another one on top of it if people > > don't have problems with this one. > > yesterday, I replace my two acpi driver delay loading patches with your patches. > > during pci root bus hot remove/add test, got the panic... I don't see what the reason may be at the moment, it would be good to get more info (like a screenshot of the panic). > did not have time to look at it yet. OK Thanks, Rafael -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH 6/6] ACPI: Change the ordering of acpi_bus_check_add() 2012-12-09 22:58 [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Rafael J. Wysocki ` (4 preceding siblings ...) 2012-12-09 23:03 ` [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type Rafael J. Wysocki @ 2012-12-09 23:04 ` Rafael J. Wysocki 2012-12-13 1:00 ` Bjorn Helgaas 2012-12-13 11:45 ` [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Yijing Wang 2012-12-13 22:15 ` [PATCH rev.2 " Rafael J. Wysocki 7 siblings, 1 reply; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-09 23:04 UTC (permalink / raw) To: Bjorn Helgaas Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> If acpi_bus_check_add() is called for a handle already having an existing struct acpi_device object attached, it is not necessary to check the type and status of the device correspondig to it, so change the ordering of acpi_bus_check_add() to avoid that. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> --- drivers/acpi/scan.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -1582,6 +1582,10 @@ static acpi_status acpi_bus_check_add(ac acpi_status status; int result; + acpi_bus_get_device(handle, &device); + if (device) + goto out; + result = acpi_bus_type_and_status(handle, &type, &sta); if (result) return AE_OK; @@ -1602,17 +1606,13 @@ static acpi_status acpi_bus_check_add(ac * We may already have an acpi_device from a previous enumeration. If * so, we needn't add it again, but we may still have to start it. */ - acpi_bus_get_device(handle, &device); - if (!device) { - acpi_add_single_object(&device, handle, type, sta, - ACPI_BUS_ADD_BASIC); - if (!device) - return AE_CTRL_DEPTH; + acpi_add_single_object(&device, handle, type, sta, ACPI_BUS_ADD_BASIC); + if (!device) + return AE_CTRL_DEPTH; - device->add_type = context ? - ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH; - } + device->add_type = context ? ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH; + out: if (!*return_value) *return_value = device; ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 6/6] ACPI: Change the ordering of acpi_bus_check_add() 2012-12-09 23:04 ` [PATCH 6/6] ACPI: Change the ordering of acpi_bus_check_add() Rafael J. Wysocki @ 2012-12-13 1:00 ` Bjorn Helgaas 2012-12-13 12:20 ` Rafael J. Wysocki 0 siblings, 1 reply; 88+ messages in thread From: Bjorn Helgaas @ 2012-12-13 1:00 UTC (permalink / raw) To: Rafael J. Wysocki Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe On Sun, Dec 9, 2012 at 4:04 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > If acpi_bus_check_add() is called for a handle already having an > existing struct acpi_device object attached, it is not necessary to > check the type and status of the device correspondig to it, so > change the ordering of acpi_bus_check_add() to avoid that. > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > --- > drivers/acpi/scan.c | 18 +++++++++--------- > 1 file changed, 9 insertions(+), 9 deletions(-) > > Index: linux/drivers/acpi/scan.c > =================================================================== > --- linux.orig/drivers/acpi/scan.c > +++ linux/drivers/acpi/scan.c > @@ -1582,6 +1582,10 @@ static acpi_status acpi_bus_check_add(ac > acpi_status status; > int result; > > + acpi_bus_get_device(handle, &device); > + if (device) > + goto out; > + > result = acpi_bus_type_and_status(handle, &type, &sta); > if (result) > return AE_OK; > @@ -1602,17 +1606,13 @@ static acpi_status acpi_bus_check_add(ac > * We may already have an acpi_device from a previous enumeration. If > * so, we needn't add it again, but we may still have to start it. It looks like this comment might need updating, since we no longer even get here if we already have an acpi_device. Presumably you take care of the "start" it mentions elsewhere now. > */ > - acpi_bus_get_device(handle, &device); > - if (!device) { > - acpi_add_single_object(&device, handle, type, sta, > - ACPI_BUS_ADD_BASIC); > - if (!device) > - return AE_CTRL_DEPTH; > + acpi_add_single_object(&device, handle, type, sta, ACPI_BUS_ADD_BASIC); > + if (!device) > + return AE_CTRL_DEPTH; > > - device->add_type = context ? > - ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH; > - } > + device->add_type = context ? ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH; > > + out: > if (!*return_value) > *return_value = device; I think all (both) callers of acpi_bus_check_add() supply a return_value pointer, so you could just remove the test. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 6/6] ACPI: Change the ordering of acpi_bus_check_add() 2012-12-13 1:00 ` Bjorn Helgaas @ 2012-12-13 12:20 ` Rafael J. Wysocki 0 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-13 12:20 UTC (permalink / raw) To: Bjorn Helgaas Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe On Wednesday, December 12, 2012 06:00:28 PM Bjorn Helgaas wrote: > On Sun, Dec 9, 2012 at 4:04 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > > > If acpi_bus_check_add() is called for a handle already having an > > existing struct acpi_device object attached, it is not necessary to > > check the type and status of the device correspondig to it, so > > change the ordering of acpi_bus_check_add() to avoid that. > > > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > --- > > drivers/acpi/scan.c | 18 +++++++++--------- > > 1 file changed, 9 insertions(+), 9 deletions(-) > > > > Index: linux/drivers/acpi/scan.c > > =================================================================== > > --- linux.orig/drivers/acpi/scan.c > > +++ linux/drivers/acpi/scan.c > > @@ -1582,6 +1582,10 @@ static acpi_status acpi_bus_check_add(ac > > acpi_status status; > > int result; > > > > + acpi_bus_get_device(handle, &device); > > + if (device) > > + goto out; > > + > > result = acpi_bus_type_and_status(handle, &type, &sta); > > if (result) > > return AE_OK; > > @@ -1602,17 +1606,13 @@ static acpi_status acpi_bus_check_add(ac > > * We may already have an acpi_device from a previous enumeration. If > > * so, we needn't add it again, but we may still have to start it. > > It looks like this comment might need updating, since we no longer > even get here if we already have an acpi_device. Presumably you take > care of the "start" it mentions elsewhere now. I think you're right, will update. Thanks, Rafael > > */ > > - acpi_bus_get_device(handle, &device); > > - if (!device) { > > - acpi_add_single_object(&device, handle, type, sta, > > - ACPI_BUS_ADD_BASIC); > > - if (!device) > > - return AE_CTRL_DEPTH; > > + acpi_add_single_object(&device, handle, type, sta, ACPI_BUS_ADD_BASIC); > > + if (!device) > > + return AE_CTRL_DEPTH; > > > > - device->add_type = context ? > > - ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH; > > - } > > + device->add_type = context ? ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH; > > > > + out: > > if (!*return_value) > > *return_value = device; > > I think all (both) callers of acpi_bus_check_add() supply a > return_value pointer, so you could just remove the test. -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering 2012-12-09 22:58 [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Rafael J. Wysocki ` (5 preceding siblings ...) 2012-12-09 23:04 ` [PATCH 6/6] ACPI: Change the ordering of acpi_bus_check_add() Rafael J. Wysocki @ 2012-12-13 11:45 ` Yijing Wang 2012-12-13 22:15 ` [PATCH rev.2 " Rafael J. Wysocki 7 siblings, 0 replies; 88+ messages in thread From: Yijing Wang @ 2012-12-13 11:45 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe Hi rafael, I tested the pachset in our IA64 machine, system boot up log seems ok, but when do IOH hot plug, there are two small problems that missing match and start acpi devices for the top acpi device(eg. pci host bridge), refer https://lkml.org/lkml/2012/12/12/268. Test Machine: IA64,2 physical nodes; PCI topology: -+-[0000:40]-+-00.0-[0000:41]-- | +-01.0-[0000:42]--+-00.0 Intel Corporation 82576 Gigabit Network Connection | | \-00.1 Intel Corporation 82576 Gigabit Network Connection | +-03.0-[0000:43]----00.0 LSI Logic / Symbios Logic SAS1064ET PCI-Express Fusion-MPT SAS | +-04.0-[0000:44]-- | +-05.0-[0000:45]-- | +-07.0-[0000:46]-- | +-0d.0 Intel Corporation Device 343a | +-0d.1 Intel Corporation Device 343b | +-0d.2 Intel Corporation Device 343c | +-0d.3 Intel Corporation Device 343d | +-0d.4 Intel Corporation 5520/5500/X58 Physical Layer Port 0 | +-0d.5 Intel Corporation 5520/5500 Physical Layer Port 1 | +-0d.6 Intel Corporation Device 341a | +-0d.7 Intel Corporation Device 341b | +-0e.0 Intel Corporation Device 341c | +-0e.1 Intel Corporation Device 341d | +-0e.2 Intel Corporation Device 341e | +-0e.3 Intel Corporation Device 341f | +-0e.4 Intel Corporation Device 3439 | +-0f.0 Intel Corporation Device 3424 | +-10.0 Intel Corporation 5520/5500/X58 Physical and Link Layer Registers Port 0 | +-10.1 Intel Corporation 5520/5500/X58 Routing and Protocol Layer Registers Port 0 | +-11.0 Intel Corporation 5520/5500 Physical and Link Layer Registers Port 1 | +-11.1 Intel Corporation 5520/5500 Routing & Protocol Layer Register Port 1 | +-13.0 Intel Corporation 5520/5500/X58 I/O Hub I/OxAPIC Interrupt Controller | +-14.0 Intel Corporation 5520/5500/X58 I/O Hub System Management Registers | +-14.1 Intel Corporation 5520/5500/X58 I/O Hub GPIO and Scratch Pad Registers | +-14.2 Intel Corporation 5520/5500/X58 I/O Hub Control Status and RAS Registers | +-14.3 Intel Corporation 5520/5500/X58 I/O Hub Throttle Registers | +-15.0 Intel Corporation 5520/5500/X58 Trusted Execution Technology Registers | +-16.0 Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device | +-16.1 Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device | +-16.2 Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device | +-16.3 Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device | +-16.4 Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device | +-16.5 Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device | +-16.6 Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device | \-16.7 Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device \-[0000:00]-+-00.0 Intel Corporation 5520/5500/X58 I/O Hub to ESI Port +-01.0-[0000:01]--+-00.0 Intel Corporation 82576 Gigabit Network Connection | \-00.1 Intel Corporation 82576 Gigabit Network Connection +-03.0-[0000:02]----00.0 LSI Logic / Symbios Logic SAS1064ET PCI-Express Fusion-MPT SAS +-04.0-[0000:03]-- +-05.0-[0000:04]-- +-07.0-[0000:05]--+-00.0 nVidia Corporation GT218 [GeForce G210] | \-00.1 nVidia Corporation High Definition Audio Controller +-0d.0 Intel Corporation Device 343a +-0d.1 Intel Corporation Device 343b +-0d.2 Intel Corporation Device 343c +-0d.3 Intel Corporation Device 343d +-0d.4 Intel Corporation 5520/5500/X58 Physical Layer Port 0 +-0d.5 Intel Corporation 5520/5500 Physical Layer Port 1 +-0d.6 Intel Corporation Device 341a +-0d.7 Intel Corporation Device 341b +-0e.0 Intel Corporation Device 341c +-0e.1 Intel Corporation Device 341d +-0e.2 Intel Corporation Device 341e +-0e.3 Intel Corporation Device 341f +-0e.4 Intel Corporation Device 3439 +-0f.0 Intel Corporation Device 3424 +-10.0 Intel Corporation 5520/5500/X58 Physical and Link Layer Registers Port 0 +-10.1 Intel Corporation 5520/5500/X58 Routing and Protocol Layer Registers Port 0 +-11.0 Intel Corporation 5520/5500 Physical and Link Layer Registers Port 1 +-11.1 Intel Corporation 5520/5500 Routing & Protocol Layer Register Port 1 +-13.0 Intel Corporation 5520/5500/X58 I/O Hub I/OxAPIC Interrupt Controller +-14.0 Intel Corporation 5520/5500/X58 I/O Hub System Management Registers +-14.1 Intel Corporation 5520/5500/X58 I/O Hub GPIO and Scratch Pad Registers +-14.2 Intel Corporation 5520/5500/X58 I/O Hub Control Status and RAS Registers +-14.3 Intel Corporation 5520/5500/X58 I/O Hub Throttle Registers +-15.0 Intel Corporation 5520/5500/X58 Trusted Execution Technology Registers +-16.0 Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device +-16.1 Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device +-16.2 Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device +-16.3 Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device +-16.4 Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device +-16.5 Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device +-16.6 Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device +-16.7 Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device +-1a.0 Intel Corporation 82801JI (ICH10 Family) USB UHCI Controller #4 +-1a.1 Intel Corporation 82801JI (ICH10 Family) USB UHCI Controller #5 +-1a.2 Intel Corporation 82801JI (ICH10 Family) USB UHCI Controller #6 +-1a.7 Intel Corporation 82801JI (ICH10 Family) USB2 EHCI Controller #2 +-1c.0-[0000:06]-- +-1c.1-[0000:07]-- +-1c.2-[0000:08]-- +-1c.3-[0000:09]-- +-1c.4-[0000:0a]----00.0 XGI Technology Inc. (eXtreme Graphics Innovation) Z11/Z11M +-1c.5-[0000:0b]-- +-1d.0 Intel Corporation 82801JI (ICH10 Family) USB UHCI Controller #1 +-1d.1 Intel Corporation 82801JI (ICH10 Family) USB UHCI Controller #2 +-1d.2 Intel Corporation 82801JI (ICH10 Family) USB UHCI Controller #3 +-1d.7 Intel Corporation 82801JI (ICH10 Family) USB2 EHCI Controller #1 +-1e.0-[0000:0c]-- +-1f.0 Intel Corporation 82801JIB (ICH10) LPC Interface Controller +-1f.2 Intel Corporation 82801JI (ICH10 Family) 4 port SATA IDE Controller #1 +-1f.3 Intel Corporation 82801JI (ICH10 Family) SMBus Controller \-1f.5 Intel Corporation 82801JI (ICH10 Family) 2 port SATA IDE Controller #2 linux kernel version: https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git + ACPI: Change the ACPI namespace scanning code ordering six patches + IOH hotplug partial patches from https://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git/for-pci-next-2 IOH hotplug dmesg log at the end. ========================================================================system boot up dmesg log================================================ ACPI: bus type pci registered bio: create slab <bio-0> at 0 ACPI: Added _OSI(Module Device) ACPI: Added _OSI(Processor Device) ACPI: Added _OSI(3.0 _SCP Extensions) ACPI: Added _OSI(Processor Aggregator Device) ACPI: EC: Look up EC in DSDT ACPI: Interpreter enabled ACPI: (supports S0 S5) ACPI: Using IOSAPIC for interrupt routing acpi_bus_scan: start 1 acpi_bus_check_add: acpi_device LNXSYSTM:00 added, add_type 2 acpi_bus_check_add: acpi_device device:00 added, add_type 2 acpi_bus_check_add: acpi_device ACPI0004:00 added, add_type 2 acpi_bus_check_add: acpi_device ACPI0004:01 added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:00 added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:01 added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:02 added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:03 added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:04 added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:05 added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:06 added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:07 added, add_type 2 acpi_bus_check_add: acpi_device PNP0C80:00 added, add_type 2 acpi_bus_check_add: acpi_device ACPI0004:02 added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:08 added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:09 added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:0a added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:0b added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:0c added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:0d added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:0e added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:0f added, add_type 2 acpi_bus_check_add: acpi_device PNP0C80:01 added, add_type 2 acpi_bus_check_add: acpi_device PNP0A08:00 added, add_type 2 acpi_bus_check_add: acpi_device ACPI0009:00 added, add_type 2 acpi_bus_check_add: acpi_device device:01 added, add_type 2 acpi_bus_check_add: acpi_device device:02 added, add_type 2 acpi_bus_check_add: acpi_device device:03 added, add_type 2 acpi_bus_check_add: acpi_device device:04 added, add_type 2 acpi_bus_check_add: acpi_device device:05 added, add_type 2 acpi_bus_check_add: acpi_device device:06 added, add_type 2 acpi_bus_check_add: acpi_device device:07 added, add_type 2 acpi_bus_check_add: acpi_device device:08 added, add_type 2 acpi_bus_check_add: acpi_device device:09 added, add_type 2 acpi_bus_check_add: acpi_device device:0a added, add_type 2 acpi_bus_check_add: acpi_device device:0b added, add_type 2 acpi_bus_check_add: acpi_device device:0c added, add_type 2 acpi_bus_check_add: acpi_device device:0d added, add_type 2 acpi_bus_check_add: acpi_device device:0e added, add_type 2 acpi_bus_check_add: acpi_device device:0f added, add_type 2 acpi_bus_check_add: acpi_device device:10 added, add_type 2 acpi_bus_check_add: acpi_device device:11 added, add_type 2 acpi_bus_check_add: acpi_device device:12 added, add_type 2 acpi_bus_check_add: acpi_device device:13 added, add_type 2 acpi_bus_check_add: acpi_device device:14 added, add_type 2 acpi_bus_check_add: acpi_device device:15 added, add_type 2 acpi_bus_check_add: acpi_device device:16 added, add_type 2 acpi_bus_check_add: acpi_device device:17 added, add_type 2 acpi_bus_check_add: acpi_device device:18 added, add_type 2 acpi_bus_check_add: acpi_device device:19 added, add_type 2 acpi_bus_check_add: acpi_device device:1a added, add_type 2 acpi_bus_check_add: acpi_device device:1b added, add_type 2 acpi_bus_check_add: acpi_device device:1c added, add_type 2 acpi_bus_check_add: acpi_device device:1d added, add_type 2 acpi_bus_check_add: acpi_device device:1e added, add_type 2 acpi_bus_check_add: acpi_device device:1f added, add_type 2 acpi_bus_check_add: acpi_device device:20 added, add_type 2 acpi_bus_check_add: acpi_device device:21 added, add_type 2 acpi_bus_check_add: acpi_device PNP0C0F:00 added, add_type 2 acpi_bus_check_add: acpi_device PNP0C0F:01 added, add_type 2 acpi_bus_check_add: acpi_device PNP0C0F:02 added, add_type 2 acpi_bus_check_add: acpi_device PNP0C0F:03 added, add_type 2 acpi_bus_check_add: acpi_device PNP0C0F:04 added, add_type 2 acpi_bus_check_add: acpi_device PNP0C0F:05 added, add_type 2 acpi_bus_check_add: acpi_device PNP0C0F:06 added, add_type 2 acpi_bus_check_add: acpi_device PNP0C0F:07 added, add_type 2 acpi_bus_check_add: acpi_device PNP0200:00 added, add_type 2 acpi_bus_check_add: acpi_device PNP0B00:00 added, add_type 2 acpi_bus_check_add: acpi_device PNP0000:00 added, add_type 2 acpi_bus_check_add: acpi_device PNP0C04:00 added, add_type 2 acpi_bus_check_add: acpi_device PNP0100:00 added, add_type 2 acpi_bus_check_add: acpi_device PNP0800:00 added, add_type 2 acpi_bus_check_add: acpi_device PNP0C02:00 added, add_type 2 acpi_bus_check_add: acpi_device PNP0700:00 added, add_type 2 acpi_bus_check_add: acpi_device PNP0400:00 added, add_type 2 acpi_bus_check_add: acpi_device PNP0F03:00 added, add_type 2 acpi_bus_check_add: acpi_device PNP0303:00 added, add_type 2 acpi_bus_check_add: acpi_device PNP0501:00 added, add_type 2 acpi_bus_check_add: acpi_device device:22 added, add_type 2 acpi_bus_check_add: acpi_device device:23 added, add_type 2 acpi_bus_check_add: acpi_device device:24 added, add_type 2 acpi_bus_check_add: acpi_device device:25 added, add_type 2 acpi_bus_check_add: acpi_device device:26 added, add_type 2 acpi_bus_check_add: acpi_device device:27 added, add_type 2 acpi_bus_check_add: acpi_device device:28 added, add_type 2 acpi_bus_check_add: acpi_device device:29 added, add_type 2 acpi_bus_check_add: acpi_device device:2a added, add_type 2 acpi_bus_check_add: acpi_device device:2b added, add_type 2 acpi_bus_check_add: acpi_device device:2c added, add_type 2 acpi_bus_check_add: acpi_device device:2d added, add_type 2 acpi_bus_check_add: acpi_device device:2e added, add_type 2 acpi_bus_check_add: acpi_device device:2f added, add_type 2 acpi_bus_check_add: acpi_device device:30 added, add_type 2 acpi_bus_check_add: acpi_device device:31 added, add_type 2 acpi_bus_check_add: acpi_device device:32 added, add_type 2 acpi_bus_check_add: acpi_device device:33 added, add_type 2 acpi_bus_check_add: acpi_device device:34 added, add_type 2 acpi_bus_check_add: acpi_device PNP0C0E:00 added, add_type 2 acpi_bus_check_add: acpi_device ACPI0004:03 added, add_type 2 acpi_bus_check_add: acpi_device ACPI0004:04 added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:10 added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:11 added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:12 added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:13 added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:14 added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:15 added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:16 added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:17 added, add_type 2 acpi_bus_check_add: acpi_device PNP0C80:02 added, add_type 2 acpi_bus_check_add: acpi_device ACPI0004:05 added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:18 added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:19 added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:1a added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:1b added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:1c added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:1d added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:1e added, add_type 2 acpi_bus_check_add: acpi_device LNXCPU:1f added, add_type 2 acpi_bus_check_add: acpi_device PNP0C80:03 added, add_type 2 acpi_bus_check_add: acpi_device PNP0A08:01 added, add_type 2 acpi_bus_check_add: acpi_device ACPI0009:01 added, add_type 2 acpi_bus_check_add: acpi_device device:35 added, add_type 2 acpi_bus_check_add: acpi_device device:36 added, add_type 2 acpi_bus_check_add: acpi_device device:37 added, add_type 2 acpi_bus_check_add: acpi_device device:38 added, add_type 2 acpi_bus_check_add: acpi_device device:39 added, add_type 2 acpi_bus_check_add: acpi_device device:3a added, add_type 2 acpi_bus_check_add: acpi_device device:3b added, add_type 2 acpi_bus_check_add: acpi_device device:3c added, add_type 2 acpi_bus_check_add: acpi_device device:3d added, add_type 2 acpi_bus_check_add: acpi_device device:3e added, add_type 2 acpi_bus_check_add: acpi_device device:3f added, add_type 2 acpi_bus_check_add: acpi_device device:40 added, add_type 2 acpi_bus_check_add: acpi_device device:41 added, add_type 2 acpi_bus_check_add: acpi_device device:42 added, add_type 2 acpi_bus_check_add: acpi_device device:43 added, add_type 2 acpi_bus_check_add: acpi_device device:44 added, add_type 2 acpi_bus_check_add: acpi_device device:45 added, add_type 2 acpi_bus_check_add: acpi_device device:46 added, add_type 2 acpi_bus_check_add: acpi_device device:47 added, add_type 2 acpi_bus_check_add: acpi_device device:48 added, add_type 2 acpi_bus_check_add: acpi_device device:49 added, add_type 2 acpi_bus_check_add: acpi_device device:4a added, add_type 2 acpi_bus_check_add: acpi_device device:4b added, add_type 2 acpi_bus_check_add: acpi_device device:4c added, add_type 2 acpi_bus_check_add: acpi_device device:4d added, add_type 2 acpi_bus_check_add: acpi_device device:4e added, add_type 2 acpi_bus_check_add: acpi_device device:4f added, add_type 2 acpi_bus_check_add: acpi_device device:50 added, add_type 2 acpi_bus_match_device: attach driver for device device:00 acpi_bus_match_device: acpi_device device:00, attached driver is NULL acpi_bus_match_device: attach driver for device ACPI0004:00 acpi_bus_match_device: acpi_device ACPI0004:00, attached driver is NULL acpi_bus_match_device: attach driver for device ACPI0004:01 acpi_bus_match_device: acpi_device ACPI0004:01, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:00 acpi_bus_match_device: acpi_device LNXCPU:00, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:01 acpi_bus_match_device: acpi_device LNXCPU:01, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:02 acpi_bus_match_device: acpi_device LNXCPU:02, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:03 acpi_bus_match_device: acpi_device LNXCPU:03, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:04 acpi_bus_match_device: acpi_device LNXCPU:04, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:05 acpi_bus_match_device: acpi_device LNXCPU:05, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:06 acpi_bus_match_device: acpi_device LNXCPU:06, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:07 acpi_bus_match_device: acpi_device LNXCPU:07, attached driver is NULL acpi_bus_match_device: attach driver for device PNP0C80:00 acpi_bus_match_device: acpi_device PNP0C80:00, attached driver is NULL acpi_bus_match_device: attach driver for device ACPI0004:02 acpi_bus_match_device: acpi_device ACPI0004:02, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:08 acpi_bus_match_device: acpi_device LNXCPU:08, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:09 acpi_bus_match_device: acpi_device LNXCPU:09, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:0a acpi_bus_match_device: acpi_device LNXCPU:0a, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:0b acpi_bus_match_device: acpi_device LNXCPU:0b, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:0c acpi_bus_match_device: acpi_device LNXCPU:0c, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:0d acpi_bus_match_device: acpi_device LNXCPU:0d, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:0e acpi_bus_match_device: acpi_device LNXCPU:0e, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:0f acpi_bus_match_device: acpi_device LNXCPU:0f, attached driver is NULL acpi_bus_match_device: attach driver for device PNP0C80:01 acpi_bus_match_device: acpi_device PNP0C80:01, attached driver is NULL acpi_bus_match_device: attach driver for device PNP0A08:00 acpi_bus_match: device PNP0A08:00 find match driver pci_root ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-3f]) pci_root PNP0A08:00: host bridge window [io 0x0000-0x0cf7] pci_root PNP0A08:00: host bridge window [io 0x1000-0x8fff] pci_root PNP0A08:00: host bridge window [mem 0x50000000-0x7fffffff] PCI host bridge to bus 0000:00 pci_bus 0000:00: root bus resource [bus 00-3f] pci_bus 0000:00: root bus resource [io 0x0000-0x0cf7] pci_bus 0000:00: root bus resource [io 0x1000-0x8fff] pci_bus 0000:00: root bus resource [mem 0x50000000-0x7fffffff] pci 0000:00:00.0: [8086:3407] type 00 class 0x060000 pci 0000:00:01.0: [8086:3408] type 01 class 0x060400 pci 0000:00:01.0: PME# supported from D0 D3hot D3cold pci 0000:00:03.0: [8086:340a] type 01 class 0x060400 pci 0000:00:03.0: PME# supported from D0 D3hot D3cold pci 0000:00:04.0: [8086:340b] type 01 class 0x060400 pci 0000:00:04.0: PME# supported from D0 D3hot D3cold pci 0000:00:05.0: [8086:340c] type 01 class 0x060400 pci 0000:00:05.0: PME# supported from D0 D3hot D3cold pci 0000:00:07.0: [8086:340e] type 01 class 0x060400 pci 0000:00:07.0: PME# supported from D0 D3hot D3cold pci 0000:00:0d.0: [8086:343a] type 00 class 0x060000 pci 0000:00:0d.1: [8086:343b] type 00 class 0x060000 pci 0000:00:0d.2: [8086:343c] type 00 class 0x060000 pci 0000:00:0d.3: [8086:343d] type 00 class 0x060000 pci 0000:00:0d.4: [8086:3418] type 00 class 0x060000 pci 0000:00:0d.5: [8086:3419] type 00 class 0x060000 pci 0000:00:0d.6: [8086:341a] type 00 class 0x060000 pci 0000:00:0d.7: [8086:341b] type 00 class 0x060000 pci 0000:00:0e.0: [8086:341c] type 00 class 0x060000 pci 0000:00:0e.1: [8086:341d] type 00 class 0x060000 pci 0000:00:0e.2: [8086:341e] type 00 class 0x060000 pci 0000:00:0e.3: [8086:341f] type 00 class 0x060000 pci 0000:00:0e.4: [8086:3439] type 00 class 0x060000 pci 0000:00:0f.0: [8086:3424] type 00 class 0x110100 pci 0000:00:10.0: [8086:3425] type 00 class 0x080000 pci 0000:00:10.1: [8086:3426] type 00 class 0x080000 pci 0000:00:11.0: [8086:3427] type 00 class 0x080000 pci 0000:00:11.1: [8086:3428] type 00 class 0x080000 pci 0000:00:13.0: [8086:342d] type 00 class 0x080020 pci 0000:00:13.0: reg 10: [mem 0x68320000-0x68320fff] pci 0000:00:13.0: PME# supported from D0 D3hot D3cold pci 0000:00:14.0: [8086:342e] type 00 class 0x080000 pci 0000:00:14.1: [8086:3422] type 00 class 0x080000 pci 0000:00:14.2: [8086:3423] type 00 class 0x080000 pci 0000:00:14.3: [8086:3438] type 00 class 0x080000 pci 0000:00:15.0: [8086:342f] type 00 class 0x080020 pci 0000:00:16.0: [8086:3430] type 00 class 0x088000 pci 0000:00:16.0: reg 10: [mem 0x68300000-0x68303fff 64bit] pci 0000:00:16.1: [8086:3431] type 00 class 0x088000 pci 0000:00:16.1: reg 10: [mem 0x68304000-0x68307fff 64bit] pci 0000:00:16.2: [8086:3432] type 00 class 0x088000 pci 0000:00:16.2: reg 10: [mem 0x68308000-0x6830bfff 64bit] pci 0000:00:16.3: [8086:3433] type 00 class 0x088000 pci 0000:00:16.3: reg 10: [mem 0x6830c000-0x6830ffff 64bit] pci 0000:00:16.4: [8086:3429] type 00 class 0x088000 pci 0000:00:16.4: reg 10: [mem 0x68310000-0x68313fff 64bit] pci 0000:00:16.5: [8086:342a] type 00 class 0x088000 pci 0000:00:16.5: reg 10: [mem 0x68314000-0x68317fff 64bit] pci 0000:00:16.6: [8086:342b] type 00 class 0x088000 pci 0000:00:16.6: reg 10: [mem 0x68318000-0x6831bfff 64bit] pci 0000:00:16.7: [8086:342c] type 00 class 0x088000 pci 0000:00:16.7: reg 10: [mem 0x6831c000-0x6831ffff 64bit] pci 0000:00:1a.0: [8086:3a37] type 00 class 0x0c0300 pci 0000:00:1a.0: reg 20: [io 0x50c0-0x50df] pci 0000:00:1a.1: [8086:3a38] type 00 class 0x0c0300 pci 0000:00:1a.1: reg 20: [io 0x50a0-0x50bf] pci 0000:00:1a.2: [8086:3a39] type 00 class 0x0c0300 pci 0000:00:1a.2: reg 20: [io 0x5080-0x509f] pci 0000:00:1a.7: [8086:3a3c] type 00 class 0x0c0320 pci 0000:00:1a.7: reg 10: [mem 0x68321400-0x683217ff] pci 0000:00:1a.7: PME# supported from D0 D3hot D3cold pci 0000:00:1c.0: [8086:3a40] type 01 class 0x060400 pci 0000:00:1c.0: PME# supported from D0 D3hot D3cold pci 0000:00:1c.1: [8086:3a42] type 01 class 0x060400 pci 0000:00:1c.1: PME# supported from D0 D3hot D3cold pci 0000:00:1c.2: [8086:3a44] type 01 class 0x060400 pci 0000:00:1c.2: PME# supported from D0 D3hot D3cold pci 0000:00:1c.3: [8086:3a46] type 01 class 0x060400 pci 0000:00:1c.3: PME# supported from D0 D3hot D3cold pci 0000:00:1c.4: [8086:3a48] type 01 class 0x060400 pci 0000:00:1c.4: PME# supported from D0 D3hot D3cold pci 0000:00:1c.5: [8086:3a4a] type 01 class 0x060400 pci 0000:00:1c.5: PME# supported from D0 D3hot D3cold pci 0000:00:1d.0: [8086:3a34] type 00 class 0x0c0300 pci 0000:00:1d.0: reg 20: [io 0x5060-0x507f] pci 0000:00:1d.1: [8086:3a35] type 00 class 0x0c0300 pci 0000:00:1d.1: reg 20: [io 0x5040-0x505f] pci 0000:00:1d.2: [8086:3a36] type 00 class 0x0c0300 pci 0000:00:1d.2: reg 20: [io 0x5020-0x503f] pci 0000:00:1d.7: [8086:3a3a] type 00 class 0x0c0320 pci 0000:00:1d.7: reg 10: [mem 0x68321000-0x683213ff] pci 0000:00:1d.7: PME# supported from D0 D3hot D3cold pci 0000:00:1e.0: [8086:244e] type 01 class 0x060401 pci 0000:00:1f.0: [8086:3a18] type 00 class 0x060100 pci 0000:00:1f.2: [8086:3a20] type 00 class 0x01018f pci 0000:00:1f.2: reg 10: [io 0x5138-0x513f] pci 0000:00:1f.2: reg 14: [io 0x514c-0x514f] pci 0000:00:1f.2: reg 18: [io 0x5130-0x5137] pci 0000:00:1f.2: reg 1c: [io 0x5148-0x514b] pci 0000:00:1f.2: reg 20: [io 0x5110-0x511f] pci 0000:00:1f.2: reg 24: [io 0x5100-0x510f] pci 0000:00:1f.3: [8086:3a30] type 00 class 0x0c0500 pci 0000:00:1f.3: reg 10: [mem 0x68321800-0x683218ff 64bit] pci 0000:00:1f.3: reg 20: [io 0x5000-0x501f] pci 0000:00:1f.5: [8086:3a26] type 00 class 0x010185 pci 0000:00:1f.5: reg 10: [io 0x5128-0x512f] pci 0000:00:1f.5: reg 14: [io 0x5144-0x5147] pci 0000:00:1f.5: reg 18: [io 0x5120-0x5127] pci 0000:00:1f.5: reg 1c: [io 0x5140-0x5143] pci 0000:00:1f.5: reg 20: [io 0x50f0-0x50ff] pci 0000:00:1f.5: reg 24: [io 0x50e0-0x50ef] pci 0000:01:00.0: [8086:10c9] type 00 class 0x020000 pci 0000:01:00.0: reg 10: [mem 0x68260000-0x6827ffff] pci 0000:01:00.0: reg 14: [mem 0x68240000-0x6825ffff] pci 0000:01:00.0: reg 18: [io 0x4020-0x403f] pci 0000:01:00.0: reg 1c: [mem 0x68284000-0x68287fff] pci 0000:01:00.0: reg 30: [mem 0xfffe0000-0xffffffff pref] pci 0000:01:00.0: PME# supported from D0 D3hot D3cold pci 0000:01:00.1: [8086:10c9] type 00 class 0x020000 pci 0000:01:00.1: reg 10: [mem 0x68220000-0x6823ffff] pci 0000:01:00.1: reg 14: [mem 0x68200000-0x6821ffff] pci 0000:01:00.1: reg 18: [io 0x4000-0x401f] pci 0000:01:00.1: reg 1c: [mem 0x68280000-0x68283fff] pci 0000:01:00.1: reg 30: [mem 0xfffe0000-0xffffffff pref] pci 0000:01:00.1: PME# supported from D0 D3hot D3cold pci 0000:00:01.0: PCI bridge to [bus 01] pci 0000:00:01.0: bridge window [io 0x4000-0x4fff] pci 0000:00:01.0: bridge window [mem 0x68200000-0x682fffff] pci 0000:02:00.0: [1000:0056] type 00 class 0x010000 pci 0000:02:00.0: reg 10: [io 0x3000-0x30ff] pci 0000:02:00.0: reg 14: [mem 0x68110000-0x68113fff 64bit] pci 0000:02:00.0: reg 1c: [mem 0x68100000-0x6810ffff 64bit] pci 0000:02:00.0: reg 30: [mem 0xffe00000-0xffffffff pref] pci 0000:02:00.0: supports D1 D2 pci 0000:02:00.0: disabling ASPM on pre-1.1 PCIe device. You can enable it with 'pcie_aspm=force' pci 0000:00:03.0: PCI bridge to [bus 02] pci 0000:00:03.0: bridge window [io 0x3000-0x3fff] pci 0000:00:03.0: bridge window [mem 0x68100000-0x681fffff] pci 0000:00:04.0: PCI bridge to [bus 03] pci 0000:00:05.0: PCI bridge to [bus 04] pci 0000:05:00.0: [10de:0a60] type 00 class 0x030000 pci 0000:05:00.0: reg 10: [mem 0x62000000-0x62ffffff] pci 0000:05:00.0: reg 14: [mem 0x50000000-0x5fffffff 64bit pref] pci 0000:05:00.0: reg 1c: [mem 0x60000000-0x61ffffff 64bit pref] pci 0000:05:00.0: reg 24: [io 0x2000-0x207f] pci 0000:05:00.0: reg 30: [mem 0xfff80000-0xffffffff pref] pci 0000:05:00.0: Boot video device pci 0000:05:00.1: [10de:0be3] type 00 class 0x040300 pci 0000:05:00.1: reg 10: [mem 0x63000000-0x63003fff] pci 0000:00:07.0: PCI bridge to [bus 05] pci 0000:00:07.0: bridge window [io 0x2000-0x2fff] pci 0000:00:07.0: bridge window [mem 0x50000000-0x630fffff] pci 0000:00:1c.0: PCI bridge to [bus 06] pci 0000:00:1c.1: PCI bridge to [bus 07] pci 0000:00:1c.2: PCI bridge to [bus 08] pci 0000:00:1c.3: PCI bridge to [bus 09] pci 0000:0a:00.0: [18ca:0027] type 00 class 0x030000 pci 0000:0a:00.0: reg 10: [mem 0x64000000-0x67ffffff pref] pci 0000:0a:00.0: reg 14: [mem 0x68000000-0x6803ffff] pci 0000:0a:00.0: reg 18: [io 0x1000-0x107f] pci 0000:0a:00.0: supports D1 D2 pci 0000:00:1c.4: PCI bridge to [bus 0a] pci 0000:00:1c.4: bridge window [io 0x1000-0x1fff] pci 0000:00:1c.4: bridge window [mem 0x64000000-0x680fffff] pci 0000:00:1c.5: PCI bridge to [bus 0b] pci 0000:00:1e.0: PCI bridge to [bus 0c] (subtractive decode) pci 0000:00:1e.0: bridge window [io 0x0000-0x0cf7] (subtractive decode) pci 0000:00:1e.0: bridge window [io 0x1000-0x8fff] (subtractive decode) pci 0000:00:1e.0: bridge window [mem 0x50000000-0x7fffffff] (subtractive decode) ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0._PRT] ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0.MRP1._PRT] ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0.MRP3._PRT] ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0.MRP4._PRT] ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0.MRP5._PRT] ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0.MRP7._PRT] ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0.PEX0._PRT] ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0.PEX1._PRT] ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0.PEX2._PRT] ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0.PEX3._PRT] ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0.PEX4._PRT] ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0.PEX5._PRT] ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0.IP2P._PRT] pci0000:00: Requesting ACPI _OSC control (0x1d) pci0000:00: ACPI _OSC control (0x1d) granted acpi_start_single_object: acpi_device PNP0A08:00, driver pci_root to start acpi_bus_match_device: acpi_device PNP0A08:00, attached driver is pci_root acpi_bus_match_device: attach driver for device PNP0C0E:00 acpi_bus_match_device: acpi_device PNP0C0E:00, attached driver is NULL acpi_bus_match_device: attach driver for device ACPI0004:03 acpi_bus_match_device: acpi_device ACPI0004:03, attached driver is NULL acpi_bus_match_device: attach driver for device ACPI0004:04 acpi_bus_match_device: acpi_device ACPI0004:04, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:10 acpi_bus_match_device: acpi_device LNXCPU:10, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:11 acpi_bus_match_device: acpi_device LNXCPU:11, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:12 acpi_bus_match_device: acpi_device LNXCPU:12, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:13 acpi_bus_match_device: acpi_device LNXCPU:13, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:14 acpi_bus_match_device: acpi_device LNXCPU:14, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:15 acpi_bus_match_device: acpi_device LNXCPU:15, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:16 acpi_bus_match_device: acpi_device LNXCPU:16, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:17 acpi_bus_match_device: acpi_device LNXCPU:17, attached driver is NULL acpi_bus_match_device: attach driver for device PNP0C80:02 acpi_bus_match_device: acpi_device PNP0C80:02, attached driver is NULL acpi_bus_match_device: attach driver for device ACPI0004:05 acpi_bus_match_device: acpi_device ACPI0004:05, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:18 acpi_bus_match_device: acpi_device LNXCPU:18, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:19 acpi_bus_match_device: acpi_device LNXCPU:19, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:1a acpi_bus_match_device: acpi_device LNXCPU:1a, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:1b acpi_bus_match_device: acpi_device LNXCPU:1b, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:1c acpi_bus_match_device: acpi_device LNXCPU:1c, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:1d acpi_bus_match_device: acpi_device LNXCPU:1d, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:1e acpi_bus_match_device: acpi_device LNXCPU:1e, attached driver is NULL acpi_bus_match_device: attach driver for device LNXCPU:1f acpi_bus_match_device: acpi_device LNXCPU:1f, attached driver is NULL acpi_bus_match_device: attach driver for device PNP0C80:03 acpi_bus_match_device: acpi_device PNP0C80:03, attached driver is NULL acpi_bus_match_device: attach driver for device PNP0A08:01 acpi_bus_match: device PNP0A08:01 find match driver pci_root ACPI: PCI Root Bridge [PCI1] (domain 0000 [bus 40-7f]) pci_root PNP0A08:01: host bridge window [io 0x9000-0xfffe] pci_root PNP0A08:01: host bridge window [mem 0x80000000-0x9fffffff] PCI host bridge to bus 0000:40 pci_bus 0000:40: root bus resource [bus 40-7f] pci_bus 0000:40: root bus resource [io 0x9000-0xfffe] pci_bus 0000:40: root bus resource [mem 0x80000000-0x9fffffff] pci 0000:40:00.0: [8086:3420] type 01 class 0x060400 pci 0000:40:00.0: PME# supported from D0 D3hot D3cold pci 0000:40:01.0: [8086:3408] type 01 class 0x060400 pci 0000:40:01.0: PME# supported from D0 D3hot D3cold pci 0000:40:03.0: [8086:340a] type 01 class 0x060400 pci 0000:40:03.0: PME# supported from D0 D3hot D3cold pci 0000:40:04.0: [8086:340b] type 01 class 0x060400 pci 0000:40:04.0: PME# supported from D0 D3hot D3cold pci 0000:40:05.0: [8086:340c] type 01 class 0x060400 pci 0000:40:05.0: PME# supported from D0 D3hot D3cold pci 0000:40:07.0: [8086:340e] type 01 class 0x060400 pci 0000:40:07.0: PME# supported from D0 D3hot D3cold pci 0000:40:0d.0: [8086:343a] type 00 class 0x060000 pci 0000:40:0d.1: [8086:343b] type 00 class 0x060000 pci 0000:40:0d.2: [8086:343c] type 00 class 0x060000 pci 0000:40:0d.3: [8086:343d] type 00 class 0x060000 pci 0000:40:0d.4: [8086:3418] type 00 class 0x060000 pci 0000:40:0d.5: [8086:3419] type 00 class 0x060000 pci 0000:40:0d.6: [8086:341a] type 00 class 0x060000 pci 0000:40:0d.7: [8086:341b] type 00 class 0x060000 pci 0000:40:0e.0: [8086:341c] type 00 class 0x060000 pci 0000:40:0e.1: [8086:341d] type 00 class 0x060000 pci 0000:40:0e.2: [8086:341e] type 00 class 0x060000 pci 0000:40:0e.3: [8086:341f] type 00 class 0x060000 pci 0000:40:0e.4: [8086:3439] type 00 class 0x060000 pci 0000:40:0f.0: [8086:3424] type 00 class 0x110100 pci 0000:40:10.0: [8086:3425] type 00 class 0x080000 pci 0000:40:10.1: [8086:3426] type 00 class 0x080000 pci 0000:40:11.0: [8086:3427] type 00 class 0x080000 pci 0000:40:11.1: [8086:3428] type 00 class 0x080000 pci 0000:40:13.0: [8086:342d] type 00 class 0x080020 pci 0000:40:13.0: reg 10: [mem 0x80220000-0x80220fff] pci 0000:40:13.0: PME# supported from D0 D3hot D3cold pci 0000:40:14.0: [8086:342e] type 00 class 0x080000 pci 0000:40:14.1: [8086:3422] type 00 class 0x080000 pci 0000:40:14.2: [8086:3423] type 00 class 0x080000 pci 0000:40:14.3: [8086:3438] type 00 class 0x080000 pci 0000:40:15.0: [8086:342f] type 00 class 0x080020 pci 0000:40:16.0: [8086:3430] type 00 class 0x088000 pci 0000:40:16.0: reg 10: [mem 0x80200000-0x80203fff 64bit] pci 0000:40:16.1: [8086:3431] type 00 class 0x088000 pci 0000:40:16.1: reg 10: [mem 0x80204000-0x80207fff 64bit] pci 0000:40:16.2: [8086:3432] type 00 class 0x088000 pci 0000:40:16.2: reg 10: [mem 0x80208000-0x8020bfff 64bit] pci 0000:40:16.3: [8086:3433] type 00 class 0x088000 pci 0000:40:16.3: reg 10: [mem 0x8020c000-0x8020ffff 64bit] pci 0000:40:16.4: [8086:3429] type 00 class 0x088000 pci 0000:40:16.4: reg 10: [mem 0x80210000-0x80213fff 64bit] pci 0000:40:16.5: [8086:342a] type 00 class 0x088000 pci 0000:40:16.5: reg 10: [mem 0x80214000-0x80217fff 64bit] pci 0000:40:16.6: [8086:342b] type 00 class 0x088000 pci 0000:40:16.6: reg 10: [mem 0x80218000-0x8021bfff 64bit] pci 0000:40:16.7: [8086:342c] type 00 class 0x088000 pci 0000:40:16.7: reg 10: [mem 0x8021c000-0x8021ffff 64bit] pci 0000:40:00.0: PCI bridge to [bus 41] pci 0000:42:00.0: [8086:10c9] type 00 class 0x020000 pci 0000:42:00.0: reg 10: [mem 0x80160000-0x8017ffff] pci 0000:42:00.0: reg 14: [mem 0x80140000-0x8015ffff] pci 0000:42:00.0: reg 18: [io 0xe020-0xe03f] pci 0000:42:00.0: reg 1c: [mem 0x80184000-0x80187fff] pci 0000:42:00.0: reg 30: [mem 0xfffe0000-0xffffffff pref] pci 0000:42:00.0: PME# supported from D0 D3hot D3cold pci 0000:42:00.1: [8086:10c9] type 00 class 0x020000 pci 0000:42:00.1: reg 10: [mem 0x80120000-0x8013ffff] pci 0000:42:00.1: reg 14: [mem 0x80100000-0x8011ffff] pci 0000:42:00.1: reg 18: [io 0xe000-0xe01f] pci 0000:42:00.1: reg 1c: [mem 0x80180000-0x80183fff] pci 0000:42:00.1: reg 30: [mem 0xfffe0000-0xffffffff pref] pci 0000:42:00.1: PME# supported from D0 D3hot D3cold pci 0000:40:01.0: PCI bridge to [bus 42] pci 0000:40:01.0: bridge window [io 0xe000-0xefff] pci 0000:40:01.0: bridge window [mem 0x80100000-0x801fffff] pci 0000:43:00.0: [1000:0056] type 00 class 0x010000 pci 0000:43:00.0: reg 10: [io 0xc000-0xc0ff] pci 0000:43:00.0: reg 14: [mem 0x80010000-0x80013fff 64bit] pci 0000:43:00.0: reg 1c: [mem 0x80000000-0x8000ffff 64bit] pci 0000:43:00.0: reg 30: [mem 0xffe00000-0xffffffff pref] pci 0000:43:00.0: supports D1 D2 pci 0000:43:00.0: disabling ASPM on pre-1.1 PCIe device. You can enable it with 'pcie_aspm=force' pci 0000:40:03.0: PCI bridge to [bus 43] pci 0000:40:03.0: bridge window [io 0xc000-0xdfff] pci 0000:40:03.0: bridge window [mem 0x80000000-0x800fffff] pci 0000:40:04.0: PCI bridge to [bus 44] pci 0000:40:04.0: bridge window [io 0xb000-0xbfff] pci 0000:40:05.0: PCI bridge to [bus 45] pci 0000:40:05.0: bridge window [io 0xa000-0xafff] pci 0000:40:07.0: PCI bridge to [bus 46] pci 0000:40:07.0: bridge window [io 0x9000-0x9fff] ACPI: PCI Interrupt Routing Table [\_SB_.NOD1.PCI1._PRT] ACPI: PCI Interrupt Routing Table [\_SB_.NOD1.PCI1.MRP1._PRT] ACPI: PCI Interrupt Routing Table [\_SB_.NOD1.PCI1.MRP3._PRT] ACPI: PCI Interrupt Routing Table [\_SB_.NOD1.PCI1.MRP4._PRT] ACPI: PCI Interrupt Routing Table [\_SB_.NOD1.PCI1.MRP5._PRT] ACPI: PCI Interrupt Routing Table [\_SB_.NOD1.PCI1.MRP7._PRT] pci0000:40: Requesting ACPI _OSC control (0x1d) pci0000:40: ACPI _OSC control (0x1d) granted acpi_start_single_object: acpi_device PNP0A08:01, driver pci_root to start acpi_bus_match_device: acpi_device PNP0A08:01, attached driver is pci_root acpi_bus_match_device: attach driver for device device:50 acpi_bus_match_device: acpi_device device:50, attached driver is NULL ACPI: No dock devices found. acpi_bus_match: device PNP0C0F:00 find match driver pci_link ACPI: PCI Interrupt Link [LNKA] (IRQs 3 4 5 *6 7 9 10 11 12 14 15) acpi_bus_match: device PNP0C0F:01 find match driver pci_link ACPI: PCI Interrupt Link [LNKB] (IRQs 3 4 5 6 7 9 10 11 12 14 15) *0, disabled. acpi_bus_match: device PNP0C0F:02 find match driver pci_link ACPI: PCI Interrupt Link [LNKC] (IRQs 3 4 5 6 7 9 10 11 12 14 15) *0, disabled. acpi_bus_match: device PNP0C0F:03 find match driver pci_link ACPI: PCI Interrupt Link [LNKD] (IRQs 3 4 5 6 7 9 10 11 12 14 15) *0, disabled. acpi_bus_match: device PNP0C0F:04 find match driver pci_link ACPI: PCI Interrupt Link [LNKE] (IRQs 3 4 5 6 7 9 10 11 12 14 15) *0, disabled. acpi_bus_match: device PNP0C0F:05 find match driver pci_link ACPI: PCI Interrupt Link [LNKF] (IRQs 3 4 5 6 7 9 10 11 12 14 15) *0, disabled. acpi_bus_match: device PNP0C0F:06 find match driver pci_link ACPI: PCI Interrupt Link [LNKG] (IRQs 3 4 5 6 7 9 10 11 12 14 15) *0, disabled. acpi_bus_match: device PNP0C0F:07 find match driver pci_link ACPI: PCI Interrupt Link [LNKH] (IRQs 3 4 5 6 7 9 10 11 12 14 15) *0, disabled. acpi root: \_SB_.NOD0.PCI0 notify handler is installed acpi root: \_SB_.NOD1.PCI1 notify handler is installed acpi root: \_SB_.NOD2.PCI2 notify handler is installed acpi root: \_SB_.NOD3.PCI3 notify handler is installed Found 4 acpi root devices ================================================================================IOH hot-add dmesg log=================================== ACPI: ACPI device name is <\_SB_.NOD1.PCI1>, event code is <1> ACPI: Notify event is queued _handle_hotplug_event_root: Device check notify on \_SB_.NOD1.PCI1 handle_root_bridge_insertion: hot add acpi_device for acpi_handle 31655c8 acpi_bus_scan: start 0 acpi_bus_check_add: acpi_device PNP0A08:02 added, add_type 1 acpi_bus_check_add: acpi_device ACPI0009:02 added, add_type 1 acpi_bus_check_add: acpi_device device:51 added, add_type 1 acpi_bus_check_add: acpi_device device:52 added, add_type 1 acpi_bus_check_add: acpi_device device:53 added, add_type 1 acpi_bus_check_add: acpi_device device:54 added, add_type 1 acpi_bus_check_add: acpi_device device:55 added, add_type 1 acpi_bus_check_add: acpi_device device:56 added, add_type 1 acpi_bus_check_add: acpi_device device:57 added, add_type 1 acpi_bus_check_add: acpi_device device:58 added, add_type 1 acpi_bus_check_add: acpi_device device:59 added, add_type 1 acpi_bus_check_add: acpi_device device:5a added, add_type 1 acpi_bus_check_add: acpi_device device:5b added, add_type 1 acpi_bus_check_add: acpi_device device:5c added, add_type 1 acpi_bus_check_add: acpi_device device:5d added, add_type 1 acpi_bus_check_add: acpi_device device:5e added, add_type 1 acpi_bus_check_add: acpi_device device:5f added, add_type 1 acpi_bus_check_add: acpi_device device:60 added, add_type 1 acpi_bus_check_add: acpi_device device:61 added, add_type 1 acpi_bus_check_add: acpi_device device:62 added, add_type 1 acpi_bus_check_add: acpi_device device:63 added, add_type 1 acpi_bus_check_add: acpi_device device:64 added, add_type 1 acpi_bus_check_add: acpi_device device:65 added, add_type 1 acpi_bus_check_add: acpi_device device:66 added, add_type 1 acpi_bus_check_add: acpi_device device:67 added, add_type 1 acpi_bus_check_add: acpi_device device:68 added, add_type 1 acpi_bus_check_add: acpi_device device:69 added, add_type 1 acpi_bus_check_add: acpi_device device:6a added, add_type 1 acpi_bus_check_add: acpi_device device:6b added, add_type 1 acpi_bus_match_device: attach driver for device ACPI0009:02 <====================== bus match for PNP0A08:02 missing acpi_bus_match_device: acpi_device ACPI0009:02, attached driver is NULL acpi_bus_match_device: attach driver for device device:51 acpi_bus_match_device: acpi_device device:51, attached driver is NULL acpi_bus_match_device: attach driver for device device:52 acpi_bus_match_device: acpi_device device:52, attached driver is NULL acpi_bus_match_device: attach driver for device device:53 acpi_bus_match_device: acpi_device device:53, attached driver is NULL acpi_bus_match_device: attach driver for device device:54 acpi_bus_match_device: acpi_device device:54, attached driver is NULL acpi_bus_match_device: attach driver for device device:55 acpi_bus_match_device: acpi_device device:55, attached driver is NULL acpi_bus_match_device: attach driver for device device:56 acpi_bus_match_device: acpi_device device:56, attached driver is NULL acpi_bus_match_device: attach driver for device device:57 acpi_bus_match_device: acpi_device device:57, attached driver is NULL acpi_bus_match_device: attach driver for device device:58 acpi_bus_match_device: acpi_device device:58, attached driver is NULL acpi_bus_match_device: attach driver for device device:59 acpi_bus_match_device: acpi_device device:59, attached driver is NULL acpi_bus_match_device: attach driver for device device:5a acpi_bus_match_device: acpi_device device:5a, attached driver is NULL acpi_bus_match_device: attach driver for device device:5b acpi_bus_match_device: acpi_device device:5b, attached driver is NULL acpi_bus_match_device: attach driver for device device:5c acpi_bus_match_device: acpi_device device:5c, attached driver is NULL acpi_bus_match_device: attach driver for device device:5d acpi_bus_match_device: acpi_device device:5d, attached driver is NULL acpi_bus_match_device: attach driver for device device:5e acpi_bus_match_device: acpi_device device:5e, attached driver is NULL acpi_bus_match_device: attach driver for device device:5f acpi_bus_match_device: acpi_device device:5f, attached driver is NULL acpi_bus_match_device: attach driver for device device:60 acpi_bus_match_device: acpi_device device:60, attached driver is NULL acpi_bus_match_device: attach driver for device device:61 acpi_bus_match_device: acpi_device device:61, attached driver is NULL acpi_bus_match_device: attach driver for device device:62 acpi_bus_match_device: acpi_device device:62, attached driver is NULL acpi_bus_match_device: attach driver for device device:63 acpi_bus_match_device: acpi_device device:63, attached driver is NULL acpi_bus_match_device: attach driver for device device:64 acpi_bus_match_device: acpi_device device:64, attached driver is NULL acpi_bus_match_device: attach driver for device device:65 acpi_bus_match_device: acpi_device device:65, attached driver is NULL acpi_bus_match_device: attach driver for device device:66 acpi_bus_match_device: acpi_device device:66, attached driver is NULL acpi_bus_match_device: attach driver for device device:67 acpi_bus_match_device: acpi_device device:67, attached driver is NULL acpi_bus_match_device: attach driver for device device:68 acpi_bus_match_device: acpi_device device:68, attached driver is NULL acpi_bus_match_device: attach driver for device device:69 acpi_bus_match_device: acpi_device device:69, attached driver is NULL acpi_bus_match_device: attach driver for device device:6a acpi_bus_match_device: acpi_device device:6a, attached driver is NULL acpi_bus_match_device: attach driver for device device:6b acpi_bus_match_device: acpi_device device:6b, attached driver is NULL acpi_bus_start: acpi_device PNP0A08:02 acpi_bus_start_device: acpi_device ACPI0009:02 <====================== bus start for PNP0A08:02 missing,so pci_root driver won't be called acpi_bus_start_device: acpi_device device:51 acpi_bus_start_device: acpi_device device:52 acpi_bus_start_device: acpi_device device:53 acpi_bus_start_device: acpi_device device:54 acpi_bus_start_device: acpi_device device:55 acpi_bus_start_device: acpi_device device:56 acpi_bus_start_device: acpi_device device:57 acpi_bus_start_device: acpi_device device:58 acpi_bus_start_device: acpi_device device:59 acpi_bus_start_device: acpi_device device:5a acpi_bus_start_device: acpi_device device:5b acpi_bus_start_device: acpi_device device:5c acpi_bus_start_device: acpi_device device:5d acpi_bus_start_device: acpi_device device:5e acpi_bus_start_device: acpi_device device:5f acpi_bus_start_device: acpi_device device:60 acpi_bus_start_device: acpi_device device:61 acpi_bus_start_device: acpi_device device:62 acpi_bus_start_device: acpi_device device:63 acpi_bus_start_device: acpi_device device:64 acpi_bus_start_device: acpi_device device:65 acpi_bus_start_device: acpi_device device:66 acpi_bus_start_device: acpi_device device:67 acpi_bus_start_device: acpi_device device:68 acpi_bus_start_device: acpi_device device:69 acpi_bus_start_device: acpi_device device:6a acpi_bus_start_device: acpi_device device:6b -- Thanks! Yijing ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH rev.2 0/6] ACPI: Change the ACPI namespace scanning code ordering 2012-12-09 22:58 [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Rafael J. Wysocki ` (6 preceding siblings ...) 2012-12-13 11:45 ` [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Yijing Wang @ 2012-12-13 22:15 ` Rafael J. Wysocki 2012-12-13 22:17 ` [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki ` (6 more replies) 7 siblings, 7 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-13 22:15 UTC (permalink / raw) To: ACPI Devel Maling List Cc: Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu Hi All, On Sunday, December 09, 2012 11:58:42 PM Rafael J. Wysocki wrote: > Hi, > > The following patches change the ordering of the ACPI namespace scanning code > so that all struct acpi_device objects in the given scope are registered before > ACPI drivers are probed against them. They also do some simplifications and > clarifications of the code made possible by this main change. > > This is done for three basic reasons. First, we need the boot ACPI namespace > scanning code to be as similar as reasonably possible to the hot-plug ACPI > namespace scanning code. Second, the ordering of PCI devices enumeration > versus ACPI-backed platform devices registration needs to be such that the PCI > devices in the given scope are all registered first. Finally, when we start to > actually manage ACPI device resources as appropriate (e.g. resolve resource > conflicts properly) we'll need all struct acpi_device nodes to be registered > before any "companion" physical nodes or ACPI drivers are bound to them. > > The patches have been tested on Toshiba Portege R500 without breaking stuff > (I used some additional debug code to verify that the ordering of device > discovery had not been modified by them), but if you see any problems with > them regarding hot-plug, please let me know. > > [1/6] - Separate adding ACPI device objects from probing ACPI drivers. > [2/6] - Change the ordering of PCI root bridge driver registration. > [3/6] - Make acpi_bus_add() and acpi_bus_start() visibly different. > [4/6] - Reduce the usage of struct acpi_bus_ops > [5/6] - Replace struct acpi_bus_ops with an enum type > [6/6] - Change the ordering of acpi_bus_check_add() to avoid unnecessary checks. The second revision is necessary to address problems found by Yijing Wang during testing and explained by Jiang Liu (thanks guys!). The problem is that acpi_walk_namespace() doesn't execute the pre_order_visit callback for the starting handle, so the callback routine has the be executed for it directly, if necessary. I also modified a couple of changelogs to better explain the motivation of the patches. Boot sequence tested on Toshiba Portege R500, but testing on systems with hotplug will be appreciated. Thanks, Rafael -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-13 22:15 ` [PATCH rev.2 " Rafael J. Wysocki @ 2012-12-13 22:17 ` Rafael J. Wysocki 2012-12-18 0:08 ` Toshi Kani 2012-12-13 22:18 ` [PATCH rev.2 2/6] ACPI: Change the ordering of PCI root bridge driver registrarion Rafael J. Wysocki ` (5 subsequent siblings) 6 siblings, 1 reply; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-13 22:17 UTC (permalink / raw) To: ACPI Devel Maling List Cc: Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Split the ACPI namespace scanning for devices into two passes, such that struct acpi_device objects are registerd in the first pass without probing ACPI drivers and the drivers are probed against them directly in the second pass. There are two main reasons for doing that. First, the ACPI PCI root bridge driver's .add() routine, acpi_pci_root_add(), causes struct pci_dev objects to be created for all PCI devices under the given root bridge. Usually, there are corresponding ACPI device nodes in the ACPI namespace for some of those devices and therefore there should be "companion" struct acpi_device objects to attach those struct pci_dev objects to. These struct acpi_device objects should exist when the corresponding struct pci_dev objects are created, but that is only guaranteed during boot and not during hotplug. This leads to a number of functional differences between the boot and the hotplug cases which are not strictly necessary and make the code more complicated. For example, this forces the ACPI PCI root bridge driver to defer the registration of the just created struct pci_dev objects and to use a special .start() callback routine, acpi_pci_root_start(), to make sure that all of the "companion" struct acpi_device objects will be present at PCI devices registration time during hotplug. If those differences can be eliminated, we will be able to consolidate the boot and hotplug code paths for the enumeration and registration of PCI devices and to reduce the complexity of that code quite a bit. The second reason is that, in general, it should be possible to resolve conflicts of resources assigned by the BIOS to different devices represented by ACPI namespace nodes before any drivers bind to them and before they are attached to "companion" objects representing physical devices (such as struct pci_dev). However, for this purpose we first need to enumerate all ACPI device nodes in the given namespace scope. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> --- drivers/acpi/scan.c | 105 +++++++++++++++++++++++++++++++++--------------- include/acpi/acpi_bus.h | 1 2 files changed, 75 insertions(+), 31 deletions(-) Index: linux/include/acpi/acpi_bus.h =================================================================== --- linux.orig/include/acpi/acpi_bus.h +++ linux/include/acpi/acpi_bus.h @@ -98,6 +98,7 @@ typedef void (*acpi_op_notify) (struct a struct acpi_bus_ops { u32 acpi_op_add:1; u32 acpi_op_start:1; + u32 acpi_op_match:1; }; struct acpi_device_ops { Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -494,7 +494,8 @@ static int acpi_bus_match(struct device struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_driver *acpi_drv = to_acpi_driver(drv); - return !acpi_match_device_ids(acpi_dev, acpi_drv->ids); + return acpi_dev->bus_ops.acpi_op_match + && !acpi_match_device_ids(acpi_dev, acpi_drv->ids); } static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) @@ -1418,6 +1419,17 @@ static int acpi_bus_remove(struct acpi_d return 0; } +/* + * acpi_hot_add_bind - Bind _ADR-based devices on hot-add. + * @device: ACPI device node to bind. + */ +static void acpi_hot_add_bind(struct acpi_device *device) +{ + if (device->flags.bus_address + && device->parent && device->parent->ops.bind) + device->parent->ops.bind(device); +} + static int acpi_add_single_object(struct acpi_device **child, acpi_handle handle, int type, unsigned long long sta, @@ -1490,13 +1502,8 @@ static int acpi_add_single_object(struct result = acpi_device_register(device); - /* - * Bind _ADR-Based Devices when hot add - */ - if (device->flags.bus_address) { - if (device->parent && device->parent->ops.bind) - device->parent->ops.bind(device); - } + if (device->bus_ops.acpi_op_match) + acpi_hot_add_bind(device); end: if (!result) { @@ -1522,6 +1529,7 @@ static void acpi_bus_add_power_resource( struct acpi_bus_ops ops = { .acpi_op_add = 1, .acpi_op_start = 1, + .acpi_op_match = 1, }; struct acpi_device *device = NULL; @@ -1574,9 +1582,9 @@ static acpi_status acpi_bus_check_add(ac void *context, void **return_value) { struct acpi_bus_ops *ops = context; + struct acpi_device *device = NULL; int type; unsigned long long sta; - struct acpi_device *device; acpi_status status; int result; @@ -1596,52 +1604,86 @@ static acpi_status acpi_bus_check_add(ac return AE_CTRL_DEPTH; } - /* - * We may already have an acpi_device from a previous enumeration. If - * so, we needn't add it again, but we may still have to start it. - */ - device = NULL; acpi_bus_get_device(handle, &device); if (ops->acpi_op_add && !device) { - acpi_add_single_object(&device, handle, type, sta, ops); - /* Is the device a known good platform device? */ - if (device - && !acpi_match_device_ids(device, acpi_platform_device_ids)) - acpi_create_platform_device(device); - } - - if (!device) - return AE_CTRL_DEPTH; + struct acpi_bus_ops add_ops = *ops; - if (ops->acpi_op_start && !(ops->acpi_op_add)) { - status = acpi_start_single_object(device); - if (ACPI_FAILURE(status)) + add_ops.acpi_op_match = 0; + acpi_add_single_object(&device, handle, type, sta, &add_ops); + if (!device) return AE_CTRL_DEPTH; + + device->bus_ops.acpi_op_match = 1; } if (!*return_value) *return_value = device; + return AE_OK; } +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl, + void *context, void **not_used) +{ + struct acpi_bus_ops *ops = context; + acpi_status status = AE_OK; + struct acpi_device *device; + unsigned long long sta_not_used; + int type_not_used; + + /* + * Ignore errors ignored by acpi_bus_check_add() to avoid terminating + * namespace walks prematurely. + */ + if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used)) + return AE_OK; + + if (acpi_bus_get_device(handle, &device)) + return AE_CTRL_DEPTH; + + if (ops->acpi_op_add) { + if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { + /* This is a known good platform device. */ + acpi_create_platform_device(device); + } else { + int ret = device_attach(&device->dev); + acpi_hot_add_bind(device); + if (ret) + status = AE_CTRL_DEPTH; + } + } else if (ops->acpi_op_start) { + if (ACPI_FAILURE(acpi_start_single_object(device))) + status = AE_CTRL_DEPTH; + } + return status; +} + static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops, struct acpi_device **child) { - acpi_status status; void *device = NULL; + acpi_status status; + int ret = -ENODEV; status = acpi_bus_check_add(handle, 0, ops, &device); if (ACPI_SUCCESS(status)) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, acpi_bus_check_add, NULL, ops, &device); + if (!device) + goto out; + + ret = 0; + status = acpi_bus_probe_start(handle, 0, ops, NULL); + if (ACPI_SUCCESS(status)) + acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, + acpi_bus_probe_start, NULL, ops, NULL); + + out: if (child) *child = device; - if (device) - return 0; - else - return -ENODEV; + return ret; } /* @@ -1752,6 +1794,7 @@ static int acpi_bus_scan_fixed(void) memset(&ops, 0, sizeof(ops)); ops.acpi_op_add = 1; ops.acpi_op_start = 1; + ops.acpi_op_match = 1; /* * Enumerate all fixed-feature devices. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-13 22:17 ` [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki @ 2012-12-18 0:08 ` Toshi Kani 2012-12-18 1:48 ` Rafael J. Wysocki 0 siblings, 1 reply; 88+ messages in thread From: Toshi Kani @ 2012-12-18 0:08 UTC (permalink / raw) To: Rafael J. Wysocki Cc: ACPI Devel Maling List, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu On Thu, 2012-12-13 at 23:17 +0100, Rafael J. Wysocki wrote: > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > (snip) > struct acpi_device_ops { > Index: linux/drivers/acpi/scan.c > =================================================================== > --- linux.orig/drivers/acpi/scan.c > +++ linux/drivers/acpi/scan.c > @@ -494,7 +494,8 @@ static int acpi_bus_match(struct device > struct acpi_device *acpi_dev = to_acpi_device(dev); > struct acpi_driver *acpi_drv = to_acpi_driver(drv); > > - return !acpi_match_device_ids(acpi_dev, acpi_drv->ids); > + return acpi_dev->bus_ops.acpi_op_match > + && !acpi_match_device_ids(acpi_dev, acpi_drv->ids); > } > > static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) > @@ -1418,6 +1419,17 @@ static int acpi_bus_remove(struct acpi_d > return 0; > } > > +/* > + * acpi_hot_add_bind - Bind _ADR-based devices on hot-add. > + * @device: ACPI device node to bind. > + */ > +static void acpi_hot_add_bind(struct acpi_device *device) > +{ > + if (device->flags.bus_address > + && device->parent && device->parent->ops.bind) > + device->parent->ops.bind(device); > +} > + > static int acpi_add_single_object(struct acpi_device **child, > acpi_handle handle, int type, > unsigned long long sta, > @@ -1490,13 +1502,8 @@ static int acpi_add_single_object(struct > > result = acpi_device_register(device); > > - /* > - * Bind _ADR-Based Devices when hot add > - */ > - if (device->flags.bus_address) { > - if (device->parent && device->parent->ops.bind) > - device->parent->ops.bind(device); > - } I think the original code above is hot-add only because ops.bind is not set at boot since the acpi_pci driver has not been registered yet. It seems that acpi_pci_bridge_scan() called from acpi_pci_root_add() takes care of the binding. This brings me a question for acpi_bus_probe_start() below... > + if (device->bus_ops.acpi_op_match) > + acpi_hot_add_bind(device); > > end: > if (!result) { > @@ -1522,6 +1529,7 @@ static void acpi_bus_add_power_resource( > struct acpi_bus_ops ops = { > .acpi_op_add = 1, > .acpi_op_start = 1, > + .acpi_op_match = 1, > }; > struct acpi_device *device = NULL; > > @@ -1574,9 +1582,9 @@ static acpi_status acpi_bus_check_add(ac > void *context, void **return_value) > { > struct acpi_bus_ops *ops = context; > + struct acpi_device *device = NULL; > int type; > unsigned long long sta; > - struct acpi_device *device; > acpi_status status; > int result; > > @@ -1596,52 +1604,86 @@ static acpi_status acpi_bus_check_add(ac > return AE_CTRL_DEPTH; > } > > - /* > - * We may already have an acpi_device from a previous enumeration. If > - * so, we needn't add it again, but we may still have to start it. > - */ > - device = NULL; > acpi_bus_get_device(handle, &device); > if (ops->acpi_op_add && !device) { > - acpi_add_single_object(&device, handle, type, sta, ops); > - /* Is the device a known good platform device? */ > - if (device > - && !acpi_match_device_ids(device, acpi_platform_device_ids)) > - acpi_create_platform_device(device); > - } > - > - if (!device) > - return AE_CTRL_DEPTH; > + struct acpi_bus_ops add_ops = *ops; > > - if (ops->acpi_op_start && !(ops->acpi_op_add)) { > - status = acpi_start_single_object(device); > - if (ACPI_FAILURE(status)) > + add_ops.acpi_op_match = 0; > + acpi_add_single_object(&device, handle, type, sta, &add_ops); > + if (!device) > return AE_CTRL_DEPTH; > + > + device->bus_ops.acpi_op_match = 1; > } > > if (!*return_value) > *return_value = device; > + > return AE_OK; > } > > +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl, > + void *context, void **not_used) > +{ > + struct acpi_bus_ops *ops = context; > + acpi_status status = AE_OK; > + struct acpi_device *device; > + unsigned long long sta_not_used; > + int type_not_used; > + > + /* > + * Ignore errors ignored by acpi_bus_check_add() to avoid terminating "ignore" seems duplicated. > + * namespace walks prematurely. > + */ > + if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used)) > + return AE_OK; > + > + if (acpi_bus_get_device(handle, &device)) > + return AE_CTRL_DEPTH; > + > + if (ops->acpi_op_add) { > + if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { > + /* This is a known good platform device. */ > + acpi_create_platform_device(device); > + } else { > + int ret = device_attach(&device->dev); > + acpi_hot_add_bind(device); Since acpi_pci_root_add() is called by device_attach(), I think this acpi_hot_add_bind() calls .bind() of a device at boot since its .bind() may be set. Is that correct? If so, how does it coordinate with the bind procedure in acpi_pci_bridge_scan()? Thanks, -Toshi ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-18 0:08 ` Toshi Kani @ 2012-12-18 1:48 ` Rafael J. Wysocki 2012-12-18 16:10 ` Toshi Kani 2012-12-20 1:45 ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki 0 siblings, 2 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-18 1:48 UTC (permalink / raw) To: Toshi Kani Cc: ACPI Devel Maling List, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu On Monday, December 17, 2012 05:08:17 PM Toshi Kani wrote: > On Thu, 2012-12-13 at 23:17 +0100, Rafael J. Wysocki wrote: > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > > > (snip) > > > struct acpi_device_ops { > > Index: linux/drivers/acpi/scan.c > > =================================================================== > > --- linux.orig/drivers/acpi/scan.c > > +++ linux/drivers/acpi/scan.c > > @@ -494,7 +494,8 @@ static int acpi_bus_match(struct device > > struct acpi_device *acpi_dev = to_acpi_device(dev); > > struct acpi_driver *acpi_drv = to_acpi_driver(drv); > > > > - return !acpi_match_device_ids(acpi_dev, acpi_drv->ids); > > + return acpi_dev->bus_ops.acpi_op_match > > + && !acpi_match_device_ids(acpi_dev, acpi_drv->ids); > > } > > > > static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) > > @@ -1418,6 +1419,17 @@ static int acpi_bus_remove(struct acpi_d > > return 0; > > } > > > > +/* > > + * acpi_hot_add_bind - Bind _ADR-based devices on hot-add. > > + * @device: ACPI device node to bind. > > + */ > > +static void acpi_hot_add_bind(struct acpi_device *device) > > +{ > > + if (device->flags.bus_address > > + && device->parent && device->parent->ops.bind) > > + device->parent->ops.bind(device); > > +} > > + > > static int acpi_add_single_object(struct acpi_device **child, > > acpi_handle handle, int type, > > unsigned long long sta, > > @@ -1490,13 +1502,8 @@ static int acpi_add_single_object(struct > > > > result = acpi_device_register(device); > > > > - /* > > - * Bind _ADR-Based Devices when hot add > > - */ > > - if (device->flags.bus_address) { > > - if (device->parent && device->parent->ops.bind) > > - device->parent->ops.bind(device); > > - } > > I think the original code above is hot-add only because ops.bind is not > set at boot since the acpi_pci driver has not been registered yet. It > seems that acpi_pci_bridge_scan() called from acpi_pci_root_add() takes > care of the binding. Ah, I see the problem. During boot the PCI root bridge driver is not present yet when all struct acpi_device "devices" are registered, so their parents' .bind() callbacks are all empty, so the code above has no effect. But say we're doing a PCI root bridge hotplug, in which case the driver is present, so acpi_pci_bind() will be executed both from acpi_pci_bridge_scan() and from here, won't it? OK, this needs to be addressed. > This brings me a question for acpi_bus_probe_start() below... > > > > + if (device->bus_ops.acpi_op_match) > > + acpi_hot_add_bind(device); > > > > end: > > if (!result) { > > @@ -1522,6 +1529,7 @@ static void acpi_bus_add_power_resource( > > struct acpi_bus_ops ops = { > > .acpi_op_add = 1, > > .acpi_op_start = 1, > > + .acpi_op_match = 1, > > }; > > struct acpi_device *device = NULL; > > > > @@ -1574,9 +1582,9 @@ static acpi_status acpi_bus_check_add(ac > > void *context, void **return_value) > > { > > struct acpi_bus_ops *ops = context; > > + struct acpi_device *device = NULL; > > int type; > > unsigned long long sta; > > - struct acpi_device *device; > > acpi_status status; > > int result; > > > > @@ -1596,52 +1604,86 @@ static acpi_status acpi_bus_check_add(ac > > return AE_CTRL_DEPTH; > > } > > > > - /* > > - * We may already have an acpi_device from a previous enumeration. If > > - * so, we needn't add it again, but we may still have to start it. > > - */ > > - device = NULL; > > acpi_bus_get_device(handle, &device); > > if (ops->acpi_op_add && !device) { > > - acpi_add_single_object(&device, handle, type, sta, ops); > > - /* Is the device a known good platform device? */ > > - if (device > > - && !acpi_match_device_ids(device, acpi_platform_device_ids)) > > - acpi_create_platform_device(device); > > - } > > - > > - if (!device) > > - return AE_CTRL_DEPTH; > > + struct acpi_bus_ops add_ops = *ops; > > > > - if (ops->acpi_op_start && !(ops->acpi_op_add)) { > > - status = acpi_start_single_object(device); > > - if (ACPI_FAILURE(status)) > > + add_ops.acpi_op_match = 0; > > + acpi_add_single_object(&device, handle, type, sta, &add_ops); > > + if (!device) > > return AE_CTRL_DEPTH; > > + > > + device->bus_ops.acpi_op_match = 1; > > } > > > > if (!*return_value) > > *return_value = device; > > + > > return AE_OK; > > } > > > > +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl, > > + void *context, void **not_used) > > +{ > > + struct acpi_bus_ops *ops = context; > > + acpi_status status = AE_OK; > > + struct acpi_device *device; > > + unsigned long long sta_not_used; > > + int type_not_used; > > + > > + /* > > + * Ignore errors ignored by acpi_bus_check_add() to avoid terminating > > "ignore" seems duplicated. It is not. This is supposed to mean that the errors previously ignored by acpi_bus_check_add() should be ignored here as well. > > + * namespace walks prematurely. > > + */ > > + if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used)) > > + return AE_OK; > > + > > + if (acpi_bus_get_device(handle, &device)) > > + return AE_CTRL_DEPTH; > > + > > + if (ops->acpi_op_add) { > > + if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { > > + /* This is a known good platform device. */ > > + acpi_create_platform_device(device); > > + } else { > > + int ret = device_attach(&device->dev); > > + acpi_hot_add_bind(device); > > Since acpi_pci_root_add() is called by device_attach(), I think this > acpi_hot_add_bind() calls .bind() of a device at boot since its .bind() > may be set. Is that correct? If so, how does it coordinate with the > bind procedure in acpi_pci_bridge_scan()? It actually doesn't. However, the $subject patch doesn't change this particular aspect of the original behavior, because with it applied the PCI root bridge driver is still not present when the device_attach() above is executed for all objects in the given namespace scope, so the .bind() callbacks should all be empty. In other words, it doesn't change the boot case. It also reproduces the original behavior in the hotplug case which may not be correct. Patch [2/6], however, kind of changes the boot case into the hotplug case and things start to get ugly. Well, what about calling acpi_hot_add_bind() from acpi_bus_check_add(), right after doing the acpi_add_single_object()? It would avoid calling acpi_pci_bind() twice for the same device during root bridge hotplug too, because in that case acpi_pci_root_add() will be called after all of these acpi_hot_add_bind() calls. At the same time if a single device is hot-added and its parent happens to have .bind() set, it will be run from acpi_bus_check_add(). Updated patch is appended. Thanks, Rafael --- From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Subject: ACPI: Separate adding ACPI device objects from probing ACPI drivers Split the ACPI namespace scanning for devices into two passes, such that struct acpi_device objects are registerd in the first pass without probing ACPI drivers and the drivers are probed against them directly in the second pass. There are two main reasons for doing that. First, the ACPI PCI root bridge driver's .add() routine, acpi_pci_root_add(), causes struct pci_dev objects to be created for all PCI devices under the given root bridge. Usually, there are corresponding ACPI device nodes in the ACPI namespace for some of those devices and therefore there should be "companion" struct acpi_device objects to attach those struct pci_dev objects to. These struct acpi_device objects should exist when the corresponding struct pci_dev objects are created, but that is only guaranteed during boot and not during hotplug. This leads to a number of functional differences between the boot and the hotplug cases which are not strictly necessary and make the code more complicated. For example, this forces the ACPI PCI root bridge driver to defer the registration of the just created struct pci_dev objects and to use a special .start() callback routine, acpi_pci_root_start(), to make sure that all of the "companion" struct acpi_device objects will be present at PCI devices registration time during hotplug. If those differences can be eliminated, we will be able to consolidate the boot and hotplug code paths for the enumeration and registration of PCI devices and to reduce the complexity of that code quite a bit. The second reason is that, in general, it should be possible to resolve conflicts of resources assigned by the BIOS to different devices represented by ACPI namespace nodes before any drivers bind to them and before they are attached to "companion" objects representing physical devices (such as struct pci_dev). However, for this purpose we first need to enumerate all ACPI device nodes in the given namespace scope. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> --- drivers/acpi/scan.c | 103 +++++++++++++++++++++++++++++++++--------------- include/acpi/acpi_bus.h | 1 2 files changed, 73 insertions(+), 31 deletions(-) Index: linux/include/acpi/acpi_bus.h =================================================================== --- linux.orig/include/acpi/acpi_bus.h +++ linux/include/acpi/acpi_bus.h @@ -98,6 +98,7 @@ typedef void (*acpi_op_notify) (struct a struct acpi_bus_ops { u32 acpi_op_add:1; u32 acpi_op_start:1; + u32 acpi_op_match:1; }; struct acpi_device_ops { Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -494,7 +494,8 @@ static int acpi_bus_match(struct device struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_driver *acpi_drv = to_acpi_driver(drv); - return !acpi_match_device_ids(acpi_dev, acpi_drv->ids); + return acpi_dev->bus_ops.acpi_op_match + && !acpi_match_device_ids(acpi_dev, acpi_drv->ids); } static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) @@ -1418,6 +1419,17 @@ static int acpi_bus_remove(struct acpi_d return 0; } +/* + * acpi_hot_add_bind - Bind _ADR-based devices on hot-add. + * @device: ACPI device node to bind. + */ +static void acpi_hot_add_bind(struct acpi_device *device) +{ + if (device->flags.bus_address + && device->parent && device->parent->ops.bind) + device->parent->ops.bind(device); +} + static int acpi_add_single_object(struct acpi_device **child, acpi_handle handle, int type, unsigned long long sta, @@ -1490,13 +1502,8 @@ static int acpi_add_single_object(struct result = acpi_device_register(device); - /* - * Bind _ADR-Based Devices when hot add - */ - if (device->flags.bus_address) { - if (device->parent && device->parent->ops.bind) - device->parent->ops.bind(device); - } + if (device->bus_ops.acpi_op_match) + acpi_hot_add_bind(device); end: if (!result) { @@ -1522,6 +1529,7 @@ static void acpi_bus_add_power_resource( struct acpi_bus_ops ops = { .acpi_op_add = 1, .acpi_op_start = 1, + .acpi_op_match = 1, }; struct acpi_device *device = NULL; @@ -1574,9 +1582,9 @@ static acpi_status acpi_bus_check_add(ac void *context, void **return_value) { struct acpi_bus_ops *ops = context; + struct acpi_device *device = NULL; int type; unsigned long long sta; - struct acpi_device *device; acpi_status status; int result; @@ -1596,52 +1604,84 @@ static acpi_status acpi_bus_check_add(ac return AE_CTRL_DEPTH; } - /* - * We may already have an acpi_device from a previous enumeration. If - * so, we needn't add it again, but we may still have to start it. - */ - device = NULL; acpi_bus_get_device(handle, &device); if (ops->acpi_op_add && !device) { - acpi_add_single_object(&device, handle, type, sta, ops); - /* Is the device a known good platform device? */ - if (device - && !acpi_match_device_ids(device, acpi_platform_device_ids)) - acpi_create_platform_device(device); - } - - if (!device) - return AE_CTRL_DEPTH; + struct acpi_bus_ops add_ops = *ops; - if (ops->acpi_op_start && !(ops->acpi_op_add)) { - status = acpi_start_single_object(device); - if (ACPI_FAILURE(status)) + add_ops.acpi_op_match = 0; + acpi_add_single_object(&device, handle, type, sta, &add_ops); + if (!device) return AE_CTRL_DEPTH; + + device->bus_ops.acpi_op_match = 1; + acpi_hot_add_bind(device); } if (!*return_value) *return_value = device; + return AE_OK; } +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl, + void *context, void **not_used) +{ + struct acpi_bus_ops *ops = context; + acpi_status status = AE_OK; + struct acpi_device *device; + unsigned long long sta_not_used; + int type_not_used; + + /* + * Ignore errors ignored by acpi_bus_check_add() to avoid terminating + * namespace walks prematurely. + */ + if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used)) + return AE_OK; + + if (acpi_bus_get_device(handle, &device)) + return AE_CTRL_DEPTH; + + if (ops->acpi_op_add) { + if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { + /* This is a known good platform device. */ + acpi_create_platform_device(device); + } else if (device_attach(&device->dev)) { + status = AE_CTRL_DEPTH; + } + } else if (ops->acpi_op_start) { + if (ACPI_FAILURE(acpi_start_single_object(device))) + status = AE_CTRL_DEPTH; + } + return status; +} + static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops, struct acpi_device **child) { - acpi_status status; void *device = NULL; + acpi_status status; + int ret = -ENODEV; status = acpi_bus_check_add(handle, 0, ops, &device); if (ACPI_SUCCESS(status)) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, acpi_bus_check_add, NULL, ops, &device); + if (!device) + goto out; + + ret = 0; + status = acpi_bus_probe_start(handle, 0, ops, NULL); + if (ACPI_SUCCESS(status)) + acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, + acpi_bus_probe_start, NULL, ops, NULL); + + out: if (child) *child = device; - if (device) - return 0; - else - return -ENODEV; + return ret; } /* @@ -1752,6 +1792,7 @@ static int acpi_bus_scan_fixed(void) memset(&ops, 0, sizeof(ops)); ops.acpi_op_add = 1; ops.acpi_op_start = 1; + ops.acpi_op_match = 1; /* * Enumerate all fixed-feature devices. -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-18 1:48 ` Rafael J. Wysocki @ 2012-12-18 16:10 ` Toshi Kani 2012-12-18 18:59 ` Yinghai Lu 2012-12-18 21:57 ` Rafael J. Wysocki 2012-12-20 1:45 ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki 1 sibling, 2 replies; 88+ messages in thread From: Toshi Kani @ 2012-12-18 16:10 UTC (permalink / raw) To: Rafael J. Wysocki Cc: ACPI Devel Maling List, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu On Tue, 2012-12-18 at 02:48 +0100, Rafael J. Wysocki wrote: > On Monday, December 17, 2012 05:08:17 PM Toshi Kani wrote: > > On Thu, 2012-12-13 at 23:17 +0100, Rafael J. Wysocki wrote: > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > > > > > > (snip) > > > > > struct acpi_device_ops { > > > Index: linux/drivers/acpi/scan.c > > > =================================================================== > > > --- linux.orig/drivers/acpi/scan.c > > > +++ linux/drivers/acpi/scan.c > > > @@ -494,7 +494,8 @@ static int acpi_bus_match(struct device > > > struct acpi_device *acpi_dev = to_acpi_device(dev); > > > struct acpi_driver *acpi_drv = to_acpi_driver(drv); > > > > > > - return !acpi_match_device_ids(acpi_dev, acpi_drv->ids); > > > + return acpi_dev->bus_ops.acpi_op_match > > > + && !acpi_match_device_ids(acpi_dev, acpi_drv->ids); > > > } > > > > > > static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) > > > @@ -1418,6 +1419,17 @@ static int acpi_bus_remove(struct acpi_d > > > return 0; > > > } > > > > > > +/* > > > + * acpi_hot_add_bind - Bind _ADR-based devices on hot-add. > > > + * @device: ACPI device node to bind. > > > + */ > > > +static void acpi_hot_add_bind(struct acpi_device *device) > > > +{ > > > + if (device->flags.bus_address > > > + && device->parent && device->parent->ops.bind) > > > + device->parent->ops.bind(device); > > > +} > > > + > > > static int acpi_add_single_object(struct acpi_device **child, > > > acpi_handle handle, int type, > > > unsigned long long sta, > > > @@ -1490,13 +1502,8 @@ static int acpi_add_single_object(struct > > > > > > result = acpi_device_register(device); > > > > > > - /* > > > - * Bind _ADR-Based Devices when hot add > > > - */ > > > - if (device->flags.bus_address) { > > > - if (device->parent && device->parent->ops.bind) > > > - device->parent->ops.bind(device); > > > - } > > > > I think the original code above is hot-add only because ops.bind is not > > set at boot since the acpi_pci driver has not been registered yet. It > > seems that acpi_pci_bridge_scan() called from acpi_pci_root_add() takes > > care of the binding. > > Ah, I see the problem. During boot the PCI root bridge driver is not present > yet when all struct acpi_device "devices" are registered, so their parents' > .bind() callbacks are all empty, so the code above has no effect. > > But say we're doing a PCI root bridge hotplug, in which case the driver is > present, so acpi_pci_bind() will be executed both from acpi_pci_bridge_scan() > and from here, won't it? Right. > OK, this needs to be addressed. > > > This brings me a question for acpi_bus_probe_start() below... > > > > > > > + if (device->bus_ops.acpi_op_match) > > > + acpi_hot_add_bind(device); > > > > > > end: > > > if (!result) { > > > @@ -1522,6 +1529,7 @@ static void acpi_bus_add_power_resource( > > > struct acpi_bus_ops ops = { > > > .acpi_op_add = 1, > > > .acpi_op_start = 1, > > > + .acpi_op_match = 1, > > > }; > > > struct acpi_device *device = NULL; > > > > > > @@ -1574,9 +1582,9 @@ static acpi_status acpi_bus_check_add(ac > > > void *context, void **return_value) > > > { > > > struct acpi_bus_ops *ops = context; > > > + struct acpi_device *device = NULL; > > > int type; > > > unsigned long long sta; > > > - struct acpi_device *device; > > > acpi_status status; > > > int result; > > > > > > @@ -1596,52 +1604,86 @@ static acpi_status acpi_bus_check_add(ac > > > return AE_CTRL_DEPTH; > > > } > > > > > > - /* > > > - * We may already have an acpi_device from a previous enumeration. If > > > - * so, we needn't add it again, but we may still have to start it. > > > - */ > > > - device = NULL; > > > acpi_bus_get_device(handle, &device); > > > if (ops->acpi_op_add && !device) { > > > - acpi_add_single_object(&device, handle, type, sta, ops); > > > - /* Is the device a known good platform device? */ > > > - if (device > > > - && !acpi_match_device_ids(device, acpi_platform_device_ids)) > > > - acpi_create_platform_device(device); > > > - } > > > - > > > - if (!device) > > > - return AE_CTRL_DEPTH; > > > + struct acpi_bus_ops add_ops = *ops; > > > > > > - if (ops->acpi_op_start && !(ops->acpi_op_add)) { > > > - status = acpi_start_single_object(device); > > > - if (ACPI_FAILURE(status)) > > > + add_ops.acpi_op_match = 0; > > > + acpi_add_single_object(&device, handle, type, sta, &add_ops); > > > + if (!device) > > > return AE_CTRL_DEPTH; > > > + > > > + device->bus_ops.acpi_op_match = 1; > > > } > > > > > > if (!*return_value) > > > *return_value = device; > > > + > > > return AE_OK; > > > } > > > > > > +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl, > > > + void *context, void **not_used) > > > +{ > > > + struct acpi_bus_ops *ops = context; > > > + acpi_status status = AE_OK; > > > + struct acpi_device *device; > > > + unsigned long long sta_not_used; > > > + int type_not_used; > > > + > > > + /* > > > + * Ignore errors ignored by acpi_bus_check_add() to avoid terminating > > > > "ignore" seems duplicated. > > It is not. This is supposed to mean that the errors previously ignored by > acpi_bus_check_add() should be ignored here as well. Oh, I see. Thanks for the clarification. > > > + * namespace walks prematurely. > > > + */ > > > + if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used)) > > > + return AE_OK; > > > + > > > + if (acpi_bus_get_device(handle, &device)) > > > + return AE_CTRL_DEPTH; > > > + > > > + if (ops->acpi_op_add) { > > > + if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { > > > + /* This is a known good platform device. */ > > > + acpi_create_platform_device(device); > > > + } else { > > > + int ret = device_attach(&device->dev); > > > + acpi_hot_add_bind(device); > > > > Since acpi_pci_root_add() is called by device_attach(), I think this > > acpi_hot_add_bind() calls .bind() of a device at boot since its .bind() > > may be set. Is that correct? If so, how does it coordinate with the > > bind procedure in acpi_pci_bridge_scan()? > > It actually doesn't. > > However, the $subject patch doesn't change this particular aspect of the > original behavior, because with it applied the PCI root bridge driver is still > not present when the device_attach() above is executed for all objects in the > given namespace scope, so the .bind() callbacks should all be empty. In other > words, it doesn't change the boot case. > > It also reproduces the original behavior in the hotplug case which may not be > correct. Patch [2/6], however, kind of changes the boot case into the hotplug > case and things start to get ugly. Yes, I was concerned with the behavior when patch [2/6] applied. It is actually a good thing that this hotplug issue is now exposed in the boot path. This means that boot and hot-add paths are consistent. So, we just need to fix it. > Well, what about calling acpi_hot_add_bind() from acpi_bus_check_add(), > right after doing the acpi_add_single_object()? It would avoid calling > acpi_pci_bind() twice for the same device during root bridge hotplug too, > because in that case acpi_pci_root_add() will be called after all of these > acpi_hot_add_bind() calls. At the same time if a single device is > hot-added and its parent happens to have .bind() set, it will be run > from acpi_bus_check_add(). I may be missing something here, but in case of root bridge hot-add, I think acpi_pci_root_add() still calls .bind() after acpi_bus_check_add() called it. So, it's called twice, isn't it? We need to decide which module is responsible for calling .bind(). I think it should be the ACPI scan module, not the ACPI PCI root bridge driver, because: - bind() needs to be called when _ADR device is added. The ACPI scan module can scan any devices, while the PCI root driver can only scan when it is added. - acpi_bus_remove() calls unbind() at hot-remove. The same module should be responsible for both bind() and unbind() handling. - It is cleaner to keep struct acpi_device_ops interface to be called by the ACPI core. So, I would propose the following changes. - Move the acpi_hot_add_bind() call back to the original place after the device_attach() call. - Rename the name of acpi_hot_add_bind() to something like acpi_bind_adr_device() since it is no longer hot-add only (and is specific to _ADR devices). - Create its pair function, acpi_unbind_adr_device(), which is called from acpi_bus_remove(). When a constructor interface is introduced, its destructor should be introduced as well. - Remove the binding procedure from acpi_pci_root_add(). This should be done in patch [2/6]. Thanks, -Toshi ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-18 16:10 ` Toshi Kani @ 2012-12-18 18:59 ` Yinghai Lu 2012-12-18 20:48 ` Toshi Kani 2012-12-18 22:05 ` Rafael J. Wysocki 2012-12-18 21:57 ` Rafael J. Wysocki 1 sibling, 2 replies; 88+ messages in thread From: Yinghai Lu @ 2012-12-18 18:59 UTC (permalink / raw) To: Toshi Kani Cc: Rafael J. Wysocki, ACPI Devel Maling List, Bjorn Helgaas, LKML, linux-pci, Myron Stowe, Yijing Wang, Jiang Liu On Tue, Dec 18, 2012 at 8:10 AM, Toshi Kani <toshi.kani@hp.com> wrote: > On Tue, 2012-12-18 at 02:48 +0100, Rafael J. Wysocki wrote: > > So, I would propose the following changes. > > - Move the acpi_hot_add_bind() call back to the original place after > the device_attach() call. > - Rename the name of acpi_hot_add_bind() to something like > acpi_bind_adr_device() since it is no longer hot-add only (and is > specific to _ADR devices). > - Create its pair function, acpi_unbind_adr_device(), which is called > from acpi_bus_remove(). When a constructor interface is introduced, its > destructor should be introduced as well. > - Remove the binding procedure from acpi_pci_root_add(). This should > be done in patch [2/6]. i think we should put jiang four patches before Rafael's patches. http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=shortlog;h=refs/heads/for-pci-jiang-hotplug ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-18 18:59 ` Yinghai Lu @ 2012-12-18 20:48 ` Toshi Kani 2012-12-18 21:11 ` Yinghai Lu 2012-12-18 22:05 ` Rafael J. Wysocki 1 sibling, 1 reply; 88+ messages in thread From: Toshi Kani @ 2012-12-18 20:48 UTC (permalink / raw) To: Yinghai Lu Cc: Rafael J. Wysocki, ACPI Devel Maling List, Bjorn Helgaas, LKML, linux-pci, Myron Stowe, Yijing Wang, Jiang Liu On Tue, 2012-12-18 at 10:59 -0800, Yinghai Lu wrote: > On Tue, Dec 18, 2012 at 8:10 AM, Toshi Kani <toshi.kani@hp.com> wrote: > > On Tue, 2012-12-18 at 02:48 +0100, Rafael J. Wysocki wrote: > > > > So, I would propose the following changes. > > > > - Move the acpi_hot_add_bind() call back to the original place after > > the device_attach() call. > > - Rename the name of acpi_hot_add_bind() to something like > > acpi_bind_adr_device() since it is no longer hot-add only (and is > > specific to _ADR devices). > > - Create its pair function, acpi_unbind_adr_device(), which is called > > from acpi_bus_remove(). When a constructor interface is introduced, its > > destructor should be introduced as well. > > - Remove the binding procedure from acpi_pci_root_add(). This should > > be done in patch [2/6]. > > i think we should put jiang four patches before Rafael's patches. > > http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=shortlog;h=refs/heads/for-pci-jiang-hotplug Thanks for the pointer! Oh, I did not know that pci_dev gets removed before acpi_bus_trim() is called... I looked at Jiang's last two patches for the bind update, and they look good to me. Thanks, -Toshi ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-18 20:48 ` Toshi Kani @ 2012-12-18 21:11 ` Yinghai Lu 0 siblings, 0 replies; 88+ messages in thread From: Yinghai Lu @ 2012-12-18 21:11 UTC (permalink / raw) To: Toshi Kani Cc: Rafael J. Wysocki, ACPI Devel Maling List, Bjorn Helgaas, LKML, linux-pci, Myron Stowe, Yijing Wang, Jiang Liu On Tue, Dec 18, 2012 at 12:48 PM, Toshi Kani <toshi.kani@hp.com> wrote: > On Tue, 2012-12-18 at 10:59 -0800, Yinghai Lu wrote: >> On Tue, Dec 18, 2012 at 8:10 AM, Toshi Kani <toshi.kani@hp.com> wrote: >> > On Tue, 2012-12-18 at 02:48 +0100, Rafael J. Wysocki wrote: >> > >> > So, I would propose the following changes. >> > >> > - Move the acpi_hot_add_bind() call back to the original place after >> > the device_attach() call. >> > - Rename the name of acpi_hot_add_bind() to something like >> > acpi_bind_adr_device() since it is no longer hot-add only (and is >> > specific to _ADR devices). >> > - Create its pair function, acpi_unbind_adr_device(), which is called >> > from acpi_bus_remove(). When a constructor interface is introduced, its >> > destructor should be introduced as well. >> > - Remove the binding procedure from acpi_pci_root_add(). This should >> > be done in patch [2/6]. >> >> i think we should put jiang four patches before Rafael's patches. >> >> http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=shortlog;h=refs/heads/for-pci-jiang-hotplug > > Thanks for the pointer! Oh, I did not know that pci_dev gets removed > before acpi_bus_trim() is called... yes. that is http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=8b4b836d8c56c290bc80ffa0b08b91fb3fe38867 > I looked at Jiang's last two > patches for the bind update, and they look good to me. > > Thanks, > -Toshi > ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-18 18:59 ` Yinghai Lu 2012-12-18 20:48 ` Toshi Kani @ 2012-12-18 22:05 ` Rafael J. Wysocki 2012-12-19 1:57 ` Yinghai Lu 1 sibling, 1 reply; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-18 22:05 UTC (permalink / raw) To: Yinghai Lu Cc: Toshi Kani, ACPI Devel Maling List, Bjorn Helgaas, LKML, linux-pci, Myron Stowe, Yijing Wang, Jiang Liu On Tuesday, December 18, 2012 10:59:46 AM Yinghai Lu wrote: > On Tue, Dec 18, 2012 at 8:10 AM, Toshi Kani <toshi.kani@hp.com> wrote: > > On Tue, 2012-12-18 at 02:48 +0100, Rafael J. Wysocki wrote: > > > > So, I would propose the following changes. > > > > - Move the acpi_hot_add_bind() call back to the original place after > > the device_attach() call. > > - Rename the name of acpi_hot_add_bind() to something like > > acpi_bind_adr_device() since it is no longer hot-add only (and is > > specific to _ADR devices). > > - Create its pair function, acpi_unbind_adr_device(), which is called > > from acpi_bus_remove(). When a constructor interface is introduced, its > > destructor should be introduced as well. > > - Remove the binding procedure from acpi_pci_root_add(). This should > > be done in patch [2/6]. > > i think we should put jiang four patches before Rafael's patches. > > http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=shortlog;h=refs/heads/for-pci-jiang-hotplug Actually, I have something more radical than that in mind. :-) Namely, we don't need to call the wakeup-related stuff from acpi_pci_bind() and acpi_pci_unbind(). It's only there, because I did't find a better place for it when I added it. If we can set the ACPI handles of PCI devices in pci_scan_device(), which isn't too difficult to do (I actually have a patch for that and it's not too invasive), we can easily move the wakeup enabling stuff to pci_pm_init() and wakeup disabling somewhere near pci_release_capabilities(). Then we are only left with the _PRT setup in there, but that could be done as soon as in pci_scan_device() too, if I'm not mistaken. Thanks, Rafael -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-18 22:05 ` Rafael J. Wysocki @ 2012-12-19 1:57 ` Yinghai Lu 0 siblings, 0 replies; 88+ messages in thread From: Yinghai Lu @ 2012-12-19 1:57 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Toshi Kani, ACPI Devel Maling List, Bjorn Helgaas, LKML, linux-pci, Myron Stowe, Yijing Wang, Jiang Liu On Tue, Dec 18, 2012 at 2:05 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: >> >> i think we should put jiang four patches before Rafael's patches. >> >> http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=shortlog;h=refs/heads/for-pci-jiang-hotplug > > Actually, I have something more radical than that in mind. :-) > > Namely, we don't need to call the wakeup-related stuff from acpi_pci_bind() and > acpi_pci_unbind(). It's only there, because I did't find a better place for it > when I added it. > > If we can set the ACPI handles of PCI devices in pci_scan_device(), which isn't > too difficult to do (I actually have a patch for that and it's not too invasive), > we can easily move the wakeup enabling stuff to pci_pm_init() and wakeup > disabling somewhere near pci_release_capabilities(). good, let's see how acpi handles could be be passed to pci devices. Yinghai ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-18 16:10 ` Toshi Kani 2012-12-18 18:59 ` Yinghai Lu @ 2012-12-18 21:57 ` Rafael J. Wysocki 2012-12-18 22:15 ` Toshi Kani 1 sibling, 1 reply; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-18 21:57 UTC (permalink / raw) To: Toshi Kani Cc: ACPI Devel Maling List, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu On Tuesday, December 18, 2012 09:10:41 AM Toshi Kani wrote: > On Tue, 2012-12-18 at 02:48 +0100, Rafael J. Wysocki wrote: > > On Monday, December 17, 2012 05:08:17 PM Toshi Kani wrote: > > > On Thu, 2012-12-13 at 23:17 +0100, Rafael J. Wysocki wrote: > > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > > > > > > > > > (snip) > > > > > > > struct acpi_device_ops { > > > > Index: linux/drivers/acpi/scan.c > > > > =================================================================== > > > > --- linux.orig/drivers/acpi/scan.c > > > > +++ linux/drivers/acpi/scan.c > > > > @@ -494,7 +494,8 @@ static int acpi_bus_match(struct device > > > > struct acpi_device *acpi_dev = to_acpi_device(dev); > > > > struct acpi_driver *acpi_drv = to_acpi_driver(drv); > > > > > > > > - return !acpi_match_device_ids(acpi_dev, acpi_drv->ids); > > > > + return acpi_dev->bus_ops.acpi_op_match > > > > + && !acpi_match_device_ids(acpi_dev, acpi_drv->ids); > > > > } > > > > > > > > static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) > > > > @@ -1418,6 +1419,17 @@ static int acpi_bus_remove(struct acpi_d > > > > return 0; > > > > } > > > > > > > > +/* > > > > + * acpi_hot_add_bind - Bind _ADR-based devices on hot-add. > > > > + * @device: ACPI device node to bind. > > > > + */ > > > > +static void acpi_hot_add_bind(struct acpi_device *device) > > > > +{ > > > > + if (device->flags.bus_address > > > > + && device->parent && device->parent->ops.bind) > > > > + device->parent->ops.bind(device); > > > > +} > > > > + > > > > static int acpi_add_single_object(struct acpi_device **child, > > > > acpi_handle handle, int type, > > > > unsigned long long sta, > > > > @@ -1490,13 +1502,8 @@ static int acpi_add_single_object(struct > > > > > > > > result = acpi_device_register(device); > > > > > > > > - /* > > > > - * Bind _ADR-Based Devices when hot add > > > > - */ > > > > - if (device->flags.bus_address) { > > > > - if (device->parent && device->parent->ops.bind) > > > > - device->parent->ops.bind(device); > > > > - } > > > > > > I think the original code above is hot-add only because ops.bind is not > > > set at boot since the acpi_pci driver has not been registered yet. It > > > seems that acpi_pci_bridge_scan() called from acpi_pci_root_add() takes > > > care of the binding. > > > > Ah, I see the problem. During boot the PCI root bridge driver is not present > > yet when all struct acpi_device "devices" are registered, so their parents' > > .bind() callbacks are all empty, so the code above has no effect. > > > > But say we're doing a PCI root bridge hotplug, in which case the driver is > > present, so acpi_pci_bind() will be executed both from acpi_pci_bridge_scan() > > and from here, won't it? > > Right. > > > > OK, this needs to be addressed. > > > > > This brings me a question for acpi_bus_probe_start() below... > > > > > > > > > > + if (device->bus_ops.acpi_op_match) > > > > + acpi_hot_add_bind(device); > > > > > > > > end: > > > > if (!result) { > > > > @@ -1522,6 +1529,7 @@ static void acpi_bus_add_power_resource( > > > > struct acpi_bus_ops ops = { > > > > .acpi_op_add = 1, > > > > .acpi_op_start = 1, > > > > + .acpi_op_match = 1, > > > > }; > > > > struct acpi_device *device = NULL; > > > > > > > > @@ -1574,9 +1582,9 @@ static acpi_status acpi_bus_check_add(ac > > > > void *context, void **return_value) > > > > { > > > > struct acpi_bus_ops *ops = context; > > > > + struct acpi_device *device = NULL; > > > > int type; > > > > unsigned long long sta; > > > > - struct acpi_device *device; > > > > acpi_status status; > > > > int result; > > > > > > > > @@ -1596,52 +1604,86 @@ static acpi_status acpi_bus_check_add(ac > > > > return AE_CTRL_DEPTH; > > > > } > > > > > > > > - /* > > > > - * We may already have an acpi_device from a previous enumeration. If > > > > - * so, we needn't add it again, but we may still have to start it. > > > > - */ > > > > - device = NULL; > > > > acpi_bus_get_device(handle, &device); > > > > if (ops->acpi_op_add && !device) { > > > > - acpi_add_single_object(&device, handle, type, sta, ops); > > > > - /* Is the device a known good platform device? */ > > > > - if (device > > > > - && !acpi_match_device_ids(device, acpi_platform_device_ids)) > > > > - acpi_create_platform_device(device); > > > > - } > > > > - > > > > - if (!device) > > > > - return AE_CTRL_DEPTH; > > > > + struct acpi_bus_ops add_ops = *ops; > > > > > > > > - if (ops->acpi_op_start && !(ops->acpi_op_add)) { > > > > - status = acpi_start_single_object(device); > > > > - if (ACPI_FAILURE(status)) > > > > + add_ops.acpi_op_match = 0; > > > > + acpi_add_single_object(&device, handle, type, sta, &add_ops); > > > > + if (!device) > > > > return AE_CTRL_DEPTH; > > > > + > > > > + device->bus_ops.acpi_op_match = 1; > > > > } > > > > > > > > if (!*return_value) > > > > *return_value = device; > > > > + > > > > return AE_OK; > > > > } > > > > > > > > +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl, > > > > + void *context, void **not_used) > > > > +{ > > > > + struct acpi_bus_ops *ops = context; > > > > + acpi_status status = AE_OK; > > > > + struct acpi_device *device; > > > > + unsigned long long sta_not_used; > > > > + int type_not_used; > > > > + > > > > + /* > > > > + * Ignore errors ignored by acpi_bus_check_add() to avoid terminating > > > > > > "ignore" seems duplicated. > > > > It is not. This is supposed to mean that the errors previously ignored by > > acpi_bus_check_add() should be ignored here as well. > > Oh, I see. Thanks for the clarification. > > > > > > + * namespace walks prematurely. > > > > + */ > > > > + if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used)) > > > > + return AE_OK; > > > > + > > > > + if (acpi_bus_get_device(handle, &device)) > > > > + return AE_CTRL_DEPTH; > > > > + > > > > + if (ops->acpi_op_add) { > > > > + if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { > > > > + /* This is a known good platform device. */ > > > > + acpi_create_platform_device(device); > > > > + } else { > > > > + int ret = device_attach(&device->dev); > > > > + acpi_hot_add_bind(device); > > > > > > Since acpi_pci_root_add() is called by device_attach(), I think this > > > acpi_hot_add_bind() calls .bind() of a device at boot since its .bind() > > > may be set. Is that correct? If so, how does it coordinate with the > > > bind procedure in acpi_pci_bridge_scan()? > > > > It actually doesn't. > > > > However, the $subject patch doesn't change this particular aspect of the > > original behavior, because with it applied the PCI root bridge driver is still > > not present when the device_attach() above is executed for all objects in the > > given namespace scope, so the .bind() callbacks should all be empty. In other > > words, it doesn't change the boot case. > > > > It also reproduces the original behavior in the hotplug case which may not be > > correct. Patch [2/6], however, kind of changes the boot case into the hotplug > > case and things start to get ugly. > > Yes, I was concerned with the behavior when patch [2/6] applied. It is > actually a good thing that this hotplug issue is now exposed in the boot > path. This means that boot and hot-add paths are consistent. So, we > just need to fix it. > > > > Well, what about calling acpi_hot_add_bind() from acpi_bus_check_add(), > > right after doing the acpi_add_single_object()? It would avoid calling > > acpi_pci_bind() twice for the same device during root bridge hotplug too, > > because in that case acpi_pci_root_add() will be called after all of these > > acpi_hot_add_bind() calls. At the same time if a single device is > > hot-added and its parent happens to have .bind() set, it will be run > > from acpi_bus_check_add(). > > I may be missing something here, but in case of root bridge hot-add, I > think acpi_pci_root_add() still calls .bind() after acpi_bus_check_add() > called it. So, it's called twice, isn't it? No, it isn't. The reason is that the .bind pointers of all devices below the root bridge are populated from within acpi_pci_root_add() and are NULL before it is called. Therefore they are NULL when acpi_bus_check_add() checks them. Of course, I'm referring to this patch: https://patchwork.kernel.org/patch/1889821/ After this and [2/6] (https://patchwork.kernel.org/patch/1884701/) have been applied, it is quite easy to verify that acpi_pci_bind() is called exactly once for each PCI device during boot (just add a debug printk to that function) and the same should happen during root bridge hotplug. > We need to decide which module is responsible for calling .bind(). I > think it should be the ACPI scan module, not the ACPI PCI root bridge > driver, because: > - bind() needs to be called when _ADR device is added. The ACPI scan > module can scan any devices, while the PCI root driver can only scan > when it is added. > - acpi_bus_remove() calls unbind() at hot-remove. The same module > should be responsible for both bind() and unbind() handling. > - It is cleaner to keep struct acpi_device_ops interface to be called > by the ACPI core. I agree with that. :-) Moreover, I don't think we need acpi_pci_bind() and acpi_pci_unbind() at all. > So, I would propose the following changes. > > - Move the acpi_hot_add_bind() call back to the original place after > the device_attach() call. > - Rename the name of acpi_hot_add_bind() to something like > acpi_bind_adr_device() since it is no longer hot-add only (and is > specific to _ADR devices). > - Create its pair function, acpi_unbind_adr_device(), which is called > from acpi_bus_remove(). When a constructor interface is introduced, its > destructor should be introduced as well. > - Remove the binding procedure from acpi_pci_root_add(). This should > be done in patch [2/6]. Well, what about moving the code from acpi_pci_bind()/acpi_pci_unbind() somewhere else and removing those things altogether? Rafael -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-18 21:57 ` Rafael J. Wysocki @ 2012-12-18 22:15 ` Toshi Kani 2012-12-18 23:00 ` Rafael J. Wysocki 0 siblings, 1 reply; 88+ messages in thread From: Toshi Kani @ 2012-12-18 22:15 UTC (permalink / raw) To: Rafael J. Wysocki Cc: ACPI Devel Maling List, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu On Tue, 2012-12-18 at 22:57 +0100, Rafael J. Wysocki wrote: > On Tuesday, December 18, 2012 09:10:41 AM Toshi Kani wrote: > > On Tue, 2012-12-18 at 02:48 +0100, Rafael J. Wysocki wrote: : > > We need to decide which module is responsible for calling .bind(). I > > think it should be the ACPI scan module, not the ACPI PCI root bridge > > driver, because: > > - bind() needs to be called when _ADR device is added. The ACPI scan > > module can scan any devices, while the PCI root driver can only scan > > when it is added. > > - acpi_bus_remove() calls unbind() at hot-remove. The same module > > should be responsible for both bind() and unbind() handling. > > - It is cleaner to keep struct acpi_device_ops interface to be called > > by the ACPI core. > > I agree with that. :-) > > Moreover, I don't think we need acpi_pci_bind() and acpi_pci_unbind() at all. > > > So, I would propose the following changes. > > > > - Move the acpi_hot_add_bind() call back to the original place after > > the device_attach() call. > > - Rename the name of acpi_hot_add_bind() to something like > > acpi_bind_adr_device() since it is no longer hot-add only (and is > > specific to _ADR devices). > > - Create its pair function, acpi_unbind_adr_device(), which is called > > from acpi_bus_remove(). When a constructor interface is introduced, its > > destructor should be introduced as well. > > - Remove the binding procedure from acpi_pci_root_add(). This should > > be done in patch [2/6]. > > Well, what about moving the code from acpi_pci_bind()/acpi_pci_unbind() > somewhere else and removing those things altogether? Sounds nice. It will be bonus point if you can do that. :-) Thanks, -Toshi ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-18 22:15 ` Toshi Kani @ 2012-12-18 23:00 ` Rafael J. Wysocki 2012-12-18 23:19 ` Bjorn Helgaas 0 siblings, 1 reply; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-18 23:00 UTC (permalink / raw) To: Toshi Kani Cc: ACPI Devel Maling List, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu On Tuesday, December 18, 2012 03:15:12 PM Toshi Kani wrote: > On Tue, 2012-12-18 at 22:57 +0100, Rafael J. Wysocki wrote: > > On Tuesday, December 18, 2012 09:10:41 AM Toshi Kani wrote: > > > On Tue, 2012-12-18 at 02:48 +0100, Rafael J. Wysocki wrote: > : > > > We need to decide which module is responsible for calling .bind(). I > > > think it should be the ACPI scan module, not the ACPI PCI root bridge > > > driver, because: > > > - bind() needs to be called when _ADR device is added. The ACPI scan > > > module can scan any devices, while the PCI root driver can only scan > > > when it is added. > > > - acpi_bus_remove() calls unbind() at hot-remove. The same module > > > should be responsible for both bind() and unbind() handling. > > > - It is cleaner to keep struct acpi_device_ops interface to be called > > > by the ACPI core. > > > > I agree with that. :-) > > > > Moreover, I don't think we need acpi_pci_bind() and acpi_pci_unbind() at all. > > > > > So, I would propose the following changes. > > > > > > - Move the acpi_hot_add_bind() call back to the original place after > > > the device_attach() call. > > > - Rename the name of acpi_hot_add_bind() to something like > > > acpi_bind_adr_device() since it is no longer hot-add only (and is > > > specific to _ADR devices). > > > - Create its pair function, acpi_unbind_adr_device(), which is called > > > from acpi_bus_remove(). When a constructor interface is introduced, its > > > destructor should be introduced as well. > > > - Remove the binding procedure from acpi_pci_root_add(). This should > > > be done in patch [2/6]. > > > > Well, what about moving the code from acpi_pci_bind()/acpi_pci_unbind() > > somewhere else and removing those things altogether? > > Sounds nice. It will be bonus point if you can do that. :-) I think I can, but I need a few more patches on top of what I've already posted to do that. I think that https://patchwork.kernel.org/patch/1889821/ and https://patchwork.kernel.org/patch/1884701/ can stay as they are, since there's some material on top of them already and I'll cut the new patches on top of all that. I'll repost the whole series some time later this week, stay tuned. :-) Thanks, Rafael -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-18 23:00 ` Rafael J. Wysocki @ 2012-12-18 23:19 ` Bjorn Helgaas 2012-12-19 11:13 ` Rafael J. Wysocki 0 siblings, 1 reply; 88+ messages in thread From: Bjorn Helgaas @ 2012-12-18 23:19 UTC (permalink / raw) To: Rafael J. Wysocki Cc: Toshi Kani, ACPI Devel Maling List, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu On Tue, Dec 18, 2012 at 4:00 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > On Tuesday, December 18, 2012 03:15:12 PM Toshi Kani wrote: >> On Tue, 2012-12-18 at 22:57 +0100, Rafael J. Wysocki wrote: >> > On Tuesday, December 18, 2012 09:10:41 AM Toshi Kani wrote: >> > > On Tue, 2012-12-18 at 02:48 +0100, Rafael J. Wysocki wrote: >> : >> > > We need to decide which module is responsible for calling .bind(). I >> > > think it should be the ACPI scan module, not the ACPI PCI root bridge >> > > driver, because: >> > > - bind() needs to be called when _ADR device is added. The ACPI scan >> > > module can scan any devices, while the PCI root driver can only scan >> > > when it is added. >> > > - acpi_bus_remove() calls unbind() at hot-remove. The same module >> > > should be responsible for both bind() and unbind() handling. >> > > - It is cleaner to keep struct acpi_device_ops interface to be called >> > > by the ACPI core. >> > >> > I agree with that. :-) >> > >> > Moreover, I don't think we need acpi_pci_bind() and acpi_pci_unbind() at all. >> > >> > > So, I would propose the following changes. >> > > >> > > - Move the acpi_hot_add_bind() call back to the original place after >> > > the device_attach() call. >> > > - Rename the name of acpi_hot_add_bind() to something like >> > > acpi_bind_adr_device() since it is no longer hot-add only (and is >> > > specific to _ADR devices). >> > > - Create its pair function, acpi_unbind_adr_device(), which is called >> > > from acpi_bus_remove(). When a constructor interface is introduced, its >> > > destructor should be introduced as well. >> > > - Remove the binding procedure from acpi_pci_root_add(). This should >> > > be done in patch [2/6]. >> > >> > Well, what about moving the code from acpi_pci_bind()/acpi_pci_unbind() >> > somewhere else and removing those things altogether? >> >> Sounds nice. It will be bonus point if you can do that. :-) > > I think I can, but I need a few more patches on top of what I've already posted > to do that. > > I think that https://patchwork.kernel.org/patch/1889821/ and > https://patchwork.kernel.org/patch/1884701/ can stay as they are, since there's > some material on top of them already and I'll cut the new patches on top of all > that. I'll repost the whole series some time later this week, stay tuned. :-) I haven't follow this closely enough to give useful feedback, but I trust that what you're doing is going in the right direction. The only question I have right now is what I mentioned earlier on IRC, namely, the idea of "binding" an ACPI handle or device to a pci_dev, and whether there's a way to guarantee that the binding doesn't become stale. For example, if we bind pci_dev A to acpi_device B, I think we essentially capture the pointer to B and store that pointer in A. Obviously we want to know that the captured pointer in A remains valid as long as A exists, but I don't know what assures us of that. I don't think this is a new question; I have the same question about the current code before your changes. But it seems like you're simplifying this area in a way that might make it easier to answer the question. Bjorn ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-18 23:19 ` Bjorn Helgaas @ 2012-12-19 11:13 ` Rafael J. Wysocki 0 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-19 11:13 UTC (permalink / raw) To: Bjorn Helgaas Cc: Toshi Kani, ACPI Devel Maling List, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu On Tuesday, December 18, 2012 04:19:55 PM Bjorn Helgaas wrote: > On Tue, Dec 18, 2012 at 4:00 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > > On Tuesday, December 18, 2012 03:15:12 PM Toshi Kani wrote: > >> On Tue, 2012-12-18 at 22:57 +0100, Rafael J. Wysocki wrote: > >> > On Tuesday, December 18, 2012 09:10:41 AM Toshi Kani wrote: > >> > > On Tue, 2012-12-18 at 02:48 +0100, Rafael J. Wysocki wrote: > >> : > >> > > We need to decide which module is responsible for calling .bind(). I > >> > > think it should be the ACPI scan module, not the ACPI PCI root bridge > >> > > driver, because: > >> > > - bind() needs to be called when _ADR device is added. The ACPI scan > >> > > module can scan any devices, while the PCI root driver can only scan > >> > > when it is added. > >> > > - acpi_bus_remove() calls unbind() at hot-remove. The same module > >> > > should be responsible for both bind() and unbind() handling. > >> > > - It is cleaner to keep struct acpi_device_ops interface to be called > >> > > by the ACPI core. > >> > > >> > I agree with that. :-) > >> > > >> > Moreover, I don't think we need acpi_pci_bind() and acpi_pci_unbind() at all. > >> > > >> > > So, I would propose the following changes. > >> > > > >> > > - Move the acpi_hot_add_bind() call back to the original place after > >> > > the device_attach() call. > >> > > - Rename the name of acpi_hot_add_bind() to something like > >> > > acpi_bind_adr_device() since it is no longer hot-add only (and is > >> > > specific to _ADR devices). > >> > > - Create its pair function, acpi_unbind_adr_device(), which is called > >> > > from acpi_bus_remove(). When a constructor interface is introduced, its > >> > > destructor should be introduced as well. > >> > > - Remove the binding procedure from acpi_pci_root_add(). This should > >> > > be done in patch [2/6]. > >> > > >> > Well, what about moving the code from acpi_pci_bind()/acpi_pci_unbind() > >> > somewhere else and removing those things altogether? > >> > >> Sounds nice. It will be bonus point if you can do that. :-) > > > > I think I can, but I need a few more patches on top of what I've already posted > > to do that. > > > > I think that https://patchwork.kernel.org/patch/1889821/ and > > https://patchwork.kernel.org/patch/1884701/ can stay as they are, since there's > > some material on top of them already and I'll cut the new patches on top of all > > that. I'll repost the whole series some time later this week, stay tuned. :-) > > I haven't follow this closely enough to give useful feedback, but I > trust that what you're doing is going in the right direction. Cool. :-) > The only question I have right now is what I mentioned earlier on IRC, > namely, the idea of "binding" an ACPI handle or device to a pci_dev, > and whether there's a way to guarantee that the binding doesn't become > stale. For example, if we bind pci_dev A to acpi_device B, I think we > essentially capture the pointer to B and store that pointer in A. > Obviously we want to know that the captured pointer in A remains valid > as long as A exists, but I don't know what assures us of that. This really is a bit more complicated. First, what we store in A is not a pointer to B, but rather the corresponding ACPICA handle, which is guaranteed to live longer that B itself. Second, we not only store the B's handle in A, but also a pointer to A in B (in the physical_node_list list). Moreover, we create the "firmware_node" sysfs file under A and a "physical_node" sysfs file under B. All of that becomes invalid when either A or B is removed without notice. For the removal of A we have acpi_platform_notify() that calls acpi_unbind_one() which kills all of that stuff, so as long as A is removed earlier than B, we have no problems. For the removal of B, however, we seem to assume that if the device is ejectable, there will be an ACPI driver bound to B (ie. the struct acpi_device) that will take care of the removal of the physical nodes associated with it before B itself is removed. At least that's my understanding of the current code. Moreover, I'm not sure if this assumption is universally satisfied. > I don't think this is a new question; I have the same question about > the current code before your changes. But it seems like you're > simplifying this area in a way that might make it easier to answer the > question. Well, my patches are not likely to make things worse in this area. :-) Anyway, I think we should make acpi_bus_scan(), or even acpi_bus_add() after my changes, mutually exclusive with acpi_bus_trim(), because that will ensure that we won't be removing ACPI device objects while setting them up (or the other way around). That would require us to redesign some ACPI drivers first, though, because they call acpi_bus_trim() in their initialization code paths (I don't really think they should be doing that). Moreover, I think we should make the ACPI core trigger the removal of all physical nodes (As) associated with the given ACPI node (B) after calling device_release_driver() in acpi_bus_remove(). That will ensure that all physical nodes are gone along with all the binding-related stuff (thanks to acpi_platform_notify()) before the ACPI node is removed. Thanks, Rafael -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices 2012-12-18 1:48 ` Rafael J. Wysocki 2012-12-18 16:10 ` Toshi Kani @ 2012-12-20 1:45 ` Rafael J. Wysocki 2012-12-20 1:47 ` [PATCH 1/16] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki ` (16 more replies) 1 sibling, 17 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-20 1:45 UTC (permalink / raw) To: ACPI Devel Maling List Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu Hi all, I've finally cut the patches removing acpi_pci_bind() and acpi_pci_unbind(), so I'm kind of ready to post the entire series reworking the ACPI namespace scanning code. Patches [1-6/16] are essentially these ones: https://patchwork.kernel.org/patch/1889821/ https://patchwork.kernel.org/patch/1876481/ https://patchwork.kernel.org/patch/1876531/ https://patchwork.kernel.org/patch/1876571/ https://patchwork.kernel.org/patch/1876511/ https://patchwork.kernel.org/patch/1876401/ but [2-6/16] have been rebased on top of the first one. Patches [7-12/16] are essentially these: https://patchwork.kernel.org/patch/1884721/ https://patchwork.kernel.org/patch/1884701/ https://patchwork.kernel.org/patch/1884761/ https://patchwork.kernel.org/patch/1884731/ https://patchwork.kernel.org/patch/1884751/ https://patchwork.kernel.org/patch/1884661/ but they have been rebased on top of https://patchwork.kernel.org/patch/1889821/. I added Yinghai's ACKs to them tentatively, although they are a bit different from the previous versions. The difference is not too important, however, because the following patches finally remove the acpi_pci_bind()/acpi_pci_unbind() stuff: [13/16] Add .setup() and .cleanup() callbacks to struct acpi_bus_type. [14/16] Rework the setup and cleanup of ACPI/PCI device wakeup. [15/16] Move the _PRT setup and cleanup code to pci-acpi.c. [16/16] Drop ACPI device .bind() and .unbind() callbacks. This is done a bit differently than I thought it would be, mostly because the _PRT-related operations require the "subordinate" pointers of bridges to be populated. I think it may be possible to simplify this further if that requirement can be removed (I haven't looked into that). In fact, patches [13-15/16] do not essentially depend on [1-12/16], only the last one does. The patches are on top of my master branch and I'm going to rebase them when v3.8-rc1 is out. There is a git tree you can pull them from at: http://git.kernel.org/?p=linux/kernel/git/rafael/linux-pm.git;a=summary acpi-scan-temp-new It's v3.7 with my master branch merged and the new patches on top. Thanks, Rafael -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH 1/16] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-20 1:45 ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki @ 2012-12-20 1:47 ` Rafael J. Wysocki 2013-01-11 20:00 ` Mika Westerberg 2012-12-20 1:48 ` [PATCH 2/16] ACPI: Change the ordering of PCI root bridge driver registrarion Rafael J. Wysocki ` (15 subsequent siblings) 16 siblings, 1 reply; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-20 1:47 UTC (permalink / raw) To: ACPI Devel Maling List Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Split the ACPI namespace scanning for devices into two passes, such that struct acpi_device objects are registerd in the first pass without probing ACPI drivers and the drivers are probed against them directly in the second pass. There are two main reasons for doing that. First, the ACPI PCI root bridge driver's .add() routine, acpi_pci_root_add(), causes struct pci_dev objects to be created for all PCI devices under the given root bridge. Usually, there are corresponding ACPI device nodes in the ACPI namespace for some of those devices and therefore there should be "companion" struct acpi_device objects to attach those struct pci_dev objects to. These struct acpi_device objects should exist when the corresponding struct pci_dev objects are created, but that is only guaranteed during boot and not during hotplug. This leads to a number of functional differences between the boot and the hotplug cases which are not strictly necessary and make the code more complicated. For example, this forces the ACPI PCI root bridge driver to defer the registration of the just created struct pci_dev objects and to use a special .start() callback routine, acpi_pci_root_start(), to make sure that all of the "companion" struct acpi_device objects will be present at PCI devices registration time during hotplug. If those differences can be eliminated, we will be able to consolidate the boot and hotplug code paths for the enumeration and registration of PCI devices and to reduce the complexity of that code quite a bit. The second reason is that, in general, it should be possible to resolve conflicts of resources assigned by the BIOS to different devices represented by ACPI namespace nodes before any drivers bind to them and before they are attached to "companion" objects representing physical devices (such as struct pci_dev). However, for this purpose we first need to enumerate all ACPI device nodes in the given namespace scope. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Yinghai Lu <yinghai@kernel.org> --- drivers/acpi/scan.c | 103 +++++++++++++++++++++++++++++++++--------------- include/acpi/acpi_bus.h | 1 2 files changed, 73 insertions(+), 31 deletions(-) Index: linux/include/acpi/acpi_bus.h =================================================================== --- linux.orig/include/acpi/acpi_bus.h +++ linux/include/acpi/acpi_bus.h @@ -98,6 +98,7 @@ typedef void (*acpi_op_notify) (struct a struct acpi_bus_ops { u32 acpi_op_add:1; u32 acpi_op_start:1; + u32 acpi_op_match:1; }; struct acpi_device_ops { Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -494,7 +494,8 @@ static int acpi_bus_match(struct device struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_driver *acpi_drv = to_acpi_driver(drv); - return !acpi_match_device_ids(acpi_dev, acpi_drv->ids); + return acpi_dev->bus_ops.acpi_op_match + && !acpi_match_device_ids(acpi_dev, acpi_drv->ids); } static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) @@ -1418,6 +1419,17 @@ static int acpi_bus_remove(struct acpi_d return 0; } +/* + * acpi_hot_add_bind - Bind _ADR-based devices on hot-add. + * @device: ACPI device node to bind. + */ +static void acpi_hot_add_bind(struct acpi_device *device) +{ + if (device->flags.bus_address + && device->parent && device->parent->ops.bind) + device->parent->ops.bind(device); +} + static int acpi_add_single_object(struct acpi_device **child, acpi_handle handle, int type, unsigned long long sta, @@ -1490,13 +1502,8 @@ static int acpi_add_single_object(struct result = acpi_device_register(device); - /* - * Bind _ADR-Based Devices when hot add - */ - if (device->flags.bus_address) { - if (device->parent && device->parent->ops.bind) - device->parent->ops.bind(device); - } + if (device->bus_ops.acpi_op_match) + acpi_hot_add_bind(device); end: if (!result) { @@ -1522,6 +1529,7 @@ static void acpi_bus_add_power_resource( struct acpi_bus_ops ops = { .acpi_op_add = 1, .acpi_op_start = 1, + .acpi_op_match = 1, }; struct acpi_device *device = NULL; @@ -1574,9 +1582,9 @@ static acpi_status acpi_bus_check_add(ac void *context, void **return_value) { struct acpi_bus_ops *ops = context; + struct acpi_device *device = NULL; int type; unsigned long long sta; - struct acpi_device *device; acpi_status status; int result; @@ -1596,52 +1604,84 @@ static acpi_status acpi_bus_check_add(ac return AE_CTRL_DEPTH; } - /* - * We may already have an acpi_device from a previous enumeration. If - * so, we needn't add it again, but we may still have to start it. - */ - device = NULL; acpi_bus_get_device(handle, &device); if (ops->acpi_op_add && !device) { - acpi_add_single_object(&device, handle, type, sta, ops); - /* Is the device a known good platform device? */ - if (device - && !acpi_match_device_ids(device, acpi_platform_device_ids)) - acpi_create_platform_device(device); - } - - if (!device) - return AE_CTRL_DEPTH; + struct acpi_bus_ops add_ops = *ops; - if (ops->acpi_op_start && !(ops->acpi_op_add)) { - status = acpi_start_single_object(device); - if (ACPI_FAILURE(status)) + add_ops.acpi_op_match = 0; + acpi_add_single_object(&device, handle, type, sta, &add_ops); + if (!device) return AE_CTRL_DEPTH; + + device->bus_ops.acpi_op_match = 1; + acpi_hot_add_bind(device); } if (!*return_value) *return_value = device; + return AE_OK; } +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl, + void *context, void **not_used) +{ + struct acpi_bus_ops *ops = context; + acpi_status status = AE_OK; + struct acpi_device *device; + unsigned long long sta_not_used; + int type_not_used; + + /* + * Ignore errors ignored by acpi_bus_check_add() to avoid terminating + * namespace walks prematurely. + */ + if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used)) + return AE_OK; + + if (acpi_bus_get_device(handle, &device)) + return AE_CTRL_DEPTH; + + if (ops->acpi_op_add) { + if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { + /* This is a known good platform device. */ + acpi_create_platform_device(device); + } else if (device_attach(&device->dev)) { + status = AE_CTRL_DEPTH; + } + } else if (ops->acpi_op_start) { + if (ACPI_FAILURE(acpi_start_single_object(device))) + status = AE_CTRL_DEPTH; + } + return status; +} + static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops, struct acpi_device **child) { - acpi_status status; void *device = NULL; + acpi_status status; + int ret = -ENODEV; status = acpi_bus_check_add(handle, 0, ops, &device); if (ACPI_SUCCESS(status)) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, acpi_bus_check_add, NULL, ops, &device); + if (!device) + goto out; + + ret = 0; + status = acpi_bus_probe_start(handle, 0, ops, NULL); + if (ACPI_SUCCESS(status)) + acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, + acpi_bus_probe_start, NULL, ops, NULL); + + out: if (child) *child = device; - if (device) - return 0; - else - return -ENODEV; + return ret; } /* @@ -1752,6 +1792,7 @@ static int acpi_bus_scan_fixed(void) memset(&ops, 0, sizeof(ops)); ops.acpi_op_add = 1; ops.acpi_op_start = 1; + ops.acpi_op_match = 1; /* * Enumerate all fixed-feature devices. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 1/16] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2012-12-20 1:47 ` [PATCH 1/16] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki @ 2013-01-11 20:00 ` Mika Westerberg 2013-01-11 20:31 ` Rafael J. Wysocki 0 siblings, 1 reply; 88+ messages in thread From: Mika Westerberg @ 2013-01-11 20:00 UTC (permalink / raw) To: Rafael J. Wysocki Cc: ACPI Devel Maling List, Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu (Sorry to jump in late but I noticed one problem with this series while testing). On Thu, Dec 20, 2012 at 02:47:47AM +0100, Rafael J. Wysocki wrote: > +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl, > + void *context, void **not_used) > +{ > + struct acpi_bus_ops *ops = context; > + acpi_status status = AE_OK; > + struct acpi_device *device; > + unsigned long long sta_not_used; > + int type_not_used; > + > + /* > + * Ignore errors ignored by acpi_bus_check_add() to avoid terminating > + * namespace walks prematurely. > + */ > + if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used)) > + return AE_OK; > + > + if (acpi_bus_get_device(handle, &device)) > + return AE_CTRL_DEPTH; > + > + if (ops->acpi_op_add) { > + if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { > + /* This is a known good platform device. */ > + acpi_create_platform_device(device); > + } else if (device_attach(&device->dev)) { device_attach() returns 1 if it succeeds to attach device to a driver. In that case we should continue and not return AE_CTRL_DEPTH, right? > + status = AE_CTRL_DEPTH; > + } > + } else if (ops->acpi_op_start) { > + if (ACPI_FAILURE(acpi_start_single_object(device))) > + status = AE_CTRL_DEPTH; > + } > + return status; > +} ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 1/16] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2013-01-11 20:00 ` Mika Westerberg @ 2013-01-11 20:31 ` Rafael J. Wysocki 2013-01-11 20:37 ` Mika Westerberg 0 siblings, 1 reply; 88+ messages in thread From: Rafael J. Wysocki @ 2013-01-11 20:31 UTC (permalink / raw) To: Mika Westerberg Cc: ACPI Devel Maling List, Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu On Friday, January 11, 2013 10:00:46 PM Mika Westerberg wrote: > (Sorry to jump in late but I noticed one problem with this series while > testing). > > On Thu, Dec 20, 2012 at 02:47:47AM +0100, Rafael J. Wysocki wrote: > > +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl, > > + void *context, void **not_used) > > +{ > > + struct acpi_bus_ops *ops = context; > > + acpi_status status = AE_OK; > > + struct acpi_device *device; > > + unsigned long long sta_not_used; > > + int type_not_used; > > + > > + /* > > + * Ignore errors ignored by acpi_bus_check_add() to avoid terminating > > + * namespace walks prematurely. > > + */ > > + if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used)) > > + return AE_OK; > > + > > + if (acpi_bus_get_device(handle, &device)) > > + return AE_CTRL_DEPTH; > > + > > + if (ops->acpi_op_add) { > > + if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { > > + /* This is a known good platform device. */ > > + acpi_create_platform_device(device); > > + } else if (device_attach(&device->dev)) { > > device_attach() returns 1 if it succeeds to attach device to a driver. In > that case we should continue and not return AE_CTRL_DEPTH, right? That's correct. The check is reversed, so we need the appended patch on top of linux-pm.git/acpi-scan. Thanks, Rafael --- From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Subject: ACPI / scan: Fix check of device_attach() return value. Since device_attach() returns 1 on success and 0 on failure, the check against its return value in acpi_bus_device_attach() should be reveresed. Make it so. Reported-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> --- drivers/acpi/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) Index: linux-pm/drivers/acpi/scan.c =================================================================== --- linux-pm.orig/drivers/acpi/scan.c +++ linux-pm/drivers/acpi/scan.c @@ -1598,7 +1598,7 @@ static acpi_status acpi_bus_device_attac if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { /* This is a known good platform device. */ acpi_create_platform_device(device); - } else if (device_attach(&device->dev)) { + } else if (!device_attach(&device->dev)) { status = AE_CTRL_DEPTH; } return status; -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 1/16] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2013-01-11 20:31 ` Rafael J. Wysocki @ 2013-01-11 20:37 ` Mika Westerberg 2013-01-11 20:58 ` Rafael J. Wysocki 0 siblings, 1 reply; 88+ messages in thread From: Mika Westerberg @ 2013-01-11 20:37 UTC (permalink / raw) To: Rafael J. Wysocki Cc: ACPI Devel Maling List, Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu On Fri, Jan 11, 2013 at 09:31:43PM +0100, Rafael J. Wysocki wrote: > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > Subject: ACPI / scan: Fix check of device_attach() return value. > > Since device_attach() returns 1 on success and 0 on failure, > the check against its return value in acpi_bus_device_attach() > should be reveresed. Make it so. Not sure if it matters but it returns 0 if no device was bound to a driver and -ENODEV in case of error. If we only want to terminate in case of error, following might be better. } else if (device_attach(&device->dev) < 0) { ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 1/16] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2013-01-11 20:37 ` Mika Westerberg @ 2013-01-11 20:58 ` Rafael J. Wysocki 2013-01-11 20:59 ` Mika Westerberg 0 siblings, 1 reply; 88+ messages in thread From: Rafael J. Wysocki @ 2013-01-11 20:58 UTC (permalink / raw) To: Mika Westerberg Cc: ACPI Devel Maling List, Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu On Friday, January 11, 2013 10:37:59 PM Mika Westerberg wrote: > On Fri, Jan 11, 2013 at 09:31:43PM +0100, Rafael J. Wysocki wrote: > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > Subject: ACPI / scan: Fix check of device_attach() return value. > > > > Since device_attach() returns 1 on success and 0 on failure, > > the check against its return value in acpi_bus_device_attach() > > should be reveresed. Make it so. > > Not sure if it matters but it returns 0 if no device was bound to a driver > and -ENODEV in case of error. If we only want to terminate in case of > error, following might be better. > > } else if (device_attach(&device->dev) < 0) { Yes, this check will be better. Which means that the patch is actually yours, so I've just added the changelog. :-) Thanks, Rafael --- From: Mika Westerberg <mika.westerberg@linux.intel.com> Subject: ACPI / scan: Fix check of device_attach() return value. Since device_attach() returns 1 on success (a driver has been bound to the device), the check against its return value in acpi_bus_device_attach() should modified to take that into accout. Make it so. [rjw: Subject and changelog.] Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> --- drivers/acpi/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) Index: linux-pm/drivers/acpi/scan.c =================================================================== --- linux-pm.orig/drivers/acpi/scan.c +++ linux-pm/drivers/acpi/scan.c @@ -1598,7 +1598,7 @@ static acpi_status acpi_bus_device_attac if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { /* This is a known good platform device. */ acpi_create_platform_device(device); - } else if (device_attach(&device->dev)) { + } else if (device_attach(&device->dev) < 0) { status = AE_CTRL_DEPTH; } return status; ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 1/16] ACPI: Separate adding ACPI device objects from probing ACPI drivers 2013-01-11 20:58 ` Rafael J. Wysocki @ 2013-01-11 20:59 ` Mika Westerberg 0 siblings, 0 replies; 88+ messages in thread From: Mika Westerberg @ 2013-01-11 20:59 UTC (permalink / raw) To: Rafael J. Wysocki Cc: ACPI Devel Maling List, Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu On Fri, Jan 11, 2013 at 09:58:50PM +0100, Rafael J. Wysocki wrote: > On Friday, January 11, 2013 10:37:59 PM Mika Westerberg wrote: > > On Fri, Jan 11, 2013 at 09:31:43PM +0100, Rafael J. Wysocki wrote: > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > > Subject: ACPI / scan: Fix check of device_attach() return value. > > > > > > Since device_attach() returns 1 on success and 0 on failure, > > > the check against its return value in acpi_bus_device_attach() > > > should be reveresed. Make it so. > > > > Not sure if it matters but it returns 0 if no device was bound to a driver > > and -ENODEV in case of error. If we only want to terminate in case of > > error, following might be better. > > > > } else if (device_attach(&device->dev) < 0) { > > Yes, this check will be better. > > Which means that the patch is actually yours, so I've just added the changelog. :-) > Thanks! (and I've tested this, it works ;-)) ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH 2/16] ACPI: Change the ordering of PCI root bridge driver registrarion 2012-12-20 1:45 ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki 2012-12-20 1:47 ` [PATCH 1/16] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki @ 2012-12-20 1:48 ` Rafael J. Wysocki 2012-12-20 1:49 ` [PATCH 3/16] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different Rafael J. Wysocki ` (14 subsequent siblings) 16 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-20 1:48 UTC (permalink / raw) To: ACPI Devel Maling List Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Instead of running acpi_pci_root_init() from a separate subsys initcall, call it directly from acpi_scan_init() before scanning the ACPI namespace for the first time, so that the PCI root bridge driver's .add() routine, acpi_pci_root_start(), is always run before binding ACPI drivers or attaching "companion" device objects to struct acpi_device objects below the root bridge's device node in the ACPI namespace. The first, simpler reason for doing this is that it makes the situation during boot more similar to the situation during hotplug, in which the ACPI PCI root bridge driver is always present. The second reason is that acpi_pci_root_init() causes struct pci_dev objects to be created for all PCI devices below the bridge and these objects may be necessary for whatever is done with the other ACPI device nodes in that namespace scope. For example, devices created by acpi_create_platform_device() sometimes may need to be added to the device hierarchy as children of PCI bridges. For this purpose, however, the struct pci_dev objects representing those bridges need to exist before the platform devices in question are registered. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Yinghai Lu <yinghai@kernel.org> --- drivers/acpi/internal.h | 1 + drivers/acpi/pci_root.c | 4 +--- drivers/acpi/scan.c | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) Index: linux/drivers/acpi/internal.h =================================================================== --- linux.orig/drivers/acpi/internal.h +++ linux/drivers/acpi/internal.h @@ -67,6 +67,7 @@ struct acpi_ec { extern struct acpi_ec *first_ec; +int acpi_pci_root_init(void); int acpi_ec_init(void); int acpi_ec_ecdt_probe(void); int acpi_boot_ec_enable(void); Index: linux/drivers/acpi/pci_root.c =================================================================== --- linux.orig/drivers/acpi/pci_root.c +++ linux/drivers/acpi/pci_root.c @@ -674,7 +674,7 @@ static int acpi_pci_root_remove(struct a return 0; } -static int __init acpi_pci_root_init(void) +int __init acpi_pci_root_init(void) { acpi_hest_init(); @@ -687,5 +687,3 @@ static int __init acpi_pci_root_init(voi return 0; } - -subsys_initcall(acpi_pci_root_init); Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -1831,6 +1831,7 @@ int __init acpi_scan_init(void) } acpi_power_init(); + acpi_pci_root_init(); /* * Enumerate devices in the ACPI namespace. ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH 3/16] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different 2012-12-20 1:45 ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki 2012-12-20 1:47 ` [PATCH 1/16] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki 2012-12-20 1:48 ` [PATCH 2/16] ACPI: Change the ordering of PCI root bridge driver registrarion Rafael J. Wysocki @ 2012-12-20 1:49 ` Rafael J. Wysocki 2012-12-20 1:50 ` [PATCH 4/16] ACPI: Reduce the usage of struct acpi_bus_ops Rafael J. Wysocki ` (13 subsequent siblings) 16 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-20 1:49 UTC (permalink / raw) To: ACPI Devel Maling List Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> The current ACPI namespace scanning code suggests that acpi_bus_add() and acpi_bus_start() share some code. In fact, however, they are completely different code paths (except for the initial checks), so refactor the code to make that distinction visibly clear. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Yinghai Lu <yinghai@kernel.org> --- drivers/acpi/scan.c | 63 ++++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 28 deletions(-) Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -1623,10 +1623,9 @@ static acpi_status acpi_bus_check_add(ac return AE_OK; } -static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl, - void *context, void **not_used) +static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, + void *not_used, void **ret_not_used) { - struct acpi_bus_ops *ops = context; acpi_status status = AE_OK; struct acpi_device *device; unsigned long long sta_not_used; @@ -1642,16 +1641,11 @@ static acpi_status acpi_bus_probe_start( if (acpi_bus_get_device(handle, &device)) return AE_CTRL_DEPTH; - if (ops->acpi_op_add) { - if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { - /* This is a known good platform device. */ - acpi_create_platform_device(device); - } else if (device_attach(&device->dev)) { - status = AE_CTRL_DEPTH; - } - } else if (ops->acpi_op_start) { - if (ACPI_FAILURE(acpi_start_single_object(device))) - status = AE_CTRL_DEPTH; + if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { + /* This is a known good platform device. */ + acpi_create_platform_device(device); + } else if (device_attach(&device->dev)) { + status = AE_CTRL_DEPTH; } return status; } @@ -1672,10 +1666,10 @@ static int acpi_bus_scan(acpi_handle han goto out; ret = 0; - status = acpi_bus_probe_start(handle, 0, ops, NULL); + status = acpi_bus_device_attach(handle, 0, NULL, NULL); if (ACPI_SUCCESS(status)) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - acpi_bus_probe_start, NULL, ops, NULL); + acpi_bus_device_attach, NULL, NULL, NULL); out: if (child) @@ -1700,31 +1694,44 @@ int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent, acpi_handle handle, int type) { - struct acpi_bus_ops ops; - - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_add = 1; + struct acpi_bus_ops ops = { .acpi_op_add = 1, }; return acpi_bus_scan(handle, &ops, child); } EXPORT_SYMBOL(acpi_bus_add); -int acpi_bus_start(struct acpi_device *device) +static acpi_status acpi_bus_start_device(acpi_handle handle, u32 lvl, + void *not_used, void **ret_not_used) { - struct acpi_bus_ops ops; - int result; + struct acpi_device *device; + unsigned long long sta_not_used; + int type_not_used; + /* + * Ignore errors ignored by acpi_bus_check_add() to avoid terminating + * namespace walks prematurely. + */ + if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used)) + return AE_OK; + + if (acpi_bus_get_device(handle, &device)) + return AE_CTRL_DEPTH; + + return acpi_start_single_object(device); +} + +int acpi_bus_start(struct acpi_device *device) +{ if (!device) return -EINVAL; - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_start = 1; - - result = acpi_bus_scan(device->handle, &ops, NULL); + if (ACPI_SUCCESS(acpi_start_single_object(device))) + acpi_walk_namespace(ACPI_TYPE_ANY, device->handle, + ACPI_UINT32_MAX, acpi_bus_start_device, + NULL, NULL, NULL); acpi_update_all_gpes(); - - return result; + return 0; } EXPORT_SYMBOL(acpi_bus_start); ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH 4/16] ACPI: Reduce the usage of struct acpi_bus_ops 2012-12-20 1:45 ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki ` (2 preceding siblings ...) 2012-12-20 1:49 ` [PATCH 3/16] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different Rafael J. Wysocki @ 2012-12-20 1:50 ` Rafael J. Wysocki 2012-12-20 1:50 ` [PATCH 5/16] ACPI: Replace struct acpi_bus_ops with enum type Rafael J. Wysocki ` (12 subsequent siblings) 16 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-20 1:50 UTC (permalink / raw) To: ACPI Devel Maling List Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Objects of type struct acpi_bus_ops are currently used to pass information between different parts of the ACPI namespace scanning code, sometimes in quite convoluted ways. It turns out that that is not necessary in some cases, so simplify the code by reducing the utilization of struct acpi_bus_ops objects where clearly possible. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Yinghai Lu <yinghai@kernel.org> --- drivers/acpi/scan.c | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -1527,7 +1527,6 @@ end: static void acpi_bus_add_power_resource(acpi_handle handle) { struct acpi_bus_ops ops = { - .acpi_op_add = 1, .acpi_op_start = 1, .acpi_op_match = 1, }; @@ -1581,7 +1580,6 @@ static int acpi_bus_type_and_status(acpi static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl, void *context, void **return_value) { - struct acpi_bus_ops *ops = context; struct acpi_device *device = NULL; int type; unsigned long long sta; @@ -1605,11 +1603,13 @@ static acpi_status acpi_bus_check_add(ac } acpi_bus_get_device(handle, &device); - if (ops->acpi_op_add && !device) { - struct acpi_bus_ops add_ops = *ops; + if (!device) { + struct acpi_bus_ops ops = { + .acpi_op_start = !!context, + .acpi_op_match = 0, + }; - add_ops.acpi_op_match = 0; - acpi_add_single_object(&device, handle, type, sta, &add_ops); + acpi_add_single_object(&device, handle, type, sta, &ops); if (!device) return AE_CTRL_DEPTH; @@ -1650,17 +1650,18 @@ static acpi_status acpi_bus_device_attac return status; } -static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops, +static int acpi_bus_scan(acpi_handle handle, bool start, struct acpi_device **child) { void *device = NULL; acpi_status status; int ret = -ENODEV; - status = acpi_bus_check_add(handle, 0, ops, &device); + status = acpi_bus_check_add(handle, 0, (void *)start, &device); if (ACPI_SUCCESS(status)) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - acpi_bus_check_add, NULL, ops, &device); + acpi_bus_check_add, NULL, (void *)start, + &device); if (!device) goto out; @@ -1694,9 +1695,7 @@ int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent, acpi_handle handle, int type) { - struct acpi_bus_ops ops = { .acpi_op_add = 1, }; - - return acpi_bus_scan(handle, &ops, child); + return acpi_bus_scan(handle, false, child); } EXPORT_SYMBOL(acpi_bus_add); @@ -1794,12 +1793,10 @@ static int acpi_bus_scan_fixed(void) { int result = 0; struct acpi_device *device = NULL; - struct acpi_bus_ops ops; - - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_add = 1; - ops.acpi_op_start = 1; - ops.acpi_op_match = 1; + struct acpi_bus_ops ops = { + .acpi_op_start = 1, + .acpi_op_match = 1, + }; /* * Enumerate all fixed-feature devices. @@ -1825,11 +1822,6 @@ static int acpi_bus_scan_fixed(void) int __init acpi_scan_init(void) { int result; - struct acpi_bus_ops ops; - - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_add = 1; - ops.acpi_op_start = 1; result = bus_register(&acpi_bus_type); if (result) { @@ -1843,7 +1835,7 @@ int __init acpi_scan_init(void) /* * Enumerate devices in the ACPI namespace. */ - result = acpi_bus_scan(ACPI_ROOT_OBJECT, &ops, &acpi_root); + result = acpi_bus_scan(ACPI_ROOT_OBJECT, true, &acpi_root); if (!result) result = acpi_bus_scan_fixed(); ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH 5/16] ACPI: Replace struct acpi_bus_ops with enum type 2012-12-20 1:45 ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki ` (3 preceding siblings ...) 2012-12-20 1:50 ` [PATCH 4/16] ACPI: Reduce the usage of struct acpi_bus_ops Rafael J. Wysocki @ 2012-12-20 1:50 ` Rafael J. Wysocki 2012-12-20 1:51 ` [PATCH 6/16] ACPI: Change the ordering of acpi_bus_check_add() Rafael J. Wysocki ` (11 subsequent siblings) 16 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-20 1:50 UTC (permalink / raw) To: ACPI Devel Maling List Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Notice that one member of struct acpi_bus_ops, acpi_op_add, is not used anywhere any more and the relationship between its remaining members, acpi_op_match and acpi_op_start, is such that it doesn't make sense to set the latter without setting the former at the same time. Therefore, replace struct acpi_bus_ops with new a enum type, enum acpi_bus_add_type, with three values, ACPI_BUS_ADD_BASIC, ACPI_BUS_ADD_MATCH, ACPI_BUS_ADD_START, corresponding to both acpi_op_match and acpi_op_start unset, acpi_op_match set and acpi_op_start unset, and both acpi_op_match and acpi_op_start set, respectively. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Yinghai Lu <yinghai@kernel.org> --- drivers/acpi/scan.c | 35 ++++++++++++----------------------- include/acpi/acpi_bus.h | 15 ++++++++------- 2 files changed, 20 insertions(+), 30 deletions(-) Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -494,7 +494,7 @@ static int acpi_bus_match(struct device struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_driver *acpi_drv = to_acpi_driver(drv); - return acpi_dev->bus_ops.acpi_op_match + return acpi_dev->add_type >= ACPI_BUS_ADD_MATCH && !acpi_match_device_ids(acpi_dev, acpi_drv->ids); } @@ -580,7 +580,7 @@ static int acpi_device_probe(struct devi ret = acpi_bus_driver_init(acpi_dev, acpi_drv); if (!ret) { - if (acpi_dev->bus_ops.acpi_op_start) + if (acpi_dev->add_type == ACPI_BUS_ADD_START) acpi_start_single_object(acpi_dev); if (acpi_drv->ops.notify) { @@ -1433,7 +1433,7 @@ static void acpi_hot_add_bind(struct acp static int acpi_add_single_object(struct acpi_device **child, acpi_handle handle, int type, unsigned long long sta, - struct acpi_bus_ops *ops) + enum acpi_bus_add_type add_type) { int result; struct acpi_device *device; @@ -1449,7 +1449,7 @@ static int acpi_add_single_object(struct device->device_type = type; device->handle = handle; device->parent = acpi_bus_get_parent(handle); - device->bus_ops = *ops; /* workround for not call .start */ + device->add_type = add_type; STRUCT_TO_INT(device->status) = sta; acpi_device_get_busid(device); @@ -1502,7 +1502,7 @@ static int acpi_add_single_object(struct result = acpi_device_register(device); - if (device->bus_ops.acpi_op_match) + if (device->add_type >= ACPI_BUS_ADD_MATCH) acpi_hot_add_bind(device); end: @@ -1526,16 +1526,12 @@ end: static void acpi_bus_add_power_resource(acpi_handle handle) { - struct acpi_bus_ops ops = { - .acpi_op_start = 1, - .acpi_op_match = 1, - }; struct acpi_device *device = NULL; acpi_bus_get_device(handle, &device); if (!device) acpi_add_single_object(&device, handle, ACPI_BUS_TYPE_POWER, - ACPI_STA_DEFAULT, &ops); + ACPI_STA_DEFAULT, ACPI_BUS_ADD_START); } static int acpi_bus_type_and_status(acpi_handle handle, int *type, @@ -1604,16 +1600,13 @@ static acpi_status acpi_bus_check_add(ac acpi_bus_get_device(handle, &device); if (!device) { - struct acpi_bus_ops ops = { - .acpi_op_start = !!context, - .acpi_op_match = 0, - }; - - acpi_add_single_object(&device, handle, type, sta, &ops); + acpi_add_single_object(&device, handle, type, sta, + ACPI_BUS_ADD_BASIC); if (!device) return AE_CTRL_DEPTH; - device->bus_ops.acpi_op_match = 1; + device->add_type = context ? + ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH; acpi_hot_add_bind(device); } @@ -1793,10 +1786,6 @@ static int acpi_bus_scan_fixed(void) { int result = 0; struct acpi_device *device = NULL; - struct acpi_bus_ops ops = { - .acpi_op_start = 1, - .acpi_op_match = 1, - }; /* * Enumerate all fixed-feature devices. @@ -1805,7 +1794,7 @@ static int acpi_bus_scan_fixed(void) result = acpi_add_single_object(&device, NULL, ACPI_BUS_TYPE_POWER_BUTTON, ACPI_STA_DEFAULT, - &ops); + ACPI_BUS_ADD_START); device_init_wakeup(&device->dev, true); } @@ -1813,7 +1802,7 @@ static int acpi_bus_scan_fixed(void) result = acpi_add_single_object(&device, NULL, ACPI_BUS_TYPE_SLEEP_BUTTON, ACPI_STA_DEFAULT, - &ops); + ACPI_BUS_ADD_START); } return result; Index: linux/include/acpi/acpi_bus.h =================================================================== --- linux.orig/include/acpi/acpi_bus.h +++ linux/include/acpi/acpi_bus.h @@ -63,6 +63,13 @@ acpi_get_physical_device_location(acpi_h #define ACPI_BUS_FILE_ROOT "acpi" extern struct proc_dir_entry *acpi_root_dir; +enum acpi_bus_add_type { + ACPI_BUS_ADD_BASIC = 0, + ACPI_BUS_ADD_MATCH, + ACPI_BUS_ADD_START, + ACPI_BUS_ADD_TYPE_COUNT +}; + enum acpi_bus_removal_type { ACPI_BUS_REMOVAL_NORMAL = 0, ACPI_BUS_REMOVAL_EJECT, @@ -95,12 +102,6 @@ typedef int (*acpi_op_bind) (struct acpi typedef int (*acpi_op_unbind) (struct acpi_device * device); typedef void (*acpi_op_notify) (struct acpi_device * device, u32 event); -struct acpi_bus_ops { - u32 acpi_op_add:1; - u32 acpi_op_start:1; - u32 acpi_op_match:1; -}; - struct acpi_device_ops { acpi_op_add add; acpi_op_remove remove; @@ -284,7 +285,7 @@ struct acpi_device { struct acpi_driver *driver; void *driver_data; struct device dev; - struct acpi_bus_ops bus_ops; /* workaround for different code path for hotplug */ + enum acpi_bus_add_type add_type; /* how to handle adding */ enum acpi_bus_removal_type removal_type; /* indicate for different removal type */ u8 physical_node_count; struct list_head physical_node_list; ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH 6/16] ACPI: Change the ordering of acpi_bus_check_add() 2012-12-20 1:45 ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki ` (4 preceding siblings ...) 2012-12-20 1:50 ` [PATCH 5/16] ACPI: Replace struct acpi_bus_ops with enum type Rafael J. Wysocki @ 2012-12-20 1:51 ` Rafael J. Wysocki 2012-12-20 1:52 ` [PATCH 7/16] ACPI / PCI: Fold acpi_pci_root_start() into acpi_pci_root_add() Rafael J. Wysocki ` (10 subsequent siblings) 16 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-20 1:51 UTC (permalink / raw) To: ACPI Devel Maling List Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> If acpi_bus_check_add() is called for a handle already having an existing struct acpi_device object attached, it is not necessary to check the type and status of the device correspondig to it, so change the ordering of acpi_bus_check_add() to avoid that. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Yinghai Lu <yinghai@kernel.org> --- drivers/acpi/scan.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -1582,6 +1582,10 @@ static acpi_status acpi_bus_check_add(ac acpi_status status; int result; + acpi_bus_get_device(handle, &device); + if (device) + goto out; + result = acpi_bus_type_and_status(handle, &type, &sta); if (result) return AE_OK; @@ -1598,18 +1602,14 @@ static acpi_status acpi_bus_check_add(ac return AE_CTRL_DEPTH; } - acpi_bus_get_device(handle, &device); - if (!device) { - acpi_add_single_object(&device, handle, type, sta, - ACPI_BUS_ADD_BASIC); - if (!device) - return AE_CTRL_DEPTH; + acpi_add_single_object(&device, handle, type, sta, ACPI_BUS_ADD_BASIC); + if (!device) + return AE_CTRL_DEPTH; - device->add_type = context ? - ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH; - acpi_hot_add_bind(device); - } + device->add_type = context ? ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH; + acpi_hot_add_bind(device); + out: if (!*return_value) *return_value = device; ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH 7/16] ACPI / PCI: Fold acpi_pci_root_start() into acpi_pci_root_add() 2012-12-20 1:45 ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki ` (5 preceding siblings ...) 2012-12-20 1:51 ` [PATCH 6/16] ACPI: Change the ordering of acpi_bus_check_add() Rafael J. Wysocki @ 2012-12-20 1:52 ` Rafael J. Wysocki 2012-12-20 1:53 ` [PATCH 8/16] ACPI: Remove acpi_start_single_object() and acpi_bus_start() Rafael J. Wysocki ` (9 subsequent siblings) 16 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-20 1:52 UTC (permalink / raw) To: ACPI Devel Maling List Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Move the code from the ACPI PCI root bridge's .start() callback routine, acpi_pci_root_start(), directly into acpi_pci_root_add() and drop acpi_pci_root_start(). It is safe to do that, because it is now always guaranteed that when struct pci_dev objects are created, their companion struct acpi_device objects are already present, so it is not necessary to wait for them to be created before calling pci_bus_add_devices(). This change was previously proposed in a different form by Yinghai Lu. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Yinghai Lu <yinghai@kernel.org> --- drivers/acpi/pci_root.c | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) Index: linux/drivers/acpi/pci_root.c =================================================================== --- linux.orig/drivers/acpi/pci_root.c +++ linux/drivers/acpi/pci_root.c @@ -47,7 +47,6 @@ ACPI_MODULE_NAME("pci_root"); #define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge" static int acpi_pci_root_add(struct acpi_device *device); static int acpi_pci_root_remove(struct acpi_device *device, int type); -static int acpi_pci_root_start(struct acpi_device *device); #define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \ | OSC_ACTIVE_STATE_PWR_SUPPORT \ @@ -67,7 +66,6 @@ static struct acpi_driver acpi_pci_root_ .ops = { .add = acpi_pci_root_add, .remove = acpi_pci_root_remove, - .start = acpi_pci_root_start, }, }; @@ -453,6 +451,7 @@ static int __devinit acpi_pci_root_add(s struct acpi_pci_root *root; acpi_handle handle; struct acpi_device *child; + struct acpi_pci_driver *driver; u32 flags, base_flags; root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); @@ -628,6 +627,13 @@ static int __devinit acpi_pci_root_add(s if (device->wakeup.flags.run_wake) device_set_run_wake(root->bus->bridge, true); + mutex_lock(&acpi_pci_root_lock); + list_for_each_entry(driver, &acpi_pci_drivers, node) + if (driver->add) + driver->add(root); + mutex_unlock(&acpi_pci_root_lock); + + pci_bus_add_devices(root->bus); return 0; out_del_root: @@ -639,22 +645,6 @@ end: return result; } -static int acpi_pci_root_start(struct acpi_device *device) -{ - struct acpi_pci_root *root = acpi_driver_data(device); - struct acpi_pci_driver *driver; - - mutex_lock(&acpi_pci_root_lock); - list_for_each_entry(driver, &acpi_pci_drivers, node) - if (driver->add) - driver->add(root); - mutex_unlock(&acpi_pci_root_lock); - - pci_bus_add_devices(root->bus); - - return 0; -} - static int acpi_pci_root_remove(struct acpi_device *device, int type) { struct acpi_pci_root *root = acpi_driver_data(device); ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH 8/16] ACPI: Remove acpi_start_single_object() and acpi_bus_start() 2012-12-20 1:45 ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki ` (6 preceding siblings ...) 2012-12-20 1:52 ` [PATCH 7/16] ACPI / PCI: Fold acpi_pci_root_start() into acpi_pci_root_add() Rafael J. Wysocki @ 2012-12-20 1:53 ` Rafael J. Wysocki 2012-12-20 1:54 ` [PATCH 9/16] ACPI: Remove the arguments of acpi_bus_add() that are not used Rafael J. Wysocki ` (8 subsequent siblings) 16 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-20 1:53 UTC (permalink / raw) To: ACPI Devel Maling List Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> The ACPI PCI root bridge driver was the only ACPI driver implementing the .start() callback, which isn't used by any ACPI drivers any more now. For this reason, acpi_start_single_object() has no purpose any more, so remove it and all references to it. Also remove acpi_bus_start_device(), whose only purpose was to call acpi_start_single_object(). Moreover, since after the removal of acpi_bus_start_device() the only purpose of acpi_bus_start() remains to call acpi_update_all_gpes(), move that into acpi_bus_add() and drop acpi_bus_start() too, remove its header from acpi_bus.h and update all of its former users accordingly. This change was previously proposed in a different from by Yinghai Lu. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Yinghai Lu <yinghai@kernel.org> --- drivers/acpi/container.c | 16 +------- drivers/acpi/scan.c | 66 ++++--------------------------------- drivers/pci/hotplug/acpiphp_glue.c | 4 -- drivers/pci/hotplug/sgi_hotplug.c | 2 - include/acpi/acpi_bus.h | 1 5 files changed, 12 insertions(+), 77 deletions(-) Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -612,7 +612,6 @@ static void acpi_device_remove_notify_ha } static int acpi_bus_driver_init(struct acpi_device *, struct acpi_driver *); -static int acpi_start_single_object(struct acpi_device *); static int acpi_device_probe(struct device * dev) { struct acpi_device *acpi_dev = to_acpi_device(dev); @@ -621,9 +620,6 @@ static int acpi_device_probe(struct devi ret = acpi_bus_driver_init(acpi_dev, acpi_drv); if (!ret) { - if (acpi_dev->add_type == ACPI_BUS_ADD_START) - acpi_start_single_object(acpi_dev); - if (acpi_drv->ops.notify) { ret = acpi_device_install_notify_handler(acpi_dev); if (ret) { @@ -802,24 +798,6 @@ acpi_bus_driver_init(struct acpi_device return 0; } -static int acpi_start_single_object(struct acpi_device *device) -{ - int result = 0; - struct acpi_driver *driver; - - - if (!(driver = device->driver)) - return 0; - - if (driver->ops.start) { - result = driver->ops.start(device); - if (result && driver->ops.remove) - driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL); - } - - return result; -} - /** * acpi_bus_register_driver - register a driver with the ACPI bus * @driver: driver being registered @@ -1714,59 +1692,31 @@ static int acpi_bus_scan(acpi_handle han } /* - * acpi_bus_add and acpi_bus_start + * acpi_bus_add * * scan a given ACPI tree and (probably recently hot-plugged) - * create and add or starts found devices. + * create and add found devices. * * If no devices were found -ENODEV is returned which does not * mean that this is a real error, there just have been no suitable * ACPI objects in the table trunk from which the kernel could create - * a device and add/start an appropriate driver. + * a device and add an appropriate driver. */ int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent, acpi_handle handle, int type) { - return acpi_bus_scan(handle, false, child); -} -EXPORT_SYMBOL(acpi_bus_add); - -static acpi_status acpi_bus_start_device(acpi_handle handle, u32 lvl, - void *not_used, void **ret_not_used) -{ - struct acpi_device *device; - unsigned long long sta_not_used; - int type_not_used; - - /* - * Ignore errors ignored by acpi_bus_check_add() to avoid terminating - * namespace walks prematurely. - */ - if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used)) - return AE_OK; - - if (acpi_bus_get_device(handle, &device)) - return AE_CTRL_DEPTH; - - return acpi_start_single_object(device); -} - -int acpi_bus_start(struct acpi_device *device) -{ - if (!device) - return -EINVAL; + int err; - if (ACPI_SUCCESS(acpi_start_single_object(device))) - acpi_walk_namespace(ACPI_TYPE_ANY, device->handle, - ACPI_UINT32_MAX, acpi_bus_start_device, - NULL, NULL, NULL); + err = acpi_bus_scan(handle, false, child); + if (err) + return err; acpi_update_all_gpes(); return 0; } -EXPORT_SYMBOL(acpi_bus_start); +EXPORT_SYMBOL(acpi_bus_add); int acpi_bus_trim(struct acpi_device *start, int rmdevice) { Index: linux/include/acpi/acpi_bus.h =================================================================== --- linux.orig/include/acpi/acpi_bus.h +++ linux/include/acpi/acpi_bus.h @@ -402,7 +402,6 @@ int acpi_bus_add(struct acpi_device **ch acpi_handle handle, int type); void acpi_bus_hot_remove_device(void *context); int acpi_bus_trim(struct acpi_device *start, int rmdevice); -int acpi_bus_start(struct acpi_device *device); acpi_status acpi_bus_get_ejd(acpi_handle handle, acpi_handle * ejd); int acpi_match_device_ids(struct acpi_device *device, const struct acpi_device_id *ids); Index: linux/drivers/pci/hotplug/sgi_hotplug.c =================================================================== --- linux.orig/drivers/pci/hotplug/sgi_hotplug.c +++ linux/drivers/pci/hotplug/sgi_hotplug.c @@ -457,8 +457,6 @@ static int enable_slot(struct hotplug_sl ret, (int)(adr>>16), (int)(adr&0xffff)); /* try to continue on */ - } else { - acpi_bus_start(device); } } } Index: linux/drivers/pci/hotplug/acpiphp_glue.c =================================================================== --- linux.orig/drivers/pci/hotplug/acpiphp_glue.c +++ linux/drivers/pci/hotplug/acpiphp_glue.c @@ -759,7 +759,6 @@ static int acpiphp_bus_add(struct acpiph -ret_val); goto acpiphp_bus_add_out; } - ret_val = acpi_bus_start(device); acpiphp_bus_add_out: return ret_val; @@ -1148,8 +1147,7 @@ static void handle_bridge_insertion(acpi err("cannot add bridge to acpi list\n"); return; } - if (!acpiphp_configure_bridge(handle) && - !acpi_bus_start(device)) + if (!acpiphp_configure_bridge(handle)) add_bridge(handle); else err("cannot configure and start bridge\n"); Index: linux/drivers/acpi/container.c =================================================================== --- linux.orig/drivers/acpi/container.c +++ linux/drivers/acpi/container.c @@ -139,24 +139,14 @@ static int container_device_add(struct a { acpi_handle phandle; struct acpi_device *pdev; - int result; - - if (acpi_get_parent(handle, &phandle)) { - return -ENODEV; - } - - if (acpi_bus_get_device(phandle, &pdev)) { + if (acpi_get_parent(handle, &phandle)) return -ENODEV; - } - if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_DEVICE)) { + if (acpi_bus_get_device(phandle, &pdev)) return -ENODEV; - } - - result = acpi_bus_start(*device); - return result; + return acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_DEVICE); } static void container_notify_cb(acpi_handle handle, u32 type, void *context) ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH 9/16] ACPI: Remove the arguments of acpi_bus_add() that are not used 2012-12-20 1:45 ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki ` (7 preceding siblings ...) 2012-12-20 1:53 ` [PATCH 8/16] ACPI: Remove acpi_start_single_object() and acpi_bus_start() Rafael J. Wysocki @ 2012-12-20 1:54 ` Rafael J. Wysocki 2012-12-20 1:54 ` [PATCH 10/16] ACPI: Drop the second argument of acpi_bus_scan() Rafael J. Wysocki ` (7 subsequent siblings) 16 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-20 1:54 UTC (permalink / raw) To: ACPI Devel Maling List Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Notice that acpi_bus_add() uses only 2 of its 4 arguments and redefine its header to match the body. Update all of its callers as necessary and observe that this leads to quite a number of removed lines of code (Linus will like that). Add a kerneldoc comment documenting acpi_bus_add() and wonder how its callers make wrong assumptions about the second argument (make note to self to take care of that later). Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Yinghai Lu <yinghai@kernel.org> --- drivers/acpi/acpi_memhotplug.c | 19 +------------------ drivers/acpi/container.c | 16 +--------------- drivers/acpi/dock.c | 13 ++----------- drivers/acpi/processor_driver.c | 24 +----------------------- drivers/acpi/scan.c | 34 +++++++++++++++++++++------------- drivers/pci/hotplug/acpiphp_glue.c | 21 ++++----------------- drivers/pci/hotplug/sgi_hotplug.c | 3 +-- include/acpi/acpi_bus.h | 3 +-- 8 files changed, 32 insertions(+), 101 deletions(-) Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -1691,25 +1691,33 @@ static int acpi_bus_scan(acpi_handle han return ret; } -/* - * acpi_bus_add +/** + * acpi_bus_add - Add ACPI device node objects in a given namespace scope. + * @handle: Root of the namespace scope to scan. + * @ret: Location to store a return struct acpi_device pointer. * - * scan a given ACPI tree and (probably recently hot-plugged) - * create and add found devices. + * Scan a given ACPI tree (probably recently hot-plugged) and create and add + * found devices. * - * If no devices were found -ENODEV is returned which does not - * mean that this is a real error, there just have been no suitable - * ACPI objects in the table trunk from which the kernel could create - * a device and add an appropriate driver. + * If no devices were found, -ENODEV is returned, but it does not mean that + * there has been a real error. There just have been no suitable ACPI objects + * in the table trunk from which the kernel could create a device and add an + * appropriate driver. + * + * If 0 is returned, the memory location pointed to by @ret will be populated + * with a pointer to a struct acpi_device created while scanning the namespace. + * If @handle corresponds to a device node, that will be a pointer to the struct + * acpi_device object corresponding to @handle. Otherwise, it will be a pointer + * to a struct acpi_device corresponding to one of its descendants. + * + * If an error code is returned, NULL will be stored in the memory location + * pointed to by @ret. */ - -int -acpi_bus_add(struct acpi_device **child, - struct acpi_device *parent, acpi_handle handle, int type) +int acpi_bus_add(acpi_handle handle, struct acpi_device **ret) { int err; - err = acpi_bus_scan(handle, false, child); + err = acpi_bus_scan(handle, false, ret); if (err) return err; Index: linux/include/acpi/acpi_bus.h =================================================================== --- linux.orig/include/acpi/acpi_bus.h +++ linux/include/acpi/acpi_bus.h @@ -398,8 +398,7 @@ static inline int acpi_bus_generate_proc #endif int acpi_bus_register_driver(struct acpi_driver *driver); void acpi_bus_unregister_driver(struct acpi_driver *driver); -int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent, - acpi_handle handle, int type); +int acpi_bus_add(acpi_handle handle, struct acpi_device **ret); void acpi_bus_hot_remove_device(void *context); int acpi_bus_trim(struct acpi_device *start, int rmdevice); acpi_status acpi_bus_get_ejd(acpi_handle handle, acpi_handle * ejd); Index: linux/drivers/pci/hotplug/sgi_hotplug.c =================================================================== --- linux.orig/drivers/pci/hotplug/sgi_hotplug.c +++ linux/drivers/pci/hotplug/sgi_hotplug.c @@ -448,8 +448,7 @@ static int enable_slot(struct hotplug_sl if (ACPI_SUCCESS(ret) && (adr>>16) == (slot->device_num + 1)) { - ret = acpi_bus_add(&device, pdevice, chandle, - ACPI_BUS_TYPE_DEVICE); + ret = acpi_bus_add(chandle, &device); if (ACPI_FAILURE(ret)) { printk(KERN_ERR "%s: acpi_bus_add " "failed (0x%x) for slot %d " Index: linux/drivers/pci/hotplug/acpiphp_glue.c =================================================================== --- linux.orig/drivers/pci/hotplug/acpiphp_glue.c +++ linux/drivers/pci/hotplug/acpiphp_glue.c @@ -734,15 +734,9 @@ static unsigned char acpiphp_max_busnr(s */ static int acpiphp_bus_add(struct acpiphp_func *func) { - acpi_handle phandle; - struct acpi_device *device, *pdevice; + struct acpi_device *device; int ret_val; - acpi_get_parent(func->handle, &phandle); - if (acpi_bus_get_device(phandle, &pdevice)) { - dbg("no parent device, assuming NULL\n"); - pdevice = NULL; - } if (!acpi_bus_get_device(func->handle, &device)) { dbg("bus exists... trim\n"); /* this shouldn't be in here, so remove @@ -752,8 +746,7 @@ static int acpiphp_bus_add(struct acpiph dbg("acpi_bus_trim return %x\n", ret_val); } - ret_val = acpi_bus_add(&device, pdevice, func->handle, - ACPI_BUS_TYPE_DEVICE); + ret_val = acpi_bus_add(func->handle, &device); if (ret_val) { dbg("error adding bus, %x\n", -ret_val); @@ -1129,8 +1122,7 @@ static int acpiphp_configure_bridge (acp static void handle_bridge_insertion(acpi_handle handle, u32 type) { - struct acpi_device *device, *pdevice; - acpi_handle phandle; + struct acpi_device *device; if ((type != ACPI_NOTIFY_BUS_CHECK) && (type != ACPI_NOTIFY_DEVICE_CHECK)) { @@ -1138,12 +1130,7 @@ static void handle_bridge_insertion(acpi return; } - acpi_get_parent(handle, &phandle); - if (acpi_bus_get_device(phandle, &pdevice)) { - dbg("no parent device, assuming NULL\n"); - pdevice = NULL; - } - if (acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE)) { + if (acpi_bus_add(handle, &device)) { err("cannot add bridge to acpi list\n"); return; } Index: linux/drivers/acpi/processor_driver.c =================================================================== --- linux.orig/drivers/acpi/processor_driver.c +++ linux/drivers/acpi/processor_driver.c @@ -677,28 +677,6 @@ static int is_processor_present(acpi_han return 0; } -static -int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) -{ - acpi_handle phandle; - struct acpi_device *pdev; - - - if (acpi_get_parent(handle, &phandle)) { - return -ENODEV; - } - - if (acpi_bus_get_device(phandle, &pdev)) { - return -ENODEV; - } - - if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_PROCESSOR)) { - return -ENODEV; - } - - return 0; -} - static void acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data) { @@ -721,7 +699,7 @@ static void acpi_processor_hotplug_notif if (!acpi_bus_get_device(handle, &device)) break; - result = acpi_processor_device_add(handle, &device); + result = acpi_bus_add(handle, &device); if (result) { acpi_handle_err(handle, "Unable to add the device\n"); break; Index: linux/drivers/acpi/dock.c =================================================================== --- linux.orig/drivers/acpi/dock.c +++ linux/drivers/acpi/dock.c @@ -310,8 +310,6 @@ static int dock_present(struct dock_stat static struct acpi_device * dock_create_acpi_device(acpi_handle handle) { struct acpi_device *device; - struct acpi_device *parent_device; - acpi_handle parent; int ret; if (acpi_bus_get_device(handle, &device)) { @@ -319,16 +317,9 @@ static struct acpi_device * dock_create_ * no device created for this object, * so we should create one. */ - acpi_get_parent(handle, &parent); - if (acpi_bus_get_device(parent, &parent_device)) - parent_device = NULL; - - ret = acpi_bus_add(&device, parent_device, handle, - ACPI_BUS_TYPE_DEVICE); - if (ret) { + ret = acpi_bus_add(handle, &device); + if (ret) pr_debug("error adding bus, %x\n", -ret); - return NULL; - } } return device; } Index: linux/drivers/acpi/container.c =================================================================== --- linux.orig/drivers/acpi/container.c +++ linux/drivers/acpi/container.c @@ -135,20 +135,6 @@ static int acpi_container_remove(struct return status; } -static int container_device_add(struct acpi_device **device, acpi_handle handle) -{ - acpi_handle phandle; - struct acpi_device *pdev; - - if (acpi_get_parent(handle, &phandle)) - return -ENODEV; - - if (acpi_bus_get_device(phandle, &pdev)) - return -ENODEV; - - return acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_DEVICE); -} - static void container_notify_cb(acpi_handle handle, u32 type, void *context) { struct acpi_device *device = NULL; @@ -180,7 +166,7 @@ static void container_notify_cb(acpi_han if (!ACPI_FAILURE(status) || device) break; - result = container_device_add(&device, handle); + result = acpi_bus_add(handle, &device); if (result) { acpi_handle_warn(handle, "Failed to add container\n"); break; Index: linux/drivers/acpi/acpi_memhotplug.c =================================================================== --- linux.orig/drivers/acpi/acpi_memhotplug.c +++ linux/drivers/acpi/acpi_memhotplug.c @@ -157,34 +157,17 @@ static int acpi_memory_get_device(acpi_handle handle, struct acpi_memory_device **mem_device) { - acpi_status status; - acpi_handle phandle; struct acpi_device *device = NULL; - struct acpi_device *pdevice = NULL; int result; - if (!acpi_bus_get_device(handle, &device) && device) goto end; - status = acpi_get_parent(handle, &phandle); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Cannot find acpi parent")); - return -EINVAL; - } - - /* Get the parent device */ - result = acpi_bus_get_device(phandle, &pdevice); - if (result) { - acpi_handle_warn(phandle, "Cannot get acpi bus device\n"); - return -EINVAL; - } - /* * Now add the notified device. This creates the acpi_device * and invokes .add function */ - result = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE); + result = acpi_bus_add(handle, &device); if (result) { acpi_handle_warn(handle, "Cannot add acpi bus\n"); return -EINVAL; ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH 10/16] ACPI: Drop the second argument of acpi_bus_scan() 2012-12-20 1:45 ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki ` (8 preceding siblings ...) 2012-12-20 1:54 ` [PATCH 9/16] ACPI: Remove the arguments of acpi_bus_add() that are not used Rafael J. Wysocki @ 2012-12-20 1:54 ` Rafael J. Wysocki 2012-12-20 1:55 ` [PATCH 11/16] ACPI: Replace ACPI device add_type field with a match_driver flag Rafael J. Wysocki ` (6 subsequent siblings) 16 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-20 1:54 UTC (permalink / raw) To: ACPI Devel Maling List Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> After the removal of acpi_start_single_object() and acpi_bus_start() the second argument of acpi_bus_scan() is not necessary any more, so drop it and update acpi_bus_check_add() accordingly. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Yinghai Lu <yinghai@kernel.org> --- drivers/acpi/scan.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -1592,8 +1592,8 @@ static int acpi_bus_type_and_status(acpi return 0; } -static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl, - void *context, void **return_value) +static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, + void *not_used, void **return_value) { struct acpi_device *device = NULL; int type; @@ -1625,7 +1625,7 @@ static acpi_status acpi_bus_check_add(ac if (!device) return AE_CTRL_DEPTH; - device->add_type = context ? ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH; + device->add_type = ACPI_BUS_ADD_START; acpi_hot_add_bind(device); out: @@ -1662,18 +1662,16 @@ static acpi_status acpi_bus_device_attac return status; } -static int acpi_bus_scan(acpi_handle handle, bool start, - struct acpi_device **child) +static int acpi_bus_scan(acpi_handle handle, struct acpi_device **child) { void *device = NULL; acpi_status status; int ret = -ENODEV; - status = acpi_bus_check_add(handle, 0, (void *)start, &device); + status = acpi_bus_check_add(handle, 0, NULL, &device); if (ACPI_SUCCESS(status)) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - acpi_bus_check_add, NULL, (void *)start, - &device); + acpi_bus_check_add, NULL, NULL, &device); if (!device) goto out; @@ -1717,7 +1715,7 @@ int acpi_bus_add(acpi_handle handle, str { int err; - err = acpi_bus_scan(handle, false, ret); + err = acpi_bus_scan(handle, ret); if (err) return err; @@ -1823,7 +1821,7 @@ int __init acpi_scan_init(void) /* * Enumerate devices in the ACPI namespace. */ - result = acpi_bus_scan(ACPI_ROOT_OBJECT, true, &acpi_root); + result = acpi_bus_scan(ACPI_ROOT_OBJECT, &acpi_root); if (!result) result = acpi_bus_scan_fixed(); ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH 11/16] ACPI: Replace ACPI device add_type field with a match_driver flag 2012-12-20 1:45 ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki ` (9 preceding siblings ...) 2012-12-20 1:54 ` [PATCH 10/16] ACPI: Drop the second argument of acpi_bus_scan() Rafael J. Wysocki @ 2012-12-20 1:55 ` Rafael J. Wysocki 2012-12-20 1:56 ` [PATCH 12/16] ACPI: Make acpi_bus_scan() and acpi_bus_add() take only one argument Rafael J. Wysocki ` (5 subsequent siblings) 16 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-20 1:55 UTC (permalink / raw) To: ACPI Devel Maling List Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> After the removal of the second argument of acpi_bus_scan() there is no difference between the ACPI_BUS_ADD_MATCH and ACPI_BUS_ADD_START add types, so the add_type field in struct acpi_device may be replaced with a single flag. Do that calling the flag match_driver. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Yinghai Lu <yinghai@kernel.org> --- drivers/acpi/scan.c | 21 +++++++++------------ include/acpi/acpi_bus.h | 11 ++--------- 2 files changed, 11 insertions(+), 21 deletions(-) Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -535,7 +535,7 @@ static int acpi_bus_match(struct device struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_driver *acpi_drv = to_acpi_driver(drv); - return acpi_dev->add_type >= ACPI_BUS_ADD_MATCH + return acpi_dev->flags.match_driver && !acpi_match_device_ids(acpi_dev, acpi_drv->ids); } @@ -1451,8 +1451,7 @@ static void acpi_hot_add_bind(struct acp static int acpi_add_single_object(struct acpi_device **child, acpi_handle handle, int type, - unsigned long long sta, - enum acpi_bus_add_type add_type) + unsigned long long sta, bool match_driver) { int result; struct acpi_device *device; @@ -1468,7 +1467,6 @@ static int acpi_add_single_object(struct device->device_type = type; device->handle = handle; device->parent = acpi_bus_get_parent(handle); - device->add_type = add_type; STRUCT_TO_INT(device->status) = sta; acpi_device_get_busid(device); @@ -1519,9 +1517,10 @@ static int acpi_add_single_object(struct if ((result = acpi_device_set_context(device))) goto end; + device->flags.match_driver = match_driver; result = acpi_device_register(device); - if (device->add_type >= ACPI_BUS_ADD_MATCH) + if (device->flags.match_driver) acpi_hot_add_bind(device); end: @@ -1550,7 +1549,7 @@ static void acpi_bus_add_power_resource( acpi_bus_get_device(handle, &device); if (!device) acpi_add_single_object(&device, handle, ACPI_BUS_TYPE_POWER, - ACPI_STA_DEFAULT, ACPI_BUS_ADD_START); + ACPI_STA_DEFAULT, true); } static int acpi_bus_type_and_status(acpi_handle handle, int *type, @@ -1621,11 +1620,11 @@ static acpi_status acpi_bus_check_add(ac return AE_CTRL_DEPTH; } - acpi_add_single_object(&device, handle, type, sta, ACPI_BUS_ADD_BASIC); + acpi_add_single_object(&device, handle, type, sta, false); if (!device) return AE_CTRL_DEPTH; - device->add_type = ACPI_BUS_ADD_START; + device->flags.match_driver = true; acpi_hot_add_bind(device); out: @@ -1790,16 +1789,14 @@ static int acpi_bus_scan_fixed(void) if ((acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON) == 0) { result = acpi_add_single_object(&device, NULL, ACPI_BUS_TYPE_POWER_BUTTON, - ACPI_STA_DEFAULT, - ACPI_BUS_ADD_START); + ACPI_STA_DEFAULT, true); device_init_wakeup(&device->dev, true); } if ((acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON) == 0) { result = acpi_add_single_object(&device, NULL, ACPI_BUS_TYPE_SLEEP_BUTTON, - ACPI_STA_DEFAULT, - ACPI_BUS_ADD_START); + ACPI_STA_DEFAULT, true); } return result; Index: linux/include/acpi/acpi_bus.h =================================================================== --- linux.orig/include/acpi/acpi_bus.h +++ linux/include/acpi/acpi_bus.h @@ -63,13 +63,6 @@ acpi_get_physical_device_location(acpi_h #define ACPI_BUS_FILE_ROOT "acpi" extern struct proc_dir_entry *acpi_root_dir; -enum acpi_bus_add_type { - ACPI_BUS_ADD_BASIC = 0, - ACPI_BUS_ADD_MATCH, - ACPI_BUS_ADD_START, - ACPI_BUS_ADD_TYPE_COUNT -}; - enum acpi_bus_removal_type { ACPI_BUS_REMOVAL_NORMAL = 0, ACPI_BUS_REMOVAL_EJECT, @@ -150,7 +143,8 @@ struct acpi_device_flags { u32 power_manageable:1; u32 performance_manageable:1; u32 eject_pending:1; - u32 reserved:24; + u32 match_driver:1; + u32 reserved:23; }; /* File System */ @@ -285,7 +279,6 @@ struct acpi_device { struct acpi_driver *driver; void *driver_data; struct device dev; - enum acpi_bus_add_type add_type; /* how to handle adding */ enum acpi_bus_removal_type removal_type; /* indicate for different removal type */ u8 physical_node_count; struct list_head physical_node_list; ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH 12/16] ACPI: Make acpi_bus_scan() and acpi_bus_add() take only one argument 2012-12-20 1:45 ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki ` (10 preceding siblings ...) 2012-12-20 1:55 ` [PATCH 11/16] ACPI: Replace ACPI device add_type field with a match_driver flag Rafael J. Wysocki @ 2012-12-20 1:56 ` Rafael J. Wysocki 2012-12-20 1:57 ` [PATCH 13/16] ACPI: Add .setup() and .cleanup() callbacks to struct acpi_bus_type Rafael J. Wysocki ` (4 subsequent siblings) 16 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-20 1:56 UTC (permalink / raw) To: ACPI Devel Maling List Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> The callers of acpi_bus_add() usually assume that if it has succeeded, then a struct acpi_device object has been attached to the handle passed as the first argument. Unfortunately, however, this assumption is wrong, because acpi_bus_scan(), and acpi_bus_add() too as a result, may return a pointer to a different struct acpi_device object on success (it may be an object corresponding to one of the descendant ACPI nodes in the namespace scope below that handle). For this reason, the callers of acpi_bus_add() who care about whether or not a struct acpi_device object has been created for its first argument need to check that using acpi_bus_get_device() anyway, so the second argument of acpi_bus_add() is not really useful for them. The same observation applies to acpi_bus_scan() executed directly from acpi_scan_init(). Therefore modify the relevant callers of acpi_bus_add() to check the existence of the struct acpi_device in question with the help of acpi_bus_get_device() and drop the no longer necessary second argument of acpi_bus_add(). Accordingly, modify acpi_scan_init() to use acpi_bus_get_device() to get acpi_root and drop the no longer needed second argument of acpi_bus_scan(). Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Yinghai Lu <yinghai@kernel.org> --- drivers/acpi/acpi_memhotplug.c | 7 +++++- drivers/acpi/container.c | 7 +++++- drivers/acpi/dock.c | 4 ++- drivers/acpi/processor_driver.c | 8 +++++-- drivers/acpi/scan.c | 38 ++++++++++--------------------------- drivers/pci/hotplug/acpiphp_glue.c | 19 ++++++++++-------- drivers/pci/hotplug/sgi_hotplug.c | 3 -- include/acpi/acpi_bus.h | 2 - 8 files changed, 45 insertions(+), 43 deletions(-) Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -1661,37 +1661,27 @@ static acpi_status acpi_bus_device_attac return status; } -static int acpi_bus_scan(acpi_handle handle, struct acpi_device **child) +static int acpi_bus_scan(acpi_handle handle) { void *device = NULL; - acpi_status status; - int ret = -ENODEV; - status = acpi_bus_check_add(handle, 0, NULL, &device); - if (ACPI_SUCCESS(status)) + if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device))) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, acpi_bus_check_add, NULL, NULL, &device); if (!device) - goto out; + return -ENODEV; - ret = 0; - status = acpi_bus_device_attach(handle, 0, NULL, NULL); - if (ACPI_SUCCESS(status)) + if (ACPI_SUCCESS(acpi_bus_device_attach(handle, 0, NULL, NULL))) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, acpi_bus_device_attach, NULL, NULL, NULL); - out: - if (child) - *child = device; - - return ret; + return 0; } /** * acpi_bus_add - Add ACPI device node objects in a given namespace scope. * @handle: Root of the namespace scope to scan. - * @ret: Location to store a return struct acpi_device pointer. * * Scan a given ACPI tree (probably recently hot-plugged) and create and add * found devices. @@ -1700,21 +1690,12 @@ static int acpi_bus_scan(acpi_handle han * there has been a real error. There just have been no suitable ACPI objects * in the table trunk from which the kernel could create a device and add an * appropriate driver. - * - * If 0 is returned, the memory location pointed to by @ret will be populated - * with a pointer to a struct acpi_device created while scanning the namespace. - * If @handle corresponds to a device node, that will be a pointer to the struct - * acpi_device object corresponding to @handle. Otherwise, it will be a pointer - * to a struct acpi_device corresponding to one of its descendants. - * - * If an error code is returned, NULL will be stored in the memory location - * pointed to by @ret. */ -int acpi_bus_add(acpi_handle handle, struct acpi_device **ret) +int acpi_bus_add(acpi_handle handle) { int err; - err = acpi_bus_scan(handle, ret); + err = acpi_bus_scan(handle); if (err) return err; @@ -1818,8 +1799,11 @@ int __init acpi_scan_init(void) /* * Enumerate devices in the ACPI namespace. */ - result = acpi_bus_scan(ACPI_ROOT_OBJECT, &acpi_root); + result = acpi_bus_scan(ACPI_ROOT_OBJECT); + if (result) + return result; + result = acpi_bus_get_device(ACPI_ROOT_OBJECT, &acpi_root); if (!result) result = acpi_bus_scan_fixed(); Index: linux/include/acpi/acpi_bus.h =================================================================== --- linux.orig/include/acpi/acpi_bus.h +++ linux/include/acpi/acpi_bus.h @@ -391,7 +391,7 @@ static inline int acpi_bus_generate_proc #endif int acpi_bus_register_driver(struct acpi_driver *driver); void acpi_bus_unregister_driver(struct acpi_driver *driver); -int acpi_bus_add(acpi_handle handle, struct acpi_device **ret); +int acpi_bus_add(acpi_handle handle); void acpi_bus_hot_remove_device(void *context); int acpi_bus_trim(struct acpi_device *start, int rmdevice); acpi_status acpi_bus_get_ejd(acpi_handle handle, acpi_handle * ejd); Index: linux/drivers/pci/hotplug/sgi_hotplug.c =================================================================== --- linux.orig/drivers/pci/hotplug/sgi_hotplug.c +++ linux/drivers/pci/hotplug/sgi_hotplug.c @@ -412,7 +412,6 @@ static int enable_slot(struct hotplug_sl if (SN_ACPI_BASE_SUPPORT() && ssdt) { unsigned long long adr; struct acpi_device *pdevice; - struct acpi_device *device; acpi_handle phandle; acpi_handle chandle = NULL; acpi_handle rethandle; @@ -448,7 +447,7 @@ static int enable_slot(struct hotplug_sl if (ACPI_SUCCESS(ret) && (adr>>16) == (slot->device_num + 1)) { - ret = acpi_bus_add(chandle, &device); + ret = acpi_bus_add(chandle); if (ACPI_FAILURE(ret)) { printk(KERN_ERR "%s: acpi_bus_add " "failed (0x%x) for slot %d " Index: linux/drivers/pci/hotplug/acpiphp_glue.c =================================================================== --- linux.orig/drivers/pci/hotplug/acpiphp_glue.c +++ linux/drivers/pci/hotplug/acpiphp_glue.c @@ -746,14 +746,13 @@ static int acpiphp_bus_add(struct acpiph dbg("acpi_bus_trim return %x\n", ret_val); } - ret_val = acpi_bus_add(func->handle, &device); - if (ret_val) { - dbg("error adding bus, %x\n", - -ret_val); - goto acpiphp_bus_add_out; - } + ret_val = acpi_bus_add(func->handle); + if (!ret_val) + ret_val = acpi_bus_get_device(func->handle, &device); + + if (ret_val) + dbg("error adding bus, %x\n", -ret_val); -acpiphp_bus_add_out: return ret_val; } @@ -1130,10 +1129,14 @@ static void handle_bridge_insertion(acpi return; } - if (acpi_bus_add(handle, &device)) { + if (acpi_bus_add(handle)) { err("cannot add bridge to acpi list\n"); return; } + if (acpi_bus_get_device(handle, &device)) { + err("ACPI device object missing\n"); + return; + } if (!acpiphp_configure_bridge(handle)) add_bridge(handle); else Index: linux/drivers/acpi/processor_driver.c =================================================================== --- linux.orig/drivers/acpi/processor_driver.c +++ linux/drivers/acpi/processor_driver.c @@ -699,12 +699,16 @@ static void acpi_processor_hotplug_notif if (!acpi_bus_get_device(handle, &device)) break; - result = acpi_bus_add(handle, &device); + result = acpi_bus_add(handle); if (result) { acpi_handle_err(handle, "Unable to add the device\n"); break; } - + result = acpi_bus_get_device(handle, &device); + if (result) { + acpi_handle_err(handle, "Missing device object\n"); + break; + } ost_code = ACPI_OST_SC_SUCCESS; break; Index: linux/drivers/acpi/dock.c =================================================================== --- linux.orig/drivers/acpi/dock.c +++ linux/drivers/acpi/dock.c @@ -317,9 +317,11 @@ static struct acpi_device * dock_create_ * no device created for this object, * so we should create one. */ - ret = acpi_bus_add(handle, &device); + ret = acpi_bus_add(handle); if (ret) pr_debug("error adding bus, %x\n", -ret); + + acpi_bus_get_device(handle, &device); } return device; } Index: linux/drivers/acpi/container.c =================================================================== --- linux.orig/drivers/acpi/container.c +++ linux/drivers/acpi/container.c @@ -166,11 +166,16 @@ static void container_notify_cb(acpi_han if (!ACPI_FAILURE(status) || device) break; - result = acpi_bus_add(handle, &device); + result = acpi_bus_add(handle); if (result) { acpi_handle_warn(handle, "Failed to add container\n"); break; } + result = acpi_bus_get_device(handle, &device); + if (result) { + acpi_handle_warn(handle, "Missing device object\n"); + break; + } kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); ost_code = ACPI_OST_SC_SUCCESS; Index: linux/drivers/acpi/acpi_memhotplug.c =================================================================== --- linux.orig/drivers/acpi/acpi_memhotplug.c +++ linux/drivers/acpi/acpi_memhotplug.c @@ -167,11 +167,16 @@ acpi_memory_get_device(acpi_handle handl * Now add the notified device. This creates the acpi_device * and invokes .add function */ - result = acpi_bus_add(handle, &device); + result = acpi_bus_add(handle); if (result) { acpi_handle_warn(handle, "Cannot add acpi bus\n"); return -EINVAL; } + result = acpi_bus_get_device(handle, &device); + if (result) { + acpi_handle_warn(handle, "Missing device object\n"); + return -EINVAL; + } end: *mem_device = acpi_driver_data(device); ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH 13/16] ACPI: Add .setup() and .cleanup() callbacks to struct acpi_bus_type 2012-12-20 1:45 ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki ` (11 preceding siblings ...) 2012-12-20 1:56 ` [PATCH 12/16] ACPI: Make acpi_bus_scan() and acpi_bus_add() take only one argument Rafael J. Wysocki @ 2012-12-20 1:57 ` Rafael J. Wysocki 2012-12-20 1:58 ` [PATCH 14/16] ACPI / PCI: Rework the setup and cleanup of device wakeup Rafael J. Wysocki ` (3 subsequent siblings) 16 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-20 1:57 UTC (permalink / raw) To: ACPI Devel Maling List Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Add two new callbacks,.setup() and .cleanup(), struct acpi_bus_type and modify acpi_platform_notify() to call .setup() after executing acpi_bind_one() successfully and acpi_platform_notify_remove() to call .cleanup() before running acpi_unbind_one(). This will allow the users of struct acpi_bus_type, PCI in particular, to specify operations to be executed right after the given device has been associated with a companion struct acpi_device and right before it's going to be detached from that companion, respectively. The main motivation is to be able to get rid of acpi_pci_bind() and acpi_pci_unbind(), which are horrible horrible stuff. [In short, there are three problems with them: The way they populate the .bind() and .unbind() callbacks of ACPI devices is rather less than straightforward, they require special hotplug-specific paths to be present in the ACPI namespace scanning code and by the time acpi_pci_unbind() is called the PCI device object in question may not exist any more.] Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> --- drivers/acpi/glue.c | 52 +++++++++++++++++++++++++++++++++--------------- include/acpi/acpi_bus.h | 2 + 2 files changed, 38 insertions(+), 16 deletions(-) Index: linux/include/acpi/acpi_bus.h =================================================================== --- linux.orig/include/acpi/acpi_bus.h +++ linux/include/acpi/acpi_bus.h @@ -423,6 +423,8 @@ struct acpi_bus_type { int (*find_device) (struct device *, acpi_handle *); /* For bridges, such as PCI root bridge, IDE controller */ int (*find_bridge) (struct device *, acpi_handle *); + void (*setup)(struct device *); + void (*cleanup)(struct device *); }; int register_acpi_bus_type(struct acpi_bus_type *); int unregister_acpi_bus_type(struct acpi_bus_type *); Index: linux/drivers/acpi/glue.c =================================================================== --- linux.orig/drivers/acpi/glue.c +++ linux/drivers/acpi/glue.c @@ -63,6 +63,9 @@ static struct acpi_bus_type *acpi_get_bu { struct acpi_bus_type *tmp, *ret = NULL; + if (!type) + return NULL; + down_read(&bus_type_sem); list_for_each_entry(tmp, &bus_type_list, list) { if (tmp->bus == type) { @@ -264,28 +267,39 @@ static int acpi_platform_notify(struct d { struct acpi_bus_type *type; acpi_handle handle; - int ret = -EINVAL; + int ret; ret = acpi_bind_one(dev, NULL); - if (!ret) - goto out; - - if (!dev->bus || !dev->parent) { + if (ret && (!dev->bus || !dev->parent)) { /* bridge devices genernally haven't bus or parent */ ret = acpi_find_bridge_device(dev, &handle); - goto end; + if (!ret) { + ret = acpi_bind_one(dev, handle); + if (ret) + goto out; + } } + type = acpi_get_bus_type(dev->bus); - if (!type) { - DBG("No ACPI bus support for %s\n", dev_name(dev)); - ret = -EINVAL; - goto end; - } - if ((ret = type->find_device(dev, &handle)) != 0) - DBG("Can't get handler for %s\n", dev_name(dev)); - end: - if (!ret) - acpi_bind_one(dev, handle); + if (ret) { + if (!type || !type->find_device) { + DBG("No ACPI bus support for %s\n", dev_name(dev)); + ret = -EINVAL; + goto out; + } + + ret = type->find_device(dev, &handle); + if (ret) { + DBG("Unable to get handle for %s\n", dev_name(dev)); + goto out; + } + ret = acpi_bind_one(dev, handle); + if (ret) + goto out; + } + + if (type && type->setup) + type->setup(dev); out: #if ACPI_GLUE_DEBUG @@ -304,6 +318,12 @@ static int acpi_platform_notify(struct d static int acpi_platform_notify_remove(struct device *dev) { + struct acpi_bus_type *type; + + type = acpi_get_bus_type(dev->bus); + if (type && type->cleanup) + type->cleanup(dev); + acpi_unbind_one(dev); return 0; } ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH 14/16] ACPI / PCI: Rework the setup and cleanup of device wakeup 2012-12-20 1:45 ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki ` (12 preceding siblings ...) 2012-12-20 1:57 ` [PATCH 13/16] ACPI: Add .setup() and .cleanup() callbacks to struct acpi_bus_type Rafael J. Wysocki @ 2012-12-20 1:58 ` Rafael J. Wysocki 2012-12-20 1:59 ` [PATCH 15/16] ACPI / PCI: Move the _PRT setup and cleanup code to pci-acpi.c Rafael J. Wysocki ` (2 subsequent siblings) 16 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-20 1:58 UTC (permalink / raw) To: ACPI Devel Maling List Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Currently, the ACPI wakeup capability of PCI devices is set up in two different places, partially in acpi_pci_bind() where runtime wakeup is initialized and partially in platform_pci_wakeup_init(), where system wakeup is initialized. The cleanup is only done in acpi_pci_unbind() and it only covers runtime wakeup. Use the new .setup() and .cleanup() callbacks in struct acpi_bus_type to consolidate that code and do the setup and the cleanup each in one place. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> --- drivers/acpi/device_pm.c | 2 +- drivers/acpi/pci_bind.c | 7 ------- drivers/pci/pci-acpi.c | 30 +++++++++++++++++++++++++++++- drivers/pci/pci.c | 26 +------------------------- drivers/pci/pci.h | 5 ----- drivers/pci/probe.c | 1 - include/linux/acpi.h | 5 +++++ 7 files changed, 36 insertions(+), 40 deletions(-) Index: linux/drivers/acpi/pci_bind.c =================================================================== --- linux.orig/drivers/acpi/pci_bind.c +++ linux/drivers/acpi/pci_bind.c @@ -43,9 +43,6 @@ static int acpi_pci_unbind(struct acpi_d if (!dev) goto out; - device_set_run_wake(&dev->dev, false); - pci_acpi_remove_pm_notifier(device); - if (!dev->subordinate) goto out; @@ -70,10 +67,6 @@ static int acpi_pci_bind(struct acpi_dev if (!dev) return 0; - pci_acpi_add_pm_notifier(device, dev); - if (device->wakeup.flags.run_wake) - device_set_run_wake(&dev->dev, true); - /* * Install the 'bind' function to facilitate callbacks for * children of the P2P bridge. Index: linux/drivers/pci/pci.h =================================================================== --- linux.orig/drivers/pci/pci.h +++ linux/drivers/pci/pci.h @@ -44,9 +44,6 @@ int pci_probe_reset_function(struct pci_ * platform; to be used during system-wide transitions from a * sleeping state to the working state and vice versa * - * @can_wakeup: returns 'true' if given device is capable of waking up the - * system from a sleeping state - * * @sleep_wake: enables/disables the system wake up capability of given device * * @run_wake: enables/disables the platform to generate run-time wake-up events @@ -60,7 +57,6 @@ struct pci_platform_pm_ops { bool (*is_manageable)(struct pci_dev *dev); int (*set_state)(struct pci_dev *dev, pci_power_t state); pci_power_t (*choose_state)(struct pci_dev *dev); - bool (*can_wakeup)(struct pci_dev *dev); int (*sleep_wake)(struct pci_dev *dev, bool enable); int (*run_wake)(struct pci_dev *dev, bool enable); }; @@ -75,7 +71,6 @@ extern void pci_wakeup_bus(struct pci_bu extern void pci_config_pm_runtime_get(struct pci_dev *dev); extern void pci_config_pm_runtime_put(struct pci_dev *dev); extern void pci_pm_init(struct pci_dev *dev); -extern void platform_pci_wakeup_init(struct pci_dev *dev); extern void pci_allocate_cap_save_buffers(struct pci_dev *dev); void pci_free_cap_save_buffers(struct pci_dev *dev); Index: linux/drivers/pci/probe.c =================================================================== --- linux.orig/drivers/pci/probe.c +++ linux/drivers/pci/probe.c @@ -1276,7 +1276,6 @@ static void pci_init_capabilities(struct /* Power Management */ pci_pm_init(dev); - platform_pci_wakeup_init(dev); /* Vital Product Data */ pci_vpd_pci22_init(dev); Index: linux/drivers/pci/pci.c =================================================================== --- linux.orig/drivers/pci/pci.c +++ linux/drivers/pci/pci.c @@ -450,7 +450,7 @@ static struct pci_platform_pm_ops *pci_p int pci_set_platform_pm(struct pci_platform_pm_ops *ops) { if (!ops->is_manageable || !ops->set_state || !ops->choose_state - || !ops->sleep_wake || !ops->can_wakeup) + || !ops->sleep_wake) return -EINVAL; pci_platform_pm = ops; return 0; @@ -473,11 +473,6 @@ static inline pci_power_t platform_pci_c pci_platform_pm->choose_state(dev) : PCI_POWER_ERROR; } -static inline bool platform_pci_can_wakeup(struct pci_dev *dev) -{ - return pci_platform_pm ? pci_platform_pm->can_wakeup(dev) : false; -} - static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable) { return pci_platform_pm ? @@ -1960,25 +1955,6 @@ void pci_pm_init(struct pci_dev *dev) } } -/** - * platform_pci_wakeup_init - init platform wakeup if present - * @dev: PCI device - * - * Some devices don't have PCI PM caps but can still generate wakeup - * events through platform methods (like ACPI events). If @dev supports - * platform wakeup events, set the device flag to indicate as much. This - * may be redundant if the device also supports PCI PM caps, but double - * initialization should be safe in that case. - */ -void platform_pci_wakeup_init(struct pci_dev *dev) -{ - if (!platform_pci_can_wakeup(dev)) - return; - - device_set_wakeup_capable(&dev->dev, true); - platform_pci_sleep_wake(dev, false); -} - static void pci_add_saved_cap(struct pci_dev *pci_dev, struct pci_cap_saved_state *new_cap) { Index: linux/include/linux/acpi.h =================================================================== --- linux.orig/include/linux/acpi.h +++ linux/include/linux/acpi.h @@ -510,9 +510,14 @@ static inline int acpi_subsys_resume_ear #endif #if defined(CONFIG_ACPI) && defined(CONFIG_PM) +struct acpi_device *acpi_dev_pm_get_node(struct device *dev); int acpi_dev_pm_attach(struct device *dev, bool power_on); void acpi_dev_pm_detach(struct device *dev, bool power_off); #else +static struct acpi_device *acpi_dev_pm_get_node(struct device *dev) +{ + return NULL; +} static inline int acpi_dev_pm_attach(struct device *dev, bool power_on) { return -ENODEV; Index: linux/drivers/acpi/device_pm.c =================================================================== --- linux.orig/drivers/acpi/device_pm.c +++ linux/drivers/acpi/device_pm.c @@ -634,7 +634,7 @@ int acpi_pm_device_sleep_wake(struct dev * acpi_dev_pm_get_node - Get ACPI device node for the given physical device. * @dev: Device to get the ACPI node for. */ -static struct acpi_device *acpi_dev_pm_get_node(struct device *dev) +struct acpi_device *acpi_dev_pm_get_node(struct device *dev) { acpi_handle handle = DEVICE_ACPI_HANDLE(dev); struct acpi_device *adev; Index: linux/drivers/pci/pci-acpi.c =================================================================== --- linux.orig/drivers/pci/pci-acpi.c +++ linux/drivers/pci/pci-acpi.c @@ -283,7 +283,6 @@ static struct pci_platform_pm_ops acpi_p .is_manageable = acpi_pci_power_manageable, .set_state = acpi_pci_set_power_state, .choose_state = acpi_pci_choose_state, - .can_wakeup = acpi_pci_can_wakeup, .sleep_wake = acpi_pci_sleep_wake, .run_wake = acpi_pci_run_wake, }; @@ -321,10 +320,39 @@ static int acpi_pci_find_root_bridge(str return 0; } +static void acpi_pci_wakeup_setup(struct device *dev) +{ + struct acpi_device *adev = acpi_dev_pm_get_node(dev); + struct pci_dev *pci_dev = to_pci_dev(dev); + + if (!adev || !adev->wakeup.flags.valid) + return; + + device_set_wakeup_capable(dev, true); + acpi_pci_sleep_wake(pci_dev, false); + + pci_acpi_add_pm_notifier(adev, pci_dev); + if (adev->wakeup.flags.run_wake) + device_set_run_wake(dev, true); +} + +static void acpi_pci_wakeup_cleanup(struct device *dev) +{ + struct acpi_device *adev = acpi_dev_pm_get_node(dev); + + if (adev && adev->wakeup.flags.valid) { + device_set_wakeup_capable(dev, false); + device_set_run_wake(dev, false); + pci_acpi_remove_pm_notifier(adev); + } +} + static struct acpi_bus_type acpi_pci_bus = { .bus = &pci_bus_type, .find_device = acpi_pci_find_device, .find_bridge = acpi_pci_find_root_bridge, + .setup = acpi_pci_wakeup_setup, + .cleanup = acpi_pci_wakeup_cleanup, }; static int __init acpi_pci_init(void) ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH 15/16] ACPI / PCI: Move the _PRT setup and cleanup code to pci-acpi.c 2012-12-20 1:45 ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki ` (13 preceding siblings ...) 2012-12-20 1:58 ` [PATCH 14/16] ACPI / PCI: Rework the setup and cleanup of device wakeup Rafael J. Wysocki @ 2012-12-20 1:59 ` Rafael J. Wysocki 2012-12-20 2:06 ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Yinghai Lu 2012-12-20 21:07 ` Toshi Kani 16 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-20 1:59 UTC (permalink / raw) To: ACPI Devel Maling List Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Move the code related to _PRT setup and removal from acpi_pci_bind() and acpi_pci_unbind() to the .setup() and .cleanup() callbacks in acpi_pci_bus and remove acpi_pci_bind() and acpi_pci_unbind() that have no purpose any more. Accordingly, remove the code related to device .bind() and .unbind() operations from the ACPI PCI root bridge driver. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> --- drivers/acpi/Makefile | 2 drivers/acpi/pci_bind.c | 113 ------------------------------------------------ drivers/acpi/pci_root.c | 31 ------------- drivers/pci/pci-acpi.c | 34 +++++++++++--- 4 files changed, 29 insertions(+), 151 deletions(-) Index: linux/drivers/acpi/pci_bind.c =================================================================== --- linux.orig/drivers/acpi/pci_bind.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * pci_bind.c - ACPI PCI Device Binding ($Revision: 2 $) - * - * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> - * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/pci.h> -#include <linux/pci-acpi.h> -#include <linux/acpi.h> -#include <linux/pm_runtime.h> -#include <acpi/acpi_bus.h> -#include <acpi/acpi_drivers.h> - -#define _COMPONENT ACPI_PCI_COMPONENT -ACPI_MODULE_NAME("pci_bind"); - -static int acpi_pci_unbind(struct acpi_device *device) -{ - struct pci_dev *dev; - - dev = acpi_get_pci_dev(device->handle); - if (!dev) - goto out; - - if (!dev->subordinate) - goto out; - - acpi_pci_irq_del_prt(dev->subordinate); - - device->ops.bind = NULL; - device->ops.unbind = NULL; - -out: - pci_dev_put(dev); - return 0; -} - -static int acpi_pci_bind(struct acpi_device *device) -{ - acpi_status status; - acpi_handle handle; - struct pci_bus *bus; - struct pci_dev *dev; - - dev = acpi_get_pci_dev(device->handle); - if (!dev) - return 0; - - /* - * Install the 'bind' function to facilitate callbacks for - * children of the P2P bridge. - */ - if (dev->subordinate) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Device %04x:%02x:%02x.%d is a PCI bridge\n", - pci_domain_nr(dev->bus), dev->bus->number, - PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn))); - device->ops.bind = acpi_pci_bind; - device->ops.unbind = acpi_pci_unbind; - } - - /* - * Evaluate and parse _PRT, if exists. This code allows parsing of - * _PRT objects within the scope of non-bridge devices. Note that - * _PRTs within the scope of a PCI bridge assume the bridge's - * subordinate bus number. - * - * TBD: Can _PRTs exist within the scope of non-bridge PCI devices? - */ - status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); - if (ACPI_FAILURE(status)) - goto out; - - if (dev->subordinate) - bus = dev->subordinate; - else - bus = dev->bus; - - acpi_pci_irq_add_prt(device->handle, bus); - -out: - pci_dev_put(dev); - return 0; -} - -int acpi_pci_bind_root(struct acpi_device *device) -{ - device->ops.bind = acpi_pci_bind; - device->ops.unbind = acpi_pci_unbind; - - return 0; -} Index: linux/drivers/pci/pci-acpi.c =================================================================== --- linux.orig/drivers/pci/pci-acpi.c +++ linux/drivers/pci/pci-acpi.c @@ -320,12 +320,30 @@ static int acpi_pci_find_root_bridge(str return 0; } -static void acpi_pci_wakeup_setup(struct device *dev) +static void pci_acpi_setup(struct device *dev) { - struct acpi_device *adev = acpi_dev_pm_get_node(dev); struct pci_dev *pci_dev = to_pci_dev(dev); + acpi_handle handle = ACPI_HANDLE(dev); + struct acpi_device *adev; + acpi_status status; + acpi_handle dummy; + + /* + * Evaluate and parse _PRT, if exists. This code allows parsing of + * _PRT objects within the scope of non-bridge devices. Note that + * _PRTs within the scope of a PCI bridge assume the bridge's + * subordinate bus number. + * + * TBD: Can _PRTs exist within the scope of non-bridge PCI devices? + */ + status = acpi_get_handle(handle, METHOD_NAME__PRT, &dummy); + if (ACPI_SUCCESS(status)) { + struct pci_bus *bus = pci_dev->subordinate; + + acpi_pci_irq_add_prt(handle, bus ? bus : pci_dev->bus); + } - if (!adev || !adev->wakeup.flags.valid) + if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid) return; device_set_wakeup_capable(dev, true); @@ -336,23 +354,27 @@ static void acpi_pci_wakeup_setup(struct device_set_run_wake(dev, true); } -static void acpi_pci_wakeup_cleanup(struct device *dev) +static void pci_acpi_cleanup(struct device *dev) { struct acpi_device *adev = acpi_dev_pm_get_node(dev); + struct pci_dev *pci_dev = to_pci_dev(dev); if (adev && adev->wakeup.flags.valid) { device_set_wakeup_capable(dev, false); device_set_run_wake(dev, false); pci_acpi_remove_pm_notifier(adev); } + + if (pci_dev->subordinate) + acpi_pci_irq_del_prt(pci_dev->subordinate); } static struct acpi_bus_type acpi_pci_bus = { .bus = &pci_bus_type, .find_device = acpi_pci_find_device, .find_bridge = acpi_pci_find_root_bridge, - .setup = acpi_pci_wakeup_setup, - .cleanup = acpi_pci_wakeup_cleanup, + .setup = pci_acpi_setup, + .cleanup = pci_acpi_cleanup, }; static int __init acpi_pci_init(void) Index: linux/drivers/acpi/Makefile =================================================================== --- linux.orig/drivers/acpi/Makefile +++ linux/drivers/acpi/Makefile @@ -37,7 +37,7 @@ acpi-y += resource.o acpi-y += processor_core.o acpi-y += ec.o acpi-$(CONFIG_ACPI_DOCK) += dock.o -acpi-y += pci_root.o pci_link.o pci_irq.o pci_bind.o +acpi-y += pci_root.o pci_link.o pci_irq.o acpi-y += acpi_platform.o acpi-y += power.o acpi-y += event.o Index: linux/drivers/acpi/pci_root.c =================================================================== --- linux.orig/drivers/acpi/pci_root.c +++ linux/drivers/acpi/pci_root.c @@ -186,21 +186,6 @@ static acpi_status try_get_root_bridge_b return AE_OK; } -static void acpi_pci_bridge_scan(struct acpi_device *device) -{ - int status; - struct acpi_device *child = NULL; - - if (device->flags.bus_address) - if (device->parent && device->parent->ops.bind) { - status = device->parent->ops.bind(device); - if (!status) { - list_for_each_entry(child, &device->children, node) - acpi_pci_bridge_scan(child); - } - } -} - static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766"; static acpi_status acpi_pci_run_osc(acpi_handle handle, @@ -450,7 +435,6 @@ static int __devinit acpi_pci_root_add(s int result; struct acpi_pci_root *root; acpi_handle handle; - struct acpi_device *child; struct acpi_pci_driver *driver; u32 flags, base_flags; @@ -538,15 +522,6 @@ static int __devinit acpi_pci_root_add(s } /* - * Attach ACPI-PCI Context - * ----------------------- - * Thus binding the ACPI and PCI devices. - */ - result = acpi_pci_bind_root(device); - if (result) - goto out_del_root; - - /* * PCI Routing Table * ----------------- * Evaluate and parse _PRT, if exists. @@ -555,12 +530,6 @@ static int __devinit acpi_pci_root_add(s if (ACPI_SUCCESS(status)) result = acpi_pci_irq_add_prt(device->handle, root->bus); - /* - * Scan and bind all _ADR-Based Devices - */ - list_for_each_entry(child, &device->children, node) - acpi_pci_bridge_scan(child); - /* Indicate support for various _OSC capabilities. */ if (pci_ext_cfg_avail(root->bus->self)) flags |= OSC_EXT_PCI_CONFIG_SUPPORT; ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices 2012-12-20 1:45 ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki ` (14 preceding siblings ...) 2012-12-20 1:59 ` [PATCH 15/16] ACPI / PCI: Move the _PRT setup and cleanup code to pci-acpi.c Rafael J. Wysocki @ 2012-12-20 2:06 ` Yinghai Lu 2012-12-21 0:09 ` Rafael J. Wysocki 2012-12-20 21:07 ` Toshi Kani 16 siblings, 1 reply; 88+ messages in thread From: Yinghai Lu @ 2012-12-20 2:06 UTC (permalink / raw) To: Rafael J. Wysocki Cc: ACPI Devel Maling List, Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Myron Stowe, Yijing Wang, Jiang Liu On Wed, Dec 19, 2012 at 5:45 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: great!, the .bind and .unbind go away. > > The patches are on top of my master branch and I'm going to rebase them when > v3.8-rc1 is out. > > There is a git tree you can pull them from at: > > http://git.kernel.org/?p=linux/kernel/git/rafael/linux-pm.git;a=summary acpi-scan-temp-new > > It's v3.7 with my master branch merged and the new patches on top. can you make it base to today's Linus tree ? otherwise I have to do some manual merge... Bjorn change the _PRT for v.3.8... Thanks Yinghai ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices 2012-12-20 2:06 ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Yinghai Lu @ 2012-12-21 0:09 ` Rafael J. Wysocki 2012-12-21 3:59 ` Yinghai Lu 0 siblings, 1 reply; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-21 0:09 UTC (permalink / raw) To: Yinghai Lu Cc: ACPI Devel Maling List, Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Myron Stowe, Yijing Wang, Jiang Liu On Wednesday, December 19, 2012 06:06:57 PM Yinghai Lu wrote: > On Wed, Dec 19, 2012 at 5:45 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > > great!, the .bind and .unbind go away. > > > > > The patches are on top of my master branch and I'm going to rebase them when > > v3.8-rc1 is out. > > > > > There is a git tree you can pull them from at: > > > > http://git.kernel.org/?p=linux/kernel/git/rafael/linux-pm.git;a=summary acpi-scan-temp-new > > > > It's v3.7 with my master branch merged and the new patches on top. > > > can you make it base to today's Linus tree ? Sure. Rebased and pushed out: git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git acpi-scan-next Untested, though, so caveat emptor. :-) > otherwise I have to do some manual merge... > > Bjorn change the _PRT for v.3.8... Well, not only that has changed. Thanks, Rafael -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices 2012-12-21 0:09 ` Rafael J. Wysocki @ 2012-12-21 3:59 ` Yinghai Lu 2012-12-21 22:23 ` Rafael J. Wysocki 0 siblings, 1 reply; 88+ messages in thread From: Yinghai Lu @ 2012-12-21 3:59 UTC (permalink / raw) To: Rafael J. Wysocki Cc: ACPI Devel Maling List, Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Myron Stowe, Yijing Wang, Jiang Liu On Thu, Dec 20, 2012 at 4:09 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > On Wednesday, December 19, 2012 06:06:57 PM Yinghai Lu wrote: >> On Wed, Dec 19, 2012 at 5:45 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: >> >> great!, the .bind and .unbind go away. >> >> > >> > The patches are on top of my master branch and I'm going to rebase them when >> > v3.8-rc1 is out. >> >> > >> > There is a git tree you can pull them from at: >> > >> > http://git.kernel.org/?p=linux/kernel/git/rafael/linux-pm.git;a=summary acpi-scan-temp-new >> > >> > It's v3.7 with my master branch merged and the new patches on top. >> >> >> can you make it base to today's Linus tree ? > > Sure. Rebased and pushed out: > > git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git acpi-scan-next > Thanks. I rebased pci-root-bus-hotplug patchset on top it, and it works well. So Acked-by: Yinghai Lu <yinghai@kernel.org> for the four new ones in your acpi_scan_next branch. i put the updated patches in git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git for-pci-root-bus-3.9 ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices 2012-12-21 3:59 ` Yinghai Lu @ 2012-12-21 22:23 ` Rafael J. Wysocki 0 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-21 22:23 UTC (permalink / raw) To: Yinghai Lu Cc: ACPI Devel Maling List, Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Myron Stowe, Yijing Wang, Jiang Liu On Thursday, December 20, 2012 07:59:15 PM Yinghai Lu wrote: > On Thu, Dec 20, 2012 at 4:09 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > > On Wednesday, December 19, 2012 06:06:57 PM Yinghai Lu wrote: > >> On Wed, Dec 19, 2012 at 5:45 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > >> > >> great!, the .bind and .unbind go away. > >> > >> > > >> > The patches are on top of my master branch and I'm going to rebase them when > >> > v3.8-rc1 is out. > >> > >> > > >> > There is a git tree you can pull them from at: > >> > > >> > http://git.kernel.org/?p=linux/kernel/git/rafael/linux-pm.git;a=summary acpi-scan-temp-new > >> > > >> > It's v3.7 with my master branch merged and the new patches on top. > >> > >> > >> can you make it base to today's Linus tree ? > > > > Sure. Rebased and pushed out: > > > > git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git acpi-scan-next > > > > Thanks. > > I rebased pci-root-bus-hotplug patchset on top it, and it works well. Great, thanks for testing! > So > Acked-by: Yinghai Lu <yinghai@kernel.org> > for the four new ones in your acpi_scan_next branch. Thanks! I'll rebase the whole series on top of v3.8-rc1 when it's out. > i put the updated patches in > > git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git > for-pci-root-bus-3.9 OK, thanks. I'll have a look at that series next week. Thanks, Rafael -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices 2012-12-20 1:45 ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki ` (15 preceding siblings ...) 2012-12-20 2:06 ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Yinghai Lu @ 2012-12-20 21:07 ` Toshi Kani 2012-12-20 23:20 ` Rafael J. Wysocki 16 siblings, 1 reply; 88+ messages in thread From: Toshi Kani @ 2012-12-20 21:07 UTC (permalink / raw) To: Rafael J. Wysocki Cc: ACPI Devel Maling List, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu Hi Rafael, The changes look very good. It's much cleaner and consistent. :-) For the series: Acked-by: Toshi Kani <toshi.kani@hp.com> Thanks, -Toshi On Thu, 2012-12-20 at 02:45 +0100, Rafael J. Wysocki wrote: > Hi all, > > I've finally cut the patches removing acpi_pci_bind() and acpi_pci_unbind(), > so I'm kind of ready to post the entire series reworking the ACPI namespace > scanning code. > > Patches [1-6/16] are essentially these ones: > > https://patchwork.kernel.org/patch/1889821/ > https://patchwork.kernel.org/patch/1876481/ > https://patchwork.kernel.org/patch/1876531/ > https://patchwork.kernel.org/patch/1876571/ > https://patchwork.kernel.org/patch/1876511/ > https://patchwork.kernel.org/patch/1876401/ > > but [2-6/16] have been rebased on top of the first one. > > Patches [7-12/16] are essentially these: > > https://patchwork.kernel.org/patch/1884721/ > https://patchwork.kernel.org/patch/1884701/ > https://patchwork.kernel.org/patch/1884761/ > https://patchwork.kernel.org/patch/1884731/ > https://patchwork.kernel.org/patch/1884751/ > https://patchwork.kernel.org/patch/1884661/ > > but they have been rebased on top of https://patchwork.kernel.org/patch/1889821/. > I added Yinghai's ACKs to them tentatively, although they are a bit different > from the previous versions. The difference is not too important, however, > because the following patches finally remove the acpi_pci_bind()/acpi_pci_unbind() > stuff: > > [13/16] Add .setup() and .cleanup() callbacks to struct acpi_bus_type. > [14/16] Rework the setup and cleanup of ACPI/PCI device wakeup. > [15/16] Move the _PRT setup and cleanup code to pci-acpi.c. > [16/16] Drop ACPI device .bind() and .unbind() callbacks. > > This is done a bit differently than I thought it would be, mostly because the > _PRT-related operations require the "subordinate" pointers of bridges to be > populated. I think it may be possible to simplify this further if that > requirement can be removed (I haven't looked into that). > > In fact, patches [13-15/16] do not essentially depend on [1-12/16], only the > last one does. > > The patches are on top of my master branch and I'm going to rebase them when > v3.8-rc1 is out. > > There is a git tree you can pull them from at: > > http://git.kernel.org/?p=linux/kernel/git/rafael/linux-pm.git;a=summary acpi-scan-temp-new > > It's v3.7 with my master branch merged and the new patches on top. > > > Thanks, > Rafael > > ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices 2012-12-20 21:07 ` Toshi Kani @ 2012-12-20 23:20 ` Rafael J. Wysocki 0 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-20 23:20 UTC (permalink / raw) To: Toshi Kani Cc: ACPI Devel Maling List, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu On Thursday, December 20, 2012 02:07:27 PM Toshi Kani wrote: > Hi Rafael, > > The changes look very good. It's much cleaner and consistent. :-) For > the series: > > Acked-by: Toshi Kani <toshi.kani@hp.com> Thanks! -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH rev.2 2/6] ACPI: Change the ordering of PCI root bridge driver registrarion 2012-12-13 22:15 ` [PATCH rev.2 " Rafael J. Wysocki 2012-12-13 22:17 ` [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki @ 2012-12-13 22:18 ` Rafael J. Wysocki 2012-12-13 22:21 ` [PATCH rev.2 3/6] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different Rafael J. Wysocki ` (4 subsequent siblings) 6 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-13 22:18 UTC (permalink / raw) To: ACPI Devel Maling List Cc: Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Instead of running acpi_pci_root_init() from a separate subsys initcall, call it directly from acpi_scan_init() before scanning the ACPI namespace for the first time, so that the PCI root bridge driver's .add() routine, acpi_pci_root_start(), is always run before binding ACPI drivers or attaching "companion" device objects to struct acpi_device objects below the root bridge's device node in the ACPI namespace. The first, simpler reason for doing this is that it makes the situation during boot more similar to the situation during hotplug, in which the ACPI PCI root bridge driver is always present. The second reason is that acpi_pci_root_init() causes struct pci_dev objects to be created for all PCI devices below the bridge and these objects may be necessary for whatever is done with the other ACPI device nodes in that namespace scope. For example, devices created by acpi_create_platform_device() sometimes may need to be added to the device hierarchy as children of PCI bridges. For this purpose, however, the struct pci_dev objects representing those bridges need to exist before the platform devices in question are registered. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> --- drivers/acpi/internal.h | 1 + drivers/acpi/pci_root.c | 4 +--- drivers/acpi/scan.c | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) Index: linux/drivers/acpi/internal.h =================================================================== --- linux.orig/drivers/acpi/internal.h +++ linux/drivers/acpi/internal.h @@ -67,6 +67,7 @@ struct acpi_ec { extern struct acpi_ec *first_ec; +int acpi_pci_root_init(void); int acpi_ec_init(void); int acpi_ec_ecdt_probe(void); int acpi_boot_ec_enable(void); Index: linux/drivers/acpi/pci_root.c =================================================================== --- linux.orig/drivers/acpi/pci_root.c +++ linux/drivers/acpi/pci_root.c @@ -674,7 +674,7 @@ static int acpi_pci_root_remove(struct a return 0; } -static int __init acpi_pci_root_init(void) +int __init acpi_pci_root_init(void) { acpi_hest_init(); @@ -687,5 +687,3 @@ static int __init acpi_pci_root_init(voi return 0; } - -subsys_initcall(acpi_pci_root_init); Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -1833,6 +1833,7 @@ int __init acpi_scan_init(void) } acpi_power_init(); + acpi_pci_root_init(); /* * Enumerate devices in the ACPI namespace. ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH rev.2 3/6] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different 2012-12-13 22:15 ` [PATCH rev.2 " Rafael J. Wysocki 2012-12-13 22:17 ` [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki 2012-12-13 22:18 ` [PATCH rev.2 2/6] ACPI: Change the ordering of PCI root bridge driver registrarion Rafael J. Wysocki @ 2012-12-13 22:21 ` Rafael J. Wysocki 2012-12-13 22:21 ` [PATCH rev.2 4/6] ACPI: Reduce the usage of struct acpi_bus_ops Rafael J. Wysocki ` (3 subsequent siblings) 6 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-13 22:21 UTC (permalink / raw) To: ACPI Devel Maling List Cc: Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> The current ACPI namespace scanning code suggests that acpi_bus_add() and acpi_bus_start() share some code. In fact, however, they are completely different code paths (except for the initial checks), so refactor the code to make that distinction visibly clear. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> --- drivers/acpi/scan.c | 68 +++++++++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 30 deletions(-) Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -1622,10 +1622,9 @@ static acpi_status acpi_bus_check_add(ac return AE_OK; } -static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl, - void *context, void **not_used) +static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, + void *not_used, void **ret_not_used) { - struct acpi_bus_ops *ops = context; acpi_status status = AE_OK; struct acpi_device *device; unsigned long long sta_not_used; @@ -1641,18 +1640,13 @@ static acpi_status acpi_bus_probe_start( if (acpi_bus_get_device(handle, &device)) return AE_CTRL_DEPTH; - if (ops->acpi_op_add) { - if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { - /* This is a known good platform device. */ - acpi_create_platform_device(device); - } else { - int ret = device_attach(&device->dev); - acpi_hot_add_bind(device); - if (ret) - status = AE_CTRL_DEPTH; - } - } else if (ops->acpi_op_start) { - if (ACPI_FAILURE(acpi_start_single_object(device))) + if (!acpi_match_device_ids(device, acpi_platform_device_ids)) { + /* This is a known good platform device. */ + acpi_create_platform_device(device); + } else { + int ret = device_attach(&device->dev); + acpi_hot_add_bind(device); + if (ret) status = AE_CTRL_DEPTH; } return status; @@ -1674,10 +1668,10 @@ static int acpi_bus_scan(acpi_handle han goto out; ret = 0; - status = acpi_bus_probe_start(handle, 0, ops, NULL); + status = acpi_bus_device_attach(handle, 0, NULL, NULL); if (ACPI_SUCCESS(status)) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - acpi_bus_probe_start, NULL, ops, NULL); + acpi_bus_device_attach, NULL, NULL, NULL); out: if (child) @@ -1702,31 +1696,45 @@ int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent, acpi_handle handle, int type) { - struct acpi_bus_ops ops; - - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_add = 1; + struct acpi_bus_ops ops = { .acpi_op_add = 1, }; return acpi_bus_scan(handle, &ops, child); } EXPORT_SYMBOL(acpi_bus_add); -int acpi_bus_start(struct acpi_device *device) +static acpi_status acpi_bus_start_device(acpi_handle handle, u32 lvl, + void *not_used, void **ret_not_used) { - struct acpi_bus_ops ops; - int result; + struct acpi_device *device; + unsigned long long sta_not_used; + int type_not_used; + acpi_status status; + + /* + * Ignore errors ignored by acpi_bus_check_add() to avoid terminating + * namespace walks prematurely. + */ + if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used)) + return AE_OK; + + if (acpi_bus_get_device(handle, &device)) + return AE_CTRL_DEPTH; + return acpi_start_single_object(device); +} + +int acpi_bus_start(struct acpi_device *device) +{ if (!device) return -EINVAL; - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_start = 1; - - result = acpi_bus_scan(device->handle, &ops, NULL); + if (ACPI_SUCCESS(acpi_start_single_object(device))) + acpi_walk_namespace(ACPI_TYPE_ANY, device->handle, + ACPI_UINT32_MAX, acpi_bus_start_device, + NULL, NULL, NULL); acpi_update_all_gpes(); - - return result; + return 0; } EXPORT_SYMBOL(acpi_bus_start); ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH rev.2 4/6] ACPI: Reduce the usage of struct acpi_bus_ops 2012-12-13 22:15 ` [PATCH rev.2 " Rafael J. Wysocki ` (2 preceding siblings ...) 2012-12-13 22:21 ` [PATCH rev.2 3/6] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different Rafael J. Wysocki @ 2012-12-13 22:21 ` Rafael J. Wysocki 2012-12-13 22:22 ` [PATCH rev.2 5/6] ACPI: Replace struct acpi_bus_ops with enum type Rafael J. Wysocki ` (2 subsequent siblings) 6 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-13 22:21 UTC (permalink / raw) To: ACPI Devel Maling List Cc: Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Objects of type struct acpi_bus_ops are currently used to pass information between different parts of the ACPI namespace scanning code, sometimes in quite convoluted ways. It turns out that that is not necessary in some cases, so simplify the code by reducing the utilization of struct acpi_bus_ops objects where clearly possible. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> --- drivers/acpi/scan.c | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -1527,7 +1527,6 @@ end: static void acpi_bus_add_power_resource(acpi_handle handle) { struct acpi_bus_ops ops = { - .acpi_op_add = 1, .acpi_op_start = 1, .acpi_op_match = 1, }; @@ -1581,7 +1580,6 @@ static int acpi_bus_type_and_status(acpi static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl, void *context, void **return_value) { - struct acpi_bus_ops *ops = context; struct acpi_device *device = NULL; int type; unsigned long long sta; @@ -1605,11 +1603,13 @@ static acpi_status acpi_bus_check_add(ac } acpi_bus_get_device(handle, &device); - if (ops->acpi_op_add && !device) { - struct acpi_bus_ops add_ops = *ops; + if (!device) { + struct acpi_bus_ops ops = { + .acpi_op_start = !!context, + .acpi_op_match = 0, + }; - add_ops.acpi_op_match = 0; - acpi_add_single_object(&device, handle, type, sta, &add_ops); + acpi_add_single_object(&device, handle, type, sta, &ops); if (!device) return AE_CTRL_DEPTH; @@ -1652,17 +1652,18 @@ static acpi_status acpi_bus_device_attac return status; } -static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops, +static int acpi_bus_scan(acpi_handle handle, bool start, struct acpi_device **child) { void *device = NULL; acpi_status status; int ret = -ENODEV; - status = acpi_bus_check_add(handle, 0, ops, &device); + status = acpi_bus_check_add(handle, 0, (void *)start, &device); if (ACPI_SUCCESS(status)) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - acpi_bus_check_add, NULL, ops, &device); + acpi_bus_check_add, NULL, (void *)start, + &device); if (!device) goto out; @@ -1696,9 +1697,7 @@ int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent, acpi_handle handle, int type) { - struct acpi_bus_ops ops = { .acpi_op_add = 1, }; - - return acpi_bus_scan(handle, &ops, child); + return acpi_bus_scan(handle, false, child); } EXPORT_SYMBOL(acpi_bus_add); @@ -1796,12 +1795,10 @@ static int acpi_bus_scan_fixed(void) { int result = 0; struct acpi_device *device = NULL; - struct acpi_bus_ops ops; - - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_add = 1; - ops.acpi_op_start = 1; - ops.acpi_op_match = 1; + struct acpi_bus_ops ops = { + .acpi_op_start = 1, + .acpi_op_match = 1, + }; /* * Enumerate all fixed-feature devices. @@ -1827,11 +1824,6 @@ static int acpi_bus_scan_fixed(void) int __init acpi_scan_init(void) { int result; - struct acpi_bus_ops ops; - - memset(&ops, 0, sizeof(ops)); - ops.acpi_op_add = 1; - ops.acpi_op_start = 1; result = bus_register(&acpi_bus_type); if (result) { @@ -1845,7 +1837,7 @@ int __init acpi_scan_init(void) /* * Enumerate devices in the ACPI namespace. */ - result = acpi_bus_scan(ACPI_ROOT_OBJECT, &ops, &acpi_root); + result = acpi_bus_scan(ACPI_ROOT_OBJECT, true, &acpi_root); if (!result) result = acpi_bus_scan_fixed(); ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH rev.2 5/6] ACPI: Replace struct acpi_bus_ops with enum type 2012-12-13 22:15 ` [PATCH rev.2 " Rafael J. Wysocki ` (3 preceding siblings ...) 2012-12-13 22:21 ` [PATCH rev.2 4/6] ACPI: Reduce the usage of struct acpi_bus_ops Rafael J. Wysocki @ 2012-12-13 22:22 ` Rafael J. Wysocki 2012-12-13 22:23 ` [PATCH rev.2 6/6] ACPI: Change the ordering of acpi_bus_check_add() Rafael J. Wysocki 2012-12-14 9:56 ` [PATCH rev.2 0/6] ACPI: Change the ACPI namespace scanning code ordering Yijing Wang 6 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-13 22:22 UTC (permalink / raw) To: ACPI Devel Maling List Cc: Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Notice that one member of struct acpi_bus_ops, acpi_op_add, is not used anywhere any more and the relationship between its remaining members, acpi_op_match and acpi_op_start, is such that it doesn't make sense to set the latter without setting the former at the same time. Therefore, replace struct acpi_bus_ops with new a enum type, enum acpi_bus_add_type, with three values, ACPI_BUS_ADD_BASIC, ACPI_BUS_ADD_MATCH, ACPI_BUS_ADD_START, corresponding to both acpi_op_match and acpi_op_start unset, acpi_op_match set and acpi_op_start unset, and both acpi_op_match and acpi_op_start set, respectively. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> --- drivers/acpi/scan.c | 35 ++++++++++++----------------------- include/acpi/acpi_bus.h | 15 ++++++++------- 2 files changed, 20 insertions(+), 30 deletions(-) Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -494,7 +494,7 @@ static int acpi_bus_match(struct device struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_driver *acpi_drv = to_acpi_driver(drv); - return acpi_dev->bus_ops.acpi_op_match + return acpi_dev->add_type >= ACPI_BUS_ADD_MATCH && !acpi_match_device_ids(acpi_dev, acpi_drv->ids); } @@ -580,7 +580,7 @@ static int acpi_device_probe(struct devi ret = acpi_bus_driver_init(acpi_dev, acpi_drv); if (!ret) { - if (acpi_dev->bus_ops.acpi_op_start) + if (acpi_dev->add_type == ACPI_BUS_ADD_START) acpi_start_single_object(acpi_dev); if (acpi_drv->ops.notify) { @@ -1433,7 +1433,7 @@ static void acpi_hot_add_bind(struct acp static int acpi_add_single_object(struct acpi_device **child, acpi_handle handle, int type, unsigned long long sta, - struct acpi_bus_ops *ops) + enum acpi_bus_add_type add_type) { int result; struct acpi_device *device; @@ -1449,7 +1449,7 @@ static int acpi_add_single_object(struct device->device_type = type; device->handle = handle; device->parent = acpi_bus_get_parent(handle); - device->bus_ops = *ops; /* workround for not call .start */ + device->add_type = add_type; STRUCT_TO_INT(device->status) = sta; acpi_device_get_busid(device); @@ -1502,7 +1502,7 @@ static int acpi_add_single_object(struct result = acpi_device_register(device); - if (device->bus_ops.acpi_op_match) + if (device->add_type >= ACPI_BUS_ADD_MATCH) acpi_hot_add_bind(device); end: @@ -1526,16 +1526,12 @@ end: static void acpi_bus_add_power_resource(acpi_handle handle) { - struct acpi_bus_ops ops = { - .acpi_op_start = 1, - .acpi_op_match = 1, - }; struct acpi_device *device = NULL; acpi_bus_get_device(handle, &device); if (!device) acpi_add_single_object(&device, handle, ACPI_BUS_TYPE_POWER, - ACPI_STA_DEFAULT, &ops); + ACPI_STA_DEFAULT, ACPI_BUS_ADD_START); } static int acpi_bus_type_and_status(acpi_handle handle, int *type, @@ -1604,16 +1600,13 @@ static acpi_status acpi_bus_check_add(ac acpi_bus_get_device(handle, &device); if (!device) { - struct acpi_bus_ops ops = { - .acpi_op_start = !!context, - .acpi_op_match = 0, - }; - - acpi_add_single_object(&device, handle, type, sta, &ops); + acpi_add_single_object(&device, handle, type, sta, + ACPI_BUS_ADD_BASIC); if (!device) return AE_CTRL_DEPTH; - device->bus_ops.acpi_op_match = 1; + device->add_type = context ? + ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH; } if (!*return_value) @@ -1795,10 +1788,6 @@ static int acpi_bus_scan_fixed(void) { int result = 0; struct acpi_device *device = NULL; - struct acpi_bus_ops ops = { - .acpi_op_start = 1, - .acpi_op_match = 1, - }; /* * Enumerate all fixed-feature devices. @@ -1807,7 +1796,7 @@ static int acpi_bus_scan_fixed(void) result = acpi_add_single_object(&device, NULL, ACPI_BUS_TYPE_POWER_BUTTON, ACPI_STA_DEFAULT, - &ops); + ACPI_BUS_ADD_START); device_init_wakeup(&device->dev, true); } @@ -1815,7 +1804,7 @@ static int acpi_bus_scan_fixed(void) result = acpi_add_single_object(&device, NULL, ACPI_BUS_TYPE_SLEEP_BUTTON, ACPI_STA_DEFAULT, - &ops); + ACPI_BUS_ADD_START); } return result; Index: linux/include/acpi/acpi_bus.h =================================================================== --- linux.orig/include/acpi/acpi_bus.h +++ linux/include/acpi/acpi_bus.h @@ -63,6 +63,13 @@ acpi_get_physical_device_location(acpi_h #define ACPI_BUS_FILE_ROOT "acpi" extern struct proc_dir_entry *acpi_root_dir; +enum acpi_bus_add_type { + ACPI_BUS_ADD_BASIC = 0, + ACPI_BUS_ADD_MATCH, + ACPI_BUS_ADD_START, + ACPI_BUS_ADD_TYPE_COUNT +}; + enum acpi_bus_removal_type { ACPI_BUS_REMOVAL_NORMAL = 0, ACPI_BUS_REMOVAL_EJECT, @@ -95,12 +102,6 @@ typedef int (*acpi_op_bind) (struct acpi typedef int (*acpi_op_unbind) (struct acpi_device * device); typedef void (*acpi_op_notify) (struct acpi_device * device, u32 event); -struct acpi_bus_ops { - u32 acpi_op_add:1; - u32 acpi_op_start:1; - u32 acpi_op_match:1; -}; - struct acpi_device_ops { acpi_op_add add; acpi_op_remove remove; @@ -284,7 +285,7 @@ struct acpi_device { struct acpi_driver *driver; void *driver_data; struct device dev; - struct acpi_bus_ops bus_ops; /* workaround for different code path for hotplug */ + enum acpi_bus_add_type add_type; /* how to handle adding */ enum acpi_bus_removal_type removal_type; /* indicate for different removal type */ u8 physical_node_count; struct list_head physical_node_list; ^ permalink raw reply [flat|nested] 88+ messages in thread
* [PATCH rev.2 6/6] ACPI: Change the ordering of acpi_bus_check_add() 2012-12-13 22:15 ` [PATCH rev.2 " Rafael J. Wysocki ` (4 preceding siblings ...) 2012-12-13 22:22 ` [PATCH rev.2 5/6] ACPI: Replace struct acpi_bus_ops with enum type Rafael J. Wysocki @ 2012-12-13 22:23 ` Rafael J. Wysocki 2012-12-14 9:56 ` [PATCH rev.2 0/6] ACPI: Change the ACPI namespace scanning code ordering Yijing Wang 6 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-13 22:23 UTC (permalink / raw) To: ACPI Devel Maling List Cc: Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> If acpi_bus_check_add() is called for a handle already having an existing struct acpi_device object attached, it is not necessary to check the type and status of the device correspondig to it, so change the ordering of acpi_bus_check_add() to avoid that. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> --- drivers/acpi/scan.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) Index: linux/drivers/acpi/scan.c =================================================================== --- linux.orig/drivers/acpi/scan.c +++ linux/drivers/acpi/scan.c @@ -1582,6 +1582,10 @@ static acpi_status acpi_bus_check_add(ac acpi_status status; int result; + acpi_bus_get_device(handle, &device); + if (device) + goto out; + result = acpi_bus_type_and_status(handle, &type, &sta); if (result) return AE_OK; @@ -1598,17 +1602,13 @@ static acpi_status acpi_bus_check_add(ac return AE_CTRL_DEPTH; } - acpi_bus_get_device(handle, &device); - if (!device) { - acpi_add_single_object(&device, handle, type, sta, - ACPI_BUS_ADD_BASIC); - if (!device) - return AE_CTRL_DEPTH; + acpi_add_single_object(&device, handle, type, sta, ACPI_BUS_ADD_BASIC); + if (!device) + return AE_CTRL_DEPTH; - device->add_type = context ? - ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH; - } + device->add_type = context ? ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH; + out: if (!*return_value) *return_value = device; ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH rev.2 0/6] ACPI: Change the ACPI namespace scanning code ordering 2012-12-13 22:15 ` [PATCH rev.2 " Rafael J. Wysocki ` (5 preceding siblings ...) 2012-12-13 22:23 ` [PATCH rev.2 6/6] ACPI: Change the ordering of acpi_bus_check_add() Rafael J. Wysocki @ 2012-12-14 9:56 ` Yijing Wang 2012-12-14 22:59 ` Rafael J. Wysocki 6 siblings, 1 reply; 88+ messages in thread From: Yijing Wang @ 2012-12-14 9:56 UTC (permalink / raw) To: Rafael J. Wysocki Cc: ACPI Devel Maling List, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu On 2012/12/14 6:15, Rafael J. Wysocki wrote: > Hi All, > > On Sunday, December 09, 2012 11:58:42 PM Rafael J. Wysocki wrote: >> Hi, >> >> The following patches change the ordering of the ACPI namespace scanning code >> so that all struct acpi_device objects in the given scope are registered before >> ACPI drivers are probed against them. They also do some simplifications and >> clarifications of the code made possible by this main change. >> >> This is done for three basic reasons. First, we need the boot ACPI namespace >> scanning code to be as similar as reasonably possible to the hot-plug ACPI >> namespace scanning code. Second, the ordering of PCI devices enumeration >> versus ACPI-backed platform devices registration needs to be such that the PCI >> devices in the given scope are all registered first. Finally, when we start to >> actually manage ACPI device resources as appropriate (e.g. resolve resource >> conflicts properly) we'll need all struct acpi_device nodes to be registered >> before any "companion" physical nodes or ACPI drivers are bound to them. >> >> The patches have been tested on Toshiba Portege R500 without breaking stuff >> (I used some additional debug code to verify that the ordering of device >> discovery had not been modified by them), but if you see any problems with >> them regarding hot-plug, please let me know. >> >> [1/6] - Separate adding ACPI device objects from probing ACPI drivers. >> [2/6] - Change the ordering of PCI root bridge driver registration. >> [3/6] - Make acpi_bus_add() and acpi_bus_start() visibly different. >> [4/6] - Reduce the usage of struct acpi_bus_ops >> [5/6] - Replace struct acpi_bus_ops with an enum type >> [6/6] - Change the ordering of acpi_bus_check_add() to avoid unnecessary checks. > > The second revision is necessary to address problems found by Yijing Wang > during testing and explained by Jiang Liu (thanks guys!). > > The problem is that acpi_walk_namespace() doesn't execute the pre_order_visit > callback for the starting handle, so the callback routine has the be executed > for it directly, if necessary. > > I also modified a couple of changelogs to better explain the motivation of the > patches. > > Boot sequence tested on Toshiba Portege R500, but testing on systems with > hotplug will be appreciated. Hi rafael, I tested this version patchset in my ia64 hotplug machine, and the result looks ok. Thanks! Yijing > > Thanks, > Rafael > > -- Thanks! Yijing ^ permalink raw reply [flat|nested] 88+ messages in thread
* Re: [PATCH rev.2 0/6] ACPI: Change the ACPI namespace scanning code ordering 2012-12-14 9:56 ` [PATCH rev.2 0/6] ACPI: Change the ACPI namespace scanning code ordering Yijing Wang @ 2012-12-14 22:59 ` Rafael J. Wysocki 0 siblings, 0 replies; 88+ messages in thread From: Rafael J. Wysocki @ 2012-12-14 22:59 UTC (permalink / raw) To: Yijing Wang Cc: ACPI Devel Maling List, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu On Friday, December 14, 2012 05:56:46 PM Yijing Wang wrote: > On 2012/12/14 6:15, Rafael J. Wysocki wrote: > > Hi All, > > > > On Sunday, December 09, 2012 11:58:42 PM Rafael J. Wysocki wrote: > >> Hi, > >> > >> The following patches change the ordering of the ACPI namespace scanning code > >> so that all struct acpi_device objects in the given scope are registered before > >> ACPI drivers are probed against them. They also do some simplifications and > >> clarifications of the code made possible by this main change. > >> > >> This is done for three basic reasons. First, we need the boot ACPI namespace > >> scanning code to be as similar as reasonably possible to the hot-plug ACPI > >> namespace scanning code. Second, the ordering of PCI devices enumeration > >> versus ACPI-backed platform devices registration needs to be such that the PCI > >> devices in the given scope are all registered first. Finally, when we start to > >> actually manage ACPI device resources as appropriate (e.g. resolve resource > >> conflicts properly) we'll need all struct acpi_device nodes to be registered > >> before any "companion" physical nodes or ACPI drivers are bound to them. > >> > >> The patches have been tested on Toshiba Portege R500 without breaking stuff > >> (I used some additional debug code to verify that the ordering of device > >> discovery had not been modified by them), but if you see any problems with > >> them regarding hot-plug, please let me know. > >> > >> [1/6] - Separate adding ACPI device objects from probing ACPI drivers. > >> [2/6] - Change the ordering of PCI root bridge driver registration. > >> [3/6] - Make acpi_bus_add() and acpi_bus_start() visibly different. > >> [4/6] - Reduce the usage of struct acpi_bus_ops > >> [5/6] - Replace struct acpi_bus_ops with an enum type > >> [6/6] - Change the ordering of acpi_bus_check_add() to avoid unnecessary checks. > > > > The second revision is necessary to address problems found by Yijing Wang > > during testing and explained by Jiang Liu (thanks guys!). > > > > The problem is that acpi_walk_namespace() doesn't execute the pre_order_visit > > callback for the starting handle, so the callback routine has the be executed > > for it directly, if necessary. > > > > I also modified a couple of changelogs to better explain the motivation of the > > patches. > > > > Boot sequence tested on Toshiba Portege R500, but testing on systems with > > hotplug will be appreciated. > > Hi rafael, > I tested this version patchset in my ia64 hotplug machine, and the result looks ok. Great, thanks a lot for testing! Rafael -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. ^ permalink raw reply [flat|nested] 88+ messages in thread
end of thread, other threads:[~2013-01-11 20:59 UTC | newest] Thread overview: 88+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2012-12-09 22:58 [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Rafael J. Wysocki 2012-12-09 23:00 ` [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki 2012-12-12 15:50 ` Jiang Liu 2012-12-12 22:34 ` Rafael J. Wysocki 2012-12-12 16:38 ` Jiang Liu 2012-12-12 22:32 ` Rafael J. Wysocki 2012-12-12 23:43 ` [update][PATCH " Rafael J. Wysocki 2012-12-13 13:05 ` [PATCH " Jiang Liu 2012-12-13 19:40 ` Rafael J. Wysocki 2012-12-13 1:00 ` Bjorn Helgaas 2012-12-13 11:41 ` Rafael J. Wysocki 2012-12-09 23:00 ` [PATCH 2/6] ACPI: Change the ordering of PCI root bridge driver registrarion Rafael J. Wysocki 2012-12-13 1:00 ` Bjorn Helgaas 2012-12-13 12:19 ` Rafael J. Wysocki 2012-12-09 23:01 ` [PATCH 3/6] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different Rafael J. Wysocki 2012-12-13 0:11 ` [Update][PATCH " Rafael J. Wysocki 2012-12-09 23:02 ` [PATCH 4/6] ACPI: Reduce the usage of struct acpi_bus_ops Rafael J. Wysocki 2012-12-09 23:03 ` [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type Rafael J. Wysocki 2012-12-10 5:34 ` Yinghai Lu 2012-12-10 14:46 ` Rafael J. Wysocki 2012-12-10 17:07 ` Yinghai Lu 2012-12-10 22:47 ` Rafael J. Wysocki 2012-12-10 23:09 ` Rafael J. Wysocki 2012-12-10 23:14 ` Yinghai Lu 2012-12-11 1:02 ` Rafael J. Wysocki 2012-12-11 1:28 ` Rafael J. Wysocki 2012-12-11 2:26 ` Yinghai Lu 2012-12-11 12:45 ` Rafael J. Wysocki 2012-12-11 15:09 ` Jiang Liu 2012-12-11 18:30 ` Rafael J. Wysocki 2012-12-12 14:34 ` Yijing Wang 2012-12-12 15:05 ` Jiang Liu 2012-12-12 22:39 ` Rafael J. Wysocki 2012-12-10 23:22 ` Yinghai Lu 2012-12-11 0:48 ` Rafael J. Wysocki 2012-12-09 23:04 ` [PATCH 6/6] ACPI: Change the ordering of acpi_bus_check_add() Rafael J. Wysocki 2012-12-13 1:00 ` Bjorn Helgaas 2012-12-13 12:20 ` Rafael J. Wysocki 2012-12-13 11:45 ` [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Yijing Wang 2012-12-13 22:15 ` [PATCH rev.2 " Rafael J. Wysocki 2012-12-13 22:17 ` [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki 2012-12-18 0:08 ` Toshi Kani 2012-12-18 1:48 ` Rafael J. Wysocki 2012-12-18 16:10 ` Toshi Kani 2012-12-18 18:59 ` Yinghai Lu 2012-12-18 20:48 ` Toshi Kani 2012-12-18 21:11 ` Yinghai Lu 2012-12-18 22:05 ` Rafael J. Wysocki 2012-12-19 1:57 ` Yinghai Lu 2012-12-18 21:57 ` Rafael J. Wysocki 2012-12-18 22:15 ` Toshi Kani 2012-12-18 23:00 ` Rafael J. Wysocki 2012-12-18 23:19 ` Bjorn Helgaas 2012-12-19 11:13 ` Rafael J. Wysocki 2012-12-20 1:45 ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki 2012-12-20 1:47 ` [PATCH 1/16] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki 2013-01-11 20:00 ` Mika Westerberg 2013-01-11 20:31 ` Rafael J. Wysocki 2013-01-11 20:37 ` Mika Westerberg 2013-01-11 20:58 ` Rafael J. Wysocki 2013-01-11 20:59 ` Mika Westerberg 2012-12-20 1:48 ` [PATCH 2/16] ACPI: Change the ordering of PCI root bridge driver registrarion Rafael J. Wysocki 2012-12-20 1:49 ` [PATCH 3/16] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different Rafael J. Wysocki 2012-12-20 1:50 ` [PATCH 4/16] ACPI: Reduce the usage of struct acpi_bus_ops Rafael J. Wysocki 2012-12-20 1:50 ` [PATCH 5/16] ACPI: Replace struct acpi_bus_ops with enum type Rafael J. Wysocki 2012-12-20 1:51 ` [PATCH 6/16] ACPI: Change the ordering of acpi_bus_check_add() Rafael J. Wysocki 2012-12-20 1:52 ` [PATCH 7/16] ACPI / PCI: Fold acpi_pci_root_start() into acpi_pci_root_add() Rafael J. Wysocki 2012-12-20 1:53 ` [PATCH 8/16] ACPI: Remove acpi_start_single_object() and acpi_bus_start() Rafael J. Wysocki 2012-12-20 1:54 ` [PATCH 9/16] ACPI: Remove the arguments of acpi_bus_add() that are not used Rafael J. Wysocki 2012-12-20 1:54 ` [PATCH 10/16] ACPI: Drop the second argument of acpi_bus_scan() Rafael J. Wysocki 2012-12-20 1:55 ` [PATCH 11/16] ACPI: Replace ACPI device add_type field with a match_driver flag Rafael J. Wysocki 2012-12-20 1:56 ` [PATCH 12/16] ACPI: Make acpi_bus_scan() and acpi_bus_add() take only one argument Rafael J. Wysocki 2012-12-20 1:57 ` [PATCH 13/16] ACPI: Add .setup() and .cleanup() callbacks to struct acpi_bus_type Rafael J. Wysocki 2012-12-20 1:58 ` [PATCH 14/16] ACPI / PCI: Rework the setup and cleanup of device wakeup Rafael J. Wysocki 2012-12-20 1:59 ` [PATCH 15/16] ACPI / PCI: Move the _PRT setup and cleanup code to pci-acpi.c Rafael J. Wysocki 2012-12-20 2:06 ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Yinghai Lu 2012-12-21 0:09 ` Rafael J. Wysocki 2012-12-21 3:59 ` Yinghai Lu 2012-12-21 22:23 ` Rafael J. Wysocki 2012-12-20 21:07 ` Toshi Kani 2012-12-20 23:20 ` Rafael J. Wysocki 2012-12-13 22:18 ` [PATCH rev.2 2/6] ACPI: Change the ordering of PCI root bridge driver registrarion Rafael J. Wysocki 2012-12-13 22:21 ` [PATCH rev.2 3/6] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different Rafael J. Wysocki 2012-12-13 22:21 ` [PATCH rev.2 4/6] ACPI: Reduce the usage of struct acpi_bus_ops Rafael J. Wysocki 2012-12-13 22:22 ` [PATCH rev.2 5/6] ACPI: Replace struct acpi_bus_ops with enum type Rafael J. Wysocki 2012-12-13 22:23 ` [PATCH rev.2 6/6] ACPI: Change the ordering of acpi_bus_check_add() Rafael J. Wysocki 2012-12-14 9:56 ` [PATCH rev.2 0/6] ACPI: Change the ACPI namespace scanning code ordering Yijing Wang 2012-12-14 22:59 ` Rafael J. Wysocki
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).