On Tue, 6 Oct 2020 14:55:09 -0700 dmitry.torokhov@xxxxxxxxx wrote: > The order in which 'users' counter is decremented vs calling drivers' > close() method is implementation specific, and we should not rely on > it. Let's introduce driver private flag and use it to signal ISR > to exit when device is being closed. > > This has a side-effect of fixing issue of accessing inut->users > outside of input->mutex protection. > > Reported-by: Andrzej Pietrasiewicz <andrzej.p@xxxxxxxxxxxxx> > Acked-by: Krzysztof Kozlowski <krzk@xxxxxxxxxx> > Reviewed-by: Michał Mirosław <mirq-linux@xxxxxxxxxxxx> > Signed-off-by: Dmitry Torokhov <dmitry.torokhov@xxxxxxxxx> Applied to the togreg branch of iio.git and pushed out as testing for the autobuilders to work their magic. Given this doesn't have a fixes tag etc I'm assuming it isn't high priority etc. Let me know if it is! Thanks, Jonathan > --- > > v3: fixed typo in exynos_adc_ts_close() per Michał Mirosław > v2: switched from ordinary read/write to READ_ONCE/WRITE_ONCE per Michał > Mirosław > > drivers/iio/adc/exynos_adc.c | 7 ++++++- > 1 file changed, 6 insertions(+), 1 deletion(-) > > diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c > index 22131a677445..908df4b9b93c 100644 > --- a/drivers/iio/adc/exynos_adc.c > +++ b/drivers/iio/adc/exynos_adc.c > @@ -7,6 +7,7 @@ > * Copyright (C) 2013 Naveen Krishna Chatradhi <ch.naveen@xxxxxxxxxxx> > */ > > +#include <linux/compiler.h> > #include <linux/module.h> > #include <linux/platform_device.h> > #include <linux/interrupt.h> > @@ -135,6 +136,8 @@ struct exynos_adc { > u32 value; > unsigned int version; > > + bool ts_enabled; > + > bool read_ts; > u32 ts_x; > u32 ts_y; > @@ -633,7 +636,7 @@ static irqreturn_t exynos_ts_isr(int irq, void *dev_id) > bool pressed; > int ret; > > - while (info->input->users) { > + while (READ_ONCE(info->ts_enabled)) { > ret = exynos_read_s3c64xx_ts(dev, &x, &y); > if (ret == -ETIMEDOUT) > break; > @@ -712,6 +715,7 @@ static int exynos_adc_ts_open(struct input_dev *dev) > { > struct exynos_adc *info = input_get_drvdata(dev); > > + WRITE_ONCE(info->ts_enabled, true); > enable_irq(info->tsirq); > > return 0; > @@ -721,6 +725,7 @@ static void exynos_adc_ts_close(struct input_dev *dev) > { > struct exynos_adc *info = input_get_drvdata(dev); > > + WRITE_ONCE(info->ts_enabled, false); > disable_irq(info->tsirq); > } >