Received: by 2002:a5b:505:0:0:0:0:0 with SMTP id o5csp2000514ybp; Sat, 12 Oct 2019 02:08:28 -0700 (PDT) X-Google-Smtp-Source: APXvYqw5I/w0KYkGTALO8hdQioL9XV9Km518NxLzh7MooD8rxUXWh9d0UD9mHvdi7augTv4BY42E X-Received: by 2002:a05:6402:1612:: with SMTP id f18mr17973329edv.66.1570871308298; Sat, 12 Oct 2019 02:08:28 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1570871308; cv=none; d=google.com; s=arc-20160816; b=LQ4kGRH4KeGgbBkpbtAfj5eQOuy3owbt/lKxZwysc09O6N81LtBYpXZenboJmRj22n Z15SLKz9ALJto/kdJvj5fR7iDbonaAKqK7BVe7pVRiJEZmoT3Ecj6Jq452NukwSZ2Ki7 xHY2jgS8U0FAP8Yaj6/qXm5Wz6VKr1xCpYA3HvJ971R8RB9ZR0HsUMB/dX3rFaDrV9bg zsYNF8IY4rcmySsRK+F4UiECD1jO6TbRu5SEFcIqYxpJE4RWKmiSk86b3dqySkjVdObh RA35bzWtZ1gDc9nZ4gc6EQ15Vd4c0McisYYK+AU1dEUiIssokQx4ZMrNas+FH740DdP4 359g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:subject:cc:to:from:date :dkim-signature; bh=tz8XefiMcSVSwqQH4I0dS5MK27ZJLEq413JmcZXpPqs=; b=tTVCkecjmgWV3WJzlVgToXbNQTmOlUpVSDJseRJpP6RQDu1p6UT5ab6uZiks3lRsCw 2XcY+BKZ8dW4XBzquG81LZa8Cz7nWYt8DSwzlq2GjtnXQuYExyUyF0RPIgsafcJ6jvqT RAtTPbcKy+y5EdHnx22OvZG0ElVfEUeoypB5ZqQFhLTVwVRGDWYwnMpHHuSYvB9c6wSN LnawlQR/qRCphes+dQAcykzlwVWv2xd2HTCzBM8CwH+mEC//arRvtgZfoF5bhmikam+8 USEcbPJr5k+lyZxzRsDCcYors6fCctTLsHlz+qVtnFgA4H3hxmMOG2o98Snp7w0VrI/R v5jw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=kE80NsZp; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f13si7462848ejj.402.2019.10.12.02.08.04; Sat, 12 Oct 2019 02:08:28 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=kE80NsZp; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729023AbfJLI7y (ORCPT + 99 others); Sat, 12 Oct 2019 04:59:54 -0400 Received: from mail.kernel.org ([198.145.29.99]:47052 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726821AbfJLI5y (ORCPT ); Sat, 12 Oct 2019 04:57:54 -0400 Received: from archlinux (cpc149474-cmbg20-2-0-cust94.5-4.cable.virginm.net [82.4.196.95]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id A07F72087E; Sat, 12 Oct 2019 08:57:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1570870673; bh=RipfHWEIkpJnWKib5xTZIXJ4ltV45KJyDOOq5i6WXYI=; h=Date:From:To:Cc:Subject:In-Reply-To:References:From; b=kE80NsZp3Qh2HX060okbKBFlCpOuRbMfdC8w9N5gFd1SkkIhi44aL3IofPGP/zM+X qf85aFaZ2WOR/GQ6Gmg3BDSaD+pzwmfBfeoqjkeB+A9QjMV0amkvO/3nYz5xVB1LyZ ZsL50oNyO2WVqiXHokANhgx13JveFtxeJ28zMtPM= Date: Sat, 12 Oct 2019 09:57:47 +0100 From: Jonathan Cameron To: Olivier Moysan Cc: , , , , , , , , , , Subject: Re: [PATCH][RFC] iio: core: add a class hierarchy on iio device lock Message-ID: <20191012095747.3acd95e6@archlinux> In-Reply-To: <20191011151314.5365-1-olivier.moysan@st.com> References: <20191011151314.5365-1-olivier.moysan@st.com> X-Mailer: Claws Mail 3.17.4 (GTK+ 2.24.32; x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Fri, 11 Oct 2019 17:13:14 +0200 Olivier Moysan wrote: > The aim of this patch is to correct a recursive locking warning, > detected when setting CONFIG_PROVE_LOCKING flag (as shown in message below). > This message was initially triggered by the following call sequence > in stm32-dfsdm-adc.c driver, when using IIO hardware consumer interface. > > in stm32_dfsdm_read_raw() > iio_device_claim_direct_mode > mutex_lock(&indio_dev->mlock); -> lock on dfsdm device > iio_hw_consumer_enable > iio_update_buffers > mutex_lock(&indio_dev->mlock); -> lock on hw consumer device Hmm. I'm not sure I follow the logic. That lock is for one thing and one thing only, preventing access to the iio device that are unsafe when it is running in a buffered mode. We shouldn't be in a position where we both say don't do this if we are in buffered mode, + enter buffered mode whilst doing this, or we need special functions for entering buffering mode if in this state. We are in some sense combining internal driver logic with overall IIO states. IIO shouldn't care that the device is using the same methods under the hood for buffered and non buffered operations. I can't really recall how this driver works. Is it actually possible to have multiple hw_consumers at the same time? So do we end up with multiple buffers registered and have to demux out to the read_raw + the actual buffered path? Given we have a bit of code saying grab one sample, I'm going to guess we don't... If so, the vast majority of the buffer setup code in IIO is irrelevant here and we just need to call a few of the callbacks from this driver directly... (I think though I haven't chased through every corner. I'd rather avoid introducing this nesting for a corner case that makes no 'semantic' sense in IIO as it leaves us in two separate states at the same time that the driver is trying to make mutually exclusive. We can't both not be in buffered mode, and in buffered mode. Thanks and good luck with this nasty corner! Jonathan > > Here two instances of the same lock class are requested > on two different objects. > The locking validator needs to be informed of the nesting level > of each lock to avoid a false positive. > > This patch introduces a class hierarchy in iio device lock, > assuming that hardware consumer is at a lower level than iio device. > > [ 52.086174] > [ 52.086223] ============================================ > [ 52.091516] WARNING: possible recursive locking detected > [ 52.096825] 4.19.49 #162 Not tainted > [ 52.100384] -------------------------------------------- > [ 52.105691] cat/823 is trying to acquire lock: > [ 52.110132] 37acb703 (&dev->mlock){+.+.}, at: iio_update_buffers+0x3c/0xd0 > [ 52.116995] > [ 52.116995] but task is already holding lock: > [ 52.122821] 368bb908 (&dev->mlock){+.+.}, at: iio_device_claim_direct_mode+0x18/0x34 > [ 52.130560] > [ 52.130560] other info that might help us debug this: > [ 52.137083] Possible unsafe locking scenario: > [ 52.137083] > [ 52.142995] CPU0 > [ 52.145430] ---- > [ 52.147864] lock(&dev->mlock); > [ 52.151082] lock(&dev->mlock); > [ 52.154301] > [ 52.154301] * DEADLOCK * > [ 52.154301] > [ 52.160215] May be due to missing lock nesting notation > [ 52.160215] > [ 52.167000] 5 locks held by cat/823: > [ 52.170563] #0: 96d6554b (&p->lock){+.+.}, at: seq_read+0x34/0x51c > [ 52.176824] #1: 3cf6739a (&of->mutex){+.+.}, at: kernfs_seq_start+0x1c/0x8c > [ 52.183866] #2: a6090e0a (kn->count#29){.+.+}, at: kernfs_seq_start+0x24/0x8c > [ 52.191083] #3: 368bb908 (&dev->mlock){+.+.}, at: iio_device_claim_direct_mode+0x18/0x34 > [ 52.199257] #4: 77e2bcfe (&dev->info_exist_lock){+.+.}, at: iio_update_buffers+0x30/0xd0 > [ 52.207431] > [ 52.207431] stack backtrace: > [ 52.211787] CPU: 0 PID: 823 Comm: cat Not tainted 4.19.49 #162 > [ 52.217606] Hardware name: STM32 (Device Tree Support) > [ 52.222756] [] (unwind_backtrace) from [] (show_stack+0x10/0x14) > [ 52.230487] [] (show_stack) from [] (dump_stack+0xc4/0xf0) > [ 52.237703] [] (dump_stack) from [] (__lock_acquire+0x874/0x1344) > [ 52.245525] [] (__lock_acquire) from [] (lock_acquire+0xd8/0x268) > [ 52.253353] [] (lock_acquire) from [] (__mutex_lock+0x70/0xab0) > [ 52.261005] [] (__mutex_lock) from [] (mutex_lock_nested+0x1c/0x24) > [ 52.269001] [] (mutex_lock_nested) from [] (iio_update_buffers+0x3c/0xd0) > [ 52.277523] [] (iio_update_buffers) from [] (iio_hw_consumer_enable+0x34/0x70) > [ 52.286476] [] (iio_hw_consumer_enable) from [] (stm32_dfsdm_read_raw+0xf4/0x3fc) > [ 52.295695] [] (stm32_dfsdm_read_raw) from [] (iio_read_channel_info+0xa8/0xb0) > [ 52.304738] [] (iio_read_channel_info) from [] (dev_attr_show+0x1c/0x48) > [ 52.313170] [] (dev_attr_show) from [] (sysfs_kf_seq_show+0x84/0xec) > [ 52.321256] [] (sysfs_kf_seq_show) from [] (seq_read+0x154/0x51c) > [ 52.329082] [] (seq_read) from [] (__vfs_read+0x2c/0x15c) > [ 52.336209] [] (__vfs_read) from [] (vfs_read+0x90/0x15c) > [ 52.343339] [] (vfs_read) from [] (ksys_read+0x5c/0xdc) > [ 52.350296] [] (ksys_read) from [] (ret_fast_syscall+0x0/0x28) > [ 52.357852] Exception stack(0xe5761fa8 to 0xe5761ff0) > [ 52.362904] 1fa0: 0000006c 7ff00000 00000003 b6e06000 00020000 00000000 > [ 52.371077] 1fc0: 0000006c 7ff00000 00020000 00000003 00000003 00000000 00020000 00000000 > [ 52.379245] 1fe0: 00000003 beb6e790 b6eb17b7 b6e3e6c6 > > Signed-off-by: Olivier Moysan > --- > drivers/iio/buffer/industrialio-hw-consumer.c | 9 ++++++++- > drivers/iio/industrialio-buffer.c | 2 +- > drivers/iio/industrialio-core.c | 3 ++- > include/linux/iio/iio.h | 6 ++++++ > 4 files changed, 17 insertions(+), 3 deletions(-) > > diff --git a/drivers/iio/buffer/industrialio-hw-consumer.c b/drivers/iio/buffer/industrialio-hw-consumer.c > index 95165697d8ae..652ce31b4b5f 100644 > --- a/drivers/iio/buffer/industrialio-hw-consumer.c > +++ b/drivers/iio/buffer/industrialio-hw-consumer.c > @@ -101,6 +101,7 @@ struct iio_hw_consumer *iio_hw_consumer_alloc(struct device *dev) > > chan = &hwc->channels[0]; > while (chan->indio_dev) { > + chan->indio_dev->mutex_class = IIO_MUTEX_HWC; > buf = iio_hw_consumer_get_buffer(hwc, chan->indio_dev); > if (!buf) { > ret = -ENOMEM; > @@ -129,8 +130,14 @@ EXPORT_SYMBOL_GPL(iio_hw_consumer_alloc); > void iio_hw_consumer_free(struct iio_hw_consumer *hwc) > { > struct hw_consumer_buffer *buf, *n; > + struct iio_channel *chan = &hwc->channels[0]; > + > + while (chan->indio_dev) { > + chan->indio_dev->mutex_class = IIO_MUTEX_NORMAL; > + iio_channel_release(chan); > + chan++; > + } > > - iio_channel_release_all(hwc->channels); > list_for_each_entry_safe(buf, n, &hwc->buffers, head) > iio_buffer_put(&buf->buffer); > kfree(hwc); > diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c > index c193d64e5217..d1df04167978 100644 > --- a/drivers/iio/industrialio-buffer.c > +++ b/drivers/iio/industrialio-buffer.c > @@ -1077,7 +1077,7 @@ int iio_update_buffers(struct iio_dev *indio_dev, > return 0; > > mutex_lock(&indio_dev->info_exist_lock); > - mutex_lock(&indio_dev->mlock); > + mutex_lock_nested(&indio_dev->mlock, indio_dev->mutex_class); > > if (insert_buffer && iio_buffer_is_active(insert_buffer)) > insert_buffer = NULL; > diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c > index f72c2dc5f703..b14ba42559a3 100644 > --- a/drivers/iio/industrialio-core.c > +++ b/drivers/iio/industrialio-core.c > @@ -1454,6 +1454,7 @@ struct iio_dev *iio_device_alloc(int sizeof_priv) > dev->dev.groups = dev->groups; > dev->dev.type = &iio_device_type; > dev->dev.bus = &iio_bus_type; > + dev->mutex_class = IIO_MUTEX_NORMAL; > device_initialize(&dev->dev); > dev_set_drvdata(&dev->dev, (void *)dev); > mutex_init(&dev->mlock); > @@ -1805,7 +1806,7 @@ EXPORT_SYMBOL_GPL(devm_iio_device_unregister); > */ > int iio_device_claim_direct_mode(struct iio_dev *indio_dev) > { > - mutex_lock(&indio_dev->mlock); > + mutex_lock_nested(&indio_dev->mlock, indio_dev->mutex_class); > > if (iio_buffer_enabled(indio_dev)) { > mutex_unlock(&indio_dev->mlock); > diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h > index 862ce0019eba..1192eca124f4 100644 > --- a/include/linux/iio/iio.h > +++ b/include/linux/iio/iio.h > @@ -17,6 +17,11 @@ > * Currently assumes nano seconds. > */ > > +enum iio_mutex_lock_class { > + IIO_MUTEX_NORMAL, > + IIO_MUTEX_HWC, > +}; > + > enum iio_shared_by { > IIO_SEPARATE, > IIO_SHARED_BY_TYPE, > @@ -537,6 +542,7 @@ struct iio_dev { > struct list_head buffer_list; > int scan_bytes; > struct mutex mlock; > + int mutex_class; > > const unsigned long *available_scan_masks; > unsigned masklength;