FAILED: patch "[PATCH] i2c: stm32f7: unmap DMA mapped buffer" failed to apply to 6.6-stable tree
[email protected]
maintainerThe patch below does not apply to the 6.6-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.6.y
git checkout FETCH_HEAD
git cherry-pick -x 6aae87fe7f180cd93a74466cdb6cf2aa9bb28798
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2025072104-bacteria-resend-dcff@gregkh' --subject-prefix 'PATCH 6.6.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 6aae87fe7f180cd93a74466cdb6cf2aa9bb28798 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20Le=20Goffic?= <[email protected]>
Date: Fri, 4 Jul 2025 10:39:15 +0200
Subject: [PATCH] i2c: stm32f7: unmap DMA mapped buffer
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
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.
drivers/i2c/busses/i2c-stm32f7.c +7 -13
@@ -739,10 +739,11 @@ static void stm32f7_i2c_disable_dma_req(struct stm32f7_i2c_dev *i2c_dev)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_isr_errs(struct stm32f7_i2c_dev *i2c_dev,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_isr_errs(struct stm32f7_i2c_dev *i2c_dev, }/* 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_thread(int irq, void *data) {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_thread(int irq, void *data)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_thread(int irq, void *data) 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 ; } }
Sasha Levin
maintainerPATCH 1/6 i2c: stm32f7: Use devm_clk_get_enabled()
From: Andi Shyti <[email protected]>
[ Upstream commit 7ba2b17a87466e1410ae0ccc94d8eb381de177c2 ]
Replace the pair of functions, devm_clk_get() andclk_prepare_enable(), with a single functiondevm_clk_get_enabled().
Stable-dep-of: 6aae87fe7f18 ("i2c: stm32f7: unmap DMA mapped buffer")
--- drivers/i2c/busses/i2c-stm32f7.c | 37 +++++++++++--------------------- 1 file changed, 12 insertions(+), 25 deletions(-)
drivers/i2c/busses/i2c-stm32f7.c +12 -25
@@ -2177,23 +2177,16 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) i2c_dev->wakeup_src =of_property_read_bool (pdev->dev.of_node,"wakeup-source" ); - i2c_dev->clk =devm_clk_get (&pdev->dev,NULL ); + i2c_dev->clk =devm_clk_get_enabled (&pdev->dev,NULL );if (IS_ERR (i2c_dev->clk))return dev_err_probe (&pdev->dev,PTR_ERR (i2c_dev->clk), -"Failed to get controller clock\n" ); - - ret =clk_prepare_enable (i2c_dev->clk); -if (ret) { -dev_err (&pdev->dev,"Failed to prepare_enable clock\n" ); -return ret; - } +"Failed to enable controller clock\n" ); rst =devm_reset_control_get (&pdev->dev,NULL ); -if (IS_ERR (rst)) { - ret =dev_err_probe (&pdev->dev,PTR_ERR (rst), -"Error: Missing reset ctrl\n" ); - goto clk_free; - } +if (IS_ERR (rst)) +return dev_err_probe (&pdev->dev,PTR_ERR (rst), +"Error: Missing reset ctrl\n" ); +reset_control_assert (rst);udelay (2 );reset_control_deassert (rst);
@@ -2208,7 +2201,7 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)if (ret) {dev_err (&pdev->dev,"Failed to request irq event %i\n" , irq_event); - goto clk_free; +return ret; } ret = devm_request_irq(&pdev->dev, irq_error, stm32f7_i2c_isr_error, 0,
@@ -2216,29 +2209,28 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)if (ret) {dev_err (&pdev->dev,"Failed to request irq error %i\n" , irq_error); - goto clk_free; +return ret; } setup =of_device_get_match_data (&pdev->dev);if (!setup) {dev_err (&pdev->dev,"Can't get device data\n" ); - ret = -ENODEV ; - goto clk_free; +return -ENODEV ; } i2c_dev->setup = *setup; ret =stm32f7_i2c_setup_timing (i2c_dev, &i2c_dev->setup);if (ret) - goto clk_free; +return ret;/* Setup Fast mode plus if necessary */ if (i2c_dev->bus_rate >I2C_MAX_FAST_MODE_FREQ ) { ret =stm32f7_i2c_setup_fm_plus_bits (pdev, i2c_dev);if (ret) - goto clk_free; +return ret; ret =stm32f7_i2c_write_fm_plus_bits (i2c_dev, true);if (ret) - goto clk_free; +return ret; } adap = &i2c_dev->adap;
@@ -2349,9 +2341,6 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) fmp_clear:stm32f7_i2c_write_fm_plus_bits (i2c_dev, false); -clk_free: -clk_disable_unprepare (i2c_dev->clk); -return ret; }
@@ -2385,8 +2374,6 @@ static void stm32f7_i2c_remove(struct platform_device *pdev) }stm32f7_i2c_write_fm_plus_bits (i2c_dev, false); - -clk_disable_unprepare (i2c_dev->clk); }static int __maybe_unused stm32f7_i2c_runtime_suspend (struct device *dev)
Signature · 1 line
2.39.5
Sasha Levin
maintainerPATCH 2/6 i2c: stm32f7: use dev_err_probe upon calls of devm_request_irq
From: Alain Volmat <[email protected]>
[ Upstream commit a51e224c2f42417e95a3e1a672ade221bcd006ba ]
Convert error handling upon calls of devm_request_irq functions during the probe of the driver.
Stable-dep-of: 6aae87fe7f18 ("i2c: stm32f7: unmap DMA mapped buffer")
--- drivers/i2c/busses/i2c-stm32f7.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-)
drivers/i2c/busses/i2c-stm32f7.c +4 -10
@@ -2198,19 +2198,13 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) stm32f7_i2c_isr_event_thread,IRQF_ONESHOT , pdev->name, i2c_dev); -if (ret) { -dev_err (&pdev->dev,"Failed to request irq event %i\n" , - irq_event); -return ret; - } +if (ret) +return dev_err_probe (&pdev->dev, ret,"Failed to request irq event\n" ); ret =devm_request_irq (&pdev->dev, irq_error, stm32f7_i2c_isr_error,0 , pdev->name, i2c_dev); -if (ret) { -dev_err (&pdev->dev,"Failed to request irq error %i\n" , - irq_error); -return ret; - } +if (ret) +return dev_err_probe (&pdev->dev, ret,"Failed to request irq error\n" ); setup =of_device_get_match_data (&pdev->dev);if (!setup) {
Signature · 1 line
2.39.5
Sasha Levin
maintainerPATCH 3/6 i2c: stm32f7: perform most of irq job in threaded handler
In reply to Sasha LevinFrom: Alain Volmat <[email protected]>
[ Upstream commit e6103cd45ef0e14eb02f0666bc6b494902cfe821 ]
The irq handling is currently split between the irq handler and the threaded irq handler. Some of the handling (such as dma related stuffs) done within the irq handler might sleep or take some time leading to issues if the kernel is built with realtime constraints. In order to fix that, perform an overall rework to perform most of the job within the threaded handler and only keep fifo access in the non threaded handler.
Stable-dep-of: 6aae87fe7f18 ("i2c: stm32f7: unmap DMA mapped buffer")
--- drivers/i2c/busses/i2c-stm32f7.c | 126 ++++++++++++++----------------- 1 file changed, 56 insertions(+), 70 deletions(-)
drivers/i2c/busses/i2c-stm32f7.c +56 -70
@@ -1496,17 +1496,11 @@ static irqreturn_t stm32f7_i2c_slave_isr_event(struct stm32f7_i2c_dev *i2c_dev)static irqreturn_t stm32f7_i2c_isr_event (int irq,void *data) {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 =IRQ_HANDLED ; +u32 status; -/* Check if the interrupt if for a slave device */ -if (!i2c_dev->master_mode) { - ret =stm32f7_i2c_slave_isr_event (i2c_dev); -return ret; - } +/* Check if the interrupt is for a slave device */ +if (!i2c_dev->master_mode) +return IRQ_WAKE_THREAD ; status =readl_relaxed (i2c_dev->base +STM32F7_I2C_ISR );
@@ -1518,6 +1512,29 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)if (status &STM32F7_I2C_ISR_RXNE )stm32f7_i2c_read_rx_data (i2c_dev); +/* Wake up the thread if other flags are raised */ +if (status & + (STM32F7_I2C_ISR_NACKF |STM32F7_I2C_ISR_STOPF | +STM32F7_I2C_ISR_TC |STM32F7_I2C_ISR_TCR )) +return IRQ_WAKE_THREAD ; + +return IRQ_HANDLED ; +} + +static irqreturn_t stm32f7_i2c_isr_event_thread (int irq,void *data) +{ +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; + +if (!i2c_dev->master_mode) +return stm32f7_i2c_slave_isr_event (i2c_dev); + + status =readl_relaxed (i2c_dev->base +STM32F7_I2C_ISR ); +/* NACK received */ if (status &STM32F7_I2C_ISR_NACKF ) { dev_dbg(i2c_dev->dev, "<%s>: Receive NACK (addr %x)\n",
@@ -1530,33 +1547,28 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) f7_msg->result = -ENXIO ; } -/* STOP detection flag */ -if (status &STM32F7_I2C_ISR_STOPF ) { -/* Disable interrupts */ -if (stm32f7_i2c_is_slave_registered (i2c_dev)) - mask =STM32F7_I2C_XFER_IRQ_MASK ; +if (status &STM32F7_I2C_ISR_TCR ) { +if (f7_msg->smbus) +stm32f7_i2c_smbus_reload (i2c_dev);else - mask =STM32F7_I2C_ALL_IRQ_MASK ; -stm32f7_i2c_disable_irq (i2c_dev, mask); - -/* Clear STOP flag */ -writel_relaxed (STM32F7_I2C_ICR_STOPCF , base +STM32F7_I2C_ICR ); - -if (i2c_dev->use_dma && !f7_msg->result) { - ret =IRQ_WAKE_THREAD ; - }else { - i2c_dev->master_mode = false; -complete (&i2c_dev->complete); - } +stm32f7_i2c_reload (i2c_dev); }/* Transfer complete */ if (status &STM32F7_I2C_ISR_TC ) { +/* Wait for dma transfer completion before sending next message */ +if (i2c_dev->use_dma && !f7_msg->result) { + 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); + f7_msg->result = -ETIMEDOUT ; + } + }if (f7_msg->stop) { mask =STM32F7_I2C_CR2_STOP ;stm32f7_i2c_set_bits (base +STM32F7_I2C_CR2 , mask); - }else if (i2c_dev->use_dma && !f7_msg->result) { - ret =IRQ_WAKE_THREAD ; }else if (f7_msg->smbus) {stm32f7_i2c_smbus_rep_start (i2c_dev); }else {
@@ -1566,47 +1578,18 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) } } -if (status &STM32F7_I2C_ISR_TCR ) { -if (f7_msg->smbus) -stm32f7_i2c_smbus_reload (i2c_dev); +/* STOP detection flag */ +if (status &STM32F7_I2C_ISR_STOPF ) { +/* Disable interrupts */ +if (stm32f7_i2c_is_slave_registered (i2c_dev)) + mask =STM32F7_I2C_XFER_IRQ_MASK ;else -stm32f7_i2c_reload (i2c_dev); - } - -return ret; -} - -static irqreturn_t stm32f7_i2c_isr_event_thread (int irq,void *data) -{ -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; -u32 status; -int ret; - -/* -* Wait for dma transfer completion before sending next message or -* notity the end of xfer to the client -*/ - 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); - f7_msg->result = -ETIMEDOUT ; - } + mask =STM32F7_I2C_ALL_IRQ_MASK ; +stm32f7_i2c_disable_irq (i2c_dev, mask); - status =readl_relaxed (i2c_dev->base +STM32F7_I2C_ISR ); +/* Clear STOP flag */ +writel_relaxed (STM32F7_I2C_ICR_STOPCF , base +STM32F7_I2C_ICR ); -if (status &STM32F7_I2C_ISR_TC ) { -if (f7_msg->smbus) { -stm32f7_i2c_smbus_rep_start (i2c_dev); - }else { - i2c_dev->msg_id++; - i2c_dev->msg++; -stm32f7_i2c_xfer_msg (i2c_dev, i2c_dev->msg); - } - }else { i2c_dev->master_mode = false;complete (&i2c_dev->complete); }
@@ -1614,7 +1597,7 @@ static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data)return IRQ_HANDLED ; } -static irqreturn_t stm32f7_i2c_isr_error (int irq,void *data) +static irqreturn_t stm32f7_i2c_isr_error_thread (int irq,void *data) {struct stm32f7_i2c_dev *i2c_dev = data;struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
@@ -2201,8 +2184,11 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)if (ret)return dev_err_probe (&pdev->dev, ret,"Failed to request irq event\n" ); - ret =devm_request_irq (&pdev->dev, irq_error, stm32f7_i2c_isr_error,0 , - pdev->name, i2c_dev); + ret =devm_request_threaded_irq (&pdev->dev, irq_error, +NULL , + stm32f7_i2c_isr_error_thread, +IRQF_ONESHOT , + pdev->name, i2c_dev);if (ret)return dev_err_probe (&pdev->dev, ret,"Failed to request irq error\n" );
Signature · 1 line
2.39.5
Sasha Levin
maintainerPATCH 4/6 i2c: stm32f7: simplify status messages in case of errors
In reply to Sasha LevinFrom: Alain Volmat <[email protected]>
[ Upstream commit 33a00d919253022aabafecae6bc88a6fad446589 ]
Avoid usage of __func__ when reporting an error message since dev_err/dev_dbg are already providing enough details to identify the source of the message.
Stable-dep-of: 6aae87fe7f18 ("i2c: stm32f7: unmap DMA mapped buffer")
--- drivers/i2c/busses/i2c-stm32f7.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-)
drivers/i2c/busses/i2c-stm32f7.c +5 -7
@@ -1601,6 +1601,7 @@ static irqreturn_t stm32f7_i2c_isr_error_thread(int irq, void *data) {struct stm32f7_i2c_dev *i2c_dev = data;struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg; +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;
@@ -1610,8 +1611,7 @@ static irqreturn_t stm32f7_i2c_isr_error_thread(int irq, void *data)/* Bus error */ if (status &STM32F7_I2C_ISR_BERR ) { -dev_err (dev,"<%s>: Bus error accessing addr 0x%x\n" , - __func__, f7_msg->addr); +dev_err (dev,"Bus error accessing addr 0x%x\n" , addr);writel_relaxed (STM32F7_I2C_ICR_BERRCF , base +STM32F7_I2C_ICR );stm32f7_i2c_release_bus (&i2c_dev->adap); f7_msg->result = -EIO ;
@@ -1619,21 +1619,19 @@ static irqreturn_t stm32f7_i2c_isr_error_thread(int irq, void *data)/* Arbitration loss */ if (status &STM32F7_I2C_ISR_ARLO ) { -dev_dbg (dev,"<%s>: Arbitration loss accessing addr 0x%x\n" , - __func__, f7_msg->addr); +dev_dbg (dev,"Arbitration loss accessing addr 0x%x\n" , addr);writel_relaxed (STM32F7_I2C_ICR_ARLOCF , base +STM32F7_I2C_ICR ); f7_msg->result = -EAGAIN ; }if (status &STM32F7_I2C_ISR_PECERR ) { -dev_err (dev,"<%s>: PEC error in reception accessing addr 0x%x\n" , - __func__, f7_msg->addr); +dev_err (dev,"PEC error in reception accessing addr 0x%x\n" , addr);writel_relaxed (STM32F7_I2C_ICR_PECCF , base +STM32F7_I2C_ICR ); f7_msg->result = -EINVAL ; }if (status &STM32F7_I2C_ISR_ALERT ) { -dev_dbg (dev,"<%s>: SMBus alert received\n" , __func__); +dev_dbg (dev,"SMBus alert received\n" );writel_relaxed (STM32F7_I2C_ICR_ALERTCF , base +STM32F7_I2C_ICR );i2c_handle_smbus_alert (i2c_dev->alert->ara);return IRQ_HANDLED ;
Signature · 1 line
2.39.5
Sasha Levin
maintainerPATCH 5/6 i2c: stm32: fix the device used for the DMA map
In reply to Sasha LevinFrom: Clément Le Goffic <[email protected]>
[ Upstream commit c870cbbd71fccda71d575f0acd4a8d2b7cd88861 ]
If the DMA mapping failed, it produced an error log with the wrong device name:
"stm32-dma3 40400000.dma-controller: rejecting DMA map of vmalloc memory" Fix this issue by replacing the dev with the I2C dev.
--- drivers/i2c/busses/i2c-stm32.c | 8 +++----- drivers/i2c/busses/i2c-stm32f7.c | 4 ++-- 2 files changed, 5 insertions(+), 7 deletions(-)
drivers/i2c/busses/i2c-stm32.c +3 -5
@@ -102,7 +102,6 @@ int stm32_i2c_prep_dma_xfer(struct device *dev, struct stm32_i2c_dma *dma, void *dma_async_param) {struct dma_async_tx_descriptor *txdesc; -struct device *chan_dev;int ret;if (rd_wr) {
@@ -116,11 +115,10 @@ int stm32_i2c_prep_dma_xfer(struct device *dev, struct stm32_i2c_dma *dma, } dma->dma_len = len; - chan_dev = dma->chan_using->device->dev; - dma->dma_buf =dma_map_single (chan_dev, buf, dma->dma_len, + dma->dma_buf =dma_map_single (dev, buf, dma->dma_len, dma->dma_data_dir); -if (dma_mapping_error (chan_dev, dma->dma_buf)) { +if (dma_mapping_error (dev, dma->dma_buf)) {dev_err (dev,"DMA mapping failed\n" );return -EINVAL ; }
@@ -150,7 +148,7 @@ int stm32_i2c_prep_dma_xfer(struct device *dev, struct stm32_i2c_dma *dma,return 0 ; err: -dma_unmap_single (chan_dev, dma->dma_buf, dma->dma_len, +dma_unmap_single (dev, dma->dma_buf, dma->dma_len, dma->dma_data_dir);return ret; }
drivers/i2c/busses/i2c-stm32f7.c +2 -2
@@ -728,10 +728,10 @@ static void stm32f7_i2c_dma_callback(void *arg) {struct stm32f7_i2c_dev *i2c_dev = (struct stm32f7_i2c_dev *)arg;struct stm32_i2c_dma *dma = i2c_dev->dma; -struct device *dev = dma->chan_using->device->dev;stm32f7_i2c_disable_dma_req (i2c_dev); -dma_unmap_single (dev, dma->dma_buf, dma->dma_len, dma->dma_data_dir); +dma_unmap_single (i2c_dev->dev, dma->dma_buf, dma->dma_len, + dma->dma_data_dir);complete (&dma->dma_complete); }
Signature · 1 line
2.39.5
Greg KH
maintainerRe: [PATCH 6.6.y 5/6] i2c: stm32: fix the device used for the DMA map
Quoted 16 lines · Sasha Levin
From: Clément Le Goffic <[email protected]>
[ Upstream commit
c870cbbd71fccda71d575f0acd4a8d2b7cd88861]If the DMA mapping failed, it produced an error log with the wrong device name:
"stm32-dma3 40400000.dma-controller: rejecting DMA map of vmalloc memory" Fix this issue by replacing the dev with the I2C dev.Fixes bb8822cbbc53 ("i2c: i2c-stm32: Add generic DMA API")Signed-off-by Clément Le Goffic <[email protected]>Cc <[email protected]> # v4.18+Acked-by Alain Volmat <[email protected]>Signed-off-by Andi Shyti <[email protected]>Signed-off-by Sasha Levin <[email protected]>
Quoted 4 lines
--- drivers/i2c/busses/i2c-stm32.c | 8 +++----- drivers/i2c/busses/i2c-stm32f7.c | 4 ++-- 2 files changed, 5 insertions(+), 7 deletions(-)
This is already in 6.6.100, so are you sure you want it again? :)
Care to redo this series?
thanks,
greg k-h
Sasha Levin
maintainerRe: [PATCH 6.6.y 5/6] i2c: stm32: fix the device used for the DMA map
Quoted 22 lines · Greg KH
Quoted 16 lines · Sasha Levin
From: Clément Le Goffic <[email protected]>
[ Upstream commit
c870cbbd71fccda71d575f0acd4a8d2b7cd88861]If the DMA mapping failed, it produced an error log with the wrong device name:
"stm32-dma3 40400000.dma-controller: rejecting DMA map of vmalloc memory" Fix this issue by replacing the dev with the I2C dev.Fixes bb8822cbbc53 ("i2c: i2c-stm32: Add generic DMA API")Signed-off-by Clément Le Goffic <[email protected]>Cc <[email protected]> # v4.18+Acked-by Alain Volmat <[email protected]>Signed-off-by Andi Shyti <[email protected]>Signed-off-by Sasha Levin <[email protected]>Quoted 4 lines
--- drivers/i2c/busses/i2c-stm32.c | 8 +++----- drivers/i2c/busses/i2c-stm32f7.c | 4 ++-- 2 files changed, 5 insertions(+), 7 deletions(-)
Quoted 3 lines
This is already in 6.6.100, so are you sure you want it again? :)
Care to redo this series?
Looks like we raced on that one. I'l send out a v2.
Signature · 2 lines
Thanks, Sasha
Sasha Levin
maintainerPATCH 6/6 i2c: stm32f7: unmap DMA mapped buffer
In reply to Sasha LevinFrom: Clément Le Goffic <[email protected]>
[ Upstream commit 6aae87fe7f180cd93a74466cdb6cf2aa9bb28798 ]
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.
--- drivers/i2c/busses/i2c-stm32f7.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-)
drivers/i2c/busses/i2c-stm32f7.c +7 -13
@@ -726,10 +726,11 @@ static void stm32f7_i2c_disable_dma_req(struct stm32f7_i2c_dev *i2c_dev)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);
@@ -1525,7 +1526,6 @@ static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data) {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;
@@ -1540,10 +1540,8 @@ static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data)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 ; }
@@ -1561,8 +1559,7 @@ static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data) 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 ; } }
@@ -1604,7 +1601,6 @@ static irqreturn_t stm32f7_i2c_isr_error_thread(int irq, void *data)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;u32 status; status =readl_relaxed (i2c_dev->base +STM32F7_I2C_ISR );
@@ -1648,10 +1644,8 @@ static irqreturn_t stm32f7_i2c_isr_error_thread(int irq, void *data) }/* 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);
Signature · 1 line
2.39.5
Sasha Levin
maintainerPATCH v2 1/5 i2c: stm32f7: Use devm_clk_get_enabled()
In reply to [email protected]From: Andi Shyti <[email protected]>
[ Upstream commit 7ba2b17a87466e1410ae0ccc94d8eb381de177c2 ]
Replace the pair of functions, devm_clk_get() andclk_prepare_enable(), with a single functiondevm_clk_get_enabled().
Stable-dep-of: 6aae87fe7f18 ("i2c: stm32f7: unmap DMA mapped buffer")
--- drivers/i2c/busses/i2c-stm32f7.c | 37 +++++++++++--------------------- 1 file changed, 12 insertions(+), 25 deletions(-)
drivers/i2c/busses/i2c-stm32f7.c +12 -25
@@ -2177,23 +2177,16 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) i2c_dev->wakeup_src =of_property_read_bool (pdev->dev.of_node,"wakeup-source" ); - i2c_dev->clk =devm_clk_get (&pdev->dev,NULL ); + i2c_dev->clk =devm_clk_get_enabled (&pdev->dev,NULL );if (IS_ERR (i2c_dev->clk))return dev_err_probe (&pdev->dev,PTR_ERR (i2c_dev->clk), -"Failed to get controller clock\n" ); - - ret =clk_prepare_enable (i2c_dev->clk); -if (ret) { -dev_err (&pdev->dev,"Failed to prepare_enable clock\n" ); -return ret; - } +"Failed to enable controller clock\n" ); rst =devm_reset_control_get (&pdev->dev,NULL ); -if (IS_ERR (rst)) { - ret =dev_err_probe (&pdev->dev,PTR_ERR (rst), -"Error: Missing reset ctrl\n" ); - goto clk_free; - } +if (IS_ERR (rst)) +return dev_err_probe (&pdev->dev,PTR_ERR (rst), +"Error: Missing reset ctrl\n" ); +reset_control_assert (rst);udelay (2 );reset_control_deassert (rst);
@@ -2208,7 +2201,7 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)if (ret) {dev_err (&pdev->dev,"Failed to request irq event %i\n" , irq_event); - goto clk_free; +return ret; } ret = devm_request_irq(&pdev->dev, irq_error, stm32f7_i2c_isr_error, 0,
@@ -2216,29 +2209,28 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)if (ret) {dev_err (&pdev->dev,"Failed to request irq error %i\n" , irq_error); - goto clk_free; +return ret; } setup =of_device_get_match_data (&pdev->dev);if (!setup) {dev_err (&pdev->dev,"Can't get device data\n" ); - ret = -ENODEV ; - goto clk_free; +return -ENODEV ; } i2c_dev->setup = *setup; ret =stm32f7_i2c_setup_timing (i2c_dev, &i2c_dev->setup);if (ret) - goto clk_free; +return ret;/* Setup Fast mode plus if necessary */ if (i2c_dev->bus_rate >I2C_MAX_FAST_MODE_FREQ ) { ret =stm32f7_i2c_setup_fm_plus_bits (pdev, i2c_dev);if (ret) - goto clk_free; +return ret; ret =stm32f7_i2c_write_fm_plus_bits (i2c_dev, true);if (ret) - goto clk_free; +return ret; } adap = &i2c_dev->adap;
@@ -2349,9 +2341,6 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) fmp_clear:stm32f7_i2c_write_fm_plus_bits (i2c_dev, false); -clk_free: -clk_disable_unprepare (i2c_dev->clk); -return ret; }
@@ -2385,8 +2374,6 @@ static void stm32f7_i2c_remove(struct platform_device *pdev) }stm32f7_i2c_write_fm_plus_bits (i2c_dev, false); - -clk_disable_unprepare (i2c_dev->clk); }static int __maybe_unused stm32f7_i2c_runtime_suspend (struct device *dev)
Signature · 1 line
2.39.5
Sasha Levin
maintainerPATCH v2 2/5 i2c: stm32f7: use dev_err_probe upon calls of devm_request_irq
From: Alain Volmat <[email protected]>
[ Upstream commit a51e224c2f42417e95a3e1a672ade221bcd006ba ]
Convert error handling upon calls of devm_request_irq functions during the probe of the driver.
Stable-dep-of: 6aae87fe7f18 ("i2c: stm32f7: unmap DMA mapped buffer")
--- drivers/i2c/busses/i2c-stm32f7.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-)
drivers/i2c/busses/i2c-stm32f7.c +4 -10
@@ -2198,19 +2198,13 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) stm32f7_i2c_isr_event_thread,IRQF_ONESHOT , pdev->name, i2c_dev); -if (ret) { -dev_err (&pdev->dev,"Failed to request irq event %i\n" , - irq_event); -return ret; - } +if (ret) +return dev_err_probe (&pdev->dev, ret,"Failed to request irq event\n" ); ret =devm_request_irq (&pdev->dev, irq_error, stm32f7_i2c_isr_error,0 , pdev->name, i2c_dev); -if (ret) { -dev_err (&pdev->dev,"Failed to request irq error %i\n" , - irq_error); -return ret; - } +if (ret) +return dev_err_probe (&pdev->dev, ret,"Failed to request irq error\n" ); setup =of_device_get_match_data (&pdev->dev);if (!setup) {
Signature · 1 line
2.39.5
Sasha Levin
maintainerPATCH v2 3/5 i2c: stm32f7: perform most of irq job in threaded handler
In reply to Sasha LevinFrom: Alain Volmat <[email protected]>
[ Upstream commit e6103cd45ef0e14eb02f0666bc6b494902cfe821 ]
The irq handling is currently split between the irq handler and the threaded irq handler. Some of the handling (such as dma related stuffs) done within the irq handler might sleep or take some time leading to issues if the kernel is built with realtime constraints. In order to fix that, perform an overall rework to perform most of the job within the threaded handler and only keep fifo access in the non threaded handler.
Stable-dep-of: 6aae87fe7f18 ("i2c: stm32f7: unmap DMA mapped buffer")
--- drivers/i2c/busses/i2c-stm32f7.c | 126 ++++++++++++++----------------- 1 file changed, 56 insertions(+), 70 deletions(-)
drivers/i2c/busses/i2c-stm32f7.c +56 -70
@@ -1496,17 +1496,11 @@ static irqreturn_t stm32f7_i2c_slave_isr_event(struct stm32f7_i2c_dev *i2c_dev)static irqreturn_t stm32f7_i2c_isr_event (int irq,void *data) {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 =IRQ_HANDLED ; +u32 status; -/* Check if the interrupt if for a slave device */ -if (!i2c_dev->master_mode) { - ret =stm32f7_i2c_slave_isr_event (i2c_dev); -return ret; - } +/* Check if the interrupt is for a slave device */ +if (!i2c_dev->master_mode) +return IRQ_WAKE_THREAD ; status =readl_relaxed (i2c_dev->base +STM32F7_I2C_ISR );
@@ -1518,6 +1512,29 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)if (status &STM32F7_I2C_ISR_RXNE )stm32f7_i2c_read_rx_data (i2c_dev); +/* Wake up the thread if other flags are raised */ +if (status & + (STM32F7_I2C_ISR_NACKF |STM32F7_I2C_ISR_STOPF | +STM32F7_I2C_ISR_TC |STM32F7_I2C_ISR_TCR )) +return IRQ_WAKE_THREAD ; + +return IRQ_HANDLED ; +} + +static irqreturn_t stm32f7_i2c_isr_event_thread (int irq,void *data) +{ +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; + +if (!i2c_dev->master_mode) +return stm32f7_i2c_slave_isr_event (i2c_dev); + + status =readl_relaxed (i2c_dev->base +STM32F7_I2C_ISR ); +/* NACK received */ if (status &STM32F7_I2C_ISR_NACKF ) { dev_dbg(i2c_dev->dev, "<%s>: Receive NACK (addr %x)\n",
@@ -1530,33 +1547,28 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) f7_msg->result = -ENXIO ; } -/* STOP detection flag */ -if (status &STM32F7_I2C_ISR_STOPF ) { -/* Disable interrupts */ -if (stm32f7_i2c_is_slave_registered (i2c_dev)) - mask =STM32F7_I2C_XFER_IRQ_MASK ; +if (status &STM32F7_I2C_ISR_TCR ) { +if (f7_msg->smbus) +stm32f7_i2c_smbus_reload (i2c_dev);else - mask =STM32F7_I2C_ALL_IRQ_MASK ; -stm32f7_i2c_disable_irq (i2c_dev, mask); - -/* Clear STOP flag */ -writel_relaxed (STM32F7_I2C_ICR_STOPCF , base +STM32F7_I2C_ICR ); - -if (i2c_dev->use_dma && !f7_msg->result) { - ret =IRQ_WAKE_THREAD ; - }else { - i2c_dev->master_mode = false; -complete (&i2c_dev->complete); - } +stm32f7_i2c_reload (i2c_dev); }/* Transfer complete */ if (status &STM32F7_I2C_ISR_TC ) { +/* Wait for dma transfer completion before sending next message */ +if (i2c_dev->use_dma && !f7_msg->result) { + 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); + f7_msg->result = -ETIMEDOUT ; + } + }if (f7_msg->stop) { mask =STM32F7_I2C_CR2_STOP ;stm32f7_i2c_set_bits (base +STM32F7_I2C_CR2 , mask); - }else if (i2c_dev->use_dma && !f7_msg->result) { - ret =IRQ_WAKE_THREAD ; }else if (f7_msg->smbus) {stm32f7_i2c_smbus_rep_start (i2c_dev); }else {
@@ -1566,47 +1578,18 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) } } -if (status &STM32F7_I2C_ISR_TCR ) { -if (f7_msg->smbus) -stm32f7_i2c_smbus_reload (i2c_dev); +/* STOP detection flag */ +if (status &STM32F7_I2C_ISR_STOPF ) { +/* Disable interrupts */ +if (stm32f7_i2c_is_slave_registered (i2c_dev)) + mask =STM32F7_I2C_XFER_IRQ_MASK ;else -stm32f7_i2c_reload (i2c_dev); - } - -return ret; -} - -static irqreturn_t stm32f7_i2c_isr_event_thread (int irq,void *data) -{ -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; -u32 status; -int ret; - -/* -* Wait for dma transfer completion before sending next message or -* notity the end of xfer to the client -*/ - 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); - f7_msg->result = -ETIMEDOUT ; - } + mask =STM32F7_I2C_ALL_IRQ_MASK ; +stm32f7_i2c_disable_irq (i2c_dev, mask); - status =readl_relaxed (i2c_dev->base +STM32F7_I2C_ISR ); +/* Clear STOP flag */ +writel_relaxed (STM32F7_I2C_ICR_STOPCF , base +STM32F7_I2C_ICR ); -if (status &STM32F7_I2C_ISR_TC ) { -if (f7_msg->smbus) { -stm32f7_i2c_smbus_rep_start (i2c_dev); - }else { - i2c_dev->msg_id++; - i2c_dev->msg++; -stm32f7_i2c_xfer_msg (i2c_dev, i2c_dev->msg); - } - }else { i2c_dev->master_mode = false;complete (&i2c_dev->complete); }
@@ -1614,7 +1597,7 @@ static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data)return IRQ_HANDLED ; } -static irqreturn_t stm32f7_i2c_isr_error (int irq,void *data) +static irqreturn_t stm32f7_i2c_isr_error_thread (int irq,void *data) {struct stm32f7_i2c_dev *i2c_dev = data;struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
@@ -2201,8 +2184,11 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)if (ret)return dev_err_probe (&pdev->dev, ret,"Failed to request irq event\n" ); - ret =devm_request_irq (&pdev->dev, irq_error, stm32f7_i2c_isr_error,0 , - pdev->name, i2c_dev); + ret =devm_request_threaded_irq (&pdev->dev, irq_error, +NULL , + stm32f7_i2c_isr_error_thread, +IRQF_ONESHOT , + pdev->name, i2c_dev);if (ret)return dev_err_probe (&pdev->dev, ret,"Failed to request irq error\n" );
Signature · 1 line
2.39.5
Sasha Levin
maintainerPATCH v2 4/5 i2c: stm32f7: simplify status messages in case of errors
In reply to Sasha LevinFrom: Alain Volmat <[email protected]>
[ Upstream commit 33a00d919253022aabafecae6bc88a6fad446589 ]
Avoid usage of __func__ when reporting an error message since dev_err/dev_dbg are already providing enough details to identify the source of the message.
Stable-dep-of: 6aae87fe7f18 ("i2c: stm32f7: unmap DMA mapped buffer")
--- drivers/i2c/busses/i2c-stm32f7.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-)
drivers/i2c/busses/i2c-stm32f7.c +5 -7
@@ -1601,6 +1601,7 @@ static irqreturn_t stm32f7_i2c_isr_error_thread(int irq, void *data) {struct stm32f7_i2c_dev *i2c_dev = data;struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg; +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;
@@ -1610,8 +1611,7 @@ static irqreturn_t stm32f7_i2c_isr_error_thread(int irq, void *data)/* Bus error */ if (status &STM32F7_I2C_ISR_BERR ) { -dev_err (dev,"<%s>: Bus error accessing addr 0x%x\n" , - __func__, f7_msg->addr); +dev_err (dev,"Bus error accessing addr 0x%x\n" , addr);writel_relaxed (STM32F7_I2C_ICR_BERRCF , base +STM32F7_I2C_ICR );stm32f7_i2c_release_bus (&i2c_dev->adap); f7_msg->result = -EIO ;
@@ -1619,21 +1619,19 @@ static irqreturn_t stm32f7_i2c_isr_error_thread(int irq, void *data)/* Arbitration loss */ if (status &STM32F7_I2C_ISR_ARLO ) { -dev_dbg (dev,"<%s>: Arbitration loss accessing addr 0x%x\n" , - __func__, f7_msg->addr); +dev_dbg (dev,"Arbitration loss accessing addr 0x%x\n" , addr);writel_relaxed (STM32F7_I2C_ICR_ARLOCF , base +STM32F7_I2C_ICR ); f7_msg->result = -EAGAIN ; }if (status &STM32F7_I2C_ISR_PECERR ) { -dev_err (dev,"<%s>: PEC error in reception accessing addr 0x%x\n" , - __func__, f7_msg->addr); +dev_err (dev,"PEC error in reception accessing addr 0x%x\n" , addr);writel_relaxed (STM32F7_I2C_ICR_PECCF , base +STM32F7_I2C_ICR ); f7_msg->result = -EINVAL ; }if (status &STM32F7_I2C_ISR_ALERT ) { -dev_dbg (dev,"<%s>: SMBus alert received\n" , __func__); +dev_dbg (dev,"SMBus alert received\n" );writel_relaxed (STM32F7_I2C_ICR_ALERTCF , base +STM32F7_I2C_ICR );i2c_handle_smbus_alert (i2c_dev->alert->ara);return IRQ_HANDLED ;
Signature · 1 line
2.39.5
Sasha Levin
maintainerPATCH v2 5/5 i2c: stm32f7: unmap DMA mapped buffer
In reply to Sasha LevinFrom: Clément Le Goffic <[email protected]>
[ Upstream commit 6aae87fe7f180cd93a74466cdb6cf2aa9bb28798 ]
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.
--- drivers/i2c/busses/i2c-stm32f7.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-)
drivers/i2c/busses/i2c-stm32f7.c +7 -13
@@ -726,10 +726,11 @@ static void stm32f7_i2c_disable_dma_req(struct stm32f7_i2c_dev *i2c_dev)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);
@@ -1525,7 +1526,6 @@ static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data) {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;
@@ -1540,10 +1540,8 @@ static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data)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 ; }
@@ -1561,8 +1559,7 @@ static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data) 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 ; } }
@@ -1604,7 +1601,6 @@ static irqreturn_t stm32f7_i2c_isr_error_thread(int irq, void *data)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;u32 status; status =readl_relaxed (i2c_dev->base +STM32F7_I2C_ISR );
@@ -1648,10 +1644,8 @@ static irqreturn_t stm32f7_i2c_isr_error_thread(int irq, void *data) }/* 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);
Signature · 1 line
2.39.5