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)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.