Re: [PATCH 1/3] spi: dw: Fix controller unregister order

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

 



On Mon, May 25, 2020 at 02:25:01PM +0200, Lukas Wunner wrote:
> The Designware SPI driver uses devm_spi_register_controller() on bind.
> As a consequence, on unbind, __device_release_driver() first invokes
> dw_spi_remove_host() before unregistering the SPI controller via
> devres_release_all().
> 
> This order is incorrect:  dw_spi_remove_host() shuts down the chip,
> rendering the SPI bus inaccessible even though the SPI controller is
> still registered.  When the SPI controller is subsequently unregistered,
> it unbinds all its slave devices.  Because their drivers cannot access
> the SPI bus, e.g. to quiesce interrupts, the slave devices may be left
> in an improper state.
> 
> As a rule, devm_spi_register_controller() must not be used if the
> ->remove() hook performs teardown steps which shall be performed after
> unregistering the controller and specifically after unbinding of slaves.
> 
> Fix by reverting to the non-devm variant of spi_register_controller().
> 
> An alternative approach would be to use device-managed functions for all
> steps in dw_spi_remove_host(), e.g. by calling devm_add_action_or_reset()
> on probe.  However that approach would add more LoC to the driver and
> it wouldn't lend itself as well to backporting to stable.

I think it's, unregistering controller first, proper way to quiescence it,
otherwise it can be a surprise transfer started while we are in removal stage.

Reviewed-by: Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx>

> 
> Fixes: 04f421e7b0b1 ("spi: dw: use managed resources")
> Signed-off-by: Lukas Wunner <lukas@xxxxxxxxx>
> Cc: stable@xxxxxxxxxxxxxxx # v3.14+
> Cc: Baruch Siach <baruch@xxxxxxxxxx>
> ---
>  drivers/spi/spi-dw.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c
> index 1edb8cdd11ee..9d6904d30104 100644
> --- a/drivers/spi/spi-dw.c
> +++ b/drivers/spi/spi-dw.c
> @@ -520,7 +520,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
>  		}
>  	}
>  
> -	ret = devm_spi_register_controller(dev, master);
> +	ret = spi_register_controller(master);
>  	if (ret) {
>  		dev_err(&master->dev, "problem registering spi master\n");
>  		goto err_dma_exit;
> @@ -544,6 +544,8 @@ void dw_spi_remove_host(struct dw_spi *dws)
>  {
>  	dw_spi_debugfs_remove(dws);
>  
> +	spi_unregister_controller(dws->master);
> +
>  	if (dws->dma_ops && dws->dma_ops->dma_exit)
>  		dws->dma_ops->dma_exit(dws);
>  
> -- 
> 2.25.0
> 

-- 
With Best Regards,
Andy Shevchenko





[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