| From 59f92868176f191eefde70d284bdfc1ed76a84bc Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org> |
| Date: Mon, 18 Oct 2021 13:37:31 +0200 |
| Subject: iio: dln2-adc: Fix lockdep complaint |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Noralf Trønnes <noralf@tronnes.org> |
| |
| commit 59f92868176f191eefde70d284bdfc1ed76a84bc upstream. |
| |
| When reading the voltage: |
| |
| $ cat /sys/bus/iio/devices/iio\:device0/in_voltage0_raw |
| |
| Lockdep complains: |
| |
| [ 153.910616] ====================================================== |
| [ 153.916918] WARNING: possible circular locking dependency detected |
| [ 153.923221] 5.14.0+ #5 Not tainted |
| [ 153.926692] ------------------------------------------------------ |
| [ 153.932992] cat/717 is trying to acquire lock: |
| [ 153.937525] c2585358 (&indio_dev->mlock){+.+.}-{3:3}, at: iio_device_claim_direct_mode+0x28/0x44 |
| [ 153.946541] |
| but task is already holding lock: |
| [ 153.952487] c2585860 (&dln2->mutex){+.+.}-{3:3}, at: dln2_adc_read_raw+0x94/0x2bc [dln2_adc] |
| [ 153.961152] |
| which lock already depends on the new lock. |
| |
| Fix this by not calling into the iio core underneath the dln2->mutex lock. |
| |
| Fixes: 7c0299e879dd ("iio: adc: Add support for DLN2 ADC") |
| Cc: Jack Andersen <jackoalan@gmail.com> |
| Signed-off-by: Noralf Trønnes <noralf@tronnes.org> |
| Link: https://lore.kernel.org/r/20211018113731.25723-1-noralf@tronnes.org |
| Cc: <Stable@vger.kernel.org> |
| Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/iio/adc/dln2-adc.c | 15 +++++++-------- |
| 1 file changed, 7 insertions(+), 8 deletions(-) |
| |
| --- a/drivers/iio/adc/dln2-adc.c |
| +++ b/drivers/iio/adc/dln2-adc.c |
| @@ -248,7 +248,6 @@ static int dln2_adc_set_chan_period(stru |
| static int dln2_adc_read(struct dln2_adc *dln2, unsigned int channel) |
| { |
| int ret, i; |
| - struct iio_dev *indio_dev = platform_get_drvdata(dln2->pdev); |
| u16 conflict; |
| __le16 value; |
| int olen = sizeof(value); |
| @@ -257,13 +256,9 @@ static int dln2_adc_read(struct dln2_adc |
| .chan = channel, |
| }; |
| |
| - ret = iio_device_claim_direct_mode(indio_dev); |
| - if (ret < 0) |
| - return ret; |
| - |
| ret = dln2_adc_set_chan_enabled(dln2, channel, true); |
| if (ret < 0) |
| - goto release_direct; |
| + return ret; |
| |
| ret = dln2_adc_set_port_enabled(dln2, true, &conflict); |
| if (ret < 0) { |
| @@ -300,8 +295,6 @@ disable_port: |
| dln2_adc_set_port_enabled(dln2, false, NULL); |
| disable_chan: |
| dln2_adc_set_chan_enabled(dln2, channel, false); |
| -release_direct: |
| - iio_device_release_direct_mode(indio_dev); |
| |
| return ret; |
| } |
| @@ -337,10 +330,16 @@ static int dln2_adc_read_raw(struct iio_ |
| |
| switch (mask) { |
| case IIO_CHAN_INFO_RAW: |
| + ret = iio_device_claim_direct_mode(indio_dev); |
| + if (ret < 0) |
| + return ret; |
| + |
| mutex_lock(&dln2->mutex); |
| ret = dln2_adc_read(dln2, chan->channel); |
| mutex_unlock(&dln2->mutex); |
| |
| + iio_device_release_direct_mode(indio_dev); |
| + |
| if (ret < 0) |
| return ret; |
| |