提交 b423e9ae 编写于 作者: F françois romieu 提交者: David S. Miller

r8169: fix offloaded tx checksum for small packets.

8168evl offloaded checksums are wrong since commit
e5195c1f ("r8169: fix 8168evl frame padding.")
pads small packets to 60 bytes (without ethernet checksum). Typical symptoms
appear as UDP checksums which are wrong by the count of added bytes.

It isn't worth compensating. Let the driver checksum.

Due to the skb length changes, TSO code is moved before the Tx descriptor gets
written.
Signed-off-by: NFrancois Romieu <romieu@fr.zoreil.com>
Tested-by: NHolger Hoffstätte <holger.hoffstaette@googlemail.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 318debd8
...@@ -5856,7 +5856,20 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, ...@@ -5856,7 +5856,20 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
return -EIO; return -EIO;
} }
static inline void rtl8169_tso_csum(struct rtl8169_private *tp, static bool rtl_skb_pad(struct sk_buff *skb)
{
if (skb_padto(skb, ETH_ZLEN))
return false;
skb_put(skb, ETH_ZLEN - skb->len);
return true;
}
static bool rtl_test_hw_pad_bug(struct rtl8169_private *tp, struct sk_buff *skb)
{
return skb->len < ETH_ZLEN && tp->mac_version == RTL_GIGA_MAC_VER_34;
}
static inline bool rtl8169_tso_csum(struct rtl8169_private *tp,
struct sk_buff *skb, u32 *opts) struct sk_buff *skb, u32 *opts)
{ {
const struct rtl_tx_desc_info *info = tx_desc_info + tp->txd_version; const struct rtl_tx_desc_info *info = tx_desc_info + tp->txd_version;
...@@ -5869,13 +5882,20 @@ static inline void rtl8169_tso_csum(struct rtl8169_private *tp, ...@@ -5869,13 +5882,20 @@ static inline void rtl8169_tso_csum(struct rtl8169_private *tp,
} else if (skb->ip_summed == CHECKSUM_PARTIAL) { } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
const struct iphdr *ip = ip_hdr(skb); const struct iphdr *ip = ip_hdr(skb);
if (unlikely(rtl_test_hw_pad_bug(tp, skb)))
return skb_checksum_help(skb) == 0 && rtl_skb_pad(skb);
if (ip->protocol == IPPROTO_TCP) if (ip->protocol == IPPROTO_TCP)
opts[offset] |= info->checksum.tcp; opts[offset] |= info->checksum.tcp;
else if (ip->protocol == IPPROTO_UDP) else if (ip->protocol == IPPROTO_UDP)
opts[offset] |= info->checksum.udp; opts[offset] |= info->checksum.udp;
else else
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
} else {
if (unlikely(rtl_test_hw_pad_bug(tp, skb)))
return rtl_skb_pad(skb);
} }
return true;
} }
static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
...@@ -5896,17 +5916,15 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, ...@@ -5896,17 +5916,15 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
goto err_stop_0; goto err_stop_0;
} }
/* 8168evl does not automatically pad to minimum length. */
if (unlikely(tp->mac_version == RTL_GIGA_MAC_VER_34 &&
skb->len < ETH_ZLEN)) {
if (skb_padto(skb, ETH_ZLEN))
goto err_update_stats;
skb_put(skb, ETH_ZLEN - skb->len);
}
if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) if (unlikely(le32_to_cpu(txd->opts1) & DescOwn))
goto err_stop_0; goto err_stop_0;
opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(skb));
opts[0] = DescOwn;
if (!rtl8169_tso_csum(tp, skb, opts))
goto err_update_stats;
len = skb_headlen(skb); len = skb_headlen(skb);
mapping = dma_map_single(d, skb->data, len, DMA_TO_DEVICE); mapping = dma_map_single(d, skb->data, len, DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(d, mapping))) { if (unlikely(dma_mapping_error(d, mapping))) {
...@@ -5918,11 +5936,6 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, ...@@ -5918,11 +5936,6 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
tp->tx_skb[entry].len = len; tp->tx_skb[entry].len = len;
txd->addr = cpu_to_le64(mapping); txd->addr = cpu_to_le64(mapping);
opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(skb));
opts[0] = DescOwn;
rtl8169_tso_csum(tp, skb, opts);
frags = rtl8169_xmit_frags(tp, skb, opts); frags = rtl8169_xmit_frags(tp, skb, opts);
if (frags < 0) if (frags < 0)
goto err_dma_1; goto err_dma_1;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册