All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv3 net-next 1/9] net: usb: move updating filter and status from cdc drivers to usbnet
@ 2026-07-14 11:44 Oliver Neukum
  2026-07-14 11:44 ` [PATCHv3 net-next 2/9] net: usb: centralize usbnet_cdc_zte_rx_fixup in usbnet Oliver Neukum
                   ` (8 more replies)
  0 siblings, 9 replies; 13+ messages in thread
From: Oliver Neukum @ 2026-07-14 11:44 UTC (permalink / raw)
  To: andrew+netdev, davem, edumazet, kuba, pabeni, manuelebner, netdev,
	linux-kernel
  Cc: Oliver Neukum

These helpers are used by multiple drivers and do not depend
on the rest. For example rndis_host will also need cdc_ether.
Leaving them in a cdc driver means that additional drivers are loaded
just as a library, not to support hardware by themselves.

Signed-off-by: Oliver Neukum <oneukum@suse.com>
---

v2:
- update change log entry

 drivers/net/usb/cdc_ether.c | 75 -----------------------------------
 drivers/net/usb/usbnet.c    | 79 +++++++++++++++++++++++++++++++++++++
 2 files changed, 79 insertions(+), 75 deletions(-)

diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index a0a5740590b9..b4df32e18461 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -63,35 +63,6 @@ static const u8 mbm_guid[16] = {
 	0xa6, 0x07, 0xc0, 0xff, 0xcb, 0x7e, 0x39, 0x2a,
 };
 
-void usbnet_cdc_update_filter(struct usbnet *dev)
-{
-	struct net_device	*net = dev->net;
-
-	u16 cdc_filter = USB_CDC_PACKET_TYPE_DIRECTED
-			| USB_CDC_PACKET_TYPE_BROADCAST;
-
-	/* filtering on the device is an optional feature and not worth
-	 * the hassle so we just roughly care about snooping and if any
-	 * multicast is requested, we take every multicast
-	 */
-	if (net->flags & IFF_PROMISC)
-		cdc_filter |= USB_CDC_PACKET_TYPE_PROMISCUOUS;
-	if (!netdev_mc_empty(net) || (net->flags & IFF_ALLMULTI))
-		cdc_filter |= USB_CDC_PACKET_TYPE_ALL_MULTICAST;
-
-	usb_control_msg(dev->udev,
-			usb_sndctrlpipe(dev->udev, 0),
-			USB_CDC_SET_ETHERNET_PACKET_FILTER,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-			cdc_filter,
-			dev->intf->cur_altsetting->desc.bInterfaceNumber,
-			NULL,
-			0,
-			USB_CTRL_SET_TIMEOUT
-		);
-}
-EXPORT_SYMBOL_GPL(usbnet_cdc_update_filter);
-
 /* We need to override usbnet_*_link_ksettings in bind() */
 static const struct ethtool_ops cdc_ether_ethtool_ops = {
 	.get_link		= usbnet_get_link,
@@ -400,52 +371,6 @@ EXPORT_SYMBOL_GPL(usbnet_cdc_unbind);
  * (by Brad Hards) talked with, with more functionality.
  */
 
-static void speed_change(struct usbnet *dev, __le32 *speeds)
-{
-	dev->tx_speed = __le32_to_cpu(speeds[0]);
-	dev->rx_speed = __le32_to_cpu(speeds[1]);
-}
-
-void usbnet_cdc_status(struct usbnet *dev, struct urb *urb)
-{
-	struct usb_cdc_notification	*event;
-
-	if (urb->actual_length < sizeof(*event))
-		return;
-
-	/* SPEED_CHANGE can get split into two 8-byte packets */
-	if (test_and_clear_bit(EVENT_STS_SPLIT, &dev->flags)) {
-		speed_change(dev, (__le32 *) urb->transfer_buffer);
-		return;
-	}
-
-	event = urb->transfer_buffer;
-	switch (event->bNotificationType) {
-	case USB_CDC_NOTIFY_NETWORK_CONNECTION:
-		netif_dbg(dev, timer, dev->net, "CDC: carrier %s\n",
-			  event->wValue ? "on" : "off");
-		if (netif_carrier_ok(dev->net) != !!event->wValue)
-			usbnet_link_change(dev, !!event->wValue, 0);
-		break;
-	case USB_CDC_NOTIFY_SPEED_CHANGE:	/* tx/rx rates */
-		netif_dbg(dev, timer, dev->net, "CDC: speed change (len %d)\n",
-			  urb->actual_length);
-		if (urb->actual_length != (sizeof(*event) + 8))
-			set_bit(EVENT_STS_SPLIT, &dev->flags);
-		else
-			speed_change(dev, (__le32 *) &event[1]);
-		break;
-	/* USB_CDC_NOTIFY_RESPONSE_AVAILABLE can happen too (e.g. RNDIS),
-	 * but there are no standard formats for the response data.
-	 */
-	default:
-		netdev_err(dev->net, "CDC: unexpected notification %02x!\n",
-			   event->bNotificationType);
-		break;
-	}
-}
-EXPORT_SYMBOL_GPL(usbnet_cdc_status);
-
 int usbnet_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
 {
 	int				status;
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 25518635b7b7..21c55d70f27c 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/usb/cdc.h>
 #include <linux/ctype.h>
 #include <linux/ethtool.h>
 #include <linux/workqueue.h>
@@ -2271,6 +2272,84 @@ int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
 
 }
 EXPORT_SYMBOL_GPL(usbnet_write_cmd_async);
+
+void usbnet_cdc_update_filter(struct usbnet *dev)
+{
+	struct net_device	*net = dev->net;
+
+	u16 cdc_filter = USB_CDC_PACKET_TYPE_DIRECTED
+			| USB_CDC_PACKET_TYPE_BROADCAST;
+
+	/* filtering on the device is an optional feature and not worth
+	 * the hassle so we just roughly care about snooping and if any
+	 * multicast is requested, we take every multicast
+	 */
+	if (net->flags & IFF_PROMISC)
+		cdc_filter |= USB_CDC_PACKET_TYPE_PROMISCUOUS;
+	if (!netdev_mc_empty(net) || (net->flags & IFF_ALLMULTI))
+		cdc_filter |= USB_CDC_PACKET_TYPE_ALL_MULTICAST;
+
+	usb_control_msg(dev->udev,
+			usb_sndctrlpipe(dev->udev, 0),
+			USB_CDC_SET_ETHERNET_PACKET_FILTER,
+			USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+			cdc_filter,
+			dev->intf->cur_altsetting->desc.bInterfaceNumber,
+			NULL,
+			0,
+			USB_CTRL_SET_TIMEOUT
+		);
+}
+EXPORT_SYMBOL_GPL(usbnet_cdc_update_filter);
+
+static void speed_change(struct usbnet *dev, __le32 *speeds)
+{
+	dev->tx_speed = __le32_to_cpu(speeds[0]);
+	dev->rx_speed = __le32_to_cpu(speeds[1]);
+}
+
+void usbnet_cdc_status(struct usbnet *dev, struct urb *urb)
+{
+	struct usb_cdc_notification	*event;
+
+	if (urb->actual_length < sizeof(*event)) {
+		/* we cannot assume the device is in sync with us*/ 
+		clear_bit(EVENT_STS_SPLIT, &dev->flags);
+		return;
+	}
+
+	/* SPEED_CHANGE can get split into two 8-byte packets */
+	if (test_and_clear_bit(EVENT_STS_SPLIT, &dev->flags)) {
+		speed_change(dev, (__le32 *)urb->transfer_buffer);
+		return;
+	}
+
+	event = urb->transfer_buffer;
+	switch (event->bNotificationType) {
+	case USB_CDC_NOTIFY_NETWORK_CONNECTION:
+		netif_dbg(dev, timer, dev->net, "CDC: carrier %s\n",
+			  event->wValue ? "on" : "off");
+		if (netif_carrier_ok(dev->net) != !!event->wValue)
+			usbnet_link_change(dev, !!event->wValue, 0);
+		break;
+	case USB_CDC_NOTIFY_SPEED_CHANGE:	/* tx/rx rates */
+		netif_dbg(dev, timer, dev->net, "CDC: speed change (len %d)\n",
+			  urb->actual_length);
+		if (urb->actual_length != (sizeof(*event) + 8))
+			set_bit(EVENT_STS_SPLIT, &dev->flags);
+		else
+			speed_change(dev, (__le32 *)&event[1]);
+		break;
+	/* USB_CDC_NOTIFY_RESPONSE_AVAILABLE can happen too (e.g. RNDIS),
+	 * but there are no standard formats for the response data.
+	 */
+	default:
+		netdev_err(dev->net, "CDC: unexpected notification %02x!\n",
+			   event->bNotificationType);
+		break;
+	}
+}
+EXPORT_SYMBOL_GPL(usbnet_cdc_status);
 /*-------------------------------------------------------------------------*/
 
 static int __init usbnet_init(void)
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCHv3 net-next 2/9] net: usb: centralize usbnet_cdc_zte_rx_fixup in usbnet
  2026-07-14 11:44 [PATCHv3 net-next 1/9] net: usb: move updating filter and status from cdc drivers to usbnet Oliver Neukum
