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

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
Loading
Loading
Loading
Loading
+34 −21
Original line number Diff line number Diff line
@@ -618,9 +618,7 @@ static void smsc95xx_status(struct usbnet *dev, struct urb *urb)
		return;
	}

	memcpy(&intdata, urb->transfer_buffer, 4);
	le32_to_cpus(&intdata);

	intdata = get_unaligned_le32(urb->transfer_buffer);
	netif_dbg(dev, link, dev->net, "intdata: 0x%08X\n", intdata);

	if (intdata & INT_ENP_PHY_INT_)
@@ -1295,6 +1293,7 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
		dev->net->features |= 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);

@@ -1933,8 +1932,7 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
		unsigned char *packet;
		u16 size;

		memcpy(&header, skb->data, sizeof(header));
		le32_to_cpus(&header);
		header = get_unaligned_le32(skb->data);
		skb_pull(skb, 4 + NET_IP_ALIGN);
		packet = skb->data;

@@ -2011,12 +2009,30 @@ static u32 smsc95xx_calc_csum_preamble(struct sk_buff *skb)
	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,
					 struct sk_buff *skb, gfp_t flags)
{
	bool csum = skb->ip_summed == CHECKSUM_PARTIAL;
	int overhead = csum ? SMSC95XX_TX_OVERHEAD_CSUM : SMSC95XX_TX_OVERHEAD;
	u32 tx_cmd_a, tx_cmd_b;
	void *ptr;

	/* We do not advertise SG, so skbs should be already linearized */
	BUG_ON(skb_shinfo(skb)->nr_frags);
@@ -2030,8 +2046,11 @@ static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev,
		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 (skb->len <= 45) {
		if (!smsc95xx_can_tx_checksum(skb)) {
			/* workaround - hardware tx checksum does not work
			 * properly with extremely small packets */
			long csstart = skb_checksum_start_offset(skb);
@@ -2043,24 +2062,18 @@ static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev,
			csum = false;
		} else {
			u32 csum_preamble = smsc95xx_calc_csum_preamble(skb);
			skb_push(skb, 4);
			cpu_to_le32s(&csum_preamble);
			memcpy(skb->data, &csum_preamble, 4);
			ptr = skb_push(skb, 4);
			put_unaligned_le32(csum_preamble, ptr);

			tx_cmd_a += 4;
			tx_cmd_b += 4;
			tx_cmd_b |= TX_CMD_B_CSUM_ENABLE;
		}
	}

	skb_push(skb, 4);
	tx_cmd_b = (u32)(skb->len - 4);
	if (csum)
		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);
	ptr = skb_push(skb, 8);
	put_unaligned_le32(tx_cmd_a, ptr);
	put_unaligned_le32(tx_cmd_b, ptr+4);

	return skb;
}