mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-11-04 06:54:27 -05:00 
			
		
		
		
	Removed upstreamed: generic/101-Use-stddefs.h-instead-of-compiler.h.patch[1] All patches automatically rebased. 1. https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v5.10.163&id=ddd2bb08bd99b7ee4442fbbe0f9b80236fdd71d2 Build system: x86_64 Build-tested: ramips/tplink_archer-a6-v3 Run-tested: ramips/tplink_archer-a6-v3 Signed-off-by: John Audia <therealgraysky@proton.me>
		
			
				
	
	
		
			270 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			270 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
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(ð->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 <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
 | 
						|
@@ -854,6 +854,7 @@ enum net_device_path_type {
 | 
						|
 	DEV_PATH_BRIDGE,
 | 
						|
 	DEV_PATH_PPPOE,
 | 
						|
 	DEV_PATH_DSA,
 | 
						|
+	DEV_PATH_MTK_WDMA,
 | 
						|
 };
 | 
						|
 
 | 
						|
 struct net_device_path {
 | 
						|
@@ -879,6 +880,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;
 |