Re: [PATCH 2/2] spi: fsl-qspi: Explicitly unregister SPI host in remove()

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

 



On 25/03/21 08:40PM, Kevin Hao wrote:
> 
> Currently, the SPI host is registered using a managed API, which
> automatically unregisters it when the device is detached from its driver.
> However, this unregistration occurs after the driver's remove() callback.
> 
> Since the host is already disabled inside the remove(), any pending IO
> from child devices can easily corrupt the kernel.
> 
> For example, the following steps on an imx8mq-evk board can trigger a
> kernel panic:
>   while true; do cat /dev/mtd0 >/dev/null; done &
>   echo 30bb0000.spi >/sys/bus/platform/drivers/fsl-quadspi/unbind
> 
> To fix this, explicitly call spi_unregister_controller() in the
> remove() callback. This ensures that all child devices are properly
> removed before the host is disabled.

If you explicitly remove the child devices, such as 
cd /sys/bus/spi/drivers/spi-nor
echo spi0.0 > unbind
then unbind the fsl-quadspi driver, the kernel panic does not occur.

Not sure if it should be the responsibility of the fsl-quadspi driver to handle
this, IMO it is a common issue with all SPI drivers.

> 
> Cc: stable@xxxxxxxxxxxxxxx
> Fixes: 8fcb830a00f0 ("spi: spi-fsl-qspi: use devm_spi_register_controller")
> Signed-off-by: Kevin Hao <haokexin@xxxxxxxxx>
> ---
>  drivers/spi/spi-fsl-qspi.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/spi/spi-fsl-qspi.c b/drivers/spi/spi-fsl-qspi.c
> index efd87f44c63a5b12b76538aa459ca8eb203b9dcd..4767d2085510c2f231476ba75e46f83271c4c645 100644
> --- a/drivers/spi/spi-fsl-qspi.c
> +++ b/drivers/spi/spi-fsl-qspi.c
> @@ -272,6 +272,7 @@ struct fsl_qspi {
>         struct device *dev;
>         int selected;
>         u32 memmap_phy;
> +       struct spi_controller *host;
>  };
> 
>  static inline int needs_swap_endian(struct fsl_qspi *q)
> @@ -862,6 +863,7 @@ static int fsl_qspi_probe(struct platform_device *pdev)
> 
>         q = spi_controller_get_devdata(ctlr);
>         q->dev = dev;
> +       q->host = ctlr;
>         q->devtype_data = of_device_get_match_data(dev);
>         if (!q->devtype_data) {
>                 ret = -ENODEV;
> @@ -934,7 +936,7 @@ static int fsl_qspi_probe(struct platform_device *pdev)
> 
>         ctlr->dev.of_node = np;
> 
> -       ret = devm_spi_register_controller(dev, ctlr);
> +       ret = spi_register_controller(ctlr);
>         if (ret)
>                 goto err_destroy_mutex;
> 
> @@ -957,6 +959,8 @@ static void fsl_qspi_remove(struct platform_device *pdev)
>  {
>         struct fsl_qspi *q = platform_get_drvdata(pdev);
> 
> +       spi_unregister_controller(q->host);
> +
>         /* disable the hardware */
>         qspi_writel(q, QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR);
>         qspi_writel(q, 0x0, q->iobase + QUADSPI_RSER);
> 
> --
> 2.48.1
> 




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux