Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * USB CDC EEM network interface driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Copyright (C) 2009 Oberthur Technologies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * by Omar Laazimani, Olivier Condemine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/ethtool.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/mii.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/usb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/crc32.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/usb/cdc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/usb/usbnet.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/gfp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/if_vlan.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  * This driver is an implementation of the CDC "Ethernet Emulation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  * Model" (EEM) specification, which encapsulates Ethernet frames
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  * for transport over USB using a simpler USB device model than the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  * previous CDC "Ethernet Control Model" (ECM, or "CDC Ethernet").
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  * For details, see www.usb.org/developers/devclass_docs/CDC_EEM10.pdf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  * This version has been tested with GIGAntIC WuaoW SIM Smart Card on 2.6.24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  * 2.6.27 and 2.6.30rc2 kernel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)  * It has also been validated on Openmoko Om 2008.12 (based on 2.6.24 kernel).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34)  * build on 23-April-2009
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #define EEM_HEAD	2		/* 2 byte header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) /*-------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) static void eem_linkcmd_complete(struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	dev_kfree_skb(urb->context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	usb_free_urb(urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) static void eem_linkcmd(struct usbnet *dev, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	struct urb		*urb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	int			status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	urb = usb_alloc_urb(0, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	if (!urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 		goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	usb_fill_bulk_urb(urb, dev->udev, dev->out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 			skb->data, skb->len, eem_linkcmd_complete, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	status = usb_submit_urb(urb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	if (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 		usb_free_urb(urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 		netdev_warn(dev->net, "link cmd failure\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) static int eem_bind(struct usbnet *dev, struct usb_interface *intf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	int status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	status = usbnet_get_endpoints(dev, intf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	/* no jumbogram (16K) support for now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN + VLAN_HLEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)  * EEM permits packing multiple Ethernet frames into USB transfers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87)  * (a "bundle"), but for TX we don't try to do that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) static struct sk_buff *eem_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 				       gfp_t flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	struct sk_buff	*skb2 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	u16		len = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	u32		crc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	int		padlen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	/* When ((len + EEM_HEAD + ETH_FCS_LEN) % dev->maxpacket) is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	 * zero, stick two bytes of zero length EEM packet on the end.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	 * Else the framework would add invalid single byte padding,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	 * since it can't know whether ZLPs will be handled right by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	 * all the relevant hardware and software.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	if (!((len + EEM_HEAD + ETH_FCS_LEN) % dev->maxpacket))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		padlen += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	if (!skb_cloned(skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		int	headroom = skb_headroom(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		int	tailroom = skb_tailroom(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		if ((tailroom >= ETH_FCS_LEN + padlen) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 		    (headroom >= EEM_HEAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 			goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 		if ((headroom + tailroom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 				> (EEM_HEAD + ETH_FCS_LEN + padlen)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 			skb->data = memmove(skb->head +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 					EEM_HEAD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 					skb->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 					skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 			skb_set_tail_pointer(skb, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 			goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	skb2 = skb_copy_expand(skb, EEM_HEAD, ETH_FCS_LEN + padlen, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	dev_kfree_skb_any(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	if (!skb2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	skb = skb2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	/* we don't use the "no Ethernet CRC" option */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	crc = crc32_le(~0, skb->data, skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	crc = ~crc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	put_unaligned_le32(crc, skb_put(skb, 4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	/* EEM packet header format:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	 * b0..13:	length of ethernet frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	 * b14:		bmCRC (1 == valid Ethernet CRC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	 * b15:		bmType (0 == data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	len = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	put_unaligned_le16(BIT(14) | len, skb_push(skb, 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	/* Bundle a zero length EEM packet if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	if (padlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		put_unaligned_le16(0, skb_put(skb, 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	return skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static int eem_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	 * Our task here is to strip off framing, leaving skb with one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	 * data frame for the usbnet framework code to process.  But we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	 * may have received multiple EEM payloads, or command payloads.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	 * So we must process _everything_ as if it's a header, except
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	 * maybe the last data payload
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	 * REVISIT the framework needs updating so that when we consume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	 * all payloads (the last or only message was a command, or a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	 * zero length EEM packet) that is not accounted as an rx_error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		struct sk_buff	*skb2 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		u16		header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		u16		len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 		/* incomplete EEM header? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 		if (skb->len < EEM_HEAD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		 * EEM packet header format:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		 * b0..14:	EEM type dependent (Data or Command)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		 * b15:		bmType
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		header = get_unaligned_le16(skb->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 		skb_pull(skb, EEM_HEAD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		 * The bmType bit helps to denote when EEM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		 * packet is data or command :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		 *	bmType = 0	: EEM data payload
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		 *	bmType = 1	: EEM (link) command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		if (header & BIT(15)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 			u16	bmEEMCmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 			 * EEM (link) command packet:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 			 * b0..10:	bmEEMCmdParam
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 			 * b11..13:	bmEEMCmd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 			 * b14:		bmReserved (must be 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 			 * b15:		1 (EEM command)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 			if (header & BIT(14)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 				netdev_dbg(dev->net, "reserved command %04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 					   header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 			bmEEMCmd = (header >> 11) & 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 			switch (bmEEMCmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 			/* Responding to echo requests is mandatory. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 			case 0:		/* Echo command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 				len = header & 0x7FF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 				/* bogus command? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 				if (skb->len < len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 					return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 				skb2 = skb_clone(skb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 				if (unlikely(!skb2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 					goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 				skb_trim(skb2, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 				put_unaligned_le16(BIT(15) | (1 << 11) | len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 						skb_push(skb2, 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 				eem_linkcmd(dev, skb2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 			 * Host may choose to ignore hints.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 			 *  - suspend: peripheral ready to suspend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 			 *  - response: suggest N millisec polling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 			 *  - response complete: suggest N sec polling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 			 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 			 * Suspend is reported and maybe heeded.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 			case 2:		/* Suspend hint */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 				usbnet_device_suggests_idle(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 			case 3:		/* Response hint */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 			case 4:		/* Response complete hint */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 			 * Hosts should never receive host-to-peripheral
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 			 * or reserved command codes; or responses to an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 			 * echo command we didn't send.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 			case 1:		/* Echo response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 			case 5:		/* Tickle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 			default:	/* reserved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 				netdev_warn(dev->net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 					    "unexpected link command %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 					    bmEEMCmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 			u32	crc, crc2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 			int	is_last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 			/* zero length EEM packet? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 			if (header == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 			 * EEM data packet header :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 			 * b0..13:	length of ethernet frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 			 * b14:		bmCRC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 			 * b15:		0 (EEM data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 			len = header & 0x3FFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 			/* bogus EEM payload? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 			if (skb->len < len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 				return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 			/* bogus ethernet frame? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 			if (len < (ETH_HLEN + ETH_FCS_LEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 				goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 			 * Treat the last payload differently: framework
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 			 * code expects our "fixup" to have stripped off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 			 * headers, so "skb" is a data packet (or error).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 			 * Else if it's not the last payload, keep "skb"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 			 * for further processing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 			is_last = (len == skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 			if (is_last)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 				skb2 = skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 			else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 				skb2 = skb_clone(skb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 				if (unlikely(!skb2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 					return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 			 * The bmCRC helps to denote when the CRC field in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 			 * the Ethernet frame contains a calculated CRC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 			 *	bmCRC = 1	: CRC is calculated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 			 *	bmCRC = 0	: CRC = 0xDEADBEEF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 			if (header & BIT(14)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 				crc = get_unaligned_le32(skb2->data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 						+ len - ETH_FCS_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 				crc2 = ~crc32_le(~0, skb2->data, skb2->len
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 						- ETH_FCS_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 				crc = get_unaligned_be32(skb2->data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 						+ len - ETH_FCS_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 				crc2 = 0xdeadbeef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 			skb_trim(skb2, len - ETH_FCS_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 			if (is_last)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 				return crc == crc2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 			if (unlikely(crc != crc2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 				dev->net->stats.rx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 				dev_kfree_skb_any(skb2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 			} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 				usbnet_skb_return(dev, skb2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		skb_pull(skb, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	} while (skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) static const struct driver_info eem_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	.description =	"CDC EEM Device",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	.flags =	FLAG_ETHER | FLAG_POINTTOPOINT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	.bind =		eem_bind,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	.rx_fixup =	eem_rx_fixup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	.tx_fixup =	eem_tx_fixup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) /*-------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) static const struct usb_device_id products[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_EEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 			USB_CDC_PROTO_EEM),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	.driver_info = (unsigned long) &eem_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	/* EMPTY == end of list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) MODULE_DEVICE_TABLE(usb, products);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) static struct usb_driver eem_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	.name =		"cdc_eem",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	.id_table =	products,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	.probe =	usbnet_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	.disconnect =	usbnet_disconnect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	.suspend =	usbnet_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	.resume =	usbnet_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	.disable_hub_initiated_lpm = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) module_usb_driver(eem_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) MODULE_AUTHOR("Omar Laazimani <omar.oberthur@gmail.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) MODULE_DESCRIPTION("USB CDC EEM");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) MODULE_LICENSE("GPL");