[PATCH v1] i2c: qcom-geni: Skip extra TX DMA TRE for single read message in GPI mode
From: Aniket Randive
Date: Thu Mar 26 2026 - 00:32:21 EST
In GPI mode, the I2C GENI driver incorrectly generates an extra TX DMA
TRE on the TX channel during single read message transfer. This results
in an unnecessary write operation on the I2C bus, which is not required.
Update the logic to avoid generating the extra TX DMA TRE for single
read message, ensuring correct behavior and preventing redundant
transfers.
Co-developed-by: Maramaina Naresh <naresh.maramaina@xxxxxxxxxxxxxxxx>
Signed-off-by: Maramaina Naresh <naresh.maramaina@xxxxxxxxxxxxxxxx>
Signed-off-by: Aniket Randive <aniket.randive@xxxxxxxxxxxxxxxx>
---
drivers/i2c/busses/i2c-qcom-geni.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
index a4acb78fafb6..2706309bbebb 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -625,8 +625,8 @@ static int geni_i2c_gpi(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[],
{
struct gpi_i2c_config *peripheral;
unsigned int flags;
- void *dma_buf;
- dma_addr_t addr;
+ void *dma_buf = NULL;
+ dma_addr_t addr = 0;
enum dma_data_direction map_dirn;
enum dma_transfer_direction dma_dirn;
struct dma_async_tx_descriptor *desc;
@@ -639,6 +639,11 @@ static int geni_i2c_gpi(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[],
gi2c_gpi_xfer = &gi2c->i2c_multi_desc_config;
msg_idx = gi2c_gpi_xfer->msg_idx_cnt;
+ if (op == I2C_WRITE && msgs[msg_idx].flags & I2C_M_RD) {
+ peripheral->multi_msg = true;
+ goto skip_dma;
+ }
+
dma_buf = i2c_get_dma_safe_msg_buf(&msgs[msg_idx], 1);
if (!dma_buf) {
ret = -ENOMEM;
@@ -668,6 +673,7 @@ static int geni_i2c_gpi(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[],
flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
}
+skip_dma:
/* set the length as message for rx txn */
peripheral->rx_len = msgs[msg_idx].len;
peripheral->op = op;
@@ -740,9 +746,11 @@ static int geni_i2c_gpi(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[],
return 0;
err_config:
- dma_unmap_single(gi2c->se.dev->parent, addr,
- msgs[msg_idx].len, map_dirn);
- i2c_put_dma_safe_msg_buf(dma_buf, &msgs[msg_idx], false);
+ if (op == I2C_WRITE && (msgs[msg_idx].flags & I2C_M_RD)) {
+ dma_unmap_single(gi2c->se.dev->parent, addr,
+ msgs[msg_idx].len, map_dirn);
+ i2c_put_dma_safe_msg_buf(dma_buf, &msgs[msg_idx], false);
+ }
out:
gi2c->err = ret;
---
base-commit: 785f0eb2f85decbe7c1ef9ae922931f0194ffc2e
change-id: 20260325-skip_extra_dma_tre-a3cf22f81d9b
Best regards,
--
Aniket Randive <aniket.randive@xxxxxxxxxxxxxxxx>