Unverified Commit 16a8e2fb authored by Uwe Kleine-König's avatar Uwe Kleine-König Committed by Mark Brown
Browse files

spi-mux: Fix false-positive lockdep splats



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: default avatarUwe Kleine-König <u.kleine-koenig@pengutronix.de>
Link: https://lore.kernel.org/r/20211013133710.2679703-2-u.kleine-koenig@pengutronix.de


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 6098475d
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -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),
+6 −6
Original line number Diff line number Diff line
@@ -2547,6 +2547,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;
@@ -2819,12 +2825,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)