Commit 0a5aeee0 authored by David Woodhouse's avatar David Woodhouse Committed by David S. Miller

8139cp: Reduce duplicate csum/tso code in cp_start_xmit()

We calculate the value of the opts1 descriptor field in three different
places. With two different behaviours when given an invalid packet to
be checksummed — none of them correct. Sort that out.
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a3b80404
...@@ -733,7 +733,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, ...@@ -733,7 +733,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
{ {
struct cp_private *cp = netdev_priv(dev); struct cp_private *cp = netdev_priv(dev);
unsigned entry; unsigned entry;
u32 eor, flags; u32 eor, opts1;
unsigned long intr_flags; unsigned long intr_flags;
__le32 opts2; __le32 opts2;
int mss = 0; int mss = 0;
...@@ -753,6 +753,21 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, ...@@ -753,6 +753,21 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
mss = skb_shinfo(skb)->gso_size; mss = skb_shinfo(skb)->gso_size;
opts2 = cpu_to_le32(cp_tx_vlan_tag(skb)); opts2 = cpu_to_le32(cp_tx_vlan_tag(skb));
opts1 = DescOwn;
if (mss)
opts1 |= LargeSend | ((mss & MSSMask) << MSSShift);
else if (skb->ip_summed == CHECKSUM_PARTIAL) {
const struct iphdr *ip = ip_hdr(skb);
if (ip->protocol == IPPROTO_TCP)
opts1 |= IPCS | TCPCS;
else if (ip->protocol == IPPROTO_UDP)
opts1 |= IPCS | UDPCS;
else {
WARN_ONCE(1,
"Net bug: asked to checksum invalid Legacy IP packet\n");
goto out_dma_error;
}
}
if (skb_shinfo(skb)->nr_frags == 0) { if (skb_shinfo(skb)->nr_frags == 0) {
struct cp_desc *txd = &cp->tx_ring[entry]; struct cp_desc *txd = &cp->tx_ring[entry];
...@@ -768,21 +783,9 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, ...@@ -768,21 +783,9 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
txd->addr = cpu_to_le64(mapping); txd->addr = cpu_to_le64(mapping);
wmb(); wmb();
flags = eor | len | DescOwn | FirstFrag | LastFrag; opts1 |= eor | len | FirstFrag | LastFrag;
if (mss) txd->opts1 = cpu_to_le32(opts1);
flags |= LargeSend | ((mss & MSSMask) << MSSShift);
else if (skb->ip_summed == CHECKSUM_PARTIAL) {
const struct iphdr *ip = ip_hdr(skb);
if (ip->protocol == IPPROTO_TCP)
flags |= IPCS | TCPCS;
else if (ip->protocol == IPPROTO_UDP)
flags |= IPCS | UDPCS;
else
WARN_ON(1); /* we need a WARN() */
}
txd->opts1 = cpu_to_le32(flags);
wmb(); wmb();
cp->tx_skb[entry] = skb; cp->tx_skb[entry] = skb;
...@@ -793,7 +796,6 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, ...@@ -793,7 +796,6 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
u32 first_len, first_eor, ctrl; u32 first_len, first_eor, ctrl;
dma_addr_t first_mapping; dma_addr_t first_mapping;
int frag, first_entry = entry; int frag, first_entry = entry;
const struct iphdr *ip = ip_hdr(skb);
/* We must give this initial chunk to the device last. /* We must give this initial chunk to the device last.
* Otherwise we could race with the device. * Otherwise we could race with the device.
...@@ -825,19 +827,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, ...@@ -825,19 +827,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0; eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
ctrl = eor | len | DescOwn; ctrl = opts1 | eor | len;
if (mss)
ctrl |= LargeSend |
((mss & MSSMask) << MSSShift);
else if (skb->ip_summed == CHECKSUM_PARTIAL) {
if (ip->protocol == IPPROTO_TCP)
ctrl |= IPCS | TCPCS;
else if (ip->protocol == IPPROTO_UDP)
ctrl |= IPCS | UDPCS;
else
BUG();
}
if (frag == skb_shinfo(skb)->nr_frags - 1) if (frag == skb_shinfo(skb)->nr_frags - 1)
ctrl |= LastFrag; ctrl |= LastFrag;
...@@ -857,18 +847,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, ...@@ -857,18 +847,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
txd->addr = cpu_to_le64(first_mapping); txd->addr = cpu_to_le64(first_mapping);
wmb(); wmb();
ctrl = first_eor | first_len | FirstFrag | DescOwn; ctrl = opts1 | first_eor | first_len | FirstFrag;
if (mss)
ctrl |= LargeSend | ((mss & MSSMask) << MSSShift);
else if (skb->ip_summed == CHECKSUM_PARTIAL) {
if (ip->protocol == IPPROTO_TCP)
ctrl |= IPCS | TCPCS;
else if (ip->protocol == IPPROTO_UDP)
ctrl |= IPCS | UDPCS;
else
BUG();
}
txd->opts1 = cpu_to_le32(ctrl); txd->opts1 = cpu_to_le32(ctrl);
wmb(); wmb();
......
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