From fa2d1ea42271b81b04e64b2fa73d6ebbbc563294 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Thu, 11 Mar 2021 11:01:42 +0530 Subject: [PATCH] drivers: spi: Use timeout for transfer completion Instead of waiting forever for the SPI transfer to complete, let's use a timeout value and bail out if elapsed. The timeout value logic is, xfer_len/frequency + tolerance Tolerance value can be modified using a Kconfig symbol, CONFIG_SPI_COMPLETION_TIMEOUT_TOLERANCE. It defaults to 200ms. Fixes: #33192 Signed-off-by: Manivannan Sadhasivam --- drivers/spi/Kconfig | 6 ++++++ drivers/spi/spi_context.h | 16 ++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index e069b471928..679aa9c7f7b 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -31,6 +31,12 @@ config SPI_INIT_PRIORITY help Device driver initialization priority. +config SPI_COMPLETION_TIMEOUT_TOLERANCE + int "Completion timeout tolerance (ms)" + default 200 + help + The tolerance value in ms for the SPI completion timeout logic. + module = SPI module-str = spi source "subsys/logging/Kconfig.template.log_config" diff --git a/drivers/spi/spi_context.h b/drivers/spi/spi_context.h index 62805e93671..d899f4f6b70 100644 --- a/drivers/spi/spi_context.h +++ b/drivers/spi/spi_context.h @@ -112,13 +112,25 @@ static inline void spi_context_release(struct spi_context *ctx, int status) static inline int spi_context_wait_for_completion(struct spi_context *ctx) { int status = 0; + uint32_t timeout_ms; + + timeout_ms = MAX(ctx->tx_len, ctx->rx_len) * 8 * 1000 / + ctx->config->frequency; + timeout_ms += CONFIG_SPI_COMPLETION_TIMEOUT_TOLERANCE; + #ifdef CONFIG_SPI_ASYNC if (!ctx->asynchronous) { - k_sem_take(&ctx->sync, K_FOREVER); + if (k_sem_take(&ctx->sync, K_MSEC(timeout_ms))) { + LOG_ERR("Timeout waiting for transfer complete"); + return -ETIMEDOUT; + } status = ctx->sync_status; } #else - k_sem_take(&ctx->sync, K_FOREVER); + if (k_sem_take(&ctx->sync, K_MSEC(timeout_ms))) { + LOG_ERR("Timeout waiting for transfer complete"); + return -ETIMEDOUT; + } status = ctx->sync_status; #endif /* CONFIG_SPI_ASYNC */