On Mon, Sep 19, 2022 at 3:54 AM Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx> wrote: > > On Wed, Sep 14, 2022 at 05:57:55PM -0600, Raul E Rangel wrote: > > Device tree already has a mechanism to pass the wake_irq. It does this > > by looking for the wakeup-source property and setting the > > I2C_CLIENT_WAKE flag. This CL adds the ACPI equivalent. It uses the > > ACPI interrupt wake flag to determine if the interrupt can be used to > > wake the system. Previously the i2c drivers had to make assumptions and > > blindly enable the wake IRQ. This can cause spurious wake events. e.g., > > If there is a device with an Active Low interrupt and the device gets > > powered off while suspending, the interrupt line will go low since it's > > no longer powered and wakes the system. For this reason we should > > respect the board designers wishes and honor the wake bit defined on the > > interrupt. > > Okay, let's go with this variant, but I'm afraid that in time we may come up > to the proposed (generic structure for ACPI IRQ parameters which can be used > in a few places). > > Reviewed-by: Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx> > > > Signed-off-by: Raul E Rangel <rrangel@xxxxxxxxxxxx> > > --- > > > > Changes in v3: > > - Convert wake_capable to bool > > - Only update wake_capable pointer once > > - Move wake_capable local into local block > > > > Changes in v2: > > - Look at wake_cabple bit for IRQ/Interrupt resources > > > > drivers/i2c/i2c-core-acpi.c | 33 ++++++++++++++++++++++++--------- > > drivers/i2c/i2c-core-base.c | 8 +++++++- > > drivers/i2c/i2c-core.h | 4 ++-- > > 3 files changed, 33 insertions(+), 12 deletions(-) > > > > diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c > > index c762a879c4cc6b..b3d68a9659ff4f 100644 > > --- a/drivers/i2c/i2c-core-acpi.c > > +++ b/drivers/i2c/i2c-core-acpi.c > > @@ -137,6 +137,11 @@ static const struct acpi_device_id i2c_acpi_ignored_device_ids[] = { > > {} > > }; > > > > +struct i2c_acpi_irq_context { > > + int irq; > > + bool wake_capable; > > +}; > > + > > static int i2c_acpi_do_lookup(struct acpi_device *adev, > > struct i2c_acpi_lookup *lookup) > > { > > @@ -170,11 +175,14 @@ static int i2c_acpi_do_lookup(struct acpi_device *adev, > > > > static int i2c_acpi_add_resource(struct acpi_resource *ares, void *data) > > { > > - int *irq = data; > > + struct i2c_acpi_irq_context *irq_ctx = data; > > struct resource r; > > > > - if (*irq <= 0 && acpi_dev_resource_interrupt(ares, 0, &r)) > > - *irq = i2c_dev_irq_from_resources(&r, 1); > > + if (irq_ctx->irq <= 0 && acpi_dev_resource_interrupt(ares, 0, &r)) { > > + irq_ctx->irq = i2c_dev_irq_from_resources(&r, 1); > > + irq_ctx->wake_capable = > > + !!(r.flags & IORESOURCE_IRQ_WAKECAPABLE); > > + } > > Maybe > > if (irq_ctx->irq > 0) > return 1; > > if (!acpi_dev_resource_interrupt(ares, 0, &r)) > return 1; > > irq_ctx->irq = i2c_dev_irq_from_resources(&r, 1); > irq_ctx->wake_capable = !!(r.flags & IORESOURCE_IRQ_WAKECAPABLE); > > ? > > > return 1; /* No need to add resource to the list */ > > } > Done > Also not sure why the callback is not called i2c_acpi_add_irq_resource(). > But it probably can be done in a separate change. > I had the same thought. I went ahead and added it into this change since I already refactored the logic like you suggested above. > > @@ -182,31 +190,38 @@ static int i2c_acpi_add_resource(struct acpi_resource *ares, void *data) > > /** > > * i2c_acpi_get_irq - get device IRQ number from ACPI > > * @client: Pointer to the I2C client device > > + * @wake_capable: Set to true if the IRQ is wake capable > > * > > * Find the IRQ number used by a specific client device. > > * > > * Return: The IRQ number or an error code. > > */ > > -int i2c_acpi_get_irq(struct i2c_client *client) > > +int i2c_acpi_get_irq(struct i2c_client *client, bool *wake_capable) > > { > > struct acpi_device *adev = ACPI_COMPANION(&client->dev); > > struct list_head resource_list; > > - int irq = -ENOENT; > > + struct i2c_acpi_irq_context irq_ctx = { > > + .irq = -ENOENT, > > + }; > > int ret; > > > > INIT_LIST_HEAD(&resource_list); > > > > ret = acpi_dev_get_resources(adev, &resource_list, > > - i2c_acpi_add_resource, &irq); > > + i2c_acpi_add_resource, &irq_ctx); > > if (ret < 0) > > return ret; > > > > acpi_dev_free_resource_list(&resource_list); > > > > - if (irq == -ENOENT) > > - irq = acpi_dev_gpio_irq_get(adev, 0); > > + if (irq_ctx.irq == -ENOENT) > > + irq_ctx.irq = acpi_dev_gpio_irq_wake_get(adev, 0, > > + &irq_ctx.wake_capable); > > + > > + if (wake_capable) > > + *wake_capable = irq_ctx.wake_capable; > > > > - return irq; > > + return irq_ctx.irq; > > } > > > > static int i2c_acpi_get_info(struct acpi_device *adev, > > diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c > > index 91007558bcb260..c4debd46c6340f 100644 > > --- a/drivers/i2c/i2c-core-base.c > > +++ b/drivers/i2c/i2c-core-base.c > > @@ -487,8 +487,14 @@ static int i2c_device_probe(struct device *dev) > > if (irq == -EINVAL || irq == -ENODATA) > > irq = of_irq_get(dev->of_node, 0); > > } else if (ACPI_COMPANION(dev)) { > > - irq = i2c_acpi_get_irq(client); > > + bool wake_capable; > > + > > + irq = i2c_acpi_get_irq(client, &wake_capable); > > > + > > Unneeded blank line. > Done > > + if (irq > 0 && wake_capable) > > + client->flags |= I2C_CLIENT_WAKE; > > } > > > + > > Ditto. (This even looks like a stray change) > Done > > if (irq == -EPROBE_DEFER) { > > status = irq; > > goto put_sync_adapter; > > diff --git a/drivers/i2c/i2c-core.h b/drivers/i2c/i2c-core.h > > index 87e2c914f1c57b..1247e6e6e97517 100644 > > --- a/drivers/i2c/i2c-core.h > > +++ b/drivers/i2c/i2c-core.h > > @@ -61,11 +61,11 @@ static inline int __i2c_check_suspended(struct i2c_adapter *adap) > > #ifdef CONFIG_ACPI > > void i2c_acpi_register_devices(struct i2c_adapter *adap); > > > > -int i2c_acpi_get_irq(struct i2c_client *client); > > +int i2c_acpi_get_irq(struct i2c_client *client, bool *wake_capable); > > #else /* CONFIG_ACPI */ > > static inline void i2c_acpi_register_devices(struct i2c_adapter *adap) { } > > > > -static inline int i2c_acpi_get_irq(struct i2c_client *client) > > +static inline int i2c_acpi_get_irq(struct i2c_client *client, bool *wake_capable) > > { > > return 0; > > } > > -- > > 2.37.3.968.ga6b4b080e4-goog > > > > -- > With Best Regards, > Andy Shevchenko > > I'll send out a V4 series in a few minutes with all the latest changes. Thanks!