Skip to content

Commit 5f4ce26

Browse files
committed
ACPI: scan: Fix race related to dropping dependencies
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 <[email protected]> Reviewed-by: Hans de Goede <[email protected]>
1 parent c6a493a commit 5f4ce26

File tree

1 file changed

+32
-13
lines changed

1 file changed

+32
-13
lines changed

drivers/acpi/scan.c

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -650,16 +650,12 @@ static int acpi_tie_acpi_dev(struct acpi_device *adev)
650650
return 0;
651651
}
652652

653-
int acpi_device_add(struct acpi_device *device,
654-
void (*release)(struct device *))
653+
static int __acpi_device_add(struct acpi_device *device,
654+
void (*release)(struct device *))
655655
{
656656
struct acpi_device_bus_id *acpi_device_bus_id;
657657
int result;
658658

659-
result = acpi_tie_acpi_dev(device);
660-
if (result)
661-
return result;
662-
663659
/*
664660
* Linkage
665661
* -------
@@ -748,6 +744,17 @@ int acpi_device_add(struct acpi_device *device,
748744
return result;
749745
}
750746

747+
int acpi_device_add(struct acpi_device *adev, void (*release)(struct device *))
748+
{
749+
int ret;
750+
751+
ret = acpi_tie_acpi_dev(adev);
752+
if (ret)
753+
return ret;
754+
755+
return __acpi_device_add(adev, release);
756+
}
757+
751758
/* --------------------------------------------------------------------------
752759
Device Enumeration
753760
-------------------------------------------------------------------------- */
@@ -1675,14 +1682,10 @@ static void acpi_scan_dep_init(struct acpi_device *adev)
16751682
{
16761683
struct acpi_dep_data *dep;
16771684

1678-
mutex_lock(&acpi_dep_list_lock);
1679-
16801685
list_for_each_entry(dep, &acpi_dep_list, node) {
16811686
if (dep->consumer == adev->handle)
16821687
adev->dep_unmet++;
16831688
}
1684-
1685-
mutex_unlock(&acpi_dep_list_lock);
16861689
}
16871690

16881691
void acpi_device_add_finalize(struct acpi_device *device)
@@ -1701,6 +1704,7 @@ static int acpi_add_single_object(struct acpi_device **child,
17011704
acpi_handle handle, int type, bool dep_init)
17021705
{
17031706
struct acpi_device *device;
1707+
bool release_dep_lock = false;
17041708
int result;
17051709

17061710
device = kzalloc(sizeof(struct acpi_device), GFP_KERNEL);
@@ -1714,16 +1718,31 @@ static int acpi_add_single_object(struct acpi_device **child,
17141718
* this must be done before the get power-/wakeup_dev-flags calls.
17151719
*/
17161720
if (type == ACPI_BUS_TYPE_DEVICE || type == ACPI_BUS_TYPE_PROCESSOR) {
1717-
if (dep_init)
1721+
if (dep_init) {
1722+
mutex_lock(&acpi_dep_list_lock);
1723+
/*
1724+
* Hold the lock until the acpi_tie_acpi_dev() call
1725+
* below to prevent concurrent acpi_scan_clear_dep()
1726+
* from deleting a dependency list entry without
1727+
* updating dep_unmet for the device.
1728+
*/
1729+
release_dep_lock = true;
17181730
acpi_scan_dep_init(device);
1719-
1731+
}
17201732
acpi_scan_init_status(device);
17211733
}
17221734

17231735
acpi_bus_get_power_flags(device);
17241736
acpi_bus_get_wakeup_device_flags(device);
17251737

1726-
result = acpi_device_add(device, acpi_device_release);
1738+
result = acpi_tie_acpi_dev(device);
1739+
1740+
if (release_dep_lock)
1741+
mutex_unlock(&acpi_dep_list_lock);
1742+
1743+
if (!result)
1744+
result = __acpi_device_add(device, acpi_device_release);
1745+
17271746
if (result) {
17281747
acpi_device_release(&device->dev);
17291748
return result;

0 commit comments

Comments
 (0)