[PATCH v3 2/2] USB: serial: ftdi_sio: make explicit latency_timer sysfs write authoritative
From: Chinna Mopurigari Naveen Kumar Reddy
Date: Tue Jun 23 2026 - 04:04:31 EST
write_latency_timer() clamps the value programmed into the FT chip's
per-channel latency_timer register to 1 whenever ASYNC_LOW_LATENCY is
set in priv->flags. ASYNC_LOW_LATENCY is set by userspace via
TIOCSSERIAL, used by setserial(8), libftdi and certain tcsetattr
paths. The interaction with the existing sysfs latency_timer
attribute is surprising: once any of those tools has set the flag, a
later write of "16" (or any other value) to
/sys/bus/usb-serial/devices/ttyUSBx/latency_timer is silently
clamped to 1 and never reaches the chip.
The store path is the most explicit way userspace can ask for a
particular latency_timer value; treat it as authoritative. On an
explicit sysfs write, clear ASYNC_LOW_LATENCY before calling
write_latency_timer() so the requested value is what the chip
register actually receives. The override is logged at debug level
(dev_dbg) for diagnostics only.
Reads continue to honour ASYNC_LOW_LATENCY (returning "1") so any
userspace that previously inspected the attribute to confirm
low-latency mode keeps working until it does its own explicit write.
Signed-off-by: Chinna Mopurigari Naveen Kumar Reddy <naveen.reddy@xxxxxxxxxxxx>
---
drivers/usb/serial/ftdi_sio.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 7aaa7fc1be71..d2547ad76423 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1683,6 +1683,23 @@ static ssize_t latency_timer_store(struct device *dev,
if (kstrtou8(valbuf, 10, &v))
return -EINVAL;
+ /*
+ * An explicit sysfs write wins over the legacy ASYNC_LOW_LATENCY
+ * tty-flag override. Without this, if any userspace tool
+ * (setserial(8), libftdi, certain tcsetattr paths) had set
+ * ASYNC_LOW_LATENCY via TIOCSSERIAL, write_latency_timer() would
+ * silently clamp the chip register to 1 regardless of what was
+ * written to sysfs. Clearing the flag here makes sysfs the
+ * authoritative source so the next chip-side write uses exactly
+ * the value the caller asked for.
+ */
+ if (priv->flags & ASYNC_LOW_LATENCY) {
+ dev_dbg(&port->dev,
+ "explicit latency_timer=%u clears ASYNC_LOW_LATENCY flag\n",
+ v);
+ priv->flags &= ~ASYNC_LOW_LATENCY;
+ }
+
priv->latency = v;
rv = write_latency_timer(port);
if (rv < 0)
--
2.43.0