@ 2026-07-14 11:44 ` Oliver Neukum
  2026-07-14 11:44 ` [PATCHv3 net-next 3/9] net: usb: usbnet: add cdc_state to struct usbnet Oliver Neukum
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Oliver Neukum @ 2026-07-14 11:44 UTC (permalink / raw)
  To: andrew+netdev, davem, edumazet, kuba, pabeni, manuelebner, netdev,
	linux-kernel
  Cc: Oliver Neukum

This helper is used by multiple drivers using usbnet.
It is better to be provided by usbnet than one of them.

Signed-off-by: Oliver Neukum <oneukum@suse.com>
---

v2:
- spelling issues
- issue with lost synchronization with SPLIT packets

 drivers/net/usb/cdc_ether.c | 19 -------------------
 drivers/net/usb/usbnet.c    | 19 +++++++++++++++++++
 2 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index b4df32e18461..e688fb99c61d 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -404,25 +404,6 @@ static int usbnet_cdc_zte_bind(struct usbnet *dev, struct usb_interface *intf)
 	return status;
 }
 
-/* Make sure packets have correct destination MAC address
- *
- * A firmware bug observed on some devices (ZTE MF823/831/910) is that the
- * device sends packets with a static, bogus, random MAC address (event if
- * device MAC address has been updated). Always set MAC address to that of the
- * device.
- */
-int usbnet_cdc_zte_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
-{
-	if (skb->len < ETH_HLEN || !(skb->data[0] & 0x02))
-		return 1;
-
-	skb_reset_mac_header(skb);
-	ether_addr_copy(eth_hdr(skb)->h_dest, dev->net->dev_addr);
-
-	return 1;
-}
-EXPORT_SYMBOL_GPL(usbnet_cdc_zte_rx_fixup);
-
 /* Ensure correct link state
  *
  * Some devices (ZTE MF823/831/910) export two carrier on notifications when
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 21c55d70f27c..14e9f1b1e0a2 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -2350,6 +2350,25 @@ void usbnet_cdc_status(struct usbnet *dev, struct urb *urb)
 	}
 }
 EXPORT_SYMBOL_GPL(usbnet_cdc_status);
+
+/* Make sure packets have correct destination MAC address
+ *
+ * A firmware bug observed on some devices (ZTE MF823/831/910) is that the
+ * device sends packets with a static, bogus, random MAC address (event if
+ * device MAC address has been updated). Always set MAC address to that of the
+ * device.
+ */
+int usbnet_cdc_zte_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+	if (skb->len < ETH_HLEN || !(skb->data[0] & 0x02))
+		return 1;
+
+	skb_reset_mac_header(skb);
+	ether_addr_copy(eth_hdr(skb)->h_dest, dev->net->dev_addr);
+
+	return 1;
+}
+EXPORT_SYMBOL_GPL(usbnet_cdc_zte_rx_fixup);
 /*-------------------------------------------------------------------------*/
 
 static int __init usbnet_init(void)
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCHv3 net-next 3/9] net: usb: usbnet: add cdc_state to struct usbnet
  2026-07-14 11:44 [PATCHv3 net-next 1/9] net: usb: move updating filter and status from cdc drivers to usbnet Oliver Neukum
  2026-07-14 11:44 ` [PATCHv3 net-next 2/9] net: usb: centralize usbnet_cdc_zte_rx_fixup in usbnet Oliver Neukum
@ 2026-07-14 11:44 ` Oliver Neukum
  2026-07-15  1:18   ` Andrew Lunn
  2026-07-14 11:44 ` [PATCHv3 net-next 4/9] net: usb: use cdc_state in " Oliver Neukum
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 13+ messages in thread
From: Oliver Neukum @ 2026-07-14 11:44 UTC (permalink / raw)
  To: andrew+netdev, davem, edumazet, kuba, pabeni, manuelebner, netdev,
	linux-kernel
  Cc: Oliver Neukum

This allows centralisation of code using cdc_state in usbnet, reducing
code duplication. No functional change intended.

Signed-off-by: Oliver Neukum <oneukum@suse.com>
---
 include/linux/usb/usbnet.h | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index bbf799ccf3b3..79f48eb388ee 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -16,6 +16,14 @@
 #include <linux/usb.h>
 #include <linux/spinlock.h>
 
+struct cdc_state {
+	struct usb_cdc_header_desc      *header;
+	struct usb_cdc_union_desc       *u;
+	struct usb_cdc_ether_desc       *ether;
+	struct usb_interface            *control;
+	struct usb_interface            *data;
+};
+
 /* interface from usbnet core to each USB networking link we handle */
 struct usbnet {
 	/* housekeeping */
@@ -41,6 +49,7 @@ struct usbnet {
 	/* protocol/interface state */
 	struct net_device	*net;
 	int			msg_enable;
+	struct cdc_state	cdc;		/* too common to leave out*/
 	unsigned long		data[5];
 	u32			xid;
 	u32			hard_mtu;	/* count any extra framing */
@@ -211,13 +220,6 @@ extern int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
  * (notably, using multiple interfaces according to the CDC
  * union descriptor) get some helper code.
  */
-struct cdc_state {
-	struct usb_cdc_header_desc	*header;
-	struct usb_cdc_union_desc	*u;
-	struct usb_cdc_ether_desc	*ether;
-	struct usb_interface		*control;
-	struct usb_interface		*data;
-};
 
 extern void usbnet_cdc_update_filter(struct usbnet *dev);
 extern int usbnet_generic_cdc_bind(struct usbnet *, struct usb_interface *);
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCHv3 net-next 4/9] net: usb: use cdc_state in struct usbnet
  2026-07-14 11:44 [PATCHv3 net-next 1/9] net: usb: move updating filter and status from cdc drivers to usbnet Oliver Neukum
  2026-07-14 11:44 ` [PATCHv3 net-next 2/9] net: usb: centralize usbnet_cdc_zte_rx_fixup in usbnet Oliver Neukum
  2026-07-14 11:44 ` [PATCHv3 net-next 3/9] net: usb: usbnet: add cdc_state to struct usbnet Oliver Neukum
@ 2026-07-14 11:44 ` Oliver Neukum
  2026-07-14 11:44 ` [PATCHv3 net-next 5/9] net: usb: int51x1: drop dependency on cdc_ether Oliver Neukum
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Oliver Neukum @ 2026-07-14 11:44 UTC (permalink / raw)
  To: andrew+netdev, davem, edumazet, kuba, pabeni, manuelebner, netdev,
	linux-kernel
  Cc: Oliver Neukum

Remove private copies as now a central state can be used.

Signed-off-by: Oliver Neukum <oneukum@suse.com>
---
 drivers/net/usb/cdc_ether.c  | 9 +++------
 drivers/net/usb/rndis_host.c | 6 +++---
 2 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index e688fb99c61d..76ad4ffa950a 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -85,7 +85,7 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
 	u8				*buf = intf->cur_altsetting->extra;
 	int				len = intf->cur_altsetting->extralen;
 	struct usb_interface_descriptor	*d;
-	struct cdc_state		*info = (void *) &dev->data;
+	struct cdc_state		*info = &dev->cdc;
 	int				status = -ENODEV;
 	int				rndis;
 	bool				android_rndis_quirk = false;
@@ -336,7 +336,7 @@ EXPORT_SYMBOL_GPL(usbnet_ether_cdc_bind);
 
 void usbnet_cdc_unbind(struct usbnet *dev, struct usb_interface *intf)
 {
-	struct cdc_state		*info = (void *) &dev->data;
+	struct cdc_state		*info = &dev->cdc;
 	struct usb_driver		*driver = driver_of(intf);
 
 	/* combined interface - nothing  to do */
@@ -374,10 +374,7 @@ EXPORT_SYMBOL_GPL(usbnet_cdc_unbind);
 int usbnet_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
 {
 	int				status;
-	struct cdc_state		*info = (void *) &dev->data;
-
-	BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data)
-			< sizeof(struct cdc_state)));
+	struct cdc_state		*info = &dev->cdc;
 
 	status = usbnet_ether_cdc_bind(dev, intf);
 	if (status < 0)
diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c
index 5e39d05a2d7b..d539654687c3 100644
--- a/drivers/net/usb/rndis_host.c
+++ b/drivers/net/usb/rndis_host.c
@@ -57,7 +57,7 @@ EXPORT_SYMBOL_GPL(rndis_status);
 static void rndis_msg_indicate(struct usbnet *dev, struct rndis_indicate *msg,
 				int buflen)
 {
-	struct cdc_state *info = (void *)&dev->data;
+	struct cdc_state *info = &dev->cdc;
 	struct device *udev = &info->control->dev;
 
 	if (dev->driver_info->indication) {
@@ -90,7 +90,7 @@ static void rndis_msg_indicate(struct usbnet *dev, struct rndis_indicate *msg,
  */
 int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen)
 {
-	struct cdc_state	*info = (void *) &dev->data;
+	struct cdc_state	*info = &dev->cdc;
 	struct usb_cdc_notification notification;
 	int			master_ifnum;
 	int			retval;
@@ -290,7 +290,7 @@ generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags)
 {
 	int			retval;
 	struct net_device	*net = dev->net;
-	struct cdc_state	*info = (void *) &dev->data;
+	struct cdc_state	*info = &dev->cdc;
 	union {
 		void			*buf;
 		struct rndis_msg_hdr	*header;
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCHv3 net-next 5/9] net: usb: int51x1: drop dependency on cdc_ether
  2026-07-14 11:44 [PATCHv3 net-next 1/9] net: usb: move updating filter and status from cdc drivers to usbnet Oliver Neukum
                   ` (2 preceding siblings ...)
  2026-07-14 11:44 ` [PATCHv3 net-next 4/9] net: usb: use cdc_state in " Oliver Neukum
@ 2026-07-14 11:44 ` Oliver Neukum
  2026-07-14 11:44 ` [PATCHv3 net-next 6/9] net: usb: move exported symbols from cdc_ether to usbnet Oliver Neukum
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Oliver Neukum @ 2026-07-14 11:44 UTC (permalink / raw)
  To: andrew+netdev, davem, edumazet, kuba, pabeni, manuelebner, netdev,
	linux-kernel
  Cc: Oliver Neukum

The driver depended on cdc_ether only for usbnet_cdc_update_filter().
This has been shifted to usbnet. Drop the dependency.

Signed-off-by: Oliver Neukum <oneukum@suse.com>
---

v2:
- added as missed opportunity

 drivers/net/usb/Kconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index 52a5c0922c79..da0f6a138f4f 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -563,7 +563,6 @@ config USB_HSO
 config USB_NET_INT51X1
 	tristate "Intellon PLC based usb adapter"
 	depends on USB_USBNET
-	select USB_NET_CDCETHER
 	help
 	  Choose this option if you're using a 14Mb USB-based PLC
 	  (Powerline Communications) solution with an Intellon
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCHv3 net-next 6/9] net: usb: move exported symbols from cdc_ether to usbnet
  2026-07-14 11:44 [PATCHv3 net-next 1/9] net: usb: move updating filter and status from cdc drivers to usbnet Oliver Neukum
                   ` (3 preceding siblings ...)
  2026-07-14 11:44 ` [PATCHv3 net-next 5/9] net: usb: int51x1: drop dependency on cdc_ether Oliver Neukum
@ 2026-07-14 11:44 ` Oliver Neukum
  2026-07-21 16:24   ` Jakub Kicinski
  2026-07-14 11:44 ` [PATCHv3 net-next 7/9] net: usb: remove dependencies on cdc_ether Oliver Neukum
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 13+ messages in thread
From: Oliver Neukum @ 2026-07-14 11:44 UTC (permalink / raw)
  To: andrew+netdev, davem, edumazet, kuba, pabeni, manuelebner, netdev,
	linux-kernel
  Cc: Oliver Neukum

Move the rest of the symbols to usbnet, so that the cdc_ether
driver does not need to be loaded as a library.

Signed-off-by: Oliver Neukum <oneukum@suse.com>
---
 drivers/net/usb/cdc_ether.c | 372 ------------------------------------
 drivers/net/usb/usbnet.c    | 356 ++++++++++++++++++++++++++++++++++
 include/linux/usb/usbnet.h  |  17 ++
 3 files changed, 373 insertions(+), 372 deletions(-)

diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index 76ad4ffa950a..6bf6538f3468 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -19,378 +19,6 @@
 #include <linux/usb/usbnet.h>
 
 
-#if IS_ENABLED(CONFIG_USB_NET_RNDIS_HOST)
-
-static int is_rndis(struct usb_interface_descriptor *desc)
-{
-	return (desc->bInterfaceClass == USB_CLASS_COMM &&
-		desc->bInterfaceSubClass == 2 &&
-		desc->bInterfaceProtocol == 0xff);
-}
-
-static int is_activesync(struct usb_interface_descriptor *desc)
-{
-	return (desc->bInterfaceClass == USB_CLASS_MISC &&
-		desc->bInterfaceSubClass == 1 &&
-		desc->bInterfaceProtocol == 1);
-}
-
-static int is_wireless_rndis(struct usb_interface_descriptor *desc)
-{
-	return (desc->bInterfaceClass == USB_CLASS_WIRELESS_CONTROLLER &&
-		desc->bInterfaceSubClass == 1 &&
-		desc->bInterfaceProtocol == 3);
-}
-
-static int is_novatel_rndis(struct usb_interface_descriptor *desc)
-{
-	return (desc->bInterfaceClass == USB_CLASS_MISC &&
-		desc->bInterfaceSubClass == 4 &&
-		desc->bInterfaceProtocol == 1);
-}
-
-#else
-
-#define is_rndis(desc)		0
-#define is_activesync(desc)	0
-#define is_wireless_rndis(desc)	0
-#define is_novatel_rndis(desc)	0
-
-#endif
-
-static const u8 mbm_guid[16] = {
-	0xa3, 0x17, 0xa8, 0x8b, 0x04, 0x5e, 0x4f, 0x01,
-	0xa6, 0x07, 0xc0, 0xff, 0xcb, 0x7e, 0x39, 0x2a,
-};
-
-/* We need to override usbnet_*_link_ksettings in bind() */
-static const struct ethtool_ops cdc_ether_ethtool_ops = {
-	.get_link		= usbnet_get_link,
-	.nway_reset		= usbnet_nway_reset,
-	.get_drvinfo		= usbnet_get_drvinfo,
-	.get_msglevel		= usbnet_get_msglevel,
-	.set_msglevel		= usbnet_set_msglevel,
-	.get_ts_info		= ethtool_op_get_ts_info,
-	.get_link_ksettings	= usbnet_get_link_ksettings_internal,
-	.set_link_ksettings	= NULL,
-};
-
-/* probes control interface, claims data interface, collects the bulk
- * endpoints, activates data interface (if needed), maybe sets MTU.
- * all pure cdc, except for certain firmware workarounds, and knowing
- * that rndis uses one different rule.
- */
-int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
-{
-	u8				*buf = intf->cur_altsetting->extra;
-	int				len = intf->cur_altsetting->extralen;
-	struct usb_interface_descriptor	*d;
-	struct cdc_state		*info = &dev->cdc;
-	int				status = -ENODEV;
-	int				rndis;
-	bool				android_rndis_quirk = false;
-	struct usb_driver		*driver = driver_of(intf);
-	struct usb_cdc_parsed_header header;
-
-	if (sizeof(dev->data) < sizeof(*info))
-		return -EDOM;
-
-	/* expect strict spec conformance for the descriptors, but
-	 * cope with firmware which stores them in the wrong place
-	 */
-	if (len == 0 && dev->udev->actconfig->extralen) {
-		/* Motorola SB4100 (and others: Brad Hards says it's
-		 * from a Broadcom design) put CDC descriptors here
-		 */
-		buf = dev->udev->actconfig->extra;
-		len = dev->udev->actconfig->extralen;
-		dev_dbg(&intf->dev, "CDC descriptors on config\n");
-	}
-
-	/* Maybe CDC descriptors are after the endpoint?  This bug has
-	 * been seen on some 2Wire Inc RNDIS-ish products.
-	 */
-	if (len == 0) {
-		struct usb_host_endpoint	*hep;
-
-		hep = intf->cur_altsetting->endpoint;
-		if (hep) {
-			buf = hep->extra;
-			len = hep->extralen;
-		}
-		if (len)
-			dev_dbg(&intf->dev,
-				"CDC descriptors on endpoint\n");
-	}
-
-	/* this assumes that if there's a non-RNDIS vendor variant
-	 * of cdc-acm, it'll fail RNDIS requests cleanly.
-	 */
-	rndis = (is_rndis(&intf->cur_altsetting->desc) ||
-		 is_activesync(&intf->cur_altsetting->desc) ||
-		 is_wireless_rndis(&intf->cur_altsetting->desc) ||
-		 is_novatel_rndis(&intf->cur_altsetting->desc));
-
-	memset(info, 0, sizeof(*info));
-	info->control = intf;
-
-	cdc_parse_cdc_header(&header, intf, buf, len);
-
-	info->u = header.usb_cdc_union_desc;
-	info->header = header.usb_cdc_header_desc;
-	info->ether = header.usb_cdc_ether_desc;
-	if (!info->u) {
-		if (rndis) {
-			goto skip;
-		} else {
-			/* in that case a quirk is mandatory */
-			dev_err(&dev->udev->dev, "No union descriptors\n");
-			goto bad_desc;
-		}
-	}
-	/* we need a master/control interface (what we're
-	 * probed with) and a slave/data interface; union
-	 * descriptors sort this all out.
-	 */
-	info->control = usb_ifnum_to_if(dev->udev, info->u->bMasterInterface0);
-	info->data = usb_ifnum_to_if(dev->udev, info->u->bSlaveInterface0);
-	if (!info->control || !info->data) {
-		dev_dbg(&intf->dev,
-			"master #%u/%p slave #%u/%p\n",
-			info->u->bMasterInterface0,
-			info->control,
-			info->u->bSlaveInterface0,
-			info->data);
-		/* fall back to hard-wiring for RNDIS */
-		if (rndis) {
-			android_rndis_quirk = true;
-			goto skip;
-		}
-		dev_err(&intf->dev, "bad CDC descriptors\n");
-		goto bad_desc;
-	}
-	if (info->control != intf) {
-		/* Ambit USB Cable Modem (and maybe others)
-		 * interchanges master and slave interface.
-		 */
-		if (info->data == intf) {
-			info->data = info->control;
-			info->control = intf;
-		} else {
-			dev_err(&intf->dev, "bogus CDC Union\n");
-			goto bad_desc;
-		}
-	}
-
-	/* some devices merge these - skip class check */
-	if (info->control == info->data)
-		goto skip;
-
-	/* a data interface altsetting does the real i/o */
-	d = &info->data->cur_altsetting->desc;
-	if (d->bInterfaceClass != USB_CLASS_CDC_DATA) {
-		dev_err(&intf->dev, "slave class %u\n", d->bInterfaceClass);
-		goto bad_desc;
-	}
-skip:
-	/* Communication class functions with bmCapabilities are not
-	 * RNDIS.  But some Wireless class RNDIS functions use
-	 * bmCapabilities for their own purpose. The failsafe is
-	 * therefore applied only to Communication class RNDIS
-	 * functions.  The rndis test is redundant, but a cheap
-	 * optimization.
-	 */
-	if (rndis && is_rndis(&intf->cur_altsetting->desc) &&
-	    header.usb_cdc_acm_descriptor &&
-	    header.usb_cdc_acm_descriptor->bmCapabilities) {
-		dev_err(&intf->dev,
-			"ACM capabilities %02x, not really RNDIS?\n",
-			header.usb_cdc_acm_descriptor->bmCapabilities);
-		goto bad_desc;
-	}
-
-	if (header.usb_cdc_ether_desc && info->ether->wMaxSegmentSize) {
-		dev->hard_mtu = le16_to_cpu(info->ether->wMaxSegmentSize);
-		/* because of Zaurus, we may be ignoring the host
-		 * side link address we were given.
-		 */
-	}
-
-	if (header.usb_cdc_mdlm_desc &&
-	    memcmp(header.usb_cdc_mdlm_desc->bGUID, mbm_guid, 16)) {
-		dev_err(&intf->dev, "GUID doesn't match\n");
-		goto bad_desc;
-	}
-
-	if (header.usb_cdc_mdlm_detail_desc &&
-		header.usb_cdc_mdlm_detail_desc->bLength <
-			(sizeof(struct usb_cdc_mdlm_detail_desc) + 1)) {
-		dev_err(&intf->dev, "Descriptor too short\n");
-		goto bad_desc;
-	}
-
-
-
-	/* Microsoft ActiveSync based and some regular RNDIS devices lack the
-	 * CDC descriptors, so we'll hard-wire the interfaces and not check
-	 * for descriptors.
-	 *
-	 * Some Android RNDIS devices have a CDC Union descriptor pointing
-	 * to non-existing interfaces.  Ignore that and attempt the same
-	 * hard-wired 0 and 1 interfaces.
-	 */
-	if (rndis && (!info->u || android_rndis_quirk)) {
-		info->control = usb_ifnum_to_if(dev->udev, 0);
-		info->data = usb_ifnum_to_if(dev->udev, 1);
-		if (!info->control || !info->data || info->control != intf) {
-			dev_err(&intf->dev,
-				"rndis: master #0/%p slave #1/%p\n",
-				info->control,
-				info->data);
-			goto bad_desc;
-		}
-
-	} else if (!info->header || (!rndis && !info->ether)) {
-		dev_err(&intf->dev, "missing cdc %s%s%sdescriptor\n",
-			info->header ? "" : "header ",
-			info->u ? "" : "union ",
-			info->ether ? "" : "ether ");
-		goto bad_desc;
-	}
-
-	/* claim data interface and set it up ... with side effects.
-	 * network traffic can't flow until an altsetting is enabled.
-	 */
-	if (info->data != info->control) {
-		status = usb_driver_claim_interface(driver, info->data, dev);
-		if (status < 0) {
-			dev_err(&intf->dev, "Second interface unclaimable\n");
-			goto bad_desc;
-		}
-	}
-	status = usbnet_get_endpoints(dev, info->data);
-	if (status < 0) {
-		dev_dbg(&intf->dev, "Mandatory endpoints missing\n");
-		goto bail_out_and_release;
-	}
-
-	/* status endpoint: optional for CDC Ethernet, not RNDIS (or ACM) */
-	if (info->data != info->control)
-		dev->status = NULL;
-	if (info->control->cur_altsetting->desc.bNumEndpoints == 1) {
-		struct usb_endpoint_descriptor	*desc;
-
-		dev->status = &info->control->cur_altsetting->endpoint[0];
-		desc = &dev->status->desc;
-		if (!usb_endpoint_is_int_in(desc) ||
-		    (le16_to_cpu(desc->wMaxPacketSize)
-		     < sizeof(struct usb_cdc_notification)) ||
-		    !desc->bInterval) {
-			dev_dbg(&intf->dev, "bad notification endpoint\n");
-			dev->status = NULL;
-		}
-	}
-	if (rndis && !dev->status) {
-		dev_err(&intf->dev, "missing RNDIS status endpoint\n");
-		status = -ENODEV;
-		goto bail_out_and_release;
-	}
-
-	/* override ethtool_ops */
-	dev->net->ethtool_ops = &cdc_ether_ethtool_ops;
-
-	return 0;
-
-bail_out_and_release:
-	usb_set_intfdata(info->data, NULL);
-	if (info->data != info->control)
-		usb_driver_release_interface(driver, info->data);
-bad_desc:
-	return status;
-}
-EXPORT_SYMBOL_GPL(usbnet_generic_cdc_bind);
-
-
-/* like usbnet_generic_cdc_bind() but handles filter initialization
- * correctly
- */
-int usbnet_ether_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
-{
-	int rv;
-
-	rv = usbnet_generic_cdc_bind(dev, intf);
-	if (rv < 0)
-		goto bail_out;
-
-	/* Some devices don't initialise properly. In particular
-	 * the packet filter is not reset. There are devices that
-	 * don't do reset all the way. So the packet filter should
-	 * be set to a sane initial value.
-	 */
-	usbnet_cdc_update_filter(dev);
-
-bail_out:
-	return rv;
-}
-EXPORT_SYMBOL_GPL(usbnet_ether_cdc_bind);
-
-void usbnet_cdc_unbind(struct usbnet *dev, struct usb_interface *intf)
-{
-	struct cdc_state		*info = &dev->cdc;
-	struct usb_driver		*driver = driver_of(intf);
-
-	/* combined interface - nothing  to do */
-	if (info->data == info->control)
-		return;
-
-	/* disconnect master --> disconnect slave */
-	if (intf == info->control && info->data) {
-		/* ensure immediate exit from usbnet_disconnect */
-		usb_set_intfdata(info->data, NULL);
-		usb_driver_release_interface(driver, info->data);
-		info->data = NULL;
-	}
-
-	/* and vice versa (just in case) */
-	else if (intf == info->data && info->control) {
-		/* ensure immediate exit from usbnet_disconnect */
-		usb_set_intfdata(info->control, NULL);
-		usb_driver_release_interface(driver, info->control);
-		info->control = NULL;
-	}
-}
-EXPORT_SYMBOL_GPL(usbnet_cdc_unbind);
-
-/* Communications Device Class, Ethernet Control model
- *
- * Takes two interfaces.  The DATA interface is inactive till an altsetting
- * is selected.  Configuration data includes class descriptors.  There's
- * an optional status endpoint on the control interface.
- *
- * This should interop with whatever the 2.4 "CDCEther.c" driver
- * (by Brad Hards) talked with, with more functionality.
- */
-
-int usbnet_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
-{
-	int				status;
-	struct cdc_state		*info = &dev->cdc;
-
-	status = usbnet_ether_cdc_bind(dev, intf);
-	if (status < 0)
-		return status;
-
-	status = usbnet_get_ethernet_addr(dev, info->ether->iMACAddress);
-	if (status < 0) {
-		usb_set_intfdata(info->data, NULL);
-		usb_driver_release_interface(driver_of(intf), info->data);
-		return status;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(usbnet_cdc_bind);
-
 static int usbnet_cdc_zte_bind(struct usbnet *dev, struct usb_interface *intf)
 {
 	int status = usbnet_cdc_bind(dev, intf);
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 14e9f1b1e0a2..ce932c81382e 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -2369,6 +2369,362 @@ int usbnet_cdc_zte_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 	return 1;
 }
 EXPORT_SYMBOL_GPL(usbnet_cdc_zte_rx_fixup);
+
+
+#if IS_ENABLED(CONFIG_USB_NET_RNDIS_HOST)
+
+static int is_rndis(struct usb_interface_descriptor *desc)
+{
+	return (desc->bInterfaceClass == USB_CLASS_COMM &&
+		desc->bInterfaceSubClass == 2 &&
+		desc->bInterfaceProtocol == 0xff);
+}
+
+static int is_activesync(struct usb_interface_descriptor *desc)
+{
+	return (desc->bInterfaceClass == USB_CLASS_MISC &&
+		desc->bInterfaceSubClass == 1 &&
+		desc->bInterfaceProtocol == 1);
+}
+
+static int is_wireless_rndis(struct usb_interface_descriptor *desc)
+{
+	return (desc->bInterfaceClass == USB_CLASS_WIRELESS_CONTROLLER &&
+		desc->bInterfaceSubClass == 1 &&
+		desc->bInterfaceProtocol == 3);
+}
+
+static int is_novatel_rndis(struct usb_interface_descriptor *desc)
+{
+	return (desc->bInterfaceClass == USB_CLASS_MISC &&
+		desc->bInterfaceSubClass == 4 &&
+		desc->bInterfaceProtocol == 1);
+}
+
+#else
+
+#define is_rndis(desc)		0
+#define is_activesync(desc)	0
+#define is_wireless_rndis(desc)	0
+#define is_novatel_rndis(desc)	0
+
+#endif
+
+/* Communications Device Class, Ethernet Control model
+ *
+ * Takes two interfaces.  The DATA interface is inactive till an altsetting
+ * is selected.  Configuration data includes class descriptors.  There's
+ * an optional status endpoint on the control interface.
+ *
+ * This should interop with whatever the 2.4 "CDCEther.c" driver
+ * (by Brad Hards) talked with, with more functionality.
+ */
+
+int usbnet_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+	int				status;
+	struct cdc_state		*info = &dev->cdc;
+
+	status = usbnet_ether_cdc_bind(dev, intf);
+	if (status < 0)
+		return status;
+
+	status = usbnet_get_ethernet_addr(dev, info->ether->iMACAddress);
+	if (status < 0) {
+		usb_set_intfdata(info->data, NULL);
+		usb_driver_release_interface(driver_of(intf), info->data);
+		return status;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(usbnet_cdc_bind);
+
+/* probes control interface, claims data interface, collects the bulk
+ * endpoints, activates data interface (if needed), maybe sets MTU.
+ * all pure cdc, except for certain firmware workarounds, and knowing
+ * that rndis uses one different rule.
+ */
+int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+	u8				*buf = intf->cur_altsetting->extra;
+	int				len = intf->cur_altsetting->extralen;
+	struct usb_interface_descriptor	*d;
+	struct cdc_state		*info = &dev->cdc;
+	int				status = -ENODEV;
+	int				rndis;
+	bool				android_rndis_quirk = false;
+	struct usb_driver		*driver = driver_of(intf);
+	struct usb_cdc_parsed_header header;
+
+	if (sizeof(dev->data) < sizeof(*info))
+		return -EDOM;
+
+	/* expect strict spec conformance for the descriptors, but
+	 * cope with firmware which stores them in the wrong place
+	 */
+	if (len == 0 && dev->udev->actconfig->extralen) {
+		/* Motorola SB4100 (and others: Brad Hards says it's
+		 * from a Broadcom design) put CDC descriptors here
+		 */
+		buf = dev->udev->actconfig->extra;
+		len = dev->udev->actconfig->extralen;
+		dev_dbg(&intf->dev, "CDC descriptors on config\n");
+	}
+
+	/* Maybe CDC descriptors are after the endpoint?  This bug has
+	 * been seen on some 2Wire Inc RNDIS-ish products.
+	 */
+	if (len == 0) {
+		struct usb_host_endpoint	*hep;
+
+		hep = intf->cur_altsetting->endpoint;
+		if (hep) {
+			buf = hep->extra;
+			len = hep->extralen;
+		}
+		if (len)
+			dev_dbg(&intf->dev,
+				"CDC descriptors on endpoint\n");
+	}
+
+	/* this assumes that if there's a non-RNDIS vendor variant
+	 * of cdc-acm, it'll fail RNDIS requests cleanly.
+	 */
+	rndis = (is_rndis(&intf->cur_altsetting->desc) ||
+		 is_activesync(&intf->cur_altsetting->desc) ||
+		 is_wireless_rndis(&intf->cur_altsetting->desc) ||
+		 is_novatel_rndis(&intf->cur_altsetting->desc));
+
+	memset(info, 0, sizeof(*info));
+	info->control = intf;
+
+	cdc_parse_cdc_header(&header, intf, buf, len);
+
+	info->u = header.usb_cdc_union_desc;
+	info->header = header.usb_cdc_header_desc;
+	info->ether = header.usb_cdc_ether_desc;
+	if (!info->u) {
+		if (rndis) {
+			goto skip;
+		} else {
+			/* in that case a quirk is mandatory */
+			dev_err(&dev->udev->dev, "No union descriptors\n");
+			goto bad_desc;
+		}
+	}
+	/* we need a master/control interface (what we're
+	 * probed with) and a slave/data interface; union
+	 * descriptors sort this all out.
+	 */
+	info->control = usb_ifnum_to_if(dev->udev, info->u->bMasterInterface0);
+	info->data = usb_ifnum_to_if(dev->udev, info->u->bSlaveInterface0);
+	if (!info->control || !info->data) {
+		dev_dbg(&intf->dev,
+			"master #%u/%p slave #%u/%p\n",
+			info->u->bMasterInterface0,
+			info->control,
+			info->u->bSlaveInterface0,
+			info->data);
+		/* fall back to hard-wiring for RNDIS */
+		if (rndis) {
+			android_rndis_quirk = true;
+			goto skip;
+		}
+		dev_err(&intf->dev, "bad CDC descriptors\n");
+		goto bad_desc;
+	}
+	if (info->control != intf) {
+		/* Ambit USB Cable Modem (and maybe others)
+		 * interchanges master and slave interface.
+		 */
+		if (info->data == intf) {
+			info->data = info->control;
+			info->control = intf;
+		} else {
+			dev_err(&intf->dev, "bogus CDC Union\n");
+			goto bad_desc;
+		}
+	}
+
+	/* some devices merge these - skip class check */
+	if (info->control == info->data)
+		goto skip;
+
+	/* a data interface altsetting does the real i/o */
+	d = &info->data->cur_altsetting->desc;
+	if (d->bInterfaceClass != USB_CLASS_CDC_DATA) {
+		dev_err(&intf->dev, "slave class %u\n", d->bInterfaceClass);
+		goto bad_desc;
+	}
+skip:
+	/* Communication class functions with bmCapabilities are not
+	 * RNDIS.  But some Wireless class RNDIS functions use
+	 * bmCapabilities for their own purpose. The failsafe is
+	 * therefore applied only to Communication class RNDIS
+	 * functions.  The rndis test is redundant, but a cheap
+	 * optimization.
+	 */
+	if (rndis && is_rndis(&intf->cur_altsetting->desc) &&
+	    header.usb_cdc_acm_descriptor &&
+	    header.usb_cdc_acm_descriptor->bmCapabilities) {
+		dev_err(&intf->dev,
+			"ACM capabilities %02x, not really RNDIS?\n",
+			header.usb_cdc_acm_descriptor->bmCapabilities);
+		goto bad_desc;
+	}
+
+	if (header.usb_cdc_ether_desc && info->ether->wMaxSegmentSize) {
+		dev->hard_mtu = le16_to_cpu(info->ether->wMaxSegmentSize);
+		/* because of Zaurus, we may be ignoring the host
+		 * side link address we were given.
+		 */
+	}
+
+	if (header.usb_cdc_mdlm_desc &&
+	    memcmp(header.usb_cdc_mdlm_desc->bGUID, mbm_guid, 16)) {
+		dev_err(&intf->dev, "GUID doesn't match\n");
+		goto bad_desc;
+	}
+
+	if (header.usb_cdc_mdlm_detail_desc &&
+		header.usb_cdc_mdlm_detail_desc->bLength <
+			(sizeof(struct usb_cdc_mdlm_detail_desc) + 1)) {
+		dev_err(&intf->dev, "Descriptor too short\n");
+		goto bad_desc;
+	}
+
+
+
+	/* Microsoft ActiveSync based and some regular RNDIS devices lack the
+	 * CDC descriptors, so we'll hard-wire the interfaces and not check
+	 * for descriptors.
+	 *
+	 * Some Android RNDIS devices have a CDC Union descriptor pointing
+	 * to non-existing interfaces.  Ignore that and attempt the same
+	 * hard-wired 0 and 1 interfaces.
+	 */
+	if (rndis && (!info->u || android_rndis_quirk)) {
+		info->control = usb_ifnum_to_if(dev->udev, 0);
+		info->data = usb_ifnum_to_if(dev->udev, 1);
+		if (!info->control || !info->data || info->control != intf) {
+			dev_err(&intf->dev,
+				"rndis: master #0/%p slave #1/%p\n",
+				info->control,
+				info->data);
+			goto bad_desc;
+		}
+
+	} else if (!info->header || (!rndis && !info->ether)) {
+		dev_err(&intf->dev, "missing cdc %s%s%sdescriptor\n",
+			info->header ? "" : "header ",
+			info->u ? "" : "union ",
+			info->ether ? "" : "ether ");
+		goto bad_desc;
+	}
+
+	/* claim data interface and set it up ... with side effects.
+	 * network traffic can't flow until an altsetting is enabled.
+	 */
+	if (info->data != info->control) {
+		status = usb_driver_claim_interface(driver, info->data, dev);
+		if (status < 0) {
+			dev_err(&intf->dev, "Second interface unclaimable\n");
+			goto bad_desc;
+		}
+	}
+	status = usbnet_get_endpoints(dev, info->data);
+	if (status < 0) {
+		dev_dbg(&intf->dev, "Mandatory endpoints missing\n");
+		goto bail_out_and_release;
+	}
+
+	/* status endpoint: optional for CDC Ethernet, not RNDIS (or ACM) */
+	if (info->data != info->control)
+		dev->status = NULL;
+	if (info->control->cur_altsetting->desc.bNumEndpoints == 1) {
+		struct usb_endpoint_descriptor	*desc;
+
+		dev->status = &info->control->cur_altsetting->endpoint[0];
+		desc = &dev->status->desc;
+		if (!usb_endpoint_is_int_in(desc) ||
+		    (le16_to_cpu(desc->wMaxPacketSize)
+		     < sizeof(struct usb_cdc_notification)) ||
+		    !desc->bInterval) {
+			dev_dbg(&intf->dev, "bad notification endpoint\n");
+			dev->status = NULL;
+		}
+	}
+	if (rndis && !dev->status) {
+		dev_err(&intf->dev, "missing RNDIS status endpoint\n");
+		status = -ENODEV;
+		goto bail_out_and_release;
+	}
+
+	/* override ethtool_ops */
+	dev->net->ethtool_ops = &cdc_ether_ethtool_ops;
+
+	return 0;
+
+bail_out_and_release:
+	usb_set_intfdata(info->data, NULL);
+	if (info->data != info->control)
+		usb_driver_release_interface(driver, info->data);
+bad_desc:
+	return status;
+}
+EXPORT_SYMBOL_GPL(usbnet_generic_cdc_bind);
+
+/* like usbnet_generic_cdc_bind() but handles filter initialization
+ * correctly
+ */
+int usbnet_ether_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+	int rv;
+
+	rv = usbnet_generic_cdc_bind(dev, intf);
+	if (rv < 0)
+		goto bail_out;
+
+	/* Some devices don't initialise properly. In particular
+	 * the packet filter is not reset. There are devices that
+	 * don't do reset all the way. So the packet filter should
+	 * be set to a sane initial value.
+	 */
+	usbnet_cdc_update_filter(dev);
+
+bail_out:
+	return rv;
+}
+EXPORT_SYMBOL_GPL(usbnet_ether_cdc_bind);
+
+void usbnet_cdc_unbind(struct usbnet *dev, struct usb_interface *intf)
+{
+	struct cdc_state		*info = &dev->cdc;
+	struct usb_driver		*driver = driver_of(intf);
+
+	/* combined interface - nothing  to do */
+	if (info->data == info->control)
+		return;
+
+	/* disconnect master --> disconnect slave */
+	if (intf == info->control && info->data) {
+		/* ensure immediate exit from usbnet_disconnect */
+		usb_set_intfdata(info->data, NULL);
+		usb_driver_release_interface(driver, info->data);
+		info->data = NULL;
+	}
+
+	/* and vice versa (just in case) */
+	else if (intf == info->data && info->control) {
+		/* ensure immediate exit from usbnet_disconnect */
+		usb_set_intfdata(info->control, NULL);
+		usb_driver_release_interface(driver, info->control);
+		info->control = NULL;
+	}
+}
+EXPORT_SYMBOL_GPL(usbnet_cdc_unbind);
+
 /*-------------------------------------------------------------------------*/
 
 static int __init usbnet_init(void)
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index 79f48eb388ee..b3a77078fb10 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -16,6 +16,11 @@
 #include <linux/usb.h>
 #include <linux/spinlock.h>
 
+static const u8 mbm_guid[16] = {
+	0xa3, 0x17, 0xa8, 0x8b, 0x04, 0x5e, 0x4f, 0x01,
+	0xa6, 0x07, 0xc0, 0xff, 0xcb, 0x7e, 0x39, 0x2a,
+};
+
 struct cdc_state {
 	struct usb_cdc_header_desc      *header;
 	struct usb_cdc_union_desc       *u;
@@ -304,4 +309,16 @@ extern void usbnet_status_stop(struct usbnet *dev);
 
 extern void usbnet_update_max_qlen(struct usbnet *dev);
 
+/* We need to override usbnet_*_link_ksettings in bind() */
+static const struct ethtool_ops cdc_ether_ethtool_ops = {
+	.get_link		= usbnet_get_link,
+	.nway_reset		= usbnet_nway_reset,
+	.get_drvinfo		= usbnet_get_drvinfo,
+	.get_msglevel		= usbnet_get_msglevel,
+	.set_msglevel		= usbnet_set_msglevel,
+	.get_ts_info		= ethtool_op_get_ts_info,
+	.get_link_ksettings	= usbnet_get_link_ksettings_internal,
+	.set_link_ksettings	= NULL,
+};
+
 #endif /* __LINUX_USB_USBNET_H */
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCHv3 net-next 7/9] net: usb: remove dependencies on cdc_ether
  2026-07-14 11:44 [PATCHv3 net-next 1/9] net: usb: move updating filter and status from cdc drivers to usbnet Oliver Neukum
                   ` (4 preceding siblings ...)
  2026-07-14 11:44 ` [PATCHv3 net-next 6/9] net: usb: move exported symbols from cdc_ether to usbnet Oliver Neukum
@ 2026-07-14 11:44 ` Oliver Neukum
  2026-07-14 11:44 ` [PATCHv3 net-next 8/9] net: usb: usbnet: remove outdated sanity check Oliver Neukum
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Oliver Neukum @ 2026-07-14 11:44 UTC (permalink / raw)
  To: andrew+netdev, davem, edumazet, kuba, pabeni, manuelebner, netdev,
	linux-kernel
  Cc: Oliver Neukum

Now that the driver no longer exports symbols to act
as a library for other drivers other drivers don't
depend on it. Remove the dependencies.

Signed-off-by: Oliver Neukum <oneukum@suse.com>
---

v3:
- removed unneeded parantheses

 drivers/net/usb/Kconfig | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index da0f6a138f4f..732e0d5f331d 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -258,7 +258,6 @@ config USB_NET_CDC_EEM
 config USB_NET_CDC_NCM
 	tristate "CDC NCM support"
 	depends on USB_USBNET
-	select USB_NET_CDCETHER
 	default y
 	help
 	  This driver provides support for CDC NCM (Network Control Model
@@ -399,7 +398,6 @@ config USB_NET_MCS7830
 config USB_NET_RNDIS_HOST
 	tristate "Host for RNDIS and ActiveSync devices"
 	depends on USB_USBNET
-	select USB_NET_CDCETHER
 	help
 	  This option enables hosting "Remote NDIS" USB networking links,
 	  as encouraged by Microsoft (instead of CDC Ethernet!) for use in
@@ -494,7 +492,6 @@ config USB_KC2190
 config USB_NET_ZAURUS
 	tristate "Sharp Zaurus (stock ROMs) and compatible"
 	depends on USB_USBNET
-	select USB_NET_CDCETHER
 	select CRC32
 	default y
 	help
@@ -597,7 +594,7 @@ config USB_SIERRA_NET
 
 config USB_VL600
 	tristate "LG VL600 modem dongle"
-	depends on USB_NET_CDCETHER && TTY
+	depends on TTY
 	select USB_ACM
 	help
 	  Select this if you want to use an LG Electronics 4G/LTE usb modem
@@ -634,7 +631,7 @@ config USB_NET_AQC111
 
 config USB_RTL8153_ECM
 	tristate
-	depends on USB_NET_CDCETHER && (USB_RTL8152 || USB_RTL8152=n)
+	depends on USB_RTL8152 || USB_RTL8152=n
 	default y
 	help
 	  This option supports ECM mode for RTL8153 ethernet adapter, when
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCHv3 net-next 8/9] net: usb: usbnet: remove outdated sanity check
  2026-07-14 11:44 [PATCHv3 net-next 1/9] net: usb: move updating filter and status from cdc drivers to usbnet Oliver Neukum
                   ` (5 preceding siblings ...)
  2026-07-14 11:44 ` [PATCHv3 net-next 7/9] net: usb: remove dependencies on cdc_ether Oliver Neukum
@ 2026-07-14 11:44 ` Oliver Neukum
  2026-07-14 11:44 ` [PATCHv3 net-next 9/9] net: usb: usbnet: corrections in the comments Oliver Neukum
  2026-07-21 16:23 ` [PATCHv3 net-next 1/9] net: usb: move updating filter and status from cdc drivers to usbnet Jakub Kicinski
  8 siblings, 0 replies; 13+ messages in thread
From: Oliver Neukum @ 2026-07-14 11:44 UTC (permalink / raw)
  To: andrew+netdev, davem, edumazet, kuba, pabeni, manuelebner, netdev,
	linux-kernel
  Cc: Oliver Neukum

The cdc state is now included as a proper member in the descriptor.
There is no point in checking whether it fits into the scratchpad
area. Just remove the check.

Signed-off-by: Oliver Neukum <oneukum@suse.com>
---
 drivers/net/usb/usbnet.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index ce932c81382e..0347f6887222 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -2457,9 +2457,6 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
 	struct usb_driver		*driver = driver_of(intf);
 	struct usb_cdc_parsed_header header;
 
-	if (sizeof(dev->data) < sizeof(*info))
-		return -EDOM;
-
 	/* expect strict spec conformance for the descriptors, but
 	 * cope with firmware which stores them in the wrong place
 	 */
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCHv3 net-next 9/9] net: usb: usbnet: corrections in the comments
  2026-07-14 11:44 [PATCHv3 net-next 1/9] net: usb: move updating filter and status from cdc drivers to usbnet Oliver Neukum
                   ` (6 preceding siblings ...)
  2026-07-14 11:44 ` [PATCHv3 net-next 8/9] net: usb: usbnet: remove outdated sanity check Oliver Neukum
@ 2026-07-14 11:44 ` Oliver Neukum
  2026-07-21 16:23 ` [PATCHv3 net-next 1/9] net: usb: move updating filter and status from cdc drivers to usbnet Jakub Kicinski
  8 siblings, 0 replies; 13+ messages in thread
From: Oliver Neukum @ 2026-07-14 11:44 UTC (permalink / raw)
  To: andrew+netdev, davem, edumazet, kuba, pabeni, manuelebner, netdev,
	linux-kernel
  Cc: Oliver Neukum

Correct grammar in comments.

Signed-off-by: Oliver Neukum <oneukum@suse.com>
---

v3:
- added to fix concerns about language in comments

 drivers/net/usb/usbnet.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 0347f6887222..76bbbfb7a24e 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -2351,12 +2351,12 @@ void usbnet_cdc_status(struct usbnet *dev, struct urb *urb)
 }
 EXPORT_SYMBOL_GPL(usbnet_cdc_status);
 
