From nobody Mon Feb 9 12:28:47 2026 Received: from m16.mail.163.com (m16.mail.163.com [220.197.31.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 230EE3806B7; Thu, 15 Jan 2026 11:47:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=220.197.31.2 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768477652; cv=none; b=nFZj+GfVMQIAQlXkYDpZp0/oEdxODTNlOHjBaF0YFV95wb/cCAntei4FzLekqoQN3OsHXHELMLcdepHpwLXGIHTR6TVqJ5AgxafRwIvux6KcX9XqeMvTYIeL5AXOx7bvNCPN5wxLcGAigkKesklP8zczQPl0+0rkF1fXUFfcZCg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768477652; c=relaxed/simple; bh=DOndyKOPHC+XjWwo8IQmKVVgE+2YxR9PrmL7vaEb2Uk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=QqEUV2BwSwNYn3TXapOk6dPoNeGWFh6qnzD+Dm+3O90aoC2gVS9oEcjG8uSlI6hAe3r1QIfv5W/9Qf2+OeUKA2KXdgu7Oyfv3muL/QaV+A01WF7j6HPC90E6fVk7KyoN64FAEsk1Wh3sIogxtQxCEw//ebGi/bY4FFWXmULBcVk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com; spf=pass smtp.mailfrom=163.com; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b=enbuSupH; arc=none smtp.client-ip=220.197.31.2 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=163.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b="enbuSupH" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:To:Subject:Date:Message-Id:MIME-Version; bh=vk 5iutERJA27zH/tcNhHf5mNR2d/fQros4GcMViC0s4=; b=enbuSupH6cvbsQ4bAc /V6ixb+Da5H8ipj4dbgwgcgWOZJpUWxHifAuEwlIpfsPl6UG0YlgPOtszovA47Gf 55HpHPygrnsibnh/MLgJDHFg7LGVXLCW4VZdWicXIrLJs6X3fmH/uSqu323dBixs SW58fAGEUuEIZFtKNPeuvqY60= Received: from localhost.localdomain (unknown []) by gzga-smtp-mtada-g1-3 (Coremail) with SMTP id _____wBHLGiX02hpr2PzGQ--.4331S3; Thu, 15 Jan 2026 19:46:37 +0800 (CST) From: Slark Xiao To: loic.poulain@oss.qualcomm.com, ryazanov.s.a@gmail.com, johannes@sipsolutions.net, andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, mani@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, slark_xiao@163.com Subject: [net-next v7 1/8] net: wwan: core: remove unused port_id field Date: Thu, 15 Jan 2026 19:46:18 +0800 Message-Id: <20260115114625.46991-2-slark_xiao@163.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260115114625.46991-1-slark_xiao@163.com> References: <20260115114625.46991-1-slark_xiao@163.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: _____wBHLGiX02hpr2PzGQ--.4331S3 X-Coremail-Antispam: 1Uf129KBjvdXoW7Jw15Jr48Kw1DZF1fKw17ZFb_yoWkGwbEkr nYvrZ5Z348CFyvvr42gF43ZFWFvF4IqF4kuwnaqrZ3AFWDXrWrW3Z8XFnrWrn8ur18ZrZr WrZrXFs2vr1fKjkaLaAFLSUrUUUUjb8apTn2vfkv8UJUUUU8Yxn0WfASr-VFAUDa7-sFnT 9fnUUvcSsGvfC2KfnxnUUI43ZEXa7sR_a9aJUUUUU== X-CM-SenderInfo: xvod2y5b0lt0i6rwjhhfrp/xtbC5x2Q9Glo0538PwAA3S Content-Type: text/plain; charset="utf-8" From: Sergey Ryazanov 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 Reviewed-by: Loic Poulain --- 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 --=20 2.25.1 From nobody Mon Feb 9 12:28:47 2026 Received: from m16.mail.163.com (m16.mail.163.com [117.135.210.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7ABD4393DE8; Thu, 15 Jan 2026 11:47:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=117.135.210.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768477655; cv=none; b=DMZAL9l4wTg3ZfKZSZ1oSCzF/+pw/KjG1da1osAuPJS8oVHyq8HGKe9M+WkDvYzG0AeDCy2ZWiqe3X6dofu+/bH49w/scXF8Q2Ze8GM6yYuXzVwMp5ip26U7o+RmS60hywP29gqVrEeKXlLRfyWkIBjKESYOs3lPeM5moJrnlVE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768477655; c=relaxed/simple; bh=4DVhCl4gbIXZz7OZyWroJqYsJfVpaSbkJ/cFhnuOB1c=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=U1/0VPvJzYnMhcHHBGegbU+7wZFyPLBXWBjutIPPXtV/wGCJwaQ/fN/BRljh6lPiksIyqmZgj+aA3byIezRt7swhNqN1q/Jxy4CfWoSkR5r8RzFzksGPU4nSPyUs1WULQ8JGNvcHhJ5DkpmpWXyVDf8+JU5N2AdVbdh69YgGr6k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com; spf=pass smtp.mailfrom=163.com; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b=A+xS9meI; arc=none smtp.client-ip=117.135.210.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=163.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b="A+xS9meI" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:To:Subject:Date:Message-Id:MIME-Version; bh=ez xx3sezb37S1HGZPsf+TTq5UcEdoA3/kKhmJ7zHOx4=; b=A+xS9meIXscL+2kO/C sGy6dF0UVWU9eJUUf96HIbXlHtXrgMpSvu+jDelMxOkcPwNNNuC0Rr7G3mzw3dQg 18yu4NxyVfs2EDg47TORcGR3U26/rdOxT5UEfAyhD30YP7Mf2MpqL/KEUVu75ASp KazA22+jWQREVsKP97HPP8pJ4= Received: from localhost.localdomain (unknown []) by gzga-smtp-mtada-g1-3 (Coremail) with SMTP id _____wBHLGiX02hpr2PzGQ--.4331S4; Thu, 15 Jan 2026 19:46:40 +0800 (CST) From: Slark Xiao To: loic.poulain@oss.qualcomm.com, ryazanov.s.a@gmail.com, johannes@sipsolutions.net, andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, mani@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, slark_xiao@163.com, Daniele Palmas Subject: [net-next v7 2/8] net: wwan: core: explicit WWAN device reference counting Date: Thu, 15 Jan 2026 19:46:19 +0800 Message-Id: <20260115114625.46991-3-slark_xiao@163.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260115114625.46991-1-slark_xiao@163.com> References: <20260115114625.46991-1-slark_xiao@163.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: _____wBHLGiX02hpr2PzGQ--.4331S4 X-Coremail-Antispam: 1Uf129KBjvJXoWxCw13Gry8Gw45Xry7CFyxuFg_yoWrZF47pa y3KFy3KFW8Jr4Uu39avr47XFyF9a1xCw1ft348W34Fkry3tryrXrWUXFyYqFy8tFWkCF45 urWUta18CF4UW3DanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x0pRUUUUUUUUU= X-CM-SenderInfo: xvod2y5b0lt0i6rwjhhfrp/xtbC6AKR9Wlo06L4BAAA3C Content-Type: text/plain; charset="utf-8" From: Sergey Ryazanov We need information about existing WWAN device children since we remove the device after removing the last child. Previously, we tracked users implicitly by checking whether ops was registered and existence of a child device of the wwan_class class. Upcoming GNSS (NMEA) port type support breaks this approach by introducing a child device of the gnss_class class. And a modem driver can easily trigger a kernel Oops by removing regular (e.g., MBIM, AT) ports first and then removing a GNSS port. The WWAN device will be unregistered on removal of a last regular WWAN port. And subsequent GNSS port removal will cause NULL pointer dereference in simple_recursive_removal(). In order to support ports of classes other than wwan_class, switch to explicit references counting. Introduce a dedicated counter to the WWAN device struct, increment it on every wwan_create_dev() call, decrement on wwan_remove_dev(), and actually unregister the WWAN device when there are no more references. Run tested with wwan_hwsim with NMEA support patches applied and different port removing sequences. Reported-by: Daniele Palmas Closes: https://lore.kernel.org/netdev/CAGRyCJE28yf-rrfkFbzu44ygLEvoUM7fecK= 1vnrghjG_e9UaRA@mail.gmail.com/ Suggested-by: Loic Poulain Signed-off-by: Sergey Ryazanov --- drivers/net/wwan/wwan_core.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/drivers/net/wwan/wwan_core.c b/drivers/net/wwan/wwan_core.c index ade8bbffc93e..1da935e84008 100644 --- a/drivers/net/wwan/wwan_core.c +++ b/drivers/net/wwan/wwan_core.c @@ -42,6 +42,9 @@ static struct dentry *wwan_debugfs_dir; * struct wwan_device - The structure that defines a WWAN device * * @id: WWAN device unique ID. + * @refcount: Reference count of this WWAN device. When this refcount reac= hes + * zero, the device is deleted. NB: access is protected by global + * wwan_register_lock mutex. * @dev: Underlying device. * @ops: wwan device ops * @ops_ctxt: context to pass to ops @@ -49,6 +52,7 @@ static struct dentry *wwan_debugfs_dir; */ struct wwan_device { unsigned int id; + int refcount; struct device dev; const struct wwan_ops *ops; void *ops_ctxt; @@ -222,8 +226,10 @@ static struct wwan_device *wwan_create_dev(struct devi= ce *parent) =20 /* If wwandev already exists, return it */ wwandev =3D wwan_dev_get_by_parent(parent); - if (!IS_ERR(wwandev)) + if (!IS_ERR(wwandev)) { + wwandev->refcount++; goto done_unlock; + } =20 id =3D ida_alloc(&wwan_dev_ids, GFP_KERNEL); if (id < 0) { @@ -242,6 +248,7 @@ static struct wwan_device *wwan_create_dev(struct devic= e *parent) wwandev->dev.class =3D &wwan_class; wwandev->dev.type =3D &wwan_dev_type; wwandev->id =3D id; + wwandev->refcount =3D 1; dev_set_name(&wwandev->dev, "wwan%d", wwandev->id); =20 err =3D device_register(&wwandev->dev); @@ -263,30 +270,18 @@ static struct wwan_device *wwan_create_dev(struct dev= ice *parent) return wwandev; } =20 -static int is_wwan_child(struct device *dev, void *data) -{ - return dev->class =3D=3D &wwan_class; -} - static void wwan_remove_dev(struct wwan_device *wwandev) { - int ret; - /* Prevent concurrent picking from wwan_create_dev */ mutex_lock(&wwan_register_lock); =20 - /* WWAN device is created and registered (get+add) along with its first - * child port, and subsequent port registrations only grab a reference - * (get). The WWAN device must then be unregistered (del+put) along with - * its last port, and reference simply dropped (put) otherwise. In the - * same fashion, we must not unregister it when the ops are still there. - */ - if (wwandev->ops) - ret =3D 1; - else - ret =3D device_for_each_child(&wwandev->dev, NULL, is_wwan_child); + if (--wwandev->refcount <=3D 0) { + struct device *child =3D device_find_any_child(&wwandev->dev); + + put_device(child); + if (WARN_ON(wwandev->ops || child)) /* Paranoid */ + goto out_unlock; =20 - if (!ret) { #ifdef CONFIG_WWAN_DEBUGFS debugfs_remove_recursive(wwandev->debugfs_dir); #endif @@ -295,6 +290,7 @@ static void wwan_remove_dev(struct wwan_device *wwandev) put_device(&wwandev->dev); } =20 +out_unlock: mutex_unlock(&wwan_register_lock); } =20 --=20 2.25.1 From nobody Mon Feb 9 12:28:47 2026 Received: from m16.mail.163.com (m16.mail.163.com [220.197.31.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C2C8C38A9B6; Thu, 15 Jan 2026 11:47:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=220.197.31.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768477643; cv=none; b=GuEv9ubuPktt/S13TOyMX2DCE9ndJsX8Z0+OhXPUm4OlhyuJwlCxS7stGYgr9hXYuTQqNqZRrVIkHiWoclcNIVK0RbLSGByvfgVN0ZqtMYucj1wnCg+C0IwTWN56uJf9mcUDfG6frmPkWp4ZqpYNliXlbFERyXoQDI/MjC3N5Fs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768477643; c=relaxed/simple; bh=h2aKPbYYSCfPFp+IaCbNK1a2/jGwBhkzQ4eo2a8O6QQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=iIbHHdHliHW3jS+tULjiCZCn1j3vSqDDYUa5XQf41LFNbGPhFH3kEyn+nNCCq8Qa752qI4ra13L7SZgMDUqolAUZNNGSzQRx0Npd1YjmzWye1q+1VtLs+MJKJvhtL/eJNxY/hVzro8HL4zkpcv6WABaGzyPEGJSJD1kvQYFtPzw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com; spf=pass smtp.mailfrom=163.com; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b=UBMq8LG9; arc=none smtp.client-ip=220.197.31.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=163.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b="UBMq8LG9" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:To:Subject:Date:Message-Id:MIME-Version; bh=3U FBFgL70KdmPe6agoutZjKBWX5ibQPwtUx3H8N2FHE=; b=UBMq8LG9hTsmdHPuU2 PT/mdryuI1PwSqMITEyqLNjW/7zIlhs7/K0BFvL5oyGeNSkg1cz1Wb5PpdVdAgGV AKVLuGuKFmLt00BTRoZ/jWpIPJUCiiKsTsM6qxwiwv01yY2SZRnZ3tziOVcn8XnS frFefJ8sRhxnGNoKG/WM+Kapg= Received: from localhost.localdomain (unknown []) by gzga-smtp-mtada-g1-3 (Coremail) with SMTP id _____wBHLGiX02hpr2PzGQ--.4331S5; Thu, 15 Jan 2026 19:46:43 +0800 (CST) From: Slark Xiao To: loic.poulain@oss.qualcomm.com, ryazanov.s.a@gmail.com, johannes@sipsolutions.net, andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, mani@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, slark_xiao@163.com Subject: [net-next v7 3/8] net: wwan: core: split port creation and registration Date: Thu, 15 Jan 2026 19:46:20 +0800 Message-Id: <20260115114625.46991-4-slark_xiao@163.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260115114625.46991-1-slark_xiao@163.com> References: <20260115114625.46991-1-slark_xiao@163.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: _____wBHLGiX02hpr2PzGQ--.4331S5 X-Coremail-Antispam: 1Uf129KBjvJXoWxJFWkAw45CFWxKFW5Jw1xuFg_yoWrZF4kp3 W0gas5tFW8Jrnrur43AF47ZF4rua1Ik34IyrW8W34Skrn0qryFvFZY9FyqvFWrGFy7GFy3 Xrs8ta10ka4UWr7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x0zRrhLnUUUUU= X-CM-SenderInfo: xvod2y5b0lt0i6rwjhhfrp/xtbCwASS9mlo06Tm+gAA3K Content-Type: text/plain; charset="utf-8" From: Sergey Ryazanov 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. While at it, fix a minor number leak upon WWAN port registration failure. Signed-off-by: Sergey Ryazanov --- drivers/net/wwan/wwan_core.c | 68 ++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/drivers/net/wwan/wwan_core.c b/drivers/net/wwan/wwan_core.c index 1da935e84008..1a9a77d597e6 100644 --- a/drivers/net/wwan/wwan_core.c +++ b/drivers/net/wwan/wwan_core.c @@ -357,7 +357,8 @@ static void wwan_port_destroy(struct device *dev) { struct wwan_port *port =3D to_wwan_port(dev); =20 - ida_free(&minors, MINOR(port->dev.devt)); + if (dev->class =3D=3D &wwan_class) + ida_free(&minors, MINOR(dev->devt)); mutex_destroy(&port->data_lock); mutex_destroy(&port->ops_lock); kfree(port); @@ -436,6 +437,43 @@ static int __wwan_port_dev_assign_name(struct wwan_por= t *port, const char *fmt) return dev_set_name(&port->dev, "%s", buf); } =20 +/* 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 =3D to_wwan_dev(port->dev.parent); + char namefmt[0x20]; + int minor, err; + + /* A port is exposed as character device, get a minor */ + minor =3D ida_alloc_range(&minors, 0, WWAN_MAX_MINORS - 1, GFP_KERNEL); + if (minor < 0) + return minor; + + port->dev.class =3D &wwan_class; + port->dev.devt =3D 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 =3D device_add(&port->dev); + + mutex_unlock(&wwan_register_lock); + + if (err) { + ida_free(&minors, minor); + 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, @@ -444,8 +482,7 @@ struct wwan_port *wwan_create_port(struct device *paren= t, { struct wwan_device *wwandev; struct wwan_port *port; - char namefmt[0x20]; - int minor, err; + int err; =20 if (type > WWAN_PORT_MAX || !ops) return ERR_PTR(-EINVAL); @@ -457,17 +494,9 @@ struct wwan_port *wwan_create_port(struct device *pare= nt, if (IS_ERR(wwandev)) return ERR_CAST(wwandev); =20 - /* A port is exposed as character device, get a minor */ - minor =3D ida_alloc_range(&minors, 0, WWAN_MAX_MINORS - 1, GFP_KERNEL); - if (minor < 0) { - err =3D minor; - goto error_wwandev_remove; - } - port =3D kzalloc(sizeof(*port), GFP_KERNEL); if (!port) { err =3D -ENOMEM; - ida_free(&minors, minor); goto error_wwandev_remove; } =20 @@ -481,27 +510,14 @@ struct wwan_port *wwan_create_port(struct device *par= ent, mutex_init(&port->data_lock); =20 port->dev.parent =3D &wwandev->dev; - port->dev.class =3D &wwan_class; port->dev.type =3D &wwan_port_dev_type; - port->dev.devt =3D MKDEV(wwan_major, minor); dev_set_drvdata(&port->dev, drvdata); + device_initialize(&port->dev); =20 - /* 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 =3D device_register(&port->dev); - - mutex_unlock(&wwan_register_lock); - + err =3D wwan_port_register_wwan(port); if (err) goto error_put_device; =20 - dev_info(&wwandev->dev, "port %s attached\n", dev_name(&port->dev)); return port; =20 error_put_device: --=20 2.25.1 From nobody Mon Feb 9 12:28:47 2026 Received: from m16.mail.163.com (m16.mail.163.com [220.197.31.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6FEE938734A; Thu, 15 Jan 2026 11:47:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=220.197.31.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768477657; cv=none; b=vBw64TiXKyTUB5iumx1Ndpm4sINfeRcnxNioOZrwLtS4EZShOXtd/CdHVfETitJTUCQbwFHRjwRlhu1DHHOQDbJBhXjHCCea8Z8l87BHpXmIQ8bosnnNzrKzdcZXJWEIOv0WDsWtR7F6GBK1YAcc80tAigYb/nnyqyUqUO/EwUs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768477657; c=relaxed/simple; bh=6aLsYlkk3jIQO8gt6D9AaFgb7AsBDAjEB/hEJZbfP/k=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=PN6Rqzje9e/PJr73WNaNwrXZpadKz3BQcM9x1VBhuNOY20CBn3DVTgSRy043bE/+WFBTP2DYyE1b2YDWvSCcEOEr8ysCJfOgGGGSP07S4x9JFBHzfI1t1gMMzWbA0PYnqSqUOX59O78HmgdP6HD+OJH+XDP5JDKbVQNJJ2m8N6Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com; spf=pass smtp.mailfrom=163.com; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b=F26NJ0mU; arc=none smtp.client-ip=220.197.31.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=163.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b="F26NJ0mU" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:To:Subject:Date:Message-Id:MIME-Version; bh=8O CMe3qyAgtsYnHFNUeAUlbwQX+dOXErx0oh72oVj0g=; b=F26NJ0mUabTcRspvbf XaZJPqS1BWrt6hla/hGo/BqjyNRMUft1oamlcAtc3HrVsychjNS8Mx0GPwCFWzTI YTJPxPzxOOJKdr9JKEo8XoHVUcgNQd2sF9Aw9eAlVm5e4ctn+6lWRemIajHNICln 0Y5lRLdPQoqKrwcPTcc2ywouk= Received: from localhost.localdomain (unknown []) by gzga-smtp-mtada-g1-3 (Coremail) with SMTP id _____wBHLGiX02hpr2PzGQ--.4331S6; Thu, 15 Jan 2026 19:46:45 +0800 (CST) From: Slark Xiao To: loic.poulain@oss.qualcomm.com, ryazanov.s.a@gmail.com, johannes@sipsolutions.net, andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, mani@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, slark_xiao@163.com Subject: [net-next v7 4/8] net: wwan: core: split port unregister and stop Date: Thu, 15 Jan 2026 19:46:21 +0800 Message-Id: <20260115114625.46991-5-slark_xiao@163.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260115114625.46991-1-slark_xiao@163.com> References: <20260115114625.46991-1-slark_xiao@163.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: _____wBHLGiX02hpr2PzGQ--.4331S6 X-Coremail-Antispam: 1Uf129KBjvJXoW7Ww48CFy3Cr1kJr15WFWxZwb_yoW5Jr15pa 1jgF9xKFW8Jr43Ww43XF4xXFWruF4xG34Sy34xW34Skrn5tryFvrWkuF1qyrWrJFyxWFy5 ZrW5tFWUCa4UCr7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x0pEfMarUUUUU= X-CM-SenderInfo: xvod2y5b0lt0i6rwjhhfrp/xtbCwAWS9mlo06XnFQAA3k Content-Type: text/plain; charset="utf-8" From: Sergey Ryazanov 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 Reviewed-by: Loic Poulain --- 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 1a9a77d597e6..ae91b1cd7142 100644 --- a/drivers/net/wwan/wwan_core.c +++ b/drivers/net/wwan/wwan_core.c @@ -474,6 +474,18 @@ static int wwan_port_register_wwan(struct wwan_port *p= ort) return 0; } =20 +/* Unregister a regular WWAN port (e.g. AT, MBIM, etc) */ +static void wwan_port_unregister_wwan(struct wwan_port *port) +{ + struct wwan_device *wwandev =3D 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, @@ -534,18 +546,19 @@ void wwan_remove_port(struct wwan_port *port) struct wwan_device *wwandev =3D to_wwan_dev(port->dev.parent); =20 mutex_lock(&port->ops_lock); - if (port->start_count) + if (port->start_count) { port->ops->stop(port); + port->start_count =3D 0; + } port->ops =3D NULL; /* Prevent any new port operations (e.g. from fops) */ mutex_unlock(&port->ops_lock); =20 wake_up_interruptible(&port->waitqueue); - skb_queue_purge(&port->rxq); - dev_set_drvdata(&port->dev, NULL); =20 - 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); =20 /* Release related wwan device */ wwan_remove_dev(wwandev); --=20 2.25.1 From nobody Mon Feb 9 12:28:47 2026 Received: from m16.mail.163.com (m16.mail.163.com [220.197.31.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 18DC737BE95; Thu, 15 Jan 2026 11:48:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=220.197.31.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768477688; cv=none; b=KXvm2KByo2Ah/DTahqvbT3z3cAj6+Inu2sVuzgtUIRqFNXw5oilckSl2/LZOj08YIhEji12xrqB5O/5iWkzwxWLuBRY1dqjb+1IlnL795ggzsW9LD0ZgBvbCQm2hJebSMWFCcdMMx6spefChfmYTDIwqVNxkUlZwyymDiHROJH8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768477688; c=relaxed/simple; bh=0jJOMxzLsMb17DtgbKdwfIg16N7cV5nNPrbp2xfSBxg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=gt7gC0Texww5ftqkJUzWU9NygI8YSvh7luN1SYRLn9V6HWeA4mtzkHHQEWc5o704OfvT6rr7GFJwBoaGTK/mhHsvSGBoJWAl2YZIleji1VAzew7nATr4DjElI9uuu3yXHNcNeHOlBH/fvCX7V5GjlpxZ76RVH4pz/cvZT3c9xfo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com; spf=pass smtp.mailfrom=163.com; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b=JpyG8zbF; arc=none smtp.client-ip=220.197.31.5 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=163.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b="JpyG8zbF" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:To:Subject:Date:Message-Id:MIME-Version; bh=Lp Y+aJmoEhOG44KQ3VdTvnBgg4wtPWt0VenoOwUOBcE=; b=JpyG8zbFdtP0tzb/XE +4JGF1d2Mpy6QwjQx0frnOD+Kg5Wvb/VPbq9Ns+PRNnOANM4k43knY/XsMoV5U9B Zx//7r8+3+VPYePB8w6VQL+FVjhbrpSZjk55ss16+adTL5AMe2EdkBgf8SwKhZ9Q rh5a6SbkCvrUImWSZix5Uim78= Received: from localhost.localdomain (unknown []) by gzga-smtp-mtada-g1-3 (Coremail) with SMTP id _____wBHLGiX02hpr2PzGQ--.4331S7; Thu, 15 Jan 2026 19:46:47 +0800 (CST) From: Slark Xiao To: loic.poulain@oss.qualcomm.com, ryazanov.s.a@gmail.com, johannes@sipsolutions.net, andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, mani@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, slark_xiao@163.com, Muhammad Nuzaihan , Qiang Yu , Manivannan Sadhasivam , Johan Hovold Subject: [net-next v7 5/8] net: wwan: add NMEA port support Date: Thu, 15 Jan 2026 19:46:22 +0800 Message-Id: <20260115114625.46991-6-slark_xiao@163.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260115114625.46991-1-slark_xiao@163.com> References: <20260115114625.46991-1-slark_xiao@163.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: _____wBHLGiX02hpr2PzGQ--.4331S7 X-Coremail-Antispam: 1Uf129KBjvJXoWxKrW8uF4rWw1kXw17CFW5GFg_yoWfAry3pa yqga45KrZ5JF47Wr47JF42vFWY93WxCryxtry8W34Skr1UtryFvaykuFyqyFy5JrZ7uFya krZ5KFW09345CrJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x0pRAHUhUUUUU= X-CM-SenderInfo: xvod2y5b0lt0i6rwjhhfrp/xtbC5weS9mlo06f82AAA3V Content-Type: text/plain; charset="utf-8" From: Sergey Ryazanov 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 CC: Muhammad Nuzaihan CC: Qiang Yu CC: Manivannan Sadhasivam CC: Johan Hovold Suggested-by: Loic Poulain Signed-off-by: Sergey Ryazanov Reviewed-by: Loic Poulain --- drivers/net/wwan/Kconfig | 1 + drivers/net/wwan/wwan_core.c | 156 +++++++++++++++++++++++++++++++++-- include/linux/wwan.h | 2 + 3 files changed, 154 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" =20 config WWAN tristate "WWAN Driver Core" + depends on GNSS || GNSS =3D 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 ae91b1cd7142..c50f1fad17a5 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 */ +/* WWAN Driver Core + * + * Copyright (c) 2021, Linaro Ltd + * Copyright (c) 2025, Sergey Ryazanov + */ =20 #include #include @@ -16,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -75,6 +80,7 @@ struct wwan_device { * @headroom_len: SKB reserved headroom size * @frag_len: Length to fragment packet * @at_data: AT port specific data + * @gnss: Pointer to GNSS device associated with this port */ struct wwan_port { enum wwan_port_type type; @@ -93,9 +99,16 @@ struct wwan_port { struct ktermios termios; int mdmbits; } at_data; + struct gnss_device *gnss; }; }; =20 +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 *att= r, char *buf) { struct wwan_device *wwan =3D to_wwan_dev(dev); @@ -336,6 +349,7 @@ static const struct { .name =3D "MIPC", .devsuf =3D "mipc", }, + /* WWAN_PORT_NMEA is exported via the GNSS subsystem */ }; =20 static ssize_t type_show(struct device *dev, struct device_attribute *attr, @@ -486,6 +500,124 @@ static void wwan_port_unregister_wwan(struct wwan_por= t *port) device_del(&port->dev); } =20 +#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 =3D gnss_get_drvdata(gdev); + struct sk_buff *skb, *head =3D NULL, *tail =3D NULL; + size_t frag_len, remain =3D count; + int ret; + + ret =3D wwan_wait_tx(port, false); + if (ret) + return ret; + + do { + frag_len =3D min(remain, port->frag_len); + skb =3D alloc_skb(frag_len + port->headroom_len, GFP_KERNEL); + if (!skb) { + ret =3D -ENOMEM; + goto freeskb; + } + skb_reserve(skb, port->headroom_len); + memcpy(skb_put(skb, frag_len), buf + count - remain, frag_len); + + if (!head) { + head =3D skb; + } else { + if (!tail) + skb_shinfo(head)->frag_list =3D skb; + else + tail->next =3D skb; + + tail =3D skb; + head->data_len +=3D skb->len; + head->len +=3D skb->len; + head->truesize +=3D skb->truesize; + } + } while (remain -=3D frag_len); + + ret =3D wwan_port_op_tx(port, head, false); + if (!ret) + return count; + +freeskb: + kfree_skb(head); + return ret; +} + +static struct gnss_operations wwan_gnss_ops =3D { + .open =3D wwan_gnss_open, + .close =3D wwan_gnss_close, + .write_raw =3D wwan_gnss_write, +}; + +/* GNSS port specific device registration */ +static int wwan_port_register_gnss(struct wwan_port *port) +{ + struct wwan_device *wwandev =3D to_wwan_dev(port->dev.parent); + struct gnss_device *gdev; + int err; + + gdev =3D 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 map WWAN port type to GNSS type. + */ + gdev->type =3D GNSS_TYPE_NMEA; + gdev->ops =3D &wwan_gnss_ops; + gnss_set_drvdata(gdev, port); + + port->gnss =3D gdev; + + err =3D 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 =3D to_wwan_dev(port->dev.parent); + struct gnss_device *gdev =3D 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, @@ -526,7 +658,11 @@ struct wwan_port *wwan_create_port(struct device *pare= nt, dev_set_drvdata(&port->dev, drvdata); device_initialize(&port->dev); =20 - err =3D wwan_port_register_wwan(port); + if (port->type =3D=3D WWAN_PORT_NMEA) + err =3D wwan_port_register_gnss(port); + else + err =3D wwan_port_register_wwan(port); + if (err) goto error_put_device; =20 @@ -556,7 +692,10 @@ void wwan_remove_port(struct wwan_port *port) wake_up_interruptible(&port->waitqueue); skb_queue_purge(&port->rxq); =20 - wwan_port_unregister_wwan(port); + if (port->type =3D=3D WWAN_PORT_NMEA) + wwan_port_unregister_gnss(port); + else + wwan_port_unregister_wwan(port); =20 put_device(&port->dev); =20 @@ -567,8 +706,15 @@ EXPORT_SYMBOL_GPL(wwan_remove_port); =20 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 =3D=3D 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); =20 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, =20 /* Add new port types above this line */ =20 --=20 2.25.1 From nobody Mon Feb 9 12:28:47 2026 Received: from m16.mail.163.com (m16.mail.163.com [220.197.31.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 700AB3939C3; Thu, 15 Jan 2026 11:47:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=220.197.31.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768477655; cv=none; b=KFoX6aAjk1DW8iCxRooXib4U03FTBPj//EkaO9ovPmoEltFqU34glaLxM398kR89qezI4NS4tcIZAagOu3rh+97Pg+uuwk3nRypsyB4HbX8qZ1NtPJcJrqzBjpsCW1oxDLv1A3zF5Cl1NcT3PrQYHaSuISkV3DsseSk6ml8+ZOY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768477655; c=relaxed/simple; bh=ch3WUowE0r41pxeM/FiSHDm2a/bn91+yh/Iqf4f8cno=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=VM2rErcgDzM80yycMEZVc1aCXxR6HleDAUJxvWVgJqDYarnDoXhSSkH5KP+GWIhfYgb2SxYe9KVBLa2ciRs7YVGGRxppHaCcX+TXy4+bQ7MFl9GKoz7v983xzGJGLKWn1L2GStBHScc76Vl2MuGv/u7GIf/Nakzr6GLxk1JzHMc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com; spf=pass smtp.mailfrom=163.com; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b=hBEWCU4J; arc=none smtp.client-ip=220.197.31.5 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=163.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b="hBEWCU4J" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:To:Subject:Date:Message-Id:MIME-Version; bh=xj XLh9OxB7OyImjOAQduujoqYcXrgtQdnE2zosJw5bA=; b=hBEWCU4JCy/S4vL5LG TRJ6yOAUxUAmbIjCVL3LxlfpyOKwbwj9HIygaVbe9QJR7TxeDEkTRwQ8i8esWbmO MYhKIAXeTvS12YxvJxntrDEGgCCQzzbxlDD4z/lABmTDHTHmX7/wKRSjkyscyOf2 MbeXXeGiE9aNl1vKYL5Gx0oIs= Received: from localhost.localdomain (unknown []) by gzga-smtp-mtada-g1-3 (Coremail) with SMTP id _____wBHLGiX02hpr2PzGQ--.4331S8; Thu, 15 Jan 2026 19:46:48 +0800 (CST) From: Slark Xiao To: loic.poulain@oss.qualcomm.com, ryazanov.s.a@gmail.com, johannes@sipsolutions.net, andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, mani@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, slark_xiao@163.com Subject: [net-next v7 6/8] net: wwan: hwsim: refactor to support more port types Date: Thu, 15 Jan 2026 19:46:23 +0800 Message-Id: <20260115114625.46991-7-slark_xiao@163.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260115114625.46991-1-slark_xiao@163.com> References: <20260115114625.46991-1-slark_xiao@163.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: _____wBHLGiX02hpr2PzGQ--.4331S8 X-Coremail-Antispam: 1Uf129KBjvJXoW3Xr4UKr1UAry5CFWfAFykAFb_yoWxJrykpa yqgr9xKrWUt3Z3Wry7tFsrAa4Fkrn5WryvqrWrW34FqFn7t345ZFWvk3s0kr4DAFy7CFy3 Cr98t343Jw47Cr7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x0pETmhrUUUUU= X-CM-SenderInfo: xvod2y5b0lt0i6rwjhhfrp/xtbCwAiT92lo06jnRgAA33 Content-Type: text/plain; charset="utf-8" From: Sergey Ryazanov 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 Reviewed-by: Loic Poulain --- 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; + }; }; =20 static const struct file_operations wwan_hwsim_debugfs_portdestroy_fops; @@ -101,16 +105,16 @@ static const struct wwan_ops wwan_hwsim_wwan_rtnl_ops= =3D { .setup =3D wwan_hwsim_netdev_setup, }; =20 -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 =3D wwan_port_get_drvdata(wport); =20 - port->pstate =3D AT_PARSER_WAIT_A; + port->at_emul.pstate =3D AT_PARSER_WAIT_A; =20 return 0; } =20 -static void wwan_hwsim_port_stop(struct wwan_port *wport) +static void wwan_hwsim_at_emul_stop(struct wwan_port *wport) { } =20 @@ -120,7 +124,7 @@ static void wwan_hwsim_port_stop(struct wwan_port *wpor= t) * * 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 =3D 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 =3D 0, s =3D 0; i < in->len; ++i) { char c =3D in->data[i]; =20 - if (port->pstate =3D=3D AT_PARSER_WAIT_A) { + if (port->at_emul.pstate =3D=3D AT_PARSER_WAIT_A) { if (c =3D=3D 'A' || c =3D=3D 'a') - port->pstate =3D AT_PARSER_WAIT_T; + port->at_emul.pstate =3D AT_PARSER_WAIT_T; else if (c !=3D '\n') /* Ignore formating char */ - port->pstate =3D AT_PARSER_SKIP_LINE; - } else if (port->pstate =3D=3D AT_PARSER_WAIT_T) { + port->at_emul.pstate =3D AT_PARSER_SKIP_LINE; + } else if (port->at_emul.pstate =3D=3D AT_PARSER_WAIT_T) { if (c =3D=3D 'T' || c =3D=3D 't') - port->pstate =3D AT_PARSER_WAIT_TERM; + port->at_emul.pstate =3D AT_PARSER_WAIT_TERM; else - port->pstate =3D AT_PARSER_SKIP_LINE; - } else if (port->pstate =3D=3D AT_PARSER_WAIT_TERM) { + port->at_emul.pstate =3D AT_PARSER_SKIP_LINE; + } else if (port->at_emul.pstate =3D=3D AT_PARSER_WAIT_TERM) { if (c !=3D '\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 =3D i + 1; - port->pstate =3D AT_PARSER_WAIT_A; - } else if (port->pstate =3D=3D AT_PARSER_SKIP_LINE) { + port->at_emul.pstate =3D AT_PARSER_WAIT_A; + } else if (port->at_emul.pstate =3D=3D AT_PARSER_SKIP_LINE) { if (c !=3D '\r') continue; - port->pstate =3D AT_PARSER_WAIT_A; + port->at_emul.pstate =3D AT_PARSER_WAIT_A; } } =20 @@ -183,18 +187,25 @@ static int wwan_hwsim_port_tx(struct wwan_port *wport= , struct sk_buff *in) return 0; } =20 -static const struct wwan_port_ops wwan_hwsim_port_ops =3D { - .start =3D wwan_hwsim_port_start, - .stop =3D wwan_hwsim_port_stop, - .tx =3D wwan_hwsim_port_tx, +static const struct wwan_port_ops wwan_hwsim_at_emul_port_ops =3D { + .start =3D wwan_hwsim_at_emul_start, + .stop =3D wwan_hwsim_at_emul_stop, + .tx =3D wwan_hwsim_at_emul_tx, }; =20 -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; =20 + if (type =3D=3D WWAN_PORT_AT) + ops =3D &wwan_hwsim_at_emul_port_ops; + else + return ERR_PTR(-EINVAL); + port =3D kzalloc(sizeof(*port), GFP_KERNEL); if (!port) return ERR_PTR(-ENOMEM); @@ -205,9 +216,7 @@ static struct wwan_hwsim_port *wwan_hwsim_port_new(stru= ct wwan_hwsim_dev *dev) port->id =3D dev->port_idx++; spin_unlock(&dev->ports_lock); =20 - port->wwan =3D wwan_create_port(&dev->dev, WWAN_PORT_AT, - &wwan_hwsim_port_ops, - NULL, port); + port->wwan =3D wwan_create_port(&dev->dev, type, ops, NULL, port); if (IS_ERR(port->wwan)) { err =3D PTR_ERR(port->wwan); goto err_free_port; @@ -392,7 +401,7 @@ static ssize_t wwan_hwsim_debugfs_portcreate_write(stru= ct file *file, struct wwan_hwsim_dev *dev =3D file->private_data; struct wwan_hwsim_port *port; =20 - port =3D wwan_hwsim_port_new(dev); + port =3D wwan_hwsim_port_new(dev, WWAN_PORT_AT); if (IS_ERR(port)) return PTR_ERR(port); =20 @@ -459,6 +468,8 @@ static int __init wwan_hwsim_init_devs(void) int i, j; =20 for (i =3D 0; i < wwan_hwsim_devsnum; ++i) { + struct wwan_hwsim_port *port; + dev =3D 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 =3D 0; j < 2; ++j) { - struct wwan_hwsim_port *port; - - port =3D wwan_hwsim_port_new(dev); + port =3D wwan_hwsim_port_new(dev, WWAN_PORT_AT); if (IS_ERR(port)) return PTR_ERR(port); =20 --=20 2.25.1 From nobody Mon Feb 9 12:28:47 2026 Received: from m16.mail.163.com (m16.mail.163.com [117.135.210.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7AAE73939D2; Thu, 15 Jan 2026 11:47:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=117.135.210.2 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768477657; cv=none; b=Z+lwq87Ay5pIAC69/QSx4wJqMim4rqFB3AY+jFq81ziHwVednD2LmSCeOnPPOH/3bCTARr/4rDqDF9+53rknCLOshMCE4UU66WBP5SXI8cDPu8s9XOp9vghvzF+sbMkk2dLQHsZqn8urooi1oldeOiFi1Hf7fOZPvi2l7X9R59Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768477657; c=relaxed/simple; bh=SyKRwH1c8v3mmIugLNkly0F2wmJQ7i/fgDJBgjlJW+I=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=CN87FwxpBDv2ZCm3P7xMWQmA60Q5htEHknyXlbu6PqszgFWL0gHtKZGThFA9sxhkcwsB+WbYiZrU6zpwXVelQSRPsHpOXGqicZxbxQTFh4YVl/6E0gJxdCbaaZHzXQF35UU4TWIMUt9L/tMjBv2bfTOx4imejzntOva5hdhYp+E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com; spf=pass smtp.mailfrom=163.com; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b=cpYx4zzQ; arc=none smtp.client-ip=117.135.210.2 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=163.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b="cpYx4zzQ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:To:Subject:Date:Message-Id:MIME-Version; bh=p1 iWJqqdKYOk1pu+XFp9eZ3OVLK5D4FBSV3XmNWR0X4=; b=cpYx4zzQGBbH9sW5fM 3HNZa8AZMk3mO9+h3vr8o4IQlLJahNj2bsmWogKGrWnKeW2dX0KocflKKLZsVeDJ Al7lajE/NlSPoScRtb3Iz3ATFZgpBQz4qqi+0MyIqQ1l5rK5nJRMRVJI0/pGiA8F EMLSAmsKVEVfU40YJLk543JC4= Received: from localhost.localdomain (unknown []) by gzga-smtp-mtada-g1-3 (Coremail) with SMTP id _____wBHLGiX02hpr2PzGQ--.4331S9; Thu, 15 Jan 2026 19:46:49 +0800 (CST) From: Slark Xiao To: loic.poulain@oss.qualcomm.com, ryazanov.s.a@gmail.com, johannes@sipsolutions.net, andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, mani@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, slark_xiao@163.com Subject: [net-next v7 7/8] net: wwan: hwsim: support NMEA port emulation Date: Thu, 15 Jan 2026 19:46:24 +0800 Message-Id: <20260115114625.46991-8-slark_xiao@163.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260115114625.46991-1-slark_xiao@163.com> References: <20260115114625.46991-1-slark_xiao@163.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: _____wBHLGiX02hpr2PzGQ--.4331S9 X-Coremail-Antispam: 1Uf129KBjvJXoWxKrWUJr4UKFy5AFykJFW8WFg_yoWxJF43pa 1qgasxKrWUAw47Wry3GFsxJFWYqF1kWry0v34fWryYvr1xtry5XFWvkr90vrW5GFZ7uFy3 urs5tw13Z397CrJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x0pR6HqcUUUUU= X-CM-SenderInfo: xvod2y5b0lt0i6rwjhhfrp/xtbCvwqT92lo06ofDgAA34 Content-Type: text/plain; charset="utf-8" From: Sergey Ryazanov 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 Reviewed-by: Loic Poulain --- 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 + * Copyright (c) 2021, 2025, Sergey Ryazanov */ =20 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -12,8 +12,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -65,6 +67,9 @@ struct wwan_hwsim_port { AT_PARSER_SKIP_LINE, } pstate; } at_emul; + struct { + struct timer_list timer; + } nmea_emul; }; }; =20 @@ -193,6 +198,108 @@ static const struct wwan_port_ops wwan_hwsim_at_emul_= port_ops =3D { .tx =3D wwan_hwsim_at_emul_tx, }; =20 +#if IS_ENABLED(CONFIG_GNSS) +#define NMEA_MAX_LEN 82 /* Max sentence length */ +#define NMEA_TRAIL_LEN 5 /* '*' + Checksum + */ +#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 =3D 0; + int len; + + s =3D skb_put(skb, NMEA_MAX_LEN + 1); /* +'\0' */ + if (!s) + return; + + va_start(ap, fmt); + len =3D 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 =3D s + 1; *p !=3D '\0'; ++p)/* Skip leading '$' or '!' */ + cs ^=3D *p; + p +=3D snprintf(p, 5 + 1, "*%02X\r\n", cs); + + len =3D (p - s) - (NMEA_MAX_LEN + 1); /* exp. vs real length diff */ + skb->tail +=3D len; /* Adjust tail to real length */ + skb->len +=3D 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] =3D { 43, 44, 8528, 0, + 11, 15, 4559, 0 }; + struct wwan_hwsim_port *port =3D timer_container_of(port, t, nmea_emul.ti= mer); + 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 =3D 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,3= 1.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 =3D 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 =3D 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 =3D { + .start =3D wwan_hwsim_nmea_emul_start, + .stop =3D wwan_hwsim_nmea_emul_stop, + .tx =3D 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(str= uct wwan_hwsim_dev *dev, =20 if (type =3D=3D WWAN_PORT_AT) ops =3D &wwan_hwsim_at_emul_port_ops; +#if IS_ENABLED(CONFIG_GNSS) + else if (type =3D=3D WWAN_PORT_NMEA) + ops =3D &wwan_hwsim_nmea_emul_port_ops; +#endif else return ERR_PTR(-EINVAL); =20 @@ -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); =20 - /* 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 =3D 0; j < 2; ++j) { port =3D 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 =3D 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 } =20 return 0; --=20 2.25.1 From nobody Mon Feb 9 12:28:47 2026 Received: from m16.mail.163.com (m16.mail.163.com [220.197.31.3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2E8B9389E0E; Thu, 15 Jan 2026 11:47:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=220.197.31.3 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768477655; cv=none; b=TShBoQMS3zGnmfQrEcNzqlfY4XqnRRqK+wxdws2v9k3Xp52VIZeCHOe9l1v9wPYGaBmwSpDZuzcuz1HJXY0EfuOMVOJGhtIqzlqmoRZAF6C2uwdfU4eHClc7PFjO9L2xBwJ9b7Cfccd8b8F0spnKSebtd2Vx2mhFv4JTUjiv1cs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768477655; c=relaxed/simple; bh=hPpGrhBm7dswjrLDv/THjvYEQrlbFx3TtA9jAFW1hNQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=lY8HJ2SbyDhGAA0GuAfk1abaTFmiTzMuHLWhaaoTGzeOWDHDI6LA6wqjLhTWrnFwgxhznjZTFTNNYyhCEwH3TXIEWdduXkSYNDGPo3J07h/01ZgH5ZN9AVepY5Rnd0ZT8WBSoA2UOrOkTldpPILskT5f5gYu5FrjQA+jCxavs+A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com; spf=pass smtp.mailfrom=163.com; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b=aHXhSO0u; arc=none smtp.client-ip=220.197.31.3 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=163.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b="aHXhSO0u" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:To:Subject:Date:Message-Id:MIME-Version; bh=/4 b01nswZlIsKdbMEMUcNlPloW0gjn+e2EWs/AY2u78=; b=aHXhSO0u60uet3jDlt ozkenQewX2OaKjX6xLMNdcSH6EI1p9o3jtfxiau7+wGmsqWF1IlyzLNeM9sPRpbD FZ7S0qiYSgr4l+dtEocNr/YKKl7I5jCmlrvFoeKsaTECKqDvF4GLtwrt+G8Ax7wt ntIt1rp4fmVTGE0fRBJTkHLxU= Received: from localhost.localdomain (unknown []) by gzga-smtp-mtada-g1-3 (Coremail) with SMTP id _____wBHLGiX02hpr2PzGQ--.4331S10; Thu, 15 Jan 2026 19:46:51 +0800 (CST) From: Slark Xiao To: loic.poulain@oss.qualcomm.com, ryazanov.s.a@gmail.com, johannes@sipsolutions.net, andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, mani@kernel.org Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, slark_xiao@163.com Subject: [net-next v7 8/8] net: wwan: mhi_wwan_ctrl: Add NMEA channel support Date: Thu, 15 Jan 2026 19:46:25 +0800 Message-Id: <20260115114625.46991-9-slark_xiao@163.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260115114625.46991-1-slark_xiao@163.com> References: <20260115114625.46991-1-slark_xiao@163.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: _____wBHLGiX02hpr2PzGQ--.4331S10 X-Coremail-Antispam: 1Uf129KBjvdXoWrKrW3Xw48Gr4fGr4kur1rJFb_yoWfKrgE9w 1kXF9rJrW3J347KFsF9F13urWfK3W0qF4kXFnaqr9Yv347XFyfWw1kZF4Dtr9F9r17CF9r urnxWayFyw4fWjkaLaAFLSUrUUUUjb8apTn2vfkv8UJUUUU8Yxn0WfASr-VFAUDa7-sFnT 9fnUUvcSsGvfC2KfnxnUUI43ZEXa7sREEfO5UUUUU== X-CM-SenderInfo: xvod2y5b0lt0i6rwjhhfrp/xtbC5wuT92lo06v9NgAA36 Content-Type: text/plain; charset="utf-8" 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 Reviewed-by: Loic Poulain Acked-by: Sergey Ryazanov --- 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_c= trl.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_t= able[] =3D { { .chan =3D "QMI", .driver_data =3D WWAN_PORT_QMI }, { .chan =3D "DIAG", .driver_data =3D WWAN_PORT_QCDM }, { .chan =3D "FIREHOSE", .driver_data =3D WWAN_PORT_FIREHOSE }, + { .chan =3D "NMEA", .driver_data =3D WWAN_PORT_NMEA }, {}, }; MODULE_DEVICE_TABLE(mhi, mhi_wwan_ctrl_match_table); --=20 2.25.1