[PATCH v3 2/3] spi: atmel: Prevent false timeouts on long transfers

Ryan.Wanner at microchip.com Ryan.Wanner at microchip.com
Thu Jun 22 09:29:05 PDT 2023


On 6/22/23 02:06, Miquel Raynal wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> A slow SPI bus clocks at ~20MHz, which means it would transfer about
> 2500 bytes per second with a single data line. Big transfers, like when
> dealing with flashes can easily reach a few MiB. The current DMA timeout
> is set to 1 second, which means any working transfer of about 4MiB will
> always be cancelled.
> 
> With the above derivations, on a slow bus, we can assume every byte will
> take at most 0.4ms. Said otherwise, we could add 4ms to the 1-second
> timeout delay every 10kiB. On a 4MiB transfer, it would bring the
> timeout delay up to 2.6s which still seems rather acceptable for a
> timeout.
> 
> The consequence of this is that long transfers might be allowed, which
> hence requires the need to interrupt the transfer if wanted by the
> user. We can hence switch to the _interruptible variant of
> wait_for_completion. This leads to a little bit more handling to also
> handle the interrupted case but looks really acceptable overall.
> 
> While at it, we drop the useless, noisy and redundant WARN_ON() call.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
Acked-by: Ryan Wanner <ryan.wanner at microchip.com>
> ---
>  drivers/spi/spi-atmel.c | 18 +++++++++++-------
>  1 file changed, 11 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
> index 943548aab8af..d87be2890597 100644
> --- a/drivers/spi/spi-atmel.c
> +++ b/drivers/spi/spi-atmel.c
> @@ -233,7 +233,8 @@
>   */
>  #define DMA_MIN_BYTES  16
> 
> -#define SPI_DMA_TIMEOUT                (msecs_to_jiffies(1000))
> +#define SPI_DMA_MIN_TIMEOUT    (msecs_to_jiffies(1000))
> +#define SPI_DMA_TIMEOUT_PER_10K        (msecs_to_jiffies(4))
> 
>  #define AUTOSUSPEND_TIMEOUT    2000
> 
> @@ -1279,7 +1280,8 @@ static int atmel_spi_one_transfer(struct spi_controller *host,
>         struct atmel_spi_device *asd;
>         int                     timeout;
>         int                     ret;
> -       unsigned long           dma_timeout;
> +       unsigned int            dma_timeout;
> +       long                    ret_timeout;
> 
>         as = spi_controller_get_devdata(host);
> 
> @@ -1333,11 +1335,13 @@ static int atmel_spi_one_transfer(struct spi_controller *host,
>                         atmel_spi_unlock(as);
>                 }
> 
> -               dma_timeout = wait_for_completion_timeout(&as->xfer_completion,
> -                                                         SPI_DMA_TIMEOUT);
> -               if (WARN_ON(dma_timeout == 0)) {
> -                       dev_err(&spi->dev, "spi transfer timeout\n");
> -                       as->done_status = -EIO;
> +               dma_timeout = msecs_to_jiffies(spi_controller_xfer_timeout(host, xfer));
> +               ret_timeout = wait_for_completion_interruptible_timeout(&as->xfer_completion,
> +                                                                       dma_timeout);
> +               if (ret_timeout <= 0) {
> +                       dev_err(&spi->dev, "spi transfer %s\n",
> +                               !ret_timeout ? "timeout" : "canceled");
> +                       as->done_status = ret_timeout < 0 ? ret_timeout : -EIO;
>                 }
> 
>                 if (as->done_status)
> --
> 2.34.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel



More information about the linux-arm-kernel mailing list