50d65b1eb6ff53d92ed6004bf4c090479dd24f28
[openwrt/staging/blogic.git] /
1 From: Felix Fietkau <nbd@nbd.name>
2 Date: Sat, 5 Feb 2022 18:29:22 +0100
3 Subject: [PATCH] net: ethernet: mtk_eth_soc: implement flow offloading
4 to WED devices
5
6 This allows hardware flow offloading from Ethernet to WLAN on MT7622 SoC
7
8 Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
9 Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
10 Signed-off-by: Felix Fietkau <nbd@nbd.name>
11 ---
12
13 --- a/drivers/net/ethernet/mediatek/mtk_ppe.c
14 +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
15 @@ -329,6 +329,24 @@ int mtk_foe_entry_set_pppoe(struct mtk_f
16 return 0;
17 }
18
19 +int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
20 + int bss, int wcid)
21 +{
22 + struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(entry);
23 + u32 *ib2 = mtk_foe_entry_ib2(entry);
24 +
25 + *ib2 &= ~MTK_FOE_IB2_PORT_MG;
26 + *ib2 |= MTK_FOE_IB2_WDMA_WINFO;
27 + if (wdma_idx)
28 + *ib2 |= MTK_FOE_IB2_WDMA_DEVIDX;
29 +
30 + l2->vlan2 = FIELD_PREP(MTK_FOE_VLAN2_WINFO_BSS, bss) |
31 + FIELD_PREP(MTK_FOE_VLAN2_WINFO_WCID, wcid) |
32 + FIELD_PREP(MTK_FOE_VLAN2_WINFO_RING, txq);
33 +
34 + return 0;
35 +}
36 +
37 static inline bool mtk_foe_entry_usable(struct mtk_foe_entry *entry)
38 {
39 return !(entry->ib1 & MTK_FOE_IB1_STATIC) &&
40 --- a/drivers/net/ethernet/mediatek/mtk_ppe.h
41 +++ b/drivers/net/ethernet/mediatek/mtk_ppe.h
42 @@ -48,9 +48,9 @@ enum {
43 #define MTK_FOE_IB2_DEST_PORT GENMASK(7, 5)
44 #define MTK_FOE_IB2_MULTICAST BIT(8)
45
46 -#define MTK_FOE_IB2_WHNAT_QID2 GENMASK(13, 12)
47 -#define MTK_FOE_IB2_WHNAT_DEVIDX BIT(16)
48 -#define MTK_FOE_IB2_WHNAT_NAT BIT(17)
49 +#define MTK_FOE_IB2_WDMA_QID2 GENMASK(13, 12)
50 +#define MTK_FOE_IB2_WDMA_DEVIDX BIT(16)
51 +#define MTK_FOE_IB2_WDMA_WINFO BIT(17)
52
53 #define MTK_FOE_IB2_PORT_MG GENMASK(17, 12)
54
55 @@ -58,9 +58,9 @@ enum {
56
57 #define MTK_FOE_IB2_DSCP GENMASK(31, 24)
58
59 -#define MTK_FOE_VLAN2_WHNAT_BSS GEMMASK(5, 0)
60 -#define MTK_FOE_VLAN2_WHNAT_WCID GENMASK(13, 6)
61 -#define MTK_FOE_VLAN2_WHNAT_RING GENMASK(15, 14)
62 +#define MTK_FOE_VLAN2_WINFO_BSS GENMASK(5, 0)
63 +#define MTK_FOE_VLAN2_WINFO_WCID GENMASK(13, 6)
64 +#define MTK_FOE_VLAN2_WINFO_RING GENMASK(15, 14)
65
66 enum {
67 MTK_FOE_STATE_INVALID,
68 @@ -281,6 +281,8 @@ int mtk_foe_entry_set_ipv6_tuple(struct
69 int mtk_foe_entry_set_dsa(struct mtk_foe_entry *entry, int port);
70 int mtk_foe_entry_set_vlan(struct mtk_foe_entry *entry, int vid);
71 int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid);
72 +int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
73 + int bss, int wcid);
74 int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_foe_entry *entry,
75 u16 timestamp);
76 int mtk_ppe_debugfs_init(struct mtk_ppe *ppe);
77 --- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
78 +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
79 @@ -10,6 +10,7 @@
80 #include <net/pkt_cls.h>
81 #include <net/dsa.h>
82 #include "mtk_eth_soc.h"
83 +#include "mtk_wed.h"
84
85 struct mtk_flow_data {
86 struct ethhdr eth;
87 @@ -39,6 +40,7 @@ struct mtk_flow_entry {
88 struct rhash_head node;
89 unsigned long cookie;
90 u16 hash;
91 + s8 wed_index;
92 };
93
94 static const struct rhashtable_params mtk_flow_ht_params = {
95 @@ -80,6 +82,35 @@ mtk_flow_offload_mangle_eth(const struct
96 memcpy(dest, src, act->mangle.mask ? 2 : 4);
97 }
98
99 +static int
100 +mtk_flow_get_wdma_info(struct net_device *dev, const u8 *addr, struct mtk_wdma_info *info)
101 +{
102 + struct net_device_path_ctx ctx = {
103 + .dev = dev,
104 + .daddr = addr,
105 + };
106 + struct net_device_path path = {};
107 +
108 + if (!IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED))
109 + return -1;
110 +
111 + if (!dev->netdev_ops->ndo_fill_forward_path)
112 + return -1;
113 +
114 + if (dev->netdev_ops->ndo_fill_forward_path(&ctx, &path))
115 + return -1;
116 +
117 + if (path.type != DEV_PATH_MTK_WDMA)
118 + return -1;
119 +
120 + info->wdma_idx = path.mtk_wdma.wdma_idx;
121 + info->queue = path.mtk_wdma.queue;
122 + info->bss = path.mtk_wdma.bss;
123 + info->wcid = path.mtk_wdma.wcid;
124 +
125 + return 0;
126 +}
127 +
128
129 static int
130 mtk_flow_mangle_ports(const struct flow_action_entry *act,
131 @@ -149,10 +180,20 @@ mtk_flow_get_dsa_port(struct net_device
132
133 static int
134 mtk_flow_set_output_device(struct mtk_eth *eth, struct mtk_foe_entry *foe,
135 - struct net_device *dev)
136 + struct net_device *dev, const u8 *dest_mac,
137 + int *wed_index)
138 {
139 + struct mtk_wdma_info info = {};
140 int pse_port, dsa_port;
141
142 + if (mtk_flow_get_wdma_info(dev, dest_mac, &info) == 0) {
143 + mtk_foe_entry_set_wdma(foe, info.wdma_idx, info.queue, info.bss,
144 + info.wcid);
145 + pse_port = 3;
146 + *wed_index = info.wdma_idx;
147 + goto out;
148 + }
149 +
150 dsa_port = mtk_flow_get_dsa_port(&dev);
151 if (dsa_port >= 0)
152 mtk_foe_entry_set_dsa(foe, dsa_port);
153 @@ -164,6 +205,7 @@ mtk_flow_set_output_device(struct mtk_et
154 else
155 return -EOPNOTSUPP;
156
157 +out:
158 mtk_foe_entry_set_pse_port(foe, pse_port);
159
160 return 0;
161 @@ -179,6 +221,7 @@ mtk_flow_offload_replace(struct mtk_eth
162 struct net_device *odev = NULL;
163 struct mtk_flow_entry *entry;
164 int offload_type = 0;
165 + int wed_index = -1;
166 u16 addr_type = 0;
167 u32 timestamp;
168 u8 l4proto = 0;
169 @@ -326,10 +369,14 @@ mtk_flow_offload_replace(struct mtk_eth
170 if (data.pppoe.num == 1)
171 mtk_foe_entry_set_pppoe(&foe, data.pppoe.sid);
172
173 - err = mtk_flow_set_output_device(eth, &foe, odev);
174 + err = mtk_flow_set_output_device(eth, &foe, odev, data.eth.h_dest,
175 + &wed_index);
176 if (err)
177 return err;
178
179 + if (wed_index >= 0 && (err = mtk_wed_flow_add(wed_index)) < 0)
180 + return err;
181 +
182 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
183 if (!entry)
184 return -ENOMEM;
185 @@ -343,6 +390,7 @@ mtk_flow_offload_replace(struct mtk_eth
186 }
187
188 entry->hash = hash;
189 + entry->wed_index = wed_index;
190 err = rhashtable_insert_fast(&eth->flow_table, &entry->node,
191 mtk_flow_ht_params);
192 if (err < 0)
193 @@ -353,6 +401,8 @@ clear_flow:
194 mtk_foe_entry_clear(&eth->ppe, hash);
195 free:
196 kfree(entry);
197 + if (wed_index >= 0)
198 + mtk_wed_flow_remove(wed_index);
199 return err;
200 }
201
202 @@ -369,6 +419,8 @@ mtk_flow_offload_destroy(struct mtk_eth
203 mtk_foe_entry_clear(&eth->ppe, entry->hash);
204 rhashtable_remove_fast(&eth->flow_table, &entry->node,
205 mtk_flow_ht_params);
206 + if (entry->wed_index >= 0)
207 + mtk_wed_flow_remove(entry->wed_index);
208 kfree(entry);
209
210 return 0;
211 --- a/drivers/net/ethernet/mediatek/mtk_wed.h
212 +++ b/drivers/net/ethernet/mediatek/mtk_wed.h
213 @@ -7,6 +7,7 @@
214 #include <linux/soc/mediatek/mtk_wed.h>
215 #include <linux/debugfs.h>
216 #include <linux/regmap.h>
217 +#include <linux/netdevice.h>
218
219 struct mtk_eth;
220
221 @@ -27,6 +28,12 @@ struct mtk_wed_hw {
222 int index;
223 };
224
225 +struct mtk_wdma_info {
226 + u8 wdma_idx;
227 + u8 queue;
228 + u16 wcid;
229 + u8 bss;
230 +};
231
232 #ifdef CONFIG_NET_MEDIATEK_SOC_WED
233 static inline void
234 --- a/include/linux/netdevice.h
235 +++ b/include/linux/netdevice.h
236 @@ -872,6 +872,7 @@ enum net_device_path_type {
237 DEV_PATH_BRIDGE,
238 DEV_PATH_PPPOE,
239 DEV_PATH_DSA,
240 + DEV_PATH_MTK_WDMA,
241 };
242
243 struct net_device_path {
244 @@ -897,6 +898,12 @@ struct net_device_path {
245 int port;
246 u16 proto;
247 } dsa;
248 + struct {
249 + u8 wdma_idx;
250 + u8 queue;
251 + u16 wcid;
252 + u8 bss;
253 + } mtk_wdma;
254 };
255 };
256
257 --- a/net/core/dev.c
258 +++ b/net/core/dev.c
259 @@ -763,6 +763,10 @@ int dev_fill_forward_path(const struct n
260 if (WARN_ON_ONCE(last_dev == ctx.dev))
261 return -1;
262 }
263 +
264 + if (!ctx.dev)
265 + return ret;
266 +
267 path = dev_fwd_path(stack);
268 if (!path)
269 return -1;