-/* Make sure packets have correct destination MAC address
+/* Make sure packets have the correct destination MAC address
  *
  * A firmware bug observed on some devices (ZTE MF823/831/910) is that the
- * device sends packets with a static, bogus, random MAC address (event if
- * device MAC address has been updated). Always set MAC address to that of the
- * device.
+ * device sends packets with a static, bogus, random MAC address (event if the
+ * device MAC address has been updated). Always set the MAC address to that
+ * of the device.
  */
 int usbnet_cdc_zte_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCHv3 net-next 3/9] net: usb: usbnet: add cdc_state to struct usbnet
  2026-07-14 11:44 ` [PATCHv3 net-next 3/9] net: usb: usbnet: add cdc_state to struct usbnet Oliver Neukum
@ 2026-07-15  1:18   ` Andrew Lunn
  2026-07-21 16:22     ` Jakub Kicinski
  0 siblings, 1 reply; 13+ messages in thread
From: Andrew Lunn @ 2026-07-15  1:18 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: andrew+netdev, davem, edumazet, kuba, pabeni, manuelebner, netdev,
	linux-kernel

On Tue, Jul 14, 2026 at 01:44:23PM +0200, Oliver Neukum wrote:
> This allows centralisation of code using cdc_state in usbnet, reducing
> code duplication. No functional change intended.
> 
> Signed-off-by: Oliver Neukum <oneukum@suse.com>

I gave a Reviewed-by to v2 of this patch. You are supposed to attach
them here on the next version. b4 collect them and add them for you,
if you use it.

   Andrew

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCHv3 net-next 3/9] net: usb: usbnet: add cdc_state to struct usbnet
  2026-07-15  1:18   ` Andrew Lunn
@ 2026-07-21 16:22     ` Jakub Kicinski
  0 siblings, 0 replies; 13+ messages in thread
From: Jakub Kicinski @ 2026-07-21 16:22 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: Andrew Lunn, andrew+netdev, davem, edumazet, pabeni, manuelebner,
	netdev, linux-kernel

On Wed, 15 Jul 2026 03:18:00 +0200 Andrew Lunn wrote:
> On Tue, Jul 14, 2026 at 01:44:23PM +0200, Oliver Neukum wrote:
> > This allows centralisation of code using cdc_state in usbnet, reducing
> > code duplication. No functional change intended.
> > 
> > Signed-off-by: Oliver Neukum <oneukum@suse.com>  
> 
> I gave a Reviewed-by to v2 of this patch. You are supposed to attach
> them here on the next version. b4 collect them and add them for you,
> if you use it.

Yes, please repost this with the missing tags and add a cover letter.
The basics :/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCHv3 net-next 1/9] net: usb: move updating filter and status from cdc drivers to usbnet
  2026-07-14 11:44 [PATCHv3 net-next 1/9] net: usb: move updating filter and status from cdc drivers to usbnet Oliver Neukum
                   ` (7 preceding siblings ...)
  2026-07-14 11:44 ` [PATCHv3 net-next 9/9] net: usb: usbnet: corrections in the comments Oliver Neukum
@ 2026-07-21 16:23 ` Jakub Kicinski
  8 siblings, 0 replies; 13+ messages in thread
From: Jakub Kicinski @ 2026-07-21 16:23 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: andrew+netdev, davem, edumazet, pabeni, manuelebner, netdev,
	linux-kernel

On Tue, 14 Jul 2026 13:44:21 +0200 Oliver Neukum wrote:
> These helpers are used by multiple drivers and do not depend
> on the rest. For example rndis_host will also need cdc_ether.
> Leaving them in a cdc driver means that additional drivers are loaded
> just as a library, not to support hardware by themselves.

checkpatch

ERROR: trailing whitespace
#169: FILE: drivers/net/usb/usbnet.c:2316:
+^I^I/* we cannot assume the device is in sync with us*/ $

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCHv3 net-next 6/9] net: usb: move exported symbols from cdc_ether to usbnet
  2026-07-14 11:44 ` [PATCHv3 net-next 6/9] net: usb: move exported symbols from cdc_ether to usbnet Oliver Neukum
@ 2026-07-21 16:24   ` Jakub Kicinski
  0 siblings, 0 replies; 13+ messages in thread
From: Jakub Kicinski @ 2026-07-21 16:24 UTC (permalink / raw)
  To: Oliver Neukum
  Cc: andrew+netdev, davem, edumazet, pabeni, manuelebner, netdev,
	linux-kernel

On Tue, 14 Jul 2026 13:44:26 +0200 Oliver Neukum wrote:
> --- a/include/linux/usb/usbnet.h
> +++ b/include/linux/usb/usbnet.h
> @@ -16,6 +16,11 @@
>  #include <linux/usb.h>
>  #include <linux/spinlock.h>
>  
> +static const u8 mbm_guid[16] = {
> +	0xa3, 0x17, 0xa8, 0x8b, 0x04, 0x5e, 0x4f, 0x01,
> +	0xa6, 0x07, 0xc0, 0xff, 0xcb, 0x7e, 0x39, 0x2a,
> +};
> +
>  struct cdc_state {
>  	struct usb_cdc_header_desc      *header;
>  	struct usb_cdc_union_desc       *u;
> @@ -304,4 +309,16 @@ extern void usbnet_status_stop(struct usbnet *dev);
>  
>  extern void usbnet_update_max_qlen(struct usbnet *dev);
>  
> +/* We need to override usbnet_*_link_ksettings in bind() */
> +static const struct ethtool_ops cdc_ether_ethtool_ops = {
> +	.get_link		= usbnet_get_link,
> +	.nway_reset		= usbnet_nway_reset,
> +	.get_drvinfo		= usbnet_get_drvinfo,
> +	.get_msglevel		= usbnet_get_msglevel,
> +	.set_msglevel		= usbnet_set_msglevel,
> +	.get_ts_info		= ethtool_op_get_ts_info,
> +	.get_link_ksettings	= usbnet_get_link_ksettings_internal,
> +	.set_link_ksettings	= NULL,
> +};

spews a ton of defined but not used warnings

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2026-07-21 16:24 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-14 11:44 [PATCHv3 net-next 1/9] net: usb: move updating filter and status from cdc drivers to usbnet Oliver Neukum
2026-07-14 11:44 ` [PATCHv3 net-next 2/9] net: usb: centralize usbnet_cdc_zte_rx_fixup in usbnet Oliver Neukum
2026-07-14 11:44 ` [PATCHv3 net-next 3/9] net: usb: usbnet: add cdc_state to struct usbnet Oliver Neukum
2026-07-15  1:18   ` Andrew Lunn
2026-07-21 16:22     ` Jakub Kicinski
2026-07-14 11:44 ` [PATCHv3 net-next 4/9] net: usb: use cdc_state in " Oliver Neukum
2026-07-14 11:44 ` [PATCHv3 net-next 5/9] net: usb: int51x1: drop dependency on cdc_ether Oliver Neukum
2026-07-14 11:44 ` [PATCHv3 net-next 6/9] net: usb: move exported symbols from cdc_ether to usbnet Oliver Neukum
2026-07-21 16:24   ` Jakub Kicinski
2026-07-14 11:44 ` [PATCHv3 net-next 7/9] net: usb: remove dependencies on cdc_ether Oliver Neukum
2026-07-14 11:44 ` [PATCHv3 net-next 8/9] net: usb: usbnet: remove outdated sanity check Oliver Neukum
2026-07-14 11:44 ` [PATCHv3 net-next 9/9] net: usb: usbnet: corrections in the comments Oliver Neukum
2026-07-21 16:23 ` [PATCHv3 net-next 1/9] net: usb: move updating filter and status from cdc drivers to usbnet Jakub Kicinski

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.