3384086bdc685de720630f04e7bd2e9fd3b1ae61
[openwrt/openwrt.git] / target / linux / generic / backport-6.1 / 733-v6.4-23-net-ethernet-mtk_eth_soc-ppe-add-support-for-flow-ac.patch
1 From f601293f37c4be618c5efaef85d2ee21f97e82e0 Mon Sep 17 00:00:00 2001
2 From: Daniel Golle <daniel@makrotopia.org>
3 Date: Sun, 19 Mar 2023 12:57:35 +0000
4 Subject: [PATCH 092/250] net: ethernet: mtk_eth_soc: ppe: add support for flow
5 accounting
6 MIME-Version: 1.0
7 Content-Type: text/plain; charset=UTF-8
8 Content-Transfer-Encoding: 8bit
9
10 The PPE units found in MT7622 and newer support packet and byte
11 accounting of hw-offloaded flows. Add support for reading those counters
12 as found in MediaTek's SDK[1].
13
14 [1]: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/bc6a6a375c800dc2b80e1a325a2c732d1737df92
15 Tested-by: Bjørn Mork <bjorn@mork.no>
16 Signed-off-by: Daniel Golle <daniel@makrotopia.org>
17 Signed-off-by: Jakub Kicinski <kuba@kernel.org>
18 ---
19 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 8 +-
20 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 3 +
21 drivers/net/ethernet/mediatek/mtk_ppe.c | 114 +++++++++++++++++-
22 drivers/net/ethernet/mediatek/mtk_ppe.h | 25 +++-
23 .../net/ethernet/mediatek/mtk_ppe_debugfs.c | 9 +-
24 .../net/ethernet/mediatek/mtk_ppe_offload.c | 8 ++
25 drivers/net/ethernet/mediatek/mtk_ppe_regs.h | 14 +++
26 7 files changed, 172 insertions(+), 9 deletions(-)
27
28 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
29 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
30 @@ -4689,8 +4689,8 @@ static int mtk_probe(struct platform_dev
31 for (i = 0; i < num_ppe; i++) {
32 u32 ppe_addr = eth->soc->reg_map->ppe_base + i * 0x400;
33
34 - eth->ppe[i] = mtk_ppe_init(eth, eth->base + ppe_addr,
35 - eth->soc->offload_version, i);
36 + eth->ppe[i] = mtk_ppe_init(eth, eth->base + ppe_addr, i);
37 +
38 if (!eth->ppe[i]) {
39 err = -ENOMEM;
40 goto err_deinit_ppe;
41 @@ -4814,6 +4814,7 @@ static const struct mtk_soc_data mt7622_
42 .required_pctl = false,
43 .offload_version = 2,
44 .hash_offset = 2,
45 + .has_accounting = true,
46 .foe_entry_size = sizeof(struct mtk_foe_entry) - 16,
47 .txrx = {
48 .txd_size = sizeof(struct mtk_tx_dma),
49 @@ -4851,6 +4852,7 @@ static const struct mtk_soc_data mt7629_
50 .hw_features = MTK_HW_FEATURES,
51 .required_clks = MT7629_CLKS_BITMAP,
52 .required_pctl = false,
53 + .has_accounting = true,
54 .txrx = {
55 .txd_size = sizeof(struct mtk_tx_dma),
56 .rxd_size = sizeof(struct mtk_rx_dma),
57 @@ -4871,6 +4873,7 @@ static const struct mtk_soc_data mt7981_
58 .offload_version = 2,
59 .hash_offset = 4,
60 .foe_entry_size = sizeof(struct mtk_foe_entry),
61 + .has_accounting = true,
62 .txrx = {
63 .txd_size = sizeof(struct mtk_tx_dma_v2),
64 .rxd_size = sizeof(struct mtk_rx_dma_v2),
65 @@ -4891,6 +4894,7 @@ static const struct mtk_soc_data mt7986_
66 .offload_version = 2,
67 .hash_offset = 4,
68 .foe_entry_size = sizeof(struct mtk_foe_entry),
69 + .has_accounting = true,
70 .txrx = {
71 .txd_size = sizeof(struct mtk_tx_dma_v2),
72 .rxd_size = sizeof(struct mtk_rx_dma_v2),
73 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
74 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
75 @@ -1011,6 +1011,8 @@ struct mtk_reg_map {
76 * the extra setup for those pins used by GMAC.
77 * @hash_offset Flow table hash offset.
78 * @foe_entry_size Foe table entry size.
79 + * @has_accounting Bool indicating support for accounting of
80 + * offloaded flows.
81 * @txd_size Tx DMA descriptor size.
82 * @rxd_size Rx DMA descriptor size.
83 * @rx_irq_done_mask Rx irq done register mask.
84 @@ -1028,6 +1030,7 @@ struct mtk_soc_data {
85 u8 hash_offset;
86 u16 foe_entry_size;
87 netdev_features_t hw_features;
88 + bool has_accounting;
89 struct {
90 u32 txd_size;
91 u32 rxd_size;
92 --- a/drivers/net/ethernet/mediatek/mtk_ppe.c
93 +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
94 @@ -74,6 +74,48 @@ static int mtk_ppe_wait_busy(struct mtk_
95 return ret;
96 }
97
98 +static int mtk_ppe_mib_wait_busy(struct mtk_ppe *ppe)
99 +{
100 + int ret;
101 + u32 val;
102 +
103 + ret = readl_poll_timeout(ppe->base + MTK_PPE_MIB_SER_CR, val,
104 + !(val & MTK_PPE_MIB_SER_CR_ST),
105 + 20, MTK_PPE_WAIT_TIMEOUT_US);
106 +
107 + if (ret)
108 + dev_err(ppe->dev, "MIB table busy");
109 +
110 + return ret;
111 +}
112 +
113 +static int mtk_mib_entry_read(struct mtk_ppe *ppe, u16 index, u64 *bytes, u64 *packets)
114 +{
115 + u32 byte_cnt_low, byte_cnt_high, pkt_cnt_low, pkt_cnt_high;
116 + u32 val, cnt_r0, cnt_r1, cnt_r2;
117 + int ret;
118 +
119 + val = FIELD_PREP(MTK_PPE_MIB_SER_CR_ADDR, index) | MTK_PPE_MIB_SER_CR_ST;
120 + ppe_w32(ppe, MTK_PPE_MIB_SER_CR, val);
121 +
122 + ret = mtk_ppe_mib_wait_busy(ppe);
123 + if (ret)
124 + return ret;
125 +
126 + cnt_r0 = readl(ppe->base + MTK_PPE_MIB_SER_R0);
127 + cnt_r1 = readl(ppe->base + MTK_PPE_MIB_SER_R1);
128 + cnt_r2 = readl(ppe->base + MTK_PPE_MIB_SER_R2);
129 +
130 + byte_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW, cnt_r0);
131 + byte_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH, cnt_r1);
132 + pkt_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R1_PKT_CNT_LOW, cnt_r1);
133 + pkt_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH, cnt_r2);
134 + *bytes = ((u64)byte_cnt_high << 32) | byte_cnt_low;
135 + *packets = (pkt_cnt_high << 16) | pkt_cnt_low;
136 +
137 + return 0;
138 +}
139 +
140 static void mtk_ppe_cache_clear(struct mtk_ppe *ppe)
141 {
142 ppe_set(ppe, MTK_PPE_CACHE_CTL, MTK_PPE_CACHE_CTL_CLEAR);
143 @@ -459,6 +501,13 @@ __mtk_foe_entry_clear(struct mtk_ppe *pp
144 hwe->ib1 |= FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_INVALID);
145 dma_wmb();
146 mtk_ppe_cache_clear(ppe);
147 + if (ppe->accounting) {
148 + struct mtk_foe_accounting *acct;
149 +
150 + acct = ppe->acct_table + entry->hash * sizeof(*acct);
151 + acct->packets = 0;
152 + acct->bytes = 0;
153 + }
154 }
155 entry->hash = 0xffff;
156
157 @@ -566,6 +615,9 @@ __mtk_foe_entry_commit(struct mtk_ppe *p
158 wmb();
159 hwe->ib1 = entry->ib1;
160
161 + if (ppe->accounting)
162 + *mtk_foe_entry_ib2(eth, hwe) |= MTK_FOE_IB2_MIB_CNT;
163 +
164 dma_wmb();
165
166 mtk_ppe_cache_clear(ppe);
167 @@ -757,11 +809,39 @@ int mtk_ppe_prepare_reset(struct mtk_ppe
168 return mtk_ppe_wait_busy(ppe);
169 }
170
171 -struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base,
172 - int version, int index)
173 +struct mtk_foe_accounting *mtk_foe_entry_get_mib(struct mtk_ppe *ppe, u32 index,
174 + struct mtk_foe_accounting *diff)
175 +{
176 + struct mtk_foe_accounting *acct;
177 + int size = sizeof(struct mtk_foe_accounting);
178 + u64 bytes, packets;
179 +
180 + if (!ppe->accounting)
181 + return NULL;
182 +
183 + if (mtk_mib_entry_read(ppe, index, &bytes, &packets))
184 + return NULL;
185 +
186 + acct = ppe->acct_table + index * size;
187 +
188 + acct->bytes += bytes;
189 + acct->packets += packets;
190 +
191 + if (diff) {
192 + diff->bytes = bytes;
193 + diff->packets = packets;
194 + }
195 +
196 + return acct;
197 +}
198 +
199 +struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int index)
200 {
201 + bool accounting = eth->soc->has_accounting;
202 const struct mtk_soc_data *soc = eth->soc;
203 + struct mtk_foe_accounting *acct;
204 struct device *dev = eth->dev;
205 + struct mtk_mib_entry *mib;
206 struct mtk_ppe *ppe;
207 u32 foe_flow_size;
208 void *foe;
209 @@ -778,7 +858,8 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_
210 ppe->base = base;
211 ppe->eth = eth;
212 ppe->dev = dev;
213 - ppe->version = version;
214 + ppe->version = eth->soc->offload_version;
215 + ppe->accounting = accounting;
216
217 foe = dmam_alloc_coherent(ppe->dev,
218 MTK_PPE_ENTRIES * soc->foe_entry_size,
219 @@ -794,6 +875,23 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_
220 if (!ppe->foe_flow)
221 goto err_free_l2_flows;
222
223 + if (accounting) {
224 + mib = dmam_alloc_coherent(ppe->dev, MTK_PPE_ENTRIES * sizeof(*mib),
225 + &ppe->mib_phys, GFP_KERNEL);
226 + if (!mib)
227 + return NULL;
228 +
229 + ppe->mib_table = mib;
230 +
231 + acct = devm_kzalloc(dev, MTK_PPE_ENTRIES * sizeof(*acct),
232 + GFP_KERNEL);
233 +
234 + if (!acct)
235 + return NULL;
236 +
237 + ppe->acct_table = acct;
238 + }
239 +
240 mtk_ppe_debugfs_init(ppe, index);
241
242 return ppe;
243 @@ -923,6 +1021,16 @@ void mtk_ppe_start(struct mtk_ppe *ppe)
244 ppe_w32(ppe, MTK_PPE_DEFAULT_CPU_PORT1, 0xcb777);
245 ppe_w32(ppe, MTK_PPE_SBW_CTRL, 0x7f);
246 }
247 +
248 + if (ppe->accounting && ppe->mib_phys) {
249 + ppe_w32(ppe, MTK_PPE_MIB_TB_BASE, ppe->mib_phys);
250 + ppe_m32(ppe, MTK_PPE_MIB_CFG, MTK_PPE_MIB_CFG_EN,
251 + MTK_PPE_MIB_CFG_EN);
252 + ppe_m32(ppe, MTK_PPE_MIB_CFG, MTK_PPE_MIB_CFG_RD_CLR,
253 + MTK_PPE_MIB_CFG_RD_CLR);
254 + ppe_m32(ppe, MTK_PPE_MIB_CACHE_CTL, MTK_PPE_MIB_CACHE_CTL_EN,
255 + MTK_PPE_MIB_CFG_RD_CLR);
256 + }
257 }
258
259 int mtk_ppe_stop(struct mtk_ppe *ppe)
260 --- a/drivers/net/ethernet/mediatek/mtk_ppe.h
261 +++ b/drivers/net/ethernet/mediatek/mtk_ppe.h
262 @@ -57,6 +57,7 @@ enum {
263 #define MTK_FOE_IB2_MULTICAST BIT(8)
264
265 #define MTK_FOE_IB2_WDMA_QID2 GENMASK(13, 12)
266 +#define MTK_FOE_IB2_MIB_CNT BIT(15)
267 #define MTK_FOE_IB2_WDMA_DEVIDX BIT(16)
268 #define MTK_FOE_IB2_WDMA_WINFO BIT(17)
269
270 @@ -285,16 +286,34 @@ struct mtk_flow_entry {
271 unsigned long cookie;
272 };
273
274 +struct mtk_mib_entry {
275 + u32 byt_cnt_l;
276 + u16 byt_cnt_h;
277 + u32 pkt_cnt_l;
278 + u8 pkt_cnt_h;
279 + u8 _rsv0;
280 + u32 _rsv1;
281 +} __packed;
282 +
283 +struct mtk_foe_accounting {
284 + u64 bytes;
285 + u64 packets;
286 +};
287 +
288 struct mtk_ppe {
289 struct mtk_eth *eth;
290 struct device *dev;
291 void __iomem *base;
292 int version;
293 char dirname[5];
294 + bool accounting;
295
296 void *foe_table;
297 dma_addr_t foe_phys;
298
299 + struct mtk_mib_entry *mib_table;
300 + dma_addr_t mib_phys;
301 +
302 u16 foe_check_time[MTK_PPE_ENTRIES];
303 struct hlist_head *foe_flow;
304
305 @@ -303,8 +322,8 @@ struct mtk_ppe {
306 void *acct_table;
307 };
308
309 -struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base,
310 - int version, int index);
311 +struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int index);
312 +
313 void mtk_ppe_deinit(struct mtk_eth *eth);
314 void mtk_ppe_start(struct mtk_ppe *ppe);
315 int mtk_ppe_stop(struct mtk_ppe *ppe);
316 @@ -359,5 +378,7 @@ int mtk_foe_entry_commit(struct mtk_ppe
317 void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry);
318 int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry);
319 int mtk_ppe_debugfs_init(struct mtk_ppe *ppe, int index);
320 +struct mtk_foe_accounting *mtk_foe_entry_get_mib(struct mtk_ppe *ppe, u32 index,
321 + struct mtk_foe_accounting *diff);
322
323 #endif
324 --- a/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c
325 +++ b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c
326 @@ -82,6 +82,7 @@ mtk_ppe_debugfs_foe_show(struct seq_file
327 struct mtk_foe_entry *entry = mtk_foe_get_entry(ppe, i);
328 struct mtk_foe_mac_info *l2;
329 struct mtk_flow_addr_info ai = {};
330 + struct mtk_foe_accounting *acct;
331 unsigned char h_source[ETH_ALEN];
332 unsigned char h_dest[ETH_ALEN];
333 int type, state;
334 @@ -95,6 +96,8 @@ mtk_ppe_debugfs_foe_show(struct seq_file
335 if (bind && state != MTK_FOE_STATE_BIND)
336 continue;
337
338 + acct = mtk_foe_entry_get_mib(ppe, i, NULL);
339 +
340 type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1);
341 seq_printf(m, "%05x %s %7s", i,
342 mtk_foe_entry_state_str(state),
343 @@ -153,9 +156,11 @@ mtk_ppe_debugfs_foe_show(struct seq_file
344 *((__be16 *)&h_dest[4]) = htons(l2->dest_mac_lo);
345
346 seq_printf(m, " eth=%pM->%pM etype=%04x"
347 - " vlan=%d,%d ib1=%08x ib2=%08x\n",
348 + " vlan=%d,%d ib1=%08x ib2=%08x"
349 + " packets=%llu bytes=%llu\n",
350 h_source, h_dest, ntohs(l2->etype),
351 - l2->vlan1, l2->vlan2, entry->ib1, ib2);
352 + l2->vlan1, l2->vlan2, entry->ib1, ib2,
353 + acct ? acct->packets : 0, acct ? acct->bytes : 0);
354 }
355
356 return 0;
357 --- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
358 +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
359 @@ -497,6 +497,7 @@ static int
360 mtk_flow_offload_stats(struct mtk_eth *eth, struct flow_cls_offload *f)
361 {
362 struct mtk_flow_entry *entry;
363 + struct mtk_foe_accounting diff;
364 u32 idle;
365
366 entry = rhashtable_lookup(&eth->flow_table, &f->cookie,
367 @@ -507,6 +508,13 @@ mtk_flow_offload_stats(struct mtk_eth *e
368 idle = mtk_foe_entry_idle_time(eth->ppe[entry->ppe_index], entry);
369 f->stats.lastused = jiffies - idle * HZ;
370
371 + if (entry->hash != 0xFFFF &&
372 + mtk_foe_entry_get_mib(eth->ppe[entry->ppe_index], entry->hash,
373 + &diff)) {
374 + f->stats.pkts += diff.packets;
375 + f->stats.bytes += diff.bytes;
376 + }
377 +
378 return 0;
379 }
380
381 --- a/drivers/net/ethernet/mediatek/mtk_ppe_regs.h
382 +++ b/drivers/net/ethernet/mediatek/mtk_ppe_regs.h
383 @@ -149,6 +149,20 @@ enum {
384
385 #define MTK_PPE_MIB_TB_BASE 0x338
386
387 +#define MTK_PPE_MIB_SER_CR 0x33C
388 +#define MTK_PPE_MIB_SER_CR_ST BIT(16)
389 +#define MTK_PPE_MIB_SER_CR_ADDR GENMASK(13, 0)
390 +
391 +#define MTK_PPE_MIB_SER_R0 0x340
392 +#define MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW GENMASK(31, 0)
393 +
394 +#define MTK_PPE_MIB_SER_R1 0x344
395 +#define MTK_PPE_MIB_SER_R1_PKT_CNT_LOW GENMASK(31, 16)
396 +#define MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH GENMASK(15, 0)
397 +
398 +#define MTK_PPE_MIB_SER_R2 0x348
399 +#define MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH GENMASK(23, 0)
400 +
401 #define MTK_PPE_MIB_CACHE_CTL 0x350
402 #define MTK_PPE_MIB_CACHE_CTL_EN BIT(0)
403 #define MTK_PPE_MIB_CACHE_CTL_FLUSH BIT(2)