linux-spi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] spi: Make spi_add_lock a per-controller lock
@ 2021-10-13 13:37 Uwe Kleine-König
  2021-10-13 13:37 ` [PATCH 2/2] spi-mux: Fix false-positive lockdep splats Uwe Kleine-König
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Uwe Kleine-König @ 2021-10-13 13:37 UTC (permalink / raw)
  To: Mark Brown; +Cc: kernel, linux-spi

The spi_add_lock that is removed with this change was held when
spi_add_device() called device_add() (via __spi_add_device()).

In the case where the added device is an spi-mux calling device_add()
might result in calling the spi-mux's probe function which adds another
controller and for that spi_add_device() might be called. This results
in a dead-lock.

To circumvent this deadlock replace the global spi_add_lock with a lock
per controller.

The biggest part of this patch was authored by Mark Brown.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/spi/spi.c       | 17 ++++++-----------
 include/linux/spi/spi.h |  4 ++++
 2 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 50591de16e0f..193e3264f7eb 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -477,12 +477,6 @@ static LIST_HEAD(spi_controller_list);
  */
 static DEFINE_MUTEX(board_lock);
 
-/*
- * Prevents addition of devices with same chip select and
- * addition of devices below an unregistering controller.
- */
-static DEFINE_MUTEX(spi_add_lock);
-
 /**
  * spi_alloc_device - Allocate a new SPI device
  * @ctlr: Controller to which device is connected
@@ -635,9 +629,9 @@ static int spi_add_device(struct spi_device *spi)
 	/* Set the bus ID string */
 	spi_dev_set_name(spi);
 
-	mutex_lock(&spi_add_lock);
+	mutex_lock(&ctlr->add_lock);
 	status = __spi_add_device(spi);
-	mutex_unlock(&spi_add_lock);
+	mutex_unlock(&ctlr->add_lock);
 	return status;
 }
 
@@ -656,7 +650,7 @@ static int spi_add_device_locked(struct spi_device *spi)
 	/* Set the bus ID string */
 	spi_dev_set_name(spi);
 
-	WARN_ON(!mutex_is_locked(&spi_add_lock));
+	WARN_ON(!mutex_is_locked(&ctlr->add_lock));
 	return __spi_add_device(spi);
 }
 
@@ -2909,6 +2903,7 @@ int spi_register_controller(struct spi_controller *ctlr)
 	spin_lock_init(&ctlr->bus_lock_spinlock);
 	mutex_init(&ctlr->bus_lock_mutex);
 	mutex_init(&ctlr->io_mutex);
+	mutex_init(&ctlr->add_lock);
 	ctlr->bus_lock_flag = 0;
 	init_completion(&ctlr->xfer_completion);
 	if (!ctlr->max_dma_len)
@@ -3045,7 +3040,7 @@ void spi_unregister_controller(struct spi_controller *ctlr)
 
 	/* Prevent addition of new devices, unregister existing ones */
 	if (IS_ENABLED(CONFIG_SPI_DYNAMIC))
-		mutex_lock(&spi_add_lock);
+		mutex_lock(&ctlr->add_lock);
 
 	device_for_each_child(&ctlr->dev, NULL, __unregister);
 
@@ -3076,7 +3071,7 @@ void spi_unregister_controller(struct spi_controller *ctlr)
 	mutex_unlock(&board_lock);
 
 	if (IS_ENABLED(CONFIG_SPI_DYNAMIC))
-		mutex_unlock(&spi_add_lock);
+		mutex_unlock(&ctlr->add_lock);
 }
 EXPORT_SYMBOL_GPL(spi_unregister_controller);
 
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 29e21d49aafc..5b61abe679f1 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -349,6 +349,7 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch
  * @max_message_size: function that returns the max message size for
  *	a &spi_device; may be %NULL, so the default %SIZE_MAX will be used.
  * @io_mutex: mutex for physical bus access
+ * @add_lock: mutex to avoid adding two devices on the same CS
  * @bus_lock_spinlock: spinlock for SPI bus locking
  * @bus_lock_mutex: mutex for exclusion of multiple callers
  * @bus_lock_flag: indicates that the SPI bus is locked for exclusive use
@@ -527,6 +528,9 @@ struct spi_controller {
 	/* I/O mutex */
 	struct mutex		io_mutex;
 
+	/* Used to avoid adding two devices on the same CS line */
+	struct mutex		add_lock;
+
 	/* lock and mutex for SPI bus locking */
 	spinlock_t		bus_lock_spinlock;
 	struct mutex		bus_lock_mutex;

base-commit: da21fde0fdb393c2fbe0ae0735cc826cd55fd46f
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/2] spi-mux: Fix false-positive lockdep splats
  2021-10-13 13:37 [PATCH 1/2] spi: Make spi_add_lock a per-controller lock Uwe Kleine-König
@ 2021-10-13 13:37 ` Uwe Kleine-König
  2021-10-13 15:21 ` [PATCH 1/2] spi: Make spi_add_lock a per-controller lock Mark Brown
  2021-10-14 13:18 ` (subset) " Mark Brown
  2 siblings, 0 replies; 6+ messages in thread
