aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/usb')
-rw-r--r--drivers/net/usb/dm9601.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c
index 732a926e3f51..c0bfc818c701 100644
--- a/drivers/net/usb/dm9601.c
+++ b/drivers/net/usb/dm9601.c
@@ -473,7 +473,7 @@ static int dm9601_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
473static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb, 473static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
474 gfp_t flags) 474 gfp_t flags)
475{ 475{
476 int len; 476 int len, pad;
477 477
478 /* format: 478 /* format:
479 b1: packet length low 479 b1: packet length low
@@ -481,12 +481,23 @@ static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
481 b3..n: packet data 481 b3..n: packet data
482 */ 482 */
483 483
484 len = skb->len; 484 len = skb->len + DM_TX_OVERHEAD;
485
486 /* workaround for dm962x errata with tx fifo getting out of
487 * sync if a USB bulk transfer retry happens right after a
488 * packet with odd / maxpacket length by adding up to 3 bytes
489 * padding.
490 */
491 while ((len & 1) || !(len % dev->maxpacket))
492 len++;
485 493
486 if (skb_headroom(skb) < DM_TX_OVERHEAD) { 494 len -= DM_TX_OVERHEAD; /* hw header doesn't count as part of length */
495 pad = len - skb->len;
496
497 if (skb_headroom(skb) < DM_TX_OVERHEAD || skb_tailroom(skb) < pad) {
487 struct sk_buff *skb2; 498 struct sk_buff *skb2;
488 499
489 skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, 0, flags); 500 skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, pad, flags);
490 dev_kfree_skb_any(skb); 501 dev_kfree_skb_any(skb);
491 skb = skb2; 502 skb = skb2;
492 if (!skb) 503 if (!skb)
@@ -495,10 +506,10 @@ static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
495 506
496 __skb_push(skb, DM_TX_OVERHEAD); 507 __skb_push(skb, DM_TX_OVERHEAD);
497 508
498 /* usbnet adds padding if length is a multiple of packet size 509 if (pad) {
499 if so, adjust length value in header */ 510 memset(skb->data + skb->len, 0, pad);
500 if ((skb->len % dev->maxpacket) == 0) 511 __skb_put(skb, pad);
501 len++; 512 }
502 513
503 skb->data[0] = len; 514 skb->data[0] = len;
504 skb->data[1] = len >> 8; 515 skb->data[1] = len >> 8;