blob: ed90d2c39e4c94e513a6f1095d10e882216286a9 [file] [log] [blame]
developerbc6a6a32022-07-19 11:03:07 +08001diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
2index 4f53794..dc5d050 100644
3--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
4+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
5@@ -3944,7 +3944,8 @@ static int mtk_probe(struct platform_device *pdev)
6 for (i = 0; i < eth->ppe_num; i++) {
7 eth->ppe[i] = mtk_ppe_init(eth,
8 eth->base + MTK_ETH_PPE_BASE + i * 0x400,
9- 2, eth->soc->hash_way, i);
10+ 2, eth->soc->hash_way, i,
11+ eth->soc->has_accounting);
12 if (!eth->ppe[i]) {
13 err = -ENOMEM;
14 goto err_free_dev;
15@@ -4057,6 +4058,7 @@ static const struct mtk_soc_data mt2701_data = {
16 .required_clks = MT7623_CLKS_BITMAP,
17 .required_pctl = true,
18 .has_sram = false,
19+ .has_accounting = false,
20 .hash_way = 2,
21 .offload_version = 2,
developer16b22152023-06-01 13:48:39 +080022 .rss_num = 0,
developerbc6a6a32022-07-19 11:03:07 +080023@@ -4073,6 +4075,7 @@ static const struct mtk_soc_data mt7621_data = {
24 .required_clks = MT7621_CLKS_BITMAP,
25 .required_pctl = false,
26 .has_sram = false,
27+ .has_accounting = false,
28 .hash_way = 2,
29 .offload_version = 2,
developer16b22152023-06-01 13:48:39 +080030 .rss_num = 0,
developerbc6a6a32022-07-19 11:03:07 +080031@@ -4090,6 +4093,7 @@ static const struct mtk_soc_data mt7622_data = {
32 .required_clks = MT7622_CLKS_BITMAP,
33 .required_pctl = false,
34 .has_sram = false,
35+ .has_accounting = true,
36 .hash_way = 2,
37 .offload_version = 2,
developer16b22152023-06-01 13:48:39 +080038 .rss_num = 0,
developerbc6a6a32022-07-19 11:03:07 +080039@@ -4106,6 +4110,7 @@ static const struct mtk_soc_data mt7623_data = {
40 .required_clks = MT7623_CLKS_BITMAP,
41 .required_pctl = true,
42 .has_sram = false,
43+ .has_accounting = false,
44 .hash_way = 2,
45 .offload_version = 2,
developer16b22152023-06-01 13:48:39 +080046 .rss_num = 0,
developerbc6a6a32022-07-19 11:03:07 +080047@@ -4123,6 +4128,7 @@ static const struct mtk_soc_data mt7629_data = {
48 .required_clks = MT7629_CLKS_BITMAP,
49 .required_pctl = false,
50 .has_sram = false,
51+ .has_accounting = true,
developer16b22152023-06-01 13:48:39 +080052 .rss_num = 0,
developerbc6a6a32022-07-19 11:03:07 +080053 .txrx = {
54 .txd_size = sizeof(struct mtk_tx_dma),
developerbc6a6a32022-07-19 11:03:07 +080055@@ -4138,6 +4144,7 @@ static const struct mtk_soc_data mt7986_data = {
56 .required_clks = MT7986_CLKS_BITMAP,
57 .required_pctl = false,
58 .has_sram = true,
59+ .has_accounting = true,
60 .hash_way = 4,
61 .offload_version = 2,
developer16b22152023-06-01 13:48:39 +080062 .rss_num = 0,
developerbc6a6a32022-07-19 11:03:07 +080063@@ -4155,6 +4162,7 @@ static const struct mtk_soc_data mt7981_data = {
64 .required_clks = MT7981_CLKS_BITMAP,
65 .required_pctl = false,
66 .has_sram = true,
67+ .has_accounting = true,
68 .hash_way = 4,
69 .offload_version = 2,
developer16b22152023-06-01 13:48:39 +080070 .rss_num = 0,
developerbc6a6a32022-07-19 11:03:07 +080071@@ -4171,6 +4179,7 @@ static const struct mtk_soc_data rt5350_data = {
72 .required_clks = MT7628_CLKS_BITMAP,
73 .required_pctl = false,
74 .has_sram = false,
75+ .has_accounting = false,
developer16b22152023-06-01 13:48:39 +080076 .rss_num = 0,
developerbc6a6a32022-07-19 11:03:07 +080077 .txrx = {
78 .txd_size = sizeof(struct mtk_tx_dma),
developerbc6a6a32022-07-19 11:03:07 +080079diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
80index f659633..5e16fa8 100644
81--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
82+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
83@@ -1213,6 +1213,7 @@ struct mtk_soc_data {
84 u8 offload_version;
85 netdev_features_t hw_features;
86 bool has_sram;
87+ bool has_accounting;
88 struct {
89 u32 txd_size;
90 u32 rxd_size;
91diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
92index 918aa22..8c036cd 100755
93--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
94+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
95@@ -74,6 +74,46 @@ static int mtk_ppe_wait_busy(struct mtk_ppe *ppe)
96 return ret;
97 }
98
99+static int mtk_ppe_mib_wait_busy(struct mtk_ppe *ppe)
100+{
101+ int ret;
102+ u32 val;
103+
104+ ret = readl_poll_timeout(ppe->base + MTK_PPE_MIB_SER_CR, val,
105+ !(val & MTK_PPE_MIB_SER_CR_ST),
106+ 20, MTK_PPE_WAIT_TIMEOUT_US);
107+
108+ if (ret)
109+ dev_err(ppe->dev, "MIB table busy");
110+
111+ return ret;
112+}
113+
114+int mtk_mib_entry_read(struct mtk_ppe *ppe, u16 index, u64 *bytes, u64 *packets)
115+{
116+ u32 val, cnt_r0, cnt_r1, cnt_r2;
117+ u32 byte_cnt_low, byte_cnt_high, pkt_cnt_low, pkt_cnt_high;
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+ if (mtk_ppe_mib_wait_busy(ppe))
123+ return -ETIMEDOUT;
124+
125+ cnt_r0 = readl(ppe->base + MTK_PPE_MIB_SER_R0);
126+ cnt_r1 = readl(ppe->base + MTK_PPE_MIB_SER_R1);
127+ cnt_r2 = readl(ppe->base + MTK_PPE_MIB_SER_R2);
128+
129+ byte_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW, cnt_r0);
130+ byte_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH, cnt_r1);
131+ pkt_cnt_low = FIELD_GET(MTK_PPE_MIB_SER_R1_PKT_CNT_LOW, cnt_r1);
132+ pkt_cnt_high = FIELD_GET(MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH, cnt_r2);
133+ *bytes = ((u64)byte_cnt_high << 32) | byte_cnt_low;
134+ *packets = (pkt_cnt_high << 16) | pkt_cnt_low;
135+
136+ return 0;
137+}
138+
139 static void mtk_ppe_cache_clear(struct mtk_ppe *ppe)
140 {
141 ppe_set(ppe, MTK_PPE_CACHE_CTL, MTK_PPE_CACHE_CTL_CLEAR);
developer18a49a22023-03-03 13:45:06 +0800142@@ -412,7 +452,19 @@ __mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry)
developerbc6a6a32022-07-19 11:03:07 +0800143 MTK_FOE_STATE_INVALID);
144 dma_wmb();
developer18a49a22023-03-03 13:45:06 +0800145 mtk_ppe_cache_clear(ppe);
developerbc6a6a32022-07-19 11:03:07 +0800146+
147+ if (ppe->accounting) {
developerae582382023-02-03 09:08:52 +0800148+ struct mtk_foe_accounting *acct, *acct_updated;
developerbc6a6a32022-07-19 11:03:07 +0800149+
150+ acct = ppe->acct_table + entry->hash * sizeof(*acct);
151+ acct->packets = 0;
152+ acct->bytes = 0;
developerae582382023-02-03 09:08:52 +0800153+
154+ acct_updated = ppe->acct_updated_table + entry->hash * sizeof(*acct_updated);
155+ acct_updated->packets = 0;
156+ acct_updated->bytes = 0;
developerbc6a6a32022-07-19 11:03:07 +0800157+ }
158 }
159 entry->hash = 0xffff;
160
161 if (entry->type != MTK_FLOW_TYPE_L2_SUBFLOW)
162@@ -513,6 +560,16 @@ __mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_foe_entry *entry,
163 wmb();
164 hwe->ib1 = entry->ib1;
165
166+ if (ppe->accounting) {
167+ int type;
168+
169+ type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1);
170+ if (type >= MTK_PPE_PKT_TYPE_IPV4_DSLITE)
171+ hwe->ipv6.ib2 |= MTK_FOE_IB2_MIB_CNT;
172+ else
173+ hwe->ipv4.ib2 |= MTK_FOE_IB2_MIB_CNT;
174+ }
175+
176 dma_wmb();
177
178 mtk_ppe_cache_clear(ppe);
179@@ -618,8 +675,6 @@ void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash)
180 }
181
182 if (found || !mtk_flow_entry_match(entry, hwe)) {
183- if (entry->hash != 0xffff)
184- entry->hash = 0xffff;
185 continue;
186 }
187
developerae582382023-02-03 09:08:52 +0800188@@ -676,12 +731,44 @@ int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry)
developerbc6a6a32022-07-19 11:03:07 +0800189 return __mtk_foe_entry_idle_time(ppe, entry->data.ib1);
190 }
191
192-struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int version, int way, int id)
193+struct mtk_foe_accounting *mtk_foe_entry_get_mib(struct mtk_ppe *ppe, u32 index, struct mtk_foe_accounting *diff)
194+{
developerae582382023-02-03 09:08:52 +0800195+ struct mtk_foe_accounting *acct, *acct_updated;
developerbc6a6a32022-07-19 11:03:07 +0800196+ int size = sizeof(struct mtk_foe_accounting);
197+ u64 bytes, packets;
198+
199+ if (!ppe->accounting)
200+ return NULL;
201+
202+ if (mtk_mib_entry_read(ppe, index, &bytes, &packets))
203+ return NULL;
204+
205+ acct = ppe->acct_table + index * size;
206+
207+ acct->bytes += bytes;
208+ acct->packets += packets;
209+
210+ if (diff) {
developerae582382023-02-03 09:08:52 +0800211+ acct_updated = ppe->acct_updated_table + index * size;
212+
213+ diff->bytes = acct->bytes - acct_updated->bytes;
214+ diff->packets = acct->packets - acct_updated->packets;
215+ acct_updated->bytes += diff->bytes;
216+ acct_updated->packets += diff->packets;
developerbc6a6a32022-07-19 11:03:07 +0800217+ }
218+
219+ return acct;
220+}
221+
222+struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int version, int way, int id,
223+ int accounting)
224 {
225 struct device *dev = eth->dev;
226 struct mtk_foe_entry *foe;
227+ struct mtk_mib_entry *mib;
228 struct mtk_ppe *ppe;
229 struct hlist_head *flow;
developerae582382023-02-03 09:08:52 +0800230+ struct mtk_foe_accounting *acct, *acct_updated;
developerbc6a6a32022-07-19 11:03:07 +0800231
232 ppe = devm_kzalloc(dev, sizeof(*ppe), GFP_KERNEL);
233 if (!ppe)
234@@ -698,6 +781,7 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int versio
235 ppe->version = version;
236 ppe->way = way;
237 ppe->id = id;
238+ ppe->accounting = accounting;
239
240 foe = dmam_alloc_coherent(ppe->dev, MTK_PPE_ENTRIES * sizeof(*foe),
241 &ppe->foe_phys, GFP_KERNEL);
developerae582382023-02-03 09:08:52 +0800242@@ -713,6 +797,31 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int versio
developerbc6a6a32022-07-19 11:03:07 +0800243
244 ppe->foe_flow = flow;
245
246+ if (accounting) {
247+ mib = dmam_alloc_coherent(ppe->dev, MTK_PPE_ENTRIES * sizeof(*mib),
248+ &ppe->mib_phys, GFP_KERNEL);
249+ if (!foe)
250+ return NULL;
251+
252+ memset(mib, 0, MTK_PPE_ENTRIES * sizeof(*mib));
253+
254+ ppe->mib_table = mib;
255+
256+ acct = devm_kzalloc(dev, MTK_PPE_ENTRIES * sizeof(*acct),
257+ GFP_KERNEL);
258+ if (!acct)
259+ return NULL;
260+
261+ ppe->acct_table = acct;
developerae582382023-02-03 09:08:52 +0800262+
263+ acct_updated = devm_kzalloc(dev, MTK_PPE_ENTRIES * sizeof(*acct_updated),
264+ GFP_KERNEL);
265+ if (!acct_updated)
266+ return NULL;
267+
268+ ppe->acct_updated_table = acct_updated;
developerbc6a6a32022-07-19 11:03:07 +0800269+ }
270+
271 return ppe;
272 }
273
274@@ -811,6 +949,13 @@ int mtk_ppe_start(struct mtk_ppe *ppe)
275 ppe_w32(ppe, MTK_PPE_DEFAULT_CPU_PORT1, 0xcb777);
276 ppe_w32(ppe, MTK_PPE_SBW_CTRL, 0x7f);
277
278+ if (ppe->accounting && ppe->mib_phys) {
279+ ppe_w32(ppe, MTK_PPE_MIB_TB_BASE, ppe->mib_phys);
280+ ppe_m32(ppe, MTK_PPE_MIB_CFG, MTK_PPE_MIB_CFG_EN, MTK_PPE_MIB_CFG_EN);
281+ ppe_m32(ppe, MTK_PPE_MIB_CFG, MTK_PPE_MIB_CFG_RD_CLR, MTK_PPE_MIB_CFG_RD_CLR);
282+ ppe_m32(ppe, MTK_PPE_MIB_CACHE_CTL, MTK_PPE_MIB_CACHE_CTL_EN, MTK_PPE_MIB_CFG_RD_CLR);
283+ }
284+
285 return 0;
286 }
287
288diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.h b/drivers/net/ethernet/mediatek/mtk_ppe.h
289index 3d6928c..8076e5d 100644
290--- a/drivers/net/ethernet/mediatek/mtk_ppe.h
291+++ b/drivers/net/ethernet/mediatek/mtk_ppe.h
292@@ -270,6 +270,20 @@ struct mtk_flow_entry {
293 unsigned long cookie;
294 };
295
296+struct mtk_mib_entry {
297+ u32 byt_cnt_l;
298+ u16 byt_cnt_h;
299+ u32 pkt_cnt_l;
300+ u8 pkt_cnt_h;
301+ u8 _rsv0;
302+ u32 _rsv1;
303+} __packed;
304+
305+struct mtk_foe_accounting {
306+ u64 bytes;
307+ u64 packets;
308+};
309+
310 struct mtk_ppe {
311 struct mtk_eth *eth;
312 struct device *dev;
313@@ -277,10 +291,14 @@ struct mtk_ppe {
314 int version;
315 int id;
316 int way;
317+ int accounting;
318
319 struct mtk_foe_entry *foe_table;
320 dma_addr_t foe_phys;
321
322+ struct mtk_mib_entry *mib_table;
323+ dma_addr_t mib_phys;
324+
325 u16 foe_check_time[MTK_PPE_ENTRIES];
326 struct hlist_head *foe_flow;
327
developerae582382023-02-03 09:08:52 +0800328@@ -289,7 +307,9 @@ struct mtk_ppe {
developerbc6a6a32022-07-19 11:03:07 +0800329 void *acct_table;
developerae582382023-02-03 09:08:52 +0800330+ void *acct_updated_table;
developerbc6a6a32022-07-19 11:03:07 +0800331 };
332
333-struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int version, int way, int id);
334+struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int version, int way, int id,
335+ int accounting);
336 int mtk_ppe_start(struct mtk_ppe *ppe);
337 int mtk_ppe_stop(struct mtk_ppe *ppe);
338
339@@ -340,5 +359,6 @@ int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
340 int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry);
341 void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry);
342 int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry);
343+struct mtk_foe_accounting *mtk_foe_entry_get_mib(struct mtk_ppe *ppe, u32 index, struct mtk_foe_accounting *diff);
344
345 #endif
346diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c
347index f4ebe59..d713e2e 100644
348--- a/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c
349+++ b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c
350@@ -81,6 +81,7 @@ mtk_ppe_debugfs_foe_show(struct seq_file *m, struct mtk_ppe *ppe, bool bind)
351 struct mtk_foe_entry *entry = &ppe->foe_table[i];
352 struct mtk_foe_mac_info *l2;
353 struct mtk_flow_addr_info ai = {};
354+ struct mtk_foe_accounting *acct;
355 unsigned char h_source[ETH_ALEN];
356 unsigned char h_dest[ETH_ALEN];
357 int type, state;
358@@ -94,6 +95,8 @@ mtk_ppe_debugfs_foe_show(struct seq_file *m, struct mtk_ppe *ppe, bool bind)
359 if (bind && state != MTK_FOE_STATE_BIND)
360 continue;
361
362+ acct = mtk_foe_entry_get_mib(ppe, i, NULL);
363+
364 type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1);
365 seq_printf(m, "%05x %s %7s", i,
366 mtk_foe_entry_state_str(state),
367@@ -154,9 +157,12 @@ mtk_ppe_debugfs_foe_show(struct seq_file *m, struct mtk_ppe *ppe, bool bind)
368 *((__be16 *)&h_dest[4]) = htons(l2->dest_mac_lo);
369
370 seq_printf(m, " eth=%pM->%pM etype=%04x"
371- " vlan=%d,%d ib1=%08x ib2=%08x\n",
372+ " vlan=%d,%d ib1=%08x ib2=%08x"
373+ " packets=%lld bytes=%lld\n",
374 h_source, h_dest, ntohs(l2->etype),
375- l2->vlan1, l2->vlan2, entry->ib1, ib2);
376+ l2->vlan1, l2->vlan2, entry->ib1, ib2,
377+ acct->packets, acct->bytes
378+ );
379 }
380
381 return 0;
382diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
383index 2f7d76d..f258539 100755
384--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
385+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
386@@ -504,6 +504,7 @@ static int
387 mtk_flow_offload_stats(struct mtk_eth *eth, struct flow_cls_offload *f)
388 {
389 struct mtk_flow_entry *entry;
390+ struct mtk_foe_accounting diff;
391 u32 idle;
392 int i;
393
394@@ -516,6 +517,12 @@ mtk_flow_offload_stats(struct mtk_eth *eth, struct flow_cls_offload *f)
395 idle = mtk_foe_entry_idle_time(eth->ppe[i], entry);
396 f->stats.lastused = jiffies - idle * HZ;
397
398+ if (entry->hash != 0xFFFF) {
399+ mtk_foe_entry_get_mib(eth->ppe[i], entry->hash, &diff);
400+ f->stats.pkts += diff.packets;
401+ f->stats.bytes += diff.bytes;
402+ }
403+
404 return 0;
405 }
406
407diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_regs.h b/drivers/net/ethernet/mediatek/mtk_ppe_regs.h
408index d319f18..9eb7a0d 100644
409--- a/drivers/net/ethernet/mediatek/mtk_ppe_regs.h
410+++ b/drivers/net/ethernet/mediatek/mtk_ppe_regs.h
411@@ -145,6 +146,20 @@ enum {
412
413 #define MTK_PPE_MIB_TB_BASE 0x338
414
415+#define MTK_PPE_MIB_SER_CR 0x33C
416+#define MTK_PPE_MIB_SER_CR_ST BIT(16)
417+#define MTK_PPE_MIB_SER_CR_ADDR GENMASK(13, 0)
418+
419+#define MTK_PPE_MIB_SER_R0 0x340
420+#define MTK_PPE_MIB_SER_R0_BYTE_CNT_LOW GENMASK(31, 0)
421+
422+#define MTK_PPE_MIB_SER_R1 0x344
423+#define MTK_PPE_MIB_SER_R1_PKT_CNT_LOW GENMASK(31, 16)
424+#define MTK_PPE_MIB_SER_R1_BYTE_CNT_HIGH GENMASK(15, 0)
425+
426+#define MTK_PPE_MIB_SER_R2 0x348
427+#define MTK_PPE_MIB_SER_R2_PKT_CNT_HIGH GENMASK(23, 0)
428+
429 #define MTK_PPE_MIB_CACHE_CTL 0x350
430 #define MTK_PPE_MIB_CACHE_CTL_EN BIT(0)
431 #define MTK_PPE_MIB_CACHE_CTL_FLUSH BIT(2)
432diff --git a/net/netfilter/xt_FLOWOFFLOAD.c b/net/netfilter/xt_FLOWOFFLOAD.c
433index 8547f4a..c175e4d 100644
434--- a/net/netfilter/xt_FLOWOFFLOAD.c
435+++ b/net/netfilter/xt_FLOWOFFLOAD.c
436@@ -700,12 +781,12 @@ static int __init xt_flowoffload_tg_init(void)
437 if (ret)
438 goto cleanup;
439
440- flowtable[1].ft.flags = NF_FLOWTABLE_HW_OFFLOAD;
441+ flowtable[1].ft.flags = NF_FLOWTABLE_HW_OFFLOAD | NF_FLOWTABLE_COUNTER;
442
443 ret = xt_register_target(&offload_tg_reg);
444 if (ret)
445 goto cleanup2;
446
447 return 0;
448
449 cleanup2: