Commit e119a369 authored by David S. Miller's avatar David S. Miller

Merge branch 'SMSC95xx-driver-updates'

Ben Dooks says:

====================
SMSC95xx driver updates (round 1)

This is a series of a few driver cleanups and some fixups of the code
for the SMSC95XX driver. There have been a few reviews, and the issues
have been fixed so this should be ready for merging.

I will work on the tx-alignment and the other bits of usbnet changes
and produce at least two more patch series for this later.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 9cd821b7 75938f77
...@@ -618,9 +618,7 @@ static void smsc95xx_status(struct usbnet *dev, struct urb *urb) ...@@ -618,9 +618,7 @@ static void smsc95xx_status(struct usbnet *dev, struct urb *urb)
return; return;
} }
memcpy(&intdata, urb->transfer_buffer, 4); intdata = get_unaligned_le32(urb->transfer_buffer);
le32_to_cpus(&intdata);
netif_dbg(dev, link, dev->net, "intdata: 0x%08X\n", intdata); netif_dbg(dev, link, dev->net, "intdata: 0x%08X\n", intdata);
if (intdata & INT_ENP_PHY_INT_) if (intdata & INT_ENP_PHY_INT_)
...@@ -1295,6 +1293,7 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) ...@@ -1295,6 +1293,7 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
dev->net->features |= NETIF_F_RXCSUM; dev->net->features |= NETIF_F_RXCSUM;
dev->net->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM; dev->net->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
set_bit(EVENT_NO_IP_ALIGN, &dev->flags);
smsc95xx_init_mac_address(dev); smsc95xx_init_mac_address(dev);
...@@ -1933,8 +1932,7 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) ...@@ -1933,8 +1932,7 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
unsigned char *packet; unsigned char *packet;
u16 size; u16 size;
memcpy(&header, skb->data, sizeof(header)); header = get_unaligned_le32(skb->data);
le32_to_cpus(&header);
skb_pull(skb, 4 + NET_IP_ALIGN); skb_pull(skb, 4 + NET_IP_ALIGN);
packet = skb->data; packet = skb->data;
...@@ -2011,12 +2009,30 @@ static u32 smsc95xx_calc_csum_preamble(struct sk_buff *skb) ...@@ -2011,12 +2009,30 @@ static u32 smsc95xx_calc_csum_preamble(struct sk_buff *skb)
return (high_16 << 16) | low_16; return (high_16 << 16) | low_16;
} }
/* The TX CSUM won't work if the checksum lies in the last 4 bytes of the
* transmission. This is fairly unlikely, only seems to trigger with some
* short TCP ACK packets sent.
*
* Note, this calculation should probably check for the alignment of the
* data as well, but a straight check for csum being in the last four bytes
* of the packet should be ok for now.
*/
static bool smsc95xx_can_tx_checksum(struct sk_buff *skb)
{
unsigned int len = skb->len - skb_checksum_start_offset(skb);
if (skb->len <= 45)
return false;
return skb->csum_offset < (len - (4 + 1));
}
static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev, static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev,
struct sk_buff *skb, gfp_t flags) struct sk_buff *skb, gfp_t flags)
{ {
bool csum = skb->ip_summed == CHECKSUM_PARTIAL; bool csum = skb->ip_summed == CHECKSUM_PARTIAL;
int overhead = csum ? SMSC95XX_TX_OVERHEAD_CSUM : SMSC95XX_TX_OVERHEAD; int overhead = csum ? SMSC95XX_TX_OVERHEAD_CSUM : SMSC95XX_TX_OVERHEAD;
u32 tx_cmd_a, tx_cmd_b; u32 tx_cmd_a, tx_cmd_b;
void *ptr;
/* We do not advertise SG, so skbs should be already linearized */ /* We do not advertise SG, so skbs should be already linearized */
BUG_ON(skb_shinfo(skb)->nr_frags); BUG_ON(skb_shinfo(skb)->nr_frags);
...@@ -2030,8 +2046,11 @@ static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev, ...@@ -2030,8 +2046,11 @@ static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev,
return NULL; return NULL;
} }
tx_cmd_b = (u32)skb->len;
tx_cmd_a = tx_cmd_b | TX_CMD_A_FIRST_SEG_ | TX_CMD_A_LAST_SEG_;
if (csum) { if (csum) {
if (skb->len <= 45) { if (!smsc95xx_can_tx_checksum(skb)) {
/* workaround - hardware tx checksum does not work /* workaround - hardware tx checksum does not work
* properly with extremely small packets */ * properly with extremely small packets */
long csstart = skb_checksum_start_offset(skb); long csstart = skb_checksum_start_offset(skb);
...@@ -2043,24 +2062,18 @@ static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev, ...@@ -2043,24 +2062,18 @@ static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev,
csum = false; csum = false;
} else { } else {
u32 csum_preamble = smsc95xx_calc_csum_preamble(skb); u32 csum_preamble = smsc95xx_calc_csum_preamble(skb);
skb_push(skb, 4); ptr = skb_push(skb, 4);
cpu_to_le32s(&csum_preamble); put_unaligned_le32(csum_preamble, ptr);
memcpy(skb->data, &csum_preamble, 4);
tx_cmd_a += 4;
tx_cmd_b += 4;
tx_cmd_b |= TX_CMD_B_CSUM_ENABLE;
} }
} }
skb_push(skb, 4); ptr = skb_push(skb, 8);
tx_cmd_b = (u32)(skb->len - 4); put_unaligned_le32(tx_cmd_a, ptr);
if (csum) put_unaligned_le32(tx_cmd_b, ptr+4);
tx_cmd_b |= TX_CMD_B_CSUM_ENABLE;
cpu_to_le32s(&tx_cmd_b);
memcpy(skb->data, &tx_cmd_b, 4);
skb_push(skb, 4);
tx_cmd_a = (u32)(skb->len - 8) | TX_CMD_A_FIRST_SEG_ |
TX_CMD_A_LAST_SEG_;
cpu_to_le32s(&tx_cmd_a);
memcpy(skb->data, &tx_cmd_a, 4);
return skb; return skb;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment