[PATCH net-next v10 0/2] net: wwan: support DTR/RTS on AT ports via MHI IP_CTRL
flat view
WARM2d
From: Peter Hunt <hidden>
Date: 2026-10-13 18:35:20
Also in:
linux-arm-msm, lkml
Revision v10 of 10 in this series.
Revisions (10)
Qualcomm/Sierra SDX55/SDX65 modems (e.g. EM9291) withhold unsolicited AT
result codes until the host asserts DTR. The in-tree mhi_wwan_ctrl driver
exposes AT ports but never signals DTR, so URCs never reach userspace.
Patch 1 extends the wwan core with an optional ->dtr_rts(port, mdmbits)
port op. The TIOCM bitmask state is tracked in the wwan core, which raises
DTR/RTS on first open of an AT port whose driver implements ->dtr_rts,
drops them on last close (if HUPCL is set, which is the default for AT
ports) and on port removal, and passes the resolved bitmask to the
driver on TIOCMSET/TIOCMBIC/TIOCMBIS.
Patch 2 adds a second mhi_driver to mhi_wwan_ctrl that binds the IP_CTRL
channel and implements ->dtr_rts by sending the host serial state to the
modem over that channel. The existing AT/QMI/MBIM data path is untouched.
This is a two-patch series. The pci_generic patch from v5 that
enumerates the IP_CTRL channel for the Sierra EM919x/EM929x has been
applied to mhi-next by Mani as commit 83c29a55b89e ("bus: mhi: host:
pci_generic: Add IP_CTRL channel for Sierra EM919x/EM929x"). There is no
build dependency between the two, without that commit the IP_CTRL driver
simply never binds and ->dtr_rts is a no-op.
Note on the ->dtr_rts signature (Loic):
In v3 I replaced ->tiocmget/->tiocmset with ->dtr_rts(port, bool on)
modelled on tty_port_operations, and moved the TIOCM handling into the
wwan core, as you suggested on v2. Review of v3 and v4 then pointed out
that a single bool cannot represent the two lines independently. With
TIOCMBIC/TIOCMBIS on one line while the other is in the opposite state,
the line state sent to the modem no longer matches what TIOCMGET reports
(e.g. RTS re-asserted after TIOCMBIC(TIOCM_RTS)).
Since v5 the op keeps the dtr_rts name and the core still owns all TIOCM
handling, but it is passed the resolved TIOCM bitmask instead of a bool,
so the driver can drive DTR and RTS independently. I kept the dtr_rts
name deliberately, following your v2 preference over ->tiocmset, even
though the signature now differs from tty_port_operations.dtr_rts. The
open/close paths still behave as tty_port dtr_rts does. Is this
acceptable to you, or would you prefer a different shape, for example a
bool ->dtr_rts for open/close plus a separate op for the ioctl path?
Changes in v10 (Sashiko review of v9):
- Patch 1: the AT/QCDM ioctl handler only holds ops_lock around the
termios/TIOCM state, never across a user-memory copy, returns
-ERESTARTSYS when interrupted, and no longer takes ops_lock for
ioctls that don't touch that state (TCFLSH, TIOCEXCL and friends,
and the FIONREAD fallback). Still ops_lock only, as agreed with Loic
- Patch 1: word the TTY comparisons and the ->dtr_rts kernel-doc more
precisely (the baud rate is not used, removal only drops the lines
while the port is open, open only once ->start() has succeeded)
- Patch 2: send DTR/RTS changes from a per-port work item that
coalesces bursts and retries a send that fails because the IP_CTRL UL
ring is full or memory is short, so the modem always ends up with the
final state. Stress testing showed rapid toggling could fill the ring
and drop updates. Loic, I've dropped your Reviewed-by on this patch as
the send path changed
Changes in v9:
- Patch 1: drop data_lock, so the termios/TIOCM state and ->dtr_rts
calls are all serialised by ops_lock, which the AT/QCDM ioctl handler
now takes interruptibly (Loic Poulain)
- Patch 1: raise DTR/RTS inside the existing first-open branch of
wwan_port_op_start() (Loic Poulain)
- Patch 1: mask TIOCMSET/TIOCMBIS/TIOCMBIC to the output bits, only call
->dtr_rts when DTR or RTS changes, and commit TCSETS/TCSETS2 only on a
successful copy (Sashiko review of v7)
- Patch 2: requeue the IP_CTRL DL sink buffer only from the refill work,
and disable it with disable_delayed_work_sync() before
mhi_unprepare_from_transfer() in remove() (Loic Poulain, Sashiko
review of v7 and v8)
- Patch 2: leave unpreparing to mhi_probe() when probe fails, and name
the wwan core commit in the commit message (Sashiko review of v7)
- DTR/RTS stays limited to AT ports, as agreed with Loic and Daniele,
and the ->dtr_rts kernel-doc now says why
Changes in v8 (Loic Poulain's review of v7, no functional change):
- Patch 1: add wwan_port_raise_dtr_rts() as the counterpart of
wwan_port_drop_dtr_rts() and move the open-path handling into it
- Patch 1: do the AT port and ->dtr_rts checks inside both helpers
- Patch 1: use scoped_guard() for data_lock in the helpers
Changes in v7 (all from the Sashiko review of v6):
- Patch 1: drop DTR/RTS on last close only if HUPCL is set, as a TTY
does, and default HUPCL on for AT ports so close behaviour is
unchanged unless userspace clears it with TCSETS
- Patch 1: wwan_remove_port() passes the masked mdmbits rather than 0,
via a helper shared with the close path
- Patch 2: retry a failed DL sink buffer requeue from a delayed work
item on -ENOMEM, and log other failures
- Patch 2: note in the commit message that the IP_CTRL channel entry
for the EM919x/EM929x is 83c29a55b89e in the MHI tree
Changes in v6:
- Rebased onto net-next, dropped the pci_generic patch (now in mhi-next)
- Patch 1: snapshot mdmbits under data_lock before calling ->dtr_rts from
the open/close paths
- Patch 2: allocate the IP_CTRL DL sink buffer separately instead of
embedding it in struct mhi_wwan_dtr (DMA safety on non-coherent
platforms), and do not requeue it when the DL transfer completes with an
error such as -ENOTCONN during channel teardown
v9: https://lore.kernel.org/netdev/20261012172219.3668624-1-peter.hunt@opengear.com/ (local)
v8: https://lore.kernel.org/netdev/20261007182238.1154851-1-peter.hunt@opengear.com/ (local)
v7: https://lore.kernel.org/netdev/20261006040422.3208888-1-peter.hunt@opengear.com/ (local)
v6: https://lore.kernel.org/netdev/20261001204614.3481089-1-peter.hunt@opengear.com/ (local)
v5: https://lore.kernel.org/netdev/20260819224927.2274790-1-peter.hunt@opengear.com/ (local)
v4: https://lore.kernel.org/netdev/20260816121705.858013-1-peter.hunt@opengear.com/ (local)
v3: https://lore.kernel.org/netdev/20260807215042.2714442-1-peter.hunt@opengear.com/ (local)
v2: https://lore.kernel.org/netdev/20260806155253.3378294-1-peter.hunt@opengear.com/ (local)
v1: https://lore.kernel.org/netdev/20260804233411.1953445-1-peter.hunt@opengear.com/ (local)
Peter Hunt (2):
net: wwan: core: propagate modem control signals to port drivers
net: wwan: mhi_wwan_ctrl: drive DTR/RTS via the IP_CTRL channel
drivers/net/wwan/mhi_wwan_ctrl.c | 262 ++++++++++++++++++++++++++++++-
drivers/net/wwan/wwan_core.c | 172 +++++++++++++-------
include/linux/wwan.h | 9 ++
3 files changed, 385 insertions(+), 58 deletions(-)
--
2.43.0