Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0cea7788 authored by Alain Volmat's avatar Alain Volmat Committed by Greg Kroah-Hartman
Browse files

i2c: stm32f7: stop dma transfer in case of NACK



commit 31b90a95ccbbb4b628578ac17e3b3cc8eeacfe31 upstream.

In case of receiving a NACK, the dma transfer should be stopped
to avoid feeding data into the FIFO.
Also ensure to properly return the proper error code and avoid
waiting for the end of the dma completion in case of
error happening during the transmission.

Fixes: 7ecc8cfd ("i2c: i2c-stm32f7: Add DMA support")
Signed-off-by: default avatarAlain Volmat <alain.volmat@foss.st.com>
Reviewed-by: default avatarPierre-Yves MORDRET <pierre-yves.mordret@foss.st.com>
Signed-off-by: default avatarWolfram Sang <wsa@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 34702908
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -1379,6 +1379,7 @@ 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;
@@ -1403,6 +1404,10 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
	if (status & STM32F7_I2C_ISR_NACKF) {
		dev_dbg(i2c_dev->dev, "<%s>: Receive NACK\n", __func__);
		writel_relaxed(STM32F7_I2C_ICR_NACKCF, base + STM32F7_I2C_ICR);
		if (i2c_dev->use_dma) {
			stm32f7_i2c_disable_dma_req(i2c_dev);
			dmaengine_terminate_all(dma->chan_using);
		}
		f7_msg->result = -ENXIO;
	}

@@ -1418,7 +1423,7 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
		/* Clear STOP flag */
		writel_relaxed(STM32F7_I2C_ICR_STOPCF, base + STM32F7_I2C_ICR);

		if (i2c_dev->use_dma) {
		if (i2c_dev->use_dma && !f7_msg->result) {
			ret = IRQ_WAKE_THREAD;
		} else {
			i2c_dev->master_mode = false;
@@ -1431,7 +1436,7 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
		if (f7_msg->stop) {
			mask = STM32F7_I2C_CR2_STOP;
			stm32f7_i2c_set_bits(base + STM32F7_I2C_CR2, mask);
		} else if (i2c_dev->use_dma) {
		} 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);