* [net-next v3 1/8] net: wwan: core: remove unused port_id field
2025-12-31 6:51 [net-next v3 0/8] net: wwan: add NMEA port type support Slark Xiao
@ 2025-12-31 6:51 ` Slark Xiao
2025-12-31 6:51 ` [net-next v3 2/8] net: wwan: core: split port creation and registration Slark Xiao
` (7 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Slark Xiao @ 2025-12-31 6:51 UTC (permalink / raw)
To: loic.poulain, ryazanov.s.a, johannes, andrew+netdev, davem,
edumazet, kuba, pabeni, mani
Cc: netdev, linux-kernel
From: Sergey Ryazanov <ryazanov.s.a@gmail.com>
It was used initially for a port id allocation, then removed, and then
accidently introduced again, but it is still unused. Drop it again to
keep code clean.
Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
Reviewed-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
---
drivers/net/wwan/wwan_core.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/net/wwan/wwan_core.c b/drivers/net/wwan/wwan_core.c
index 63a47d420bc5..ade8bbffc93e 100644
--- a/drivers/net/wwan/wwan_core.c
+++ b/drivers/net/wwan/wwan_core.c
@@ -43,7 +43,6 @@ static struct dentry *wwan_debugfs_dir;
*
* @id: WWAN device unique ID.
* @dev: Underlying device.
- * @port_id: Current available port ID to pick.
* @ops: wwan device ops
* @ops_ctxt: context to pass to ops
* @debugfs_dir: WWAN device debugfs dir
@@ -51,7 +50,6 @@ static struct dentry *wwan_debugfs_dir;
struct wwan_device {
unsigned int id;
struct device dev;
- atomic_t port_id;
const struct wwan_ops *ops;
void *ops_ctxt;
#ifdef CONFIG_WWAN_DEBUGFS
--
2.25.1
^ permalink raw reply [flat|nested] 12+ messages in thread* [net-next v3 2/8] net: wwan: core: split port creation and registration
2025-12-31 6:51 [net-next v3 0/8] net: wwan: add NMEA port type support Slark Xiao
2025-12-31 6:51 ` [net-next v3 1/8] net: wwan: core: remove unused port_id field Slark Xiao
@ 2025-12-31 6:51 ` Slark Xiao
2025-12-31 6:51 ` [net-next v3 3/8] net: wwan: core: split port unregister and stop Slark Xiao
` (6 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Slark Xiao @ 2025-12-31 6:51 UTC (permalink / raw)
To: loic.poulain, ryazanov.s.a, johannes, andrew+netdev, davem,
edumazet, kuba, pabeni, mani
Cc: netdev, linux-kernel
From: Sergey Ryazanov <ryazanov.s.a@gmail.com>
Upcoming GNSS (NMEA) port type support requires exporting it via the
GNSS subsystem. On another hand, we still need to do basic WWAN core
work: find or allocate the WWAN device, make it the port parent, etc. To
reuse as much code as possible, split the port creation function into
the registration of a regular WWAN port device, and basic port struct
initialization.
To be able to use put_device() uniformly, break the device_register()
call into device_initialize() and device_add() and call device
initialization earlier.
Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
---
drivers/net/wwan/wwan_core.c | 66 ++++++++++++++++++++++--------------
1 file changed, 40 insertions(+), 26 deletions(-)
diff --git a/drivers/net/wwan/wwan_core.c b/drivers/net/wwan/wwan_core.c
index ade8bbffc93e..edee5ff48f28 100644
--- a/drivers/net/wwan/wwan_core.c
+++ b/drivers/net/wwan/wwan_core.c
@@ -361,7 +361,8 @@ static void wwan_port_destroy(struct device *dev)
{
struct wwan_port *port = to_wwan_port(dev);
- ida_free(&minors, MINOR(port->dev.devt));
+ if (dev->class == &wwan_class)
+ ida_free(&minors, MINOR(dev->devt));
mutex_destroy(&port->data_lock);
mutex_destroy(&port->ops_lock);
kfree(port);
@@ -440,6 +441,41 @@ static int __wwan_port_dev_assign_name(struct wwan_port *port, const char *fmt)
return dev_set_name(&port->dev, "%s", buf);
}
+/* Register a regular WWAN port device (e.g. AT, MBIM, etc.) */
+static int wwan_port_register_wwan(struct wwan_port *port)
+{
+ struct wwan_device *wwandev = to_wwan_dev(port->dev.parent);
+ char namefmt[0x20];
+ int minor, err;
+
+ /* A port is exposed as character device, get a minor */
+ minor = ida_alloc_range(&minors, 0, WWAN_MAX_MINORS - 1, GFP_KERNEL);
+ if (minor < 0)
+ return minor;
+
+ port->dev.class = &wwan_class;
+ port->dev.devt = MKDEV(wwan_major, minor);
+
+ /* allocate unique name based on wwan device id, port type and number */
+ snprintf(namefmt, sizeof(namefmt), "wwan%u%s%%d", wwandev->id,
+ wwan_port_types[port->type].devsuf);
+
+ /* Serialize ports registration */
+ mutex_lock(&wwan_register_lock);
+
+ __wwan_port_dev_assign_name(port, namefmt);
+ err = device_add(&port->dev);
+
+ mutex_unlock(&wwan_register_lock);
+
+ if (err)
+ return err;
+
+ dev_info(&wwandev->dev, "port %s attached\n", dev_name(&port->dev));
+
+ return 0;
+}
+
struct wwan_port *wwan_create_port(struct device *parent,
enum wwan_port_type type,
const struct wwan_port_ops *ops,
@@ -448,8 +484,7 @@ struct wwan_port *wwan_create_port(struct device *parent,
{
struct wwan_device *wwandev;
struct wwan_port *port;
- char namefmt[0x20];
- int minor, err;
+ int err;
if (type > WWAN_PORT_MAX || !ops)
return ERR_PTR(-EINVAL);
@@ -461,17 +496,9 @@ struct wwan_port *wwan_create_port(struct device *parent,
if (IS_ERR(wwandev))
return ERR_CAST(wwandev);
- /* A port is exposed as character device, get a minor */
- minor = ida_alloc_range(&minors, 0, WWAN_MAX_MINORS - 1, GFP_KERNEL);
- if (minor < 0) {
- err = minor;
- goto error_wwandev_remove;
- }
-
port = kzalloc(sizeof(*port), GFP_KERNEL);
if (!port) {
err = -ENOMEM;
- ida_free(&minors, minor);
goto error_wwandev_remove;
}
@@ -485,27 +512,14 @@ struct wwan_port *wwan_create_port(struct device *parent,
mutex_init(&port->data_lock);
port->dev.parent = &wwandev->dev;
- port->dev.class = &wwan_class;
port->dev.type = &wwan_port_dev_type;
- port->dev.devt = MKDEV(wwan_major, minor);
dev_set_drvdata(&port->dev, drvdata);
+ device_initialize(&port->dev);
- /* allocate unique name based on wwan device id, port type and number */
- snprintf(namefmt, sizeof(namefmt), "wwan%u%s%%d", wwandev->id,
- wwan_port_types[port->type].devsuf);
-
- /* Serialize ports registration */
- mutex_lock(&wwan_register_lock);
-
- __wwan_port_dev_assign_name(port, namefmt);
- err = device_register(&port->dev);
-
- mutex_unlock(&wwan_register_lock);
-
+ err = wwan_port_register_wwan(port);
if (err)
goto error_put_device;
- dev_info(&wwandev->dev, "port %s attached\n", dev_name(&port->dev));
return port;
error_put_device:
--
2.25.1
^ permalink raw reply [flat|nested] 12+ messages in thread* [net-next v3 3/8] net: wwan: core: split port unregister and stop
2025-12-31 6:51 [net-next v3 0/8] net: wwan: add NMEA port type support Slark Xiao
2025-12-31 6:51 ` [net-next v3 1/8] net: wwan: core: remove unused port_id field Slark Xiao
2025-12-31 6:51 ` [net-next v3 2/8] net: wwan: core: split port creation and registration Slark Xiao
@ 2025-12-31 6:51 ` Slark Xiao
2025-12-31 6:51 ` [net-next v3 4/8] net: wwan: add NMEA port support Slark Xiao
` (5 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Slark Xiao @ 2025-12-31 6:51 UTC (permalink / raw)
To: loic.poulain, ryazanov.s.a, johannes, andrew+netdev, davem,
edumazet, kuba, pabeni, mani
Cc: netdev, linux-kernel
From: Sergey Ryazanov <ryazanov.s.a@gmail.com>
Upcoming GNSS (NMEA) port type support requires exporting it via the
GNSS subsystem. On another hand, we still need to do basic WWAN core
work: call the port stop operation, purge queues, release the parent
WWAN device, etc. To reuse as much code as possible, split the port
unregistering function into the deregistration of a regular WWAN port
device, and the common port tearing down code.
In order to keep more code generic, break the device_unregister() call
into device_del() and put_device(), which release the port memory
uniformly.
Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
---
drivers/net/wwan/wwan_core.c | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wwan/wwan_core.c b/drivers/net/wwan/wwan_core.c
index edee5ff48f28..c735b9830e6e 100644
--- a/drivers/net/wwan/wwan_core.c
+++ b/drivers/net/wwan/wwan_core.c
@@ -476,6 +476,18 @@ static int wwan_port_register_wwan(struct wwan_port *port)
return 0;
}
+/* Unregister a regular WWAN port (e.g. AT, MBIM, etc) */
+static void wwan_port_unregister_wwan(struct wwan_port *port)
+{
+ struct wwan_device *wwandev = to_wwan_dev(port->dev.parent);
+
+ dev_set_drvdata(&port->dev, NULL);
+
+ dev_info(&wwandev->dev, "port %s disconnected\n", dev_name(&port->dev));
+
+ device_del(&port->dev);
+}
+
struct wwan_port *wwan_create_port(struct device *parent,
enum wwan_port_type type,
const struct wwan_port_ops *ops,
@@ -536,18 +548,19 @@ void wwan_remove_port(struct wwan_port *port)
struct wwan_device *wwandev = to_wwan_dev(port->dev.parent);
mutex_lock(&port->ops_lock);
- if (port->start_count)
+ if (port->start_count) {
port->ops->stop(port);
+ port->start_count = 0;
+ }
port->ops = NULL; /* Prevent any new port operations (e.g. from fops) */
mutex_unlock(&port->ops_lock);
wake_up_interruptible(&port->waitqueue);
-
skb_queue_purge(&port->rxq);
- dev_set_drvdata(&port->dev, NULL);
- dev_info(&wwandev->dev, "port %s disconnected\n", dev_name(&port->dev));
- device_unregister(&port->dev);
+ wwan_port_unregister_wwan(port);
+
+ put_device(&port->dev);
/* Release related wwan device */
wwan_remove_dev(wwandev);
--
2.25.1
^ permalink raw reply [flat|nested] 12+ messages in thread* [net-next v3 4/8] net: wwan: add NMEA port support
2025-12-31 6:51 [net-next v3 0/8] net: wwan: add NMEA port type support Slark Xiao
` (2 preceding siblings ...)
2025-12-31 6:51 ` [net-next v3 3/8] net: wwan: core: split port unregister and stop Slark Xiao
@ 2025-12-31 6:51 ` Slark Xiao
2025-12-31 20:13 ` kernel test robot
2025-12-31 6:51 ` [net-next v3 5/8] net: wwan: hwsim: refactor to support more port types Slark Xiao
` (4 subsequent siblings)
8 siblings, 1 reply; 12+ messages in thread
From: Slark Xiao @ 2025-12-31 6:51 UTC (permalink / raw)
To: loic.poulain, ryazanov.s.a, johannes, andrew+netdev, davem,
edumazet, kuba, pabeni, mani
Cc: netdev, linux-kernel, Slark Xiao, Muhammad Nuzaihan, Qiang Yu,
Manivannan Sadhasivam, Johan Hovold
From: Sergey Ryazanov <ryazanov.s.a@gmail.com>
Many WWAN modems come with embedded GNSS receiver inside and have a
dedicated port to output geopositioning data. On the one hand, the
GNSS receiver has little in common with WWAN modem and just shares a
host interface and should be exported using the GNSS subsystem. On the
other hand, GNSS receiver is not automatically activated and needs a
generic WWAN control port (AT, MBIM, etc.) to be turned on. And a user
space software needs extra information to find the control port.
Introduce the new type of WWAN port - NMEA. When driver asks to register
a NMEA port, the core allocates common parent WWAN device as usual, but
exports the NMEA port via the GNSS subsystem and acts as a proxy between
the device driver and the GNSS subsystem.
>From the WWAN device driver perspective, a NMEA port is registered as a
regular WWAN port without any difference. And the driver interacts only
with the WWAN core. From the user space perspective, the NMEA port is a
GNSS device which parent can be used to enumerate and select the proper
control port for the GNSS receiver management.
CC: Slark Xiao <slark_xiao@163.com>
CC: Muhammad Nuzaihan <zaihan@unrealasia.net>
CC: Qiang Yu <quic_qianyu@quicinc.com>
CC: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
CC: Johan Hovold <johan@kernel.org>
Suggested-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
---
drivers/net/wwan/Kconfig | 1 +
drivers/net/wwan/wwan_core.c | 155 +++++++++++++++++++++++++++++++++--
include/linux/wwan.h | 2 +
3 files changed, 153 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wwan/Kconfig b/drivers/net/wwan/Kconfig
index 410b0245114e..88df55d78d90 100644
--- a/drivers/net/wwan/Kconfig
+++ b/drivers/net/wwan/Kconfig
@@ -7,6 +7,7 @@ menu "Wireless WAN"
config WWAN
tristate "WWAN Driver Core"
+ depends on GNSS || GNSS = n
help
Say Y here if you want to use the WWAN driver core. This driver
provides a common framework for WWAN drivers.
diff --git a/drivers/net/wwan/wwan_core.c b/drivers/net/wwan/wwan_core.c
index c735b9830e6e..93998b498454 100644
--- a/drivers/net/wwan/wwan_core.c
+++ b/drivers/net/wwan/wwan_core.c
@@ -1,5 +1,9 @@
// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2021, Linaro Ltd <loic.poulain@linaro.org> */
+/* WWAN Driver Core
+ *
+ * Copyright (c) 2021, Linaro Ltd <loic.poulain@linaro.org>
+ * Copyright (c) 2025, Sergey Ryazanov <ryazanov.s.a@gmail.com>
+ */
#include <linux/bitmap.h>
#include <linux/err.h>
@@ -16,6 +20,7 @@
#include <linux/types.h>
#include <linux/uaccess.h>
#include <linux/termios.h>
+#include <linux/gnss.h>
#include <linux/wwan.h>
#include <net/rtnetlink.h>
#include <uapi/linux/wwan.h>
@@ -89,9 +94,16 @@ struct wwan_port {
struct ktermios termios;
int mdmbits;
} at_data;
+ struct gnss_device *gnss;
};
};
+static int wwan_port_op_start(struct wwan_port *port);
+static void wwan_port_op_stop(struct wwan_port *port);
+static int wwan_port_op_tx(struct wwan_port *port, struct sk_buff *skb,
+ bool nonblock);
+static int wwan_wait_tx(struct wwan_port *port, bool nonblock);
+
static ssize_t index_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct wwan_device *wwan = to_wwan_dev(dev);
@@ -340,6 +352,7 @@ static const struct {
.name = "MIPC",
.devsuf = "mipc",
},
+ /* WWAN_PORT_NMEA is exported via the GNSS subsystem */
};
static ssize_t type_show(struct device *dev, struct device_attribute *attr,
@@ -488,6 +501,124 @@ static void wwan_port_unregister_wwan(struct wwan_port *port)
device_del(&port->dev);
}
+#if IS_ENABLED(CONFIG_GNSS)
+static int wwan_gnss_open(struct gnss_device *gdev)
+{
+ return wwan_port_op_start(gnss_get_drvdata(gdev));
+}
+
+static void wwan_gnss_close(struct gnss_device *gdev)
+{
+ wwan_port_op_stop(gnss_get_drvdata(gdev));
+}
+
+static int wwan_gnss_write(struct gnss_device *gdev, const unsigned char *buf,
+ size_t count)
+{
+ struct wwan_port *port = gnss_get_drvdata(gdev);
+ struct sk_buff *skb, *head = NULL, *tail = NULL;
+ size_t frag_len, remain = count;
+ int ret;
+
+ ret = wwan_wait_tx(port, false);
+ if (ret)
+ return ret;
+
+ do {
+ frag_len = min(remain, port->frag_len);
+ skb = alloc_skb(frag_len + port->headroom_len, GFP_KERNEL);
+ if (!skb) {
+ ret = -ENOMEM;
+ goto freeskb;
+ }
+ skb_reserve(skb, port->headroom_len);
+ memcpy(skb_put(skb, frag_len), buf + count - remain, frag_len);
+
+ if (!head) {
+ head = skb;
+ } else {
+ if (!tail)
+ skb_shinfo(head)->frag_list = skb;
+ else
+ tail->next = skb;
+
+ tail = skb;
+ head->data_len += skb->len;
+ head->len += skb->len;
+ head->truesize += skb->truesize;
+ }
+ } while (remain -= frag_len);
+
+ ret = wwan_port_op_tx(port, head, false);
+ if (!ret)
+ return count;
+
+freeskb:
+ kfree_skb(head);
+ return ret;
+}
+
+static struct gnss_operations wwan_gnss_ops = {
+ .open = wwan_gnss_open,
+ .close = wwan_gnss_close,
+ .write_raw = wwan_gnss_write,
+};
+
+/* GNSS port specific device registration */
+static int wwan_port_register_gnss(struct wwan_port *port)
+{
+ struct wwan_device *wwandev = to_wwan_dev(port->dev.parent);
+ struct gnss_device *gdev;
+ int err;
+
+ gdev = gnss_allocate_device(&wwandev->dev);
+ if (!gdev)
+ return -ENOMEM;
+
+ /* NB: for now we support only NMEA WWAN port type, so hardcode
+ * the GNSS port type. If more GNSS WWAN port types will be added,
+ * then we should dynamically mapt WWAN port type to GNSS type.
+ */
+ gdev->type = GNSS_TYPE_NMEA;
+ gdev->ops = &wwan_gnss_ops;
+ gnss_set_drvdata(gdev, port);
+
+ port->gnss = gdev;
+
+ err = gnss_register_device(gdev);
+ if (err) {
+ gnss_put_device(gdev);
+ return err;
+ }
+
+ dev_info(&wwandev->dev, "port %s attached\n", dev_name(&gdev->dev));
+
+ return 0;
+}
+
+/* GNSS port specific device unregistration */
+static void wwan_port_unregister_gnss(struct wwan_port *port)
+{
+ struct wwan_device *wwandev = to_wwan_dev(port->dev.parent);
+ struct gnss_device *gdev = port->gnss;
+
+ dev_info(&wwandev->dev, "port %s disconnected\n", dev_name(&gdev->dev));
+
+ gnss_deregister_device(gdev);
+ gnss_put_device(gdev);
+}
+#else
+static inline int wwan_port_register_gnss(struct wwan_port *port)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline void wwan_port_unregister_gnss(struct wwan_port *port)
+{
+ WARN_ON(1); /* This handler cannot be called */
+}
+#endif
+
struct wwan_port *wwan_create_port(struct device *parent,
enum wwan_port_type type,
const struct wwan_port_ops *ops,
@@ -528,7 +659,11 @@ struct wwan_port *wwan_create_port(struct device *parent,
dev_set_drvdata(&port->dev, drvdata);
device_initialize(&port->dev);
- err = wwan_port_register_wwan(port);
+ if (port->type == WWAN_PORT_NMEA)
+ err = wwan_port_register_gnss(port);
+ else
+ err = wwan_port_register_wwan(port);
+
if (err)
goto error_put_device;
@@ -558,7 +693,10 @@ void wwan_remove_port(struct wwan_port *port)
wake_up_interruptible(&port->waitqueue);
skb_queue_purge(&port->rxq);
- wwan_port_unregister_wwan(port);
+ if (port->type == WWAN_PORT_NMEA)
+ wwan_port_unregister_gnss(port);
+ else
+ wwan_port_unregister_wwan(port);
put_device(&port->dev);
@@ -569,8 +707,15 @@ EXPORT_SYMBOL_GPL(wwan_remove_port);
void wwan_port_rx(struct wwan_port *port, struct sk_buff *skb)
{
- skb_queue_tail(&port->rxq, skb);
- wake_up_interruptible(&port->waitqueue);
+ if (port->type == WWAN_PORT_NMEA) {
+#if IS_ENABLED(CONFIG_GNSS)
+ gnss_insert_raw(port->gnss, skb->data, skb->len);
+#endif
+ consume_skb(skb);
+ } else {
+ skb_queue_tail(&port->rxq, skb);
+ wake_up_interruptible(&port->waitqueue);
+ }
}
EXPORT_SYMBOL_GPL(wwan_port_rx);
diff --git a/include/linux/wwan.h b/include/linux/wwan.h
index a4d6cc0c9f68..1e0e2cb53579 100644
--- a/include/linux/wwan.h
+++ b/include/linux/wwan.h
@@ -19,6 +19,7 @@
* @WWAN_PORT_FASTBOOT: Fastboot protocol control
* @WWAN_PORT_ADB: ADB protocol control
* @WWAN_PORT_MIPC: MTK MIPC diagnostic interface
+ * @WWAN_PORT_NMEA: embedded GNSS receiver with NMEA output
*
* @WWAN_PORT_MAX: Highest supported port types
* @WWAN_PORT_UNKNOWN: Special value to indicate an unknown port type
@@ -34,6 +35,7 @@ enum wwan_port_type {
WWAN_PORT_FASTBOOT,
WWAN_PORT_ADB,
WWAN_PORT_MIPC,
+ WWAN_PORT_NMEA,
/* Add new port types above this line */
--
2.25.1
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [net-next v3 4/8] net: wwan: add NMEA port support
2025-12-31 6:51 ` [net-next v3 4/8] net: wwan: add NMEA port support Slark Xiao
@ 2025-12-31 20:13 ` kernel test robot
0 siblings, 0 replies; 12+ messages in thread
From: kernel test robot @ 2025-12-31 20:13 UTC (permalink / raw)
To: Slark Xiao, loic.poulain, ryazanov.s.a, johannes, andrew+netdev,
davem, edumazet, kuba, pabeni, mani
Cc: oe-kbuild-all, netdev, linux-kernel, Slark Xiao,
Muhammad Nuzaihan, Qiang Yu, Manivannan Sadhasivam, Johan Hovold
Hi Slark,
kernel test robot noticed the following build warnings:
[auto build test WARNING on net-next/main]
url: https://github.com/intel-lab-lkp/linux/commits/Slark-Xiao/net-wwan-core-remove-unused-port_id-field/20251231-145913
base: net-next/main
patch link: https://lore.kernel.org/r/20251231065109.43378-5-slark_xiao%40163.com
patch subject: [net-next v3 4/8] net: wwan: add NMEA port support
config: x86_64-rhel-9.4-ltp (https://download.01.org/0day-ci/archive/20251231/202512312143.W82zclxI-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251231/202512312143.W82zclxI-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202512312143.W82zclxI-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> Warning: drivers/net/wwan/wwan_core.c:98 struct member 'gnss' not described in 'wwan_port'
>> Warning: drivers/net/wwan/wwan_core.c:98 struct member 'gnss' not described in 'wwan_port'
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 12+ messages in thread
* [net-next v3 5/8] net: wwan: hwsim: refactor to support more port types
2025-12-31 6:51 [net-next v3 0/8] net: wwan: add NMEA port type support Slark Xiao
` (3 preceding siblings ...)
2025-12-31 6:51 ` [net-next v3 4/8] net: wwan: add NMEA port support Slark Xiao
@ 2025-12-31 6:51 ` Slark Xiao
2025-12-31 6:51 ` [net-next v3 6/8] net: wwan: hwsim: support NMEA port emulation Slark Xiao
` (3 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Slark Xiao @ 2025-12-31 6:51 UTC (permalink / raw)
To: loic.poulain, ryazanov.s.a, johannes, andrew+netdev, davem,
edumazet, kuba, pabeni, mani
Cc: netdev, linux-kernel
From: Sergey Ryazanov <ryazanov.s.a@gmail.com>
Just introduced WWAN NMEA port type needs a testing option. The WWAN HW
simulator was developed with the AT port type in mind and cannot be
easily extended. Refactor it now to make it capable to support more port
types.
No big functional changes, mostly renaming with a little code
rearrangement.
Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
Reviewed-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
---
drivers/net/wwan/wwan_hwsim.c | 73 ++++++++++++++++++++---------------
1 file changed, 41 insertions(+), 32 deletions(-)
diff --git a/drivers/net/wwan/wwan_hwsim.c b/drivers/net/wwan/wwan_hwsim.c
index 733688cd4607..11d15dc39041 100644
--- a/drivers/net/wwan/wwan_hwsim.c
+++ b/drivers/net/wwan/wwan_hwsim.c
@@ -56,12 +56,16 @@ struct wwan_hwsim_port {
struct wwan_port *wwan;
struct work_struct del_work;
struct dentry *debugfs_topdir;
- enum { /* AT command parser state */
- AT_PARSER_WAIT_A,
- AT_PARSER_WAIT_T,
- AT_PARSER_WAIT_TERM,
- AT_PARSER_SKIP_LINE,
- } pstate;
+ union {
+ struct {
+ enum { /* AT command parser state */
+ AT_PARSER_WAIT_A,
+ AT_PARSER_WAIT_T,
+ AT_PARSER_WAIT_TERM,
+ AT_PARSER_SKIP_LINE,
+ } pstate;
+ } at_emul;
+ };
};
static const struct file_operations wwan_hwsim_debugfs_portdestroy_fops;
@@ -101,16 +105,16 @@ static const struct wwan_ops wwan_hwsim_wwan_rtnl_ops = {
.setup = wwan_hwsim_netdev_setup,
};
-static int wwan_hwsim_port_start(struct wwan_port *wport)
+static int wwan_hwsim_at_emul_start(struct wwan_port *wport)
{
struct wwan_hwsim_port *port = wwan_port_get_drvdata(wport);
- port->pstate = AT_PARSER_WAIT_A;
+ port->at_emul.pstate = AT_PARSER_WAIT_A;
return 0;
}
-static void wwan_hwsim_port_stop(struct wwan_port *wport)
+static void wwan_hwsim_at_emul_stop(struct wwan_port *wport)
{
}
@@ -120,7 +124,7 @@ static void wwan_hwsim_port_stop(struct wwan_port *wport)
*
* Be aware that this processor is not fully V.250 compliant.
*/
-static int wwan_hwsim_port_tx(struct wwan_port *wport, struct sk_buff *in)
+static int wwan_hwsim_at_emul_tx(struct wwan_port *wport, struct sk_buff *in)
{
struct wwan_hwsim_port *port = wwan_port_get_drvdata(wport);
struct sk_buff *out;
@@ -142,17 +146,17 @@ static int wwan_hwsim_port_tx(struct wwan_port *wport, struct sk_buff *in)
for (i = 0, s = 0; i < in->len; ++i) {
char c = in->data[i];
- if (port->pstate == AT_PARSER_WAIT_A) {
+ if (port->at_emul.pstate == AT_PARSER_WAIT_A) {
if (c == 'A' || c == 'a')
- port->pstate = AT_PARSER_WAIT_T;
+ port->at_emul.pstate = AT_PARSER_WAIT_T;
else if (c != '\n') /* Ignore formating char */
- port->pstate = AT_PARSER_SKIP_LINE;
- } else if (port->pstate == AT_PARSER_WAIT_T) {
+ port->at_emul.pstate = AT_PARSER_SKIP_LINE;
+ } else if (port->at_emul.pstate == AT_PARSER_WAIT_T) {
if (c == 'T' || c == 't')
- port->pstate = AT_PARSER_WAIT_TERM;
+ port->at_emul.pstate = AT_PARSER_WAIT_TERM;
else
- port->pstate = AT_PARSER_SKIP_LINE;
- } else if (port->pstate == AT_PARSER_WAIT_TERM) {
+ port->at_emul.pstate = AT_PARSER_SKIP_LINE;
+ } else if (port->at_emul.pstate == AT_PARSER_WAIT_TERM) {
if (c != '\r')
continue;
/* Consume the trailing formatting char as well */
@@ -162,11 +166,11 @@ static int wwan_hwsim_port_tx(struct wwan_port *wport, struct sk_buff *in)
skb_put_data(out, &in->data[s], n);/* Echo */
skb_put_data(out, "\r\nOK\r\n", 6);
s = i + 1;
- port->pstate = AT_PARSER_WAIT_A;
- } else if (port->pstate == AT_PARSER_SKIP_LINE) {
+ port->at_emul.pstate = AT_PARSER_WAIT_A;
+ } else if (port->at_emul.pstate == AT_PARSER_SKIP_LINE) {
if (c != '\r')
continue;
- port->pstate = AT_PARSER_WAIT_A;
+ port->at_emul.pstate = AT_PARSER_WAIT_A;
}
}
@@ -183,18 +187,25 @@ static int wwan_hwsim_port_tx(struct wwan_port *wport, struct sk_buff *in)
return 0;
}
-static const struct wwan_port_ops wwan_hwsim_port_ops = {
- .start = wwan_hwsim_port_start,
- .stop = wwan_hwsim_port_stop,
- .tx = wwan_hwsim_port_tx,
+static const struct wwan_port_ops wwan_hwsim_at_emul_port_ops = {
+ .start = wwan_hwsim_at_emul_start,
+ .stop = wwan_hwsim_at_emul_stop,
+ .tx = wwan_hwsim_at_emul_tx,
};
-static struct wwan_hwsim_port *wwan_hwsim_port_new(struct wwan_hwsim_dev *dev)
+static struct wwan_hwsim_port *wwan_hwsim_port_new(struct wwan_hwsim_dev *dev,
+ enum wwan_port_type type)
{
+ const struct wwan_port_ops *ops;
struct wwan_hwsim_port *port;
char name[0x10];
int err;
+ if (type == WWAN_PORT_AT)
+ ops = &wwan_hwsim_at_emul_port_ops;
+ else
+ return ERR_PTR(-EINVAL);
+
port = kzalloc(sizeof(*port), GFP_KERNEL);
if (!port)
return ERR_PTR(-ENOMEM);
@@ -205,9 +216,7 @@ static struct wwan_hwsim_port *wwan_hwsim_port_new(struct wwan_hwsim_dev *dev)
port->id = dev->port_idx++;
spin_unlock(&dev->ports_lock);
- port->wwan = wwan_create_port(&dev->dev, WWAN_PORT_AT,
- &wwan_hwsim_port_ops,
- NULL, port);
+ port->wwan = wwan_create_port(&dev->dev, type, ops, NULL, port);
if (IS_ERR(port->wwan)) {
err = PTR_ERR(port->wwan);
goto err_free_port;
@@ -392,7 +401,7 @@ static ssize_t wwan_hwsim_debugfs_portcreate_write(struct file *file,
struct wwan_hwsim_dev *dev = file->private_data;
struct wwan_hwsim_port *port;
- port = wwan_hwsim_port_new(dev);
+ port = wwan_hwsim_port_new(dev, WWAN_PORT_AT);
if (IS_ERR(port))
return PTR_ERR(port);
@@ -459,6 +468,8 @@ static int __init wwan_hwsim_init_devs(void)
int i, j;
for (i = 0; i < wwan_hwsim_devsnum; ++i) {
+ struct wwan_hwsim_port *port;
+
dev = wwan_hwsim_dev_new();
if (IS_ERR(dev))
return PTR_ERR(dev);
@@ -471,9 +482,7 @@ static int __init wwan_hwsim_init_devs(void)
* the simulator readiness time.
*/
for (j = 0; j < 2; ++j) {
- struct wwan_hwsim_port *port;
-
- port = wwan_hwsim_port_new(dev);
+ port = wwan_hwsim_port_new(dev, WWAN_PORT_AT);
if (IS_ERR(port))
return PTR_ERR(port);
--
2.25.1
^ permalink raw reply [flat|nested] 12+ messages in thread* [net-next v3 6/8] net: wwan: hwsim: support NMEA port emulation
2025-12-31 6:51 [net-next v3 0/8] net: wwan: add NMEA port type support Slark Xiao
` (4 preceding siblings ...)
2025-12-31 6:51 ` [net-next v3 5/8] net: wwan: hwsim: refactor to support more port types Slark Xiao
@ 2025-12-31 6:51 ` Slark Xiao
2025-12-31 6:51 ` [net-next v3 7/8] net: wwan: prevent premature device unregister when NMEA port is present Slark Xiao
` (2 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Slark Xiao @ 2025-12-31 6:51 UTC (permalink / raw)
To: loic.poulain, ryazanov.s.a, johannes, andrew+netdev, davem,
edumazet, kuba, pabeni, mani
Cc: netdev, linux-kernel
From: Sergey Ryazanov <ryazanov.s.a@gmail.com>
Support NMEA port emulation for the WWAN core GNSS port testing purpose.
Emulator produces pair of GGA + RMC sentences every second what should
be enough to fool gpsd into believing it is working with a NMEA GNSS
receiver.
If the GNSS system is enabled then one NMEA port will be created
automatically for the simulated WWAN device. Manual NMEA port creation
is not supported at the moment.
Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
---
drivers/net/wwan/wwan_hwsim.c | 128 +++++++++++++++++++++++++++++++++-
1 file changed, 126 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wwan/wwan_hwsim.c b/drivers/net/wwan/wwan_hwsim.c
index 11d15dc39041..e4b1bbff9af2 100644
--- a/drivers/net/wwan/wwan_hwsim.c
+++ b/drivers/net/wwan/wwan_hwsim.c
@@ -2,7 +2,7 @@
/*
* WWAN device simulator for WWAN framework testing.
*
- * Copyright (c) 2021, Sergey Ryazanov <ryazanov.s.a@gmail.com>
+ * Copyright (c) 2021, 2025, Sergey Ryazanov <ryazanov.s.a@gmail.com>
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -12,8 +12,10 @@
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/spinlock.h>
+#include <linux/time.h>
#include <linux/list.h>
#include <linux/skbuff.h>
+#include <linux/timer.h>
#include <linux/netdevice.h>
#include <linux/wwan.h>
#include <linux/debugfs.h>
@@ -65,6 +67,9 @@ struct wwan_hwsim_port {
AT_PARSER_SKIP_LINE,
} pstate;
} at_emul;
+ struct {
+ struct timer_list timer;
+ } nmea_emul;
};
};
@@ -193,6 +198,108 @@ static const struct wwan_port_ops wwan_hwsim_at_emul_port_ops = {
.tx = wwan_hwsim_at_emul_tx,
};
+#if IS_ENABLED(CONFIG_GNSS)
+#define NMEA_MAX_LEN 82 /* Max sentence length */
+#define NMEA_TRAIL_LEN 5 /* '*' + Checksum + <CR><LF> */
+#define NMEA_MAX_DATA_LEN (NMEA_MAX_LEN - NMEA_TRAIL_LEN)
+
+static __printf(2, 3)
+void wwan_hwsim_nmea_skb_push_sentence(struct sk_buff *skb,
+ const char *fmt, ...)
+{
+ unsigned char *s, *p;
+ va_list ap;
+ u8 cs = 0;
+ int len;
+
+ s = skb_put(skb, NMEA_MAX_LEN + 1); /* +'\0' */
+ if (!s)
+ return;
+
+ va_start(ap, fmt);
+ len = vsnprintf(s, NMEA_MAX_DATA_LEN + 1, fmt, ap);
+ va_end(ap);
+ if (WARN_ON_ONCE(len > NMEA_MAX_DATA_LEN))/* No space for trailer */
+ return;
+
+ for (p = s + 1; *p != '\0'; ++p)/* Skip leading '$' or '!' */
+ cs ^= *p;
+ p += snprintf(p, 5 + 1, "*%02X\r\n", cs);
+
+ len = (p - s) - (NMEA_MAX_LEN + 1); /* exp. vs real length diff */
+ skb->tail += len; /* Adjust tail to real length */
+ skb->len += len;
+}
+
+static void wwan_hwsim_nmea_emul_timer(struct timer_list *t)
+{
+ /* 43.74754722298909 N 11.25759835922875 E in DMM format */
+ static const unsigned int coord[4 * 2] = { 43, 44, 8528, 0,
+ 11, 15, 4559, 0 };
+ struct wwan_hwsim_port *port = timer_container_of(port, t, nmea_emul.timer);
+ struct sk_buff *skb;
+ struct tm tm;
+
+ time64_to_tm(ktime_get_real_seconds(), 0, &tm);
+
+ mod_timer(&port->nmea_emul.timer, jiffies + HZ); /* 1 second */
+
+ skb = alloc_skb(NMEA_MAX_LEN * 2, GFP_KERNEL); /* GGA + RMC */
+ if (!skb)
+ return;
+
+ wwan_hwsim_nmea_skb_push_sentence(skb,
+ "$GPGGA,%02u%02u%02u.000,%02u%02u.%04u,%c,%03u%02u.%04u,%c,1,7,1.03,176.2,M,55.2,M,,",
+ tm.tm_hour, tm.tm_min, tm.tm_sec,
+ coord[0], coord[1], coord[2],
+ coord[3] ? 'S' : 'N',
+ coord[4], coord[5], coord[6],
+ coord[7] ? 'W' : 'E');
+
+ wwan_hwsim_nmea_skb_push_sentence(skb,
+ "$GPRMC,%02u%02u%02u.000,A,%02u%02u.%04u,%c,%03u%02u.%04u,%c,0.02,31.66,%02u%02u%02u,,,A",
+ tm.tm_hour, tm.tm_min, tm.tm_sec,
+ coord[0], coord[1], coord[2],
+ coord[3] ? 'S' : 'N',
+ coord[4], coord[5], coord[6],
+ coord[7] ? 'W' : 'E',
+ tm.tm_mday, tm.tm_mon + 1,
+ (unsigned int)tm.tm_year - 100);
+
+ wwan_port_rx(port->wwan, skb);
+}
+
+static int wwan_hwsim_nmea_emul_start(struct wwan_port *wport)
+{
+ struct wwan_hwsim_port *port = wwan_port_get_drvdata(wport);
+
+ timer_setup(&port->nmea_emul.timer, wwan_hwsim_nmea_emul_timer, 0);
+ wwan_hwsim_nmea_emul_timer(&port->nmea_emul.timer);
+
+ return 0;
+}
+
+static void wwan_hwsim_nmea_emul_stop(struct wwan_port *wport)
+{
+ struct wwan_hwsim_port *port = wwan_port_get_drvdata(wport);
+
+ timer_delete_sync(&port->nmea_emul.timer);
+}
+
+static int wwan_hwsim_nmea_emul_tx(struct wwan_port *wport, struct sk_buff *in)
+{
+ consume_skb(in);
+
+ return 0;
+}
+
+static const struct wwan_port_ops wwan_hwsim_nmea_emul_port_ops = {
+ .start = wwan_hwsim_nmea_emul_start,
+ .stop = wwan_hwsim_nmea_emul_stop,
+ .tx = wwan_hwsim_nmea_emul_tx,
+};
+#endif
+
static struct wwan_hwsim_port *wwan_hwsim_port_new(struct wwan_hwsim_dev *dev,
enum wwan_port_type type)
{
@@ -203,6 +310,10 @@ static struct wwan_hwsim_port *wwan_hwsim_port_new(struct wwan_hwsim_dev *dev,
if (type == WWAN_PORT_AT)
ops = &wwan_hwsim_at_emul_port_ops;
+#if IS_ENABLED(CONFIG_GNSS)
+ else if (type == WWAN_PORT_NMEA)
+ ops = &wwan_hwsim_nmea_emul_port_ops;
+#endif
else
return ERR_PTR(-EINVAL);
@@ -478,9 +589,10 @@ static int __init wwan_hwsim_init_devs(void)
list_add_tail(&dev->list, &wwan_hwsim_devs);
spin_unlock(&wwan_hwsim_devs_lock);
- /* Create a couple of ports per each device to accelerate
+ /* Create a few various ports per each device to accelerate
* the simulator readiness time.
*/
+
for (j = 0; j < 2; ++j) {
port = wwan_hwsim_port_new(dev, WWAN_PORT_AT);
if (IS_ERR(port))
@@ -490,6 +602,18 @@ static int __init wwan_hwsim_init_devs(void)
list_add_tail(&port->list, &dev->ports);
spin_unlock(&dev->ports_lock);
}
+
+#if IS_ENABLED(CONFIG_GNSS)
+ port = wwan_hwsim_port_new(dev, WWAN_PORT_NMEA);
+ if (IS_ERR(port)) {
+ dev_warn(&dev->dev, "failed to create initial NMEA port: %d\n",
+ (int)PTR_ERR(port));
+ } else {
+ spin_lock(&dev->ports_lock);
+ list_add_tail(&port->list, &dev->ports);
+ spin_unlock(&dev->ports_lock);
+ }
+#endif
}
return 0;
--
2.25.1
^ permalink raw reply [flat|nested] 12+ messages in thread* [net-next v3 7/8] net: wwan: prevent premature device unregister when NMEA port is present
2025-12-31 6:51 [net-next v3 0/8] net: wwan: add NMEA port type support Slark Xiao
` (5 preceding siblings ...)
2025-12-31 6:51 ` [net-next v3 6/8] net: wwan: hwsim: support NMEA port emulation Slark Xiao
@ 2025-12-31 6:51 ` Slark Xiao
2025-12-31 6:51 ` [net-next v3 8/8] net: wwan: mhi_wwan_ctrl: Add NMEA channel support Slark Xiao
2025-12-31 9:06 ` [net-next v3 0/8] net: wwan: add NMEA port type support Paolo Abeni
8 siblings, 0 replies; 12+ messages in thread
From: Slark Xiao @ 2025-12-31 6:51 UTC (permalink / raw)
To: loic.poulain, ryazanov.s.a, johannes, andrew+netdev, davem,
edumazet, kuba, pabeni, mani
Cc: netdev, linux-kernel, Daniele Palmas
From: Loic Poulain <loic.poulain@oss.qualcomm.com>
The WWAN core unregisters the device when it has no remaining WWAN ops
or child devices. For NMEA port types, the child is registered under
the GNSS class instead of WWAN, so the core incorrectly assumes there
are no children and unregisters the WWAN device too early. This leads
to a second unregister attempt after the NMEA device is removed.
To fix this issue, we register a virtual WWAN port device along the
GNSS device, this ensures the WWAN device remains registered until
all associated ports, including NMEA, are properly removed.
Reported-by: Daniele Palmas <dnlplm@gmail.com>
Closes: https://lore.kernel.org/netdev/CAGRyCJE28yf-rrfkFbzu44ygLEvoUM7fecK1vnrghjG_e9UaRA@mail.gmail.com/
Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
---
drivers/net/wwan/wwan_core.c | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/drivers/net/wwan/wwan_core.c b/drivers/net/wwan/wwan_core.c
index 93998b498454..40a57fb0aa0b 100644
--- a/drivers/net/wwan/wwan_core.c
+++ b/drivers/net/wwan/wwan_core.c
@@ -455,7 +455,7 @@ static int __wwan_port_dev_assign_name(struct wwan_port *port, const char *fmt)
}
/* Register a regular WWAN port device (e.g. AT, MBIM, etc.) */
-static int wwan_port_register_wwan(struct wwan_port *port)
+static int wwan_port_register_wwan(struct wwan_port *port, bool cdev)
{
struct wwan_device *wwandev = to_wwan_dev(port->dev.parent);
char namefmt[0x20];
@@ -467,7 +467,8 @@ static int wwan_port_register_wwan(struct wwan_port *port)
return minor;
port->dev.class = &wwan_class;
- port->dev.devt = MKDEV(wwan_major, minor);
+ if (cdev)
+ port->dev.devt = MKDEV(wwan_major, minor);
/* allocate unique name based on wwan device id, port type and number */
snprintf(namefmt, sizeof(namefmt), "wwan%u%s%%d", wwandev->id,
@@ -625,6 +626,7 @@ struct wwan_port *wwan_create_port(struct device *parent,
struct wwan_port_caps *caps,
void *drvdata)
{
+ bool cdev = (type == WWAN_PORT_NMEA) ? false : true;
struct wwan_device *wwandev;
struct wwan_port *port;
int err;
@@ -659,16 +661,20 @@ struct wwan_port *wwan_create_port(struct device *parent,
dev_set_drvdata(&port->dev, drvdata);
device_initialize(&port->dev);
- if (port->type == WWAN_PORT_NMEA)
- err = wwan_port_register_gnss(port);
- else
- err = wwan_port_register_wwan(port);
-
+ err = wwan_port_register_wwan(port, cdev);
if (err)
goto error_put_device;
+ if (type == WWAN_PORT_NMEA) {
+ err = wwan_port_register_gnss(port);
+ if (err)
+ goto error_port_unregister;
+ }
+
return port;
+error_port_unregister:
+ wwan_port_unregister_wwan(port);
error_put_device:
put_device(&port->dev);
error_wwandev_remove:
@@ -695,8 +701,8 @@ void wwan_remove_port(struct wwan_port *port)
if (port->type == WWAN_PORT_NMEA)
wwan_port_unregister_gnss(port);
- else
- wwan_port_unregister_wwan(port);
+
+ wwan_port_unregister_wwan(port);
put_device(&port->dev);
--
2.25.1
^ permalink raw reply [flat|nested] 12+ messages in thread* [net-next v3 8/8] net: wwan: mhi_wwan_ctrl: Add NMEA channel support
2025-12-31 6:51 [net-next v3 0/8] net: wwan: add NMEA port type support Slark Xiao
` (6 preceding siblings ...)
2025-12-31 6:51 ` [net-next v3 7/8] net: wwan: prevent premature device unregister when NMEA port is present Slark Xiao
@ 2025-12-31 6:51 ` Slark Xiao
2025-12-31 9:06 ` [net-next v3 0/8] net: wwan: add NMEA port type support Paolo Abeni
8 siblings, 0 replies; 12+ messages in thread
From: Slark Xiao @ 2025-12-31 6:51 UTC (permalink / raw)
To: loic.poulain, ryazanov.s.a, johannes, andrew+netdev, davem,
edumazet, kuba, pabeni, mani
Cc: netdev, linux-kernel, Slark Xiao
For MHI WWAN device, we need a match between NMEA channel and
WWAN_PORT_NMEA type. Then the GNSS subsystem could create the
gnss device succssfully.
Signed-off-by: Slark Xiao <slark_xiao@163.com>
---
drivers/net/wwan/mhi_wwan_ctrl.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wwan/mhi_wwan_ctrl.c b/drivers/net/wwan/mhi_wwan_ctrl.c
index e9f979d2d851..e13c0b078175 100644
--- a/drivers/net/wwan/mhi_wwan_ctrl.c
+++ b/drivers/net/wwan/mhi_wwan_ctrl.c
@@ -263,6 +263,7 @@ static const struct mhi_device_id mhi_wwan_ctrl_match_table[] = {
{ .chan = "QMI", .driver_data = WWAN_PORT_QMI },
{ .chan = "DIAG", .driver_data = WWAN_PORT_QCDM },
{ .chan = "FIREHOSE", .driver_data = WWAN_PORT_FIREHOSE },
+ { .chan = "NMEA", .driver_data = WWAN_PORT_NMEA },
{},
};
MODULE_DEVICE_TABLE(mhi, mhi_wwan_ctrl_match_table);
--
2.25.1
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [net-next v3 0/8] net: wwan: add NMEA port type support
2025-12-31 6:51 [net-next v3 0/8] net: wwan: add NMEA port type support Slark Xiao
` (7 preceding siblings ...)
2025-12-31 6:51 ` [net-next v3 8/8] net: wwan: mhi_wwan_ctrl: Add NMEA channel support Slark Xiao
@ 2025-12-31 9:06 ` Paolo Abeni
2025-12-31 9:52 ` Slark Xiao
8 siblings, 1 reply; 12+ messages in thread
From: Paolo Abeni @ 2025-12-31 9:06 UTC (permalink / raw)
To: Slark Xiao
Cc: netdev, linux-kernel, Muhammad Nuzaihan, Qiang Yu,
Manivannan Sadhasivam, Johan Hovold, ryazanov.s.a, johannes,
loic.poulain, andrew+netdev, davem, edumazet, mani, kuba
On 12/31/25 7:51 AM, Slark Xiao wrote:
> The series introduces a long discussed NMEA port type support for the
> WWAN subsystem. There are two goals. From the WWAN driver perspective,
> NMEA exported as any other port type (e.g. AT, MBIM, QMI, etc.). From
> user space software perspective, the exported chardev belongs to the
> GNSS class what makes it easy to distinguish desired port and the WWAN
> device common to both NMEA and control (AT, MBIM, etc.) ports makes it
> easy to locate a control port for the GNSS receiver activation.
>
> Done by exporting the NMEA port via the GNSS subsystem with the WWAN
> core acting as proxy between the WWAN modem driver and the GNSS
> subsystem.
>
> The series starts from a cleanup patch. Then two patches prepares the
> WWAN core for the proxy style operation. Followed by a patch introding a
> new WWNA port type, integration with the GNSS subsystem and demux. The
> series ends with a couple of patches that introduce emulated EMEA port
> to the WWAN HW simulator.
>
> The series is the product of the discussion with Loic about the pros and
> cons of possible models and implementation. Also Muhammad and Slark did
> a great job defining the problem, sharing the code and pushing me to
> finish the implementation. Many thanks.
>
> Comments are welcomed.
>
> Changes since V1:
> Uniformly use put_device() to release port memory. This made code less
> weird and way more clear. Thank you, Loic, for noticing and the fix
> discussion!
>
> Changes since V2:
> Add supplement of Loic and Slark about some fix
>
> CC: Slark Xiao <slark_xiao@163.com>
> CC: Muhammad Nuzaihan <zaihan@unrealasia.net>
> CC: Qiang Yu <quic_qianyu@quicinc.com>
> CC: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
> CC: Johan Hovold <johan@kernel.org>
> CC: Sergey Ryazanov <ryazanov.s.a@gmail.com>
Uhm... I thingh I already shared the following with you ?!?
## Form letter - net-next-closed
The net-next tree is closed for new drivers, features, code refactoring
and optimizations due to the merge window and the winter break. We are
currently accepting bug fixes only.
Please repost when net-next reopens after Jan 2nd.
RFC patches sent for review only are obviously welcome at any time.
^ permalink raw reply [flat|nested] 12+ messages in thread* Re:Re: [net-next v3 0/8] net: wwan: add NMEA port type support
2025-12-31 9:06 ` [net-next v3 0/8] net: wwan: add NMEA port type support Paolo Abeni
@ 2025-12-31 9:52 ` Slark Xiao
0 siblings, 0 replies; 12+ messages in thread
From: Slark Xiao @ 2025-12-31 9:52 UTC (permalink / raw)
To: Paolo Abeni
Cc: netdev, linux-kernel, Muhammad Nuzaihan, Qiang Yu,
Manivannan Sadhasivam, Johan Hovold, ryazanov.s.a, johannes,
loic.poulain, andrew+netdev, davem, edumazet, mani, kuba
At 2025-12-31 17:06:29, "Paolo Abeni" <pabeni@redhat.com> wrote:
>On 12/31/25 7:51 AM, Slark Xiao wrote:
>> The series introduces a long discussed NMEA port type support for the
>> WWAN subsystem. There are two goals. From the WWAN driver perspective,
>> NMEA exported as any other port type (e.g. AT, MBIM, QMI, etc.). From
>> user space software perspective, the exported chardev belongs to the
>> GNSS class what makes it easy to distinguish desired port and the WWAN
>> device common to both NMEA and control (AT, MBIM, etc.) ports makes it
>> easy to locate a control port for the GNSS receiver activation.
>>
>> Done by exporting the NMEA port via the GNSS subsystem with the WWAN
>> core acting as proxy between the WWAN modem driver and the GNSS
>> subsystem.
>>
>> The series starts from a cleanup patch. Then two patches prepares the
>> WWAN core for the proxy style operation. Followed by a patch introding a
>> new WWNA port type, integration with the GNSS subsystem and demux. The
>> series ends with a couple of patches that introduce emulated EMEA port
>> to the WWAN HW simulator.
>>
>> The series is the product of the discussion with Loic about the pros and
>> cons of possible models and implementation. Also Muhammad and Slark did
>> a great job defining the problem, sharing the code and pushing me to
>> finish the implementation. Many thanks.
>>
>> Comments are welcomed.
>>
>> Changes since V1:
>> Uniformly use put_device() to release port memory. This made code less
>> weird and way more clear. Thank you, Loic, for noticing and the fix
>> discussion!
>>
>> Changes since V2:
>> Add supplement of Loic and Slark about some fix
>>
>> CC: Slark Xiao <slark_xiao@163.com>
>> CC: Muhammad Nuzaihan <zaihan@unrealasia.net>
>> CC: Qiang Yu <quic_qianyu@quicinc.com>
>> CC: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
>> CC: Johan Hovold <johan@kernel.org>
>> CC: Sergey Ryazanov <ryazanov.s.a@gmail.com>
>
>Uhm... I thingh I already shared the following with you ?!?
>
>## Form letter - net-next-closed
>
>The net-next tree is closed for new drivers, features, code refactoring
>and optimizations due to the merge window and the winter break. We are
>currently accepting bug fixes only.
>
>Please repost when net-next reopens after Jan 2nd.
>
>RFC patches sent for review only are obviously welcome at any time.
Yeah, I have received that notice.
Since there is a holiday from Jan 1st to Jan 4th, so I post them to net-next in advance.
You can start to review it after Jan 2nd(according to my previous experience,
maintainer will ignore these patches until the merge window is opened).
Thank you for your notice again.
Happy new year!
^ permalink raw reply [flat|nested] 12+ messages in thread