aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/pending-5.10/701-03-net-ethernet-mtk_eth_soc-implement-flow-offloading-t.patch
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@nbd.name>2021-11-30 11:55:24 +0100
committerFelix Fietkau <nbd@nbd.name>2022-05-06 19:57:57 +0200
commit77e123340f0b5490905e27ddc92f0dff8ed017a5 (patch)
tree36398f65a267775cb961539a2a3ad479a6054648 /target/linux/generic/pending-5.10/701-03-net-ethernet-mtk_eth_soc-implement-flow-offloading-t.patch
parent5ff900e0ade775062bf888b447893aefa1a37146 (diff)
downloadupstream-77e123340f0b5490905e27ddc92f0dff8ed017a5.tar.gz
upstream-77e123340f0b5490905e27ddc92f0dff8ed017a5.tar.bz2
upstream-77e123340f0b5490905e27ddc92f0dff8ed017a5.zip
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 <nbd@nbd.name> (cherry-picked from commit 0f029b3d2b505b40aca9a24a002838ed1060f83d)
Diffstat (limited to 'target/linux/generic/pending-5.10/701-03-net-ethernet-mtk_eth_soc-implement-flow-offloading-t.patch')
-rw-r--r--target/linux/generic/pending-5.10/701-03-net-ethernet-mtk_eth_soc-implement-flow-offloading-t.patch269
1 files changed, 269 insertions, 0 deletions
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 <nbd@nbd.name>
+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 <lorenzo@kernel.org>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- 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 <net/pkt_cls.h>
+ #include <net/dsa.h>
+ #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(&eth->flow_table, &entry->node,
+ mtk_flow_ht_params);
+ if (err < 0)
+@@ -354,6 +402,8 @@ clear_flow:
+ mtk_foe_entry_clear(&eth->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(&eth->ppe, entry->hash);
+ rhashtable_remove_fast(&eth->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 <linux/soc/mediatek/mtk_wed.h>
+ #include <linux/debugfs.h>
+ #include <linux/regmap.h>
++#include <linux/netdevice.h>
+
+ 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;