OSDN Git Service

i2c: tegra: Always terminate DMA transfer
authorDmitry Osipenko <digetx@gmail.com>
Tue, 14 Jan 2020 01:34:41 +0000 (04:34 +0300)
committerWolfram Sang <wsa@the-dreams.de>
Wed, 15 Jan 2020 17:32:29 +0000 (18:32 +0100)
It is possible that I2C could error out in the middle of DMA transfer and
in this case DMA channel needs to be reset, otherwise a follow up transfer
will fail because DMA channel stays blocked.

Tested-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
drivers/i2c/busses/i2c-tegra.c

index 1a390e1..3c7c86d 100644 (file)
@@ -1220,11 +1220,12 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
                time_left = tegra_i2c_wait_completion_timeout(
                                i2c_dev, &i2c_dev->dma_complete, xfer_time);
 
+               dmaengine_terminate_sync(i2c_dev->msg_read ?
+                                        i2c_dev->rx_dma_chan :
+                                        i2c_dev->tx_dma_chan);
+
                if (time_left == 0) {
                        dev_err(i2c_dev->dev, "DMA transfer timeout\n");
-                       dmaengine_terminate_sync(i2c_dev->msg_read ?
-                                                i2c_dev->rx_dma_chan :
-                                                i2c_dev->tx_dma_chan);
                        tegra_i2c_init(i2c_dev, true);
                        return -ETIMEDOUT;
                }
@@ -1237,11 +1238,6 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
                        memcpy(i2c_dev->msg_buf, i2c_dev->dma_buf,
                               msg->len);
                }
-
-               if (i2c_dev->msg_err != I2C_ERR_NONE)
-                       dmaengine_synchronize(i2c_dev->msg_read ?
-                                             i2c_dev->rx_dma_chan :
-                                             i2c_dev->tx_dma_chan);
        }
 
        time_left = tegra_i2c_wait_completion_timeout(