From 77e123340f0b5490905e27ddc92f0dff8ed017a5 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 30 Nov 2021 11:55:24 +0100 Subject: mediatek: add patches for MT7622 WED (wireless ethernet dispatch) This series also contains other improvement for hardware flow offload support Signed-off-by: Felix Fietkau (cherry-picked from commit 0f029b3d2b505b40aca9a24a002838ed1060f83d) --- ...t-mtk_eth_soc-implement-flow-offloading-t.patch | 269 +++++++++++++++++++++ 1 file changed, 269 insertions(+) create mode 100644 target/linux/generic/pending-5.10/701-03-net-ethernet-mtk_eth_soc-implement-flow-offloading-t.patch (limited to 'target/linux/generic/pending-5.10/701-03-net-ethernet-mtk_eth_soc-implement-flow-offloading-t.patch') diff --git a/target/linux/generic/pending-5.10/701-03-net-ethernet-mtk_eth_soc-implement-flow-offloading-t.patch b/target/linux/generic/pending-5.10/701-03-net-ethernet-mtk_eth_soc-implement-flow-offloading-t.patch new file mode 100644 index 0000000000..1193cb0f9d --- /dev/null +++ b/target/linux/generic/pending-5.10/701-03-net-ethernet-mtk_eth_soc-implement-flow-offloading-t.patch @@ -0,0 +1,269 @@ +From: Felix Fietkau +Date: Sat, 5 Feb 2022 18:29:22 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: implement flow offloading + to WED devices + +This allows hardware flow offloading from Ethernet to WLAN on MT7622 SoC + +Co-developed-by: Lorenzo Bianconi +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_ppe.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c +@@ -329,6 +329,24 @@ int mtk_foe_entry_set_pppoe(struct mtk_f + return 0; + } + ++int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq, ++ int bss, int wcid) ++{ ++ struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(entry); ++ u32 *ib2 = mtk_foe_entry_ib2(entry); ++ ++ *ib2 &= ~MTK_FOE_IB2_PORT_MG; ++ *ib2 |= MTK_FOE_IB2_WDMA_WINFO; ++ if (wdma_idx) ++ *ib2 |= MTK_FOE_IB2_WDMA_DEVIDX; ++ ++ l2->vlan2 = FIELD_PREP(MTK_FOE_VLAN2_WINFO_BSS, bss) | ++ FIELD_PREP(MTK_FOE_VLAN2_WINFO_WCID, wcid) | ++ FIELD_PREP(MTK_FOE_VLAN2_WINFO_RING, txq); ++ ++ return 0; ++} ++ + static inline bool mtk_foe_entry_usable(struct mtk_foe_entry *entry) + { + return !(entry->ib1 & MTK_FOE_IB1_STATIC) && +--- a/drivers/net/ethernet/mediatek/mtk_ppe.h ++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h +@@ -48,9 +48,9 @@ enum { + #define MTK_FOE_IB2_DEST_PORT GENMASK(7, 5) + #define MTK_FOE_IB2_MULTICAST BIT(8) + +-#define MTK_FOE_IB2_WHNAT_QID2 GENMASK(13, 12) +-#define MTK_FOE_IB2_WHNAT_DEVIDX BIT(16) +-#define MTK_FOE_IB2_WHNAT_NAT BIT(17) ++#define MTK_FOE_IB2_WDMA_QID2 GENMASK(13, 12) ++#define MTK_FOE_IB2_WDMA_DEVIDX BIT(16) ++#define MTK_FOE_IB2_WDMA_WINFO BIT(17) + + #define MTK_FOE_IB2_PORT_MG GENMASK(17, 12) + +@@ -58,9 +58,9 @@ enum { + + #define MTK_FOE_IB2_DSCP GENMASK(31, 24) + +-#define MTK_FOE_VLAN2_WHNAT_BSS GEMMASK(5, 0) +-#define MTK_FOE_VLAN2_WHNAT_WCID GENMASK(13, 6) +-#define MTK_FOE_VLAN2_WHNAT_RING GENMASK(15, 14) ++#define MTK_FOE_VLAN2_WINFO_BSS GENMASK(5, 0) ++#define MTK_FOE_VLAN2_WINFO_WCID GENMASK(13, 6) ++#define MTK_FOE_VLAN2_WINFO_RING GENMASK(15, 14) + + enum { + MTK_FOE_STATE_INVALID, +@@ -281,6 +281,8 @@ int mtk_foe_entry_set_ipv6_tuple(struct + int mtk_foe_entry_set_dsa(struct mtk_foe_entry *entry, int port); + int mtk_foe_entry_set_vlan(struct mtk_foe_entry *entry, int vid); + int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid); ++int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq, ++ int bss, int wcid); + int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_foe_entry *entry, + u16 timestamp); + int mtk_ppe_debugfs_init(struct mtk_ppe *ppe); +--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +@@ -11,6 +11,7 @@ + #include + #include + #include "mtk_eth_soc.h" ++#include "mtk_wed.h" + + struct mtk_flow_data { + struct ethhdr eth; +@@ -40,6 +41,7 @@ struct mtk_flow_entry { + struct rhash_head node; + unsigned long cookie; + u16 hash; ++ s8 wed_index; + }; + + static const struct rhashtable_params mtk_flow_ht_params = { +@@ -81,6 +83,35 @@ mtk_flow_offload_mangle_eth(const struct + memcpy(dest, src, act->mangle.mask ? 2 : 4); + } + ++static int ++mtk_flow_get_wdma_info(struct net_device *dev, const u8 *addr, struct mtk_wdma_info *info) ++{ ++ struct net_device_path_ctx ctx = { ++ .dev = dev, ++ .daddr = addr, ++ }; ++ struct net_device_path path = {}; ++ ++ if (!IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED)) ++ return -1; ++ ++ if (!dev->netdev_ops->ndo_fill_forward_path) ++ return -1; ++ ++ if (dev->netdev_ops->ndo_fill_forward_path(&ctx, &path)) ++ return -1; ++ ++ if (path.type != DEV_PATH_MTK_WDMA) ++ return -1; ++ ++ info->wdma_idx = path.mtk_wdma.wdma_idx; ++ info->queue = path.mtk_wdma.queue; ++ info->bss = path.mtk_wdma.bss; ++ info->wcid = path.mtk_wdma.wcid; ++ ++ return 0; ++} ++ + + static int + mtk_flow_mangle_ports(const struct flow_action_entry *act, +@@ -150,10 +181,20 @@ mtk_flow_get_dsa_port(struct net_device + + static int + mtk_flow_set_output_device(struct mtk_eth *eth, struct mtk_foe_entry *foe, +- struct net_device *dev) ++ struct net_device *dev, const u8 *dest_mac, ++ int *wed_index) + { ++ struct mtk_wdma_info info = {}; + int pse_port, dsa_port; + ++ if (mtk_flow_get_wdma_info(dev, dest_mac, &info) == 0) { ++ mtk_foe_entry_set_wdma(foe, info.wdma_idx, info.queue, info.bss, ++ info.wcid); ++ pse_port = 3; ++ *wed_index = info.wdma_idx; ++ goto out; ++ } ++ + dsa_port = mtk_flow_get_dsa_port(&dev); + if (dsa_port >= 0) + mtk_foe_entry_set_dsa(foe, dsa_port); +@@ -165,6 +206,7 @@ mtk_flow_set_output_device(struct mtk_et + else + return -EOPNOTSUPP; + ++out: + mtk_foe_entry_set_pse_port(foe, pse_port); + + return 0; +@@ -180,6 +222,7 @@ mtk_flow_offload_replace(struct mtk_eth + struct net_device *odev = NULL; + struct mtk_flow_entry *entry; + int offload_type = 0; ++ int wed_index = -1; + u16 addr_type = 0; + u32 timestamp; + u8 l4proto = 0; +@@ -327,10 +370,14 @@ mtk_flow_offload_replace(struct mtk_eth + if (data.pppoe.num == 1) + mtk_foe_entry_set_pppoe(&foe, data.pppoe.sid); + +- err = mtk_flow_set_output_device(eth, &foe, odev); ++ err = mtk_flow_set_output_device(eth, &foe, odev, data.eth.h_dest, ++ &wed_index); + if (err) + return err; + ++ if (wed_index >= 0 && (err = mtk_wed_flow_add(wed_index)) < 0) ++ return err; ++ + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; +@@ -344,6 +391,7 @@ mtk_flow_offload_replace(struct mtk_eth + } + + entry->hash = hash; ++ entry->wed_index = wed_index; + err = rhashtable_insert_fast(ð->flow_table, &entry->node, + mtk_flow_ht_params); + if (err < 0) +@@ -354,6 +402,8 @@ clear_flow: + mtk_foe_entry_clear(ð->ppe, hash); + free: + kfree(entry); ++ if (wed_index >= 0) ++ mtk_wed_flow_remove(wed_index); + return err; + } + +@@ -370,6 +420,8 @@ mtk_flow_offload_destroy(struct mtk_eth + mtk_foe_entry_clear(ð->ppe, entry->hash); + rhashtable_remove_fast(ð->flow_table, &entry->node, + mtk_flow_ht_params); ++ if (entry->wed_index >= 0) ++ mtk_wed_flow_remove(entry->wed_index); + kfree(entry); + + return 0; +--- a/drivers/net/ethernet/mediatek/mtk_wed.h ++++ b/drivers/net/ethernet/mediatek/mtk_wed.h +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + + struct mtk_eth; + +@@ -27,6 +28,12 @@ struct mtk_wed_hw { + int index; + }; + ++struct mtk_wdma_info { ++ u8 wdma_idx; ++ u8 queue; ++ u16 wcid; ++ u8 bss; ++}; + + #ifdef CONFIG_NET_MEDIATEK_SOC_WED + static inline void +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -833,6 +833,7 @@ enum net_device_path_type { + DEV_PATH_BRIDGE, + DEV_PATH_PPPOE, + DEV_PATH_DSA, ++ DEV_PATH_MTK_WDMA, + }; + + struct net_device_path { +@@ -858,6 +859,12 @@ struct net_device_path { + int port; + u16 proto; + } dsa; ++ struct { ++ u8 wdma_idx; ++ u8 queue; ++ u16 wcid; ++ u8 bss; ++ } mtk_wdma; + }; + }; + +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -883,6 +883,10 @@ int dev_fill_forward_path(const struct n + if (WARN_ON_ONCE(last_dev == ctx.dev)) + return -1; + } ++ ++ if (!ctx.dev) ++ return ret; ++ + path = dev_fwd_path(stack); + if (!path) + return -1; -- cgit v1.2.3