diff options
Diffstat (limited to 'drivers/net/usb')
-rw-r--r-- | drivers/net/usb/dm9601.c | 27 |
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) | |||
473 | static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb, | 473 | static 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; |