Re: [PATCH] spi: Fix deadlock when adding SPI controllers on SPI buses

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Oct 13, 2021 at 01:26:28PM +0100, Mark Brown wrote:
> Currently we have a global spi_add_lock which we take when adding new
> devices so that we can check that we're not trying to reuse a chip
> select that's already controlled.  This means that if the SPI device is
> itself a SPI controller and triggers the instantiation of further SPI
> devices we trigger a deadlock as we try to register and instantiate
> those devices while in the process of doing so for the parent controller
> and hence already holding the global spi_add_lock.  Since we only care
> about concurrency within a single SPI bus move the lock to be per
> controller, avoiding the deadlock.
> 
> This can be easily triggered in the case of spi-mux.
> 
> Reported-by: Uwe Kleine-König <u.kleine-koenig@xxxxxxxxxxxxxx>
> Signed-off-by: Mark Brown <broonie@xxxxxxxxxx>
> ---
>  drivers/spi/spi.c       | 21 ++++++++++-----------
>  include/linux/spi/spi.h |  3 +++
>  2 files changed, 13 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
> index 401f62f6f5b5..71d061132ada 100644
> --- a/drivers/spi/spi.c
> +++ b/drivers/spi/spi.c
> @@ -518,12 +518,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
> @@ -676,9 +670,13 @@ static int spi_add_device(struct spi_device *spi)
>  	/* Set the bus ID string */
>  	spi_dev_set_name(spi);
>  
> -	mutex_lock(&spi_add_lock);
> +	/* We need to make sure there's no other device with this
> +	 * chipselect **BEFORE** we call setup(), else we'll trash
> +	 * its configuration.  Lock against concurrent add() calls.
> +	 */

This comment is already there, it seems you duplicated it with your
patch? Maybe a merge issue with
6bfb15f34dd8c8a073e03a31c485ef5774b127df?

> +	mutex_lock(&ctlr->add_lock);
>  	status = __spi_add_device(spi);
> -	mutex_unlock(&spi_add_lock);
> +	mutex_unlock(&ctlr->add_lock);
>  	return status;
>  }
>  
> @@ -697,7 +695,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);
>  }
>  
> @@ -2950,6 +2948,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)
> @@ -3086,7 +3085,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);
>  
> @@ -3117,7 +3116,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..eb7ac8a1e03c 100644
> --- a/include/linux/spi/spi.h
> +++ b/include/linux/spi/spi.h
> @@ -527,6 +527,9 @@ struct spi_controller {
>  	/* I/O mutex */
>  	struct mutex		io_mutex;
>  
> +	/* Used to avoid adding the same CS twice */
> +	struct mutex		add_lock;
> +

Kernel-doc is missing for that one.

(In the local patch I have for testing here, I wrote:

	* @add_lock: mutex to avoid adding two devices on the same CS

.)

Best regards
Uwe

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

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux