Skip to content

Commit 2d7605a

Browse files
nbd168kuba-moo
authored andcommitted
net: ethernet: mtk_eth_soc: enable hardware DSA untagging
- pass the tag to DSA via metadata dst - disabled on 7986 for now, since it's not working yet - disabled if a MAC is enabled that does not use DSA This improves performance by bypassing the DSA tag driver and avoiding extra skb data mangling Signed-off-by: Felix Fietkau <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 08666cb commit 2d7605a

File tree

2 files changed

+67
-7
lines changed

2 files changed

+67
-7
lines changed

drivers/net/ethernet/mediatek/mtk_eth_soc.c

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <linux/jhash.h>
2424
#include <linux/bitfield.h>
2525
#include <net/dsa.h>
26+
#include <net/dst_metadata.h>
2627

2728
#include "mtk_eth_soc.h"
2829
#include "mtk_wed.h"
@@ -1939,13 +1940,19 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
19391940
__vlan_hwaccel_put_tag(skb, htons(RX_DMA_VPID(trxd.rxd3)),
19401941
RX_DMA_VID(trxd.rxd3));
19411942
}
1943+
}
1944+
1945+
/* When using VLAN untagging in combination with DSA, the
1946+
* hardware treats the MTK special tag as a VLAN and untags it.
1947+
*/
1948+
if (skb_vlan_tag_present(skb) && netdev_uses_dsa(netdev)) {
1949+
unsigned int port = ntohs(skb->vlan_proto) & GENMASK(2, 0);
19421950

1943-
/* If the device is attached to a dsa switch, the special
1944-
* tag inserted in VLAN field by hw switch can * be offloaded
1945-
* by RX HW VLAN offload. Clear vlan info.
1946-
*/
1947-
if (netdev_uses_dsa(netdev))
1948-
__vlan_hwaccel_clear_tag(skb);
1951+
if (port < ARRAY_SIZE(eth->dsa_meta) &&
1952+
eth->dsa_meta[port])
1953+
skb_dst_set_noref(skb, &eth->dsa_meta[port]->dst);
1954+
1955+
__vlan_hwaccel_clear_tag(skb);
19491956
}
19501957

19511958
skb_record_rx_queue(skb, 0);
@@ -2990,11 +2997,46 @@ static void mtk_gdm_config(struct mtk_eth *eth, u32 config)
29902997
mtk_w32(eth, 0, MTK_RST_GL);
29912998
}
29922999

3000+
3001+
static bool mtk_uses_dsa(struct net_device *dev)
3002+
{
3003+
#if IS_ENABLED(CONFIG_NET_DSA)
3004+
return netdev_uses_dsa(dev) &&
3005+
dev->dsa_ptr->tag_ops->proto == DSA_TAG_PROTO_MTK;
3006+
#else
3007+
return false;
3008+
#endif
3009+
}
3010+
29933011
static int mtk_open(struct net_device *dev)
29943012
{
29953013
struct mtk_mac *mac = netdev_priv(dev);
29963014
struct mtk_eth *eth = mac->hw;
2997-
int err;
3015+
int i, err;
3016+
3017+
if (mtk_uses_dsa(dev) && !eth->prog) {
3018+
for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) {
3019+
struct metadata_dst *md_dst = eth->dsa_meta[i];
3020+
3021+
if (md_dst)
3022+
continue;
3023+
3024+
md_dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX,
3025+
GFP_KERNEL);
3026+
if (!md_dst)
3027+
return -ENOMEM;
3028+
3029+
md_dst->u.port_info.port_id = i;
3030+
eth->dsa_meta[i] = md_dst;
3031+
}
3032+
} else {
3033+
/* Hardware special tag parsing needs to be disabled if at least
3034+
* one MAC does not use DSA.
3035+
*/
3036+
u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL);
3037+
val &= ~MTK_CDMP_STAG_EN;
3038+
mtk_w32(eth, val, MTK_CDMP_IG_CTRL);
3039+
}
29983040

29993041
err = phylink_of_phy_connect(mac->phylink, mac->of_node, 0);
30003042
if (err) {
@@ -3321,6 +3363,10 @@ static int mtk_hw_init(struct mtk_eth *eth)
33213363
*/
33223364
val = mtk_r32(eth, MTK_CDMQ_IG_CTRL);
33233365
mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL);
3366+
if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
3367+
val = mtk_r32(eth, MTK_CDMP_IG_CTRL);
3368+
mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL);
3369+
}
33243370

33253371
/* Enable RX VLan Offloading */
33263372
mtk_w32(eth, 1, MTK_CDMP_EG_CTRL);
@@ -3538,6 +3584,12 @@ static int mtk_free_dev(struct mtk_eth *eth)
35383584
free_netdev(eth->netdev[i]);
35393585
}
35403586

3587+
for (i = 0; i < ARRAY_SIZE(eth->dsa_meta); i++) {
3588+
if (!eth->dsa_meta[i])
3589+
break;
3590+
metadata_dst_free(eth->dsa_meta[i]);
3591+
}
3592+
35413593
return 0;
35423594
}
35433595

drivers/net/ethernet/mediatek/mtk_eth_soc.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
#include <linux/bpf_trace.h>
2323
#include "mtk_ppe.h"
2424

25+
#define MTK_MAX_DSA_PORTS 7
26+
#define MTK_DSA_PORT_MASK GENMASK(2, 0)
27+
2528
#define MTK_QDMA_PAGE_SIZE 2048
2629
#define MTK_MAX_RX_LENGTH 1536
2730
#define MTK_MAX_RX_LENGTH_2K 2048
@@ -91,6 +94,9 @@
9194
#define MTK_CDMQ_IG_CTRL 0x1400
9295
#define MTK_CDMQ_STAG_EN BIT(0)
9396

97+
/* CDMQ Exgress Control Register */
98+
#define MTK_CDMQ_EG_CTRL 0x1404
99+
94100
/* CDMP Ingress Control Register */
95101
#define MTK_CDMP_IG_CTRL 0x400
96102
#define MTK_CDMP_STAG_EN BIT(0)
@@ -1121,6 +1127,8 @@ struct mtk_eth {
11211127

11221128
int ip_align;
11231129

1130+
struct metadata_dst *dsa_meta[MTK_MAX_DSA_PORTS];
1131+
11241132
struct mtk_ppe *ppe[2];
11251133
struct rhashtable flow_table;
11261134

0 commit comments

Comments
 (0)