Skip to content

USB: serial: ftdi_sio: configurable read-URB defer, per-port low_latency, latency_timer reliability

Chinna Mopurigari Naveen Kumar Reddy linux-usb lkml 1 version In review

Get series with b4
b4 am [email protected]

Versions newest first

  1. v1 Latest6 patches 5 repliesIn review

Patches in v1 No applies recorded yet

#Subject and filesSizeRepliesApplied
1/6USB: serial: ftdi_sio: add configurable inter-batch defer for read URBsdrivers/usb/serial/ftdi_sio.c+273 -15 replies
2/6USB: serial: ftdi_sio: retry transient errors on chip-side control transfersdrivers/usb/serial/ftdi_sio.c+41 -70 replies
3/6USB: serial: ftdi_sio: make explicit latency_timer sysfs write authoritativedrivers/usb/serial/ftdi_sio.c+17 -00 replies
4/6USB: serial: ftdi_sio: add per-port low_latency sysfs attributedrivers/usb/serial/ftdi_sio.c+66 -00 replies
5/6USB: serial: ftdi_sio: serialise low_latency toggle against read_bulk_callbackdrivers/usb/serial/ftdi_sio.c+52 -50 replies
6/6USB: serial: ftdi_sio: pace low_latency ports with low_latency_defer_nsdrivers/usb/serial/ftdi_sio.c+43 -70 replies

Reviews trailers per patch

No Reviewed-by, Acked-by or Tested-by trailers for v1 yet.

Read the v1 thread

Cover letter [PATCH 0/6] USB: serial: ftdi_sio: configurable read-URB defer, per-port low_latency, latency_timer reliability

This series adds an opt-in mechanism to bound ftdi_sio's read-URB resubmission rate, a per-port escape hatch for it, and two small reliability fixes to the existing latency_timer sysfs attribute. None of it changes the driver's default behaviour.

Background
==========

ftdi_sio resubmits read URBs as fast as the previous URB completes. On host controllers that do not arbitrate DMA-channel allocation between devices, a single FT4232 at high baud (4 channels x ~916 kbps) can keep most or all of the controller's DMA channels occupied; multiple FT4232 chips on the same bus exhaust them entirely. The control endpoint and unrelated devices on the same bus then make no progress -- device enumeration fails, hub events stall. The BCM2835/BCM2837 DWC_OTG controller used on the Raspberry Pi Compute Module 3 is the platform where this was characterised.

This series introduces a small inter-batch defer on read-URB resubmission that bounds per-device DMA-channel occupancy. It is disabled by default; behaviour on every unaffected host is unchanged.

Series layout
=============

Patch 1 adds the inter-batch defer and the urb_defer_timer_ns module parameter that controls it (default 0 = disabled). It also adds a small helper, ftdi_atomic_submit_read_urbs(), used wherever read URBs are resubmitted from completion or hrtimer (atomic) context:
usb_serial_generic_submit_read_urbs() looks atomic-usable because it takes a gfp_t, but its error-recovery path calls usb_kill_urb(), which sleeps -- so a failed inner submit under bus pressure would sleep in atomic context. The helper submits each URB inline with usb_submit_urb(GFP_ATOMIC), which does not sleep.

Patch 2 wraps usb_control_msg() with a retry on the documented transient errno values (-ETIMEDOUT, -EPIPE, -EPROTO) seen under heavy bus pressure, and converts write_latency_timer() to use it.

Patch 3 makes an explicit sysfs write to .../latency_timer authoritative against the legacy ASYNC_LOW_LATENCY tty-flag clamp set via TIOCSSERIAL by tools such as setserial(8).

Patch 4 adds a per-port low_latency sysfs attribute that bypasses the inter-batch defer on a single port when the defer is globally enabled.

Patch 5 serialises the low_latency toggle against the read-bulk callback so the attribute can be flipped while a port is actively reading or writing.

Patch 6 adds a low_latency_defer_ns module parameter: instead of fully bypassing the defer, a low_latency port can be paced with a small per-port interval (e.g. 2 ms), which lets several low_latency ports run concurrently without re-starving control transfers.

Testing
=======

Functionally validated on the affected hardware (Raspberry Pi Compute Module 3, BCM2837 DWC_OTG, two FT4232 chips, eight RS485 channels at 916 kbps each) on the 6.12 stable kernel: with the defer enabled, worst-case control-transfer latency under concurrent load dropped from ~50 ms (stock) to ~1 ms; per-port low_latency restores native read latency on a chosen port; the paced path (low_latency_defer_ns=2ms) lets four low_latency ports run without starving control transfers or the USB-Ethernet path.

Runtime-tested on mainline at the series base (arm64, Raspberry Pi 4, VL805 xHCI host, CONFIG_DEBUG_ATOMIC_SLEEP=y): module load/unload, default-path loopback regression check, the deferred-resubmit path (urb_defer_timer_ns=30ms) with live data, low_latency toggling under load (200 cycles, no stall), explicit latency_timer writes, the paced low_latency path (low_latency_defer_ns=2ms), and 50x open/close churn -- all pass with no atomic-context splats. Note this host does not reproduce the DMA-starvation problem (that requires the DWC_OTG controller); the mainline run is functional validation of the new code paths.

scripts/checkpatch.pl --strict is clean on every patch.

Chinna Mopurigari Naveen Kumar Reddy (6):
USB: serial: ftdi_sio: add configurable inter-batch defer for read
URBs
USB: serial: ftdi_sio: retry transient errors on chip-side control
transfers
USB: serial: ftdi_sio: make explicit latency_timer sysfs write
authoritative
USB: serial: ftdi_sio: add per-port low_latency sysfs attribute
USB: serial: ftdi_sio: serialise low_latency toggle against
read_bulk_callback
USB: serial: ftdi_sio: pace low_latency ports with
low_latency_defer_ns

 drivers/usb/serial/ftdi_sio.c | 488 +++++++++++++++++++++++++++++++++-
 1 file changed, 480 insertions(+), 8 deletions(-)

base-commit: ba3e43a9e601636f5edb54e259a74f96ca3b8fd8

Signature · 1 line
2.43.0