From: Sasha Levin <sashal@kernel.org>
To: stable@vger.kernel.org
Cc: Michael Zaidman <michael.zaidman@gmail.com>,
Guillaume Champagne <champagne.guillaume.c@gmail.com>,
Jiri Kosina <jkosina@suse.cz>, Sasha Levin <sashal@kernel.org>
Subject: [PATCH 5.15.y 2/8] HID: ft260: improve i2c write performance
Date: Thu, 27 Aug 2026 00:40:00 -0400 [thread overview]
Message-ID: <20260827044007.3635916-2-sashal@kernel.org> (raw)
In-Reply-To: <20260827044007.3635916-1-sashal@kernel.org>
From: Michael Zaidman <michael.zaidman@gmail.com>
[ Upstream commit 6fca5e3f5574ca1bd5bade5737848c816f924c6a ]
The patch improves the I2C write performance by 20 - 30 percent by
revising the sleep time in the ft260_hid_output_report_check_status()
in the following ways:
1. Reduce the wait time and start to poll earlier.
Sending a large amount of data at a low I2C clock rate saturates the
internal FT260 buffer and causes hiccups in status readiness, as shown
below in the log fragment. Aligning the status check wait time to the
worst case significantly reduces the write performance.
[Oct22 10:28] ft260_i2c_write: rep 0xd8 addr 0x51 off 0 len 34 d[0] 0x0
[ +0.005296] ft260_xfer_status: bus_status 0x20, clock 100
[ +0.013460] ft260_i2c_write: rep 0xd8 addr 0x51 off 0 len 34 d[0] 0x0
[ +0.003244] ft260_hid_output_report_check_status: wait 1920 usec, len 38
[ +0.000190] ft260_xfer_status: bus_status 0x40, clock 100
[ +0.015324] ft260_i2c_write: rep 0xd8 addr 0x51 off 0 len 34 d[0] 0x0
[ +0.003491] ft260_hid_output_report_check_status: wait 1920 usec, len 38
[ +0.000202] ft260_xfer_status: bus_status 0x40, clock 100
[ +0.016047] ft260_i2c_write: rep 0xd8 addr 0x51 off 0 len 34 d[0] 0x0
[ +0.002768] ft260_hid_output_report_check_status: wait 1920 usec, len 38
[ +0.000150] ft260_xfer_status: bus_status 0x40, clock 100
[ +0.011389] ft260_i2c_write: rep 0xd8 addr 0x51 off 0 len 34 d[0] 0x0
[ +0.003467] ft260_hid_output_report_check_status: wait 1920 usec, len 38
[ +0.000191] ft260_xfer_status: bus_status 0x41, clock 100
[ +0.000172] ft260_xfer_status: bus_status 0x41, clock 100
[ +0.000131] ft260_xfer_status: bus_status 0x41, clock 100
[ +0.000241] ft260_xfer_status: bus_status 0x41, clock 100
[ +0.000233] ft260_xfer_status: bus_status 0x41, clock 100
[ +0.000190] ft260_xfer_status: bus_status 0x41, clock 100
[ +0.000196] ft260_xfer_status: bus_status 0x40, clock 100
[ +0.011314] ft260_i2c_write: rep 0xd8 addr 0x51 off 0 len 34 d[0] 0x0
[ +0.003334] ft260_hid_output_report_check_status: wait 1920 usec, len 38
[ +0.000227] ft260_xfer_status: bus_status 0x41, clock 100
[ +0.000204] ft260_xfer_status: bus_status 0x41, clock 100
[ +0.000198] ft260_xfer_status: bus_status 0x41, clock 100
[ +0.000147] ft260_xfer_status: bus_status 0x40, clock 100
[ +0.011060] ft260_i2c_write: rep 0xd8 addr 0x51 off 0 len 34 d[0] 0x0
Before:
$ sudo ./i2cperf -f 2 -o 2 -s 32 -r 0-0xff 13 0x51 -S
Fill block with increment via i2ctransfer by chunks
-------------------------------------------------------------------
data rate(bps) efficiency(%) data size(B) total IOs IO size(B)
-------------------------------------------------------------------
40510 80 256 8 32
After:
$ sudo ./i2cperf -f 2 -o 2 -s 32 -r 0-0xff 13 0x51 -S
Fill block with increment via i2ctransfer by chunks
-------------------------------------------------------------------
data rate(bps) efficiency(%) data size(B) total IOs IO size(B)
-------------------------------------------------------------------
52584 80 256 8 32
2. Do not sleep if the estimated I2C transfer time is below 2 ms since
the first xfer status query frequently takes around 1.5 ms, and the
following status queries take about 200us on average. So we usually
return from the routine after the first 1 - 3 status checks.
[Oct22 11:14] ft260_i2c_write: rep 0xd4 addr 0x51 off 0 len 18 d[0] 0x0
[ +0.004270] ft260_xfer_status: bus_status 0x20, clock 100
[ +0.013889] ft260_i2c_write: rep 0xd4 addr 0x51 off 0 len 18 d[0] 0x0
[ +0.000856] ft260_xfer_status: bus_status 0x41, clock 100
[ +0.000138] ft260_xfer_status: bus_status 0x40, clock 100
[ +0.013352] ft260_i2c_write: rep 0xd4 addr 0x51 off 0 len 18 d[0] 0x0
[ +0.001501] ft260_xfer_status: bus_status 0x41, clock 100
[ +0.000177] ft260_xfer_status: bus_status 0x40, clock 100
[ +0.014477] ft260_i2c_write: rep 0xd4 addr 0x51 off 0 len 18 d[0] 0x0
[ +0.001377] ft260_xfer_status: bus_status 0x41, clock 100
[ +0.000233] ft260_xfer_status: bus_status 0x41, clock 100
[ +0.000191] ft260_xfer_status: bus_status 0x40, clock 100
[ +0.013197] ft260_i2c_write: rep 0xd4 addr 0x51 off 0 len 18 d[0] 0x0
Before:
$ sudo ./i2cperf -f 2 -o 2 -s 16 -r 0-0xff 13 0x51 -S
Fill block with increment via i2ctransfer by chunks
-------------------------------------------------------------------
data rate(bps) efficiency(%) data size(B) total IOs IO size(B)
-------------------------------------------------------------------
28826 73 256 16 16
After:
$ sudo ./i2cperf -f 2 -o 2 -s 16 -r 0-0xff 13 0x51 -S
Fill block with increment via i2ctransfer by chunks
-------------------------------------------------------------------
data rate(bps) efficiency(%) data size(B) total IOs IO size(B)
-------------------------------------------------------------------
45138 73 256 16 16
Signed-off-by: Michael Zaidman <michael.zaidman@gmail.com>
Tested-by: Guillaume Champagne <champagne.guillaume.c@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Stable-dep-of: bf3e39df3a39 ("HID: ft260: fix stack-use-after-return write in I2C read race")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/hid/hid-ft260.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/drivers/hid/hid-ft260.c b/drivers/hid/hid-ft260.c
index 79505c64dbfe7..539d311bb9b9d 100644
--- a/drivers/hid/hid-ft260.c
+++ b/drivers/hid/hid-ft260.c
@@ -355,7 +355,7 @@ static int ft260_hid_output_report(struct hid_device *hdev, u8 *data,
static int ft260_hid_output_report_check_status(struct ft260_device *dev,
u8 *data, int len)
{
- int ret, usec, try = 3;
+ int ret, usec, try = 100;
struct hid_device *hdev = dev->hdev;
ret = ft260_hid_output_report(hdev, data, len);
@@ -366,10 +366,14 @@ static int ft260_hid_output_report_check_status(struct ft260_device *dev,
return ret;
}
- /* transfer time = 1 / clock(KHz) * 10 bits * bytes */
- usec = 10000 / dev->clock * len;
- usleep_range(usec, usec + 100);
- ft260_dbg("wait %d usec, len %d\n", usec, len);
+ /* transfer time = 1 / clock(KHz) * 9 bits * bytes */
+ usec = len * 9000 / dev->clock;
+ if (usec > 2000) {
+ usec -= 1500;
+ usleep_range(usec, usec + 100);
+ ft260_dbg("wait %d usec, len %d\n", usec, len);
+ }
+
do {
ret = ft260_xfer_status(dev);
if (ret != -EAGAIN)
--
2.53.0
next prev parent reply other threads:[~2026-08-27 4:40 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-25 13:15 FAILED: patch "[PATCH] HID: ft260: fix stack-use-after-return write in I2C read race" failed to apply to 5.15-stable tree gregkh
2026-08-27 4:39 ` [PATCH 5.15.y 1/8] HID: ft260: fix i2c probing for hwmon devices Sasha Levin
2026-08-27 4:40 ` Sasha Levin [this message]
2026-08-27 4:40 ` [PATCH 5.15.y 3/8] HID: ft260: improve i2c large reads performance Sasha Levin
2026-08-27 4:40 ` [PATCH 5.15.y 4/8] HID: ft260: skip unexpected HID input reports Sasha Levin
2026-08-27 4:40 ` [PATCH 5.15.y 5/8] HID: ft260: wake up device from power saving mode Sasha Levin
2026-08-27 4:40 ` [PATCH 5.15.y 6/8] HID: ft260: missed NACK from busy device Sasha Levin
2026-08-27 4:40 ` [PATCH 5.15.y 7/8] HID: ft260: validate i2c input report length Sasha Levin
2026-08-27 4:40 ` [PATCH 5.15.y 8/8] HID: ft260: fix stack-use-after-return write in I2C read race Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260827044007.3635916-2-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=champagne.guillaume.c@gmail.com \
--cc=jkosina@suse.cz \
--cc=michael.zaidman@gmail.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox