Re: [PATCH] iio: light: apds9306: fix PM reference leak in apds9306_read_data()
Jonathan Cameron <[email protected]>
| Newsgroups | org.kernel.vger.linux-iio,org.kernel.vger.linux-kernel,org.kernel.vger.stable |
|---|---|
| Message-ID | <20260727033151.0ea0cb9d@jic23-huawei> |
On Sat, 25 Jul 2026 05:10:48 +0000 Moksh Panicker <[email protected]> wrote: > apds9306_read_data() calls pm_runtime_resume_and_get() but several > error paths return directly without calling pm_runtime_put_autosuspend(), > leaking the runtime PM reference and preventing the device from > autosuspending. > > Add a goto label before pm_runtime_put_autosuspend() and use it on > all error paths after a successful pm_runtime_resume_and_get(). > > Fixes: 620d1e6c7a3f ("iio: light: Add support for APDS9306 Light Sensor") > Cc: [email protected] > Signed-off-by: Moksh Panicker <[email protected]> Good find. Please look at PM_RUNTIME_ACQUIRE_AUTOSUSPEND() and matching ERR macro. Using that should simplify this fix quite a bit and generally give us nicer code. > --- > drivers/iio/light/apds9306.c | 19 +++++++++++-------- > 1 file changed, 11 insertions(+), 8 deletions(-) > > diff --git a/drivers/iio/light/apds9306.c b/drivers/iio/light/apds9306.c > index 5ca4c87524fe..014db7a1787e 100644 > --- a/drivers/iio/light/apds9306.c > +++ b/drivers/iio/light/apds9306.c > @@ -475,19 +475,21 @@ static int apds9306_read_data(struct apds9306_data *data, int *val, int reg) > > ret = regmap_field_read(rf->intg_time, &intg_time_idx); > if (ret) > - return ret; > + goto out_pm_put; > > ret = regmap_field_read(rf->repeat_rate, &repeat_rate_idx); > if (ret) > - return ret; > + goto out_pm_put; > > ret = regmap_field_read(rf->int_src, &int_src); > if (ret) > - return ret; > + goto out_pm_put; > > intg_time = iio_gts_find_int_time_by_sel(&data->gts, intg_time_idx); > - if (intg_time < 0) > - return intg_time; > + if (intg_time < 0) { > + ret = intg_time; > + goto out_pm_put; > + } > > /* Whichever is greater - integration time period or sampling period. */ > delay = max(intg_time, apds9306_repeat_rate_period[repeat_rate_idx]); > @@ -510,7 +512,7 @@ static int apds9306_read_data(struct apds9306_data *data, int *val, int reg) > APDS9306_ALS_INT_STAT_MASK)), > APDS9306_ALS_READ_DATA_DELAY_US, delay * 2); > if (ret) > - return ret; > + goto out_pm_put; > > /* If we reach here before the interrupt handler we push an event */ > if ((status & APDS9306_ALS_INT_STAT_MASK)) { > @@ -530,14 +532,15 @@ static int apds9306_read_data(struct apds9306_data *data, int *val, int reg) > ret = regmap_bulk_read(data->regmap, reg, buff, sizeof(buff)); > if (ret) { > dev_err_ratelimited(dev, "read data failed\n"); > - return ret; > + goto out_pm_put; > } > > *val = get_unaligned_le24(&buff); > > +out_pm_put: > pm_runtime_put_autosuspend(data->dev); > > - return 0; > + return ret; > } > > static int apds9306_intg_time_get(struct apds9306_data *data, int *val2)