8bf036d006f06f318d46b524b23aaf01736f43f0
[openwrt/openwrt.git] / target / linux / generic / pending-5.15 / 731-net-ethernet-mediatek-ppe-add-support-for-flow-accou.patch
1 From patchwork Wed Nov 2 00:58:01 2022
2 Content-Type: text/plain; charset="utf-8"
3 MIME-Version: 1.0
4 Content-Transfer-Encoding: 7bit
5 X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
6 X-Patchwork-Id: 13027653
7 X-Patchwork-Delegate: kuba@kernel.org
8 Return-Path: <netdev-owner@kernel.org>
9 Date: Wed, 2 Nov 2022 00:58:01 +0000
10 From: Daniel Golle <daniel@makrotopia.org>
11 To: Felix Fietkau <nbd@nbd.name>, John Crispin <john@phrozen.org>,
12 Sean Wang <sean.wang@mediatek.com>,
13 Mark Lee <Mark-MC.Lee@mediatek.com>,
14 "David S. Miller" <davem@davemloft.net>,
15 Eric Dumazet <edumazet@google.com>,
16 Jakub Kicinski <kuba@kernel.org>,
17 Paolo Abeni <pabeni@redhat.com>,
18 Matthias Brugger <matthias.bgg@gmail.com>,
19 netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
20 linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org
21 Subject: [PATCH v4] net: ethernet: mediatek: ppe: add support for flow
22 accounting
23 Message-ID: <Y2HAmYYPd77dz+K5@makrotopia.org>
24 MIME-Version: 1.0
25 Content-Disposition: inline
26 Precedence: bulk
27 List-ID: <netdev.vger.kernel.org>
28 X-Mailing-List: netdev@vger.kernel.org
29 X-Patchwork-Delegate: kuba@kernel.org
30
31 The PPE units found in MT7622 and newer support packet and byte
32 accounting of hw-offloaded flows. Add support for reading those
33 counters as found in MediaTek's SDK[1].
34
35 [1]: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/bc6a6a375c800dc2b80e1a325a2c732d1737df92
36 Signed-off-by: Daniel Golle <daniel@makrotopia.org>
37 ---
38 v4: declare function mtk_mib_entry_read as static
39 v3: don't bother to set 'false' values in any zero-initialized struct
40 use mtk_foe_entry_ib2
41 both changes were requested by Felix Fietkau
42
43 v2: fix wrong variable name in return value check spotted by Denis Kirjanov
44
45 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 7 +-
46 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 +
47 drivers/net/ethernet/mediatek/mtk_ppe.c | 110 +++++++++++++++++-
48 drivers/net/ethernet/mediatek/mtk_ppe.h | 23 +++-
49 .../net/ethernet/mediatek/mtk_ppe_debugfs.c | 9 +-
50 .../net/ethernet/mediatek/mtk_ppe_offload.c | 7 ++
51 drivers/net/ethernet/mediatek/mtk_ppe_regs.h | 14 +++
52 7 files changed, 166 insertions(+), 5 deletions(-)
53
54 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
55 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
56 @@ -4088,7 +4088,9 @@ static int mtk_probe(struct platform_dev
57 u32 ppe_addr = eth->soc->reg_map->ppe_base + i * 0x400;
58
59 eth->ppe[i] = mtk_ppe_init(eth, eth->base + ppe_addr,
60 - eth->soc->offload_version, i);
61 + eth->soc->offload_version, i,
62 + eth->soc->has_accounting);
63 +
64 if (!eth->ppe[i]) {
65 err = -ENOMEM;
66 goto err_free_dev;
67 @@ -4211,6 +4213,7 @@ static const struct mtk_soc_data mt7622_
68 .required_pctl = false,
69 .offload_version = 2,
70 .hash_offset = 2,
71 + .has_accounting = true,
72 .foe_entry_size = sizeof(struct mtk_foe_entry) - 16,
73 .txrx = {
74 .txd_size = sizeof(struct mtk_tx_dma),
75 @@ -4248,6 +4251,7 @@ static const struct mtk_soc_data mt7629_
76 .hw_features = MTK_HW_FEATURES,
77 .required_clks = MT7629_CLKS_BITMAP,
78 .required_pctl = false,
79 + .has_accounting = true,
80 .txrx = {
81 .txd_size = sizeof(struct mtk_tx_dma),
82 .rxd_size = sizeof(struct mtk_rx_dma),
83 @@ -4268,6 +4272,7 @@ static const struct mtk_soc_data mt7986_
84 .offload_version = 2,
85 .hash_offset = 4,
86 .foe_entry_size = sizeof(struct mtk_foe_entry),
87 + .has_accounting = true,
88 .txrx = {
89 .txd_size = sizeof(struct mtk_tx_dma_v2),
90 .rxd_size = sizeof(struct mtk_rx_dma_v2),
91 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
92 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
93 @@ -983,6 +983,7 @@ struct mtk_soc_data {
94 u8 hash_offset;
95 u16 foe_entry_size;
96 netdev_features_t hw_features;
97 + bool has_accounting;
98 struct {
99 u32 txd_size;
100 u32 rxd_size;
101 --- a/drivers/net/ethernet/mediatek/mtk_ppe.c
102 +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
103 @@ -74,6 +74,46 @@ static int mtk_ppe_wait_busy(struct mtk_
104 return ret;
105 }
106
107 +static int mtk_ppe_mib_wait_busy(struct mtk_ppe *ppe)
108 +{
109 + int ret;
110 + u32 val;
111 +
112 + ret = readl_poll_timeout(ppe->base + MTK_PPE_MIB_SER_CR, val,
113 + !(val & MTK_PPE_MIB_SER_CR_ST),
114 + 20, MTK_PPE_WAIT_TIMEOUT_US);
115 +
116 + if (ret)
117 + dev_err(ppe->dev, "MIB table busy");
118 +
119 + return ret;
120 +}
121 +
122 +static int mtk_mib_entry_read(struct mtk_ppe *ppe, u16 index, u64 *bytes, u64 *packets)
123 +{
124 + u32 val, cnt_r0, cnt_r1, cnt_r2;
125 + u32 byte_cnt_low, byte_cnt_high, pkt_cnt_low, pkt_cnt_high;
126 +
127 + val = FIELD_PREP(MTK_PPE_MIB_SER_CR_ADDR, index) | MTK_PPE_MIB_SER_CR_ST;
128 + ppe_w32(ppe, MTK_PPE_MIB_SER_CR, val);
129 +
130 + if (mtk_ppe_mib_wait_busy(ppe))
131 + return -ETIMEDOUT;
132 +
133 + cnt_r0 = readl(ppe->base + MTK_PPE_MIB_SER_R0);
134 + cnt_r1 = readl(ppe->base + MTK_PPE_MIB_SER_R1);
135 + cnt_r2 = readl(ppe->base + MTK_PPE_MIB_SER_R2);
136 +
137 + byte_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW, cnt_r0);
138 + byte_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH, cnt_r1);
139 + pkt_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R1_PKT_CNT_LOW, cnt_r1);
140 + pkt_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH, cnt_r2);
141 + *bytes = ((u64)byte_cnt_high << 32) | byte_cnt_low;
142 + *packets = (pkt_cnt_high << 16) | pkt_cnt_low;
143 +
144 + return 0;
145 +}
146 +
147 static void mtk_ppe_cache_clear(struct mtk_ppe *ppe)
148 {
149 ppe_set(ppe, MTK_PPE_CACHE_CTL, MTK_PPE_CACHE_CTL_CLEAR);
150 @@ -444,6 +484,13 @@ __mtk_foe_entry_clear(struct mtk_ppe *pp
151 hwe->ib1 &= ~MTK_FOE_IB1_STATE;
152 hwe->ib1 |= FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_INVALID);
153 dma_wmb();
154 + if (ppe->accounting) {
155 + struct mtk_foe_accounting *acct;
156 +
157 + acct = ppe->acct_table + entry->hash * sizeof(*acct);
158 + acct->packets = 0;
159 + acct->bytes = 0;
160 + }
161 }
162 entry->hash = 0xffff;
163
164 @@ -551,6 +598,9 @@ __mtk_foe_entry_commit(struct mtk_ppe *p
165 wmb();
166 hwe->ib1 = entry->ib1;
167
168 + if (ppe->accounting)
169 + *mtk_foe_entry_ib2(eth, hwe) |= MTK_FOE_IB2_MIB_CNT;
170 +
171 dma_wmb();
172
173 mtk_ppe_cache_clear(ppe);
174 @@ -716,14 +766,42 @@ int mtk_foe_entry_idle_time(struct mtk_p
175 return __mtk_foe_entry_idle_time(ppe, entry->data.ib1);
176 }
177
178 +struct mtk_foe_accounting *mtk_foe_entry_get_mib(struct mtk_ppe *ppe, u32 index,
179 + struct mtk_foe_accounting *diff)
180 +{
181 + struct mtk_foe_accounting *acct;
182 + int size = sizeof(struct mtk_foe_accounting);
183 + u64 bytes, packets;
184 +
185 + if (!ppe->accounting)
186 + return NULL;
187 +
188 + if (mtk_mib_entry_read(ppe, index, &bytes, &packets))
189 + return NULL;
190 +
191 + acct = ppe->acct_table + index * size;
192 +
193 + acct->bytes += bytes;
194 + acct->packets += packets;
195 +
196 + if (diff) {
197 + diff->bytes = bytes;
198 + diff->packets = packets;
199 + }
200 +
201 + return acct;
202 +}
203 +
204 struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base,
205 - int version, int index)
206 + int version, int index, bool accounting)
207 {
208 const struct mtk_soc_data *soc = eth->soc;
209 struct device *dev = eth->dev;
210 struct mtk_ppe *ppe;
211 u32 foe_flow_size;
212 void *foe;
213 + struct mtk_mib_entry *mib;
214 + struct mtk_foe_accounting *acct;
215
216 ppe = devm_kzalloc(dev, sizeof(*ppe), GFP_KERNEL);
217 if (!ppe)
218 @@ -738,6 +816,7 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_
219 ppe->eth = eth;
220 ppe->dev = dev;
221 ppe->version = version;
222 + ppe->accounting = accounting;
223
224 foe = dmam_alloc_coherent(ppe->dev,
225 MTK_PPE_ENTRIES * soc->foe_entry_size,
226 @@ -753,6 +832,25 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_
227 if (!ppe->foe_flow)
228 return NULL;
229
230 + if (accounting) {
231 + mib = dmam_alloc_coherent(ppe->dev, MTK_PPE_ENTRIES * sizeof(*mib),
232 + &ppe->mib_phys, GFP_KERNEL);
233 + if (!mib)
234 + return NULL;
235 +
236 + memset(mib, 0, MTK_PPE_ENTRIES * sizeof(*mib));
237 +
238 + ppe->mib_table = mib;
239 +
240 + acct = devm_kzalloc(dev, MTK_PPE_ENTRIES * sizeof(*acct),
241 + GFP_KERNEL);
242 +
243 + if (!acct)
244 + return NULL;
245 +
246 + ppe->acct_table = acct;
247 + }
248 +
249 mtk_ppe_debugfs_init(ppe, index);
250
251 return ppe;
252 @@ -867,6 +965,16 @@ void mtk_ppe_start(struct mtk_ppe *ppe)
253 ppe_w32(ppe, MTK_PPE_DEFAULT_CPU_PORT1, 0xcb777);
254 ppe_w32(ppe, MTK_PPE_SBW_CTRL, 0x7f);
255 }
256 +
257 + if (ppe->accounting && ppe->mib_phys) {
258 + ppe_w32(ppe, MTK_PPE_MIB_TB_BASE, ppe->mib_phys);
259 + ppe_m32(ppe, MTK_PPE_MIB_CFG, MTK_PPE_MIB_CFG_EN,
260 + MTK_PPE_MIB_CFG_EN);
261 + ppe_m32(ppe, MTK_PPE_MIB_CFG, MTK_PPE_MIB_CFG_RD_CLR,
262 + MTK_PPE_MIB_CFG_RD_CLR);
263 + ppe_m32(ppe, MTK_PPE_MIB_CACHE_CTL, MTK_PPE_MIB_CACHE_CTL_EN,
264 + MTK_PPE_MIB_CFG_RD_CLR);
265 + }
266 }
267
268 int mtk_ppe_stop(struct mtk_ppe *ppe)
269 --- a/drivers/net/ethernet/mediatek/mtk_ppe.h
270 +++ b/drivers/net/ethernet/mediatek/mtk_ppe.h
271 @@ -57,6 +57,7 @@ enum {
272 #define MTK_FOE_IB2_MULTICAST BIT(8)
273
274 #define MTK_FOE_IB2_WDMA_QID2 GENMASK(13, 12)
275 +#define MTK_FOE_IB2_MIB_CNT BIT(15)
276 #define MTK_FOE_IB2_WDMA_DEVIDX BIT(16)
277 #define MTK_FOE_IB2_WDMA_WINFO BIT(17)
278
279 @@ -284,16 +285,34 @@ struct mtk_flow_entry {
280 unsigned long cookie;
281 };
282
283 +struct mtk_mib_entry {
284 + u32 byt_cnt_l;
285 + u16 byt_cnt_h;
286 + u32 pkt_cnt_l;
287 + u8 pkt_cnt_h;
288 + u8 _rsv0;
289 + u32 _rsv1;
290 +} __packed;
291 +
292 +struct mtk_foe_accounting {
293 + u64 bytes;
294 + u64 packets;
295 +};
296 +
297 struct mtk_ppe {
298 struct mtk_eth *eth;
299 struct device *dev;
300 void __iomem *base;
301 int version;
302 char dirname[5];
303 + bool accounting;
304
305 void *foe_table;
306 dma_addr_t foe_phys;
307
308 + struct mtk_mib_entry *mib_table;
309 + dma_addr_t mib_phys;
310 +
311 u16 foe_check_time[MTK_PPE_ENTRIES];
312 struct hlist_head *foe_flow;
313
314 @@ -303,7 +322,7 @@ struct mtk_ppe {
315 };
316
317 struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base,
318 - int version, int index);
319 + int version, int index, bool accounting);
320 void mtk_ppe_start(struct mtk_ppe *ppe);
321 int mtk_ppe_stop(struct mtk_ppe *ppe);
322
323 @@ -354,5 +373,7 @@ int mtk_foe_entry_commit(struct mtk_ppe
324 void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry);
325 int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry);
326 int mtk_ppe_debugfs_init(struct mtk_ppe *ppe, int index);
327 +struct mtk_foe_accounting *mtk_foe_entry_get_mib(struct mtk_ppe *ppe, u32 index,
328 + struct mtk_foe_accounting *diff);
329
330 #endif
331 --- a/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c
332 +++ b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c
333 @@ -82,6 +82,7 @@ mtk_ppe_debugfs_foe_show(struct seq_file
334 struct mtk_foe_entry *entry = mtk_foe_get_entry(ppe, i);
335 struct mtk_foe_mac_info *l2;
336 struct mtk_flow_addr_info ai = {};
337 + struct mtk_foe_accounting *acct;
338 unsigned char h_source[ETH_ALEN];
339 unsigned char h_dest[ETH_ALEN];
340 int type, state;
341 @@ -95,6 +96,8 @@ mtk_ppe_debugfs_foe_show(struct seq_file
342 if (bind && state != MTK_FOE_STATE_BIND)
343 continue;
344
345 + acct = mtk_foe_entry_get_mib(ppe, i, NULL);
346 +
347 type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1);
348 seq_printf(m, "%05x %s %7s", i,
349 mtk_foe_entry_state_str(state),
350 @@ -153,9 +156,11 @@ mtk_ppe_debugfs_foe_show(struct seq_file
351 *((__be16 *)&h_dest[4]) = htons(l2->dest_mac_lo);
352
353 seq_printf(m, " eth=%pM->%pM etype=%04x"
354 - " vlan=%d,%d ib1=%08x ib2=%08x\n",
355 + " vlan=%d,%d ib1=%08x ib2=%08x"
356 + " packets=%lld bytes=%lld\n",
357 h_source, h_dest, ntohs(l2->etype),
358 - l2->vlan1, l2->vlan2, entry->ib1, ib2);
359 + l2->vlan1, l2->vlan2, entry->ib1, ib2,
360 + acct->packets, acct->bytes);
361 }
362
363 return 0;
364 --- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
365 +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
366 @@ -491,6 +491,7 @@ static int
367 mtk_flow_offload_stats(struct mtk_eth *eth, struct flow_cls_offload *f)
368 {
369 struct mtk_flow_entry *entry;
370 + struct mtk_foe_accounting diff;
371 u32 idle;
372
373 entry = rhashtable_lookup(&eth->flow_table, &f->cookie,
374 @@ -501,6 +502,12 @@ mtk_flow_offload_stats(struct mtk_eth *e
375 idle = mtk_foe_entry_idle_time(eth->ppe[entry->ppe_index], entry);
376 f->stats.lastused = jiffies - idle * HZ;
377
378 + if (entry->hash != 0xFFFF) {
379 + mtk_foe_entry_get_mib(eth->ppe[entry->ppe_index], entry->hash, &diff);
380 + f->stats.pkts += diff.packets;
381 + f->stats.bytes += diff.bytes;
382 + }
383 +
384 return 0;
385 }
386
387 --- a/drivers/net/ethernet/mediatek/mtk_ppe_regs.h
388 +++ b/drivers/net/ethernet/mediatek/mtk_ppe_regs.h
389 @@ -143,6 +143,20 @@ enum {
390
391 #define MTK_PPE_MIB_TB_BASE 0x338
392
393 +#define MTK_PPE_MIB_SER_CR 0x33C
394 +#define MTK_PPE_MIB_SER_CR_ST BIT(16)
395 +#define MTK_PPE_MIB_SER_CR_ADDR GENMASK(13, 0)
396 +
397 +#define MTK_PPE_MIB_SER_R0 0x340
398 +#define MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW GENMASK(31, 0)
399 +
400 +#define MTK_PPE_MIB_SER_R1 0x344
401 +#define MTK_PPE_MIB_SER_R1_PKT_CNT_LOW GENMASK(31, 16)
402 +#define MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH GENMASK(15, 0)
403 +
404 +#define MTK_PPE_MIB_SER_R2 0x348
405 +#define MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH GENMASK(23, 0)
406 +
407 #define MTK_PPE_MIB_CACHE_CTL 0x350
408 #define MTK_PPE_MIB_CACHE_CTL_EN BIT(0)
409 #define MTK_PPE_MIB_CACHE_CTL_FLUSH BIT(2)