blob: e16249276041a0e39b55495890ba2ac818826671 [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/dma-mapping.h>
15#include <linux/delay.h>
16#include <linux/if.h>
17#include <linux/io.h>
18#include <linux/module.h>
19#include <linux/of_device.h>
20#include <linux/platform_device.h>
21#include <linux/reset.h>
developer731b98f2021-09-17 17:44:37 +080022#include <linux/rtnetlink.h>
23#include <net/netlink.h>
developerfd40db22021-04-29 10:08:25 +080024
25#include "nf_hnat_mtk.h"
26#include "hnat.h"
27
28struct mtk_hnat *hnat_priv;
developer731b98f2021-09-17 17:44:37 +080029static struct socket *_hnat_roam_sock;
30static struct work_struct _hnat_roam_work;
developerfd40db22021-04-29 10:08:25 +080031
32int (*ra_sw_nat_hook_rx)(struct sk_buff *skb) = NULL;
33EXPORT_SYMBOL(ra_sw_nat_hook_rx);
34int (*ra_sw_nat_hook_tx)(struct sk_buff *skb, int gmac_no) = NULL;
35EXPORT_SYMBOL(ra_sw_nat_hook_tx);
36
developera5da1972021-12-14 09:02:42 +080037int (*ppe_del_entry_by_mac)(unsigned char *mac) = NULL;
38EXPORT_SYMBOL(ppe_del_entry_by_mac);
39
developerfd40db22021-04-29 10:08:25 +080040void (*ppe_dev_register_hook)(struct net_device *dev) = NULL;
41EXPORT_SYMBOL(ppe_dev_register_hook);
42void (*ppe_dev_unregister_hook)(struct net_device *dev) = NULL;
43EXPORT_SYMBOL(ppe_dev_unregister_hook);
44
45static void hnat_sma_build_entry(struct timer_list *t)
46{
developer471f6562021-05-10 20:48:34 +080047 int i;
48
49 for (i = 0; i < CFG_PPE_NUM; i++)
50 cr_set_field(hnat_priv->ppe_base[i] + PPE_TB_CFG,
51 SMA, SMA_FWD_CPU_BUILD_ENTRY);
developerfd40db22021-04-29 10:08:25 +080052}
53
54void hnat_cache_ebl(int enable)
55{
developer471f6562021-05-10 20:48:34 +080056 int i;
57
58 for (i = 0; i < CFG_PPE_NUM; i++) {
59 cr_set_field(hnat_priv->ppe_base[i] + PPE_CAH_CTRL, CAH_X_MODE, 1);
60 cr_set_field(hnat_priv->ppe_base[i] + PPE_CAH_CTRL, CAH_X_MODE, 0);
61 cr_set_field(hnat_priv->ppe_base[i] + PPE_CAH_CTRL, CAH_EN, enable);
62 }
developerfd40db22021-04-29 10:08:25 +080063}
64
65static void hnat_reset_timestamp(struct timer_list *t)
66{
67 struct foe_entry *entry;
68 int hash_index;
69
70 hnat_cache_ebl(0);
developer471f6562021-05-10 20:48:34 +080071 cr_set_field(hnat_priv->ppe_base[0] + PPE_TB_CFG, TCP_AGE, 0);
72 cr_set_field(hnat_priv->ppe_base[0] + PPE_TB_CFG, UDP_AGE, 0);
developerfd40db22021-04-29 10:08:25 +080073 writel(0, hnat_priv->fe_base + 0x0010);
74
75 for (hash_index = 0; hash_index < hnat_priv->foe_etry_num; hash_index++) {
developer471f6562021-05-10 20:48:34 +080076 entry = hnat_priv->foe_table_cpu[0] + hash_index;
developerfd40db22021-04-29 10:08:25 +080077 if (entry->bfib1.state == BIND)
78 entry->bfib1.time_stamp =
79 readl(hnat_priv->fe_base + 0x0010) & (0xFFFF);
80 }
81
developer471f6562021-05-10 20:48:34 +080082 cr_set_field(hnat_priv->ppe_base[0] + PPE_TB_CFG, TCP_AGE, 1);
83 cr_set_field(hnat_priv->ppe_base[0] + PPE_TB_CFG, UDP_AGE, 1);
developerfd40db22021-04-29 10:08:25 +080084 hnat_cache_ebl(1);
85
86 mod_timer(&hnat_priv->hnat_reset_timestamp_timer, jiffies + 14400 * HZ);
87}
88
89static void cr_set_bits(void __iomem *reg, u32 bs)
90{
91 u32 val = readl(reg);
92
93 val |= bs;
94 writel(val, reg);
95}
96
97static void cr_clr_bits(void __iomem *reg, u32 bs)
98{
99 u32 val = readl(reg);
100
101 val &= ~bs;
102 writel(val, reg);
103}
104
105void cr_set_field(void __iomem *reg, u32 field, u32 val)
106{
107 unsigned int tv = readl(reg);
108
109 tv &= ~field;
110 tv |= ((val) << (ffs((unsigned int)field) - 1));
111 writel(tv, reg);
112}
113
114/*boundary entry can't be used to accelerate data flow*/
115static void exclude_boundary_entry(struct foe_entry *foe_table_cpu)
116{
117 int entry_base = 0;
118 int bad_entry, i, j;
119 struct foe_entry *foe_entry;
120 /*these entries are boundary every 128 entries*/
121 int boundary_entry_offset[8] = { 12, 25, 38, 51, 76, 89, 102, 115};
122
123 if (!foe_table_cpu)
124 return;
125
126 for (i = 0; entry_base < hnat_priv->foe_etry_num; i++) {
127 /* set boundary entries as static*/
128 for (j = 0; j < 8; j++) {
129 bad_entry = entry_base + boundary_entry_offset[j];
130 foe_entry = &foe_table_cpu[bad_entry];
131 foe_entry->udib1.sta = 1;
132 }
133 entry_base = (i + 1) * 128;
134 }
135}
136
137void set_gmac_ppe_fwd(int id, int enable)
138{
139 void __iomem *reg;
140 u32 val;
141
developerd35bbcc2022-09-28 22:46:01 +0800142 reg = hnat_priv->fe_base +
143 ((id == NR_GMAC1_PORT) ? GDMA1_FWD_CFG :
144 (id == NR_GMAC2_PORT) ? GDMA2_FWD_CFG : GDMA3_FWD_CFG);
developerfd40db22021-04-29 10:08:25 +0800145
146 if (enable) {
developerd35bbcc2022-09-28 22:46:01 +0800147 if (CFG_PPE_NUM == 3 && id == NR_GMAC3_PORT)
148 cr_set_bits(reg, BITS_GDM_ALL_FRC_P_PPE2);
149 else if (CFG_PPE_NUM == 3 && id == NR_GMAC2_PORT)
150 cr_set_bits(reg, BITS_GDM_ALL_FRC_P_PPE1);
151 else
152 cr_set_bits(reg, BITS_GDM_ALL_FRC_P_PPE);
developerfd40db22021-04-29 10:08:25 +0800153
154 return;
155 }
156
157 /*disabled */
158 val = readl(reg);
developerd35bbcc2022-09-28 22:46:01 +0800159 if ((val & GDM_ALL_FRC_MASK) == BITS_GDM_ALL_FRC_P_PPE ||
160 (CFG_PPE_NUM == 3 &&
161 ((val & GDM_ALL_FRC_MASK) == BITS_GDM_ALL_FRC_P_PPE1 ||
162 (val & GDM_ALL_FRC_MASK) == BITS_GDM_ALL_FRC_P_PPE2)))
developerfd40db22021-04-29 10:08:25 +0800163 cr_set_field(reg, GDM_ALL_FRC_MASK,
164 BITS_GDM_ALL_FRC_P_CPU_PDMA);
165}
166
developer731b98f2021-09-17 17:44:37 +0800167static int entry_mac_cmp(struct foe_entry *entry, u8 *mac)
168{
developer08c720e2021-11-12 14:18:53 +0800169 int ret = 0;
developer731b98f2021-09-17 17:44:37 +0800170
171 if(IS_IPV4_GRP(entry)) {
172 if(((swab32(entry->ipv4_hnapt.dmac_hi) == *(u32 *)mac) &&
173 (swab16(entry->ipv4_hnapt.dmac_lo) == *(u16 *)&mac[4])) ||
174 ((swab32(entry->ipv4_hnapt.smac_hi) == *(u32 *)mac) &&
175 (swab16(entry->ipv4_hnapt.smac_lo) == *(u16 *)&mac[4])))
176 ret = 1;
177 } else {
178 if(((swab32(entry->ipv6_5t_route.dmac_hi) == *(u32 *)mac) &&
179 (swab16(entry->ipv6_5t_route.dmac_lo) == *(u16 *)&mac[4])) ||
180 ((swab32(entry->ipv6_5t_route.smac_hi) == *(u32 *)mac) &&
181 (swab16(entry->ipv6_5t_route.smac_lo) == *(u16 *)&mac[4])))
182 ret = 1;
183 }
184
developer08c720e2021-11-12 14:18:53 +0800185 if (ret && debug_level >= 2)
186 pr_info("mac=%pM\n", mac);
developer731b98f2021-09-17 17:44:37 +0800187
188 return ret;
189}
190
191int entry_delete_by_mac(u8 *mac)
192{
193 struct foe_entry *entry = NULL;
194 int index, i, ret = 0;
195
196 for (i = 0; i < CFG_PPE_NUM; i++) {
197 entry = hnat_priv->foe_table_cpu[i];
198 for (index = 0; index < DEF_ETRY_NUM; entry++, index++) {
199 if(entry->bfib1.state == BIND && entry_mac_cmp(entry, mac)) {
200 memset(entry, 0, sizeof(*entry));
201 hnat_cache_ebl(1);
developer08c720e2021-11-12 14:18:53 +0800202 if (debug_level >= 2)
203 pr_info("delete entry idx = %d\n", index);
developer731b98f2021-09-17 17:44:37 +0800204 ret++;
205 }
206 }
207 }
208
209 if(!ret && debug_level >= 2)
210 pr_info("entry not found\n");
211
212 return ret;
213}
developer731b98f2021-09-17 17:44:37 +0800214
215static void hnat_roam_handler(struct work_struct *work)
216{
217 struct kvec iov;
218 struct msghdr msg;
219 struct nlmsghdr *nlh;
220 struct ndmsg *ndm;
221 struct nlattr *nla;
222 u8 rcv_buf[512];
223 int len;
224
225 if (!_hnat_roam_sock)
226 return;
227
228 iov.iov_base = rcv_buf;
229 iov.iov_len = sizeof(rcv_buf);
230 memset(&msg, 0, sizeof(msg));
231 msg.msg_namelen = sizeof(struct sockaddr_nl);
232
233 len = kernel_recvmsg(_hnat_roam_sock, &msg, &iov, 1, iov.iov_len, 0);
234 if (len <= 0)
235 goto out;
236
237 nlh = (struct nlmsghdr*)rcv_buf;
238 if (!NLMSG_OK(nlh, len) || nlh->nlmsg_type != RTM_NEWNEIGH)
239 goto out;
240
241 len = nlh->nlmsg_len - NLMSG_HDRLEN;
242 ndm = (struct ndmsg *)NLMSG_DATA(nlh);
243 if (ndm->ndm_family != PF_BRIDGE)
244 goto out;
245
246 nla = (struct nlattr *)((u8 *)ndm + sizeof(struct ndmsg));
247 len -= NLMSG_LENGTH(sizeof(struct ndmsg));
248 while (nla_ok(nla, len)) {
249 if (nla_type(nla) == NDA_LLADDR) {
250 entry_delete_by_mac(nla_data(nla));
251 }
252 nla = nla_next(nla, &len);
253 }
254
255out:
256 schedule_work(&_hnat_roam_work);
257}
258
259static int hnat_roaming_enable(void)
260{
261 struct socket *sock = NULL;
262 struct sockaddr_nl addr;
263 int ret;
264
265 INIT_WORK(&_hnat_roam_work, hnat_roam_handler);
266
267 ret = sock_create_kern(&init_net, AF_NETLINK, SOCK_RAW, NETLINK_ROUTE, &sock);
268 if (ret < 0)
269 goto out;
270
271 _hnat_roam_sock = sock;
272
273 addr.nl_family = AF_NETLINK;
274 addr.nl_pad = 0;
275 addr.nl_pid = 65534;
276 addr.nl_groups = 1 << (RTNLGRP_NEIGH - 1);
277 ret = kernel_bind(sock, (struct sockaddr *)&addr, sizeof(addr));
278 if (ret < 0)
279 goto out;
280
281 schedule_work(&_hnat_roam_work);
282 pr_info("hnat roaming work enable\n");
283
284 return 0;
285out:
286 if (sock)
287 sock_release(sock);
288
289 return ret;
290}
291
292static void hnat_roaming_disable(void)
293{
294 if (_hnat_roam_sock)
295 sock_release(_hnat_roam_sock);
296 _hnat_roam_sock = NULL;
297 pr_info("hnat roaming work disable\n");
298}
299
developer8051e042022-04-08 13:26:36 +0800300static int hnat_hw_init(u32 ppe_id)
developerfd40db22021-04-29 10:08:25 +0800301{
developer4c32b7a2021-11-13 16:46:43 +0800302 if (ppe_id >= CFG_PPE_NUM)
303 return -EINVAL;
304
developerfd40db22021-04-29 10:08:25 +0800305 /* setup hashing */
developer8051e042022-04-08 13:26:36 +0800306 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, TB_ETRY_NUM, hnat_priv->etry_num_cfg);
developer471f6562021-05-10 20:48:34 +0800307 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, HASH_MODE, HASH_MODE_1);
308 writel(HASH_SEED_KEY, hnat_priv->ppe_base[ppe_id] + PPE_HASH_SEED);
309 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, XMODE, 0);
developerd35bbcc2022-09-28 22:46:01 +0800310 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, TB_ENTRY_SIZE,
developer4164cfe2022-12-01 11:27:41 +0800311 (hnat_priv->data->version == MTK_HNAT_V3) ? ENTRY_128B :
312 (hnat_priv->data->version == MTK_HNAT_V2) ? ENTRY_96B :
313 ENTRY_80B);
developer471f6562021-05-10 20:48:34 +0800314 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, SMA, SMA_FWD_CPU_BUILD_ENTRY);
developerfd40db22021-04-29 10:08:25 +0800315
316 /* set ip proto */
developer471f6562021-05-10 20:48:34 +0800317 writel(0xFFFFFFFF, hnat_priv->ppe_base[ppe_id] + PPE_IP_PROT_CHK);
developerfd40db22021-04-29 10:08:25 +0800318
319 /* setup caching */
320 hnat_cache_ebl(1);
321
322 /* enable FOE */
developer471f6562021-05-10 20:48:34 +0800323 cr_set_bits(hnat_priv->ppe_base[ppe_id] + PPE_FLOW_CFG,
developerf0b0e232022-04-12 11:33:10 +0800324 BIT_IPV4_NAT_EN | BIT_IPV4_NAPT_EN |
developerfd40db22021-04-29 10:08:25 +0800325 BIT_IPV4_NAT_FRAG_EN | BIT_IPV4_HASH_GREK |
326 BIT_IPV4_DSL_EN | BIT_IPV6_6RD_EN |
327 BIT_IPV6_3T_ROUTE_EN | BIT_IPV6_5T_ROUTE_EN);
328
developer4164cfe2022-12-01 11:27:41 +0800329 if (hnat_priv->data->version == MTK_HNAT_V2 ||
330 hnat_priv->data->version == MTK_HNAT_V3)
developer471f6562021-05-10 20:48:34 +0800331 cr_set_bits(hnat_priv->ppe_base[ppe_id] + PPE_FLOW_CFG,
developerfd40db22021-04-29 10:08:25 +0800332 BIT_IPV4_MAPE_EN | BIT_IPV4_MAPT_EN);
333
developer4164cfe2022-12-01 11:27:41 +0800334 if (hnat_priv->data->version == MTK_HNAT_V3)
developer5ffc5f12022-10-25 18:51:46 +0800335 cr_set_bits(hnat_priv->ppe_base[ppe_id] + PPE_FLOW_CFG,
336 BIT_IPV6_NAT_EN | BIT_IPV6_NAPT_EN |
337 BIT_CS0_RM_ALL_IP6_IP_EN);
338
developerfd40db22021-04-29 10:08:25 +0800339 /* setup FOE aging */
developer471f6562021-05-10 20:48:34 +0800340 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, NTU_AGE, 1);
341 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, UNBD_AGE, 1);
342 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_UNB_AGE, UNB_MNP, 1000);
343 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_UNB_AGE, UNB_DLTA, 3);
344 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, TCP_AGE, 1);
345 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, UDP_AGE, 1);
346 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, FIN_AGE, 1);
347 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_BND_AGE_0, UDP_DLTA, 12);
348 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_BND_AGE_0, NTU_DLTA, 1);
349 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_BND_AGE_1, FIN_DLTA, 1);
350 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_BND_AGE_1, TCP_DLTA, 7);
developerfd40db22021-04-29 10:08:25 +0800351
352 /* setup FOE ka */
developer8051e042022-04-08 13:26:36 +0800353 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, KA_CFG, 0);
354 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_BIND_LMT_1, NTU_KA, 0);
355 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_KA, KA_T, 0);
356 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_KA, TCP_KA, 0);
357 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_KA, UDP_KA, 0);
358 mdelay(10);
359
developer471f6562021-05-10 20:48:34 +0800360 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, SCAN_MODE, 2);
361 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, KA_CFG, 3);
developer8051e042022-04-08 13:26:36 +0800362 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, TICK_SEL, 0);
developer471f6562021-05-10 20:48:34 +0800363 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_KA, KA_T, 1);
364 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_KA, TCP_KA, 1);
365 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_KA, UDP_KA, 1);
366 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_BIND_LMT_1, NTU_KA, 1);
developerfd40db22021-04-29 10:08:25 +0800367
368 /* setup FOE rate limit */
developer471f6562021-05-10 20:48:34 +0800369 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_BIND_LMT_0, QURT_LMT, 16383);
370 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_BIND_LMT_0, HALF_LMT, 16383);
371 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_BIND_LMT_1, FULL_LMT, 16383);
developerfd40db22021-04-29 10:08:25 +0800372 /* setup binding threshold as 30 packets per second */
developer471f6562021-05-10 20:48:34 +0800373 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_BNDR, BIND_RATE, 0x1E);
developerfd40db22021-04-29 10:08:25 +0800374
375 /* setup FOE cf gen */
developer471f6562021-05-10 20:48:34 +0800376 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_GLO_CFG, PPE_EN, 1);
377 writel(0, hnat_priv->ppe_base[ppe_id] + PPE_DFT_CPORT); /* pdma */
378 /* writel(0x55555555, hnat_priv->ppe_base[ppe_id] + PPE_DFT_CPORT); */ /* qdma */
379 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_GLO_CFG, TTL0_DRP, 0);
developer8051e042022-04-08 13:26:36 +0800380 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_GLO_CFG, MCAST_TB_EN, 1);
developerfd40db22021-04-29 10:08:25 +0800381
developer4164cfe2022-12-01 11:27:41 +0800382 if (hnat_priv->data->version == MTK_HNAT_V2 ||
383 hnat_priv->data->version == MTK_HNAT_V3) {
developer471f6562021-05-10 20:48:34 +0800384 writel(0xcb777, hnat_priv->ppe_base[ppe_id] + PPE_DFT_CPORT1);
385 writel(0x7f, hnat_priv->ppe_base[ppe_id] + PPE_SBW_CTRL);
developerfd40db22021-04-29 10:08:25 +0800386 }
387
developer4164cfe2022-12-01 11:27:41 +0800388 if (hnat_priv->data->version == MTK_HNAT_V3) {
developerd35bbcc2022-09-28 22:46:01 +0800389 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_SB_FIFO_DBG,
390 SB_MED_FULL_DRP_EN, 1);
391 }
392
developerfd40db22021-04-29 10:08:25 +0800393 /*enable ppe mib counter*/
394 if (hnat_priv->data->per_flow_accounting) {
developer471f6562021-05-10 20:48:34 +0800395 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_MIB_CFG, MIB_EN, 1);
396 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_MIB_CFG, MIB_READ_CLEAR, 1);
397 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_MIB_CAH_CTRL, MIB_CAH_EN, 1);
developerfd40db22021-04-29 10:08:25 +0800398 }
399
400 hnat_priv->g_ppdev = dev_get_by_name(&init_net, hnat_priv->ppd);
developer8c9c0d02021-06-18 16:15:37 +0800401 hnat_priv->g_wandev = dev_get_by_name(&init_net, hnat_priv->wan);
developerfd40db22021-04-29 10:08:25 +0800402
developer471f6562021-05-10 20:48:34 +0800403 dev_info(hnat_priv->dev, "PPE%d hwnat start\n", ppe_id);
developerfd40db22021-04-29 10:08:25 +0800404
405 return 0;
406}
407
developer8051e042022-04-08 13:26:36 +0800408static int hnat_start(u32 ppe_id)
409{
410 u32 foe_table_sz;
411 u32 foe_mib_tb_sz;
developer577ad2f2022-11-28 10:33:36 +0800412 int etry_num_cfg;
developer8051e042022-04-08 13:26:36 +0800413
414 if (ppe_id >= CFG_PPE_NUM)
415 return -EINVAL;
416
417 /* mapp the FOE table */
418 for (etry_num_cfg = DEF_ETRY_NUM_CFG ; etry_num_cfg >= 0 ;
419 etry_num_cfg--, hnat_priv->foe_etry_num /= 2) {
420 foe_table_sz = hnat_priv->foe_etry_num * sizeof(struct foe_entry);
421 hnat_priv->foe_table_cpu[ppe_id] = dma_alloc_coherent(
422 hnat_priv->dev, foe_table_sz,
423 &hnat_priv->foe_table_dev[ppe_id], GFP_KERNEL);
424
425 if (hnat_priv->foe_table_cpu[ppe_id])
426 break;
427 }
428
429 if (!hnat_priv->foe_table_cpu[ppe_id])
430 return -1;
431 dev_info(hnat_priv->dev, "PPE%d entry number = %d\n",
432 ppe_id, hnat_priv->foe_etry_num);
433
434 writel(hnat_priv->foe_table_dev[ppe_id], hnat_priv->ppe_base[ppe_id] + PPE_TB_BASE);
435 memset(hnat_priv->foe_table_cpu[ppe_id], 0, foe_table_sz);
436
developer4164cfe2022-12-01 11:27:41 +0800437 if (hnat_priv->data->version == MTK_HNAT_V1_1)
developer8051e042022-04-08 13:26:36 +0800438 exclude_boundary_entry(hnat_priv->foe_table_cpu[ppe_id]);
439
440 if (hnat_priv->data->per_flow_accounting) {
441 foe_mib_tb_sz = hnat_priv->foe_etry_num * sizeof(struct mib_entry);
442 hnat_priv->foe_mib_cpu[ppe_id] =
443 dma_alloc_coherent(hnat_priv->dev, foe_mib_tb_sz,
444 &hnat_priv->foe_mib_dev[ppe_id], GFP_KERNEL);
445 if (!hnat_priv->foe_mib_cpu[ppe_id])
446 return -1;
447 writel(hnat_priv->foe_mib_dev[ppe_id],
448 hnat_priv->ppe_base[ppe_id] + PPE_MIB_TB_BASE);
449 memset(hnat_priv->foe_mib_cpu[ppe_id], 0, foe_mib_tb_sz);
450
451 hnat_priv->acct[ppe_id] =
452 kzalloc(hnat_priv->foe_etry_num * sizeof(struct hnat_accounting),
453 GFP_KERNEL);
454 if (!hnat_priv->acct[ppe_id])
455 return -1;
456 }
457
458 hnat_priv->etry_num_cfg = etry_num_cfg;
459 hnat_hw_init(ppe_id);
460
461 return 0;
462}
463
developer4c32b7a2021-11-13 16:46:43 +0800464static int ppe_busy_wait(u32 ppe_id)
developerfd40db22021-04-29 10:08:25 +0800465{
466 unsigned long t_start = jiffies;
467 u32 r = 0;
468
developer4c32b7a2021-11-13 16:46:43 +0800469 if (ppe_id >= CFG_PPE_NUM)
470 return -EINVAL;
471
developerfd40db22021-04-29 10:08:25 +0800472 while (1) {
developer471f6562021-05-10 20:48:34 +0800473 r = readl((hnat_priv->ppe_base[ppe_id] + 0x0));
developerfd40db22021-04-29 10:08:25 +0800474 if (!(r & BIT(31)))
475 return 0;
476 if (time_after(jiffies, t_start + HZ))
477 break;
developer8051e042022-04-08 13:26:36 +0800478 mdelay(10);
developerfd40db22021-04-29 10:08:25 +0800479 }
480
481 dev_notice(hnat_priv->dev, "ppe:%s timeout\n", __func__);
482
483 return -1;
484}
485
developer4c32b7a2021-11-13 16:46:43 +0800486static void hnat_stop(u32 ppe_id)
developerfd40db22021-04-29 10:08:25 +0800487{
488 u32 foe_table_sz;
489 u32 foe_mib_tb_sz;
490 struct foe_entry *entry, *end;
developerfd40db22021-04-29 10:08:25 +0800491
developer4c32b7a2021-11-13 16:46:43 +0800492 if (ppe_id >= CFG_PPE_NUM)
493 return;
494
developerfd40db22021-04-29 10:08:25 +0800495 /* send all traffic back to the DMA engine */
developerd35bbcc2022-09-28 22:46:01 +0800496 set_gmac_ppe_fwd(NR_GMAC1_PORT, 0);
497 set_gmac_ppe_fwd(NR_GMAC2_PORT, 0);
498 set_gmac_ppe_fwd(NR_GMAC3_PORT, 0);
developerfd40db22021-04-29 10:08:25 +0800499
500 dev_info(hnat_priv->dev, "hwnat stop\n");
501
developer471f6562021-05-10 20:48:34 +0800502 if (hnat_priv->foe_table_cpu[ppe_id]) {
503 entry = hnat_priv->foe_table_cpu[ppe_id];
504 end = hnat_priv->foe_table_cpu[ppe_id] + hnat_priv->foe_etry_num;
developerfd40db22021-04-29 10:08:25 +0800505 while (entry < end) {
506 entry->bfib1.state = INVALID;
507 entry++;
508 }
509 }
510 /* disable caching */
511 hnat_cache_ebl(0);
512
513 /* flush cache has to be ahead of hnat disable --*/
developer471f6562021-05-10 20:48:34 +0800514 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_GLO_CFG, PPE_EN, 0);
developerfd40db22021-04-29 10:08:25 +0800515
516 /* disable scan mode and keep-alive */
developer471f6562021-05-10 20:48:34 +0800517 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, SCAN_MODE, 0);
518 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, KA_CFG, 0);
developerfd40db22021-04-29 10:08:25 +0800519
developer471f6562021-05-10 20:48:34 +0800520 ppe_busy_wait(ppe_id);
developerfd40db22021-04-29 10:08:25 +0800521
522 /* disable FOE */
developer471f6562021-05-10 20:48:34 +0800523 cr_clr_bits(hnat_priv->ppe_base[ppe_id] + PPE_FLOW_CFG,
developerfd40db22021-04-29 10:08:25 +0800524 BIT_IPV4_NAPT_EN | BIT_IPV4_NAT_EN | BIT_IPV4_NAT_FRAG_EN |
525 BIT_IPV6_HASH_GREK | BIT_IPV4_DSL_EN |
526 BIT_IPV6_6RD_EN | BIT_IPV6_3T_ROUTE_EN |
527 BIT_IPV6_5T_ROUTE_EN | BIT_FUC_FOE | BIT_FMC_FOE);
528
developer4164cfe2022-12-01 11:27:41 +0800529 if (hnat_priv->data->version == MTK_HNAT_V2 ||
530 hnat_priv->data->version == MTK_HNAT_V3)
developer471f6562021-05-10 20:48:34 +0800531 cr_clr_bits(hnat_priv->ppe_base[ppe_id] + PPE_FLOW_CFG,
developerfd40db22021-04-29 10:08:25 +0800532 BIT_IPV4_MAPE_EN | BIT_IPV4_MAPT_EN);
533
developer4164cfe2022-12-01 11:27:41 +0800534 if (hnat_priv->data->version == MTK_HNAT_V3)
developer5ffc5f12022-10-25 18:51:46 +0800535 cr_clr_bits(hnat_priv->ppe_base[ppe_id] + PPE_FLOW_CFG,
536 BIT_IPV6_NAT_EN | BIT_IPV6_NAPT_EN |
537 BIT_CS0_RM_ALL_IP6_IP_EN);
538
developerfd40db22021-04-29 10:08:25 +0800539 /* disable FOE aging */
developer471f6562021-05-10 20:48:34 +0800540 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, NTU_AGE, 0);
541 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, UNBD_AGE, 0);
542 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, TCP_AGE, 0);
543 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, UDP_AGE, 0);
544 cr_set_field(hnat_priv->ppe_base[ppe_id] + PPE_TB_CFG, FIN_AGE, 0);
developerfd40db22021-04-29 10:08:25 +0800545
developerfd40db22021-04-29 10:08:25 +0800546 /* free the FOE table */
547 foe_table_sz = hnat_priv->foe_etry_num * sizeof(struct foe_entry);
developer471f6562021-05-10 20:48:34 +0800548 if (hnat_priv->foe_table_cpu[ppe_id])
549 dma_free_coherent(hnat_priv->dev, foe_table_sz,
550 hnat_priv->foe_table_cpu[ppe_id],
551 hnat_priv->foe_table_dev[ppe_id]);
developer8051e042022-04-08 13:26:36 +0800552 hnat_priv->foe_table_cpu[ppe_id] = NULL;
developer471f6562021-05-10 20:48:34 +0800553 writel(0, hnat_priv->ppe_base[ppe_id] + PPE_TB_BASE);
developerfd40db22021-04-29 10:08:25 +0800554
555 if (hnat_priv->data->per_flow_accounting) {
556 foe_mib_tb_sz = hnat_priv->foe_etry_num * sizeof(struct mib_entry);
developer471f6562021-05-10 20:48:34 +0800557 if (hnat_priv->foe_mib_cpu[ppe_id])
developerfd40db22021-04-29 10:08:25 +0800558 dma_free_coherent(hnat_priv->dev, foe_mib_tb_sz,
developer471f6562021-05-10 20:48:34 +0800559 hnat_priv->foe_mib_cpu[ppe_id],
560 hnat_priv->foe_mib_dev[ppe_id]);
561 writel(0, hnat_priv->ppe_base[ppe_id] + PPE_MIB_TB_BASE);
562 kfree(hnat_priv->acct[ppe_id]);
developerfd40db22021-04-29 10:08:25 +0800563 }
564}
565
566static void hnat_release_netdev(void)
567{
568 int i;
569 struct extdev_entry *ext_entry;
570
571 for (i = 0; i < MAX_EXT_DEVS && hnat_priv->ext_if[i]; i++) {
572 ext_entry = hnat_priv->ext_if[i];
573 if (ext_entry->dev)
574 dev_put(ext_entry->dev);
575 ext_if_del(ext_entry);
576 kfree(ext_entry);
577 }
578
579 if (hnat_priv->g_ppdev)
580 dev_put(hnat_priv->g_ppdev);
developer8c9c0d02021-06-18 16:15:37 +0800581
582 if (hnat_priv->g_wandev)
583 dev_put(hnat_priv->g_wandev);
developerfd40db22021-04-29 10:08:25 +0800584}
585
586static struct notifier_block nf_hnat_netdevice_nb __read_mostly = {
587 .notifier_call = nf_hnat_netdevice_event,
588};
589
590static struct notifier_block nf_hnat_netevent_nb __read_mostly = {
591 .notifier_call = nf_hnat_netevent_handler,
592};
593
594int hnat_enable_hook(void)
595{
596 /* register hook functions used by WHNAT module.
597 */
598 if (hnat_priv->data->whnat) {
599 ra_sw_nat_hook_rx =
developer4164cfe2022-12-01 11:27:41 +0800600 (hnat_priv->data->version == MTK_HNAT_V2 ||
601 hnat_priv->data->version == MTK_HNAT_V3) ?
developerfd40db22021-04-29 10:08:25 +0800602 mtk_sw_nat_hook_rx : NULL;
603 ra_sw_nat_hook_tx = mtk_sw_nat_hook_tx;
604 ppe_dev_register_hook = mtk_ppe_dev_register_hook;
605 ppe_dev_unregister_hook = mtk_ppe_dev_unregister_hook;
606 }
607
608 if (hnat_register_nf_hooks())
609 return -1;
610
developera5da1972021-12-14 09:02:42 +0800611 ppe_del_entry_by_mac = entry_delete_by_mac;
developerfd40db22021-04-29 10:08:25 +0800612 hook_toggle = 1;
613
614 return 0;
615}
616
617int hnat_disable_hook(void)
618{
developer471f6562021-05-10 20:48:34 +0800619 int i, hash_index;
developerfd40db22021-04-29 10:08:25 +0800620 struct foe_entry *entry;
621
622 ra_sw_nat_hook_tx = NULL;
623 ra_sw_nat_hook_rx = NULL;
624 hnat_unregister_nf_hooks();
625
developer471f6562021-05-10 20:48:34 +0800626 for (i = 0; i < CFG_PPE_NUM; i++) {
627 cr_set_field(hnat_priv->ppe_base[i] + PPE_TB_CFG,
628 SMA, SMA_ONLY_FWD_CPU);
629
630 for (hash_index = 0; hash_index < hnat_priv->foe_etry_num; hash_index++) {
631 entry = hnat_priv->foe_table_cpu[i] + hash_index;
632 if (entry->bfib1.state == BIND) {
633 entry->ipv4_hnapt.udib1.state = INVALID;
634 entry->ipv4_hnapt.udib1.time_stamp =
635 readl((hnat_priv->fe_base + 0x0010)) & 0xFF;
636 }
developerfd40db22021-04-29 10:08:25 +0800637 }
638 }
639
640 /* clear HWNAT cache */
641 hnat_cache_ebl(1);
642
643 mod_timer(&hnat_priv->hnat_sma_build_entry_timer, jiffies + 3 * HZ);
developera5da1972021-12-14 09:02:42 +0800644 ppe_del_entry_by_mac = NULL;
developerfd40db22021-04-29 10:08:25 +0800645 hook_toggle = 0;
646
647 return 0;
648}
649
developer8051e042022-04-08 13:26:36 +0800650int hnat_warm_init(void)
651{
652 u32 foe_table_sz, foe_mib_tb_sz, ppe_id = 0;
653
654 unregister_netevent_notifier(&nf_hnat_netevent_nb);
655
656 for (ppe_id = 0; ppe_id < CFG_PPE_NUM; ppe_id++) {
657 foe_table_sz =
658 hnat_priv->foe_etry_num * sizeof(struct foe_entry);
659 writel(hnat_priv->foe_table_dev[ppe_id],
660 hnat_priv->ppe_base[ppe_id] + PPE_TB_BASE);
661 memset(hnat_priv->foe_table_cpu[ppe_id], 0, foe_table_sz);
662
developer4164cfe2022-12-01 11:27:41 +0800663 if (hnat_priv->data->version == MTK_HNAT_V1_1)
developer8051e042022-04-08 13:26:36 +0800664 exclude_boundary_entry(hnat_priv->foe_table_cpu[ppe_id]);
665
666 if (hnat_priv->data->per_flow_accounting) {
667 foe_mib_tb_sz =
668 hnat_priv->foe_etry_num * sizeof(struct mib_entry);
669 writel(hnat_priv->foe_mib_dev[ppe_id],
670 hnat_priv->ppe_base[ppe_id] + PPE_MIB_TB_BASE);
671 memset(hnat_priv->foe_mib_cpu[ppe_id], 0,
672 foe_mib_tb_sz);
673 }
674
675 hnat_hw_init(ppe_id);
676 }
677
678 set_gmac_ppe_fwd(0, 1);
679 set_gmac_ppe_fwd(1, 1);
680 register_netevent_notifier(&nf_hnat_netevent_nb);
681
682 return 0;
683}
684
developerfd40db22021-04-29 10:08:25 +0800685static struct packet_type mtk_pack_type __read_mostly = {
686 .type = HQOS_MAGIC_TAG,
687 .func = mtk_hqos_ptype_cb,
688};
developerfd40db22021-04-29 10:08:25 +0800689
690static int hnat_probe(struct platform_device *pdev)
691{
692 int i;
693 int err = 0;
694 int index = 0;
695 struct resource *res;
696 const char *name;
697 struct device_node *np;
698 unsigned int val;
699 struct property *prop;
700 struct extdev_entry *ext_entry;
701 const struct of_device_id *match;
702
703 hnat_priv = devm_kzalloc(&pdev->dev, sizeof(struct mtk_hnat), GFP_KERNEL);
704 if (!hnat_priv)
705 return -ENOMEM;
706
707 hnat_priv->foe_etry_num = DEF_ETRY_NUM;
708
709 match = of_match_device(of_hnat_match, &pdev->dev);
developer4c32b7a2021-11-13 16:46:43 +0800710 if (unlikely(!match))
711 return -EINVAL;
712
developerfd40db22021-04-29 10:08:25 +0800713 hnat_priv->data = (struct mtk_hnat_data *)match->data;
714
715 hnat_priv->dev = &pdev->dev;
716 np = hnat_priv->dev->of_node;
717
718 err = of_property_read_string(np, "mtketh-wan", &name);
719 if (err < 0)
720 return -EINVAL;
721
developer4c32b7a2021-11-13 16:46:43 +0800722 strncpy(hnat_priv->wan, (char *)name, IFNAMSIZ - 1);
developerfd40db22021-04-29 10:08:25 +0800723 dev_info(&pdev->dev, "wan = %s\n", hnat_priv->wan);
724
725 err = of_property_read_string(np, "mtketh-lan", &name);
726 if (err < 0)
727 strncpy(hnat_priv->lan, "eth0", IFNAMSIZ);
728 else
developer4c32b7a2021-11-13 16:46:43 +0800729 strncpy(hnat_priv->lan, (char *)name, IFNAMSIZ - 1);
developerfd40db22021-04-29 10:08:25 +0800730 dev_info(&pdev->dev, "lan = %s\n", hnat_priv->lan);
731
developerd35bbcc2022-09-28 22:46:01 +0800732 err = of_property_read_string(np, "mtketh-lan2", &name);
733 if (err < 0)
734 strncpy(hnat_priv->lan2, "eth2", IFNAMSIZ);
735 else
736 strncpy(hnat_priv->lan2, (char *)name, IFNAMSIZ - 1);
737 dev_info(&pdev->dev, "lan2 = %s\n", hnat_priv->lan2);
738
developerfd40db22021-04-29 10:08:25 +0800739 err = of_property_read_string(np, "mtketh-ppd", &name);
740 if (err < 0)
741 strncpy(hnat_priv->ppd, "eth0", IFNAMSIZ);
742 else
developer4c32b7a2021-11-13 16:46:43 +0800743 strncpy(hnat_priv->ppd, (char *)name, IFNAMSIZ - 1);
developerfd40db22021-04-29 10:08:25 +0800744 dev_info(&pdev->dev, "ppd = %s\n", hnat_priv->ppd);
745
746 /*get total gmac num in hnat*/
747 err = of_property_read_u32_index(np, "mtketh-max-gmac", 0, &val);
748
749 if (err < 0)
750 return -EINVAL;
751
752 hnat_priv->gmac_num = val;
753
754 dev_info(&pdev->dev, "gmac num = %d\n", hnat_priv->gmac_num);
755
756 err = of_property_read_u32_index(np, "mtkdsa-wan-port", 0, &val);
757
758 if (err < 0) {
759 hnat_priv->wan_dsa_port = NONE_DSA_PORT;
760 } else {
761 hnat_priv->wan_dsa_port = val;
762 dev_info(&pdev->dev, "wan dsa port = %d\n", hnat_priv->wan_dsa_port);
763 }
764
developer471f6562021-05-10 20:48:34 +0800765 err = of_property_read_u32_index(np, "mtketh-ppe-num", 0, &val);
766
767 if (err < 0)
768 hnat_priv->ppe_num = 1;
769 else
770 hnat_priv->ppe_num = val;
771
772 dev_info(&pdev->dev, "ppe num = %d\n", hnat_priv->ppe_num);
773
developerfd40db22021-04-29 10:08:25 +0800774 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
775 if (!res)
776 return -ENOENT;
777
778 hnat_priv->fe_base = devm_ioremap_nocache(&pdev->dev, res->start,
779 res->end - res->start + 1);
780 if (!hnat_priv->fe_base)
781 return -EADDRNOTAVAIL;
782
developerd35bbcc2022-09-28 22:46:01 +0800783#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
developer471f6562021-05-10 20:48:34 +0800784 hnat_priv->ppe_base[0] = hnat_priv->fe_base + 0x2200;
785
786 if (CFG_PPE_NUM > 1)
787 hnat_priv->ppe_base[1] = hnat_priv->fe_base + 0x2600;
developerd35bbcc2022-09-28 22:46:01 +0800788
789 if (CFG_PPE_NUM > 2)
790 hnat_priv->ppe_base[2] = hnat_priv->fe_base + 0x2e00;
developer471f6562021-05-10 20:48:34 +0800791#else
792 hnat_priv->ppe_base[0] = hnat_priv->fe_base + 0xe00;
793#endif
developerfd40db22021-04-29 10:08:25 +0800794
795 err = hnat_init_debugfs(hnat_priv);
796 if (err)
797 return err;
798
799 prop = of_find_property(np, "ext-devices", NULL);
800 for (name = of_prop_next_string(prop, NULL); name;
801 name = of_prop_next_string(prop, name), index++) {
802 ext_entry = kzalloc(sizeof(*ext_entry), GFP_KERNEL);
803 if (!ext_entry) {
804 err = -ENOMEM;
805 goto err_out1;
806 }
developer4c32b7a2021-11-13 16:46:43 +0800807 strncpy(ext_entry->name, (char *)name, IFNAMSIZ - 1);
developerfd40db22021-04-29 10:08:25 +0800808 ext_if_add(ext_entry);
809 }
810
811 for (i = 0; i < MAX_EXT_DEVS && hnat_priv->ext_if[i]; i++) {
812 ext_entry = hnat_priv->ext_if[i];
813 dev_info(&pdev->dev, "ext devices = %s\n", ext_entry->name);
814 }
815
816 hnat_priv->lvid = 1;
817 hnat_priv->wvid = 2;
818
developer471f6562021-05-10 20:48:34 +0800819 for (i = 0; i < CFG_PPE_NUM; i++) {
820 err = hnat_start(i);
821 if (err)
822 goto err_out;
823 }
developerfd40db22021-04-29 10:08:25 +0800824
825 if (hnat_priv->data->whnat) {
826 err = whnat_adjust_nf_hooks();
827 if (err)
828 goto err_out;
829 }
830
831 err = hnat_enable_hook();
832 if (err)
833 goto err_out;
834
835 register_netdevice_notifier(&nf_hnat_netdevice_nb);
836 register_netevent_notifier(&nf_hnat_netevent_nb);
developer471f6562021-05-10 20:48:34 +0800837
838 if (hnat_priv->data->mcast) {
839 for (i = 0; i < CFG_PPE_NUM; i++)
840 hnat_mcast_enable(i);
841 }
842
developerfd40db22021-04-29 10:08:25 +0800843 timer_setup(&hnat_priv->hnat_sma_build_entry_timer, hnat_sma_build_entry, 0);
developer4164cfe2022-12-01 11:27:41 +0800844 if (hnat_priv->data->version == MTK_HNAT_V1_3) {
developerfd40db22021-04-29 10:08:25 +0800845 timer_setup(&hnat_priv->hnat_reset_timestamp_timer, hnat_reset_timestamp, 0);
846 hnat_priv->hnat_reset_timestamp_timer.expires = jiffies;
847 add_timer(&hnat_priv->hnat_reset_timestamp_timer);
848 }
849
developer34028fb2022-01-11 13:51:29 +0800850 if (IS_HQOS_MODE && IS_GMAC1_MODE)
developerfd40db22021-04-29 10:08:25 +0800851 dev_add_pack(&mtk_pack_type);
developer24948202021-11-24 17:38:27 +0800852
developer731b98f2021-09-17 17:44:37 +0800853 err = hnat_roaming_enable();
854 if (err)
855 pr_info("hnat roaming work fail\n");
developerfd40db22021-04-29 10:08:25 +0800856
857 return 0;
858
859err_out:
developer471f6562021-05-10 20:48:34 +0800860 for (i = 0; i < CFG_PPE_NUM; i++)
861 hnat_stop(i);
developerfd40db22021-04-29 10:08:25 +0800862err_out1:
863 hnat_deinit_debugfs(hnat_priv);
864 for (i = 0; i < MAX_EXT_DEVS && hnat_priv->ext_if[i]; i++) {
865 ext_entry = hnat_priv->ext_if[i];
866 ext_if_del(ext_entry);
867 kfree(ext_entry);
868 }
869 return err;
870}
871
872static int hnat_remove(struct platform_device *pdev)
873{
developer471f6562021-05-10 20:48:34 +0800874 int i;
875
developer731b98f2021-09-17 17:44:37 +0800876 hnat_roaming_disable();
developerfd40db22021-04-29 10:08:25 +0800877 unregister_netdevice_notifier(&nf_hnat_netdevice_nb);
878 unregister_netevent_notifier(&nf_hnat_netevent_nb);
879 hnat_disable_hook();
880
881 if (hnat_priv->data->mcast)
882 hnat_mcast_disable();
883
developer471f6562021-05-10 20:48:34 +0800884 for (i = 0; i < CFG_PPE_NUM; i++)
885 hnat_stop(i);
886
developerfd40db22021-04-29 10:08:25 +0800887 hnat_deinit_debugfs(hnat_priv);
888 hnat_release_netdev();
889 del_timer_sync(&hnat_priv->hnat_sma_build_entry_timer);
developer4164cfe2022-12-01 11:27:41 +0800890 if (hnat_priv->data->version == MTK_HNAT_V1_3)
developerfd40db22021-04-29 10:08:25 +0800891 del_timer_sync(&hnat_priv->hnat_reset_timestamp_timer);
892
developer34028fb2022-01-11 13:51:29 +0800893 if (IS_HQOS_MODE && IS_GMAC1_MODE)
developerfd40db22021-04-29 10:08:25 +0800894 dev_remove_pack(&mtk_pack_type);
developerfd40db22021-04-29 10:08:25 +0800895
896 return 0;
897}
898
899static const struct mtk_hnat_data hnat_data_v1 = {
900 .num_of_sch = 2,
901 .whnat = false,
902 .per_flow_accounting = false,
903 .mcast = false,
developer4164cfe2022-12-01 11:27:41 +0800904 .version = MTK_HNAT_V1_1,
developerfd40db22021-04-29 10:08:25 +0800905};
906
907static const struct mtk_hnat_data hnat_data_v2 = {
908 .num_of_sch = 2,
909 .whnat = true,
910 .per_flow_accounting = true,
911 .mcast = false,
developer4164cfe2022-12-01 11:27:41 +0800912 .version = MTK_HNAT_V1_2,
developerfd40db22021-04-29 10:08:25 +0800913};
914
915static const struct mtk_hnat_data hnat_data_v3 = {
916 .num_of_sch = 4,
917 .whnat = false,
918 .per_flow_accounting = false,
919 .mcast = false,
developer4164cfe2022-12-01 11:27:41 +0800920 .version = MTK_HNAT_V1_3,
developerfd40db22021-04-29 10:08:25 +0800921};
922
923static const struct mtk_hnat_data hnat_data_v4 = {
924 .num_of_sch = 4,
925 .whnat = true,
926 .per_flow_accounting = true,
927 .mcast = false,
developer4164cfe2022-12-01 11:27:41 +0800928 .version = MTK_HNAT_V2,
developerfd40db22021-04-29 10:08:25 +0800929};
930
developerd35bbcc2022-09-28 22:46:01 +0800931static const struct mtk_hnat_data hnat_data_v5 = {
932 .num_of_sch = 4,
933 .whnat = true,
934 .per_flow_accounting = true,
935 .mcast = false,
developer4164cfe2022-12-01 11:27:41 +0800936 .version = MTK_HNAT_V3,
developerd35bbcc2022-09-28 22:46:01 +0800937};
938
developerfd40db22021-04-29 10:08:25 +0800939const struct of_device_id of_hnat_match[] = {
940 { .compatible = "mediatek,mtk-hnat", .data = &hnat_data_v3 },
941 { .compatible = "mediatek,mtk-hnat_v1", .data = &hnat_data_v1 },
942 { .compatible = "mediatek,mtk-hnat_v2", .data = &hnat_data_v2 },
943 { .compatible = "mediatek,mtk-hnat_v3", .data = &hnat_data_v3 },
944 { .compatible = "mediatek,mtk-hnat_v4", .data = &hnat_data_v4 },
developerd35bbcc2022-09-28 22:46:01 +0800945 { .compatible = "mediatek,mtk-hnat_v5", .data = &hnat_data_v5 },
developerfd40db22021-04-29 10:08:25 +0800946 {},
947};
948MODULE_DEVICE_TABLE(of, of_hnat_match);
949
950static struct platform_driver hnat_driver = {
951 .probe = hnat_probe,
952 .remove = hnat_remove,
953 .driver = {
954 .name = "mediatek_soc_hnat",
955 .of_match_table = of_hnat_match,
956 },
957};
958
959module_platform_driver(hnat_driver);
960
961MODULE_LICENSE("GPL v2");
962MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
963MODULE_AUTHOR("John Crispin <john@phrozen.org>");
964MODULE_DESCRIPTION("Mediatek Hardware NAT");