summaryrefslogtreecommitdiff
path: root/drivers/net/usb/smsc95xx.c
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2010-04-20 16:02:01 +0200
committerPatrick McHardy <kaber@trash.net>2010-04-20 16:02:01 +0200
commit62910554656cdcd6b6f84a5154c4155aae4ca231 (patch)
treedcf14004f6fd2ef7154362ff948bfeba0f3ea92d /drivers/net/usb/smsc95xx.c
parent22265a5c3c103cf8c50be62e6c90d045eb649e6d (diff)
parentab9304717f7624c41927f442e6b6d418b2d8b3e4 (diff)
Merge branch 'master' of /repos/git/net-next-2.6
Conflicts: Documentation/feature-removal-schedule.txt net/ipv6/netfilter/ip6t_REJECT.c net/netfilter/xt_limit.c Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'drivers/net/usb/smsc95xx.c')
-rw-r--r--drivers/net/usb/smsc95xx.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index d222d7e25273..12a3c88c5282 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -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"
@@ -384,13 +385,13 @@ static void smsc95xx_set_multicast(struct net_device *netdev)
pdata->mac_cr |= MAC_CR_MCPAS_;
pdata->mac_cr &= ~(MAC_CR_PRMS_ | MAC_CR_HPFILT_);
} else if (!netdev_mc_empty(dev->net)) {
- struct dev_mc_list *mc_list;
+ struct netdev_hw_addr *ha;
pdata->mac_cr |= MAC_CR_HPFILT_;
pdata->mac_cr &= ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_);
- netdev_for_each_mc_addr(mc_list, netdev) {
- u32 bitnum = smsc95xx_hash(mc_list->dmi_addr);
+ netdev_for_each_mc_addr(ha, netdev) {
+ u32 bitnum = smsc95xx_hash(ha->addr);
u32 mask = 0x01 << (bitnum & 0x1F);
if (bitnum & 0x20)
hash_hi |= mask;
@@ -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);