mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] i2c: qup: scale the transfer timeout with the transfer length
@ 2026-11-14 14:02 cookys via B4 Relay
  0 siblings, 0 replies; only message in thread
From: cookys via B4 Relay @ 2026-11-14 14:02 UTC (permalink / raw)
  To: Andi Shyti; +Cc: linux-kernel, linux-i2c, linux-arm-msm

From: cookys <cookys@gmail.com>

qup_i2c_probe() sets one transfer timeout for the adapter, sized for the
largest DMA transfer: TOUT_MIN (2 s) plus MX_DMA_TX_RX_LEN (128 KiB)
byte times. At the default 100 kHz that is 2 s + 131072 x 99 us, about
15 s, and every wait uses it, even for a one-byte read. A transfer that
never completes therefore stalls its caller for 15 s before -ETIMEDOUT.

On the Lenovo ThinkSmart View (APQ8053) the FT8201 touch controller
sometimes does not complete the first read after power-up (about one
boot in four). edt_ft5x06 probes asynchronously, so for those 15 s
every module init waits in async_synchronize_full(), and boot stalls:

  probe of 2-0038 with driver edt_ft5x06 returned 0 after 15343275 usecs

Set the timeout before each wait from the bytes that wait covers: the
message length on the FIFO and block paths (v1 and v2), the total of
the messages in the batch on the BAM path. The probe-time value is now
only the initial default. With this change the same failed read returns
after about 2 s:

  probe of 2-0038 with driver edt_ft5x06 returned 0 after 2353169 usecs

Tested on the ThinkSmart View (msm8953-mainline 7.3 with this change),
24 boots: touch probe 0.32-0.35 s, and 2.35 s in the one boot where
the controller missed its first read.

Assisted-by: Grok:grok-4.6
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: cookys <cookys@gmail.com>
---
 drivers/i2c/busses/i2c-qup.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index a0e076fc5..cda78933e 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -439,6 +439,12 @@ static int qup_i2c_change_state(struct qup_i2c_dev *qup, u32 state)
 	return 0;
 }
 
+static void qup_i2c_set_xfer_timeout(struct qup_i2c_dev *qup, unsigned int len)
+{
+	qup->xfer_timeout = TOUT_MIN * HZ +
+		usecs_to_jiffies(len * qup->one_byte_t);
+}
+
 /* Check if I2C bus returns to IDLE state */
 static int qup_i2c_bus_active(struct qup_i2c_dev *qup, int len)
 {
@@ -864,6 +870,7 @@ static int qup_i2c_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
 	struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
 	int ret = 0;
 	int idx = 0;
+	unsigned int xfer_len = 0;
 
 	ret = qup_i2c_vote_bw(qup, qup->src_clk_freq);
 	if (ret)
@@ -900,6 +907,8 @@ static int qup_i2c_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
 		if (ret)
 			break;
 
+		xfer_len += qup->msg->len;
+
 		/*
 		 * Make DMA descriptor and schedule the BAM transfer if its
 		 * already crossed the maximum length. Since the memory for all
@@ -910,11 +919,13 @@ static int qup_i2c_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
 		if (qup->btx.sg_cnt > qup->max_xfer_sg_len ||
 		    qup->brx.sg_cnt > qup->max_xfer_sg_len ||
 		    qup->is_last) {
+			qup_i2c_set_xfer_timeout(qup, xfer_len);
 			ret = qup_i2c_bam_schedule_desc(qup);
 			if (ret)
 				break;
 
 			qup_i2c_bam_clear_tag_buffers(qup);
+			xfer_len = 0;
 		}
 	}
 
@@ -1054,6 +1065,7 @@ static int qup_i2c_conf_xfer_v1(struct qup_i2c_dev *qup, bool is_rx)
 	if (ret)
 		goto err;
 
+	qup_i2c_set_xfer_timeout(qup, qup->msg->len);
 	ret = qup_i2c_wait_for_complete(qup, qup->msg);
 	if (ret)
 		goto err;
@@ -1432,6 +1444,7 @@ qup_i2c_conf_xfer_v2(struct qup_i2c_dev *qup, bool is_rx, bool is_first,
 	if (ret)
 		goto err;
 
+	qup_i2c_set_xfer_timeout(qup, msg->len);
 	ret = qup_i2c_wait_for_complete(qup, msg);
 	if (ret)
 		goto err;

---
base-commit: 04e9bf1648f846976b543e91c1838a712433772a
change-id: 20261114-qup-timeout-6b7a0d837b71

Best regards,
--  
cookys <cookys@gmail.com>



^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-11-14 14:02 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-14 14:02 [PATCH] i2c: qup: scale the transfer timeout with the transfer length cookys via B4 Relay

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®