Re: [PATCH net-next v2 1/3] net: wwan: core: propagate modem control signals to port drivers

From: Loic Poulain

Date: Fri Aug 07 2026 - 03:41:51 EST


On Thu, Aug 6, 2026 at 5:54 PM Peter Hunt <peter.hunt@xxxxxxxxxxxx> wrote:
>
> The WWAN character device emulates the TTY modem-control ioctls
> (TIOCMGET/TIOCMSET/TIOCMBIC/TIOCMBIS) for AT and QCDM ports, but the
> result is only stored in port->at_data.mdmbits and never reaches the port
> driver. A driver therefore cannot act on the host raising or dropping
> DTR/RTS, even though some modems depend on it (e.g. they withhold
> unsolicited AT result codes until the host asserts DTR).
>
> Add optional ->tiocmget/->tiocmset operations to struct wwan_port_ops and
> call them from the AT/QCDM ioctl path. ->tiocmset is passed the resolved
> TIOCM_* bitmask after BIC/BIS/SET has been applied; ->tiocmget, when
> provided, refreshes the cached bits from the device. Drivers that do not
> implement them keep the previous store-only behaviour.
>
> Signed-off-by: Peter Hunt <peter.hunt@xxxxxxxxxxxx>
> ---
> drivers/net/wwan/wwan_core.c | 12 +++++++++++-
> include/linux/wwan.h | 4 ++++
> 2 files changed, 15 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/wwan/wwan_core.c b/drivers/net/wwan/wwan_core.c
> index ffbcf11e4e68..bf83eb5790fe 100644
> --- a/drivers/net/wwan/wwan_core.c
> +++ b/drivers/net/wwan/wwan_core.c
> @@ -1018,7 +1018,15 @@ static long wwan_port_fops_at_ioctl(struct wwan_port *port, unsigned int cmd,
> #endif
>
> case TIOCMGET:
> - ret = put_user(port->at_data.mdmbits, (int __user *)arg);
> + if (port->ops->tiocmget) {
> + ret = port->ops->tiocmget(port);
> + if (ret >= 0) {
> + port->at_data.mdmbits = ret;
> + ret = 0;
> + }
> + }
> + if (!ret)
> + ret = put_user(port->at_data.mdmbits, (int __user *)arg);
> break;
>
> case TIOCMSET:
> @@ -1036,6 +1044,8 @@ static long wwan_port_fops_at_ioctl(struct wwan_port *port, unsigned int cmd,
> port->at_data.mdmbits |= mdmbits;
> else
> port->at_data.mdmbits = mdmbits;
> + if (port->ops->tiocmset)
> + ret = port->ops->tiocmset(port, port->at_data.mdmbits);
> break;
> }
>
> diff --git a/include/linux/wwan.h b/include/linux/wwan.h
> index 1e0e2cb53579..bac02521e274 100644
> --- a/include/linux/wwan.h
> +++ b/include/linux/wwan.h
> @@ -57,6 +57,8 @@ struct wwan_port;
> * @tx_blocking: Optional blocking routine that sends WWAN port protocol data
> * to the device.
> * @tx_poll: Optional routine that sets additional TX poll flags.
> + * @tiocmget: Optional routine that reads the modem control lines.
> + * @tiocmset: Optional routine that sets the modem control lines.
> *
> * The wwan_port_ops structure contains a list of low-level operations
> * that control a WWAN port device. All functions are mandatory unless specified.
> @@ -70,6 +72,8 @@ struct wwan_port_ops {
> int (*tx_blocking)(struct wwan_port *port, struct sk_buff *skb);
> __poll_t (*tx_poll)(struct wwan_port *port, struct file *filp,
> poll_table *wait);
> + int (*tiocmget)(struct wwan_port *port);

You don't use it in this series, so please drop.

> + int (*tiocmset)(struct wwan_port *port, unsigned int mdmbits);

TBH, I would prefer a dtr_rts(port, on/off) callback like
tty_port_operations. the tiocmset/get generic handling can stay in the
WWAN core.

> };
>
> /** struct wwan_port_caps - The WWAN port capbilities
> --
> 2.43.0
>