aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/usb/smsc95xx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/usb/smsc95xx.c')
-rw-r--r--drivers/net/usb/smsc95xx.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index d222d7e25273..3135af63d378 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -28,6 +28,7 @@
28#include <linux/usb.h> 28#include <linux/usb.h>
29#include <linux/crc32.h> 29#include <linux/crc32.h>
30#include <linux/usb/usbnet.h> 30#include <linux/usb/usbnet.h>
31#include <linux/slab.h>
31#include "smsc95xx.h" 32#include "smsc95xx.h"
32 33
33#define SMSC_CHIPNAME "smsc95xx" 34#define SMSC_CHIPNAME "smsc95xx"
@@ -1189,9 +1190,21 @@ static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev,
1189 } 1190 }
1190 1191
1191 if (csum) { 1192 if (csum) {
1192 u32 csum_preamble = smsc95xx_calc_csum_preamble(skb); 1193 if (skb->len <= 45) {
1193 skb_push(skb, 4); 1194 /* workaround - hardware tx checksum does not work
1194 memcpy(skb->data, &csum_preamble, 4); 1195 * properly with extremely small packets */
1196 long csstart = skb->csum_start - skb_headroom(skb);
1197 __wsum calc = csum_partial(skb->data + csstart,
1198 skb->len - csstart, 0);
1199 *((__sum16 *)(skb->data + csstart
1200 + skb->csum_offset)) = csum_fold(calc);
1201
1202 csum = false;
1203 } else {
1204 u32 csum_preamble = smsc95xx_calc_csum_preamble(skb);
1205 skb_push(skb, 4);
1206 memcpy(skb->data, &csum_preamble, 4);
1207 }
1195 } 1208 }
1196 1209
1197 skb_push(skb, 4); 1210 skb_push(skb, 4);