[PATCH] ACPI: bus: Only call notify for a completely bound ACPI device

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Commit d6fb6ee1820c ("ACPI: bus: Drop driver member of struct
acpi_device") removed acpi_device::driver in favour of struct
acpi_device::dev.driver.

However there is a problem: While the two pointers are equivalent after
the device is completely probed, there is a small time frame where
acpi_device::dev->driver is already set but acpi_device::driver wasn't.

The function acpi_bus_notify() used to have a check for
acpi_device::driver that was changed to a check for adev->dev.driver in
Commit d6fb6ee1820c.

Pierre Asselin reports that starting with above change his laptop
crashed during boot when on AC power. That's because acpi_bus_notify()
is called in that small time frame (triggered by acpi_ac_add()) which
results in a call to acpi_ac_notify while this function isn't ready yet.

So in acpi_bus_notify() check for the device being bound (which becomes
true only after the acpi probe call succeeds) instead of for
acpi_device::dev.driver.

Note that usually you have to hold the device lock to call
device_is_bound(). I don't think this is the case here, so there likely
is a race condition. The problem might be that the driver unbinds after
the check but before adev->dev.driver is evaluated. However this race
already existed before commit d6fb6ee1820c, so the change here is a net
improvement even though it might not result in a completely correct
handling.

A similar check in the acpi sysfs code is also converted. This is less
critical as it happens in code that is run when a sysfs file is
accessed. That shouldn't happen for a device that isn't bound.

Fixes: d6fb6ee1820c ("ACPI: bus: Drop driver member of struct acpi_device")
Reported-by: Pierre Asselin <pa@xxxxxxxxx>
Link: https://lore.kernel.org/linux-acpi/9f6cba7a8a57e5a687c934e8e406e28c.squirrel@xxxxxxxxxxxxxx
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@xxxxxxxxxxxxxx>
---
 drivers/acpi/bus.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 9531dd0fef50..a5a8f82981ce 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -518,7 +518,7 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
 	if (!adev)
 		goto err;
 
-	if (adev->dev.driver) {
+	if (device_is_bound(&adev->dev)) {
 		struct acpi_driver *driver = to_acpi_driver(adev->dev.driver);
 
 		if (driver && driver->ops.notify &&

base-commit: fe15c26ee26efa11741a7b632e9f23b01aca4cc6
-- 
2.39.2




[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]
  Powered by Linux