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

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

 



Hello,

On Fri, Mar 24, 2023 at 10:09:55AM +0100, Uwe Kleine-König wrote:
> 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 &&
> 

there is a hunk that I failed to add to the commit:

diff --git a/drivers/acpi/device_sysfs.c b/drivers/acpi/device_sysfs.c
index 0fbfbaa8d8e3..2ee756d68052 100644
--- a/drivers/acpi/device_sysfs.c
+++ b/drivers/acpi/device_sysfs.c
@@ -376,7 +376,7 @@ eject_store(struct device *d, struct device_attribute *attr,
 		return -EINVAL;
 
 	if ((!acpi_device->handler || !acpi_device->handler->hotplug.enabled)
-	    && !d->driver)
+	    && !device_is_bound(d))
 		return -ENODEV;
 
 	status = acpi_get_type(acpi_device->handle, &not_used);

Rafael sait in the thread where Pierre reported the problem that he has
a different fix in mind. So I guess it's not worth to send a v2.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | https://www.pengutronix.de/ |

Attachment: signature.asc
Description: PGP signature


[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