[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250930080709.3408463-2-yicongsrfy@163.com>
Date: Tue, 30 Sep 2025 16:07:08 +0800
From: yicongsrfy@....com
To: oneukum@...e.com,
andrew+netdev@...n.ch
Cc: davem@...emloft.net,
edumazet@...gle.com,
kuba@...nel.org,
linux-usb@...r.kernel.org,
marcan@...can.st,
netdev@...r.kernel.org,
pabeni@...hat.com,
yicong@...inos.cn
Subject: [PATCH v4 2/3] net: usb: support quirks in cdc_ncm
From: Yi Cong <yicong@...inos.cn>
Some vendors' USB network interface controllers (NICs) may be compatible
with multiple drivers.
I consulted with relevant vendors. Taking the AX88179 chip as an example,
NICs based on this chip may be used across various OS—for instance,
cdc_ncm is used on macOS, while ax88179_178a.ko is the intended driver
on Linux (despite a previous patch having disabled it).
Therefore, the firmware must support multiple protocols.
Currently, both cdc_ncm and ax88179_178a coexist in the Linux kernel.
Supporting both drivers simultaneously leads to the following issues:
1. Inconsistent driver loading order during reboot stress testing:
The order in which drivers are loaded can vary across reboots,
potentially resulting in the unintended driver being loaded. For
example:
[ 4.239893] cdc_ncm 2-1:2.0: MAC-Address: c8:a3:62:ef:99:8e
[ 4.239897] cdc_ncm 2-1:2.0: setting rx_max = 16384
[ 4.240149] cdc_ncm 2-1:2.0: setting tx_max = 16384
[ 4.240583] cdc_ncm 2-1:2.0 usb0: register 'cdc_ncm' at usb-
xxxxx:00-1, CDC NCM, c8:a3:62:ef:99:8e
[ 4.240627] usbcore: registered new interface driver cdc_ncm
[ 4.240908] usbcore: registered new interface driver ax88179_178a
In this case, network connectivity functions, but the cdc_ncm driver is
loaded instead of the expected ax88179_178a.
2. Similar issues during cable plug/unplug testing:
The same race condition can occur when reconnecting the USB device:
[ 79.879922] usb 4-1: new SuperSpeed USB device number 3 using xhci_hcd
[ 79.905168] usb 4-1: New USB device found, idVendor=0b95, idProduct=
1790, bcdDevice= 2.00
[ 79.905185] usb 4-1: New USB device strings: Mfr=1, Product=2,
SerialNumber=3
[ 79.905191] usb 4-1: Product: AX88179B
[ 79.905198] usb 4-1: Manufacturer: ASIX
[ 79.905201] usb 4-1: SerialNumber: 00EF998E
[ 79.915215] ax88179_probe, bConfigurationValue:2
[ 79.952638] cdc_ncm 4-1:2.0: MAC-Address: c8:a3:62:ef:99:8e
[ 79.952654] cdc_ncm 4-1:2.0: setting rx_max = 16384
[ 79.952919] cdc_ncm 4-1:2.0: setting tx_max = 16384
[ 79.953598] cdc_ncm 4-1:2.0 eth0: register 'cdc_ncm' at usb-0000:04:
00.2-1, CDC NCM (NO ZLP), c8:a3:62:ef:99:8e
[ 79.954029] cdc_ncm 4-1:2.0 eth0: unregister 'cdc_ncm' usb-0000:04:
00.2-1, CDC NCM (NO ZLP)
At this point, the network becomes unusable.
To resolve these issues, introduce a *quirks* mechanism into the usbnet
module. By adding chip-specific identification within the generic usbnet
framework, we can skip the usbnet probe process for devices that require a
dedicated driver.
v2: Correct the description of usbnet_quirks.h and modify the code style
v3: Add checking whether the CONFIG_USB_NET_AX88179_178A is enabled
v4: Move quirks from usbnet.ko to cdc_ncm.ko
Signed-off-by: Yi Cong <yicong@...inos.cn>
---
drivers/net/usb/cdc_ncm.c | 15 +++++++++++-
drivers/net/usb/cdc_ncm_quirks.h | 41 ++++++++++++++++++++++++++++++++
2 files changed, 55 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/usb/cdc_ncm_quirks.h
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index 5d123df0a866..fc8416af3f11 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -54,6 +54,8 @@
#include <linux/usb/cdc.h>
#include <linux/usb/cdc_ncm.h>
+#include "cdc_ncm_quirks.h"
+
#if IS_ENABLED(CONFIG_USB_NET_CDC_MBIM)
static bool prefer_mbim = true;
#else
@@ -2114,10 +2116,21 @@ static const struct usb_device_id cdc_devs[] = {
};
MODULE_DEVICE_TABLE(usb, cdc_devs);
+static int cdc_ncm_probe(struct usb_interface *intf, const struct usb_device_id *prod)
+{
+ /* Should it be ignored? */
+ if (unlikely(cdc_ncm_ignore(intf))) {
+ dev_dbg(&intf->dev, "cdc_ncm ignore this device!\n");
+ return -ENODEV;
+ }
+
+ return usbnet_probe(intf, prod);
+}
+
static struct usb_driver cdc_ncm_driver = {
.name = "cdc_ncm",
.id_table = cdc_devs,
- .probe = usbnet_probe,
+ .probe = cdc_ncm_probe,
.disconnect = usbnet_disconnect,
.suspend = usbnet_suspend,
.resume = usbnet_resume,
diff --git a/drivers/net/usb/cdc_ncm_quirks.h b/drivers/net/usb/cdc_ncm_quirks.h
new file mode 100644
index 000000000000..e5ae2265b1d7
--- /dev/null
+++ b/drivers/net/usb/cdc_ncm_quirks.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * A collection of chip information to be ignored
+ */
+
+#ifndef __CDC_NCM_IGNORE_H__
+#define __CDC_NCM_IGNORE_H__
+
+#include <linux/usb.h>
+
+/* cdc_ncm_ignore_list:
+ * Chip info which already support int vendor specific driver,
+ * and then should be ignored in generic cdc_ncm
+ */
+static const struct usb_device_id cdc_ncm_ignore_list[] = {
+#if IS_ENABLED(CONFIG_USB_NET_AX88179_178A)
+ /* Chips already support in ax88179_178a.c */
+ { USB_DEVICE(0x0b95, 0x1790) },
+ { USB_DEVICE(0x0b95, 0x178a) },
+ { USB_DEVICE(0x04b4, 0x3610) },
+ { USB_DEVICE(0x2001, 0x4a00) },
+ { USB_DEVICE(0x0df6, 0x0072) },
+ { USB_DEVICE(0x04e8, 0xa100) },
+ { USB_DEVICE(0x17ef, 0x304b) },
+ { USB_DEVICE(0x050d, 0x0128) },
+ { USB_DEVICE(0x0930, 0x0a13) },
+ { USB_DEVICE(0x0711, 0x0179) },
+ { USB_DEVICE(0x07c9, 0x000e) },
+ { USB_DEVICE(0x07c9, 0x000f) },
+ { USB_DEVICE(0x07c9, 0x0010) },
+ /* End of support in ax88179_178a.c */
+#endif
+
+ { } /*END*/
+};
+
+static inline bool cdc_ncm_ignore(struct usb_interface *intf)
+{
+ return !!usb_match_id(intf, cdc_ncm_ignore_list);
+}
+#endif
--
2.25.1
Powered by blists - more mailing lists