mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-07-24 11:16:51 +00:00
3.9.6 rl8169 checksum fix
This commit is contained in:
parent
d1cac35879
commit
fbcc2e462d
110
packages/linux/patches/3.9.6/linux-701-fix-r8169.patch
vendored
Normal file
110
packages/linux/patches/3.9.6/linux-701-fix-r8169.patch
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
From b423e9ae49d78ea3f53b131c8d5a6087aed16fd6 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?fran=C3=A7ois=20romieu?= <romieu@fr.zoreil.com>
|
||||
Date: Sat, 18 May 2013 01:24:46 +0000
|
||||
Subject: [PATCH] r8169: fix offloaded tx checksum for small packets.
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
8168evl offloaded checksums are wrong since commit
|
||||
e5195c1f31f399289347e043d6abf3ffa80f0005 ("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: Francois Romieu <romieu@fr.zoreil.com>
|
||||
Tested-by: Holger Hoffstätte <holger.hoffstaette@googlemail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/realtek/r8169.c | 41 ++++++++++++++++++++++++------------
|
||||
1 file changed, 27 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
|
||||
index 79c520b..393f961 100644
|
||||
--- a/drivers/net/ethernet/realtek/r8169.c
|
||||
+++ b/drivers/net/ethernet/realtek/r8169.c
|
||||
@@ -5856,7 +5856,20 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
|
||||
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)
|
||||
{
|
||||
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,
|
||||
} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
|
||||
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)
|
||||
opts[offset] |= info->checksum.tcp;
|
||||
else if (ip->protocol == IPPROTO_UDP)
|
||||
opts[offset] |= info->checksum.udp;
|
||||
else
|
||||
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,
|
||||
@@ -5896,17 +5916,15 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
|
||||
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))
|
||||
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);
|
||||
mapping = dma_map_single(d, skb->data, len, DMA_TO_DEVICE);
|
||||
if (unlikely(dma_mapping_error(d, mapping))) {
|
||||
@@ -5918,11 +5936,6 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
|
||||
tp->tx_skb[entry].len = len;
|
||||
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);
|
||||
if (frags < 0)
|
||||
goto err_dma_1;
|
||||
--
|
||||
1.8.1.6
|
Loading…
x
Reference in New Issue
Block a user