Re: [PATCH 13/15] iio: health: max30100: do not use internal iio_dev lock

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 2022-09-20 at 15:53 +0200, Miquel Raynal wrote:
> Hi Nuno,
> 
> Nuno.Sa@xxxxxxxxxx wrote on Tue, 20 Sep 2022 13:15:32 +0000:
> 
> > > -----Original Message-----
> > > From: Miquel Raynal <miquel.raynal@xxxxxxxxxxx>
> > > Sent: Tuesday, September 20, 2022 2:56 PM
> > > To: Sa, Nuno <Nuno.Sa@xxxxxxxxxx>
> > > Cc: linux-arm-kernel@xxxxxxxxxxxxxxxxxxx;
> > > linux-rockchip@xxxxxxxxxxxxxxxxxxx;
> > > linux-amlogic@xxxxxxxxxxxxxxxxxxx; linux-imx@xxxxxxx; linux-
> > > iio@xxxxxxxxxxxxxxx; Chunyan Zhang <zhang.lyra@xxxxxxxxx>;
> > > Hennerich,
> > > Michael <Michael.Hennerich@xxxxxxxxxx>; Martin Blumenstingl
> > > <martin.blumenstingl@xxxxxxxxxxxxxx>; Sascha Hauer
> > > <s.hauer@xxxxxxxxxxxxxx>; Cixi Geng <cixi.geng1@xxxxxxxxxx>;
> > > Kevin
> > > Hilman <khilman@xxxxxxxxxxxx>; Vladimir Zapolskiy <vz@xxxxxxxxx>;
> > > Pengutronix Kernel Team <kernel@xxxxxxxxxxxxxx>; Alexandru
> > > Ardelean
> > > <aardelean@xxxxxxxxxxx>; Fabio Estevam <festevam@xxxxxxxxx>;
> > > Andriy
> > > Tryshnivskyy <andriy.tryshnivskyy@xxxxxxxxxxxxxxx>; Haibo Chen
> > > <haibo.chen@xxxxxxx>; Shawn Guo <shawnguo@xxxxxxxxxx>; Hans de
> > > Goede <hdegoede@xxxxxxxxxx>; Jerome Brunet
> > > <jbrunet@xxxxxxxxxxxx>;
> > > Heiko Stuebner <heiko@xxxxxxxxx>; Florian Boor
> > > <florian.boor@xxxxxxxxxxxxxxxxx>; Regus, Ciprian
> > > <Ciprian.Regus@xxxxxxxxxx>; Lars-Peter Clausen <lars@xxxxxxxxxx>;
> > > Andy
> > > Shevchenko <andy.shevchenko@xxxxxxxxx>; Jonathan Cameron
> > > <jic23@xxxxxxxxxx>; Neil Armstrong <narmstrong@xxxxxxxxxxxx>;
> > > Baolin
> > > Wang <baolin.wang@xxxxxxxxxxxxxxxxx>; Jyoti Bhayana
> > > <jbhayana@xxxxxxxxxx>; Chen-Yu Tsai <wens@xxxxxxxx>; Orson Zhai
> > > <orsonzhai@xxxxxxxxx>
> > > Subject: Re: [PATCH 13/15] iio: health: max30100: do not use
> > > internal iio_dev
> > > lock
> > > 
> > > [External]
> > > 
> > > Hi Nuno,
> > > 
> > > Nuno.Sa@xxxxxxxxxx wrote on Tue, 20 Sep 2022 12:44:08 +0000:
> > >   
> > > > > -----Original Message-----
> > > > > From: Miquel Raynal <miquel.raynal@xxxxxxxxxxx>
> > > > > Sent: Tuesday, September 20, 2022 2:23 PM
> > > > > To: Sa, Nuno <Nuno.Sa@xxxxxxxxxx>
> > > > > Cc: linux-arm-kernel@xxxxxxxxxxxxxxxxxxx; linux-  
> > > rockchip@xxxxxxxxxxxxxxxxxxx;  
> > > > > linux-amlogic@xxxxxxxxxxxxxxxxxxx; linux-imx@xxxxxxx; linux-
> > > > > iio@xxxxxxxxxxxxxxx; Chunyan Zhang <zhang.lyra@xxxxxxxxx>;  
> > > Hennerich,  
> > > > > Michael <Michael.Hennerich@xxxxxxxxxx>; Martin Blumenstingl
> > > > > <martin.blumenstingl@xxxxxxxxxxxxxx>; Sascha Hauer
> > > > > <s.hauer@xxxxxxxxxxxxxx>; Cixi Geng <cixi.geng1@xxxxxxxxxx>;
> > > > > Kevin
> > > > > Hilman <khilman@xxxxxxxxxxxx>; Vladimir Zapolskiy
> > > > > <vz@xxxxxxxxx>;
> > > > > Pengutronix Kernel Team <kernel@xxxxxxxxxxxxxx>; Alexandru  
> > > Ardelean  
> > > > > <aardelean@xxxxxxxxxxx>; Fabio Estevam <festevam@xxxxxxxxx>; 
> > > Andriy  
> > > > > Tryshnivskyy <andriy.tryshnivskyy@xxxxxxxxxxxxxxx>; Haibo
> > > > > Chen
> > > > > <haibo.chen@xxxxxxx>; Shawn Guo <shawnguo@xxxxxxxxxx>; Hans
> > > > > de
> > > > > Goede <hdegoede@xxxxxxxxxx>; Jerome Brunet  
> > > <jbrunet@xxxxxxxxxxxx>;  
> > > > > Heiko Stuebner <heiko@xxxxxxxxx>; Florian Boor
> > > > > <florian.boor@xxxxxxxxxxxxxxxxx>; Regus, Ciprian
> > > > > <Ciprian.Regus@xxxxxxxxxx>; Lars-Peter Clausen
> > > > > <lars@xxxxxxxxxx>;  
> > > Andy  
> > > > > Shevchenko <andy.shevchenko@xxxxxxxxx>; Jonathan Cameron
> > > > > <jic23@xxxxxxxxxx>; Neil Armstrong <narmstrong@xxxxxxxxxxxx>;
> > > > > Baolin
> > > > > Wang <baolin.wang@xxxxxxxxxxxxxxxxx>; Jyoti Bhayana
> > > > > <jbhayana@xxxxxxxxxx>; Chen-Yu Tsai <wens@xxxxxxxx>; Orson
> > > > > Zhai
> > > > > <orsonzhai@xxxxxxxxx>
> > > > > Subject: Re: [PATCH 13/15] iio: health: max30100: do not use
> > > > > internal  
> > > iio_dev  
> > > > > lock
> > > > > 
> > > > > [External]
> > > > > 
> > > > > Hi Nuno,
> > > > >  
> > > > 
> > > > Hi Miquel,
> > > > 
> > > > Thanks for reviewing...
> > > >  
> > > > > nuno.sa@xxxxxxxxxx wrote on Tue, 20 Sep 2022 13:28:19 +0200:
> > > > >  
> > > > > > The pattern used in this device does not quite fit in the
> > > > > > iio_device_claim_direct_mode() typical usage. In this case,
> > > > > > iio_buffer_enabled() was being used not to prevent the raw
> > > > > > access but  
> > > to  
> > > > > > allow it. Hence to get rid of the 'mlock' we need to:
> > > > > > 
> > > > > > 1. Use iio_device_claim_direct_mode() to check if direct
> > > > > > mode can be
> > > > > > claimed and if we can return -EINVAL (as the original
> > > > > > code);
> > > > > > 
> > > > > > 2. Make sure that buffering is not disabled while doing a
> > > > > > raw read. For
> > > > > > that, we can make use of the local lock that already
> > > > > > exists.
> > > > > > 
> > > > > > While at it, fixed a minor coding style complain...
> > > > > > 
> > > > > > Signed-off-by: Nuno Sá <nuno.sa@xxxxxxxxxx>
> > > > > > ---
> > > > > >  drivers/iio/health/max30100.c | 24 +++++++++++++++++------
> > > > > > -
> > > > > >  1 file changed, 17 insertions(+), 7 deletions(-)
> > > > > > 
> > > > > > diff --git a/drivers/iio/health/max30100.c  
> > > b/drivers/iio/health/max30100.c  
> > > > > > index ad5717965223..aa494cad5df0 100644
> > > > > > --- a/drivers/iio/health/max30100.c
> > > > > > +++ b/drivers/iio/health/max30100.c
> > > > > > @@ -185,8 +185,19 @@ static int
> > > > > > max30100_buffer_postenable(struct  
> > > > > iio_dev *indio_dev)  
> > > > > >  static int max30100_buffer_predisable(struct iio_dev
> > > > > > *indio_dev)
> > > > > >  {
> > > > > >         struct max30100_data *data = iio_priv(indio_dev);
> > > > > > +       int ret;
> > > > > > +
> > > > > > +       /*
> > > > > > +        * As stated in the comment in the read_raw()
> > > > > > function, temperature
> > > > > > +        * can only be acquired if the engine is running.
> > > > > > As such the mutex
> > > > > > +        * is used to make sure we do not power down while
> > > > > > doing a  
> > > > > temperature  
> > > > > > +        * reading.
> > > > > > +        */
> > > > > > +       mutex_lock(&data->lock);
> > > > > > +       ret = max30100_set_powermode(data, false);
> > > > > > +       mutex_unlock(&data->lock);
> > > > > > 
> > > > > > -       return max30100_set_powermode(data, false);
> > > > > > +       return ret;
> > > > > >  }
> > > > > > 
> > > > > >  static const struct iio_buffer_setup_ops
> > > > > > max30100_buffer_setup_ops  
> > > = {  
> > > > > > @@ -387,18 +398,17 @@ static int max30100_read_raw(struct
> > > > > > iio_dev  
> > > > > *indio_dev,  
> > > > > >                  * Temperature reading can only be acquired
> > > > > > while engine
> > > > > >                  * is running
> > > > > >                  */
> > > > > > -               mutex_lock(&indio_dev->mlock);
> > > > > > -
> > > > > > -               if (!iio_buffer_enabled(indio_dev))
> > > > > > +               if
> > > > > > (!iio_device_claim_direct_mode(indio_dev)) {  
> > > > > 
> > > > > I wonder if this line change here is really needed. I agree
> > > > > the whole
> > > > > construction looks like what iio_device_claim_direct_mode()
> > > > > does but in
> > > > > practice I don't see the point of acquiring any lock here if
> > > > > we just
> > > > > release it no matter what happens right after.
> > > > >  
> > > > 
> > > > I can see that this is odd (at the very least) but AFAIK, this
> > > > is the only way
> > > > to safely infer if buffering is enabled or not.
> > > > iio_buffer_enabled() has no
> > > > protection against someone concurrently enabling/disabling the
> > > > buffer.  
> > > 
> > > Yes, but this is only relevant if you want to infer that the
> > > "buffers
> > > are enabled" and be sure that it cannot be otherwise during the
> > > next
> > > lines until you release the lock. Acquiring a lock, doing the if
> > > and
> > > then unconditionally releasing the lock, IMHO, does not make any
> > > sense
> > > (but I'm not a locking guru) because when you enter the else
> > > clause,
> > > you are not protected anyway, so in both cases all this is
> > > completely
> > > racy.
> > >   
> > 
> > Ahh crap, yes you are right... It is still racy since we can still
> > try to read
> > the temperature with the device powered off. I'm not really sure
> > how to
> > address this. One way could be to just use an internal control
> > variable
> > to reflect the device power state (set/clear on the buffer
> > callbacks) and
> > only use the local lock (completely ditching the call to
> > iio_device_claim_direct_mode())...
> 
> I tend to prefer this option than the one below.
> 
> I guess your implementation already prevents buffer_predisable() to
> run
> thanks to the local lock being held during the operation. Maybe we
> should just verify that buffers are enabled from within the local
> lock
> being held instead of just acquiring it for the get_temp() measure.
> It
> would probably solve the situation here.
> > 
Not sure if I understood... You mean something like:

mutex_lock(&data->lock);
if (!iio_buffer_enabled(indio_dev)) {
	ret = -EINVAL;
} else {
 	ret = max30100_get_temp(data, val);
 	if (!ret)
 		ret = IIO_VAL_INT;

}
mutex_unlock(&data->lock);

If so, I think this is still racy since we release the lock after the
predisable which means we could still detect the buffers as enabled (in
the above block) and try to get_temp on a powered down device.

Since we pretty much only care about the power state of the device (and
we are using the buffering state to infer that AFAIU), I was thinking
in something like:


mutex_lock(&data->lock);
if (!data->powered) {
	ret = -EINVAL;
} else {
 	ret = max30100_get_temp(data, val);
 	if (!ret)
 		ret = IIO_VAL_INT;

}
mutex_unlock(&data->lock);

Then, in the predisable, something like I have but setting the flag to
false and the opposite on the postenable... Naturally we could also
just read the registers (and I actually tend to prefer it) instead of a
new flag but I guess the flag is enough in this case.

- Nuno Sá
> 




[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux