]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/net/usb/smsc95xx.c
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[net-next-2.6.git] / drivers / net / usb / smsc95xx.c
index d222d7e2527392a79990de49f909e0330483c871..3135af63d3785f8ba38cfe3b516841bfdc2a1c92 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/usb.h>
 #include <linux/crc32.h>
 #include <linux/usb/usbnet.h>
+#include <linux/slab.h>
 #include "smsc95xx.h"
 
 #define SMSC_CHIPNAME                  "smsc95xx"
@@ -1189,9 +1190,21 @@ static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev,
        }
 
        if (csum) {
-               u32 csum_preamble = smsc95xx_calc_csum_preamble(skb);
-               skb_push(skb, 4);
-               memcpy(skb->data, &csum_preamble, 4);
+               if (skb->len <= 45) {
+                       /* workaround - hardware tx checksum does not work
+                        * properly with extremely small packets */
+                       long csstart = skb->csum_start - skb_headroom(skb);
+                       __wsum calc = csum_partial(skb->data + csstart,
+                               skb->len - csstart, 0);
+                       *((__sum16 *)(skb->data + csstart
+                               + skb->csum_offset)) = csum_fold(calc);
+
+                       csum = false;
+               } else {
+                       u32 csum_preamble = smsc95xx_calc_csum_preamble(skb);
+                       skb_push(skb, 4);
+                       memcpy(skb->data, &csum_preamble, 4);
+               }
        }
 
        skb_push(skb, 4);