Hi Dan On Tue, 13 Aug 2024 at 14:54, Dan Carpenter <dan.carpenter@xxxxxxxxxx> wrote: > > On Tue, Aug 13, 2024 at 12:13:48PM +0000, Ricardo Ribalda wrote: > > Factor out all the power off logic, except the clk_disable_unprepare(), > > to a new function __ar0521_power_off(). > > > > This allows ar0521_power_on() to explicitly clean-out the clock during > > the error-path. > > > > The following smatch warning is fixed: > > drivers/media/i2c/ar0521.c:912 ar0521_power_on() warn: 'sensor->extclk' from clk_prepare_enable() not released on lines: 912. > > > > Signed-off-by: Ricardo Ribalda <ribalda@xxxxxxxxxxxx> > > --- > > It's better to just ignore false positives... The problem here is that > Smatch can't track that to_ar0521_dev(dev_get_drvdata(dev))->sensor is the same > as sensor. What I could do is say that "this frees *something* unknown" so > let's silence the warning." > > The problem is that check_unwind.c is not very granular. It just marks things > as allocated and freed. I could make it more granular so the free and the > alloc have to match. Or we could match based on the type. This frees a > "struct ar0521_dev" so mark all those as freed in the caller. > > > drivers/media/i2c/ar0521.c | 15 +++++++++++++-- > > 1 file changed, 13 insertions(+), 2 deletions(-) > > > > diff --git a/drivers/media/i2c/ar0521.c b/drivers/media/i2c/ar0521.c > > index 09331cf95c62..2c528db31ba6 100644 > > --- a/drivers/media/i2c/ar0521.c > > +++ b/drivers/media/i2c/ar0521.c > > @@ -835,7 +835,7 @@ static const struct initial_reg { > > be(0x0707)), /* 3F44: couple k factor 2 */ > > }; > > > > -static int ar0521_power_off(struct device *dev) > > +static void __ar0521_power_off(struct device *dev) > > { > > struct v4l2_subdev *sd = dev_get_drvdata(dev); > > struct ar0521_dev *sensor = to_ar0521_dev(sd); > > @@ -850,6 +850,16 @@ static int ar0521_power_off(struct device *dev) > > if (sensor->supplies[i]) > > regulator_disable(sensor->supplies[i]); > > } > > +} > > + > > +static int ar0521_power_off(struct device *dev) > > +{ > > + struct v4l2_subdev *sd = dev_get_drvdata(dev); > > + struct ar0521_dev *sensor = to_ar0521_dev(sd); > > + > > + clk_disable_unprepare(sensor->extclk); > > + __ar0521_power_off(dev); > > You had intended to remove the clk_disable_unprepare() from __ar0521_power_off() > but forgot so these are double unprepares. Ups, thanks for catching it :) Will send as v2, unless you fix it in smatch first ;P Regards! > > regards, > dan carpenter > > > + > > return 0; > > } > > > > @@ -908,7 +918,8 @@ static int ar0521_power_on(struct device *dev) > > > > return 0; > > off: > > - ar0521_power_off(dev); > > + clk_disable_unprepare(sensor->extclk); > > + __ar0521_power_off(dev); > > return ret; > > } > > > > > > -- > > 2.46.0.76.ge559c4bf1a-goog > > -- Ricardo Ribalda