blob: 5db9291852ac6518c16e953c009bc914567751dd [file] [log] [blame]
developerfd40db22021-04-29 10:08:25 +08001/* This program is free software; you can redistribute it and/or modify
2 * it under the terms of the GNU General Public License as published by
3 * the Free Software Foundation; version 2 of the License
4 *
5 * This program is distributed in the hope that it will be useful,
6 * but WITHOUT ANY WARRANTY; without even the implied warranty of
7 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8 * GNU General Public License for more details.
9 *
10 * Copyright (C) 2014-2016 Sean Wang <sean.wang@mediatek.com>
11 * Copyright (C) 2016-2017 John Crispin <blogic@openwrt.org>
12 */
13
14#include <linux/kernel.h>
15#include <linux/slab.h>
16#include <linux/dma-mapping.h>
17#include <linux/netdevice.h>
18#include <linux/iopoll.h>
developere8b7dfa2023-04-20 10:16:44 +080019#include <linux/inet.h>
20#include <net/ipv6.h>
developerfd40db22021-04-29 10:08:25 +080021
22#include "hnat.h"
23#include "nf_hnat_mtk.h"
24#include "../mtk_eth_soc.h"
25
26int dbg_entry_state = BIND;
27typedef int (*debugfs_write_func)(int par1);
28int debug_level;
29int dbg_cpu_reason;
30int hook_toggle;
31int mape_toggle;
developeraf07fad2021-11-19 17:53:42 +080032int qos_toggle;
developer47545a32022-11-15 16:06:58 +080033int qos_dl_toggle = 1;
34int qos_ul_toggle = 1;
developere8b7dfa2023-04-20 10:16:44 +080035int xlat_toggle;
36struct hnat_desc headroom[DEF_ETRY_NUM];
developerfd40db22021-04-29 10:08:25 +080037unsigned int dbg_cpu_reason_cnt[MAX_CRSN_NUM];
38
39static const char * const entry_state[] = { "INVALID", "UNBIND", "BIND", "FIN" };
40
41static const char * const packet_type[] = {
42 "IPV4_HNAPT", "IPV4_HNAT", "IPV6_1T_ROUTE", "IPV4_DSLITE",
43 "IPV6_3T_ROUTE", "IPV6_5T_ROUTE", "REV", "IPV6_6RD",
developer5ffc5f12022-10-25 18:51:46 +080044 "IPV4_MAP_T", "IPV4_MAP_E", "IPV6_HNAPT", "IPV6_HNAT",
developerfd40db22021-04-29 10:08:25 +080045};
46
47static uint8_t *show_cpu_reason(struct sk_buff *skb)
48{
49 static u8 buf[32];
developer577ad2f2022-11-28 10:33:36 +080050 int ret;
developerfd40db22021-04-29 10:08:25 +080051
52 switch (skb_hnat_reason(skb)) {
53 case TTL_0:
54 return "IPv4(IPv6) TTL(hop limit)\n";
55 case HAS_OPTION_HEADER:
56 return "Ipv4(IPv6) has option(extension) header\n";
57 case NO_FLOW_IS_ASSIGNED:
58 return "No flow is assigned\n";
59 case IPV4_WITH_FRAGMENT:
60 return "IPv4 HNAT doesn't support IPv4 /w fragment\n";
61 case IPV4_HNAPT_DSLITE_WITH_FRAGMENT:
62 return "IPv4 HNAPT/DS-Lite doesn't support IPv4 /w fragment\n";
63 case IPV4_HNAPT_DSLITE_WITHOUT_TCP_UDP:
64 return "IPv4 HNAPT/DS-Lite can't find TCP/UDP sport/dport\n";
65 case IPV6_5T_6RD_WITHOUT_TCP_UDP:
66 return "IPv6 5T-route/6RD can't find TCP/UDP sport/dport\n";
67 case TCP_FIN_SYN_RST:
68 return "Ingress packet is TCP fin/syn/rst\n";
69 case UN_HIT:
70 return "FOE Un-hit\n";
71 case HIT_UNBIND:
72 return "FOE Hit unbind\n";
73 case HIT_UNBIND_RATE_REACH:
74 return "FOE Hit unbind & rate reach\n";
75 case HIT_BIND_TCP_FIN:
76 return "Hit bind PPE TCP FIN entry\n";
77 case HIT_BIND_TTL_1:
78 return "Hit bind PPE entry and TTL(hop limit) = 1 and TTL(hot limit) - 1\n";
79 case HIT_BIND_WITH_VLAN_VIOLATION:
80 return "Hit bind and VLAN replacement violation\n";
81 case HIT_BIND_KEEPALIVE_UC_OLD_HDR:
82 return "Hit bind and keep alive with unicast old-header packet\n";
83 case HIT_BIND_KEEPALIVE_MC_NEW_HDR:
84 return "Hit bind and keep alive with multicast new-header packet\n";
85 case HIT_BIND_KEEPALIVE_DUP_OLD_HDR:
86 return "Hit bind and keep alive with duplicate old-header packet\n";
87 case HIT_BIND_FORCE_TO_CPU:
88 return "FOE Hit bind & force to CPU\n";
89 case HIT_BIND_EXCEED_MTU:
90 return "Hit bind and exceed MTU\n";
91 case HIT_BIND_MULTICAST_TO_CPU:
92 return "Hit bind multicast packet to CPU\n";
93 case HIT_BIND_MULTICAST_TO_GMAC_CPU:
94 return "Hit bind multicast packet to GMAC & CPU\n";
95 case HIT_PRE_BIND:
96 return "Pre bind\n";
97 }
98
developer577ad2f2022-11-28 10:33:36 +080099 ret = snprintf(buf, sizeof(buf), "CPU Reason Error - %X\n",
100 skb_hnat_entry(skb));
101 if (ret == strlen(buf))
102 return buf;
103 else
104 return "CPU Reason Error\n";
developerfd40db22021-04-29 10:08:25 +0800105}
106
107uint32_t foe_dump_pkt(struct sk_buff *skb)
108{
109 struct foe_entry *entry;
110
developer79359642021-07-27 14:29:10 +0800111 if (skb_hnat_entry(skb) >= hnat_priv->foe_etry_num ||
112 skb_hnat_ppe(skb) >= CFG_PPE_NUM)
113 return 1;
114
developer471f6562021-05-10 20:48:34 +0800115 entry = &hnat_priv->foe_table_cpu[skb_hnat_ppe(skb)][skb_hnat_entry(skb)];
developerfd40db22021-04-29 10:08:25 +0800116 pr_info("\nRx===<FOE_Entry=%d>=====\n", skb_hnat_entry(skb));
117 pr_info("RcvIF=%s\n", skb->dev->name);
developer471f6562021-05-10 20:48:34 +0800118 pr_info("PPE_ID=%d\n", skb_hnat_ppe(skb));
developerfd40db22021-04-29 10:08:25 +0800119 pr_info("FOE_Entry=%d\n", skb_hnat_entry(skb));
120 pr_info("CPU Reason=%s", show_cpu_reason(skb));
121 pr_info("ALG=%d\n", skb_hnat_alg(skb));
122 pr_info("SP=%d\n", skb_hnat_sport(skb));
123
124 /* some special alert occurred, so entry_num is useless (just skip it) */
125 if (skb_hnat_entry(skb) == 0x3fff)
126 return 1;
127
128 /* PPE: IPv4 packet=IPV4_HNAT IPv6 packet=IPV6_ROUTE */
129 if (IS_IPV4_GRP(entry)) {
130 __be32 saddr = htonl(entry->ipv4_hnapt.sip);
131 __be32 daddr = htonl(entry->ipv4_hnapt.dip);
132
133 pr_info("Information Block 1=%x\n",
134 entry->ipv4_hnapt.info_blk1);
135 pr_info("SIP=%pI4\n", &saddr);
136 pr_info("DIP=%pI4\n", &daddr);
137 pr_info("SPORT=%d\n", entry->ipv4_hnapt.sport);
138 pr_info("DPORT=%d\n", entry->ipv4_hnapt.dport);
139 pr_info("Information Block 2=%x\n",
140 entry->ipv4_hnapt.info_blk2);
141 pr_info("State = %s, proto = %s\n", entry->bfib1.state == 0 ?
142 "Invalid" : entry->bfib1.state == 1 ?
143 "Unbind" : entry->bfib1.state == 2 ?
144 "BIND" : entry->bfib1.state == 3 ?
145 "FIN" : "Unknown",
146 entry->ipv4_hnapt.bfib1.udp == 0 ?
147 "TCP" : entry->ipv4_hnapt.bfib1.udp == 1 ?
148 "UDP" : "Unknown");
149 } else if (IS_IPV6_GRP(entry)) {
150 pr_info("Information Block 1=%x\n",
151 entry->ipv6_5t_route.info_blk1);
152 pr_info("IPv6_SIP=%08X:%08X:%08X:%08X\n",
153 entry->ipv6_5t_route.ipv6_sip0,
154 entry->ipv6_5t_route.ipv6_sip1,
155 entry->ipv6_5t_route.ipv6_sip2,
156 entry->ipv6_5t_route.ipv6_sip3);
157 pr_info("IPv6_DIP=%08X:%08X:%08X:%08X\n",
158 entry->ipv6_5t_route.ipv6_dip0,
159 entry->ipv6_5t_route.ipv6_dip1,
160 entry->ipv6_5t_route.ipv6_dip2,
161 entry->ipv6_5t_route.ipv6_dip3);
162 pr_info("SPORT=%d\n", entry->ipv6_5t_route.sport);
163 pr_info("DPORT=%d\n", entry->ipv6_5t_route.dport);
164 pr_info("Information Block 2=%x\n",
165 entry->ipv6_5t_route.info_blk2);
166 pr_info("State = %s, proto = %s\n", entry->bfib1.state == 0 ?
167 "Invalid" : entry->bfib1.state == 1 ?
168 "Unbind" : entry->bfib1.state == 2 ?
169 "BIND" : entry->bfib1.state == 3 ?
170 "FIN" : "Unknown",
171 entry->ipv6_5t_route.bfib1.udp == 0 ?
172 "TCP" : entry->ipv6_5t_route.bfib1.udp == 1 ?
173 "UDP" : "Unknown");
174 } else {
175 pr_info("unknown Pkt_type=%d\n", entry->bfib1.pkt_type);
176 }
177
178 pr_info("==================================\n");
179 return 1;
180}
181
182uint32_t hnat_cpu_reason_cnt(struct sk_buff *skb)
183{
184 switch (skb_hnat_reason(skb)) {
185 case TTL_0:
186 dbg_cpu_reason_cnt[0]++;
187 return 0;
188 case HAS_OPTION_HEADER:
189 dbg_cpu_reason_cnt[1]++;
190 return 0;
191 case NO_FLOW_IS_ASSIGNED:
192 dbg_cpu_reason_cnt[2]++;
193 return 0;
194 case IPV4_WITH_FRAGMENT:
195 dbg_cpu_reason_cnt[3]++;
196 return 0;
197 case IPV4_HNAPT_DSLITE_WITH_FRAGMENT:
198 dbg_cpu_reason_cnt[4]++;
199 return 0;
200 case IPV4_HNAPT_DSLITE_WITHOUT_TCP_UDP:
201 dbg_cpu_reason_cnt[5]++;
202 return 0;
203 case IPV6_5T_6RD_WITHOUT_TCP_UDP:
204 dbg_cpu_reason_cnt[6]++;
205 return 0;
206 case TCP_FIN_SYN_RST:
207 dbg_cpu_reason_cnt[7]++;
208 return 0;
209 case UN_HIT:
210 dbg_cpu_reason_cnt[8]++;
211 return 0;
212 case HIT_UNBIND:
213 dbg_cpu_reason_cnt[9]++;
214 return 0;
215 case HIT_UNBIND_RATE_REACH:
216 dbg_cpu_reason_cnt[10]++;
217 return 0;
218 case HIT_BIND_TCP_FIN:
219 dbg_cpu_reason_cnt[11]++;
220 return 0;
221 case HIT_BIND_TTL_1:
222 dbg_cpu_reason_cnt[12]++;
223 return 0;
224 case HIT_BIND_WITH_VLAN_VIOLATION:
225 dbg_cpu_reason_cnt[13]++;
226 return 0;
227 case HIT_BIND_KEEPALIVE_UC_OLD_HDR:
228 dbg_cpu_reason_cnt[14]++;
229 return 0;
230 case HIT_BIND_KEEPALIVE_MC_NEW_HDR:
231 dbg_cpu_reason_cnt[15]++;
232 return 0;
233 case HIT_BIND_KEEPALIVE_DUP_OLD_HDR:
234 dbg_cpu_reason_cnt[16]++;
235 return 0;
236 case HIT_BIND_FORCE_TO_CPU:
237 dbg_cpu_reason_cnt[17]++;
238 return 0;
239 case HIT_BIND_EXCEED_MTU:
240 dbg_cpu_reason_cnt[18]++;
241 return 0;
242 case HIT_BIND_MULTICAST_TO_CPU:
243 dbg_cpu_reason_cnt[19]++;
244 return 0;
245 case HIT_BIND_MULTICAST_TO_GMAC_CPU:
246 dbg_cpu_reason_cnt[20]++;
247 return 0;
248 case HIT_PRE_BIND:
249 dbg_cpu_reason_cnt[21]++;
250 return 0;
251 }
252
253 return 0;
254}
255
256int hnat_set_usage(int level)
257{
258 debug_level = level;
259 pr_info("Read cpu_reason count: cat /sys/kernel/debug/hnat/cpu_reason\n\n");
260 pr_info("====================Advanced Settings====================\n");
261 pr_info("Usage: echo [type] [option] > /sys/kernel/debug/hnat/cpu_reason\n\n");
262 pr_info("Commands: [type] [option]\n");
263 pr_info(" 0 0~7 Set debug_level(0~7), current debug_level=%d\n",
264 debug_level);
265 pr_info(" 1 cpu_reason Track entries of the set cpu_reason\n");
266 pr_info(" Set type=1 will change debug_level=7\n");
267 pr_info("cpu_reason list:\n");
268 pr_info(" 2 IPv4(IPv6) TTL(hop limit) = 0\n");
269 pr_info(" 3 IPv4(IPv6) has option(extension) header\n");
270 pr_info(" 7 No flow is assigned\n");
271 pr_info(" 8 IPv4 HNAT doesn't support IPv4 /w fragment\n");
272 pr_info(" 9 IPv4 HNAPT/DS-Lite doesn't support IPv4 /w fragment\n");
273 pr_info(" 10 IPv4 HNAPT/DS-Lite can't find TCP/UDP sport/dport\n");
274 pr_info(" 11 IPv6 5T-route/6RD can't find TCP/UDP sport/dport\n");
275 pr_info(" 12 Ingress packet is TCP fin/syn/rst\n");
276 pr_info(" 13 FOE Un-hit\n");
277 pr_info(" 14 FOE Hit unbind\n");
278 pr_info(" 15 FOE Hit unbind & rate reach\n");
279 pr_info(" 16 Hit bind PPE TCP FIN entry\n");
280 pr_info(" 17 Hit bind PPE entry and TTL(hop limit) = 1\n");
281 pr_info(" 18 Hit bind and VLAN replacement violation\n");
282 pr_info(" 19 Hit bind and keep alive with unicast old-header packet\n");
283 pr_info(" 20 Hit bind and keep alive with multicast new-header packet\n");
284 pr_info(" 21 Hit bind and keep alive with duplicate old-header packet\n");
285 pr_info(" 22 FOE Hit bind & force to CPU\n");
286 pr_info(" 23 HIT_BIND_WITH_OPTION_HEADER\n");
287 pr_info(" 24 Switch clone multicast packet to CPU\n");
288 pr_info(" 25 Switch clone multicast packet to GMAC1 & CPU\n");
289 pr_info(" 26 HIT_PRE_BIND\n");
290 pr_info(" 27 HIT_BIND_PACKET_SAMPLING\n");
291 pr_info(" 28 Hit bind and exceed MTU\n");
292
293 return 0;
294}
295
296int hnat_cpu_reason(int cpu_reason)
297{
298 dbg_cpu_reason = cpu_reason;
299 debug_level = 7;
300 pr_info("show cpu reason = %d\n", cpu_reason);
301
302 return 0;
303}
304
305int entry_set_usage(int level)
306{
307 debug_level = level;
308 pr_info("Show all entries(default state=bind): cat /sys/kernel/debug/hnat/hnat_entry\n\n");
309 pr_info("====================Advanced Settings====================\n");
310 pr_info("Usage: echo [type] [option] > /sys/kernel/debug/hnat/hnat_entry\n\n");
311 pr_info("Commands: [type] [option]\n");
312 pr_info(" 0 0~7 Set debug_level(0~7), current debug_level=%d\n",
313 debug_level);
314 pr_info(" 1 0~3 Change tracking state\n");
315 pr_info(" (0:invalid; 1:unbind; 2:bind; 3:fin)\n");
developer471f6562021-05-10 20:48:34 +0800316 pr_info(" 2 <entry_idx> Show PPE0 specific foe entry info. of assigned <entry_idx>\n");
317 pr_info(" 3 <entry_idx> Delete PPE0 specific foe entry of assigned <entry_idx>\n");
318 pr_info(" 4 <entry_idx> Show PPE1 specific foe entry info. of assigned <entry_idx>\n");
319 pr_info(" 5 <entry_idx> Delete PPE1 specific foe entry of assigned <entry_idx>\n");
developer3fb8d472021-11-16 15:46:38 +0800320 pr_info(" When entry_idx is -1, clear all entries\n");
developerfd40db22021-04-29 10:08:25 +0800321
322 return 0;
323}
324
325int entry_set_state(int state)
326{
327 dbg_entry_state = state;
328 pr_info("ENTRY STATE = %s\n", dbg_entry_state == 0 ?
329 "Invalid" : dbg_entry_state == 1 ?
330 "Unbind" : dbg_entry_state == 2 ?
331 "BIND" : dbg_entry_state == 3 ?
332 "FIN" : "Unknown");
333 return 0;
334}
335
developer471f6562021-05-10 20:48:34 +0800336int wrapped_ppe0_entry_detail(int index) {
337 entry_detail(0, index);
338 return 0;
339}
340
341int wrapped_ppe1_entry_detail(int index) {
342 entry_detail(1, index);
343 return 0;
344}
345
developer4c32b7a2021-11-13 16:46:43 +0800346int entry_detail(u32 ppe_id, int index)
developerfd40db22021-04-29 10:08:25 +0800347{
348 struct foe_entry *entry;
349 struct mtk_hnat *h = hnat_priv;
350 u32 *p;
351 u32 i = 0;
352 u32 print_cnt;
353 unsigned char h_dest[ETH_ALEN];
354 unsigned char h_source[ETH_ALEN];
355 __be32 saddr, daddr, nsaddr, ndaddr;
356
developer471f6562021-05-10 20:48:34 +0800357 if (ppe_id >= CFG_PPE_NUM)
358 return -EINVAL;
359
developerc6227322021-07-09 10:52:53 +0800360 if (index < 0 || index >= h->foe_etry_num) {
361 pr_info("Invalid entry index\n");
362 return -EINVAL;
363 }
364
developer471f6562021-05-10 20:48:34 +0800365 entry = h->foe_table_cpu[ppe_id] + index;
developerfd40db22021-04-29 10:08:25 +0800366 saddr = htonl(entry->ipv4_hnapt.sip);
367 daddr = htonl(entry->ipv4_hnapt.dip);
368 nsaddr = htonl(entry->ipv4_hnapt.new_sip);
369 ndaddr = htonl(entry->ipv4_hnapt.new_dip);
370 p = (uint32_t *)entry;
developer471f6562021-05-10 20:48:34 +0800371 pr_info("==========<PPE_ID=%d, Flow Table Entry=%d (%p)>===============\n",
372 ppe_id, index, entry);
developerfd40db22021-04-29 10:08:25 +0800373 if (debug_level >= 2) {
374 print_cnt = 20;
375 for (i = 0; i < print_cnt; i++)
376 pr_info("%02d: %08X\n", i, *(p + i));
377 }
378 pr_info("-----------------<Flow Info>------------------\n");
379 pr_info("Information Block 1: %08X\n", entry->ipv4_hnapt.info_blk1);
380
381 if (IS_IPV4_HNAPT(entry)) {
382 pr_info("Information Block 2: %08X (FP=%d FQOS=%d QID=%d)",
383 entry->ipv4_hnapt.info_blk2,
384 entry->ipv4_hnapt.iblk2.dp,
385 entry->ipv4_hnapt.iblk2.fqos,
386 entry->ipv4_hnapt.iblk2.qid);
387 pr_info("Create IPv4 HNAPT entry\n");
388 pr_info("IPv4 Org IP/Port: %pI4:%d->%pI4:%d\n", &saddr,
389 entry->ipv4_hnapt.sport, &daddr,
390 entry->ipv4_hnapt.dport);
391 pr_info("IPv4 New IP/Port: %pI4:%d->%pI4:%d\n", &nsaddr,
392 entry->ipv4_hnapt.new_sport, &ndaddr,
393 entry->ipv4_hnapt.new_dport);
394 } else if (IS_IPV4_HNAT(entry)) {
395 pr_info("Information Block 2: %08X\n",
396 entry->ipv4_hnapt.info_blk2);
397 pr_info("Create IPv4 HNAT entry\n");
398 pr_info("IPv4 Org IP: %pI4->%pI4\n", &saddr, &daddr);
399 pr_info("IPv4 New IP: %pI4->%pI4\n", &nsaddr, &ndaddr);
400 } else if (IS_IPV4_DSLITE(entry)) {
developere8b7dfa2023-04-20 10:16:44 +0800401 pr_info("Information Block 2: %08X (FP=%d FQOS=%d QID=%d)",
402 entry->ipv4_dslite.info_blk2,
403 entry->ipv4_dslite.iblk2.dp,
404 entry->ipv4_dslite.iblk2.fqos,
405 entry->ipv4_dslite.iblk2.qid);
developerfd40db22021-04-29 10:08:25 +0800406 pr_info("Create IPv4 Ds-Lite entry\n");
407 pr_info("IPv4 Ds-Lite: %pI4:%d->%pI4:%d\n", &saddr,
408 entry->ipv4_dslite.sport, &daddr,
409 entry->ipv4_dslite.dport);
410 pr_info("EG DIPv6: %08X:%08X:%08X:%08X->%08X:%08X:%08X:%08X\n",
411 entry->ipv4_dslite.tunnel_sipv6_0,
412 entry->ipv4_dslite.tunnel_sipv6_1,
413 entry->ipv4_dslite.tunnel_sipv6_2,
414 entry->ipv4_dslite.tunnel_sipv6_3,
415 entry->ipv4_dslite.tunnel_dipv6_0,
416 entry->ipv4_dslite.tunnel_dipv6_1,
417 entry->ipv4_dslite.tunnel_dipv6_2,
418 entry->ipv4_dslite.tunnel_dipv6_3);
developerd35bbcc2022-09-28 22:46:01 +0800419#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
developerfd40db22021-04-29 10:08:25 +0800420 } else if (IS_IPV4_MAPE(entry)) {
developerd35bbcc2022-09-28 22:46:01 +0800421 nsaddr = htonl(entry->ipv4_mape.new_sip);
422 ndaddr = htonl(entry->ipv4_mape.new_dip);
developerfd40db22021-04-29 10:08:25 +0800423
424 pr_info("Information Block 2: %08X\n",
425 entry->ipv4_dslite.info_blk2);
426 pr_info("Create IPv4 MAP-E entry\n");
427 pr_info("IPv4 MAP-E Org IP/Port: %pI4:%d->%pI4:%d\n",
428 &saddr, entry->ipv4_dslite.sport,
429 &daddr, entry->ipv4_dslite.dport);
430 pr_info("IPv4 MAP-E New IP/Port: %pI4:%d->%pI4:%d\n",
developerd35bbcc2022-09-28 22:46:01 +0800431 &nsaddr, entry->ipv4_mape.new_sport,
432 &ndaddr, entry->ipv4_mape.new_dport);
developerfd40db22021-04-29 10:08:25 +0800433 pr_info("EG DIPv6: %08X:%08X:%08X:%08X->%08X:%08X:%08X:%08X\n",
434 entry->ipv4_dslite.tunnel_sipv6_0,
435 entry->ipv4_dslite.tunnel_sipv6_1,
436 entry->ipv4_dslite.tunnel_sipv6_2,
437 entry->ipv4_dslite.tunnel_sipv6_3,
438 entry->ipv4_dslite.tunnel_dipv6_0,
439 entry->ipv4_dslite.tunnel_dipv6_1,
440 entry->ipv4_dslite.tunnel_dipv6_2,
441 entry->ipv4_dslite.tunnel_dipv6_3);
442#endif
443 } else if (IS_IPV6_3T_ROUTE(entry)) {
444 pr_info("Information Block 2: %08X\n",
445 entry->ipv6_3t_route.info_blk2);
446 pr_info("Create IPv6 3-Tuple entry\n");
447 pr_info("ING SIPv6->DIPv6: %08X:%08X:%08X:%08X-> %08X:%08X:%08X:%08X (Prot=%d)\n",
448 entry->ipv6_3t_route.ipv6_sip0,
449 entry->ipv6_3t_route.ipv6_sip1,
450 entry->ipv6_3t_route.ipv6_sip2,
451 entry->ipv6_3t_route.ipv6_sip3,
452 entry->ipv6_3t_route.ipv6_dip0,
453 entry->ipv6_3t_route.ipv6_dip1,
454 entry->ipv6_3t_route.ipv6_dip2,
455 entry->ipv6_3t_route.ipv6_dip3,
456 entry->ipv6_3t_route.prot);
457 } else if (IS_IPV6_5T_ROUTE(entry)) {
458 pr_info("Information Block 2: %08X\n",
459 entry->ipv6_5t_route.info_blk2);
460 pr_info("Create IPv6 5-Tuple entry\n");
461 pr_info("ING SIPv6->DIPv6: %08X:%08X:%08X:%08X:%d-> %08X:%08X:%08X:%08X:%d\n",
462 entry->ipv6_5t_route.ipv6_sip0,
463 entry->ipv6_5t_route.ipv6_sip1,
464 entry->ipv6_5t_route.ipv6_sip2,
465 entry->ipv6_5t_route.ipv6_sip3,
466 entry->ipv6_5t_route.sport,
467 entry->ipv6_5t_route.ipv6_dip0,
468 entry->ipv6_5t_route.ipv6_dip1,
469 entry->ipv6_5t_route.ipv6_dip2,
470 entry->ipv6_5t_route.ipv6_dip3,
471 entry->ipv6_5t_route.dport);
472 } else if (IS_IPV6_6RD(entry)) {
developere8b7dfa2023-04-20 10:16:44 +0800473 pr_info("Information Block 2: %08X (FP=%d FQOS=%d QID=%d)",
474 entry->ipv6_6rd.info_blk2,
475 entry->ipv6_6rd.iblk2.dp,
476 entry->ipv6_6rd.iblk2.fqos,
477 entry->ipv6_6rd.iblk2.qid);
developerfd40db22021-04-29 10:08:25 +0800478 pr_info("Create IPv6 6RD entry\n");
479 pr_info("ING SIPv6->DIPv6: %08X:%08X:%08X:%08X:%d-> %08X:%08X:%08X:%08X:%d\n",
480 entry->ipv6_6rd.ipv6_sip0, entry->ipv6_6rd.ipv6_sip1,
481 entry->ipv6_6rd.ipv6_sip2, entry->ipv6_6rd.ipv6_sip3,
482 entry->ipv6_6rd.sport, entry->ipv6_6rd.ipv6_dip0,
483 entry->ipv6_6rd.ipv6_dip1, entry->ipv6_6rd.ipv6_dip2,
484 entry->ipv6_6rd.ipv6_dip3, entry->ipv6_6rd.dport);
developer5ffc5f12022-10-25 18:51:46 +0800485#if defined(CONFIG_MEDIATEK_NETSYS_V3)
486 } else if (IS_IPV6_HNAPT(entry)) {
487 pr_info("Information Block 2: %08X (FP=%d FQOS=%d QID=%d)",
488 entry->ipv6_hnapt.info_blk2,
489 entry->ipv6_hnapt.iblk2.dp,
490 entry->ipv6_hnapt.iblk2.fqos,
491 entry->ipv6_hnapt.iblk2.qid);
492 pr_info("Create IPv6 HNAPT entry\n");
493 pr_info("IPv6 Org IP/Port: %08X:%08X:%08X:%08X:%d -> %08X:%08X:%08X:%08X:%d",
494 entry->ipv6_hnapt.ipv6_sip0,
495 entry->ipv6_hnapt.ipv6_sip1,
496 entry->ipv6_hnapt.ipv6_sip2,
497 entry->ipv6_hnapt.ipv6_sip3,
498 entry->ipv6_hnapt.sport,
499 entry->ipv6_hnapt.ipv6_dip0,
500 entry->ipv6_hnapt.ipv6_dip1,
501 entry->ipv6_hnapt.ipv6_dip2,
502 entry->ipv6_hnapt.ipv6_dip3,
503 entry->ipv6_hnapt.dport);
504
505 if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_SNAT) {
506 pr_info("IPv6 New IP/Port: %08X:%08X:%08X:%08X:%d -> %08X:%08X:%08X:%08X:%d\n",
507 entry->ipv6_hnapt.new_ipv6_ip0,
508 entry->ipv6_hnapt.new_ipv6_ip1,
509 entry->ipv6_hnapt.new_ipv6_ip2,
510 entry->ipv6_hnapt.new_ipv6_ip3,
511 entry->ipv6_hnapt.new_sport,
512 entry->ipv6_hnapt.ipv6_dip0,
513 entry->ipv6_hnapt.ipv6_dip1,
514 entry->ipv6_hnapt.ipv6_dip2,
515 entry->ipv6_hnapt.ipv6_dip3,
516 entry->ipv6_hnapt.new_dport);
517 } else if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_DNAT) {
518 pr_info("IPv6 New IP/Port: %08X:%08X:%08X:%08X:%d -> %08X:%08X:%08X:%08X:%d\n",
519 entry->ipv6_hnapt.ipv6_sip0,
520 entry->ipv6_hnapt.ipv6_sip1,
521 entry->ipv6_hnapt.ipv6_sip2,
522 entry->ipv6_hnapt.ipv6_sip3,
523 entry->ipv6_hnapt.new_sport,
524 entry->ipv6_hnapt.new_ipv6_ip0,
525 entry->ipv6_hnapt.new_ipv6_ip1,
526 entry->ipv6_hnapt.new_ipv6_ip2,
527 entry->ipv6_hnapt.new_ipv6_ip3,
528 entry->ipv6_hnapt.new_dport);
529 }
530 } else if (IS_IPV6_HNAT(entry)) {
531 pr_info("Information Block 2: %08X (FP=%d FQOS=%d QID=%d)",
532 entry->ipv6_hnapt.info_blk2,
533 entry->ipv6_hnapt.iblk2.dp,
534 entry->ipv6_hnapt.iblk2.fqos,
535 entry->ipv6_hnapt.iblk2.qid);
536 pr_info("Create IPv6 HNAT entry\n");
537 pr_info("IPv6 Org IP: %08X:%08X:%08X:%08X -> %08X:%08X:%08X:%08X",
538 entry->ipv6_hnapt.ipv6_sip0,
539 entry->ipv6_hnapt.ipv6_sip1,
540 entry->ipv6_hnapt.ipv6_sip2,
541 entry->ipv6_hnapt.ipv6_sip3,
542 entry->ipv6_hnapt.ipv6_dip0,
543 entry->ipv6_hnapt.ipv6_dip1,
544 entry->ipv6_hnapt.ipv6_dip2,
545 entry->ipv6_hnapt.ipv6_dip3);
546
547 if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_SNAT) {
548 pr_info("IPv6 New IP: %08X:%08X:%08X:%08X -> %08X:%08X:%08X:%08X\n",
549 entry->ipv6_hnapt.new_ipv6_ip0,
550 entry->ipv6_hnapt.new_ipv6_ip1,
551 entry->ipv6_hnapt.new_ipv6_ip2,
552 entry->ipv6_hnapt.new_ipv6_ip3,
553 entry->ipv6_hnapt.ipv6_dip0,
554 entry->ipv6_hnapt.ipv6_dip1,
555 entry->ipv6_hnapt.ipv6_dip2,
556 entry->ipv6_hnapt.ipv6_dip3);
557 } else if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_DNAT) {
558 pr_info("IPv6 New IP: %08X:%08X:%08X:%08X -> %08X:%08X:%08X:%08X\n",
559 entry->ipv6_hnapt.ipv6_sip0,
560 entry->ipv6_hnapt.ipv6_sip1,
561 entry->ipv6_hnapt.ipv6_sip2,
562 entry->ipv6_hnapt.ipv6_sip3,
563 entry->ipv6_hnapt.new_ipv6_ip0,
564 entry->ipv6_hnapt.new_ipv6_ip1,
565 entry->ipv6_hnapt.new_ipv6_ip2,
566 entry->ipv6_hnapt.new_ipv6_ip3);
567 }
568#endif
developerfd40db22021-04-29 10:08:25 +0800569 }
developer5ffc5f12022-10-25 18:51:46 +0800570
developerfd40db22021-04-29 10:08:25 +0800571 if (IS_IPV4_HNAPT(entry) || IS_IPV4_HNAT(entry)) {
572 *((u32 *)h_source) = swab32(entry->ipv4_hnapt.smac_hi);
573 *((u16 *)&h_source[4]) = swab16(entry->ipv4_hnapt.smac_lo);
574 *((u32 *)h_dest) = swab32(entry->ipv4_hnapt.dmac_hi);
575 *((u16 *)&h_dest[4]) = swab16(entry->ipv4_hnapt.dmac_lo);
576 pr_info("SMAC=%pM => DMAC=%pM\n", h_source, h_dest);
577 pr_info("State = %s, ", entry->bfib1.state == 0 ?
578 "Invalid" : entry->bfib1.state == 1 ?
579 "Unbind" : entry->bfib1.state == 2 ?
580 "BIND" : entry->bfib1.state == 3 ?
581 "FIN" : "Unknown");
582 pr_info("Vlan_Layer = %u, ", entry->bfib1.vlan_layer);
583 pr_info("Eth_type = 0x%x, Vid1 = 0x%x, Vid2 = 0x%x\n",
584 entry->ipv4_hnapt.etype, entry->ipv4_hnapt.vlan1,
585 entry->ipv4_hnapt.vlan2);
586 pr_info("multicast = %d, pppoe = %d, proto = %s\n",
587 entry->ipv4_hnapt.iblk2.mcast,
588 entry->ipv4_hnapt.bfib1.psn,
589 entry->ipv4_hnapt.bfib1.udp == 0 ?
590 "TCP" : entry->ipv4_hnapt.bfib1.udp == 1 ?
591 "UDP" : "Unknown");
developerd35bbcc2022-09-28 22:46:01 +0800592#if defined(CONFIG_MEDIATEK_NETSYS_V3)
593 pr_info("tport_id = %d, tops_entry = %d, cdrt_id = %d\n",
594 entry->ipv4_hnapt.tport_id,
595 entry->ipv4_hnapt.tops_entry,
596 entry->ipv4_hnapt.cdrt_id);
597#endif
developerfd40db22021-04-29 10:08:25 +0800598 pr_info("=========================================\n\n");
599 } else {
600 *((u32 *)h_source) = swab32(entry->ipv6_5t_route.smac_hi);
601 *((u16 *)&h_source[4]) = swab16(entry->ipv6_5t_route.smac_lo);
602 *((u32 *)h_dest) = swab32(entry->ipv6_5t_route.dmac_hi);
603 *((u16 *)&h_dest[4]) = swab16(entry->ipv6_5t_route.dmac_lo);
604 pr_info("SMAC=%pM => DMAC=%pM\n", h_source, h_dest);
605 pr_info("State = %s, ", entry->bfib1.state == 0 ?
606 "Invalid" : entry->bfib1.state == 1 ?
607 "Unbind" : entry->bfib1.state == 2 ?
608 "BIND" : entry->bfib1.state == 3 ?
609 "FIN" : "Unknown");
610
611 pr_info("Vlan_Layer = %u, ", entry->bfib1.vlan_layer);
612 pr_info("Eth_type = 0x%x, Vid1 = 0x%x, Vid2 = 0x%x\n",
613 entry->ipv6_5t_route.etype, entry->ipv6_5t_route.vlan1,
614 entry->ipv6_5t_route.vlan2);
615 pr_info("multicast = %d, pppoe = %d, proto = %s\n",
616 entry->ipv6_5t_route.iblk2.mcast,
617 entry->ipv6_5t_route.bfib1.psn,
618 entry->ipv6_5t_route.bfib1.udp == 0 ?
619 "TCP" : entry->ipv6_5t_route.bfib1.udp == 1 ?
620 "UDP" : "Unknown");
developerd35bbcc2022-09-28 22:46:01 +0800621#if defined(CONFIG_MEDIATEK_NETSYS_V3)
622 pr_info("tport_id = %d, tops_entry = %d, cdrt_id = %d\n",
623 entry->ipv6_5t_route.tport_id,
624 entry->ipv6_5t_route.tops_entry,
625 entry->ipv6_5t_route.cdrt_id);
626#endif
developerfd40db22021-04-29 10:08:25 +0800627 pr_info("=========================================\n\n");
628 }
629 return 0;
630}
631
developer471f6562021-05-10 20:48:34 +0800632int wrapped_ppe0_entry_delete(int index) {
633 entry_delete(0, index);
634 return 0;
635}
636
637int wrapped_ppe1_entry_delete(int index) {
638 entry_delete(1, index);
639 return 0;
640}
641
developer4c32b7a2021-11-13 16:46:43 +0800642int entry_delete(u32 ppe_id, int index)
developerfd40db22021-04-29 10:08:25 +0800643{
644 struct foe_entry *entry;
645 struct mtk_hnat *h = hnat_priv;
646
developer471f6562021-05-10 20:48:34 +0800647 if (ppe_id >= CFG_PPE_NUM)
648 return -EINVAL;
649
developer3fb8d472021-11-16 15:46:38 +0800650 if (index < -1 || index >= (int)h->foe_etry_num) {
developerc6227322021-07-09 10:52:53 +0800651 pr_info("Invalid entry index\n");
652 return -EINVAL;
653 }
654
developer3fb8d472021-11-16 15:46:38 +0800655 if (index == -1) {
656 memset(h->foe_table_cpu[ppe_id], 0, h->foe_etry_num * sizeof(struct foe_entry));
657 pr_info("clear all foe entry\n");
658 } else {
659
660 entry = h->foe_table_cpu[ppe_id] + index;
661 memset(entry, 0, sizeof(struct foe_entry));
662 pr_info("delete ppe id = %d, entry idx = %d\n", ppe_id, index);
663 }
developerfd40db22021-04-29 10:08:25 +0800664
665 /* clear HWNAT cache */
666 hnat_cache_ebl(1);
667
developerfd40db22021-04-29 10:08:25 +0800668 return 0;
669}
670EXPORT_SYMBOL(entry_delete);
671
672int cr_set_usage(int level)
673{
674 debug_level = level;
675 pr_info("Dump hnat CR: cat /sys/kernel/debug/hnat/hnat_setting\n\n");
676 pr_info("====================Advanced Settings====================\n");
677 pr_info("Usage: echo [type] [option] > /sys/kernel/debug/hnat/hnat_setting\n\n");
678 pr_info("Commands: [type] [option]\n");
679 pr_info(" 0 0~7 Set debug_level(0~7), current debug_level=%d\n",
680 debug_level);
681 pr_info(" 1 0~65535 Set binding threshold\n");
682 pr_info(" 2 0~65535 Set TCP bind lifetime\n");
683 pr_info(" 3 0~65535 Set FIN bind lifetime\n");
684 pr_info(" 4 0~65535 Set UDP bind lifetime\n");
685 pr_info(" 5 0~255 Set TCP keep alive interval\n");
686 pr_info(" 6 0~255 Set UDP keep alive interval\n");
developer30a47682021-11-02 17:06:14 +0800687 pr_info(" 7 0~1 Set hnat counter update to nf_conntrack\n");
developerfd40db22021-04-29 10:08:25 +0800688
689 return 0;
690}
691
692int binding_threshold(int threshold)
693{
developer471f6562021-05-10 20:48:34 +0800694 int i;
695
developerfd40db22021-04-29 10:08:25 +0800696 pr_info("Binding Threshold =%d\n", threshold);
developer471f6562021-05-10 20:48:34 +0800697
698 for (i = 0; i < CFG_PPE_NUM; i++)
699 writel(threshold, hnat_priv->ppe_base[i] + PPE_BNDR);
700
developerfd40db22021-04-29 10:08:25 +0800701 return 0;
702}
703
704int tcp_bind_lifetime(int tcp_life)
705{
developer471f6562021-05-10 20:48:34 +0800706 int i;
707
developerfd40db22021-04-29 10:08:25 +0800708 pr_info("tcp_life = %d\n", tcp_life);
developer471f6562021-05-10 20:48:34 +0800709
developerfd40db22021-04-29 10:08:25 +0800710 /* set Delta time for aging out an bind TCP FOE entry */
developer471f6562021-05-10 20:48:34 +0800711 for (i = 0; i < CFG_PPE_NUM; i++)
712 cr_set_field(hnat_priv->ppe_base[i] + PPE_BND_AGE_1,
713 TCP_DLTA, tcp_life);
developerfd40db22021-04-29 10:08:25 +0800714
715 return 0;
716}
717
718int fin_bind_lifetime(int fin_life)
719{
developer471f6562021-05-10 20:48:34 +0800720 int i;
721
developerfd40db22021-04-29 10:08:25 +0800722 pr_info("fin_life = %d\n", fin_life);
developer471f6562021-05-10 20:48:34 +0800723
developerfd40db22021-04-29 10:08:25 +0800724 /* set Delta time for aging out an bind TCP FIN FOE entry */
developer471f6562021-05-10 20:48:34 +0800725 for (i = 0; i < CFG_PPE_NUM; i++)
726 cr_set_field(hnat_priv->ppe_base[i] + PPE_BND_AGE_1,
727 FIN_DLTA, fin_life);
developerfd40db22021-04-29 10:08:25 +0800728
729 return 0;
730}
731
732int udp_bind_lifetime(int udp_life)
733{
developer471f6562021-05-10 20:48:34 +0800734 int i;
735
developerfd40db22021-04-29 10:08:25 +0800736 pr_info("udp_life = %d\n", udp_life);
developer471f6562021-05-10 20:48:34 +0800737
developerfd40db22021-04-29 10:08:25 +0800738 /* set Delta time for aging out an bind UDP FOE entry */
developer471f6562021-05-10 20:48:34 +0800739 for (i = 0; i < CFG_PPE_NUM; i++)
740 cr_set_field(hnat_priv->ppe_base[i] + PPE_BND_AGE_0,
741 UDP_DLTA, udp_life);
developerfd40db22021-04-29 10:08:25 +0800742
743 return 0;
744}
745
746int tcp_keep_alive(int tcp_interval)
747{
developer471f6562021-05-10 20:48:34 +0800748 int i;
749
developerfd40db22021-04-29 10:08:25 +0800750 if (tcp_interval > 255) {
751 tcp_interval = 255;
752 pr_info("TCP keep alive max interval = 255\n");
753 } else {
754 pr_info("tcp_interval = %d\n", tcp_interval);
755 }
developer471f6562021-05-10 20:48:34 +0800756
developerfd40db22021-04-29 10:08:25 +0800757 /* Keep alive time for bind FOE TCP entry */
developer471f6562021-05-10 20:48:34 +0800758 for (i = 0; i < CFG_PPE_NUM; i++)
759 cr_set_field(hnat_priv->ppe_base[i] + PPE_KA,
760 TCP_KA, tcp_interval);
developerfd40db22021-04-29 10:08:25 +0800761
762 return 0;
763}
764
765int udp_keep_alive(int udp_interval)
766{
developer471f6562021-05-10 20:48:34 +0800767 int i;
768
developerfd40db22021-04-29 10:08:25 +0800769 if (udp_interval > 255) {
770 udp_interval = 255;
771 pr_info("TCP/UDP keep alive max interval = 255\n");
772 } else {
773 pr_info("udp_interval = %d\n", udp_interval);
774 }
developer471f6562021-05-10 20:48:34 +0800775
developerfd40db22021-04-29 10:08:25 +0800776 /* Keep alive timer for bind FOE UDP entry */
developer471f6562021-05-10 20:48:34 +0800777 for (i = 0; i < CFG_PPE_NUM; i++)
778 cr_set_field(hnat_priv->ppe_base[i] + PPE_KA,
779 UDP_KA, udp_interval);
developerfd40db22021-04-29 10:08:25 +0800780
781 return 0;
782}
783
developer30a47682021-11-02 17:06:14 +0800784int set_nf_update_toggle(int toggle)
785{
786 struct mtk_hnat *h = hnat_priv;
787
788 if (toggle == 1)
789 pr_info("Enable hnat counter update to nf_conntrack\n");
790 else if (toggle == 0)
791 pr_info("Disable hnat counter update to nf_conntrack\n");
792 else
793 pr_info("input error\n");
794 h->nf_stat_en = toggle;
795
796 return 0;
797}
798
developerfd40db22021-04-29 10:08:25 +0800799static const debugfs_write_func hnat_set_func[] = {
800 [0] = hnat_set_usage,
801 [1] = hnat_cpu_reason,
802};
803
804static const debugfs_write_func entry_set_func[] = {
805 [0] = entry_set_usage,
806 [1] = entry_set_state,
developer471f6562021-05-10 20:48:34 +0800807 [2] = wrapped_ppe0_entry_detail,
808 [3] = wrapped_ppe0_entry_delete,
809 [4] = wrapped_ppe1_entry_detail,
810 [5] = wrapped_ppe1_entry_delete,
developerfd40db22021-04-29 10:08:25 +0800811};
812
813static const debugfs_write_func cr_set_func[] = {
814 [0] = cr_set_usage, [1] = binding_threshold,
815 [2] = tcp_bind_lifetime, [3] = fin_bind_lifetime,
816 [4] = udp_bind_lifetime, [5] = tcp_keep_alive,
developer30a47682021-11-02 17:06:14 +0800817 [6] = udp_keep_alive, [7] = set_nf_update_toggle,
developerfd40db22021-04-29 10:08:25 +0800818};
819
developer4c32b7a2021-11-13 16:46:43 +0800820int read_mib(struct mtk_hnat *h, u32 ppe_id,
developer30a47682021-11-02 17:06:14 +0800821 u32 index, u64 *bytes, u64 *packets)
developerfd40db22021-04-29 10:08:25 +0800822{
developer30a47682021-11-02 17:06:14 +0800823 int ret;
developerd35bbcc2022-09-28 22:46:01 +0800824 u32 val, cnt_r0, cnt_r1, cnt_r2, cnt_r3;
developer4c32b7a2021-11-13 16:46:43 +0800825
826 if (ppe_id >= CFG_PPE_NUM)
827 return -EINVAL;
828
developer471f6562021-05-10 20:48:34 +0800829 writel(index | (1 << 16), h->ppe_base[ppe_id] + PPE_MIB_SER_CR);
developer30a47682021-11-02 17:06:14 +0800830 ret = readx_poll_timeout_atomic(readl, h->ppe_base[ppe_id] + PPE_MIB_SER_CR, val,
831 !(val & BIT_MIB_BUSY), 20, 10000);
832
developerfd40db22021-04-29 10:08:25 +0800833 if (ret < 0) {
developer30a47682021-11-02 17:06:14 +0800834 pr_notice("mib busy, please check later\n");
835 return ret;
developerfd40db22021-04-29 10:08:25 +0800836 }
developer471f6562021-05-10 20:48:34 +0800837 cnt_r0 = readl(h->ppe_base[ppe_id] + PPE_MIB_SER_R0);
838 cnt_r1 = readl(h->ppe_base[ppe_id] + PPE_MIB_SER_R1);
839 cnt_r2 = readl(h->ppe_base[ppe_id] + PPE_MIB_SER_R2);
developerd35bbcc2022-09-28 22:46:01 +0800840
developer4164cfe2022-12-01 11:27:41 +0800841 if (hnat_priv->data->version == MTK_HNAT_V3) {
developerd35bbcc2022-09-28 22:46:01 +0800842 cnt_r3 = readl(h->ppe_base[ppe_id] + PPE_MIB_SER_R3);
843 *bytes = cnt_r0 + ((u64)cnt_r1 << 32);
844 *packets = cnt_r2 + ((u64)cnt_r3 << 32);
845 } else {
846 *bytes = cnt_r0 + ((u64)(cnt_r1 & 0xffff) << 32);
developer577ad2f2022-11-28 10:33:36 +0800847 *packets = ((cnt_r1 & 0xffff0000) >> 16) +
848 ((u64)(cnt_r2 & 0xffffff) << 16);
developerd35bbcc2022-09-28 22:46:01 +0800849 }
developerfd40db22021-04-29 10:08:25 +0800850
developer30a47682021-11-02 17:06:14 +0800851 return 0;
852
853}
854
developer4c32b7a2021-11-13 16:46:43 +0800855struct hnat_accounting *hnat_get_count(struct mtk_hnat *h, u32 ppe_id,
developer30a47682021-11-02 17:06:14 +0800856 u32 index, struct hnat_accounting *diff)
857
858{
859 u64 bytes, packets;
860
developer4c32b7a2021-11-13 16:46:43 +0800861 if (ppe_id >= CFG_PPE_NUM)
862 return NULL;
863
developer577ad2f2022-11-28 10:33:36 +0800864 if (index >= hnat_priv->foe_etry_num)
865 return NULL;
866
developer30a47682021-11-02 17:06:14 +0800867 if (!hnat_priv->data->per_flow_accounting)
868 return NULL;
869
870 if (read_mib(h, ppe_id, index, &bytes, &packets))
871 return NULL;
872
873 h->acct[ppe_id][index].bytes += bytes;
874 h->acct[ppe_id][index].packets += packets;
developer577ad2f2022-11-28 10:33:36 +0800875
developer30a47682021-11-02 17:06:14 +0800876 if (diff) {
877 diff->bytes = bytes;
878 diff->packets = packets;
879 }
880
881 return &h->acct[ppe_id][index];
developerfd40db22021-04-29 10:08:25 +0800882}
developer30a47682021-11-02 17:06:14 +0800883EXPORT_SYMBOL(hnat_get_count);
developerfd40db22021-04-29 10:08:25 +0800884
developer30a47682021-11-02 17:06:14 +0800885#define PRINT_COUNT(m, acct) {if (acct) \
developerfd40db22021-04-29 10:08:25 +0800886 seq_printf(m, "bytes=%llu|packets=%llu|", \
developer30a47682021-11-02 17:06:14 +0800887 acct->bytes, acct->packets); }
developer4c32b7a2021-11-13 16:46:43 +0800888static int __hnat_debug_show(struct seq_file *m, void *private, u32 ppe_id)
developerfd40db22021-04-29 10:08:25 +0800889{
890 struct mtk_hnat *h = hnat_priv;
891 struct foe_entry *entry, *end;
892 unsigned char h_dest[ETH_ALEN];
893 unsigned char h_source[ETH_ALEN];
developer30a47682021-11-02 17:06:14 +0800894 struct hnat_accounting *acct;
developerfd40db22021-04-29 10:08:25 +0800895 u32 entry_index = 0;
896
developer4c32b7a2021-11-13 16:46:43 +0800897 if (ppe_id >= CFG_PPE_NUM)
898 return -EINVAL;
899
developer471f6562021-05-10 20:48:34 +0800900 entry = h->foe_table_cpu[ppe_id];
901 end = h->foe_table_cpu[ppe_id] + hnat_priv->foe_etry_num;
developerfd40db22021-04-29 10:08:25 +0800902 while (entry < end) {
903 if (!entry->bfib1.state) {
904 entry++;
905 entry_index++;
906 continue;
907 }
developer30a47682021-11-02 17:06:14 +0800908 acct = hnat_get_count(h, ppe_id, entry_index, NULL);
developerfd40db22021-04-29 10:08:25 +0800909 if (IS_IPV4_HNAPT(entry)) {
910 __be32 saddr = htonl(entry->ipv4_hnapt.sip);
911 __be32 daddr = htonl(entry->ipv4_hnapt.dip);
912 __be32 nsaddr = htonl(entry->ipv4_hnapt.new_sip);
913 __be32 ndaddr = htonl(entry->ipv4_hnapt.new_dip);
914
915 *((u32 *)h_source) = swab32(entry->ipv4_hnapt.smac_hi);
916 *((u16 *)&h_source[4]) =
917 swab16(entry->ipv4_hnapt.smac_lo);
918 *((u32 *)h_dest) = swab32(entry->ipv4_hnapt.dmac_hi);
919 *((u16 *)&h_dest[4]) =
920 swab16(entry->ipv4_hnapt.dmac_lo);
developer30a47682021-11-02 17:06:14 +0800921 PRINT_COUNT(m, acct);
developerfd40db22021-04-29 10:08:25 +0800922 seq_printf(m,
developer471f6562021-05-10 20:48:34 +0800923 "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|%pI4:%d->%pI4:%d=>%pI4:%d->%pI4:%d|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
924 entry, ppe_id, ei(entry, end),
925 es(entry), pt(entry), &saddr,
developerfd40db22021-04-29 10:08:25 +0800926 entry->ipv4_hnapt.sport, &daddr,
927 entry->ipv4_hnapt.dport, &nsaddr,
928 entry->ipv4_hnapt.new_sport, &ndaddr,
929 entry->ipv4_hnapt.new_dport, h_source, h_dest,
930 ntohs(entry->ipv4_hnapt.etype),
931 entry->ipv4_hnapt.info_blk1,
932 entry->ipv4_hnapt.info_blk2,
933 entry->ipv4_hnapt.vlan1,
934 entry->ipv4_hnapt.vlan2);
935 } else if (IS_IPV4_HNAT(entry)) {
936 __be32 saddr = htonl(entry->ipv4_hnapt.sip);
937 __be32 daddr = htonl(entry->ipv4_hnapt.dip);
938 __be32 nsaddr = htonl(entry->ipv4_hnapt.new_sip);
939 __be32 ndaddr = htonl(entry->ipv4_hnapt.new_dip);
940
941 *((u32 *)h_source) = swab32(entry->ipv4_hnapt.smac_hi);
942 *((u16 *)&h_source[4]) =
943 swab16(entry->ipv4_hnapt.smac_lo);
944 *((u32 *)h_dest) = swab32(entry->ipv4_hnapt.dmac_hi);
945 *((u16 *)&h_dest[4]) =
946 swab16(entry->ipv4_hnapt.dmac_lo);
developer30a47682021-11-02 17:06:14 +0800947 PRINT_COUNT(m, acct);
developerfd40db22021-04-29 10:08:25 +0800948 seq_printf(m,
developer471f6562021-05-10 20:48:34 +0800949 "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|%pI4->%pI4=>%pI4->%pI4|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
950 entry, ppe_id, ei(entry, end),
951 es(entry), pt(entry), &saddr,
developerfd40db22021-04-29 10:08:25 +0800952 &daddr, &nsaddr, &ndaddr, h_source, h_dest,
953 ntohs(entry->ipv4_hnapt.etype),
954 entry->ipv4_hnapt.info_blk1,
955 entry->ipv4_hnapt.info_blk2,
956 entry->ipv4_hnapt.vlan1,
957 entry->ipv4_hnapt.vlan2);
958 } else if (IS_IPV6_5T_ROUTE(entry)) {
959 u32 ipv6_sip0 = entry->ipv6_3t_route.ipv6_sip0;
960 u32 ipv6_sip1 = entry->ipv6_3t_route.ipv6_sip1;
961 u32 ipv6_sip2 = entry->ipv6_3t_route.ipv6_sip2;
962 u32 ipv6_sip3 = entry->ipv6_3t_route.ipv6_sip3;
963 u32 ipv6_dip0 = entry->ipv6_3t_route.ipv6_dip0;
964 u32 ipv6_dip1 = entry->ipv6_3t_route.ipv6_dip1;
965 u32 ipv6_dip2 = entry->ipv6_3t_route.ipv6_dip2;
966 u32 ipv6_dip3 = entry->ipv6_3t_route.ipv6_dip3;
967
968 *((u32 *)h_source) =
969 swab32(entry->ipv6_5t_route.smac_hi);
970 *((u16 *)&h_source[4]) =
971 swab16(entry->ipv6_5t_route.smac_lo);
972 *((u32 *)h_dest) = swab32(entry->ipv6_5t_route.dmac_hi);
973 *((u16 *)&h_dest[4]) =
974 swab16(entry->ipv6_5t_route.dmac_lo);
developer30a47682021-11-02 17:06:14 +0800975 PRINT_COUNT(m, acct);
developerfd40db22021-04-29 10:08:25 +0800976 seq_printf(m,
developer471f6562021-05-10 20:48:34 +0800977 "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x(sp=%d)->DIP=%08x:%08x:%08x:%08x(dp=%d)|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x\n",
978 entry, ppe_id, ei(entry, end), es(entry), pt(entry), ipv6_sip0,
developerfd40db22021-04-29 10:08:25 +0800979 ipv6_sip1, ipv6_sip2, ipv6_sip3,
980 entry->ipv6_5t_route.sport, ipv6_dip0,
981 ipv6_dip1, ipv6_dip2, ipv6_dip3,
982 entry->ipv6_5t_route.dport, h_source, h_dest,
983 ntohs(entry->ipv6_5t_route.etype),
984 entry->ipv6_5t_route.info_blk1,
985 entry->ipv6_5t_route.info_blk2);
986 } else if (IS_IPV6_3T_ROUTE(entry)) {
987 u32 ipv6_sip0 = entry->ipv6_3t_route.ipv6_sip0;
988 u32 ipv6_sip1 = entry->ipv6_3t_route.ipv6_sip1;
989 u32 ipv6_sip2 = entry->ipv6_3t_route.ipv6_sip2;
990 u32 ipv6_sip3 = entry->ipv6_3t_route.ipv6_sip3;
991 u32 ipv6_dip0 = entry->ipv6_3t_route.ipv6_dip0;
992 u32 ipv6_dip1 = entry->ipv6_3t_route.ipv6_dip1;
993 u32 ipv6_dip2 = entry->ipv6_3t_route.ipv6_dip2;
994 u32 ipv6_dip3 = entry->ipv6_3t_route.ipv6_dip3;
995
996 *((u32 *)h_source) =
997 swab32(entry->ipv6_5t_route.smac_hi);
998 *((u16 *)&h_source[4]) =
999 swab16(entry->ipv6_5t_route.smac_lo);
1000 *((u32 *)h_dest) = swab32(entry->ipv6_5t_route.dmac_hi);
1001 *((u16 *)&h_dest[4]) =
1002 swab16(entry->ipv6_5t_route.dmac_lo);
developer30a47682021-11-02 17:06:14 +08001003 PRINT_COUNT(m, acct);
developerfd40db22021-04-29 10:08:25 +08001004 seq_printf(m,
developer471f6562021-05-10 20:48:34 +08001005 "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x->DIP=%08x:%08x:%08x:%08x|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x\n",
1006 entry, ppe_id, ei(entry, end),
1007 es(entry), pt(entry), ipv6_sip0,
developerfd40db22021-04-29 10:08:25 +08001008 ipv6_sip1, ipv6_sip2, ipv6_sip3, ipv6_dip0,
1009 ipv6_dip1, ipv6_dip2, ipv6_dip3, h_source,
1010 h_dest, ntohs(entry->ipv6_5t_route.etype),
1011 entry->ipv6_5t_route.info_blk1,
1012 entry->ipv6_5t_route.info_blk2);
1013 } else if (IS_IPV6_6RD(entry)) {
1014 u32 ipv6_sip0 = entry->ipv6_3t_route.ipv6_sip0;
1015 u32 ipv6_sip1 = entry->ipv6_3t_route.ipv6_sip1;
1016 u32 ipv6_sip2 = entry->ipv6_3t_route.ipv6_sip2;
1017 u32 ipv6_sip3 = entry->ipv6_3t_route.ipv6_sip3;
1018 u32 ipv6_dip0 = entry->ipv6_3t_route.ipv6_dip0;
1019 u32 ipv6_dip1 = entry->ipv6_3t_route.ipv6_dip1;
1020 u32 ipv6_dip2 = entry->ipv6_3t_route.ipv6_dip2;
1021 u32 ipv6_dip3 = entry->ipv6_3t_route.ipv6_dip3;
1022 __be32 tsaddr = htonl(entry->ipv6_6rd.tunnel_sipv4);
1023 __be32 tdaddr = htonl(entry->ipv6_6rd.tunnel_dipv4);
1024
1025 *((u32 *)h_source) =
1026 swab32(entry->ipv6_5t_route.smac_hi);
1027 *((u16 *)&h_source[4]) =
1028 swab16(entry->ipv6_5t_route.smac_lo);
1029 *((u32 *)h_dest) = swab32(entry->ipv6_5t_route.dmac_hi);
1030 *((u16 *)&h_dest[4]) =
1031 swab16(entry->ipv6_5t_route.dmac_lo);
developer30a47682021-11-02 17:06:14 +08001032 PRINT_COUNT(m, acct);
developerfd40db22021-04-29 10:08:25 +08001033 seq_printf(m,
developer471f6562021-05-10 20:48:34 +08001034 "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x(sp=%d)->DIP=%08x:%08x:%08x:%08x(dp=%d)|TSIP=%pI4->TDIP=%pI4|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x\n",
1035 entry, ppe_id, ei(entry, end),
1036 es(entry), pt(entry), ipv6_sip0,
developerfd40db22021-04-29 10:08:25 +08001037 ipv6_sip1, ipv6_sip2, ipv6_sip3,
1038 entry->ipv6_5t_route.sport, ipv6_dip0,
1039 ipv6_dip1, ipv6_dip2, ipv6_dip3,
1040 entry->ipv6_5t_route.dport, &tsaddr, &tdaddr,
1041 h_source, h_dest,
1042 ntohs(entry->ipv6_5t_route.etype),
1043 entry->ipv6_5t_route.info_blk1,
1044 entry->ipv6_5t_route.info_blk2);
developer5ffc5f12022-10-25 18:51:46 +08001045#if defined(CONFIG_MEDIATEK_NETSYS_V3)
1046 } else if (IS_IPV6_HNAPT(entry)) {
1047 u32 ipv6_sip0 = entry->ipv6_hnapt.ipv6_sip0;
1048 u32 ipv6_sip1 = entry->ipv6_hnapt.ipv6_sip1;
1049 u32 ipv6_sip2 = entry->ipv6_hnapt.ipv6_sip2;
1050 u32 ipv6_sip3 = entry->ipv6_hnapt.ipv6_sip3;
1051 u32 ipv6_dip0 = entry->ipv6_hnapt.ipv6_dip0;
1052 u32 ipv6_dip1 = entry->ipv6_hnapt.ipv6_dip1;
1053 u32 ipv6_dip2 = entry->ipv6_hnapt.ipv6_dip2;
1054 u32 ipv6_dip3 = entry->ipv6_hnapt.ipv6_dip3;
1055 u32 new_ipv6_ip0 = entry->ipv6_hnapt.new_ipv6_ip0;
1056 u32 new_ipv6_ip1 = entry->ipv6_hnapt.new_ipv6_ip1;
1057 u32 new_ipv6_ip2 = entry->ipv6_hnapt.new_ipv6_ip2;
1058 u32 new_ipv6_ip3 = entry->ipv6_hnapt.new_ipv6_ip3;
1059
1060 *((u32 *)h_source) = swab32(entry->ipv6_hnapt.smac_hi);
1061 *((u16 *)&h_source[4]) =
1062 swab16(entry->ipv6_hnapt.smac_lo);
1063 *((u32 *)h_dest) = swab32(entry->ipv6_hnapt.dmac_hi);
1064 *((u16 *)&h_dest[4]) =
1065 swab16(entry->ipv6_hnapt.dmac_lo);
1066 PRINT_COUNT(m, acct);
1067
1068 if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_SNAT) {
1069 seq_printf(m,
1070 "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x(sp=%d)->DIP=%08x:%08x:%08x:%08x(dp=%d)|NEW_SIP=%08x:%08x:%08x:%08x(sp=%d)->NEW_DIP=%08x:%08x:%08x:%08x(dp=%d)|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
1071 entry, ppe_id, ei(entry, end),
1072 es(entry), pt(entry),
1073 ipv6_sip0, ipv6_sip1,
1074 ipv6_sip2, ipv6_sip3,
1075 entry->ipv6_hnapt.sport,
1076 ipv6_dip0, ipv6_dip1,
1077 ipv6_dip2, ipv6_dip3,
1078 entry->ipv6_hnapt.dport,
1079 new_ipv6_ip0, new_ipv6_ip1,
1080 new_ipv6_ip2, new_ipv6_ip3,
1081 entry->ipv6_hnapt.new_sport,
1082 ipv6_dip0, ipv6_dip1,
1083 ipv6_dip2, ipv6_dip3,
1084 entry->ipv6_hnapt.new_dport,
1085 h_source, h_dest,
1086 ntohs(entry->ipv6_hnapt.etype),
1087 entry->ipv6_hnapt.info_blk1,
1088 entry->ipv6_hnapt.info_blk2,
1089 entry->ipv6_hnapt.vlan1,
1090 entry->ipv6_hnapt.vlan2);
1091 } else if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_DNAT) {
1092 seq_printf(m,
1093 "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x(sp=%d)->DIP=%08x:%08x:%08x:%08x(dp=%d)|NEW_SIP=%08x:%08x:%08x:%08x(sp=%d)->NEW_DIP=%08x:%08x:%08x:%08x(dp=%d)|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
1094 entry, ppe_id, ei(entry, end),
1095 es(entry), pt(entry),
1096 ipv6_sip0, ipv6_sip1,
1097 ipv6_sip2, ipv6_sip3,
1098 entry->ipv6_hnapt.sport,
1099 ipv6_dip0, ipv6_dip1,
1100 ipv6_dip2, ipv6_dip3,
1101 entry->ipv6_hnapt.dport,
1102 ipv6_sip0, ipv6_sip1,
1103 ipv6_sip2, ipv6_sip3,
1104 entry->ipv6_hnapt.new_sport,
1105 new_ipv6_ip0, new_ipv6_ip1,
1106 new_ipv6_ip2, new_ipv6_ip3,
1107 entry->ipv6_hnapt.new_dport,
1108 h_source, h_dest,
1109 ntohs(entry->ipv6_hnapt.etype),
1110 entry->ipv6_hnapt.info_blk1,
1111 entry->ipv6_hnapt.info_blk2,
1112 entry->ipv6_hnapt.vlan1,
1113 entry->ipv6_hnapt.vlan2);
1114 }
1115 } else if (IS_IPV6_HNAT(entry)) {
1116 u32 ipv6_sip0 = entry->ipv6_hnapt.ipv6_sip0;
1117 u32 ipv6_sip1 = entry->ipv6_hnapt.ipv6_sip1;
1118 u32 ipv6_sip2 = entry->ipv6_hnapt.ipv6_sip2;
1119 u32 ipv6_sip3 = entry->ipv6_hnapt.ipv6_sip3;
1120 u32 ipv6_dip0 = entry->ipv6_hnapt.ipv6_dip0;
1121 u32 ipv6_dip1 = entry->ipv6_hnapt.ipv6_dip1;
1122 u32 ipv6_dip2 = entry->ipv6_hnapt.ipv6_dip2;
1123 u32 ipv6_dip3 = entry->ipv6_hnapt.ipv6_dip3;
1124 u32 new_ipv6_ip0 = entry->ipv6_hnapt.new_ipv6_ip0;
1125 u32 new_ipv6_ip1 = entry->ipv6_hnapt.new_ipv6_ip1;
1126 u32 new_ipv6_ip2 = entry->ipv6_hnapt.new_ipv6_ip2;
1127 u32 new_ipv6_ip3 = entry->ipv6_hnapt.new_ipv6_ip3;
1128
1129 *((u32 *)h_source) = swab32(entry->ipv6_hnapt.smac_hi);
1130 *((u16 *)&h_source[4]) =
1131 swab16(entry->ipv6_hnapt.smac_lo);
1132 *((u32 *)h_dest) = swab32(entry->ipv6_hnapt.dmac_hi);
1133 *((u16 *)&h_dest[4]) =
1134 swab16(entry->ipv6_hnapt.dmac_lo);
1135 PRINT_COUNT(m, acct);
1136
1137 if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_SNAT) {
1138 seq_printf(m,
1139 "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x->DIP=%08x:%08x:%08x:%08x|NEW_SIP=%08x:%08x:%08x:%08x->NEW_DIP=%08x:%08x:%08x:%08x|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
1140 entry, ppe_id, ei(entry, end),
1141 es(entry), pt(entry),
1142 ipv6_sip0, ipv6_sip1,
1143 ipv6_sip2, ipv6_sip3,
1144 ipv6_dip0, ipv6_dip1,
1145 ipv6_dip2, ipv6_dip3,
1146 new_ipv6_ip0, new_ipv6_ip1,
1147 new_ipv6_ip2, new_ipv6_ip3,
1148 ipv6_dip0, ipv6_dip1,
1149 ipv6_dip2, ipv6_dip3,
1150 h_source, h_dest,
1151 ntohs(entry->ipv6_hnapt.etype),
1152 entry->ipv6_hnapt.info_blk1,
1153 entry->ipv6_hnapt.info_blk2,
1154 entry->ipv6_hnapt.vlan1,
1155 entry->ipv6_hnapt.vlan2);
1156 } else if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_DNAT) {
1157 seq_printf(m,
1158 "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x->DIP=%08x:%08x:%08x:%08x|NEW_SIP=%08x:%08x:%08x:%08x->NEW_DIP=%08x:%08x:%08x:%08x|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
1159 entry, ppe_id, ei(entry, end),
1160 es(entry), pt(entry),
1161 ipv6_sip0, ipv6_sip1,
1162 ipv6_sip2, ipv6_sip3,
1163 ipv6_dip0, ipv6_dip1,
1164 ipv6_dip2, ipv6_dip3,
1165 ipv6_sip0, ipv6_sip1,
1166 ipv6_sip2, ipv6_sip3,
1167 new_ipv6_ip0, new_ipv6_ip1,
1168 new_ipv6_ip2, new_ipv6_ip3,
1169 h_source, h_dest,
1170 ntohs(entry->ipv6_hnapt.etype),
1171 entry->ipv6_hnapt.info_blk1,
1172 entry->ipv6_hnapt.info_blk2,
1173 entry->ipv6_hnapt.vlan1,
1174 entry->ipv6_hnapt.vlan2);
1175 }
1176#endif
developerfd40db22021-04-29 10:08:25 +08001177 } else if (IS_IPV4_DSLITE(entry)) {
1178 __be32 saddr = htonl(entry->ipv4_hnapt.sip);
1179 __be32 daddr = htonl(entry->ipv4_hnapt.dip);
1180 u32 ipv6_tsip0 = entry->ipv4_dslite.tunnel_sipv6_0;
1181 u32 ipv6_tsip1 = entry->ipv4_dslite.tunnel_sipv6_1;
1182 u32 ipv6_tsip2 = entry->ipv4_dslite.tunnel_sipv6_2;
1183 u32 ipv6_tsip3 = entry->ipv4_dslite.tunnel_sipv6_3;
1184 u32 ipv6_tdip0 = entry->ipv4_dslite.tunnel_dipv6_0;
1185 u32 ipv6_tdip1 = entry->ipv4_dslite.tunnel_dipv6_1;
1186 u32 ipv6_tdip2 = entry->ipv4_dslite.tunnel_dipv6_2;
1187 u32 ipv6_tdip3 = entry->ipv4_dslite.tunnel_dipv6_3;
1188
1189 *((u32 *)h_source) = swab32(entry->ipv4_dslite.smac_hi);
1190 *((u16 *)&h_source[4]) =
1191 swab16(entry->ipv4_dslite.smac_lo);
1192 *((u32 *)h_dest) = swab32(entry->ipv4_dslite.dmac_hi);
1193 *((u16 *)&h_dest[4]) =
1194 swab16(entry->ipv4_dslite.dmac_lo);
developer30a47682021-11-02 17:06:14 +08001195 PRINT_COUNT(m, acct);
developerfd40db22021-04-29 10:08:25 +08001196 seq_printf(m,
developer471f6562021-05-10 20:48:34 +08001197 "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%pI4->DIP=%pI4|TSIP=%08x:%08x:%08x:%08x->TDIP=%08x:%08x:%08x:%08x|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x\n",
1198 entry, ppe_id, ei(entry, end),
1199 es(entry), pt(entry), &saddr,
developerfd40db22021-04-29 10:08:25 +08001200 &daddr, ipv6_tsip0, ipv6_tsip1, ipv6_tsip2,
1201 ipv6_tsip3, ipv6_tdip0, ipv6_tdip1, ipv6_tdip2,
1202 ipv6_tdip3, h_source, h_dest,
1203 ntohs(entry->ipv6_5t_route.etype),
1204 entry->ipv6_5t_route.info_blk1,
1205 entry->ipv6_5t_route.info_blk2);
developerd35bbcc2022-09-28 22:46:01 +08001206#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
developerfd40db22021-04-29 10:08:25 +08001207 } else if (IS_IPV4_MAPE(entry)) {
1208 __be32 saddr = htonl(entry->ipv4_dslite.sip);
1209 __be32 daddr = htonl(entry->ipv4_dslite.dip);
developerd35bbcc2022-09-28 22:46:01 +08001210 __be32 nsaddr = htonl(entry->ipv4_mape.new_sip);
1211 __be32 ndaddr = htonl(entry->ipv4_mape.new_dip);
developerfd40db22021-04-29 10:08:25 +08001212 u32 ipv6_tsip0 = entry->ipv4_dslite.tunnel_sipv6_0;
1213 u32 ipv6_tsip1 = entry->ipv4_dslite.tunnel_sipv6_1;
1214 u32 ipv6_tsip2 = entry->ipv4_dslite.tunnel_sipv6_2;
1215 u32 ipv6_tsip3 = entry->ipv4_dslite.tunnel_sipv6_3;
1216 u32 ipv6_tdip0 = entry->ipv4_dslite.tunnel_dipv6_0;
1217 u32 ipv6_tdip1 = entry->ipv4_dslite.tunnel_dipv6_1;
1218 u32 ipv6_tdip2 = entry->ipv4_dslite.tunnel_dipv6_2;
1219 u32 ipv6_tdip3 = entry->ipv4_dslite.tunnel_dipv6_3;
1220
1221 *((u32 *)h_source) = swab32(entry->ipv4_dslite.smac_hi);
1222 *((u16 *)&h_source[4]) =
1223 swab16(entry->ipv4_dslite.smac_lo);
1224 *((u32 *)h_dest) = swab32(entry->ipv4_dslite.dmac_hi);
1225 *((u16 *)&h_dest[4]) =
1226 swab16(entry->ipv4_dslite.dmac_lo);
developer30a47682021-11-02 17:06:14 +08001227 PRINT_COUNT(m, acct);
developerfd40db22021-04-29 10:08:25 +08001228 seq_printf(m,
developer471f6562021-05-10 20:48:34 +08001229 "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%pI4:%d->DIP=%pI4:%d|NSIP=%pI4:%d->NDIP=%pI4:%d|TSIP=%08x:%08x:%08x:%08x->TDIP=%08x:%08x:%08x:%08x|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x\n",
1230 entry, ppe_id, ei(entry, end),
1231 es(entry), pt(entry),
developerfd40db22021-04-29 10:08:25 +08001232 &saddr, entry->ipv4_dslite.sport,
1233 &daddr, entry->ipv4_dslite.dport,
developerd35bbcc2022-09-28 22:46:01 +08001234 &nsaddr, entry->ipv4_mape.new_sport,
1235 &ndaddr, entry->ipv4_mape.new_dport,
developerfd40db22021-04-29 10:08:25 +08001236 ipv6_tsip0, ipv6_tsip1, ipv6_tsip2,
1237 ipv6_tsip3, ipv6_tdip0, ipv6_tdip1,
1238 ipv6_tdip2, ipv6_tdip3, h_source, h_dest,
1239 ntohs(entry->ipv6_5t_route.etype),
1240 entry->ipv6_5t_route.info_blk1,
1241 entry->ipv6_5t_route.info_blk2);
1242#endif
1243 } else
developer471f6562021-05-10 20:48:34 +08001244 seq_printf(m, "addr=0x%p|ppe=%d|index=%d state=%s\n", entry, ppe_id, ei(entry, end),
developerfd40db22021-04-29 10:08:25 +08001245 es(entry));
1246 entry++;
1247 entry_index++;
1248 }
1249
1250 return 0;
1251}
1252
developer471f6562021-05-10 20:48:34 +08001253static int hnat_debug_show(struct seq_file *m, void *private)
1254{
1255 int i;
1256
1257 for (i = 0; i < CFG_PPE_NUM; i++)
1258 __hnat_debug_show(m, private, i);
1259
1260 return 0;
1261}
1262
developerfd40db22021-04-29 10:08:25 +08001263static int hnat_debug_open(struct inode *inode, struct file *file)
1264{
1265 return single_open(file, hnat_debug_show, file->private_data);
1266}
1267
1268static const struct file_operations hnat_debug_fops = {
1269 .open = hnat_debug_open,
1270 .read = seq_read,
1271 .llseek = seq_lseek,
1272 .release = single_release,
1273};
1274
1275static int hnat_whnat_show(struct seq_file *m, void *private)
1276{
1277 int i;
1278 struct net_device *dev;
1279
1280 for (i = 0; i < MAX_IF_NUM; i++) {
1281 dev = hnat_priv->wifi_hook_if[i];
1282 if (dev)
1283 seq_printf(m, "%d:%s\n", i, dev->name);
1284 else
1285 continue;
1286 }
1287
1288 return 0;
1289}
1290
1291static int hnat_whnat_open(struct inode *inode, struct file *file)
1292{
1293 return single_open(file, hnat_whnat_show, file->private_data);
1294}
1295
developerf0345dc2022-03-11 16:53:08 +08001296static ssize_t hnat_whnat_write(struct file *file, const char __user *buf,
1297 size_t length, loff_t *offset)
1298{
1299 char line[64] = {0};
1300 struct net_device *dev;
1301 int enable;
1302 char name[32];
1303 size_t size;
1304
1305 if (length >= sizeof(line))
1306 return -EINVAL;
1307
1308 if (copy_from_user(line, buf, length))
1309 return -EFAULT;
1310
developer659fdeb2022-12-01 23:03:07 +08001311 if (sscanf(line, "%15s %1d", name, &enable) != 2)
developerf0345dc2022-03-11 16:53:08 +08001312 return -EFAULT;
1313
1314 line[length] = '\0';
1315
1316 dev = dev_get_by_name(&init_net, name);
1317
1318 if (dev) {
1319 if (enable) {
1320 mtk_ppe_dev_register_hook(dev);
1321 pr_info("register wifi extern if = %s\n", dev->name);
1322 } else {
1323 mtk_ppe_dev_unregister_hook(dev);
1324 pr_info("unregister wifi extern if = %s\n", dev->name);
1325 }
developera7e6c242022-12-05 13:52:40 +08001326 dev_put(dev);
developerf0345dc2022-03-11 16:53:08 +08001327 } else {
1328 pr_info("no such device!\n");
1329 }
1330
1331 size = strlen(line);
1332 *offset += size;
1333
1334 return length;
1335}
1336
1337
developerfd40db22021-04-29 10:08:25 +08001338static const struct file_operations hnat_whnat_fops = {
1339 .open = hnat_whnat_open,
1340 .read = seq_read,
1341 .llseek = seq_lseek,
developerf0345dc2022-03-11 16:53:08 +08001342 .write = hnat_whnat_write,
developerfd40db22021-04-29 10:08:25 +08001343 .release = single_release,
1344};
1345
1346int cpu_reason_read(struct seq_file *m, void *private)
1347{
1348 int i;
1349
1350 pr_info("============ CPU REASON =========\n");
1351 pr_info("(2)IPv4(IPv6) TTL(hop limit) = %u\n", dbg_cpu_reason_cnt[0]);
1352 pr_info("(3)Ipv4(IPv6) has option(extension) header = %u\n",
1353 dbg_cpu_reason_cnt[1]);
1354 pr_info("(7)No flow is assigned = %u\n", dbg_cpu_reason_cnt[2]);
1355 pr_info("(8)IPv4 HNAT doesn't support IPv4 /w fragment = %u\n",
1356 dbg_cpu_reason_cnt[3]);
1357 pr_info("(9)IPv4 HNAPT/DS-Lite doesn't support IPv4 /w fragment = %u\n",
1358 dbg_cpu_reason_cnt[4]);
1359 pr_info("(10)IPv4 HNAPT/DS-Lite can't find TCP/UDP sport/dport = %u\n",
1360 dbg_cpu_reason_cnt[5]);
1361 pr_info("(11)IPv6 5T-route/6RD can't find TCP/UDP sport/dport = %u\n",
1362 dbg_cpu_reason_cnt[6]);
1363 pr_info("(12)Ingress packet is TCP fin/syn/rst = %u\n",
1364 dbg_cpu_reason_cnt[7]);
1365 pr_info("(13)FOE Un-hit = %u\n", dbg_cpu_reason_cnt[8]);
1366 pr_info("(14)FOE Hit unbind = %u\n", dbg_cpu_reason_cnt[9]);
1367 pr_info("(15)FOE Hit unbind & rate reach = %u\n",
1368 dbg_cpu_reason_cnt[10]);
1369 pr_info("(16)Hit bind PPE TCP FIN entry = %u\n",
1370 dbg_cpu_reason_cnt[11]);
1371 pr_info("(17)Hit bind PPE entry and TTL(hop limit) = 1 and TTL(hot limit) - 1 = %u\n",
1372 dbg_cpu_reason_cnt[12]);
1373 pr_info("(18)Hit bind and VLAN replacement violation = %u\n",
1374 dbg_cpu_reason_cnt[13]);
1375 pr_info("(19)Hit bind and keep alive with unicast old-header packet = %u\n",
1376 dbg_cpu_reason_cnt[14]);
1377 pr_info("(20)Hit bind and keep alive with multicast new-header packet = %u\n",
1378 dbg_cpu_reason_cnt[15]);
1379 pr_info("(21)Hit bind and keep alive with duplicate old-header packet = %u\n",
1380 dbg_cpu_reason_cnt[16]);
1381 pr_info("(22)FOE Hit bind & force to CPU = %u\n",
1382 dbg_cpu_reason_cnt[17]);
1383 pr_info("(28)Hit bind and exceed MTU =%u\n", dbg_cpu_reason_cnt[18]);
1384 pr_info("(24)Hit bind multicast packet to CPU = %u\n",
1385 dbg_cpu_reason_cnt[19]);
1386 pr_info("(25)Hit bind multicast packet to GMAC & CPU = %u\n",
1387 dbg_cpu_reason_cnt[20]);
1388 pr_info("(26)Pre bind = %u\n", dbg_cpu_reason_cnt[21]);
1389
1390 for (i = 0; i < 22; i++)
1391 dbg_cpu_reason_cnt[i] = 0;
1392 return 0;
1393}
1394
1395static int cpu_reason_open(struct inode *inode, struct file *file)
1396{
1397 return single_open(file, cpu_reason_read, file->private_data);
1398}
1399
1400ssize_t cpu_reason_write(struct file *file, const char __user *buffer,
1401 size_t count, loff_t *data)
1402{
1403 char buf[32];
1404 char *p_buf;
developer4c32b7a2021-11-13 16:46:43 +08001405 u32 len = count;
developerfd40db22021-04-29 10:08:25 +08001406 long arg0 = 0, arg1 = 0;
1407 char *p_token = NULL;
1408 char *p_delimiter = " \t";
1409 int ret;
1410
1411 if (len >= sizeof(buf)) {
1412 pr_info("input handling fail!\n");
developerfd40db22021-04-29 10:08:25 +08001413 return -1;
1414 }
1415
1416 if (copy_from_user(buf, buffer, len))
1417 return -EFAULT;
1418
1419 buf[len] = '\0';
1420
1421 p_buf = buf;
1422 p_token = strsep(&p_buf, p_delimiter);
1423 if (!p_token)
1424 arg0 = 0;
1425 else
1426 ret = kstrtol(p_token, 10, &arg0);
1427
1428 switch (arg0) {
1429 case 0:
1430 case 1:
1431 p_token = strsep(&p_buf, p_delimiter);
1432 if (!p_token)
1433 arg1 = 0;
1434 else
1435 ret = kstrtol(p_token, 10, &arg1);
1436 break;
1437 default:
1438 pr_info("no handler defined for command id(0x%08lx)\n\r", arg0);
1439 arg0 = 0;
1440 arg1 = 0;
1441 break;
1442 }
1443
1444 (*hnat_set_func[arg0])(arg1);
1445
1446 return len;
1447}
1448
1449static const struct file_operations cpu_reason_fops = {
1450 .open = cpu_reason_open,
1451 .read = seq_read,
1452 .llseek = seq_lseek,
1453 .write = cpu_reason_write,
1454 .release = single_release,
1455};
1456
1457void dbg_dump_entry(struct seq_file *m, struct foe_entry *entry,
1458 uint32_t index)
1459{
1460 __be32 saddr, daddr, nsaddr, ndaddr;
1461
1462 saddr = htonl(entry->ipv4_hnapt.sip);
1463 daddr = htonl(entry->ipv4_hnapt.dip);
1464 nsaddr = htonl(entry->ipv4_hnapt.new_sip);
1465 ndaddr = htonl(entry->ipv4_hnapt.new_dip);
1466
1467 if (IS_IPV4_HNAPT(entry)) {
1468 seq_printf(m,
1469 "NAPT(%d): %pI4:%d->%pI4:%d => %pI4:%d->%pI4:%d\n",
1470 index, &saddr, entry->ipv4_hnapt.sport, &daddr,
1471 entry->ipv4_hnapt.dport, &nsaddr,
1472 entry->ipv4_hnapt.new_sport, &ndaddr,
1473 entry->ipv4_hnapt.new_dport);
1474 } else if (IS_IPV4_HNAT(entry)) {
1475 seq_printf(m, "NAT(%d): %pI4->%pI4 => %pI4->%pI4\n",
1476 index, &saddr, &daddr, &nsaddr, &ndaddr);
1477 }
1478
1479 if (IS_IPV4_DSLITE(entry)) {
1480 seq_printf(m,
1481 "IPv4 Ds-Lite(%d): %pI4:%d->%pI4:%d => %08X:%08X:%08X:%08X->%08X:%08X:%08X:%08X\n",
1482 index, &saddr, entry->ipv4_dslite.sport, &daddr,
1483 entry->ipv4_dslite.dport,
1484 entry->ipv4_dslite.tunnel_sipv6_0,
1485 entry->ipv4_dslite.tunnel_sipv6_1,
1486 entry->ipv4_dslite.tunnel_sipv6_2,
1487 entry->ipv4_dslite.tunnel_sipv6_3,
1488 entry->ipv4_dslite.tunnel_dipv6_0,
1489 entry->ipv4_dslite.tunnel_dipv6_1,
1490 entry->ipv4_dslite.tunnel_dipv6_2,
1491 entry->ipv4_dslite.tunnel_dipv6_3);
developerd35bbcc2022-09-28 22:46:01 +08001492#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
developerfd40db22021-04-29 10:08:25 +08001493 } else if (IS_IPV4_MAPE(entry)) {
developerd35bbcc2022-09-28 22:46:01 +08001494 nsaddr = htonl(entry->ipv4_mape.new_sip);
1495 ndaddr = htonl(entry->ipv4_mape.new_dip);
developerfd40db22021-04-29 10:08:25 +08001496
1497 seq_printf(m,
1498 "IPv4 MAP-E(%d): %pI4:%d->%pI4:%d => %pI4:%d->%pI4:%d | Tunnel=%08X:%08X:%08X:%08X->%08X:%08X:%08X:%08X\n",
1499 index, &saddr, entry->ipv4_dslite.sport,
1500 &daddr, entry->ipv4_dslite.dport,
developerd35bbcc2022-09-28 22:46:01 +08001501 &nsaddr, entry->ipv4_mape.new_sport,
1502 &ndaddr, entry->ipv4_mape.new_dport,
developerfd40db22021-04-29 10:08:25 +08001503 entry->ipv4_dslite.tunnel_sipv6_0,
1504 entry->ipv4_dslite.tunnel_sipv6_1,
1505 entry->ipv4_dslite.tunnel_sipv6_2,
1506 entry->ipv4_dslite.tunnel_sipv6_3,
1507 entry->ipv4_dslite.tunnel_dipv6_0,
1508 entry->ipv4_dslite.tunnel_dipv6_1,
1509 entry->ipv4_dslite.tunnel_dipv6_2,
1510 entry->ipv4_dslite.tunnel_dipv6_3);
1511#endif
1512 } else if (IS_IPV6_3T_ROUTE(entry)) {
1513 seq_printf(m,
1514 "IPv6_3T(%d): %08X:%08X:%08X:%08X => %08X:%08X:%08X:%08X (Prot=%d)\n",
1515 index, entry->ipv6_3t_route.ipv6_sip0,
1516 entry->ipv6_3t_route.ipv6_sip1,
1517 entry->ipv6_3t_route.ipv6_sip2,
1518 entry->ipv6_3t_route.ipv6_sip3,
1519 entry->ipv6_3t_route.ipv6_dip0,
1520 entry->ipv6_3t_route.ipv6_dip1,
1521 entry->ipv6_3t_route.ipv6_dip2,
1522 entry->ipv6_3t_route.ipv6_dip3,
1523 entry->ipv6_3t_route.prot);
1524 } else if (IS_IPV6_5T_ROUTE(entry)) {
1525 seq_printf(m,
1526 "IPv6_5T(%d): %08X:%08X:%08X:%08X:%d => %08X:%08X:%08X:%08X:%d\n",
1527 index, entry->ipv6_5t_route.ipv6_sip0,
1528 entry->ipv6_5t_route.ipv6_sip1,
1529 entry->ipv6_5t_route.ipv6_sip2,
1530 entry->ipv6_5t_route.ipv6_sip3,
1531 entry->ipv6_5t_route.sport,
1532 entry->ipv6_5t_route.ipv6_dip0,
1533 entry->ipv6_5t_route.ipv6_dip1,
1534 entry->ipv6_5t_route.ipv6_dip2,
1535 entry->ipv6_5t_route.ipv6_dip3,
1536 entry->ipv6_5t_route.dport);
1537 } else if (IS_IPV6_6RD(entry)) {
1538 seq_printf(m,
1539 "IPv6_6RD(%d): %08X:%08X:%08X:%08X:%d => %08X:%08X:%08X:%08X:%d\n",
1540 index, entry->ipv6_6rd.ipv6_sip0,
1541 entry->ipv6_6rd.ipv6_sip1, entry->ipv6_6rd.ipv6_sip2,
1542 entry->ipv6_6rd.ipv6_sip3, entry->ipv6_6rd.sport,
1543 entry->ipv6_6rd.ipv6_dip0, entry->ipv6_6rd.ipv6_dip1,
1544 entry->ipv6_6rd.ipv6_dip2, entry->ipv6_6rd.ipv6_dip3,
1545 entry->ipv6_6rd.dport);
developer5ffc5f12022-10-25 18:51:46 +08001546#if defined(CONFIG_MEDIATEK_NETSYS_V3)
1547 } else if (IS_IPV6_HNAPT(entry)) {
1548 if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_SNAT) {
1549 seq_printf(m,
1550 "IPv6_HNAPT(%d): %08X:%08X:%08X:%08X:%d->%08X:%08X:%08X:%08X:%d => %08X:%08X:%08X:%08X:%d -> %08X:%08X:%08X:%08X:%d\n",
1551 index, entry->ipv6_hnapt.ipv6_sip0,
1552 entry->ipv6_hnapt.ipv6_sip1,
1553 entry->ipv6_hnapt.ipv6_sip2,
1554 entry->ipv6_hnapt.ipv6_sip3,
1555 entry->ipv6_hnapt.sport,
1556 entry->ipv6_hnapt.ipv6_dip0,
1557 entry->ipv6_hnapt.ipv6_dip1,
1558 entry->ipv6_hnapt.ipv6_dip2,
1559 entry->ipv6_hnapt.ipv6_dip3,
1560 entry->ipv6_hnapt.dport,
1561 entry->ipv6_hnapt.new_ipv6_ip0,
1562 entry->ipv6_hnapt.new_ipv6_ip1,
1563 entry->ipv6_hnapt.new_ipv6_ip2,
1564 entry->ipv6_hnapt.new_ipv6_ip3,
1565 entry->ipv6_hnapt.new_sport,
1566 entry->ipv6_hnapt.ipv6_dip0,
1567 entry->ipv6_hnapt.ipv6_dip1,
1568 entry->ipv6_hnapt.ipv6_dip2,
1569 entry->ipv6_hnapt.ipv6_dip3,
1570 entry->ipv6_hnapt.new_dport);
1571 } else if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_DNAT) {
1572 seq_printf(m,
1573 "IPv6_HNAPT(%d): %08X:%08X:%08X:%08X:%d->%08X:%08X:%08X:%08X:%d => %08X:%08X:%08X:%08X:%d -> %08X:%08X:%08X:%08X:%d\n",
1574 index, entry->ipv6_hnapt.ipv6_sip0,
1575 entry->ipv6_hnapt.ipv6_sip1,
1576 entry->ipv6_hnapt.ipv6_sip2,
1577 entry->ipv6_hnapt.ipv6_sip3,
1578 entry->ipv6_hnapt.sport,
1579 entry->ipv6_hnapt.ipv6_dip0,
1580 entry->ipv6_hnapt.ipv6_dip1,
1581 entry->ipv6_hnapt.ipv6_dip2,
1582 entry->ipv6_hnapt.ipv6_dip3,
1583 entry->ipv6_hnapt.dport,
1584 entry->ipv6_hnapt.ipv6_sip0,
1585 entry->ipv6_hnapt.ipv6_sip1,
1586 entry->ipv6_hnapt.ipv6_sip2,
1587 entry->ipv6_hnapt.ipv6_sip3,
1588 entry->ipv6_hnapt.new_sport,
1589 entry->ipv6_hnapt.new_ipv6_ip0,
1590 entry->ipv6_hnapt.new_ipv6_ip1,
1591 entry->ipv6_hnapt.new_ipv6_ip2,
1592 entry->ipv6_hnapt.new_ipv6_ip3,
1593 entry->ipv6_hnapt.new_dport);
1594 }
1595 } else if (IS_IPV6_HNAT(entry)) {
1596 if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_SNAT) {
1597 seq_printf(m,
1598 "IPv6_HNAT(%d): %08X:%08X:%08X:%08X->%08X:%08X:%08X:%08X => %08X:%08X:%08X:%08X -> %08X:%08X:%08X:%08X\n",
1599 index, entry->ipv6_hnapt.ipv6_sip0,
1600 entry->ipv6_hnapt.ipv6_sip1,
1601 entry->ipv6_hnapt.ipv6_sip2,
1602 entry->ipv6_hnapt.ipv6_sip3,
1603 entry->ipv6_hnapt.ipv6_dip0,
1604 entry->ipv6_hnapt.ipv6_dip1,
1605 entry->ipv6_hnapt.ipv6_dip2,
1606 entry->ipv6_hnapt.ipv6_dip3,
1607 entry->ipv6_hnapt.new_ipv6_ip0,
1608 entry->ipv6_hnapt.new_ipv6_ip1,
1609 entry->ipv6_hnapt.new_ipv6_ip2,
1610 entry->ipv6_hnapt.new_ipv6_ip3,
1611 entry->ipv6_hnapt.ipv6_dip0,
1612 entry->ipv6_hnapt.ipv6_dip1,
1613 entry->ipv6_hnapt.ipv6_dip2,
1614 entry->ipv6_hnapt.ipv6_dip3);
1615 } else if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_DNAT) {
1616 seq_printf(m,
1617 "IPv6_HNAT(%d): %08X:%08X:%08X:%08X->%08X:%08X:%08X:%08X => %08X:%08X:%08X:%08X -> %08X:%08X:%08X:%08X\n",
1618 index, entry->ipv6_hnapt.ipv6_sip0,
1619 entry->ipv6_hnapt.ipv6_sip1,
1620 entry->ipv6_hnapt.ipv6_sip2,
1621 entry->ipv6_hnapt.ipv6_sip3,
1622 entry->ipv6_hnapt.ipv6_dip0,
1623 entry->ipv6_hnapt.ipv6_dip1,
1624 entry->ipv6_hnapt.ipv6_dip2,
1625 entry->ipv6_hnapt.ipv6_dip3,
1626 entry->ipv6_hnapt.ipv6_sip0,
1627 entry->ipv6_hnapt.ipv6_sip1,
1628 entry->ipv6_hnapt.ipv6_sip2,
1629 entry->ipv6_hnapt.ipv6_sip3,
1630 entry->ipv6_hnapt.new_ipv6_ip0,
1631 entry->ipv6_hnapt.new_ipv6_ip1,
1632 entry->ipv6_hnapt.new_ipv6_ip2,
1633 entry->ipv6_hnapt.new_ipv6_ip3);
1634 }
1635#endif
developerfd40db22021-04-29 10:08:25 +08001636 }
1637}
1638
developer4c32b7a2021-11-13 16:46:43 +08001639int __hnat_entry_read(struct seq_file *m, void *private, u32 ppe_id)
developerfd40db22021-04-29 10:08:25 +08001640{
1641 struct mtk_hnat *h = hnat_priv;
1642 struct foe_entry *entry, *end;
1643 int hash_index;
1644 int cnt;
1645
developer4c32b7a2021-11-13 16:46:43 +08001646 if (ppe_id >= CFG_PPE_NUM)
1647 return -EINVAL;
1648
developerfd40db22021-04-29 10:08:25 +08001649 hash_index = 0;
1650 cnt = 0;
developer471f6562021-05-10 20:48:34 +08001651 entry = h->foe_table_cpu[ppe_id];
1652 end = h->foe_table_cpu[ppe_id] + hnat_priv->foe_etry_num;
1653
1654 seq_printf(m, "============================\n");
1655 seq_printf(m, "PPE_ID = %d\n", ppe_id);
developerfd40db22021-04-29 10:08:25 +08001656
1657 while (entry < end) {
1658 if (entry->bfib1.state == dbg_entry_state) {
1659 cnt++;
1660 dbg_dump_entry(m, entry, hash_index);
1661 }
1662 hash_index++;
1663 entry++;
1664 }
1665
1666 seq_printf(m, "Total State = %s cnt = %d\n",
1667 dbg_entry_state == 0 ?
1668 "Invalid" : dbg_entry_state == 1 ?
1669 "Unbind" : dbg_entry_state == 2 ?
1670 "BIND" : dbg_entry_state == 3 ?
1671 "FIN" : "Unknown", cnt);
1672
1673 return 0;
1674}
1675
developer471f6562021-05-10 20:48:34 +08001676int hnat_entry_read(struct seq_file *m, void *private)
1677{
1678 int i;
1679
1680 for (i = 0; i < CFG_PPE_NUM; i++)
1681 __hnat_entry_read(m, private, i);
1682
1683 return 0;
1684}
1685
developerfd40db22021-04-29 10:08:25 +08001686ssize_t hnat_entry_write(struct file *file, const char __user *buffer,
1687 size_t count, loff_t *data)
1688{
1689 char buf[32];
1690 char *p_buf;
developer4c32b7a2021-11-13 16:46:43 +08001691 u32 len = count;
developerfd40db22021-04-29 10:08:25 +08001692 long arg0 = 0, arg1 = 0;
1693 char *p_token = NULL;
1694 char *p_delimiter = " \t";
1695 int ret;
1696
1697 if (len >= sizeof(buf)) {
1698 pr_info("input handling fail!\n");
developerfd40db22021-04-29 10:08:25 +08001699 return -1;
1700 }
1701
1702 if (copy_from_user(buf, buffer, len))
1703 return -EFAULT;
1704
1705 buf[len] = '\0';
1706
1707 p_buf = buf;
1708 p_token = strsep(&p_buf, p_delimiter);
1709 if (!p_token)
1710 arg0 = 0;
1711 else
1712 ret = kstrtol(p_token, 10, &arg0);
1713
1714 switch (arg0) {
1715 case 0:
1716 case 1:
1717 case 2:
1718 case 3:
developer471f6562021-05-10 20:48:34 +08001719 case 4:
1720 case 5:
developerfd40db22021-04-29 10:08:25 +08001721 p_token = strsep(&p_buf, p_delimiter);
1722 if (!p_token)
1723 arg1 = 0;
1724 else
1725 ret = kstrtol(p_token, 10, &arg1);
1726 break;
1727 default:
1728 pr_info("no handler defined for command id(0x%08lx)\n\r", arg0);
1729 arg0 = 0;
1730 arg1 = 0;
1731 break;
1732 }
1733
1734 (*entry_set_func[arg0])(arg1);
1735
1736 return len;
1737}
1738
1739static int hnat_entry_open(struct inode *inode, struct file *file)
1740{
1741 return single_open(file, hnat_entry_read, file->private_data);
1742}
1743
1744static const struct file_operations hnat_entry_fops = {
1745 .open = hnat_entry_open,
1746 .read = seq_read,
1747 .llseek = seq_lseek,
1748 .write = hnat_entry_write,
1749 .release = single_release,
1750};
1751
developer4c32b7a2021-11-13 16:46:43 +08001752int __hnat_setting_read(struct seq_file *m, void *private, u32 ppe_id)
developerfd40db22021-04-29 10:08:25 +08001753{
1754 struct mtk_hnat *h = hnat_priv;
1755 int i;
1756 int cr_max;
1757
developer4c32b7a2021-11-13 16:46:43 +08001758 if (ppe_id >= CFG_PPE_NUM)
1759 return -EINVAL;
1760
developerfd40db22021-04-29 10:08:25 +08001761 cr_max = 319 * 4;
1762 for (i = 0; i < cr_max; i = i + 0x10) {
1763 pr_info("0x%p : 0x%08x 0x%08x 0x%08x 0x%08x\n",
developer471f6562021-05-10 20:48:34 +08001764 (void *)h->foe_table_dev[ppe_id] + i,
1765 readl(h->ppe_base[ppe_id] + i),
1766 readl(h->ppe_base[ppe_id] + i + 4),
1767 readl(h->ppe_base[ppe_id] + i + 8),
1768 readl(h->ppe_base[ppe_id] + i + 0xc));
developerfd40db22021-04-29 10:08:25 +08001769 }
1770
1771 return 0;
1772}
1773
developer471f6562021-05-10 20:48:34 +08001774int hnat_setting_read(struct seq_file *m, void *private)
1775{
1776 int i;
1777
1778 for (i = 0; i < CFG_PPE_NUM; i++)
1779 __hnat_setting_read(m, private, i);
1780
1781 return 0;
1782}
1783
developerfd40db22021-04-29 10:08:25 +08001784static int hnat_setting_open(struct inode *inode, struct file *file)
1785{
1786 return single_open(file, hnat_setting_read, file->private_data);
1787}
1788
1789ssize_t hnat_setting_write(struct file *file, const char __user *buffer,
1790 size_t count, loff_t *data)
1791{
1792 char buf[32];
1793 char *p_buf;
developer4c32b7a2021-11-13 16:46:43 +08001794 u32 len = count;
developerfd40db22021-04-29 10:08:25 +08001795 long arg0 = 0, arg1 = 0;
1796 char *p_token = NULL;
1797 char *p_delimiter = " \t";
1798 int ret;
1799
1800 if (len >= sizeof(buf)) {
1801 pr_info("input handling fail!\n");
developerfd40db22021-04-29 10:08:25 +08001802 return -1;
1803 }
1804
1805 if (copy_from_user(buf, buffer, len))
1806 return -EFAULT;
1807
1808 buf[len] = '\0';
1809
1810 p_buf = buf;
1811 p_token = strsep(&p_buf, p_delimiter);
1812 if (!p_token)
1813 arg0 = 0;
1814 else
1815 ret = kstrtol(p_token, 10, &arg0);
1816
1817 switch (arg0) {
1818 case 0:
1819 case 1:
1820 case 2:
1821 case 3:
1822 case 4:
1823 case 5:
1824 case 6:
developer30a47682021-11-02 17:06:14 +08001825 case 7:
developerfd40db22021-04-29 10:08:25 +08001826 p_token = strsep(&p_buf, p_delimiter);
1827 if (!p_token)
1828 arg1 = 0;
1829 else
1830 ret = kstrtol(p_token, 10, &arg1);
1831 break;
1832 default:
1833 pr_info("no handler defined for command id(0x%08lx)\n\r", arg0);
1834 arg0 = 0;
1835 arg1 = 0;
1836 break;
1837 }
1838
1839 (*cr_set_func[arg0])(arg1);
1840
1841 return len;
1842}
1843
1844static const struct file_operations hnat_setting_fops = {
1845 .open = hnat_setting_open,
1846 .read = seq_read,
1847 .llseek = seq_lseek,
1848 .write = hnat_setting_write,
1849 .release = single_release,
1850};
1851
developer4c32b7a2021-11-13 16:46:43 +08001852int __mcast_table_dump(struct seq_file *m, void *private, u32 ppe_id)
developerfd40db22021-04-29 10:08:25 +08001853{
1854 struct mtk_hnat *h = hnat_priv;
1855 struct ppe_mcast_h mcast_h;
1856 struct ppe_mcast_l mcast_l;
1857 u8 i, max;
1858 void __iomem *reg;
1859
developer4c32b7a2021-11-13 16:46:43 +08001860 if (ppe_id >= CFG_PPE_NUM)
1861 return -EINVAL;
1862
developerfd40db22021-04-29 10:08:25 +08001863 if (!h->pmcast)
1864 return 0;
1865
1866 max = h->pmcast->max_entry;
developer471f6562021-05-10 20:48:34 +08001867 pr_info("============================\n");
1868 pr_info("PPE_ID = %d\n", ppe_id);
developerfd40db22021-04-29 10:08:25 +08001869 pr_info("MAC | VID | PortMask | QosPortMask\n");
1870 for (i = 0; i < max; i++) {
1871 if (i < 0x10) {
developer471f6562021-05-10 20:48:34 +08001872 reg = h->ppe_base[ppe_id] + PPE_MCAST_H_0 + i * 8;
developerfd40db22021-04-29 10:08:25 +08001873 mcast_h.u.value = readl(reg);
developer471f6562021-05-10 20:48:34 +08001874 reg = h->ppe_base[ppe_id] + PPE_MCAST_L_0 + i * 8;
developerfd40db22021-04-29 10:08:25 +08001875 mcast_l.addr = readl(reg);
1876 } else {
1877 reg = h->fe_base + PPE_MCAST_H_10 + (i - 0x10) * 8;
1878 mcast_h.u.value = readl(reg);
1879 reg = h->fe_base + PPE_MCAST_L_10 + (i - 0x10) * 8;
1880 mcast_l.addr = readl(reg);
1881 }
1882 pr_info("%08x %d %c%c%c%c %c%c%c%c (QID=%d, mc_mpre_sel=%d)\n",
1883 mcast_l.addr,
1884 mcast_h.u.info.mc_vid,
1885 (mcast_h.u.info.mc_px_en & 0x08) ? '1' : '-',
1886 (mcast_h.u.info.mc_px_en & 0x04) ? '1' : '-',
1887 (mcast_h.u.info.mc_px_en & 0x02) ? '1' : '-',
1888 (mcast_h.u.info.mc_px_en & 0x01) ? '1' : '-',
1889 (mcast_h.u.info.mc_px_qos_en & 0x08) ? '1' : '-',
1890 (mcast_h.u.info.mc_px_qos_en & 0x04) ? '1' : '-',
1891 (mcast_h.u.info.mc_px_qos_en & 0x02) ? '1' : '-',
1892 (mcast_h.u.info.mc_px_qos_en & 0x01) ? '1' : '-',
1893 mcast_h.u.info.mc_qos_qid +
1894 ((mcast_h.u.info.mc_qos_qid54) << 4),
1895 mcast_h.u.info.mc_mpre_sel);
1896 }
1897
1898 return 0;
1899}
1900
developer471f6562021-05-10 20:48:34 +08001901int mcast_table_dump(struct seq_file *m, void *private)
1902{
1903 int i;
1904
1905 for (i = 0; i < CFG_PPE_NUM; i++)
1906 __mcast_table_dump(m, private, i);
1907
1908 return 0;
1909}
1910
developerfd40db22021-04-29 10:08:25 +08001911static int mcast_table_open(struct inode *inode, struct file *file)
1912{
1913 return single_open(file, mcast_table_dump, file->private_data);
1914}
1915
1916static const struct file_operations hnat_mcast_fops = {
1917 .open = mcast_table_open,
1918 .read = seq_read,
1919 .llseek = seq_lseek,
1920 .release = single_release,
1921};
1922
1923static int hnat_ext_show(struct seq_file *m, void *private)
1924{
1925 int i;
1926 struct extdev_entry *ext_entry;
1927
1928 for (i = 0; i < MAX_EXT_DEVS && hnat_priv->ext_if[i]; i++) {
1929 ext_entry = hnat_priv->ext_if[i];
1930 if (ext_entry->dev)
1931 seq_printf(m, "ext devices [%d] = %s (dev=%p, ifindex=%d)\n",
1932 i, ext_entry->name, ext_entry->dev,
1933 ext_entry->dev->ifindex);
1934 }
1935
1936 return 0;
1937}
1938
1939static int hnat_ext_open(struct inode *inode, struct file *file)
1940{
1941 return single_open(file, hnat_ext_show, file->private_data);
1942}
1943
1944static const struct file_operations hnat_ext_fops = {
1945 .open = hnat_ext_open,
1946 .read = seq_read,
1947 .llseek = seq_lseek,
1948 .release = single_release,
1949};
1950
1951static ssize_t hnat_sched_show(struct file *file, char __user *user_buf,
1952 size_t count, loff_t *ppos)
1953{
1954 long id = (long)file->private_data;
1955 struct mtk_hnat *h = hnat_priv;
1956 u32 qdma_tx_sch;
1957 int enable;
1958 int scheduling;
1959 int max_rate;
1960 char *buf;
1961 unsigned int len = 0, buf_len = 1500;
1962 ssize_t ret_cnt;
1963 int scheduler, i;
1964 u32 sch_reg;
1965
1966 buf = kzalloc(buf_len, GFP_KERNEL);
1967 if (!buf)
1968 return -ENOMEM;
1969
1970 if (hnat_priv->data->num_of_sch == 4)
1971 qdma_tx_sch = readl(h->fe_base + QDMA_TX_4SCH_BASE(id));
1972 else
1973 qdma_tx_sch = readl(h->fe_base + QDMA_TX_2SCH_BASE);
1974
1975 if (id & 0x1)
1976 qdma_tx_sch >>= 16;
1977 qdma_tx_sch &= 0xffff;
1978 enable = !!(qdma_tx_sch & BIT(11));
1979 scheduling = !!(qdma_tx_sch & BIT(15));
1980 max_rate = ((qdma_tx_sch >> 4) & 0x7f);
1981 qdma_tx_sch &= 0xf;
1982 while (qdma_tx_sch--)
1983 max_rate *= 10;
1984
1985 len += scnprintf(buf + len, buf_len - len,
1986 "EN\tScheduling\tMAX\tQueue#\n%d\t%s%16d\t", enable,
1987 (scheduling == 1) ? "WRR" : "SP", max_rate);
1988
1989 for (i = 0; i < MTK_QDMA_TX_NUM; i++) {
1990 cr_set_field(h->fe_base + QDMA_PAGE, QTX_CFG_PAGE,
1991 (i / NUM_OF_Q_PER_PAGE));
1992 sch_reg = readl(h->fe_base + QTX_SCH(i % NUM_OF_Q_PER_PAGE));
1993 if (hnat_priv->data->num_of_sch == 4)
1994 scheduler = (sch_reg >> 30) & 0x3;
1995 else
1996 scheduler = !!(sch_reg & BIT(31));
1997 if (id == scheduler)
1998 len += scnprintf(buf + len, buf_len - len, "%d ", i);
1999 }
2000
2001 len += scnprintf(buf + len, buf_len - len, "\n");
2002 if (len > buf_len)
2003 len = buf_len;
2004
2005 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
2006
2007 kfree(buf);
2008 return ret_cnt;
2009}
2010
2011static ssize_t hnat_sched_write(struct file *file, const char __user *buf,
2012 size_t length, loff_t *offset)
2013{
2014 long id = (long)file->private_data;
2015 struct mtk_hnat *h = hnat_priv;
developer4c32b7a2021-11-13 16:46:43 +08002016 char line[64] = {0};
developerfd40db22021-04-29 10:08:25 +08002017 int enable, rate, exp = 0, shift = 0;
2018 char scheduling[32];
2019 size_t size;
2020 u32 qdma_tx_sch;
2021 u32 val = 0;
2022
developerc316c852021-07-09 11:23:40 +08002023 if (length >= sizeof(line))
developerfd40db22021-04-29 10:08:25 +08002024 return -EINVAL;
2025
2026 if (copy_from_user(line, buf, length))
2027 return -EFAULT;
2028
developer659fdeb2022-12-01 23:03:07 +08002029 if (sscanf(line, "%1d %3s %9d", &enable, scheduling, &rate) != 3)
developerfd40db22021-04-29 10:08:25 +08002030 return -EFAULT;
2031
developer659fdeb2022-12-01 23:03:07 +08002032#if defined(CONFIG_MEDIATEK_NETSYS_V3)
2033 if (rate > 100000000 || rate < 0 ||
2034 rate > 100000000 || rate < 0)
2035#else
2036 if (rate > 10000000 || rate < 0 ||
2037 rate > 10000000 || rate < 0)
2038#endif
2039 return -EINVAL;
2040
developerfd40db22021-04-29 10:08:25 +08002041 while (rate > 127) {
2042 rate /= 10;
2043 exp++;
2044 }
2045
developerc316c852021-07-09 11:23:40 +08002046 line[length] = '\0';
2047
developerfd40db22021-04-29 10:08:25 +08002048 if (enable)
2049 val |= BIT(11);
2050 if (strcmp(scheduling, "sp") != 0)
2051 val |= BIT(15);
2052 val |= (rate & 0x7f) << 4;
2053 val |= exp & 0xf;
2054 if (id & 0x1)
2055 shift = 16;
2056
2057 if (hnat_priv->data->num_of_sch == 4)
2058 qdma_tx_sch = readl(h->fe_base + QDMA_TX_4SCH_BASE(id));
2059 else
2060 qdma_tx_sch = readl(h->fe_base + QDMA_TX_2SCH_BASE);
2061
2062 qdma_tx_sch &= ~(0xffff << shift);
2063 qdma_tx_sch |= val << shift;
2064 if (hnat_priv->data->num_of_sch == 4)
2065 writel(qdma_tx_sch, h->fe_base + QDMA_TX_4SCH_BASE(id));
2066 else
2067 writel(qdma_tx_sch, h->fe_base + QDMA_TX_2SCH_BASE);
2068
2069 size = strlen(line);
2070 *offset += size;
2071
2072 return length;
2073}
2074
2075static const struct file_operations hnat_sched_fops = {
2076 .open = simple_open,
2077 .read = hnat_sched_show,
2078 .write = hnat_sched_write,
2079 .llseek = default_llseek,
2080};
2081
2082static ssize_t hnat_queue_show(struct file *file, char __user *user_buf,
2083 size_t count, loff_t *ppos)
2084{
2085 struct mtk_hnat *h = hnat_priv;
2086 long id = (long)file->private_data;
2087 u32 qtx_sch;
2088 u32 qtx_cfg;
2089 int scheduler;
2090 int min_rate_en;
2091 int min_rate;
2092 int min_rate_exp;
2093 int max_rate_en;
2094 int max_weight;
2095 int max_rate;
2096 int max_rate_exp;
2097 char *buf;
2098 unsigned int len = 0, buf_len = 1500;
2099 ssize_t ret_cnt;
2100
2101 buf = kzalloc(buf_len, GFP_KERNEL);
2102 if (!buf)
2103 return -ENOMEM;
2104
2105 cr_set_field(h->fe_base + QDMA_PAGE, QTX_CFG_PAGE, (id / NUM_OF_Q_PER_PAGE));
2106 qtx_cfg = readl(h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
2107 qtx_sch = readl(h->fe_base + QTX_SCH(id % NUM_OF_Q_PER_PAGE));
2108 if (hnat_priv->data->num_of_sch == 4)
2109 scheduler = (qtx_sch >> 30) & 0x3;
2110 else
2111 scheduler = !!(qtx_sch & BIT(31));
2112 min_rate_en = !!(qtx_sch & BIT(27));
2113 min_rate = (qtx_sch >> 20) & 0x7f;
2114 min_rate_exp = (qtx_sch >> 16) & 0xf;
2115 max_rate_en = !!(qtx_sch & BIT(11));
2116 max_weight = (qtx_sch >> 12) & 0xf;
2117 max_rate = (qtx_sch >> 4) & 0x7f;
2118 max_rate_exp = qtx_sch & 0xf;
2119 while (min_rate_exp--)
2120 min_rate *= 10;
2121
2122 while (max_rate_exp--)
2123 max_rate *= 10;
2124
2125 len += scnprintf(buf + len, buf_len - len,
2126 "scheduler: %d\nhw resv: %d\nsw resv: %d\n", scheduler,
2127 (qtx_cfg >> 8) & 0xff, qtx_cfg & 0xff);
2128
developer4164cfe2022-12-01 11:27:41 +08002129 if (hnat_priv->data->version != MTK_HNAT_V1_1) {
developerfd40db22021-04-29 10:08:25 +08002130 /* Switch to debug mode */
2131 cr_set_field(h->fe_base + QTX_MIB_IF, MIB_ON_QTX_CFG, 1);
2132 cr_set_field(h->fe_base + QTX_MIB_IF, VQTX_MIB_EN, 1);
2133 qtx_cfg = readl(h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
2134 qtx_sch = readl(h->fe_base + QTX_SCH(id % NUM_OF_Q_PER_PAGE));
2135 len += scnprintf(buf + len, buf_len - len,
2136 "packet count: %u\n", qtx_cfg);
2137 len += scnprintf(buf + len, buf_len - len,
2138 "packet drop: %u\n\n", qtx_sch);
2139
2140 /* Recover to normal mode */
2141 cr_set_field(hnat_priv->fe_base + QTX_MIB_IF,
2142 MIB_ON_QTX_CFG, 0);
2143 cr_set_field(hnat_priv->fe_base + QTX_MIB_IF, VQTX_MIB_EN, 0);
2144 }
2145
2146 len += scnprintf(buf + len, buf_len - len,
2147 " EN RATE WEIGHT\n");
2148 len += scnprintf(buf + len, buf_len - len,
2149 "----------------------------\n");
2150 len += scnprintf(buf + len, buf_len - len,
2151 "max%5d%9d%9d\n", max_rate_en, max_rate, max_weight);
2152 len += scnprintf(buf + len, buf_len - len,
2153 "min%5d%9d -\n", min_rate_en, min_rate);
2154
2155 if (len > buf_len)
2156 len = buf_len;
2157
2158 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
2159
2160 kfree(buf);
2161 return ret_cnt;
2162}
2163
2164static ssize_t hnat_queue_write(struct file *file, const char __user *buf,
2165 size_t length, loff_t *offset)
2166{
2167 long id = (long)file->private_data;
2168 struct mtk_hnat *h = hnat_priv;
developer4c32b7a2021-11-13 16:46:43 +08002169 char line[64] = {0};
developerfd40db22021-04-29 10:08:25 +08002170 int max_enable, max_rate, max_exp = 0;
2171 int min_enable, min_rate, min_exp = 0;
2172 int weight;
2173 int resv;
2174 int scheduler;
2175 size_t size;
developer04f0ec82021-12-30 13:59:10 +08002176 u32 qtx_sch = 0;
developerfd40db22021-04-29 10:08:25 +08002177
2178 cr_set_field(h->fe_base + QDMA_PAGE, QTX_CFG_PAGE, (id / NUM_OF_Q_PER_PAGE));
developerc316c852021-07-09 11:23:40 +08002179 if (length >= sizeof(line))
developerfd40db22021-04-29 10:08:25 +08002180 return -EINVAL;
2181
2182 if (copy_from_user(line, buf, length))
2183 return -EFAULT;
2184
2185 if (sscanf(line, "%d %d %d %d %d %d %d", &scheduler, &min_enable, &min_rate,
2186 &max_enable, &max_rate, &weight, &resv) != 7)
2187 return -EFAULT;
2188
developerc316c852021-07-09 11:23:40 +08002189 line[length] = '\0';
2190
developer577ad2f2022-11-28 10:33:36 +08002191#if defined(CONFIG_MEDIATEK_NETSYS_V3)
2192 if (max_rate > 100000000 || max_rate < 0 ||
2193 min_rate > 100000000 || min_rate < 0)
2194#else
2195 if (max_rate > 10000000 || max_rate < 0 ||
2196 min_rate > 10000000 || min_rate < 0)
2197#endif
2198 return -EINVAL;
2199
developerfd40db22021-04-29 10:08:25 +08002200 while (max_rate > 127) {
2201 max_rate /= 10;
2202 max_exp++;
2203 }
2204
2205 while (min_rate > 127) {
2206 min_rate /= 10;
2207 min_exp++;
2208 }
2209
developerfd40db22021-04-29 10:08:25 +08002210 if (hnat_priv->data->num_of_sch == 4)
2211 qtx_sch |= (scheduler & 0x3) << 30;
2212 else
2213 qtx_sch |= (scheduler & 0x1) << 31;
2214 if (min_enable)
2215 qtx_sch |= BIT(27);
2216 qtx_sch |= (min_rate & 0x7f) << 20;
2217 qtx_sch |= (min_exp & 0xf) << 16;
2218 if (max_enable)
2219 qtx_sch |= BIT(11);
2220 qtx_sch |= (weight & 0xf) << 12;
2221 qtx_sch |= (max_rate & 0x7f) << 4;
2222 qtx_sch |= max_exp & 0xf;
2223 writel(qtx_sch, h->fe_base + QTX_SCH(id % NUM_OF_Q_PER_PAGE));
2224
2225 resv &= 0xff;
2226 qtx_sch = readl(h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
2227 qtx_sch &= 0xffff0000;
2228 qtx_sch |= (resv << 8) | resv;
2229 writel(qtx_sch, h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
2230
2231 size = strlen(line);
2232 *offset += size;
2233
2234 return length;
2235}
2236
2237static const struct file_operations hnat_queue_fops = {
2238 .open = simple_open,
2239 .read = hnat_queue_show,
2240 .write = hnat_queue_write,
2241 .llseek = default_llseek,
2242};
2243
2244static ssize_t hnat_ppd_if_write(struct file *file, const char __user *buffer,
2245 size_t count, loff_t *data)
2246{
2247 char buf[IFNAMSIZ];
2248 struct net_device *dev;
2249 char *p, *tmp;
2250
2251 if (count >= IFNAMSIZ)
2252 return -EFAULT;
2253
2254 memset(buf, 0, IFNAMSIZ);
2255 if (copy_from_user(buf, buffer, count))
2256 return -EFAULT;
2257
2258 tmp = buf;
2259 p = strsep(&tmp, "\n\r ");
2260 dev = dev_get_by_name(&init_net, p);
2261
2262 if (dev) {
2263 if (hnat_priv->g_ppdev)
2264 dev_put(hnat_priv->g_ppdev);
2265 hnat_priv->g_ppdev = dev;
2266
developer4c32b7a2021-11-13 16:46:43 +08002267 strncpy(hnat_priv->ppd, p, IFNAMSIZ - 1);
developerfd40db22021-04-29 10:08:25 +08002268 pr_info("hnat_priv ppd = %s\n", hnat_priv->ppd);
2269 } else {
2270 pr_info("no such device!\n");
2271 }
2272
2273 return count;
2274}
2275
2276static int hnat_ppd_if_read(struct seq_file *m, void *private)
2277{
2278 pr_info("hnat_priv ppd = %s\n", hnat_priv->ppd);
2279
2280 if (hnat_priv->g_ppdev) {
2281 pr_info("hnat_priv g_ppdev name = %s\n",
2282 hnat_priv->g_ppdev->name);
2283 } else {
2284 pr_info("hnat_priv g_ppdev is null!\n");
2285 }
2286
2287 return 0;
2288}
2289
2290static int hnat_ppd_if_open(struct inode *inode, struct file *file)
2291{
2292 return single_open(file, hnat_ppd_if_read, file->private_data);
2293}
2294
2295static const struct file_operations hnat_ppd_if_fops = {
2296 .open = hnat_ppd_if_open,
2297 .read = seq_read,
2298 .llseek = seq_lseek,
2299 .write = hnat_ppd_if_write,
2300 .release = single_release,
2301};
2302
2303static int hnat_mape_toggle_read(struct seq_file *m, void *private)
2304{
2305 pr_info("value=%d, %s is enabled now!\n", mape_toggle, (mape_toggle) ? "mape" : "ds-lite");
2306
2307 return 0;
2308}
2309
2310static int hnat_mape_toggle_open(struct inode *inode, struct file *file)
2311{
2312 return single_open(file, hnat_mape_toggle_read, file->private_data);
2313}
2314
2315static ssize_t hnat_mape_toggle_write(struct file *file, const char __user *buffer,
2316 size_t count, loff_t *data)
2317{
developer4c32b7a2021-11-13 16:46:43 +08002318 char buf = 0;
developer25fc8c02022-05-06 16:24:02 +08002319 int i;
2320 u32 ppe_cfg;
2321
2322 if ((count < 1) || copy_from_user(&buf, buffer, sizeof(buf)))
developerfd40db22021-04-29 10:08:25 +08002323 return -EFAULT;
2324
developer25fc8c02022-05-06 16:24:02 +08002325 if (buf == '1') {
developerfd40db22021-04-29 10:08:25 +08002326 pr_info("mape is going to be enabled, ds-lite is going to be disabled !\n");
2327 mape_toggle = 1;
developer25fc8c02022-05-06 16:24:02 +08002328 } else if (buf == '0') {
developerfd40db22021-04-29 10:08:25 +08002329 pr_info("ds-lite is going to be enabled, mape is going to be disabled !\n");
2330 mape_toggle = 0;
developer25fc8c02022-05-06 16:24:02 +08002331 } else {
2332 pr_info("Invalid parameter.\n");
2333 return -EFAULT;
2334 }
2335
2336 for (i = 0; i < CFG_PPE_NUM; i++) {
2337 ppe_cfg = readl(hnat_priv->ppe_base[i] + PPE_FLOW_CFG);
2338
2339 if (mape_toggle)
2340 ppe_cfg &= ~BIT_IPV4_DSL_EN;
2341 else
2342 ppe_cfg |= BIT_IPV4_DSL_EN;
2343
2344 writel(ppe_cfg, hnat_priv->ppe_base[i] + PPE_FLOW_CFG);
developerfd40db22021-04-29 10:08:25 +08002345 }
2346
developer25fc8c02022-05-06 16:24:02 +08002347 return count;
developerfd40db22021-04-29 10:08:25 +08002348}
2349
2350static const struct file_operations hnat_mape_toggle_fops = {
2351 .open = hnat_mape_toggle_open,
2352 .read = seq_read,
2353 .llseek = seq_lseek,
2354 .write = hnat_mape_toggle_write,
2355 .release = single_release,
2356};
2357
2358static int hnat_hook_toggle_read(struct seq_file *m, void *private)
2359{
2360 pr_info("value=%d, hook is %s now!\n", hook_toggle, (hook_toggle) ? "enabled" : "disabled");
2361
2362 return 0;
2363}
2364
2365static int hnat_hook_toggle_open(struct inode *inode, struct file *file)
2366{
2367 return single_open(file, hnat_hook_toggle_read, file->private_data);
2368}
2369
2370static ssize_t hnat_hook_toggle_write(struct file *file, const char __user *buffer,
2371 size_t count, loff_t *data)
2372{
developer4c32b7a2021-11-13 16:46:43 +08002373 char buf[8] = {0};
developerfd40db22021-04-29 10:08:25 +08002374 int len = count;
developer70cdf6e2021-12-07 18:58:35 +08002375 u32 id;
developerfd40db22021-04-29 10:08:25 +08002376
2377 if ((len > 8) || copy_from_user(buf, buffer, len))
2378 return -EFAULT;
2379
2380 if (buf[0] == '1' && !hook_toggle) {
2381 pr_info("hook is going to be enabled !\n");
2382 hnat_enable_hook();
developer70cdf6e2021-12-07 18:58:35 +08002383
2384 if (IS_PPPQ_MODE) {
2385 for (id = 0; id < MAX_PPPQ_PORT_NUM; id++)
2386 hnat_qos_shaper_ebl(id, 1);
2387 }
developerfd40db22021-04-29 10:08:25 +08002388 } else if (buf[0] == '0' && hook_toggle) {
2389 pr_info("hook is going to be disabled !\n");
2390 hnat_disable_hook();
developer70cdf6e2021-12-07 18:58:35 +08002391
2392 if (IS_PPPQ_MODE) {
2393 for (id = 0; id < MAX_PPPQ_PORT_NUM; id++)
2394 hnat_qos_shaper_ebl(id, 0);
2395 }
developerfd40db22021-04-29 10:08:25 +08002396 }
2397
2398 return len;
2399}
2400
2401static const struct file_operations hnat_hook_toggle_fops = {
2402 .open = hnat_hook_toggle_open,
2403 .read = seq_read,
2404 .llseek = seq_lseek,
2405 .write = hnat_hook_toggle_write,
2406 .release = single_release,
2407};
2408
developere8b7dfa2023-04-20 10:16:44 +08002409static int hnat_xlat_toggle_read(struct seq_file *m, void *private)
2410{
2411 pr_info("value=%d, xlat is %s now!\n",
2412 xlat_toggle, (xlat_toggle) ? "enabled" : "disabled");
2413
2414 return 0;
2415}
2416
2417static int hnat_xlat_toggle_open(struct inode *inode, struct file *file)
2418{
2419 return single_open(file, hnat_xlat_toggle_read, file->private_data);
2420}
2421
2422static ssize_t hnat_xlat_toggle_write(struct file *file,
2423 const char __user *buffer,
2424 size_t count, loff_t *data)
2425{
2426 char buf[8] = {0};
2427 int len = count;
2428 int i;
2429 u32 ppe_cfg;
2430
2431 if ((len > 8) || copy_from_user(buf, buffer, len))
2432 return -EFAULT;
2433
2434 if (buf[0] == '1' && !xlat_toggle) {
2435 pr_info("xlat is going to be enabled !\n");
2436 xlat_toggle = 1;
2437 } else if (buf[0] == '0' && xlat_toggle) {
2438 pr_info("xlat is going to be disabled !\n");
2439 xlat_toggle = 0;
2440 }
2441
2442 for (i = 0; i < CFG_PPE_NUM; i++) {
2443 ppe_cfg = readl(hnat_priv->ppe_base[i] + PPE_FLOW_CFG);
2444
2445 if (xlat_toggle)
2446 ppe_cfg |= BIT_IPV6_464XLAT_EN;
2447 else
2448 ppe_cfg &= ~BIT_IPV6_464XLAT_EN;
2449
2450 writel(ppe_cfg, hnat_priv->ppe_base[i] + PPE_FLOW_CFG);
2451 }
2452
2453 return len;
2454}
2455
2456static const struct file_operations hnat_xlat_toggle_fops = {
2457 .open = hnat_xlat_toggle_open,
2458 .read = seq_read,
2459 .llseek = seq_lseek,
2460 .write = hnat_xlat_toggle_write,
2461 .release = single_release,
2462};
2463
2464int mtk_ppe_get_xlat_v6_by_v4(u32 *ipv4, struct in6_addr *ipv6,
2465 struct in6_addr *prefix)
2466{
2467 struct mtk_hnat *h = hnat_priv;
2468 struct map46 *m = NULL;
2469
2470 list_for_each_entry(m, &h->xlat.map_list, list) {
2471 if (m->ipv4 == *ipv4) {
2472 memcpy(ipv6, &m->ipv6, sizeof(*ipv6));
2473 memcpy(prefix, &h->xlat.prefix, sizeof(*ipv6));
2474 return 0;
2475 }
2476 }
2477
2478 return -1;
2479}
2480
2481int mtk_ppe_get_xlat_v4_by_v6(struct in6_addr *ipv6, u32 *ipv4)
2482{
2483 struct mtk_hnat *h = hnat_priv;
2484 struct map46 *m = NULL;
2485
2486 list_for_each_entry(m, &h->xlat.map_list, list) {
2487 if (ipv6_addr_equal(ipv6, &m->ipv6)) {
2488 *ipv4 = m->ipv4;
2489 return 0;
2490 }
2491 }
2492
2493 return -1;
2494}
2495
2496static int hnat_xlat_cfg_read(struct seq_file *m, void *private)
2497{
2498 pr_info("\n464XLAT Config Command Usage:\n");
2499 pr_info("Show HQoS usage:\n");
2500 pr_info(" cat /sys/kernel/debug/hnat/xlat_cfg\n");
2501 pr_info("Set ipv6 prefix :\n");
2502 pr_info(" echo prefix <prefix> > /sys/kernel/debug/hnat/xlat_cfg\n");
2503 pr_info("Set ipv6 prefix len :\n");
2504 pr_info(" echo pfx_len <len> > /sys/kernel/debug/hnat/xlat_cfg\n");
2505 pr_info("Add map :\n");
2506 pr_info("echo map add <ipv4> <ipv6> > /sys/kernel/debug/hnat/xlat_cfg\n");
2507 pr_info("Delete map :\n");
2508 pr_info("echo map del <ipv4> <ipv6> > /sys/kernel/debug/hnat/xlat_cfg\n");
2509 pr_info("Show config:\n");
2510 pr_info("echo show > /sys/kernel/debug/hnat/xlat_cfg\n");
2511
2512 return 0;
2513}
2514
2515static int hnat_xlat_cfg_open(struct inode *inode, struct file *file)
2516{
2517 return single_open(file, hnat_xlat_cfg_read, file->private_data);
2518}
2519
2520static ssize_t hnat_xlat_cfg_write(struct file *file, const char __user *buffer,
2521 size_t count, loff_t *data)
2522{
2523 struct mtk_hnat *h = hnat_priv;
2524 int len = count;
2525 char buf[256] = {0}, v4_str[64] = {0}, v6_str[64] = {0};
2526 struct map46 *map = NULL, *m = NULL, *next = NULL;
2527 struct in6_addr ipv6;
2528 u32 ipv4;
2529
2530 if ((len > 256) || copy_from_user(buf, buffer, len))
2531 return -EFAULT;
2532
2533 if (!strncmp(buf, "prefix", 6)) {
2534 if (sscanf(buf, "prefix %s\n", v6_str) != 1) {
2535 pr_info("input error\n");
2536 return -1;
2537 }
2538
2539 in6_pton(v6_str, -1, (u8 *)&h->xlat.prefix, -1, NULL);
2540 pr_info("set prefix = %pI6\n", &h->xlat.prefix);
2541 } else if (!strncmp(buf, "pfx_len", 7)) {
2542 if (sscanf(buf, "pfx_len %d", &h->xlat.prefix_len) != 1) {
2543 pr_info("input error\n");
2544 return -1;
2545 }
2546
2547 pr_info("set pfx_len = %d\n", h->xlat.prefix_len);
2548 } else if (!strncmp(buf, "map add", 7)) {
2549 if (sscanf(buf, "map add %s %s\n", v4_str, v6_str) != 2) {
2550 pr_info("input error\n");
2551 return -1;
2552 }
2553
2554 map = kmalloc(sizeof(struct map46), GFP_KERNEL);
2555 if (!map)
2556 return -1;
2557
2558 in4_pton(v4_str, -1, (u8 *)&map->ipv4, -1, NULL);
2559 in6_pton(v6_str, -1, (u8 *)&map->ipv6, -1, NULL);
2560 list_for_each_entry(m, &h->xlat.map_list, list) {
2561 if (ipv6_addr_equal(&map->ipv6, &m->ipv6) &&
2562 map->ipv4 == m->ipv4) {
2563 pr_info("this map already added.\n");
2564 kfree(map);
2565 return -1;
2566 }
2567 }
2568
2569 list_add(&map->list, &h->xlat.map_list);
2570 pr_info("add map: %pI4<=>%pI6\n", &map->ipv4, &map->ipv6);
2571 } else if (!strncmp(buf, "map del", 7)) {
2572 if (sscanf(buf, "map del %s %s\n", v4_str, v6_str) != 2) {
2573 pr_info("input error\n");
2574 return -1;
2575 }
2576
2577 in4_pton(v4_str, -1, (u8 *)&ipv4, -1, NULL);
2578 in6_pton(v6_str, -1, (u8 *)&ipv6, -1, NULL);
2579
2580 list_for_each_entry_safe(m, next, &h->xlat.map_list, list) {
2581 if (ipv6_addr_equal(&ipv6, &m->ipv6) &&
2582 ipv4 == m->ipv4) {
2583 list_del(&m->list);
2584 kfree(m);
2585 pr_info("del map: %s<=>%s\n", v4_str, v6_str);
2586 return len;
2587 }
2588 }
2589
2590 pr_info("not found map: %s<=>%s\n", v4_str, v6_str);
2591 } else if (!strncmp(buf, "show", 4)) {
2592 pr_info("prefix=%pI6\n", &h->xlat.prefix);
2593 pr_info("prefix_len=%d\n", h->xlat.prefix_len);
2594
2595 list_for_each_entry(m, &h->xlat.map_list, list) {
2596 pr_info("map: %pI4<=>%pI6\n", &m->ipv4, &m->ipv6);
2597 }
2598 } else {
2599 pr_info("input error\n");
2600 return -1;
2601 }
2602
2603 return len;
2604}
2605
2606static const struct file_operations hnat_xlat_cfg_fops = {
2607 .open = hnat_xlat_cfg_open,
2608 .read = seq_read,
2609 .llseek = seq_lseek,
2610 .write = hnat_xlat_cfg_write,
2611 .release = single_release,
2612};
2613
developer47545a32022-11-15 16:06:58 +08002614static void hnat_qos_toggle_usage(void)
2615{
2616 pr_info("\nHQoS toggle Command Usage:\n");
2617 pr_info("Show HQoS mode:\n");
2618 pr_info(" cat /sys/kernel/debug/hnat/qos_toggle\n");
2619 pr_info("Disable HQoS mode:\n");
2620 pr_info(" echo 0 > /sys/kernel/debug/hnat/qos_toggle\n");
2621 pr_info("Enable HQoS on bidirection:\n");
2622 pr_info(" echo 1 > /sys/kernel/debug/hnat/qos_toggle\n");
2623 pr_info("Enable HQoS on uplink only:\n");
2624 pr_info(" echo 1 uplink > /sys/kernel/debug/hnat/qos_toggle\n");
2625 pr_info("Enable HQoS on downlink only:\n");
2626 pr_info(" echo 1 downlink > /sys/kernel/debug/hnat/qos_toggle\n");
2627 pr_info("Enable Per-port-per-queue mode:\n");
2628 pr_info(" echo 2 > /sys/kernel/debug/hnat/qos_toggle\n");
2629 pr_info("Show HQoS toggle usage:\n");
2630 pr_info(" echo 3 > /sys/kernel/debug/hnat/qos_toggle\n\n");
2631}
2632
developeraf07fad2021-11-19 17:53:42 +08002633static int hnat_qos_toggle_read(struct seq_file *m, void *private)
2634{
developer47545a32022-11-15 16:06:58 +08002635 if (qos_toggle == 0) {
2636 pr_info("HQoS is disabled now!\n");
2637 } else if (qos_toggle == 1) {
2638 pr_info("HQoS is enabled now!\n");
2639 pr_info("HQoS uplink is %s now!\n",
2640 qos_ul_toggle ? "enabled" : "disabled");
2641 pr_info("HQoS downlink is %s now!\n",
2642 qos_dl_toggle ? "enabled" : "disabled");
2643 } else if (qos_toggle == 2) {
2644 pr_info("Per-port-per-queue mode is enabled!\n");
2645 }
developeraf07fad2021-11-19 17:53:42 +08002646
2647 return 0;
2648}
2649
2650static int hnat_qos_toggle_open(struct inode *inode, struct file *file)
2651{
2652 return single_open(file, hnat_qos_toggle_read, file->private_data);
2653}
2654
developer70cdf6e2021-12-07 18:58:35 +08002655void hnat_qos_shaper_ebl(u32 id, u32 enable)
2656{
2657 struct mtk_hnat *h = hnat_priv;
2658 u32 cfg;
2659
2660 if (enable) {
2661 cfg = QTX_SCH_MIN_RATE_EN | QTX_SCH_MAX_RATE_EN;
2662 cfg |= (1 << QTX_SCH_MIN_RATE_MAN_OFFSET) |
2663 (4 << QTX_SCH_MIN_RATE_EXP_OFFSET) |
2664 (25 << QTX_SCH_MAX_RATE_MAN_OFFSET) |
2665 (5 << QTX_SCH_MAX_RATE_EXP_OFFSET) |
2666 (4 << QTX_SCH_MAX_RATE_WGHT_OFFSET);
2667
2668 writel(cfg, h->fe_base + QTX_SCH(id % NUM_OF_Q_PER_PAGE));
2669 } else {
2670 writel(0, h->fe_base + QTX_SCH(id % NUM_OF_Q_PER_PAGE));
2671 }
2672}
2673
2674static void hnat_qos_disable(void)
2675{
2676 struct mtk_hnat *h = hnat_priv;
developer34028fb2022-01-11 13:51:29 +08002677 u32 id, cfg;
developer70cdf6e2021-12-07 18:58:35 +08002678
2679 for (id = 0; id < MAX_PPPQ_PORT_NUM; id++) {
2680 hnat_qos_shaper_ebl(id, 0);
developer34028fb2022-01-11 13:51:29 +08002681 writel((4 << QTX_CFG_HW_RESV_CNT_OFFSET) |
2682 (4 << QTX_CFG_SW_RESV_CNT_OFFSET),
2683 h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
developer70cdf6e2021-12-07 18:58:35 +08002684 }
2685
developer34028fb2022-01-11 13:51:29 +08002686 cfg = (QDMA_TX_SCH_WFQ_EN) | (QDMA_TX_SCH_WFQ_EN << 16);
developer70cdf6e2021-12-07 18:58:35 +08002687 for (id = 0; id < h->data->num_of_sch; id += 2) {
2688 if (h->data->num_of_sch == 4)
developer34028fb2022-01-11 13:51:29 +08002689 writel(cfg, h->fe_base + QDMA_TX_4SCH_BASE(id));
developer70cdf6e2021-12-07 18:58:35 +08002690 else
developer34028fb2022-01-11 13:51:29 +08002691 writel(cfg, h->fe_base + QDMA_TX_2SCH_BASE);
developer70cdf6e2021-12-07 18:58:35 +08002692 }
2693}
2694
developer24948202021-11-24 17:38:27 +08002695static void hnat_qos_pppq_enable(void)
2696{
developer70cdf6e2021-12-07 18:58:35 +08002697 struct mtk_hnat *h = hnat_priv;
developer34028fb2022-01-11 13:51:29 +08002698 u32 id, cfg;
developer24948202021-11-24 17:38:27 +08002699
developer70cdf6e2021-12-07 18:58:35 +08002700 for (id = 0; id < MAX_PPPQ_PORT_NUM; id++) {
2701 if (hook_toggle)
2702 hnat_qos_shaper_ebl(id, 1);
2703 else
2704 hnat_qos_shaper_ebl(id, 0);
developer24948202021-11-24 17:38:27 +08002705
developer70cdf6e2021-12-07 18:58:35 +08002706 writel((4 << QTX_CFG_HW_RESV_CNT_OFFSET) |
2707 (4 << QTX_CFG_SW_RESV_CNT_OFFSET),
2708 h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
2709 }
developer24948202021-11-24 17:38:27 +08002710
developer34028fb2022-01-11 13:51:29 +08002711 cfg = (QDMA_TX_SCH_WFQ_EN) | (QDMA_TX_SCH_WFQ_EN << 16);
developer70cdf6e2021-12-07 18:58:35 +08002712 for (id = 0; id < h->data->num_of_sch; id+= 2) {
2713 if (h->data->num_of_sch == 4)
developer34028fb2022-01-11 13:51:29 +08002714 writel(cfg, h->fe_base + QDMA_TX_4SCH_BASE(id));
developer70cdf6e2021-12-07 18:58:35 +08002715 else
developer34028fb2022-01-11 13:51:29 +08002716 writel(cfg, h->fe_base + QDMA_TX_2SCH_BASE);
developer24948202021-11-24 17:38:27 +08002717 }
2718}
2719
developeraf07fad2021-11-19 17:53:42 +08002720static ssize_t hnat_qos_toggle_write(struct file *file, const char __user *buffer,
2721 size_t count, loff_t *data)
2722{
developer577ad2f2022-11-28 10:33:36 +08002723 char buf[32] = {0}, tmp[32];
developeraf07fad2021-11-19 17:53:42 +08002724 int len = count;
developer47545a32022-11-15 16:06:58 +08002725 char *p_buf = NULL, *p_token = NULL;
developeraf07fad2021-11-19 17:53:42 +08002726
developer47545a32022-11-15 16:06:58 +08002727 if (len >= sizeof(buf))
2728 return -EFAULT;
2729
2730 if (copy_from_user(buf, buffer, len))
developeraf07fad2021-11-19 17:53:42 +08002731 return -EFAULT;
2732
developer47545a32022-11-15 16:06:58 +08002733 buf[len] = '\0';
2734
developer24948202021-11-24 17:38:27 +08002735 if (buf[0] == '0') {
developer47545a32022-11-15 16:06:58 +08002736 pr_info("HQoS is going to be disabled!\n");
developeraf07fad2021-11-19 17:53:42 +08002737 qos_toggle = 0;
developer47545a32022-11-15 16:06:58 +08002738 qos_dl_toggle = 0;
2739 qos_ul_toggle = 0;
developer70cdf6e2021-12-07 18:58:35 +08002740 hnat_qos_disable();
developer24948202021-11-24 17:38:27 +08002741 } else if (buf[0] == '1') {
developer47545a32022-11-15 16:06:58 +08002742 p_buf = buf;
2743 p_token = strsep(&p_buf, " \t");
2744 if (p_buf) {
2745 memcpy(tmp, p_buf, strlen(p_buf));
2746 tmp[len] = '\0';
2747 if (!strncmp(tmp, "uplink", 6)) {
2748 qos_dl_toggle = 0;
2749 qos_ul_toggle = 1;
2750 } else if (!strncmp(tmp, "downlink", 8)) {
2751 qos_ul_toggle = 0;
2752 qos_dl_toggle = 1;
2753 } else {
2754 pr_info("Direction should be uplink or downlink.\n");
2755 hnat_qos_toggle_usage();
2756 return len;
2757 }
2758 } else {
2759 qos_ul_toggle = 1;
2760 qos_dl_toggle = 1;
2761 }
2762 pr_info("HQoS mode is going to be enabled!\n");
2763 pr_info("HQoS uplink is going to be %s!\n",
2764 qos_ul_toggle ? "enabled" : "disabled");
2765 pr_info("HQoS downlink is going to be %s!\n",
2766 qos_dl_toggle ? "enabled" : "disabled");
developeraf07fad2021-11-19 17:53:42 +08002767 qos_toggle = 1;
developer24948202021-11-24 17:38:27 +08002768 } else if (buf[0] == '2') {
developer47545a32022-11-15 16:06:58 +08002769 pr_info("Per-port-per-queue mode is going to be enabled!\n");
developerafff5662022-06-29 10:09:56 +08002770 pr_info("PPPQ use qid 0~5 (scheduler 0).\n");
developeraf07fad2021-11-19 17:53:42 +08002771 qos_toggle = 2;
developer934756a2022-11-18 14:51:34 +08002772 qos_dl_toggle = 1;
2773 qos_ul_toggle = 1;
developer24948202021-11-24 17:38:27 +08002774 hnat_qos_pppq_enable();
developer47545a32022-11-15 16:06:58 +08002775 } else if (buf[0] == '3') {
2776 hnat_qos_toggle_usage();
2777 } else {
2778 pr_info("Input error!\n");
2779 hnat_qos_toggle_usage();
developeraf07fad2021-11-19 17:53:42 +08002780 }
2781
2782 return len;
2783}
2784
2785static const struct file_operations hnat_qos_toggle_fops = {
2786 .open = hnat_qos_toggle_open,
2787 .read = seq_read,
2788 .llseek = seq_lseek,
2789 .write = hnat_qos_toggle_write,
2790 .release = single_release,
2791};
2792
developerfd40db22021-04-29 10:08:25 +08002793static int hnat_version_read(struct seq_file *m, void *private)
2794{
2795 pr_info("HNAT SW version : %s\nHNAT HW version : %d\n", HNAT_SW_VER, hnat_priv->data->version);
2796
2797 return 0;
2798}
2799
2800static int hnat_version_open(struct inode *inode, struct file *file)
2801{
2802 return single_open(file, hnat_version_read, file->private_data);
2803}
2804
2805static const struct file_operations hnat_version_fops = {
2806 .open = hnat_version_open,
2807 .read = seq_read,
2808 .llseek = seq_lseek,
2809 .release = single_release,
2810};
2811
developere8b7dfa2023-04-20 10:16:44 +08002812u32 hnat_get_ppe_hash(struct foe_entry *entry)
developeraeafc442022-10-14 09:10:50 +08002813{
developere8b7dfa2023-04-20 10:16:44 +08002814 u32 hv1, hv2, hv3, hash;
2815
2816 switch (entry->bfib1.pkt_type) {
2817 case IPV4_HNAPT:
2818 case IPV4_HNAT:
2819 case IPV4_DSLITE:
2820 hv1 = entry->ipv4_hnapt.sport << 16 | entry->ipv4_hnapt.dport;
2821 hv2 = entry->ipv4_hnapt.dip;
2822 hv3 = entry->ipv4_hnapt.sip;
2823 break;
2824 case IPV6_3T_ROUTE:
2825 case IPV6_5T_ROUTE:
2826 case IPV6_6RD:
2827 hv1 = entry->ipv6_5t_route.ipv6_sip3 ^
2828 entry->ipv6_5t_route.ipv6_dip3;
2829 hv1 ^= entry->ipv6_5t_route.sport << 16 |
2830 entry->ipv6_5t_route.dport;
2831 hv2 = entry->ipv6_5t_route.ipv6_sip2 ^
2832 entry->ipv6_5t_route.ipv6_dip2;
2833 hv2 ^= entry->ipv6_5t_route.ipv6_dip0;
2834 hv3 = entry->ipv6_5t_route.ipv6_sip1 ^
2835 entry->ipv6_5t_route.ipv6_dip1;
2836 hv3 ^= entry->ipv6_5t_route.ipv6_sip0;
2837 break;
2838 }
developeraeafc442022-10-14 09:10:50 +08002839
2840 hash = (hv1 & hv2) | ((~hv1) & hv3);
2841 hash = (hash >> 24) | ((hash & 0xffffff) << 8);
2842 hash ^= hv1 ^ hv2 ^ hv3;
2843 hash ^= hash >> 16;
2844 hash <<= 2;
2845 hash &= hnat_priv->foe_etry_num - 1;
2846
2847 return hash;
2848}
2849
2850static u32 hnat_char2hex(const char c)
2851{
2852 switch (c) {
2853 case '0'...'9':
2854 return 0x0 + (c - '0');
2855 case 'a'...'f':
2856 return 0xa + (c - 'a');
2857 case 'A'...'F':
2858 return 0xa + (c - 'A');
2859 default:
2860 pr_info("MAC format error\n");
2861 return 0;
2862 }
2863}
2864
2865static void hnat_parse_mac(char *str, char *mac)
2866{
2867 int i;
2868
2869 for (i = 0; i < ETH_ALEN; i++) {
2870 mac[i] = (hnat_char2hex(str[i * 3]) << 4) +
2871 (hnat_char2hex(str[i * 3 + 1]));
2872 }
2873}
2874
2875static void hnat_static_entry_help(void)
2876{
2877 pr_info("-------------------- Usage --------------------\n");
2878#if defined(CONFIG_MEDIATEK_NETSYS_V3)
2879 pr_info("echo $0 $1 $2 ... $15 > /sys/kernel/debug/hnat/static_entry\n\n");
2880#else
2881 pr_info("echo $0 $1 $2 ... $12 > /sys/kernel/debug/hnat/static_entry\n\n");
2882#endif
2883
2884 pr_info("-------------------- Parameters --------------------\n");
2885 pr_info("$0: HASH OCT\n");
2886 pr_info("$1: INFO1 HEX\n");
2887 pr_info("$2: ING SIPv4 HEX\n");
2888 pr_info("$3: ING DIPv4 HEX\n");
2889 pr_info("$4: ING SP HEX\n");
2890 pr_info("$5: ING DP HEX\n");
2891 pr_info("$6: INFO2 HEX\n");
2892 pr_info("$7: EG SIPv4 HEX\n");
2893 pr_info("$8: EG DIPv4 HEX\n");
2894 pr_info("$9: EG SP HEX\n");
2895 pr_info("$10: EG DP HEX\n");
2896 pr_info("$11: DMAC STR (00:11:22:33:44:55)\n");
2897 pr_info("$12: SMAC STR (00:11:22:33:44:55)\n");
2898#if defined(CONFIG_MEDIATEK_NETSYS_V3)
2899 pr_info("$13: TPORT IDX HEX\n");
2900 pr_info("$14: TOPS ENTRY HEX\n");
2901 pr_info("$15: CDRT IDX HEX\n");
2902#endif
2903}
2904
2905static int hnat_static_entry_read(struct seq_file *m, void *private)
2906{
2907 hnat_static_entry_help();
2908
2909 return 0;
2910}
2911
2912static int hnat_static_entry_open(struct inode *inode, struct file *file)
2913{
2914 return single_open(file, hnat_static_entry_read, file->private_data);
2915}
2916
2917static ssize_t hnat_static_entry_write(struct file *file,
2918 const char __user *buffer,
2919 size_t count, loff_t *data)
2920{
2921 struct foe_entry *foe, entry = { 0 };
2922 char buf[256], dmac_str[18], smac_str[18], dmac[6], smac[6];
2923 int len = count, hash, coll = 0;
2924 u32 ppe_id = 0;
2925#if defined(CONFIG_MEDIATEK_NETSYS_V3)
2926 u32 tport_id, tops_entry, cdrt_id;
2927#endif
2928
2929 if (len >= sizeof(buf) || copy_from_user(buf, buffer, len)) {
2930 pr_info("Input handling fail!\n");
2931 len = sizeof(buf) - 1;
2932 return -EFAULT;
2933 }
2934
2935 buf[len] = '\0';
2936#if defined(CONFIG_MEDIATEK_NETSYS_V3)
developer659fdeb2022-12-01 23:03:07 +08002937 if (sscanf(buf,
2938 "%5d %8x %8x %8x %hx %hx %8x %8x %8x %hx %hx %18s %18s %4x %4x %4x",
developer577ad2f2022-11-28 10:33:36 +08002939 &hash,
2940 &entry.ipv4_hnapt.info_blk1,
2941 &entry.ipv4_hnapt.sip,
2942 &entry.ipv4_hnapt.dip,
2943 &entry.ipv4_hnapt.sport,
2944 &entry.ipv4_hnapt.dport,
2945 &entry.ipv4_hnapt.info_blk2,
2946 &entry.ipv4_hnapt.new_sip,
2947 &entry.ipv4_hnapt.new_dip,
2948 &entry.ipv4_hnapt.new_sport,
2949 &entry.ipv4_hnapt.new_dport,
2950 dmac_str, smac_str, &tport_id, &tops_entry, &cdrt_id) != 16)
2951 return -EFAULT;
developeraeafc442022-10-14 09:10:50 +08002952
developer659fdeb2022-12-01 23:03:07 +08002953 if ((hash >= (int)hnat_priv->foe_etry_num) || (hash < -1) ||
2954 (TPORT_ID(tport_id) != tport_id) ||
2955 (TOPS_ENTRY(tops_entry) != tops_entry) ||
2956 (CDRT_ID(cdrt_id) != cdrt_id)) {
developeraeafc442022-10-14 09:10:50 +08002957 hnat_static_entry_help();
developer577ad2f2022-11-28 10:33:36 +08002958 return -EFAULT;
developeraeafc442022-10-14 09:10:50 +08002959 }
developer659fdeb2022-12-01 23:03:07 +08002960
2961 entry.ipv4_hnapt.tport_id = tport_id;
2962 entry.ipv4_hnapt.tops_entry = tops_entry;
2963 entry.ipv4_hnapt.cdrt_id = cdrt_id;
developeraeafc442022-10-14 09:10:50 +08002964#else
developer659fdeb2022-12-01 23:03:07 +08002965 if (sscanf(buf,
2966 "%5d %8x %8x %8x %hx %hx %8x %8x %8x %hx %hx %18s %18s",
developer577ad2f2022-11-28 10:33:36 +08002967 &hash,
2968 &entry.ipv4_hnapt.info_blk1,
2969 &entry.ipv4_hnapt.sip,
2970 &entry.ipv4_hnapt.dip,
2971 &entry.ipv4_hnapt.sport,
2972 &entry.ipv4_hnapt.dport,
2973 &entry.ipv4_hnapt.info_blk2,
2974 &entry.ipv4_hnapt.new_sip,
2975 &entry.ipv4_hnapt.new_dip,
2976 &entry.ipv4_hnapt.new_sport,
2977 &entry.ipv4_hnapt.new_dport,
2978 dmac_str, smac_str) != 13)
2979 return -EFAULT;
developeraeafc442022-10-14 09:10:50 +08002980
developer659fdeb2022-12-01 23:03:07 +08002981 if ((hash >= (int)hnat_priv->foe_etry_num) || (hash < -1)) {
developeraeafc442022-10-14 09:10:50 +08002982 hnat_static_entry_help();
developer577ad2f2022-11-28 10:33:36 +08002983 return -EFAULT;
developeraeafc442022-10-14 09:10:50 +08002984 }
2985#endif
2986
2987 hnat_parse_mac(smac_str, smac);
2988 hnat_parse_mac(dmac_str, dmac);
2989 entry.ipv4_hnapt.dmac_hi = swab32(*((u32 *)dmac));
2990 entry.ipv4_hnapt.dmac_lo = swab16(*((u16 *)&dmac[4]));
2991 entry.ipv4_hnapt.smac_hi = swab32(*((u32 *)smac));
2992 entry.ipv4_hnapt.smac_lo = swab16(*((u16 *)&smac[4]));
2993
developere8b7dfa2023-04-20 10:16:44 +08002994 if (hash == -1)
2995 hash = hnat_get_ppe_hash(&entry);
developeraeafc442022-10-14 09:10:50 +08002996
2997 foe = &hnat_priv->foe_table_cpu[ppe_id][hash];
2998 while ((foe->ipv4_hnapt.bfib1.state == BIND) && (coll < 4)) {
2999 hash++;
3000 coll++;
3001 foe = &hnat_priv->foe_table_cpu[ppe_id][hash];
3002 };
3003 memcpy(foe, &entry, sizeof(entry));
3004
3005 debug_level = 7;
3006 entry_detail(ppe_id, hash);
3007
3008 return len;
3009}
3010
3011static const struct file_operations hnat_static_fops = {
3012 .open = hnat_static_entry_open,
3013 .read = seq_read,
3014 .llseek = seq_lseek,
3015 .write = hnat_static_entry_write,
3016 .release = single_release,
3017};
3018
developer4c32b7a2021-11-13 16:46:43 +08003019int get_ppe_mib(u32 ppe_id, int index, u64 *pkt_cnt, u64 *byte_cnt)
developerfd40db22021-04-29 10:08:25 +08003020{
3021 struct mtk_hnat *h = hnat_priv;
developer30a47682021-11-02 17:06:14 +08003022 struct hnat_accounting *acct;
developerfd40db22021-04-29 10:08:25 +08003023 struct foe_entry *entry;
3024
developer471f6562021-05-10 20:48:34 +08003025 if (ppe_id >= CFG_PPE_NUM)
developer4c32b7a2021-11-13 16:46:43 +08003026 return -EINVAL;
developer471f6562021-05-10 20:48:34 +08003027
developerc6227322021-07-09 10:52:53 +08003028 if (index < 0 || index >= h->foe_etry_num) {
3029 pr_info("Invalid entry index\n");
3030 return -EINVAL;
3031 }
3032
developer30a47682021-11-02 17:06:14 +08003033 acct = hnat_get_count(h, ppe_id, index, NULL);
developer471f6562021-05-10 20:48:34 +08003034 entry = hnat_priv->foe_table_cpu[ppe_id] + index;
developerfd40db22021-04-29 10:08:25 +08003035
developer30a47682021-11-02 17:06:14 +08003036 if (!acct)
developerfd40db22021-04-29 10:08:25 +08003037 return -1;
3038
3039 if (entry->bfib1.state != BIND)
3040 return -1;
3041
developer30a47682021-11-02 17:06:14 +08003042 *pkt_cnt = acct->packets;
3043 *byte_cnt = acct->bytes;
developerfd40db22021-04-29 10:08:25 +08003044
3045 return 0;
3046}
3047EXPORT_SYMBOL(get_ppe_mib);
3048
developer4c32b7a2021-11-13 16:46:43 +08003049int is_entry_binding(u32 ppe_id, int index)
developerfd40db22021-04-29 10:08:25 +08003050{
developer580e6fd2021-07-11 09:55:20 +08003051 struct mtk_hnat *h = hnat_priv;
developerfd40db22021-04-29 10:08:25 +08003052 struct foe_entry *entry;
3053
developer471f6562021-05-10 20:48:34 +08003054 if (ppe_id >= CFG_PPE_NUM)
developer4c32b7a2021-11-13 16:46:43 +08003055 return -EINVAL;
developer471f6562021-05-10 20:48:34 +08003056
developerc6227322021-07-09 10:52:53 +08003057 if (index < 0 || index >= h->foe_etry_num) {
3058 pr_info("Invalid entry index\n");
3059 return -EINVAL;
3060 }
3061
developer471f6562021-05-10 20:48:34 +08003062 entry = hnat_priv->foe_table_cpu[ppe_id] + index;
developerfd40db22021-04-29 10:08:25 +08003063
3064 return entry->bfib1.state == BIND;
3065}
3066EXPORT_SYMBOL(is_entry_binding);
3067
3068#define dump_register(nm) \
3069 { \
3070 .name = __stringify(nm), .offset = PPE_##nm, \
3071 }
3072
3073static const struct debugfs_reg32 hnat_regs[] = {
3074 dump_register(GLO_CFG), dump_register(FLOW_CFG),
3075 dump_register(IP_PROT_CHK), dump_register(IP_PROT_0),
3076 dump_register(IP_PROT_1), dump_register(IP_PROT_2),
3077 dump_register(IP_PROT_3), dump_register(TB_CFG),
3078 dump_register(TB_BASE), dump_register(TB_USED),
3079 dump_register(BNDR), dump_register(BIND_LMT_0),
3080 dump_register(BIND_LMT_1), dump_register(KA),
3081 dump_register(UNB_AGE), dump_register(BND_AGE_0),
3082 dump_register(BND_AGE_1), dump_register(HASH_SEED),
3083 dump_register(DFT_CPORT), dump_register(MCAST_PPSE),
3084 dump_register(MCAST_L_0), dump_register(MCAST_H_0),
3085 dump_register(MCAST_L_1), dump_register(MCAST_H_1),
3086 dump_register(MCAST_L_2), dump_register(MCAST_H_2),
3087 dump_register(MCAST_L_3), dump_register(MCAST_H_3),
3088 dump_register(MCAST_L_4), dump_register(MCAST_H_4),
3089 dump_register(MCAST_L_5), dump_register(MCAST_H_5),
3090 dump_register(MCAST_L_6), dump_register(MCAST_H_6),
3091 dump_register(MCAST_L_7), dump_register(MCAST_H_7),
3092 dump_register(MCAST_L_8), dump_register(MCAST_H_8),
3093 dump_register(MCAST_L_9), dump_register(MCAST_H_9),
3094 dump_register(MCAST_L_A), dump_register(MCAST_H_A),
3095 dump_register(MCAST_L_B), dump_register(MCAST_H_B),
3096 dump_register(MCAST_L_C), dump_register(MCAST_H_C),
3097 dump_register(MCAST_L_D), dump_register(MCAST_H_D),
3098 dump_register(MCAST_L_E), dump_register(MCAST_H_E),
3099 dump_register(MCAST_L_F), dump_register(MCAST_H_F),
3100 dump_register(MTU_DRP), dump_register(MTU_VLYR_0),
3101 dump_register(MTU_VLYR_1), dump_register(MTU_VLYR_2),
3102 dump_register(VPM_TPID), dump_register(VPM_TPID),
3103 dump_register(CAH_CTRL), dump_register(CAH_TAG_SRH),
3104 dump_register(CAH_LINE_RW), dump_register(CAH_WDATA),
3105 dump_register(CAH_RDATA),
3106};
3107
3108int hnat_init_debugfs(struct mtk_hnat *h)
3109{
3110 int ret = 0;
3111 struct dentry *root;
3112 struct dentry *file;
3113 long i;
3114 char name[16];
3115
3116 root = debugfs_create_dir("hnat", NULL);
3117 if (!root) {
3118 dev_notice(h->dev, "%s:err at %d\n", __func__, __LINE__);
3119 ret = -ENOMEM;
3120 goto err0;
3121 }
3122 h->root = root;
developerfd40db22021-04-29 10:08:25 +08003123
developer471f6562021-05-10 20:48:34 +08003124 for (i = 0; i < CFG_PPE_NUM; i++) {
3125 h->regset[i] = kzalloc(sizeof(*h->regset[i]), GFP_KERNEL);
3126 if (!h->regset[i]) {
3127 dev_notice(h->dev, "%s:err at %d\n", __func__, __LINE__);
3128 ret = -ENOMEM;
3129 goto err1;
3130 }
3131 h->regset[i]->regs = hnat_regs;
3132 h->regset[i]->nregs = ARRAY_SIZE(hnat_regs);
3133 h->regset[i]->base = h->ppe_base[i];
3134
developer577ad2f2022-11-28 10:33:36 +08003135 ret = snprintf(name, sizeof(name), "regdump%ld", i);
3136 if (ret != strlen(name)) {
3137 ret = -ENOMEM;
3138 goto err1;
3139 }
developeraeafc442022-10-14 09:10:50 +08003140 file = debugfs_create_regset32(name, 0444,
developer471f6562021-05-10 20:48:34 +08003141 root, h->regset[i]);
3142 if (!file) {
3143 dev_notice(h->dev, "%s:err at %d\n", __func__, __LINE__);
3144 ret = -ENOMEM;
3145 goto err1;
3146 }
developerfd40db22021-04-29 10:08:25 +08003147 }
developer471f6562021-05-10 20:48:34 +08003148
developeraeafc442022-10-14 09:10:50 +08003149 debugfs_create_file("all_entry", 0444, root, h, &hnat_debug_fops);
3150 debugfs_create_file("external_interface", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08003151 &hnat_ext_fops);
developeraeafc442022-10-14 09:10:50 +08003152 debugfs_create_file("whnat_interface", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08003153 &hnat_whnat_fops);
developeraeafc442022-10-14 09:10:50 +08003154 debugfs_create_file("cpu_reason", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08003155 &cpu_reason_fops);
developeraeafc442022-10-14 09:10:50 +08003156 debugfs_create_file("hnat_entry", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08003157 &hnat_entry_fops);
developeraeafc442022-10-14 09:10:50 +08003158 debugfs_create_file("hnat_setting", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08003159 &hnat_setting_fops);
developeraeafc442022-10-14 09:10:50 +08003160 debugfs_create_file("mcast_table", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08003161 &hnat_mcast_fops);
developeraeafc442022-10-14 09:10:50 +08003162 debugfs_create_file("hook_toggle", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08003163 &hnat_hook_toggle_fops);
developeraeafc442022-10-14 09:10:50 +08003164 debugfs_create_file("mape_toggle", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08003165 &hnat_mape_toggle_fops);
developeraeafc442022-10-14 09:10:50 +08003166 debugfs_create_file("qos_toggle", 0444, root, h,
developeraf07fad2021-11-19 17:53:42 +08003167 &hnat_qos_toggle_fops);
developeraeafc442022-10-14 09:10:50 +08003168 debugfs_create_file("hnat_version", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08003169 &hnat_version_fops);
developeraeafc442022-10-14 09:10:50 +08003170 debugfs_create_file("hnat_ppd_if", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08003171 &hnat_ppd_if_fops);
developeraeafc442022-10-14 09:10:50 +08003172 debugfs_create_file("static_entry", 0444, root, h,
3173 &hnat_static_fops);
developere8b7dfa2023-04-20 10:16:44 +08003174 debugfs_create_file("xlat_toggle", 0444, root, h,
3175 &hnat_xlat_toggle_fops);
3176 debugfs_create_file("xlat_cfg", 0444, root, h,
3177 &hnat_xlat_cfg_fops);
developerfd40db22021-04-29 10:08:25 +08003178
3179 for (i = 0; i < hnat_priv->data->num_of_sch; i++) {
developer577ad2f2022-11-28 10:33:36 +08003180 ret = snprintf(name, sizeof(name), "qdma_sch%ld", i);
3181 if (ret != strlen(name)) {
3182 ret = -ENOMEM;
3183 goto err1;
3184 }
developeraeafc442022-10-14 09:10:50 +08003185 debugfs_create_file(name, 0444, root, (void *)i,
developerfd40db22021-04-29 10:08:25 +08003186 &hnat_sched_fops);
3187 }
3188
3189 for (i = 0; i < MTK_QDMA_TX_NUM; i++) {
developer577ad2f2022-11-28 10:33:36 +08003190 ret = snprintf(name, sizeof(name), "qdma_txq%ld", i);
3191 if (ret != strlen(name)) {
3192 ret = -ENOMEM;
3193 goto err1;
3194 }
developeraeafc442022-10-14 09:10:50 +08003195 debugfs_create_file(name, 0444, root, (void *)i,
developerfd40db22021-04-29 10:08:25 +08003196 &hnat_queue_fops);
3197 }
3198
3199 return 0;
3200
3201err1:
3202 debugfs_remove_recursive(root);
3203err0:
3204 return ret;
3205}
3206
3207void hnat_deinit_debugfs(struct mtk_hnat *h)
3208{
developer4c32b7a2021-11-13 16:46:43 +08003209 int i;
3210
developerfd40db22021-04-29 10:08:25 +08003211 debugfs_remove_recursive(h->root);
3212 h->root = NULL;
developer4c32b7a2021-11-13 16:46:43 +08003213
3214 for (i = 0; i < CFG_PPE_NUM; i++)
3215 kfree(h->regset[i]);
developerfd40db22021-04-29 10:08:25 +08003216}