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: 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>
This commit is contained in:
committed by
Mark Brown
parent
6098475d4c
commit
16a8e2fbb2
@@ -137,6 +137,13 @@ static int spi_mux_probe(struct spi_device *spi)
|
|||||||
priv = spi_controller_get_devdata(ctlr);
|
priv = spi_controller_get_devdata(ctlr);
|
||||||
priv->spi = spi;
|
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);
|
priv->mux = devm_mux_control_get(&spi->dev, NULL);
|
||||||
if (IS_ERR(priv->mux)) {
|
if (IS_ERR(priv->mux)) {
|
||||||
ret = dev_err_probe(&spi->dev, PTR_ERR(priv->mux),
|
ret = dev_err_probe(&spi->dev, PTR_ERR(priv->mux),
|
||||||
|
|||||||
@@ -2547,6 +2547,12 @@ struct spi_controller *__spi_alloc_controller(struct device *dev,
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
device_initialize(&ctlr->dev);
|
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->bus_num = -1;
|
||||||
ctlr->num_chipselect = 1;
|
ctlr->num_chipselect = 1;
|
||||||
ctlr->slave = slave;
|
ctlr->slave = slave;
|
||||||
@@ -2819,12 +2825,6 @@ int spi_register_controller(struct spi_controller *ctlr)
|
|||||||
return id;
|
return id;
|
||||||
ctlr->bus_num = 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;
|
ctlr->bus_lock_flag = 0;
|
||||||
init_completion(&ctlr->xfer_completion);
|
init_completion(&ctlr->xfer_completion);
|
||||||
if (!ctlr->max_dma_len)
|
if (!ctlr->max_dma_len)
|
||||||
|
|||||||
Reference in New Issue
Block a user