From 596cad8231d8816e5f3d5d03cfb559e02a27120b Mon Sep 17 00:00:00 2001 From: Stefan Bigler Date: Mon, 19 Oct 2020 08:52:29 +0200 Subject: [PATCH] spi: fix locking for SPI_LOCK_ON using synchronous API Keep locking for SPI_LOCK_ON from the first call of transceive until spi_release release the lock. Use owner parameter to in the spi_context to store the owner of the lock. The locking is in line with the SPI_HOLD_ON_CS Signed-off-by: Stefan Bigler --- drivers/spi/spi_cc13xx_cc26xx.c | 2 +- drivers/spi/spi_context.h | 19 +++++++++++++++++-- drivers/spi/spi_dw.c | 2 +- drivers/spi/spi_ll_stm32.c | 4 ++-- drivers/spi/spi_mcux_dspi.c | 2 +- drivers/spi/spi_mcux_flexcomm.c | 2 +- drivers/spi/spi_mcux_lpspi.c | 2 +- drivers/spi/spi_nrfx_spi.c | 2 +- drivers/spi/spi_nrfx_spim.c | 2 +- drivers/spi/spi_nrfx_spis.c | 2 +- drivers/spi/spi_oc_simple.c | 2 +- drivers/spi/spi_rv32m1_lpspi.c | 2 +- drivers/spi/spi_sam.c | 2 +- drivers/spi/spi_sam0.c | 4 ++-- drivers/spi/spi_sifive.c | 2 +- drivers/spi/spi_xec_qmspi.c | 2 +- drivers/spi/spi_xlnx_axi_quadspi.c | 2 +- 17 files changed, 35 insertions(+), 20 deletions(-) diff --git a/drivers/spi/spi_cc13xx_cc26xx.c b/drivers/spi/spi_cc13xx_cc26xx.c index f7edb929b61..10e0fed2c67 100644 --- a/drivers/spi/spi_cc13xx_cc26xx.c +++ b/drivers/spi/spi_cc13xx_cc26xx.c @@ -146,7 +146,7 @@ static int spi_cc13xx_cc26xx_transceive(const struct device *dev, uint32_t txd, rxd; int err; - spi_context_lock(ctx, false, NULL); + spi_context_lock(ctx, false, NULL, config); #if defined(CONFIG_SYS_POWER_MANAGEMENT) && \ defined(CONFIG_SYS_POWER_SLEEP_STATES) diff --git a/drivers/spi/spi_context.h b/drivers/spi/spi_context.h index 2b78fc9956a..62805e93671 100644 --- a/drivers/spi/spi_context.h +++ b/drivers/spi/spi_context.h @@ -26,6 +26,7 @@ enum spi_ctx_runtime_op_mode { struct spi_context { const struct spi_config *config; + const struct spi_config *owner; struct k_sem lock; struct k_sem sync; @@ -69,9 +70,17 @@ static inline bool spi_context_is_slave(struct spi_context *ctx) static inline void spi_context_lock(struct spi_context *ctx, bool asynchronous, - struct k_poll_signal *signal) + struct k_poll_signal *signal, + const struct spi_config *spi_cfg) { + if ((spi_cfg->operation & SPI_LOCK_ON) && + (k_sem_count_get(&ctx->lock) == 0) && + (ctx->owner == spi_cfg)) { + return; + } + k_sem_take(&ctx->lock, K_FOREVER); + ctx->owner = spi_cfg; #ifdef CONFIG_SPI_ASYNC ctx->asynchronous = asynchronous; @@ -89,10 +98,14 @@ static inline void spi_context_release(struct spi_context *ctx, int status) #ifdef CONFIG_SPI_ASYNC if (!ctx->asynchronous || (status < 0)) { + ctx->owner = NULL; k_sem_give(&ctx->lock); } #else - k_sem_give(&ctx->lock); + if (!(ctx->config->operation & SPI_LOCK_ON)) { + ctx->owner = NULL; + k_sem_give(&ctx->lock); + } #endif /* CONFIG_SPI_ASYNC */ } @@ -138,6 +151,7 @@ static inline void spi_context_complete(struct spi_context *ctx, int status) } if (!(ctx->config->operation & SPI_LOCK_ON)) { + ctx->owner = NULL; k_sem_give(&ctx->lock); } } @@ -205,6 +219,7 @@ static inline void spi_context_unlock_unconditionally(struct spi_context *ctx) _spi_context_cs_control(ctx, false, true); if (!k_sem_count_get(&ctx->lock)) { + ctx->owner = NULL; k_sem_give(&ctx->lock); } } diff --git a/drivers/spi/spi_dw.c b/drivers/spi/spi_dw.c index 50327b59e71..4fdb1e0f4e8 100644 --- a/drivers/spi/spi_dw.c +++ b/drivers/spi/spi_dw.c @@ -342,7 +342,7 @@ static int transceive(const struct device *dev, uint32_t reg_data; int ret; - spi_context_lock(&spi->ctx, asynchronous, signal); + spi_context_lock(&spi->ctx, asynchronous, signal, config); #ifdef CONFIG_DEVICE_POWER_MANAGEMENT if (device_busy_check(dev) != (-EBUSY)) { diff --git a/drivers/spi/spi_ll_stm32.c b/drivers/spi/spi_ll_stm32.c index 4dd332d72ca..37dc1fa1138 100644 --- a/drivers/spi/spi_ll_stm32.c +++ b/drivers/spi/spi_ll_stm32.c @@ -575,7 +575,7 @@ static int transceive(const struct device *dev, } #endif - spi_context_lock(&data->ctx, asynchronous, signal); + spi_context_lock(&data->ctx, asynchronous, signal, config); ret = spi_stm32_configure(dev, config); if (ret) { @@ -671,7 +671,7 @@ static int transceive_dma(const struct device *dev, return -ENOTSUP; } - spi_context_lock(&data->ctx, asynchronous, signal); + spi_context_lock(&data->ctx, asynchronous, signal, config); k_sem_reset(&data->status_sem); diff --git a/drivers/spi/spi_mcux_dspi.c b/drivers/spi/spi_mcux_dspi.c index e214fe1197f..4759e2eac05 100644 --- a/drivers/spi/spi_mcux_dspi.c +++ b/drivers/spi/spi_mcux_dspi.c @@ -214,7 +214,7 @@ static int transceive(const struct device *dev, struct spi_mcux_data *data = dev->data; int ret; - spi_context_lock(&data->ctx, asynchronous, signal); + spi_context_lock(&data->ctx, asynchronous, signal, spi_cfg); ret = spi_mcux_configure(dev, spi_cfg); if (ret) { diff --git a/drivers/spi/spi_mcux_flexcomm.c b/drivers/spi/spi_mcux_flexcomm.c index 894ea85ccbf..3b05e213291 100644 --- a/drivers/spi/spi_mcux_flexcomm.c +++ b/drivers/spi/spi_mcux_flexcomm.c @@ -622,7 +622,7 @@ static int transceive(const struct device *dev, struct spi_mcux_data *data = dev->data; int ret; - spi_context_lock(&data->ctx, asynchronous, signal); + spi_context_lock(&data->ctx, asynchronous, signal, spi_cfg); ret = spi_mcux_configure(dev, spi_cfg); if (ret) { diff --git a/drivers/spi/spi_mcux_lpspi.c b/drivers/spi/spi_mcux_lpspi.c index 41017907bbc..0bf49d9e35b 100644 --- a/drivers/spi/spi_mcux_lpspi.c +++ b/drivers/spi/spi_mcux_lpspi.c @@ -213,7 +213,7 @@ static int transceive(const struct device *dev, struct spi_mcux_data *data = dev->data; int ret; - spi_context_lock(&data->ctx, asynchronous, signal); + spi_context_lock(&data->ctx, asynchronous, signal, spi_cfg); ret = spi_mcux_configure(dev, spi_cfg); if (ret) { diff --git a/drivers/spi/spi_nrfx_spi.c b/drivers/spi/spi_nrfx_spi.c index 174964b30f9..d3e09756e1a 100644 --- a/drivers/spi/spi_nrfx_spi.c +++ b/drivers/spi/spi_nrfx_spi.c @@ -180,7 +180,7 @@ static int transceive(const struct device *dev, struct spi_nrfx_data *dev_data = get_dev_data(dev); int error; - spi_context_lock(&dev_data->ctx, asynchronous, signal); + spi_context_lock(&dev_data->ctx, asynchronous, signal, spi_cfg); error = configure(dev, spi_cfg); if (error == 0) { diff --git a/drivers/spi/spi_nrfx_spim.c b/drivers/spi/spi_nrfx_spim.c index c03fb46e7cb..1f0f2636e7b 100644 --- a/drivers/spi/spi_nrfx_spim.c +++ b/drivers/spi/spi_nrfx_spim.c @@ -222,7 +222,7 @@ static int transceive(const struct device *dev, struct spi_nrfx_data *dev_data = get_dev_data(dev); int error; - spi_context_lock(&dev_data->ctx, asynchronous, signal); + spi_context_lock(&dev_data->ctx, asynchronous, signal, spi_cfg); error = configure(dev, spi_cfg); if (error == 0) { diff --git a/drivers/spi/spi_nrfx_spis.c b/drivers/spi/spi_nrfx_spis.c index 32e9389ea32..8a0b0e516bb 100644 --- a/drivers/spi/spi_nrfx_spis.c +++ b/drivers/spi/spi_nrfx_spis.c @@ -151,7 +151,7 @@ static int transceive(const struct device *dev, struct spi_nrfx_data *dev_data = get_dev_data(dev); int error; - spi_context_lock(&dev_data->ctx, asynchronous, signal); + spi_context_lock(&dev_data->ctx, asynchronous, signal, spi_cfg); error = configure(dev, spi_cfg); if (error != 0) { diff --git a/drivers/spi/spi_oc_simple.c b/drivers/spi/spi_oc_simple.c index eb44c5cd938..87ee8f6dc0b 100644 --- a/drivers/spi/spi_oc_simple.c +++ b/drivers/spi/spi_oc_simple.c @@ -100,7 +100,7 @@ int spi_oc_simple_transceive(const struct device *dev, int rc; /* Lock the SPI Context */ - spi_context_lock(ctx, false, NULL); + spi_context_lock(ctx, false, NULL, config); spi_oc_simple_configure(info, spi, config); diff --git a/drivers/spi/spi_rv32m1_lpspi.c b/drivers/spi/spi_rv32m1_lpspi.c index 139da58f4c0..233998b43f9 100644 --- a/drivers/spi/spi_rv32m1_lpspi.c +++ b/drivers/spi/spi_rv32m1_lpspi.c @@ -210,7 +210,7 @@ static int transceive(const struct device *dev, struct spi_mcux_data *data = dev->data; int ret; - spi_context_lock(&data->ctx, asynchronous, signal); + spi_context_lock(&data->ctx, asynchronous, signal, spi_cfg); ret = spi_mcux_configure(dev, spi_cfg); if (ret) { diff --git a/drivers/spi/spi_sam.c b/drivers/spi/spi_sam.c index 77642eac0aa..b4f42e992bf 100644 --- a/drivers/spi/spi_sam.c +++ b/drivers/spi/spi_sam.c @@ -366,7 +366,7 @@ static int spi_sam_transceive(const struct device *dev, Spi *regs = cfg->regs; int err; - spi_context_lock(&data->ctx, false, NULL); + spi_context_lock(&data->ctx, false, NULL, config); err = spi_sam_configure(dev, config); if (err != 0) { diff --git a/drivers/spi/spi_sam0.c b/drivers/spi/spi_sam0.c index 5a860bbc5bc..daecdfd4334 100644 --- a/drivers/spi/spi_sam0.c +++ b/drivers/spi/spi_sam0.c @@ -396,7 +396,7 @@ static int spi_sam0_transceive(const struct device *dev, SercomSpi *regs = cfg->regs; int err; - spi_context_lock(&data->ctx, false, NULL); + spi_context_lock(&data->ctx, false, NULL, config); err = spi_sam0_configure(dev, config); if (err != 0) { @@ -638,7 +638,7 @@ static int spi_sam0_transceive_async(const struct device *dev, return -ENOTSUP; } - spi_context_lock(&data->ctx, true, async); + spi_context_lock(&data->ctx, true, async, config); retval = spi_sam0_configure(dev, config); if (retval != 0) { diff --git a/drivers/spi/spi_sifive.c b/drivers/spi/spi_sifive.c index 43d5c3ba942..b2393dbe2b2 100644 --- a/drivers/spi/spi_sifive.c +++ b/drivers/spi/spi_sifive.c @@ -168,7 +168,7 @@ int spi_sifive_transceive(const struct device *dev, bool hw_cs_control = false; /* Lock the SPI Context */ - spi_context_lock(&SPI_DATA(dev)->ctx, false, NULL); + spi_context_lock(&SPI_DATA(dev)->ctx, false, NULL, config); /* Configure the SPI bus */ SPI_DATA(dev)->ctx.config = config; diff --git a/drivers/spi/spi_xec_qmspi.c b/drivers/spi/spi_xec_qmspi.c index 54fcad435cf..dd321ccea84 100644 --- a/drivers/spi/spi_xec_qmspi.c +++ b/drivers/spi/spi_xec_qmspi.c @@ -517,7 +517,7 @@ static int qmspi_transceive(const struct device *dev, uint32_t descr, last_didx; int err; - spi_context_lock(&data->ctx, false, NULL); + spi_context_lock(&data->ctx, false, NULL, config); err = qmspi_configure(dev, config); if (err != 0) { diff --git a/drivers/spi/spi_xlnx_axi_quadspi.c b/drivers/spi/spi_xlnx_axi_quadspi.c index da88234fe32..23c0c18d62d 100644 --- a/drivers/spi/spi_xlnx_axi_quadspi.c +++ b/drivers/spi/spi_xlnx_axi_quadspi.c @@ -321,7 +321,7 @@ static int xlnx_quadspi_transceive(const struct device *dev, struct spi_context *ctx = &data->ctx; int ret; - spi_context_lock(ctx, async, signal); + spi_context_lock(ctx, async, signal, spi_cfg); ret = xlnx_quadspi_configure(dev, spi_cfg); if (ret) {