diff options
author | David Frey <dpfrey@gmail.com> | 2019-09-19 15:54:18 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-10-17 13:41:03 -0700 |
commit | 07bc13c09be66ab633c69af2ca46be5b5239256f (patch) | |
tree | 257e880e88f97bef27d8a5157e012f5ca92ac29f /drivers/iio | |
parent | 2a736f3547c6f13d05aae7f6e5a94cb9adb613ae (diff) |
iio: light: opt3001: fix mutex unlock race
commit 82f3015635249a8c8c45bac303fd84905066f04f upstream.
When an end-of-conversion interrupt is received after performing a
single-shot reading of the light sensor, the driver was waking up the
result ready queue before checking opt->ok_to_ignore_lock to determine
if it should unlock the mutex. The problem occurred in the case where
the other thread woke up and changed the value of opt->ok_to_ignore_lock
to false prior to the interrupt thread performing its read of the
variable. In this case, the mutex would be unlocked twice.
Signed-off-by: David Frey <dpfrey@gmail.com>
Reviewed-by: Andreas Dannenberg <dannenberg@ti.com>
Fixes: 94a9b7b1809f ("iio: light: add support for TI's opt3001 light sensor")
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/iio')
-rw-r--r-- | drivers/iio/light/opt3001.c | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c index 01e111e72d4b..eecdc50ed282 100644 --- a/drivers/iio/light/opt3001.c +++ b/drivers/iio/light/opt3001.c @@ -646,6 +646,7 @@ static irqreturn_t opt3001_irq(int irq, void *_iio) struct iio_dev *iio = _iio; struct opt3001 *opt = iio_priv(iio); int ret; + bool wake_result_ready_queue = false; if (!opt->ok_to_ignore_lock) mutex_lock(&opt->lock); @@ -680,13 +681,16 @@ static irqreturn_t opt3001_irq(int irq, void *_iio) } opt->result = ret; opt->result_ready = true; - wake_up(&opt->result_ready_queue); + wake_result_ready_queue = true; } out: if (!opt->ok_to_ignore_lock) mutex_unlock(&opt->lock); + if (wake_result_ready_queue) + wake_up(&opt->result_ready_queue); + return IRQ_HANDLED; } |