| From 6aae87fe7f180cd93a74466cdb6cf2aa9bb28798 Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Goffic?= <clement.legoffic@foss.st.com> |
| Date: Fri, 4 Jul 2025 10:39:15 +0200 |
| Subject: i2c: stm32f7: unmap DMA mapped buffer |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Clément Le Goffic <clement.legoffic@foss.st.com> |
| |
| commit 6aae87fe7f180cd93a74466cdb6cf2aa9bb28798 upstream. |
| |
| Before each I2C transfer using DMA, the I2C buffer is DMA'pped to make |
| sure the memory buffer is DMA'able. This is handle in the function |
| `stm32_i2c_prep_dma_xfer()`. |
| If the transfer fails for any reason the I2C buffer must be unmap. |
| Use the dma_callback to factorize the code and fix this issue. |
| |
| Note that the `stm32f7_i2c_dma_callback()` is now called in case of DMA |
| transfer success and error and that the `complete()` on the dma_complete |
| completion structure is done inconditionnally in case of transfer |
| success or error as well as the `dmaengine_terminate_async()`. |
| This is allowed as a `complete()` in case transfer error has no effect |
| as well as a `dmaengine_terminate_async()` on a transfer success. |
| |
| Also fix the unneeded cast and remove not more needed variables. |
| |
| Fixes: 7ecc8cfde553 ("i2c: i2c-stm32f7: Add DMA support") |
| Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com> |
| Cc: <stable@vger.kernel.org> # v4.18+ |
| Acked-by: Alain Volmat <alain.volmat@foss.st.com> |
| Signed-off-by: Andi Shyti <andi.shyti@kernel.org> |
| Link: https://lore.kernel.org/r/20250704-i2c-upstream-v4-2-84a095a2c728@foss.st.com |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/i2c/busses/i2c-stm32f7.c | 20 +++++++------------- |
| 1 file changed, 7 insertions(+), 13 deletions(-) |
| |
| --- a/drivers/i2c/busses/i2c-stm32f7.c |
| +++ b/drivers/i2c/busses/i2c-stm32f7.c |
| @@ -739,10 +739,11 @@ static void stm32f7_i2c_disable_dma_req( |
| |
| static void stm32f7_i2c_dma_callback(void *arg) |
| { |
| - struct stm32f7_i2c_dev *i2c_dev = (struct stm32f7_i2c_dev *)arg; |
| + struct stm32f7_i2c_dev *i2c_dev = arg; |
| struct stm32_i2c_dma *dma = i2c_dev->dma; |
| |
| stm32f7_i2c_disable_dma_req(i2c_dev); |
| + dmaengine_terminate_async(dma->chan_using); |
| dma_unmap_single(i2c_dev->dev, dma->dma_buf, dma->dma_len, |
| dma->dma_data_dir); |
| complete(&dma->dma_complete); |
| @@ -1510,7 +1511,6 @@ static irqreturn_t stm32f7_i2c_handle_is |
| u16 addr = f7_msg->addr; |
| void __iomem *base = i2c_dev->base; |
| struct device *dev = i2c_dev->dev; |
| - struct stm32_i2c_dma *dma = i2c_dev->dma; |
| |
| /* Bus error */ |
| if (status & STM32F7_I2C_ISR_BERR) { |
| @@ -1551,10 +1551,8 @@ static irqreturn_t stm32f7_i2c_handle_is |
| } |
| |
| /* Disable dma */ |
| - if (i2c_dev->use_dma) { |
| - stm32f7_i2c_disable_dma_req(i2c_dev); |
| - dmaengine_terminate_async(dma->chan_using); |
| - } |
| + if (i2c_dev->use_dma) |
| + stm32f7_i2c_dma_callback(i2c_dev); |
| |
| i2c_dev->master_mode = false; |
| complete(&i2c_dev->complete); |
| @@ -1600,7 +1598,6 @@ static irqreturn_t stm32f7_i2c_isr_event |
| { |
| struct stm32f7_i2c_dev *i2c_dev = data; |
| struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg; |
| - struct stm32_i2c_dma *dma = i2c_dev->dma; |
| void __iomem *base = i2c_dev->base; |
| u32 status, mask; |
| int ret; |
| @@ -1619,10 +1616,8 @@ static irqreturn_t stm32f7_i2c_isr_event |
| dev_dbg(i2c_dev->dev, "<%s>: Receive NACK (addr %x)\n", |
| __func__, f7_msg->addr); |
| writel_relaxed(STM32F7_I2C_ICR_NACKCF, base + STM32F7_I2C_ICR); |
| - if (i2c_dev->use_dma) { |
| - stm32f7_i2c_disable_dma_req(i2c_dev); |
| - dmaengine_terminate_async(dma->chan_using); |
| - } |
| + if (i2c_dev->use_dma) |
| + stm32f7_i2c_dma_callback(i2c_dev); |
| f7_msg->result = -ENXIO; |
| } |
| |
| @@ -1640,8 +1635,7 @@ static irqreturn_t stm32f7_i2c_isr_event |
| ret = wait_for_completion_timeout(&i2c_dev->dma->dma_complete, HZ); |
| if (!ret) { |
| dev_dbg(i2c_dev->dev, "<%s>: Timed out\n", __func__); |
| - stm32f7_i2c_disable_dma_req(i2c_dev); |
| - dmaengine_terminate_async(dma->chan_using); |
| + stm32f7_i2c_dma_callback(i2c_dev); |
| f7_msg->result = -ETIMEDOUT; |
| } |
| } |