kernel: mediatek: improve ethernet fix for dealing with small fragments

Replace the workaround on MT7986 with a proper fix. Software workaround is
still needed on older chips.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
Felix Fietkau 2022-12-27 19:08:27 +01:00 committed by AmadeusGhost
parent a9f98fa1b9
commit 297b6f78ca
2 changed files with 37 additions and 21 deletions

View File

@ -1,12 +1,15 @@
From: Felix Fietkau <nbd@nbd.name> From: Felix Fietkau <nbd@nbd.name>
Date: Thu, 3 Nov 2022 12:38:49 +0100 Date: Thu, 3 Nov 2022 12:38:49 +0100
Subject: [PATCH] net: ethernet: mtk_eth_soc: work around issue with Subject: [PATCH] net: ethernet: mtk_eth_soc: work around issue with sending
sending small fragments small fragments
When frames are sent with very small fragments, the DMA engine appears to When lots of frames are sent with a number of very small fragments, an
lock up and transmit attempts time out. Fix this by detecting the presence internal FIFO can overflow, causing the DMA engine to lock up lock up and
of small fragments and use skb_gso_segment + skb_linearize to deal with transmit attempts time out.
them
Fix this on MT7986 by increasing the reserved FIFO space.
Fix this on older chips by detecting the presence of small fragments and use
skb_gso_segment + skb_linearize to deal with them.
Signed-off-by: Felix Fietkau <nbd@nbd.name> Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- ---
@ -42,11 +45,12 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
bool gso = false; bool gso = false;
int tx_num; int tx_num;
@@ -1423,6 +1439,17 @@ static netdev_tx_t mtk_start_xmit(struct @@ -1423,6 +1439,18 @@ static netdev_tx_t mtk_start_xmit(struct
return NETDEV_TX_BUSY; return NETDEV_TX_BUSY;
} }
+ if (skb_is_gso(skb) && mtk_skb_has_small_frag(skb)) { + if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) &&
+ skb_is_gso(skb) && mtk_skb_has_small_frag(skb)) {
+ segs = skb_gso_segment(skb, dev->features & ~NETIF_F_ALL_TSO); + segs = skb_gso_segment(skb, dev->features & ~NETIF_F_ALL_TSO);
+ if (IS_ERR(segs)) + if (IS_ERR(segs))
+ goto drop; + goto drop;
@ -60,19 +64,31 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
/* TSO: fill MSS info in tcp checksum field */ /* TSO: fill MSS info in tcp checksum field */
if (skb_is_gso(skb)) { if (skb_is_gso(skb)) {
if (skb_cow_head(skb, 0)) { if (skb_cow_head(skb, 0)) {
@@ -1438,8 +1465,13 @@ static netdev_tx_t mtk_start_xmit(struct @@ -1438,8 +1466,14 @@ static netdev_tx_t mtk_start_xmit(struct
} }
} }
- if (mtk_tx_map(skb, dev, tx_num, ring, gso) < 0) - if (mtk_tx_map(skb, dev, tx_num, ring, gso) < 0)
- goto drop; - goto drop;
+ skb_list_walk_safe(skb, skb, next) { + if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+ if ((mtk_skb_has_small_frag(skb) && skb_linearize(skb)) || + skb_list_walk_safe(skb, skb, next) {
+ mtk_tx_map(skb, dev, tx_num, ring, gso) < 0) { + if ((mtk_skb_has_small_frag(skb) && skb_linearize(skb)) ||
+ stats->tx_dropped++; + mtk_tx_map(skb, dev, tx_num, ring, gso) < 0) {
+ dev_kfree_skb_any(skb); + stats->tx_dropped++;
+ dev_kfree_skb_any(skb);
+ }
+ } + }
+ }
if (unlikely(atomic_read(&ring->free_count) <= ring->thresh)) if (unlikely(atomic_read(&ring->free_count) <= ring->thresh))
netif_tx_stop_all_queues(dev); netif_tx_stop_all_queues(dev);
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -246,7 +246,7 @@
#define MTK_CHK_DDONE_EN BIT(28)
#define MTK_DMAD_WR_WDONE BIT(26)
#define MTK_WCOMP_EN BIT(24)
-#define MTK_RESV_BUF (0x40 << 16)
+#define MTK_RESV_BUF (0x80 << 16)
#define MTK_MUTLI_CNT (0x4 << 12)
#define MTK_LEAKY_BUCKET_EN BIT(11)

View File

@ -17,7 +17,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1993,29 +1993,16 @@ static int mtk_poll_rx(struct napi_struc @@ -1995,29 +1995,16 @@ static int mtk_poll_rx(struct napi_struc
if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED)
mtk_ppe_check_skb(eth->ppe[0], skb, hash); mtk_ppe_check_skb(eth->ppe[0], skb, hash);
@ -50,7 +50,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
} }
skb_record_rx_queue(skb, 0); skb_record_rx_queue(skb, 0);
@@ -2832,29 +2819,11 @@ static netdev_features_t mtk_fix_feature @@ -2834,29 +2821,11 @@ static netdev_features_t mtk_fix_feature
static int mtk_set_features(struct net_device *dev, netdev_features_t features) static int mtk_set_features(struct net_device *dev, netdev_features_t features)
{ {
@ -80,7 +80,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
return 0; return 0;
} }
@@ -3153,30 +3122,6 @@ static int mtk_open(struct net_device *d @@ -3155,30 +3124,6 @@ static int mtk_open(struct net_device *d
struct mtk_eth *eth = mac->hw; struct mtk_eth *eth = mac->hw;
int i, err; int i, err;
@ -111,7 +111,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0); err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0);
if (err) { if (err) {
netdev_err(dev, "%s: could not attach PHY: %d\n", __func__, netdev_err(dev, "%s: could not attach PHY: %d\n", __func__,
@@ -3217,6 +3162,35 @@ static int mtk_open(struct net_device *d @@ -3219,6 +3164,35 @@ static int mtk_open(struct net_device *d
phylink_start(mac->phylink); phylink_start(mac->phylink);
netif_tx_start_all_queues(dev); netif_tx_start_all_queues(dev);
@ -147,7 +147,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
return 0; return 0;
} }
@@ -3510,10 +3484,9 @@ static int mtk_hw_init(struct mtk_eth *e @@ -3512,10 +3486,9 @@ static int mtk_hw_init(struct mtk_eth *e
if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
val = mtk_r32(eth, MTK_CDMP_IG_CTRL); val = mtk_r32(eth, MTK_CDMP_IG_CTRL);
mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL); mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL);
@ -160,7 +160,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
/* set interrupt delays based on current Net DIM sample */ /* set interrupt delays based on current Net DIM sample */
mtk_dim_rx(&eth->rx_dim.work); mtk_dim_rx(&eth->rx_dim.work);
@@ -4134,7 +4107,7 @@ static int mtk_add_mac(struct mtk_eth *e @@ -4136,7 +4109,7 @@ static int mtk_add_mac(struct mtk_eth *e
eth->netdev[id]->hw_features |= NETIF_F_LRO; eth->netdev[id]->hw_features |= NETIF_F_LRO;
eth->netdev[id]->vlan_features = eth->soc->hw_features & eth->netdev[id]->vlan_features = eth->soc->hw_features &