spi-mux: Fix false-positive lockdep splats
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>
Wed, 13 Oct 2021 13:37:10 +0000 (15:37 +0200)
committerMark Brown <broonie@kernel.org>
Thu, 14 Oct 2021 12:32:19 +0000 (13:32 +0100)
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>
Link: https://lore.kernel.org/r/20211013133710.2679703-2-u.kleine-koenig@pengutronix.de
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi-mux.c
drivers/spi/spi.c

index 9708b78..f5d32ec 100644 (file)
@@ -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),
index 412a105..926b68a 100644 (file)
@@ -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)