generic: 6.1: refresh pending patches
[openwrt/staging/ldir.git] / target / linux / generic / pending-6.1 / 736-01-net-ethernet-mtk_eth_soc-add-code-for-offloading-flo.patch
1 From: Felix Fietkau <nbd@nbd.name>
2 Date: Mon, 20 Mar 2023 11:44:30 +0100
3 Subject: [PATCH] net: ethernet: mtk_eth_soc: add code for offloading flows
4 from wlan devices
5
6 WED version 2 (on MT7986 and later) can offload flows originating from wireless
7 devices. In order to make that work, ndo_setup_tc needs to be implemented on
8 the netdevs. This adds the required code to offload flows coming in from WED,
9 while keeping track of the incoming wed index used for selecting the correct
10 PPE device.
11
12 Signed-off-by: Felix Fietkau <nbd@nbd.name>
13 ---
14
15 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
16 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
17 @@ -1280,6 +1280,9 @@ int mtk_gmac_rgmii_path_setup(struct mtk
18 int mtk_eth_offload_init(struct mtk_eth *eth);
19 int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type,
20 void *type_data);
21 +int mtk_flow_offload_cmd(struct mtk_eth *eth, struct flow_cls_offload *cls,
22 + int ppe_index);
23 +void mtk_flow_offload_cleanup(struct mtk_eth *eth, struct list_head *list);
24 void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev);
25
26
27 --- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
28 +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
29 @@ -235,7 +235,8 @@ out:
30 }
31
32 static int
33 -mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
34 +mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f,
35 + int ppe_index)
36 {
37 struct flow_rule *rule = flow_cls_offload_flow_rule(f);
38 struct flow_action_entry *act;
39 @@ -452,6 +453,7 @@ mtk_flow_offload_replace(struct mtk_eth
40 entry->cookie = f->cookie;
41 memcpy(&entry->data, &foe, sizeof(entry->data));
42 entry->wed_index = wed_index;
43 + entry->ppe_index = ppe_index;
44
45 err = mtk_foe_entry_commit(eth->ppe[entry->ppe_index], entry);
46 if (err < 0)
47 @@ -520,25 +522,15 @@ mtk_flow_offload_stats(struct mtk_eth *e
48
49 static DEFINE_MUTEX(mtk_flow_offload_mutex);
50
51 -static int
52 -mtk_eth_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv)
53 +int mtk_flow_offload_cmd(struct mtk_eth *eth, struct flow_cls_offload *cls,
54 + int ppe_index)
55 {
56 - struct flow_cls_offload *cls = type_data;
57 - struct net_device *dev = cb_priv;
58 - struct mtk_mac *mac = netdev_priv(dev);
59 - struct mtk_eth *eth = mac->hw;
60 int err;
61
62 - if (!tc_can_offload(dev))
63 - return -EOPNOTSUPP;
64 -
65 - if (type != TC_SETUP_CLSFLOWER)
66 - return -EOPNOTSUPP;
67 -
68 mutex_lock(&mtk_flow_offload_mutex);
69 switch (cls->command) {
70 case FLOW_CLS_REPLACE:
71 - err = mtk_flow_offload_replace(eth, cls);
72 + err = mtk_flow_offload_replace(eth, cls, ppe_index);
73 break;
74 case FLOW_CLS_DESTROY:
75 err = mtk_flow_offload_destroy(eth, cls);
76 @@ -556,6 +548,23 @@ mtk_eth_setup_tc_block_cb(enum tc_setup_
77 }
78
79 static int
80 +mtk_eth_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv)
81 +{
82 + struct flow_cls_offload *cls = type_data;
83 + struct net_device *dev = cb_priv;
84 + struct mtk_mac *mac = netdev_priv(dev);
85 + struct mtk_eth *eth = mac->hw;
86 +
87 + if (!tc_can_offload(dev))
88 + return -EOPNOTSUPP;
89 +
90 + if (type != TC_SETUP_CLSFLOWER)
91 + return -EOPNOTSUPP;
92 +
93 + return mtk_flow_offload_cmd(eth, cls, 0);
94 +}
95 +
96 +static int
97 mtk_eth_setup_tc_block(struct net_device *dev, struct flow_block_offload *f)
98 {
99 struct mtk_mac *mac = netdev_priv(dev);
100 --- a/drivers/net/ethernet/mediatek/mtk_wed.c
101 +++ b/drivers/net/ethernet/mediatek/mtk_wed.c
102 @@ -13,6 +13,8 @@
103 #include <linux/mfd/syscon.h>
104 #include <linux/debugfs.h>
105 #include <linux/soc/mediatek/mtk_wed.h>
106 +#include <net/flow_offload.h>
107 +#include <net/pkt_cls.h>
108 #include "mtk_eth_soc.h"
109 #include "mtk_wed_regs.h"
110 #include "mtk_wed.h"
111 @@ -41,6 +43,11 @@
112 static struct mtk_wed_hw *hw_list[2];
113 static DEFINE_MUTEX(hw_lock);
114
115 +struct mtk_wed_flow_block_priv {
116 + struct mtk_wed_hw *hw;
117 + struct net_device *dev;
118 +};
119 +
120 static void
121 wed_m32(struct mtk_wed_device *dev, u32 reg, u32 mask, u32 val)
122 {
123 @@ -1745,6 +1752,99 @@ out:
124 mutex_unlock(&hw_lock);
125 }
126
127 +static int
128 +mtk_wed_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv)
129 +{
130 + struct mtk_wed_flow_block_priv *priv = cb_priv;
131 + struct flow_cls_offload *cls = type_data;
132 + struct mtk_wed_hw *hw = priv->hw;
133 +
134 + if (!tc_can_offload(priv->dev))
135 + return -EOPNOTSUPP;
136 +
137 + if (type != TC_SETUP_CLSFLOWER)
138 + return -EOPNOTSUPP;
139 +
140 + return mtk_flow_offload_cmd(hw->eth, cls, hw->index);
141 +}
142 +
143 +static int
144 +mtk_wed_setup_tc_block(struct mtk_wed_hw *hw, struct net_device *dev,
145 + struct flow_block_offload *f)
146 +{
147 + struct mtk_wed_flow_block_priv *priv;
148 + static LIST_HEAD(block_cb_list);
149 + struct flow_block_cb *block_cb;
150 + struct mtk_eth *eth = hw->eth;
151 + flow_setup_cb_t *cb;
152 +
153 + if (!eth->soc->offload_version)
154 + return -EOPNOTSUPP;
155 +
156 + if (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
157 + return -EOPNOTSUPP;
158 +
159 + cb = mtk_wed_setup_tc_block_cb;
160 + f->driver_block_list = &block_cb_list;
161 +
162 + switch (f->command) {
163 + case FLOW_BLOCK_BIND:
164 + block_cb = flow_block_cb_lookup(f->block, cb, dev);
165 + if (block_cb) {
166 + flow_block_cb_incref(block_cb);
167 + return 0;
168 + }
169 +
170 + priv = kzalloc(sizeof(*priv), GFP_KERNEL);
171 + if (!priv)
172 + return -ENOMEM;
173 +
174 + priv->hw = hw;
175 + priv->dev = dev;
176 + block_cb = flow_block_cb_alloc(cb, dev, priv, NULL);
177 + if (IS_ERR(block_cb)) {
178 + kfree(priv);
179 + return PTR_ERR(block_cb);
180 + }
181 +
182 + flow_block_cb_incref(block_cb);
183 + flow_block_cb_add(block_cb, f);
184 + list_add_tail(&block_cb->driver_list, &block_cb_list);
185 + return 0;
186 + case FLOW_BLOCK_UNBIND:
187 + block_cb = flow_block_cb_lookup(f->block, cb, dev);
188 + if (!block_cb)
189 + return -ENOENT;
190 +
191 + if (!flow_block_cb_decref(block_cb)) {
192 + flow_block_cb_remove(block_cb, f);
193 + list_del(&block_cb->driver_list);
194 + kfree(block_cb->cb_priv);
195 + }
196 + return 0;
197 + default:
198 + return -EOPNOTSUPP;
199 + }
200 +}
201 +
202 +static int
203 +mtk_wed_setup_tc(struct mtk_wed_device *wed, struct net_device *dev,
204 + enum tc_setup_type type, void *type_data)
205 +{
206 + struct mtk_wed_hw *hw = wed->hw;
207 +
208 + if (hw->version < 2)
209 + return -EOPNOTSUPP;
210 +
211 + switch (type) {
212 + case TC_SETUP_BLOCK:
213 + case TC_SETUP_FT:
214 + return mtk_wed_setup_tc_block(hw, dev, type_data);
215 + default:
216 + return -EOPNOTSUPP;
217 + }
218 +}
219 +
220 void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
221 void __iomem *wdma, phys_addr_t wdma_phy,
222 int index)
223 @@ -1764,6 +1864,7 @@ void mtk_wed_add_hw(struct device_node *
224 .irq_set_mask = mtk_wed_irq_set_mask,
225 .detach = mtk_wed_detach,
226 .ppe_check = mtk_wed_ppe_check,
227 + .setup_tc = mtk_wed_setup_tc,
228 };
229 struct device_node *eth_np = eth->dev->of_node;
230 struct platform_device *pdev;
231 --- a/include/linux/soc/mediatek/mtk_wed.h
232 +++ b/include/linux/soc/mediatek/mtk_wed.h
233 @@ -6,6 +6,7 @@
234 #include <linux/regmap.h>
235 #include <linux/pci.h>
236 #include <linux/skbuff.h>
237 +#include <linux/netdevice.h>
238
239 #define MTK_WED_TX_QUEUES 2
240 #define MTK_WED_RX_QUEUES 2
241 @@ -180,6 +181,8 @@ struct mtk_wed_ops {
242
243 u32 (*irq_get)(struct mtk_wed_device *dev, u32 mask);
244 void (*irq_set_mask)(struct mtk_wed_device *dev, u32 mask);
245 + int (*setup_tc)(struct mtk_wed_device *wed, struct net_device *dev,
246 + enum tc_setup_type type, void *type_data);
247 };
248
249 extern const struct mtk_wed_ops __rcu *mtk_soc_wed_ops;
250 @@ -238,6 +241,8 @@ mtk_wed_get_rx_capa(struct mtk_wed_devic
251 (_dev)->ops->msg_update(_dev, _id, _msg, _len)
252 #define mtk_wed_device_stop(_dev) (_dev)->ops->stop(_dev)
253 #define mtk_wed_device_dma_reset(_dev) (_dev)->ops->reset_dma(_dev)
254 +#define mtk_wed_device_setup_tc(_dev, _netdev, _type, _type_data) \
255 + (_dev)->ops->setup_tc(_dev, _netdev, _type, _type_data)
256 #else
257 static inline bool mtk_wed_device_active(struct mtk_wed_device *dev)
258 {
259 @@ -256,6 +261,7 @@ static inline bool mtk_wed_device_active
260 #define mtk_wed_device_update_msg(_dev, _id, _msg, _len) -ENODEV
261 #define mtk_wed_device_stop(_dev) do {} while (0)
262 #define mtk_wed_device_dma_reset(_dev) do {} while (0)
263 +#define mtk_wed_device_setup_tc(_dev, _netdev, _type, _type_data) -EOPNOTSUPP
264 #endif
265
266 #endif