From: Uwe Kleine-König @ 2021-10-13 13:37 UTC (permalink / raw)
  To: Mark Brown; +Cc: kernel, linux-spi

io_mutex is taken by spi_setup() and spi-mux's .setup() callback calls
spi_setup() which results in a nested lock of io_mutex.

add_lock is taken by spi_add_device(). The device_add() call in there
can result in calling spi-mux's .probe() callback which registers its
own spi controller which in turn results in spi_add_device() being
called again.

To fix this initialize the controller's locks already in
spi_alloc_controller() to give spi_mux_probe() a chance to set the
lockdep subclass.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/spi/spi-mux.c |  7 +++++++
 drivers/spi/spi.c     | 12 ++++++------
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/drivers/spi/spi-mux.c b/drivers/spi/spi-mux.c
index 9708b7827ff7..f5d32ec4634e 100644
--- a/drivers/spi/spi-mux.c
+++ b/drivers/spi/spi-mux.c
@@ -137,6 +137,13 @@ static int spi_mux_probe(struct spi_device *spi)
 	priv = spi_controller_get_devdata(ctlr);
 	priv->spi = spi;
 
+	/*
+	 * Increase lockdep class as these lock are taken while the parent bus
+	 * already holds their instance's lock.
+	 */
+	lockdep_set_subclass(&ctlr->io_mutex, 1);
+	lockdep_set_subclass(&ctlr->add_lock, 1);
+
 	priv->mux = devm_mux_control_get(&spi->dev, NULL);
 	if (IS_ERR(priv->mux)) {
 		ret = dev_err_probe(&spi->dev, PTR_ERR(priv->mux),
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 193e3264f7eb..72826bdab270 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -2626,6 +2626,12 @@ struct spi_controller *__spi_alloc_controller(struct device *dev,
 		return NULL;
 
 	device_initialize(&ctlr->dev);
+	INIT_LIST_HEAD(&ctlr->queue);
+	spin_lock_init(&ctlr->queue_lock);
+	spin_lock_init(&ctlr->bus_lock_spinlock);
+	mutex_init(&ctlr->bus_lock_mutex);
+	mutex_init(&ctlr->io_mutex);
+	mutex_init(&ctlr->add_lock);
 	ctlr->bus_num = -1;
 	ctlr->num_chipselect = 1;
 	ctlr->slave = slave;
@@ -2898,12 +2904,6 @@ int spi_register_controller(struct spi_controller *ctlr)
 			return id;
 		ctlr->bus_num = id;
 	}
-	INIT_LIST_HEAD(&ctlr->queue);
-	spin_lock_init(&ctlr->queue_lock);
-	spin_lock_init(&ctlr->bus_lock_spinlock);
-	mutex_init(&ctlr->bus_lock_mutex);
-	mutex_init(&ctlr->io_mutex);
-	mutex_init(&ctlr->add_lock);
 	ctlr->bus_lock_flag = 0;
 	init_completion(&ctlr->xfer_completion);
 	if (!ctlr->max_dma_len)
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/2] spi: Make spi_add_lock a per-controller lock
  2021-10-13 13:37 [PATCH 1/2] spi: Make spi_add_lock a per-controller lock Uwe Kleine-König
  2021-10-13 13:37 ` [PATCH 2/2] spi-mux: Fix false-positive lockdep splats Uwe Kleine-König
@ 2021-10-13 15:21 ` Mark Brown
  2021-10-13 16:10   ` Uwe Kleine-König
  2021-10-14 13:18 ` (subset) " Mark Brown
  2 siblings, 1 reply; 6+ messages in thread
From: Mark Brown @ 2021-10-13 15:21 UTC (permalink / raw)
  To: Uwe Kleine-König; +Cc: kernel, linux-spi

[-- Attachment #1: Type: text/plain, Size: 694 bytes --]

On Wed, Oct 13, 2021 at 03:37:09PM +0200, Uwe Kleine-König wrote:
> The spi_add_lock that is removed with this change was held when
> spi_add_device() called device_add() (via __spi_add_device()).
> 
> In the case where the added device is an spi-mux calling device_add()
> might result in calling the spi-mux's probe function which adds another
> controller and for that spi_add_device() might be called. This results
> in a dead-lock.
> 
> To circumvent this deadlock replace the global spi_add_lock with a lock
> per controller.
> 
> The biggest part of this patch was authored by Mark Brown.

I'll go ahead with my copy of this (partly as I've already got it
ready queued).

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/2] spi: Make spi_add_lock a per-controller lock
  2021-10-13 15:21 ` [PATCH 1/2] spi: Make spi_add_lock a per-controller lock Mark Brown
@ 2021-10-13 16:10   ` Uwe Kleine-König
  2021-10-13 17:22     ` Mark Brown
  0 siblings, 1 reply; 6+ messages in thread
From: Uwe Kleine-König @ 2021-10-13 16:10 UTC (permalink / raw)
  To: Mark Brown; +Cc: kernel, linux-spi

[-- Attachment #1: Type: text/plain, Size: 1218 bytes --]

Hello Mark,

On Wed, Oct 13, 2021 at 04:21:37PM +0100, Mark Brown wrote:
> On Wed, Oct 13, 2021 at 03:37:09PM +0200, Uwe Kleine-König wrote:
> > The spi_add_lock that is removed with this change was held when
> > spi_add_device() called device_add() (via __spi_add_device()).
> > 
> > In the case where the added device is an spi-mux calling device_add()
> > might result in calling the spi-mux's probe function which adds another
> > controller and for that spi_add_device() might be called. This results
> > in a dead-lock.
> > 
> > To circumvent this deadlock replace the global spi_add_lock with a lock
> > per controller.
> > 
> > The biggest part of this patch was authored by Mark Brown.
> 
> I'll go ahead with my copy of this (partly as I've already got it
> ready queued).

That's what I expected, I just sent it that the base for patch 2 is
properly available e.g. for the autobuilders. Did you modify your patch
since you sent it? If you resend or apply to your tree I can rebase
patch 2 on top of it.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | https://www.pengutronix.de/ |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/2] spi: Make spi_add_lock a per-controller lock
  2021-10-13 16:10   ` Uwe Kleine-König
@ 2021-10-13 17:22     ` Mark Brown
  0 siblings, 0 replies; 6+ messages in thread
From: Mark Brown @ 2021-10-13 17:22 UTC (permalink / raw)
  To: Uwe Kleine-König; +Cc: kernel, linux-spi

[-- Attachment #1: Type: text/plain, Size: 559 bytes --]

On Wed, Oct 13, 2021 at 06:10:33PM +0200, Uwe Kleine-König wrote:
> On Wed, Oct 13, 2021 at 04:21:37PM +0100, Mark Brown wrote:

> > I'll go ahead with my copy of this (partly as I've already got it
> > ready queued).

> That's what I expected, I just sent it that the base for patch 2 is
> properly available e.g. for the autobuilders. Did you modify your patch
> since you sent it? If you resend or apply to your tree I can rebase
> patch 2 on top of it.

It's rebased (actually the public post was rebased).  I'll let you know
if yours fails.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: (subset) [PATCH 1/2] spi: Make spi_add_lock a per-controller lock
  2021-10-13 13:37 [PATCH 1/2] spi: Make spi_add_lock a per-controller lock Uwe Kleine-König
  2021-10-13 13:37 ` [PATCH 2/2] spi-mux: Fix false-positive lockdep splats Uwe Kleine-König
  2021-10-13 15:21 ` [PATCH 1/2] spi: Make spi_add_lock a per-controller lock Mark Brown
@ 2021-10-14 13:18 ` Mark Brown
  2 siblings, 0 replies; 6+ messages in thread
From: Mark Brown @ 2021-10-14 13:18 UTC (permalink / raw)
  To: Uwe Kleine-König; +Cc: Mark Brown, linux-spi, kernel

On Wed, 13 Oct 2021 15:37:09 +0200, Uwe Kleine-König wrote:
> The spi_add_lock that is removed with this change was held when
> spi_add_device() called device_add() (via __spi_add_device()).
> 
> In the case where the added device is an spi-mux calling device_add()
> might result in calling the spi-mux's probe function which adds another
> controller and for that spi_add_device() might be called. This results
> in a dead-lock.
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next

Thanks!

[2/2] spi-mux: Fix false-positive lockdep splats
      commit: 16a8e2fbb2d49111004efc1c7342e083eafabeb0

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-10-14 13:18 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-13 13:37 [PATCH 1/2] spi: Make spi_add_lock a per-controller lock Uwe Kleine-König
2021-10-13 13:37 ` [PATCH 2/2] spi-mux: Fix false-positive lockdep splats Uwe Kleine-König
2021-10-13 15:21 ` [PATCH 1/2] spi: Make spi_add_lock a per-controller lock Mark Brown
2021-10-13 16:10   ` Uwe Kleine-König
2021-10-13 17:22     ` Mark Brown
2021-10-14 13:18 ` (subset) " Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).