diff options
Diffstat (limited to 'drivers/net/usb/dm9601.c')
| -rw-r--r-- | drivers/net/usb/dm9601.c | 57 | 
1 files changed, 44 insertions, 13 deletions
diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index c6867f926cf..6e9c344c7a2 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -1,5 +1,5 @@  /* - * Davicom DM9601 USB 1.1 10/100Mbps ethernet devices + * Davicom DM96xx USB 10/100Mbps ethernet devices   *   * Peter Korsgaard <jacmet@sunsite.dk>   * @@ -13,7 +13,6 @@  #include <linux/module.h>  #include <linux/sched.h>  #include <linux/stddef.h> -#include <linux/init.h>  #include <linux/netdevice.h>  #include <linux/etherdevice.h>  #include <linux/ethtool.h> @@ -364,7 +363,12 @@ static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf)  	dev->net->ethtool_ops = &dm9601_ethtool_ops;  	dev->net->hard_header_len += DM_TX_OVERHEAD;  	dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; -	dev->rx_urb_size = dev->net->mtu + ETH_HLEN + DM_RX_OVERHEAD; + +	/* dm9620/21a require room for 4 byte padding, even in dm9601 +	 * mode, so we need +1 to be able to receive full size +	 * ethernet frames. +	 */ +	dev->rx_urb_size = dev->net->mtu + ETH_HLEN + DM_RX_OVERHEAD + 1;  	dev->mii.dev = dev->net;  	dev->mii.mdio_read = dm9601_mdio_read; @@ -468,7 +472,7 @@ static int dm9601_rx_fixup(struct usbnet *dev, struct sk_buff *skb)  static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,  				       gfp_t flags)  { -	int len; +	int len, pad;  	/* format:  	   b1: packet length low @@ -476,12 +480,23 @@ static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,  	   b3..n: packet data  	*/ -	len = skb->len; +	len = skb->len + DM_TX_OVERHEAD; -	if (skb_headroom(skb) < DM_TX_OVERHEAD) { +	/* workaround for dm962x errata with tx fifo getting out of +	 * sync if a USB bulk transfer retry happens right after a +	 * packet with odd / maxpacket length by adding up to 3 bytes +	 * padding. +	 */ +	while ((len & 1) || !(len % dev->maxpacket)) +		len++; + +	len -= DM_TX_OVERHEAD; /* hw header doesn't count as part of length */ +	pad = len - skb->len; + +	if (skb_headroom(skb) < DM_TX_OVERHEAD || skb_tailroom(skb) < pad) {  		struct sk_buff *skb2; -		skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, 0, flags); +		skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, pad, flags);  		dev_kfree_skb_any(skb);  		skb = skb2;  		if (!skb) @@ -490,10 +505,10 @@ static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,  	__skb_push(skb, DM_TX_OVERHEAD); -	/* usbnet adds padding if length is a multiple of packet size -	   if so, adjust length value in header */ -	if ((skb->len % dev->maxpacket) == 0) -		len++; +	if (pad) { +		memset(skb->data + skb->len, 0, pad); +		__skb_put(skb, pad); +	}  	skb->data[0] = len;  	skb->data[1] = len >> 8; @@ -543,7 +558,7 @@ static int dm9601_link_reset(struct usbnet *dev)  }  static const struct driver_info dm9601_info = { -	.description	= "Davicom DM9601 USB Ethernet", +	.description	= "Davicom DM96xx USB 10/100 Ethernet",  	.flags		= FLAG_ETHER | FLAG_LINK_INTR,  	.bind		= dm9601_bind,  	.rx_fixup	= dm9601_rx_fixup, @@ -594,6 +609,22 @@ static const struct usb_device_id products[] = {  	 USB_DEVICE(0x0a46, 0x9620),	/* DM9620 USB to Fast Ethernet Adapter */  	 .driver_info = (unsigned long)&dm9601_info,  	 }, +	{ +	 USB_DEVICE(0x0a46, 0x9621),	/* DM9621A USB to Fast Ethernet Adapter */ +	 .driver_info = (unsigned long)&dm9601_info, +	}, +	{ +	 USB_DEVICE(0x0a46, 0x9622),	/* DM9622 USB to Fast Ethernet Adapter */ +	 .driver_info = (unsigned long)&dm9601_info, +	}, +	{ +	 USB_DEVICE(0x0a46, 0x0269),	/* DM962OA USB to Fast Ethernet Adapter */ +	 .driver_info = (unsigned long)&dm9601_info, +	}, +	{ +	 USB_DEVICE(0x0a46, 0x1269),	/* DM9621A USB to Fast Ethernet Adapter */ +	 .driver_info = (unsigned long)&dm9601_info, +	},  	{},			// END  }; @@ -612,5 +643,5 @@ static struct usb_driver dm9601_driver = {  module_usb_driver(dm9601_driver);  MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>"); -MODULE_DESCRIPTION("Davicom DM9601 USB 1.1 ethernet devices"); +MODULE_DESCRIPTION("Davicom DM96xx USB 10/100 ethernet devices");  MODULE_LICENSE("GPL");  | 
