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
7 Content-Type: text/plain; charset=UTF-8
8 Content-Transfer-Encoding: 8bit
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].
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>
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(-)
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;
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);
41 @@ -4814,6 +4814,7 @@ static const struct mtk_soc_data mt7622_
42 .required_pctl = false,
45 + .has_accounting = true,
46 .foe_entry_size = sizeof(struct mtk_foe_entry) - 16,
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,
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_
60 .foe_entry_size = sizeof(struct mtk_foe_entry),
61 + .has_accounting = true,
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_
68 .foe_entry_size = sizeof(struct mtk_foe_entry),
69 + .has_accounting = true,
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
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 {
87 netdev_features_t hw_features;
88 + bool has_accounting;
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_
98 +static int mtk_ppe_mib_wait_busy(struct mtk_ppe *ppe)
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);
108 + dev_err(ppe->dev, "MIB table busy");
113 +static int mtk_mib_entry_read(struct mtk_ppe *ppe, u16 index, u64 *bytes, u64 *packets)
115 + u32 byte_cnt_low, byte_cnt_high, pkt_cnt_low, pkt_cnt_high;
116 + u32 val, cnt_r0, cnt_r1, cnt_r2;
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);
122 + ret = mtk_ppe_mib_wait_busy(ppe);
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);
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;
140 static void mtk_ppe_cache_clear(struct mtk_ppe *ppe)
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);
146 mtk_ppe_cache_clear(ppe);
147 + if (ppe->accounting) {
148 + struct mtk_foe_accounting *acct;
150 + acct = ppe->acct_table + entry->hash * sizeof(*acct);
155 entry->hash = 0xffff;
157 @@ -566,6 +615,9 @@ __mtk_foe_entry_commit(struct mtk_ppe *p
159 hwe->ib1 = entry->ib1;
161 + if (ppe->accounting)
162 + *mtk_foe_entry_ib2(eth, hwe) |= MTK_FOE_IB2_MIB_CNT;
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);
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)
176 + struct mtk_foe_accounting *acct;
177 + int size = sizeof(struct mtk_foe_accounting);
178 + u64 bytes, packets;
180 + if (!ppe->accounting)
183 + if (mtk_mib_entry_read(ppe, index, &bytes, &packets))
186 + acct = ppe->acct_table + index * size;
188 + acct->bytes += bytes;
189 + acct->packets += packets;
192 + diff->bytes = bytes;
193 + diff->packets = packets;
199 +struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int index)
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;
209 @@ -778,7 +858,8 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_
213 - ppe->version = version;
214 + ppe->version = eth->soc->offload_version;
215 + ppe->accounting = accounting;
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_
221 goto err_free_l2_flows;
224 + mib = dmam_alloc_coherent(ppe->dev, MTK_PPE_ENTRIES * sizeof(*mib),
225 + &ppe->mib_phys, GFP_KERNEL);
229 + ppe->mib_table = mib;
231 + acct = devm_kzalloc(dev, MTK_PPE_ENTRIES * sizeof(*acct),
237 + ppe->acct_table = acct;
240 mtk_ppe_debugfs_init(ppe, index);
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);
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);
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)
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)
270 @@ -285,16 +286,34 @@ struct mtk_flow_entry {
271 unsigned long cookie;
274 +struct mtk_mib_entry {
283 +struct mtk_foe_accounting {
299 + struct mtk_mib_entry *mib_table;
300 + dma_addr_t mib_phys;
302 u16 foe_check_time[MTK_PPE_ENTRIES];
303 struct hlist_head *foe_flow;
305 @@ -303,8 +322,8 @@ struct mtk_ppe {
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);
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);
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];
334 @@ -95,6 +96,8 @@ mtk_ppe_debugfs_foe_show(struct seq_file
335 if (bind && state != MTK_FOE_STATE_BIND)
338 + acct = mtk_foe_entry_get_mib(ppe, i, NULL);
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);
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);
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)
362 struct mtk_flow_entry *entry;
363 + struct mtk_foe_accounting diff;
366 entry = rhashtable_lookup(ð->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;
371 + if (entry->hash != 0xFFFF &&
372 + mtk_foe_entry_get_mib(eth->ppe[entry->ppe_index], entry->hash,
374 + f->stats.pkts += diff.packets;
375 + f->stats.bytes += diff.bytes;
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 {
385 #define MTK_PPE_MIB_TB_BASE 0x338
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)
391 +#define MTK_PPE_MIB_SER_R0 0x340
392 +#define MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW GENMASK(31, 0)
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)
398 +#define MTK_PPE_MIB_SER_R2 0x348
399 +#define MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH GENMASK(23, 0)
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)