On Wed, Jun 16, 2021 at 4:55 PM Hans de Goede <hdegoede@xxxxxxxxxx> wrote: > > Hi, > > On 6/16/21 4:25 PM, Rafael J. Wysocki wrote: > > From: Rafael J. Wysocki <rafael.j.wysocki@xxxxxxxxx> > > > > If acpi_add_single_object() runs concurrently with respect to > > acpi_scan_clear_dep() which deletes a dependencies list entry where > > the device being added is the consumer, the device's dep_unmet > > counter may not be updated to reflect that change. > > > > Namely, if the dependencies list entry is deleted right after > > calling acpi_scan_dep_init() and before calling acpi_device_add(), > > acpi_scan_clear_dep() will not find the device object corresponding > > to the consumer device ACPI handle and it will not update its > > dep_unmet counter to reflect the deletion of the list entry. > > Consequently, the dep_unmet counter of the device will never > > become zero going forward which may prevent it from being > > completely enumerated. > > > > To address this problem, modify acpi_add_single_object() to run > > acpi_tie_acpi_dev(), to attach the ACPI device object created by it > > to the corresponding ACPI namespace node, under acpi_dep_list_lock > > along with acpi_scan_dep_init() whenever the latter is called. > > > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@xxxxxxxxx> > > --- > > drivers/acpi/scan.c | 46 +++++++++++++++++++++++++++++++++------------- > > 1 file changed, 33 insertions(+), 13 deletions(-) > > > > Index: linux-pm/drivers/acpi/scan.c > > =================================================================== > > --- linux-pm.orig/drivers/acpi/scan.c > > +++ linux-pm/drivers/acpi/scan.c > > @@ -657,16 +657,12 @@ static int acpi_tie_acpi_dev(struct acpi > > return 0; > > } > > > > -int acpi_device_add(struct acpi_device *device, > > - void (*release)(struct device *)) > > +int __acpi_device_add(struct acpi_device *device, > > + void (*release)(struct device *)) > > { > > struct acpi_device_bus_id *acpi_device_bus_id; > > int result; > > > > - result = acpi_tie_acpi_dev(device); > > - if (result) > > - return result; > > - > > /* > > * Linkage > > * ------- > > @@ -755,6 +751,17 @@ err_unlock: > > return result; > > } > > > > +int acpi_device_add(struct acpi_device *adev, void (*release)(struct device *)) > > +{ > > + int ret; > > + > > + ret = acpi_tie_acpi_dev(adev); > > + if (ret) > > + return ret; > > + > > + return __acpi_device_add(adev, release); > > +} > > + > > /* -------------------------------------------------------------------------- > > Device Enumeration > > -------------------------------------------------------------------------- */ > > @@ -1681,14 +1688,10 @@ static void acpi_scan_dep_init(struct ac > > { > > struct acpi_dep_data *dep; > > > > - mutex_lock(&acpi_dep_list_lock); > > - > > list_for_each_entry(dep, &acpi_dep_list, node) { > > if (dep->consumer == adev->handle) > > adev->dep_unmet++; > > } > > - > > - mutex_unlock(&acpi_dep_list_lock); > > } > > > > void acpi_device_add_finalize(struct acpi_device *device) > > @@ -1707,6 +1710,7 @@ static int acpi_add_single_object(struct > > acpi_handle handle, int type, bool dep_init) > > { > > struct acpi_device *device; > > + bool release_dep_lock = false; > > int result; > > > > device = kzalloc(sizeof(struct acpi_device), GFP_KERNEL); > > @@ -1720,16 +1724,32 @@ static int acpi_add_single_object(struct > > * this must be done before the get power-/wakeup_dev-flags calls. > > */ > > if (type == ACPI_BUS_TYPE_DEVICE || type == ACPI_BUS_TYPE_PROCESSOR) { > > - if (dep_init) > > + if (dep_init) { > > + mutex_lock(&acpi_dep_list_lock); > > + /* > > + * Hold the lock until the acpi_tie_acpi_dev() call > > + * below to prevent concurrent acpi_scan_clear_dep() > > + * from deleting a dependency list entry without > > + * updating dep_unmet for the device. > > + */ > > + release_dep_lock = true; > > acpi_scan_dep_init(device); > > - > > + } > > acpi_scan_init_status(device); > > } > > > > acpi_bus_get_power_flags(device); > > acpi_bus_get_wakeup_device_flags(device); > > > > - result = acpi_device_add(device, acpi_device_release); > > + result = acpi_tie_acpi_dev(device); > > + > > + if (release_dep_lock) > > + mutex_unlock(&acpi_dep_list_lock); > > + > > + if (result) > > AFAICT you are missing a "acpi_device_release(&device->dev);" > call in the error-exit path here, causing a mem-leak. Indeed. I'll send a v2 of this patch alone to fix this issue. > Otherwise this looks good, with the above fixed this is: > > Reviewed-by: Hans de Goede <hdegoede@xxxxxxxxxx> Thanks!