summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Frey <dpfrey@gmail.com>2019-09-19 15:54:18 -0700
committerJonathan Cameron <Jonathan.Cameron@huawei.com>2019-10-09 19:11:29 +0100
commit82f3015635249a8c8c45bac303fd84905066f04f (patch)
tree733c6c6bb18d153052a1be15dbc801e74c65271c
parentc62dd44901cfff12acc5792bf3d2dec20bcaf392 (diff)
downloadlinux-stable-82f3015635249a8c8c45bac303fd84905066f04f.tar.gz
linux-stable-82f3015635249a8c8c45bac303fd84905066f04f.tar.bz2
linux-stable-82f3015635249a8c8c45bac303fd84905066f04f.zip
iio: light: opt3001: fix mutex unlock race
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>
-rw-r--r--drivers/iio/light/opt3001.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c
index e666879007d2..92004a2563ea 100644
--- a/drivers/iio/light/opt3001.c
+++ b/drivers/iio/light/opt3001.c
@@ -686,6 +686,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);
@@ -720,13 +721,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;
}