Re: [PATCH v2 1/1] i2c: Restore initial power state when we are done.

From: Ricardo Ribalda
Date: Thu Nov 10 2022 - 05:25:58 EST


Hi Hidenori

On Thu, 10 Nov 2022 at 10:25, Hidenori Kobayashi <hidenorik@xxxxxxxxxxxx> wrote:
>
> Hi Ricardo,
>
> On Wed, Nov 09, 2022 at 04:17:06PM +0100, Ricardo Ribalda wrote:
> > A driver that supports I2C_DRV_ACPI_WAIVE_D0_PROBE is not expected to
> > power off a device that it has not powered on previously.
> >
> > For devices operating in "full_power" mode, the first call to
> > `i2c_acpi_waive_d0_probe` will return 0, which means that the device
> > will be turned on with `dev_pm_domain_attach`.
> >
> > If probe fails or the device is removed the second call to
> > `i2c_acpi_waive_d0_probe` will return 1, which means that the device
> > will not be turned off. This is, it will be left in a different power
> > state. Lets fix it.
> >
> > Fixes: b18c1ad685d9 ("i2c: Allow an ACPI driver to manage the device's power state during probe")
> > Signed-off-by: Ricardo Ribalda <ribalda@xxxxxxxxxxxx>
> >
> > diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
> > index b4edf10e8fd0..96623e0647bd 100644
> > --- a/drivers/i2c/i2c-core-base.c
> > +++ b/drivers/i2c/i2c-core-base.c
> > @@ -545,8 +545,9 @@ static int i2c_device_probe(struct device *dev)
> > if (status < 0)
> > goto err_clear_wakeup_irq;
> >
> > + client->turn_off_on_remove = !i2c_acpi_waive_d0_probe(dev);
> > status = dev_pm_domain_attach(&client->dev,
> > - !i2c_acpi_waive_d0_probe(dev));
> > + client->turn_off_on_remove);
> > if (status)
> > goto err_clear_wakeup_irq;
> >
> > @@ -585,7 +586,7 @@ static int i2c_device_probe(struct device *dev)
> > err_release_driver_resources:
> > devres_release_group(&client->dev, client->devres_group_id);
> > err_detach_pm_domain:
> > - dev_pm_domain_detach(&client->dev, !i2c_acpi_waive_d0_probe(dev));
> > + dev_pm_domain_detach(&client->dev, client->turn_off_on_remove);
> > err_clear_wakeup_irq:
> > dev_pm_clear_wake_irq(&client->dev);
> > device_init_wakeup(&client->dev, false);
> > @@ -610,7 +611,7 @@ static void i2c_device_remove(struct device *dev)
> >
> > devres_release_group(&client->dev, client->devres_group_id);
> >
> > - dev_pm_domain_detach(&client->dev, !i2c_acpi_waive_d0_probe(dev));
> > + dev_pm_domain_detach(&client->dev, client->turn_off_on_remove);
> >
> > dev_pm_clear_wake_irq(&client->dev);
> > device_init_wakeup(&client->dev, false);
> > diff --git a/include/linux/i2c.h b/include/linux/i2c.h
> > index f7c49bbdb8a1..6b2dacb0bae1 100644
> > --- a/include/linux/i2c.h
> > +++ b/include/linux/i2c.h
> > @@ -326,6 +326,8 @@ struct i2c_driver {
> > * calls it to pass on slave events to the slave driver.
> > * @devres_group_id: id of the devres group that will be created for resources
> > * acquired when probing this device.
> > + * @turn_off_on_remove: Record if we have turned on the device before probing
> > + * so we can restore the initial state after remove/probe error.
> > *
> > * An i2c_client identifies a single device (i.e. chip) connected to an
> > * i2c bus. The behaviour exposed to Linux is defined by the driver
> > @@ -355,6 +357,7 @@ struct i2c_client {
> > i2c_slave_cb_t slave_cb; /* callback for slave mode */
> > #endif
> > void *devres_group_id; /* ID of probe devres group */
> > + bool turn_off_on_remove; /* power state when done */
>
> Can we have a different name that also makes sense for attach()?
> To me, it's kind of hard to see immediately what the second argument to
> attach() meant.

I was trying to be super-clever and not adding a new variable. :P

Let me send a new version.

Thanks for your review!

>
> Since this is used for both power_on and power_off, I think something
> more neutral would be easier to read? For example: power_flag?
>
> Or I guess we could name it like full_power and provide a wrapper for
> the detach() cases?
>
> > };
> > #define to_i2c_client(d) container_of(d, struct i2c_client, dev)
> >
> >
> > --
> > b4 0.11.0-dev-d93f8
> >



--
Ricardo Ribalda