blob: 268e3eea4774ff93da548c4c85707b917d138b22 [file] [log] [blame]
developere5e687d2023-08-08 16:05:33 +08001// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (c) 2023 MediaTek Inc. All Rights Reserved.
4 *
5 * Author: Ren-Ting Wang <ren-ting.wang@mediatek.com>
6 */
7
8#include <linux/completion.h>
9#include <linux/device.h>
10#include <linux/dmaengine.h>
11#include <linux/dma-mapping.h>
12#include <linux/err.h>
13#include <linux/hashtable.h>
14#include <linux/if_ether.h>
15#include <linux/ip.h>
16#include <linux/kthread.h>
17#include <linux/list.h>
18#include <linux/lockdep.h>
19#include <linux/string.h>
20
21#include <mtk_eth_soc.h>
22#include <mtk_hnat/hnat.h>
23#include <mtk_hnat/nf_hnat_mtk.h>
24
developer84f378f2023-08-24 18:26:50 +080025#include <pce/cdrt.h>
26#include <pce/cls.h>
developere5e687d2023-08-08 16:05:33 +080027#include <pce/dipfilter.h>
developer6a0a7102023-09-18 18:03:07 +080028#include <pce/netsys.h>
developere5e687d2023-08-08 16:05:33 +080029#include <pce/pce.h>
30
31#include "internal.h"
32#include "mbox.h"
33#include "mcu.h"
34#include "netsys.h"
35#include "protocol/gre/gretap.h"
36#include "protocol/l2tp/udp_l2tp_data.h"
37#include "tunnel.h"
38
39#define TOPS_PPE_ENTRY_BUCKETS (64)
40#define TOPS_PPE_ENTRY_BUCKETS_BIT (6)
41
42struct tops_tnl {
43 /* tunnel types */
44 struct tops_tnl_type *offload_tnl_types[__TOPS_ENTRY_MAX];
45 u32 offload_tnl_type_num;
46 u32 tnl_base_addr;
47
48 /* tunnel table */
49 DECLARE_HASHTABLE(ht, CONFIG_TOPS_TNL_MAP_BIT);
50 DECLARE_BITMAP(tnl_used, CONFIG_TOPS_TNL_NUM);
51 wait_queue_head_t tnl_sync_wait;
52 spinlock_t tnl_sync_lock;
53 spinlock_t tbl_lock;
54 bool has_tnl_to_sync;
55 struct task_struct *tnl_sync_thread;
56 struct list_head *tnl_sync_pending;
57 struct list_head *tnl_sync_submit;
58 struct tops_tnl_info *tnl_infos;
59
60 /* dma request */
61 struct completion dma_done;
62 struct dma_chan *dmachan;
63
64 struct device *dev;
65};
66
67static enum mbox_msg_cnt tnl_offload_mbox_cmd_recv(struct mailbox_dev *mdev,
68 struct mailbox_msg *msg);
69
70static struct tops_tnl tops_tnl;
71
72static LIST_HEAD(tnl_sync_q1);
73static LIST_HEAD(tnl_sync_q2);
74
75struct mailbox_dev tnl_offload_mbox_recv =
76 MBOX_RECV_MGMT_DEV(TNL_OFFLOAD, tnl_offload_mbox_cmd_recv);
77
78/* tunnel mailbox communication */
79static enum mbox_msg_cnt tnl_offload_mbox_cmd_recv(struct mailbox_dev *mdev,
80 struct mailbox_msg *msg)
81{
82 switch (msg->msg1) {
83 case TOPS_TNL_START_ADDR_SYNC:
84 tops_tnl.tnl_base_addr = msg->msg2;
85
86 return MBOX_NO_RET_MSG;
87 default:
88 break;
89 }
90
91 return MBOX_NO_RET_MSG;
92}
93
94static inline void tnl_flush_ppe_entry(struct foe_entry *entry, u32 tnl_idx)
95{
96 u32 bind_tnl_idx;
97
98 if (unlikely(!entry))
99 return;
100
101 switch (entry->bfib1.pkt_type) {
102 case IPV4_HNAPT:
103 if (entry->ipv4_hnapt.tport_id != NR_TDMA_TPORT
104 && entry->ipv4_hnapt.tport_id != NR_TDMA_QDMA_TPORT)
105 return;
106
107 bind_tnl_idx = entry->ipv4_hnapt.tops_entry - __TOPS_ENTRY_MAX;
108
109 break;
110 default:
111 return;
112 }
113
114 /* unexpected tunnel index */
115 if (bind_tnl_idx >= __TOPS_ENTRY_MAX)
116 return;
117
118 if (tnl_idx == __TOPS_ENTRY_MAX || tnl_idx == bind_tnl_idx)
119 memset(entry, 0, sizeof(*entry));
120}
121
122static inline void skb_set_tops_tnl_idx(struct sk_buff *skb, u32 tnl_idx)
123{
124 skb_hnat_tops(skb) = tnl_idx + __TOPS_ENTRY_MAX;
125}
126
127static inline bool skb_tops_valid(struct sk_buff *skb)
128{
developer84f378f2023-08-24 18:26:50 +0800129 return (skb && skb_hnat_tops(skb) < __TOPS_ENTRY_MAX);
developere5e687d2023-08-08 16:05:33 +0800130}
131
132static inline struct tops_tnl_type *skb_to_tnl_type(struct sk_buff *skb)
133{
134 enum tops_entry_type tops_entry = skb_hnat_tops(skb);
135 struct tops_tnl_type *tnl_type;
136
137 if (unlikely(!tops_entry || tops_entry >= __TOPS_ENTRY_MAX))
138 return ERR_PTR(-EINVAL);
139
140 tnl_type = tops_tnl.offload_tnl_types[tops_entry];
141
142 return tnl_type ? tnl_type : ERR_PTR(-ENODEV);
143}
144
developer84f378f2023-08-24 18:26:50 +0800145static inline struct tops_tnl_info *skb_to_tnl_info(struct sk_buff *skb)
146{
147 u32 tnl_idx = skb_hnat_tops(skb) - __TOPS_ENTRY_MAX;
148
149 if (tnl_idx >= CONFIG_TOPS_TNL_NUM)
150 return ERR_PTR(-EINVAL);
151
152 if (!test_bit(tnl_idx, tops_tnl.tnl_used))
153 return ERR_PTR(-EACCES);
154
155 return &tops_tnl.tnl_infos[tnl_idx];
156}
157
developere5e687d2023-08-08 16:05:33 +0800158static inline void skb_mark_unbind(struct sk_buff *skb)
159{
160 skb_hnat_tops(skb) = 0;
161 skb_hnat_is_decap(skb) = 0;
162 skb_hnat_alg(skb) = 1;
163}
164
165static inline u32 tnl_params_hash(struct tops_tnl_params *tnl_params)
166{
167 if (!tnl_params)
168 return 0;
169
170 /* TODO: check collision possibility? */
171 return (tnl_params->sip ^ tnl_params->dip);
172}
173
174static inline bool tnl_info_decap_is_enable(struct tops_tnl_info *tnl_info)
175{
176 return tnl_info->cache.flag & TNL_DECAP_ENABLE;
177}
178
179static inline void tnl_info_decap_enable(struct tops_tnl_info *tnl_info)
180{
181 tnl_info->cache.flag |= TNL_DECAP_ENABLE;
182}
183
184static inline void tnl_info_decap_disable(struct tops_tnl_info *tnl_info)
185{
186 tnl_info->cache.flag &= ~(TNL_DECAP_ENABLE);
187}
188
189static inline bool tnl_info_encap_is_enable(struct tops_tnl_info *tnl_info)
190{
191 return tnl_info->cache.flag & TNL_ENCAP_ENABLE;
192}
193
194static inline void tnl_info_encap_enable(struct tops_tnl_info *tnl_info)
195{
196 tnl_info->cache.flag |= TNL_ENCAP_ENABLE;
197}
198
199static inline void tnl_info_encap_disable(struct tops_tnl_info *tnl_info)
200{
201 tnl_info->cache.flag &= ~(TNL_ENCAP_ENABLE);
202}
203
204static inline void tnl_info_sta_updated_no_tnl_lock(struct tops_tnl_info *tnl_info)
205{
206 tnl_info->status &= (~TNL_STA_UPDATING);
207 tnl_info->status &= (~TNL_STA_INIT);
208 tnl_info->status |= TNL_STA_UPDATED;
209}
210
211static inline void tnl_info_sta_updated(struct tops_tnl_info *tnl_info)
212{
213 unsigned long flag = 0;
214
215 if (unlikely(!tnl_info))
216 return;
217
218 spin_lock_irqsave(&tnl_info->lock, flag);
219
220 tnl_info_sta_updated_no_tnl_lock(tnl_info);
221
222 spin_unlock_irqrestore(&tnl_info->lock, flag);
223}
224
225static inline bool tnl_info_sta_is_updated(struct tops_tnl_info *tnl_info)
226{
227 return tnl_info->status & TNL_STA_UPDATED;
228}
229
230static inline void tnl_info_sta_updating_no_tnl_lock(struct tops_tnl_info *tnl_info)
231{
232 tnl_info->status |= TNL_STA_UPDATING;
233 tnl_info->status &= (~TNL_STA_QUEUED);
234 tnl_info->status &= (~TNL_STA_UPDATED);
235}
236
237static inline void tnl_info_sta_updating(struct tops_tnl_info *tnl_info)
238{
239 unsigned long flag = 0;
240
241 if (unlikely(!tnl_info))
242 return;
243
244 spin_lock_irqsave(&tnl_info->lock, flag);
245
246 tnl_info_sta_updating_no_tnl_lock(tnl_info);
247
248 spin_unlock_irqrestore(&tnl_info->lock, flag);
249}
250
251static inline bool tnl_info_sta_is_updating(struct tops_tnl_info *tnl_info)
252{
253 return tnl_info->status & TNL_STA_UPDATING;
254}
255
256static inline void tnl_info_sta_queued_no_tnl_lock(struct tops_tnl_info *tnl_info)
257{
258 tnl_info->status |= TNL_STA_QUEUED;
259 tnl_info->status &= (~TNL_STA_UPDATED);
260}
261
262static inline void tnl_info_sta_queued(struct tops_tnl_info *tnl_info)
263{
264 unsigned long flag = 0;
265
266 if (unlikely(!tnl_info))
267 return;
268
269 spin_lock_irqsave(&tnl_info->lock, flag);
270
271 tnl_info_sta_queued_no_tnl_lock(tnl_info);
272
273 spin_unlock_irqrestore(&tnl_info->lock, flag);
274}
275
276static inline bool tnl_info_sta_is_queued(struct tops_tnl_info *tnl_info)
277{
278 return tnl_info->status & TNL_STA_QUEUED;
279}
280
281static inline void tnl_info_sta_init_no_tnl_lock(struct tops_tnl_info *tnl_info)
282{
283 tnl_info->status = TNL_STA_INIT;
284}
285
286static inline void tnl_info_sta_init(struct tops_tnl_info *tnl_info)
287{
288 unsigned long flag = 0;
289
290 if (unlikely(!tnl_info))
291 return;
292
293 spin_lock_irqsave(&tnl_info->lock, flag);
294
295 tnl_info_sta_init_no_tnl_lock(tnl_info);
296
297 spin_unlock_irqrestore(&tnl_info->lock, flag);
298}
299
300static inline bool tnl_info_sta_is_init(struct tops_tnl_info *tnl_info)
301{
302 return tnl_info->status & TNL_STA_INIT;
303}
304
305static inline void tnl_info_sta_uninit_no_tnl_lock(struct tops_tnl_info *tnl_info)
306{
307 tnl_info->status = TNL_STA_UNINIT;
308}
309
310static inline void tnl_info_sta_uninit(struct tops_tnl_info *tnl_info)
311{
312 unsigned long flag = 0;
313
314 if (unlikely(!tnl_info))
315 return;
316
317 spin_lock_irqsave(&tnl_info->lock, flag);
318
319 tnl_info_sta_uninit_no_tnl_lock(tnl_info);
320
321 spin_unlock_irqrestore(&tnl_info->lock, flag);
322}
323
324static inline bool tnl_info_sta_is_uninit(struct tops_tnl_info *tnl_info)
325{
326 return tnl_info->status & TNL_STA_UNINIT;
327}
328
329static inline void tnl_info_submit_no_tnl_lock(struct tops_tnl_info *tnl_info)
330{
331 unsigned long flag = 0;
332
333 spin_lock_irqsave(&tops_tnl.tnl_sync_lock, flag);
334
335 list_add_tail(&tnl_info->sync_node, tops_tnl.tnl_sync_submit);
336
337 tops_tnl.has_tnl_to_sync = true;
338
339 spin_unlock_irqrestore(&tops_tnl.tnl_sync_lock, flag);
340
341 if (mtk_tops_mcu_alive())
342 wake_up_interruptible(&tops_tnl.tnl_sync_wait);
343}
344
developer15ee46c2023-08-24 16:35:34 +0800345static void mtk_tops_tnl_info_cls_update_idx(struct tops_tnl_info *tnl_info)
346{
347 unsigned long flag;
348
349 tnl_info->tnl_params.cls_entry = tnl_info->tcls->cls->idx;
developer15ee46c2023-08-24 16:35:34 +0800350
351 spin_lock_irqsave(&tnl_info->lock, flag);
352 tnl_info->cache.cls_entry = tnl_info->tcls->cls->idx;
353 spin_unlock_irqrestore(&tnl_info->lock, flag);
354}
355
developer84f378f2023-08-24 18:26:50 +0800356static void mtk_tops_tnl_info_cls_entry_unprepare(struct tops_tnl_info *tnl_info,
357 struct tops_tnl_params *tnl_params)
developer15ee46c2023-08-24 16:35:34 +0800358{
359 struct tops_cls_entry *tcls = tnl_info->tcls;
360
developer15ee46c2023-08-24 16:35:34 +0800361 tnl_info->tcls = NULL;
362
363 if (refcount_dec_and_test(&tcls->refcnt)) {
developer15ee46c2023-08-24 16:35:34 +0800364 list_del(&tcls->node);
365
developer84f378f2023-08-24 18:26:50 +0800366 if (!tnl_params->cdrt)
367 memset(&tcls->cls->cdesc, 0, sizeof(tcls->cls->cdesc));
368 else
369 /*
370 * recover tport_ix to let match packets to
371 * go through EIP197 only
372 */
373 CLS_DESC_DATA(&tcls->cls->cdesc, tport_idx, 2);
developer15ee46c2023-08-24 16:35:34 +0800374
375 mtk_pce_cls_entry_write(tcls->cls);
376
377 mtk_pce_cls_entry_free(tcls->cls);
378
379 devm_kfree(tops_dev, tcls);
380 }
381}
382
383static struct tops_cls_entry *
developer84f378f2023-08-24 18:26:50 +0800384mtk_tops_tnl_info_cls_entry_prepare(struct tops_tnl_info *tnl_info,
385 struct tops_tnl_params *tnl_params)
developer15ee46c2023-08-24 16:35:34 +0800386{
387 struct tops_cls_entry *tcls;
388 int ret;
389
390 tcls = devm_kzalloc(tops_dev, sizeof(struct tops_cls_entry), GFP_KERNEL);
391 if (!tcls)
392 return ERR_PTR(-ENOMEM);
393
developer84f378f2023-08-24 18:26:50 +0800394 if (!tnl_params->cdrt) {
395 tcls->cls = mtk_pce_cls_entry_alloc();
396 if (IS_ERR(tcls->cls)) {
397 ret = PTR_ERR(tcls->cls);
398 goto free_tcls;
399 }
400 } else {
401 struct cdrt_entry *cdrt = mtk_pce_cdrt_entry_find(tnl_params->cdrt);
402
403 if (IS_ERR(cdrt)) {
404 ret = PTR_ERR(cdrt);
405 goto free_tcls;
406 }
407
408 tcls->cls = cdrt->cls;
developer15ee46c2023-08-24 16:35:34 +0800409 }
410
411 INIT_LIST_HEAD(&tcls->node);
412 list_add_tail(&tnl_info->tnl_type->tcls_head, &tcls->node);
413
414 tnl_info->tcls = tcls;
415 refcount_set(&tcls->refcnt, 1);
416
417 return tcls;
418
419free_tcls:
420 devm_kfree(tops_dev, tcls);
421
422 return ERR_PTR(ret);
423}
424
425static int mtk_tops_tnl_info_cls_entry_write(struct tops_tnl_info *tnl_info)
426{
427 int ret;
428
429 if (!tnl_info->tcls)
430 return -EINVAL;
431
432 ret = mtk_pce_cls_entry_write(tnl_info->tcls->cls);
developer84f378f2023-08-24 18:26:50 +0800433 if (ret)
developer15ee46c2023-08-24 16:35:34 +0800434 return ret;
developer15ee46c2023-08-24 16:35:34 +0800435
436 tnl_info->tcls->updated = true;
437
438 mtk_tops_tnl_info_cls_update_idx(tnl_info);
439
440 return 0;
441}
442
developer84f378f2023-08-24 18:26:50 +0800443static int mtk_tops_tnl_info_cls_tear_down(struct tops_tnl_info *tnl_info,
444 struct tops_tnl_params *tnl_params)
developer15ee46c2023-08-24 16:35:34 +0800445{
developer84f378f2023-08-24 18:26:50 +0800446 mtk_tops_tnl_info_cls_entry_unprepare(tnl_info, tnl_params);
developer15ee46c2023-08-24 16:35:34 +0800447
448 return 0;
449}
450
451/*
452 * check cls entry is updated for tunnel protocols that only use 1 CLS HW entry
453 *
454 * since only tunnel sync task will operate on tcls linked list,
455 * it is safe to access without lock
456 *
457 * return true on updated
458 * return false on need update
459 */
460static bool mtk_tops_tnl_info_cls_single_is_updated(struct tops_tnl_info *tnl_info,
461 struct tops_tnl_type *tnl_type)
462{
463 /*
464 * check tnl_type has already allocate a tops_cls_entry
465 * if not, return false to prepare to allocate a new one
466 */
467 if (list_empty(&tnl_type->tcls_head))
468 return false;
469
470 /*
471 * if tnl_info is not associate to tnl_type's cls entry,
472 * make a reference to tops_cls_entry
473 */
474 if (!tnl_info->tcls) {
475 tnl_info->tcls = list_first_entry(&tnl_type->tcls_head,
476 struct tops_cls_entry,
477 node);
478
479 refcount_inc(&tnl_info->tcls->refcnt);
480 mtk_tops_tnl_info_cls_update_idx(tnl_info);
481 }
482
483 return tnl_info->tcls->updated;
484}
485
486static int mtk_tops_tnl_info_cls_single_setup(struct tops_tnl_info *tnl_info,
developer84f378f2023-08-24 18:26:50 +0800487 struct tops_tnl_params *tnl_params,
developer15ee46c2023-08-24 16:35:34 +0800488 struct tops_tnl_type *tnl_type)
489{
490 struct tops_cls_entry *tcls;
491 int ret;
492
493 if (mtk_tops_tnl_info_cls_single_is_updated(tnl_info, tnl_type))
494 return 0;
495
496 if (tnl_info->tcls)
developer84f378f2023-08-24 18:26:50 +0800497 goto cls_entry_write;
developer15ee46c2023-08-24 16:35:34 +0800498
developer84f378f2023-08-24 18:26:50 +0800499 tcls = mtk_tops_tnl_info_cls_entry_prepare(tnl_info, tnl_params);
developer15ee46c2023-08-24 16:35:34 +0800500 if (IS_ERR(tcls))
501 return PTR_ERR(tcls);
502
developer84f378f2023-08-24 18:26:50 +0800503 if (!tnl_params->cdrt) {
504 ret = tnl_type->cls_entry_setup(tnl_info, &tcls->cls->cdesc);
505 if (ret) {
506 TOPS_ERR("tops cls entry setup failed: %d\n", ret);
507 goto cls_entry_unprepare;
508 }
509 } else {
510 /*
511 * since CLS is already filled up with outer protocol rule
developer6a0a7102023-09-18 18:03:07 +0800512 * we only update CLS tport here to let matched packet to go through
513 * QDMA and specify the destination port to TOPS
developer84f378f2023-08-24 18:26:50 +0800514 */
developer6a0a7102023-09-18 18:03:07 +0800515 CLS_DESC_DATA(&tcls->cls->cdesc, tport_idx, NR_EIP197_QDMA_TPORT);
516 CLS_DESC_DATA(&tcls->cls->cdesc, fport, PSE_PORT_TDMA);
517 CLS_DESC_DATA(&tcls->cls->cdesc, qid, 12);
developer15ee46c2023-08-24 16:35:34 +0800518 }
519
developer84f378f2023-08-24 18:26:50 +0800520cls_entry_write:
521 ret = mtk_tops_tnl_info_cls_entry_write(tnl_info);
522
523cls_entry_unprepare:
524 if (ret)
525 mtk_tops_tnl_info_cls_entry_unprepare(tnl_info, tnl_params);
526
527 return ret;
developer15ee46c2023-08-24 16:35:34 +0800528}
529
530static struct tops_cls_entry *
531mtk_tops_tnl_info_cls_entry_find(struct tops_tnl_type *tnl_type,
532 struct cls_desc *cdesc)
533{
534 struct tops_cls_entry *tcls;
535
536 list_for_each_entry(tcls, &tnl_type->tcls_head, node)
537 if (!memcmp(&tcls->cls->cdesc, cdesc, sizeof(struct cls_desc)))
538 return tcls;
539
540 return NULL;
541}
542
developer84f378f2023-08-24 18:26:50 +0800543static bool mtk_tops_tnl_info_cls_multi_is_updated(struct tops_tnl_info *tnl_info,
developer15ee46c2023-08-24 16:35:34 +0800544 struct tops_tnl_type *tnl_type,
545 struct cls_desc *cdesc)
546{
547 struct tops_cls_entry *tcls;
548
549 if (list_empty(&tnl_type->tcls_head))
550 return false;
551
552 if (tnl_info->tcls) {
553 if (!memcmp(cdesc, &tnl_info->tcls->cls->cdesc, sizeof(*cdesc)))
554 return tnl_info->tcls->updated;
555
556 memcpy(&tnl_info->tcls->cls->cdesc, cdesc, sizeof(*cdesc));
557 tnl_info->tcls->updated = false;
558 return false;
559 }
560
561 tcls = mtk_tops_tnl_info_cls_entry_find(tnl_type, cdesc);
562 if (!tcls)
563 return false;
564
565 tnl_info->tcls = tcls;
566 refcount_inc(&tnl_info->tcls->refcnt);
567 mtk_tops_tnl_info_cls_update_idx(tnl_info);
568
569 return tcls->updated;
570}
571
572static int mtk_tops_tnl_info_cls_multi_setup(struct tops_tnl_info *tnl_info,
developer84f378f2023-08-24 18:26:50 +0800573 struct tops_tnl_params *tnl_params,
developer15ee46c2023-08-24 16:35:34 +0800574 struct tops_tnl_type *tnl_type)
575{
576 struct tops_cls_entry *tcls;
577 struct cls_desc cdesc;
developer84f378f2023-08-24 18:26:50 +0800578
developer15ee46c2023-08-24 16:35:34 +0800579 int ret;
580
developer84f378f2023-08-24 18:26:50 +0800581 if (!tnl_params->cdrt) {
582 memset(&cdesc, 0, sizeof(struct cls_desc));
developer15ee46c2023-08-24 16:35:34 +0800583
developer84f378f2023-08-24 18:26:50 +0800584 /* prepare cls_desc from tnl_type */
585 ret = tnl_type->cls_entry_setup(tnl_info, &cdesc);
586 if (ret) {
587 TOPS_ERR("tops cls entry setup failed: %d\n", ret);
588 return ret;
589 }
590 } else {
591 struct cdrt_entry *cdrt = mtk_pce_cdrt_entry_find(tnl_params->cdrt);
592
593 if (IS_ERR(cdrt)) {
594 TOPS_ERR("no cdrt idx: %u related CDRT found\n",
595 tnl_params->cdrt);
596 return ret;
597 }
598
599 memcpy(&cdesc, &cdrt->cls->cdesc, sizeof(struct cls_desc));
600
601 CLS_DESC_DATA(&cdesc, tport_idx, 0x7);
developer15ee46c2023-08-24 16:35:34 +0800602 }
603
604 /*
605 * check cdesc is already updated, if tnl_info is not associate with a
606 * tcls but we found a tcls has the same cls desc content as cdesc
607 * tnl_info will setup an association with that tcls
608 *
609 * we only go further to this if condition when
610 * a tcls is not yet updated or
611 * tnl_info is not yet associated to a tcls
612 */
developer84f378f2023-08-24 18:26:50 +0800613 if (mtk_tops_tnl_info_cls_multi_is_updated(tnl_info, tnl_type, &cdesc))
developer15ee46c2023-08-24 16:35:34 +0800614 return 0;
615
616 /* tcls is not yet updated, update this tcls */
617 if (tnl_info->tcls)
618 return mtk_tops_tnl_info_cls_entry_write(tnl_info);
619
620 /* create a new tcls entry and associate with tnl_info */
developer84f378f2023-08-24 18:26:50 +0800621 tcls = mtk_tops_tnl_info_cls_entry_prepare(tnl_info, tnl_params);
developer15ee46c2023-08-24 16:35:34 +0800622 if (IS_ERR(tcls))
623 return PTR_ERR(tcls);
624
625 memcpy(&tcls->cls->cdesc, &cdesc, sizeof(struct cls_desc));
626
developer84f378f2023-08-24 18:26:50 +0800627 ret = mtk_tops_tnl_info_cls_entry_write(tnl_info);
628 if (ret)
629 mtk_tops_tnl_info_cls_entry_unprepare(tnl_info, tnl_params);
630
631 return ret;
developer15ee46c2023-08-24 16:35:34 +0800632}
633
developer84f378f2023-08-24 18:26:50 +0800634static int mtk_tops_tnl_info_cls_setup(struct tops_tnl_info *tnl_info,
635 struct tops_tnl_params *tnl_params)
developer15ee46c2023-08-24 16:35:34 +0800636{
637 struct tops_tnl_type *tnl_type;
638
639 if (tnl_info->tcls && tnl_info->tcls->updated)
640 return 0;
641
642 tnl_type = tnl_info->tnl_type;
643 if (!tnl_type)
644 return -EINVAL;
645
646 if (!tnl_type->use_multi_cls)
developer84f378f2023-08-24 18:26:50 +0800647 return mtk_tops_tnl_info_cls_single_setup(tnl_info,
648 tnl_params,
649 tnl_type);
developer15ee46c2023-08-24 16:35:34 +0800650
developer84f378f2023-08-24 18:26:50 +0800651 return mtk_tops_tnl_info_cls_multi_setup(tnl_info, tnl_params, tnl_type);
developer15ee46c2023-08-24 16:35:34 +0800652}
653
developere5e687d2023-08-08 16:05:33 +0800654static int mtk_tops_tnl_info_dipfilter_tear_down(struct tops_tnl_info *tnl_info)
655{
656 struct dip_desc dipd;
657
658 memset(&dipd, 0, sizeof(struct dip_desc));
659
660 dipd.ipv4 = be32_to_cpu(tnl_info->tnl_params.sip);
661 dipd.tag = DIPFILTER_IPV4;
662
663 return mtk_pce_dipfilter_entry_del(&dipd);
664}
665
666static int mtk_tops_tnl_info_dipfilter_setup(struct tops_tnl_info *tnl_info)
667{
668 struct dip_desc dipd;
669
670 /* setup dipfilter */
671 memset(&dipd, 0, sizeof(struct dip_desc));
672
673 dipd.ipv4 = be32_to_cpu(tnl_info->tnl_params.sip);
674 dipd.tag = DIPFILTER_IPV4;
675
676 return mtk_pce_dipfilter_entry_add(&dipd);
677}
678
679void mtk_tops_tnl_info_submit_no_tnl_lock(struct tops_tnl_info *tnl_info)
680{
681 lockdep_assert_held(&tnl_info->lock);
682
683 if (tnl_info_sta_is_queued(tnl_info))
684 return;
685
686 tnl_info_submit_no_tnl_lock(tnl_info);
687
688 tnl_info_sta_queued_no_tnl_lock(tnl_info);
689}
690
691void mtk_tops_tnl_info_submit(struct tops_tnl_info *tnl_info)
692{
693 unsigned long flag = 0;
694
695 if (unlikely(!tnl_info))
696 return;
697
698 spin_lock_irqsave(&tnl_info->lock, flag);
699
700 mtk_tops_tnl_info_submit_no_tnl_lock(tnl_info);
701
702 spin_unlock_irqrestore(&tnl_info->lock, flag);
703}
704
705static void mtk_tops_tnl_info_hash_no_lock(struct tops_tnl_info *tnl_info)
706{
707 lockdep_assert_held(&tops_tnl.tbl_lock);
708 lockdep_assert_held(&tnl_info->lock);
709
710 if (hash_hashed(&tnl_info->hlist))
711 hash_del(&tnl_info->hlist);
712
713 hash_add(tops_tnl.ht, &tnl_info->hlist, tnl_params_hash(&tnl_info->cache));
714}
715
716void mtk_tops_tnl_info_hash(struct tops_tnl_info *tnl_info)
717{
718 unsigned long flag = 0;
719
720 if (unlikely(!tnl_info))
721 return;
722
723 spin_lock_irqsave(&tops_tnl.tbl_lock, flag);
724
725 spin_lock(&tnl_info->lock);
726
727 mtk_tops_tnl_info_hash_no_lock(tnl_info);
728
729 spin_unlock(&tnl_info->lock);
730
731 spin_unlock_irqrestore(&tops_tnl.tbl_lock, flag);
732}
733
734static bool mtk_tops_tnl_info_match(struct tops_tnl_type *tnl_type,
735 struct tops_tnl_info *tnl_info,
736 struct tops_tnl_params *match_data)
737{
738 unsigned long flag = 0;
739 bool match;
740
741 spin_lock_irqsave(&tnl_info->lock, flag);
742
743 match = tnl_type->tnl_info_match(&tnl_info->cache, match_data);
744
745 spin_unlock_irqrestore(&tnl_info->lock, flag);
746
747 return match;
748}
749
750struct tops_tnl_info *mtk_tops_tnl_info_find(struct tops_tnl_params *tnl_params)
751{
752 struct tops_tnl_info *tnl_info;
753 struct tops_tnl_type *tnl_type;
754
755 lockdep_assert_held(&tops_tnl.tbl_lock);
756
757 if (unlikely(!tnl_params->tops_entry_proto
758 || tnl_params->tops_entry_proto >= __TOPS_ENTRY_MAX))
759 return ERR_PTR(-EINVAL);
760
761 tnl_type = tops_tnl.offload_tnl_types[tnl_params->tops_entry_proto];
762 if (unlikely(!tnl_type))
763 return ERR_PTR(-EINVAL);
764
765 if (unlikely(!tnl_type->tnl_info_match))
766 return ERR_PTR(-ENXIO);
767
768 hash_for_each_possible(tops_tnl.ht,
769 tnl_info,
770 hlist,
771 tnl_params_hash(tnl_params))
772 if (mtk_tops_tnl_info_match(tnl_type, tnl_info, tnl_params))
773 return tnl_info;
774
775 return ERR_PTR(-ENODEV);
776}
777
778/* tnl_info->lock should be held before calling this function */
779static int mtk_tops_tnl_info_setup(struct sk_buff *skb,
780 struct tops_tnl_info *tnl_info,
781 struct tops_tnl_params *tnl_params)
782{
783 if (unlikely(!skb || !tnl_info || !tnl_params))
784 return -EPERM;
785
786 lockdep_assert_held(&tnl_info->lock);
787
developer84f378f2023-08-24 18:26:50 +0800788 /* manually preserve essential data among encapsulation and decapsulation */
developere5e687d2023-08-08 16:05:33 +0800789 tnl_params->flag |= tnl_info->cache.flag;
developer15ee46c2023-08-24 16:35:34 +0800790 tnl_params->cls_entry = tnl_info->cache.cls_entry;
developer84f378f2023-08-24 18:26:50 +0800791 if (tnl_info->cache.cdrt)
792 tnl_params->cdrt = tnl_info->cache.cdrt;
developere5e687d2023-08-08 16:05:33 +0800793
794 if (memcmp(&tnl_info->cache, tnl_params, sizeof(struct tops_tnl_params))) {
795 memcpy(&tnl_info->cache, tnl_params, sizeof(struct tops_tnl_params));
796
797 mtk_tops_tnl_info_hash_no_lock(tnl_info);
798 }
799
800 if (skb_hnat_is_decap(skb)) {
801 /* the net_device is used to forward pkt to decap'ed inf when Rx */
802 tnl_info->dev = skb->dev;
803 if (!tnl_info_decap_is_enable(tnl_info)) {
804 tnl_info_decap_enable(tnl_info);
805
806 mtk_tops_tnl_info_submit_no_tnl_lock(tnl_info);
807 }
808 } else if (skb_hnat_is_encap(skb)) {
809 /* set skb_hnat_tops(skb) to tunnel index for ppe binding */
810 skb_set_tops_tnl_idx(skb, tnl_info->tnl_idx);
811 if (!tnl_info_encap_is_enable(tnl_info)) {
812 tnl_info_encap_enable(tnl_info);
813
814 mtk_tops_tnl_info_submit_no_tnl_lock(tnl_info);
815 }
816 }
817
818 return 0;
819}
820
821/* tops_tnl.tbl_lock should be acquired before calling this functions */
developer15ee46c2023-08-24 16:35:34 +0800822static struct tops_tnl_info *
823mtk_tops_tnl_info_alloc_no_lock(struct tops_tnl_type *tnl_type)
developere5e687d2023-08-08 16:05:33 +0800824{
825 struct tops_tnl_info *tnl_info;
826 unsigned long flag = 0;
827 u32 tnl_idx;
828
829 lockdep_assert_held(&tops_tnl.tbl_lock);
830
831 tnl_idx = find_first_zero_bit(tops_tnl.tnl_used, CONFIG_TOPS_TNL_NUM);
832 if (tnl_idx == CONFIG_TOPS_TNL_NUM) {
833 TOPS_NOTICE("offload tunnel table full!\n");
834 return ERR_PTR(-ENOMEM);
835 }
836
837 /* occupy used tunnel */
838 tnl_info = &tops_tnl.tnl_infos[tnl_idx];
839 memset(&tnl_info->tnl_params, 0, sizeof(struct tops_tnl_params));
840 memset(&tnl_info->cache, 0, sizeof(struct tops_tnl_params));
841
842 /* TODO: maybe spin_lock_bh() is enough? */
843 spin_lock_irqsave(&tnl_info->lock, flag);
844
845 if (tnl_info_sta_is_init(tnl_info)) {
846 TOPS_ERR("error: fetched an initialized tunnel info\n");
847
848 spin_unlock_irqrestore(&tnl_info->lock, flag);
849
850 return ERR_PTR(-EBADF);
851 }
852 tnl_info_sta_init_no_tnl_lock(tnl_info);
853
developer15ee46c2023-08-24 16:35:34 +0800854 tnl_info->tnl_type = tnl_type;
855
developere5e687d2023-08-08 16:05:33 +0800856 INIT_HLIST_NODE(&tnl_info->hlist);
857
858 spin_unlock_irqrestore(&tnl_info->lock, flag);
859
860 set_bit(tnl_idx, tops_tnl.tnl_used);
861
862 return tnl_info;
863}
864
developer15ee46c2023-08-24 16:35:34 +0800865struct tops_tnl_info *mtk_tops_tnl_info_alloc(struct tops_tnl_type *tnl_type)
developere5e687d2023-08-08 16:05:33 +0800866{
867 struct tops_tnl_info *tnl_info;
868 unsigned long flag = 0;
869
870 spin_lock_irqsave(&tops_tnl.tbl_lock, flag);
871
developer15ee46c2023-08-24 16:35:34 +0800872 tnl_info = mtk_tops_tnl_info_alloc_no_lock(tnl_type);
developere5e687d2023-08-08 16:05:33 +0800873
874 spin_unlock_irqrestore(&tops_tnl.tbl_lock, flag);
875
876 return tnl_info;
877}
878
879static void mtk_tops_tnl_info_free_no_lock(struct tops_tnl_info *tnl_info)
880{
881 if (unlikely(!tnl_info))
882 return;
883
884 lockdep_assert_held(&tops_tnl.tbl_lock);
885 lockdep_assert_held(&tnl_info->lock);
886
887 hash_del(&tnl_info->hlist);
888
889 tnl_info_sta_uninit_no_tnl_lock(tnl_info);
890
891 clear_bit(tnl_info->tnl_idx, tops_tnl.tnl_used);
892}
893
894static void mtk_tops_tnl_info_free(struct tops_tnl_info *tnl_info)
895{
896 unsigned long flag = 0;
897
898 spin_lock_irqsave(&tops_tnl.tbl_lock, flag);
899
900 spin_lock(&tnl_info->lock);
901
902 mtk_tops_tnl_info_free_no_lock(tnl_info);
903
904 spin_unlock(&tnl_info->lock);
905
906 spin_unlock_irqrestore(&tops_tnl.tbl_lock, flag);
907}
908
909static void __mtk_tops_tnl_offload_disable(struct tops_tnl_info *tnl_info)
910{
911 tnl_info->status |= TNL_STA_DELETING;
912 mtk_tops_tnl_info_submit_no_tnl_lock(tnl_info);
913}
914
915static int mtk_tops_tnl_offload(struct sk_buff *skb,
developer15ee46c2023-08-24 16:35:34 +0800916 struct tops_tnl_type *tnl_type,
developere5e687d2023-08-08 16:05:33 +0800917 struct tops_tnl_params *tnl_params)
918{
919 struct tops_tnl_info *tnl_info;
920 unsigned long flag;
921 int ret = 0;
922
923 if (unlikely(!tnl_params))
924 return -EPERM;
925
926 /* prepare tnl_info */
927 spin_lock_irqsave(&tops_tnl.tbl_lock, flag);
928
929 tnl_info = mtk_tops_tnl_info_find(tnl_params);
930 if (IS_ERR(tnl_info) && PTR_ERR(tnl_info) != -ENODEV) {
931 /* error */
932 ret = PTR_ERR(tnl_info);
933 goto err_out;
934 } else if (IS_ERR(tnl_info) && PTR_ERR(tnl_info) == -ENODEV) {
935 /* not allocate yet */
developer15ee46c2023-08-24 16:35:34 +0800936 tnl_info = mtk_tops_tnl_info_alloc_no_lock(tnl_type);
developere5e687d2023-08-08 16:05:33 +0800937 }
938
939 if (IS_ERR(tnl_info)) {
940 ret = PTR_ERR(tnl_info);
941 TOPS_DBG("tnl offload alloc tnl_info failed: %d\n", ret);
942 goto err_out;
943 }
944
945 spin_lock(&tnl_info->lock);
946 ret = mtk_tops_tnl_info_setup(skb, tnl_info, tnl_params);
developere5e687d2023-08-08 16:05:33 +0800947 spin_unlock(&tnl_info->lock);
948
949err_out:
950 spin_unlock_irqrestore(&tops_tnl.tbl_lock, flag);
951
952 return ret;
953}
954
developer84f378f2023-08-24 18:26:50 +0800955static int mtk_tops_tnl_l2_update(struct sk_buff *skb)
956{
957 struct tops_tnl_info *tnl_info = skb_to_tnl_info(skb);
958 struct tops_tnl_type *tnl_type;
959 unsigned long flag;
960 int ret;
961
962 if (IS_ERR(tnl_info))
963 return PTR_ERR(tnl_info);
964
965 tnl_type = tnl_info->tnl_type;
966 if (!tnl_type->tnl_l2_param_update)
967 return -ENODEV;
968
969 spin_lock_irqsave(&tnl_info->lock, flag);
970
971 ret = tnl_type->tnl_l2_param_update(skb, &tnl_info->cache);
972 /* tnl params need to be updated */
973 if (ret == 1) {
974 mtk_tops_tnl_info_submit_no_tnl_lock(tnl_info);
975 ret = 0;
976 }
977
978 spin_unlock_irqrestore(&tnl_info->lock, flag);
979
980 return ret;
981}
982
developere5e687d2023-08-08 16:05:33 +0800983static bool mtk_tops_tnl_decap_offloadable(struct sk_buff *skb)
984{
985 struct tops_tnl_type *tnl_type;
986 struct ethhdr *eth;
987 u32 cnt;
988 u32 i;
989
990 if (unlikely(!mtk_tops_mcu_alive())) {
991 skb_mark_unbind(skb);
992 return -EAGAIN;
993 }
994
995 /* skb should not carry tops here */
996 if (skb_hnat_tops(skb))
997 return false;
998
999 eth = eth_hdr(skb);
1000
1001 /* TODO: currently decap only support ethernet IPv4 */
1002 if (ntohs(eth->h_proto) != ETH_P_IP)
1003 return false;
1004
1005 /* TODO: may can be optimized */
1006 for (i = TOPS_ENTRY_GRETAP, cnt = 0;
1007 i < __TOPS_ENTRY_MAX && cnt < tops_tnl.offload_tnl_type_num;
1008 i++) {
1009 tnl_type = tops_tnl.offload_tnl_types[i];
1010 if (unlikely(!tnl_type))
1011 continue;
1012
1013 cnt++;
1014 if (tnl_type->tnl_decap_offloadable
1015 && tnl_type->tnl_decap_offloadable(skb)) {
1016 skb_hnat_tops(skb) = tnl_type->tops_entry;
1017 return true;
1018 }
1019 }
1020
1021 return false;
1022}
1023
1024static int mtk_tops_tnl_decap_offload(struct sk_buff *skb)
1025{
1026 struct tops_tnl_params tnl_params;
1027 struct tops_tnl_type *tnl_type;
1028 int ret;
1029
1030 if (unlikely(!mtk_tops_mcu_alive())) {
1031 skb_mark_unbind(skb);
1032 return -EAGAIN;
1033 }
1034
1035 if (unlikely(!skb_tops_valid(skb) || !skb_hnat_is_decap(skb))) {
1036 skb_mark_unbind(skb);
1037 return -EINVAL;
1038 }
1039
1040 tnl_type = skb_to_tnl_type(skb);
1041 if (IS_ERR(tnl_type)) {
1042 skb_mark_unbind(skb);
1043 return PTR_ERR(tnl_type);
1044 }
1045
1046 if (unlikely(!tnl_type->tnl_decap_param_setup)) {
1047 skb_mark_unbind(skb);
1048 return -ENODEV;
1049 }
1050
1051 memset(&tnl_params, 0, sizeof(struct tops_tnl_params));
1052
1053 /* push removed ethernet header back first */
1054 if (tnl_type->has_inner_eth)
1055 skb_push(skb, sizeof(struct ethhdr));
1056
1057 ret = tnl_type->tnl_decap_param_setup(skb, &tnl_params);
1058
1059 /* pull ethernet header to restore skb->data to ip start */
1060 if (tnl_type->has_inner_eth)
1061 skb_pull(skb, sizeof(struct ethhdr));
1062
1063 if (unlikely(ret)) {
1064 skb_mark_unbind(skb);
1065 return ret;
1066 }
1067
1068 tnl_params.tops_entry_proto = tnl_type->tops_entry;
developer84f378f2023-08-24 18:26:50 +08001069 tnl_params.cdrt = skb_hnat_cdrt(skb);
developere5e687d2023-08-08 16:05:33 +08001070
developer15ee46c2023-08-24 16:35:34 +08001071 ret = mtk_tops_tnl_offload(skb, tnl_type, &tnl_params);
developere5e687d2023-08-08 16:05:33 +08001072
1073 /*
1074 * whether success or fail to offload a decapsulation tunnel
1075 * skb_hnat_tops(skb) must be cleared to avoid mtk_tnl_decap_offload() get
1076 * called again
1077 */
1078 skb_hnat_tops(skb) = 0;
1079 skb_hnat_is_decap(skb) = 0;
1080
1081 return ret;
1082}
1083
developer84f378f2023-08-24 18:26:50 +08001084static int __mtk_tops_tnl_encap_offload(struct sk_buff *skb)
developere5e687d2023-08-08 16:05:33 +08001085{
1086 struct tops_tnl_params tnl_params;
1087 struct tops_tnl_type *tnl_type;
1088 int ret;
1089
developere5e687d2023-08-08 16:05:33 +08001090 tnl_type = skb_to_tnl_type(skb);
1091 if (IS_ERR(tnl_type))
1092 return PTR_ERR(tnl_type);
1093
1094 if (unlikely(!tnl_type->tnl_encap_param_setup))
1095 return -ENODEV;
1096
1097 memset(&tnl_params, 0, sizeof(struct tops_tnl_params));
1098
1099 ret = tnl_type->tnl_encap_param_setup(skb, &tnl_params);
1100 if (unlikely(ret))
1101 return ret;
1102 tnl_params.tops_entry_proto = tnl_type->tops_entry;
developer84f378f2023-08-24 18:26:50 +08001103 tnl_params.cdrt = skb_hnat_cdrt(skb);
developere5e687d2023-08-08 16:05:33 +08001104
developer15ee46c2023-08-24 16:35:34 +08001105 return mtk_tops_tnl_offload(skb, tnl_type, &tnl_params);
developere5e687d2023-08-08 16:05:33 +08001106}
1107
developer84f378f2023-08-24 18:26:50 +08001108static int mtk_tops_tnl_encap_offload(struct sk_buff *skb)
1109{
1110 if (unlikely(!mtk_tops_mcu_alive())) {
1111 skb_mark_unbind(skb);
1112 return -EAGAIN;
1113 }
1114
1115 if (!skb_hnat_is_encap(skb))
1116 return -EPERM;
1117
1118 if (unlikely(skb_hnat_cdrt(skb)))
1119 return mtk_tops_tnl_l2_update(skb);
1120
1121 return __mtk_tops_tnl_encap_offload(skb);
1122}
1123
developere5e687d2023-08-08 16:05:33 +08001124static struct net_device *mtk_tops_get_tnl_dev(int tnl_idx)
1125{
1126 if (tnl_idx < TOPS_CRSN_TNL_ID_START || tnl_idx > TOPS_CRSN_TNL_ID_END)
1127 return ERR_PTR(-EINVAL);
1128
1129 tnl_idx = tnl_idx - TOPS_CRSN_TNL_ID_START;
1130
1131 return tops_tnl.tnl_infos[tnl_idx].dev;
1132}
1133
1134static void mtk_tops_tnl_sync_dma_done(void *param)
1135{
1136 /* TODO: check tx status with dmaengine_tx_status()? */
1137 complete(&tops_tnl.dma_done);
1138}
1139
1140static void mtk_tops_tnl_sync_dma_start(void *param)
1141{
1142 dma_async_issue_pending(tops_tnl.dmachan);
1143
1144 wait_for_completion(&tops_tnl.dma_done);
1145}
1146
1147static void mtk_tops_tnl_sync_dma_unprepare(struct tops_tnl_info *tnl_info,
1148 dma_addr_t *addr)
1149{
1150 dma_unmap_single(tops_dev, *addr, sizeof(struct tops_tnl_params),
1151 DMA_TO_DEVICE);
1152
1153 dma_release_channel(tops_tnl.dmachan);
1154}
1155
1156static int mtk_tops_tnl_sync_dma_prepare(struct tops_tnl_info *tnl_info,
1157 dma_addr_t *addr)
1158{
1159 u32 tnl_addr = tops_tnl.tnl_base_addr;
1160 struct dma_async_tx_descriptor *desc;
1161 dma_cookie_t cookie;
1162 int ret;
1163
1164 if (!tnl_info)
1165 return -EPERM;
1166
1167 tnl_addr += tnl_info->tnl_idx * sizeof(struct tops_tnl_params);
1168
1169 tops_tnl.dmachan = dma_request_slave_channel(tops_dev, "tnl-sync");
1170 if (!tops_tnl.dmachan) {
1171 TOPS_ERR("request dma channel failed\n");
1172 return -ENODEV;
1173 }
1174
1175 *addr = dma_map_single(tops_dev,
1176 &tnl_info->tnl_params,
1177 sizeof(struct tops_tnl_params),
1178 DMA_TO_DEVICE);
1179 if (dma_mapping_error(tops_dev, *addr)) {
1180 ret = -ENOMEM;
1181 goto dma_release;
1182 }
1183
1184 desc = dmaengine_prep_dma_memcpy(tops_tnl.dmachan,
1185 (dma_addr_t)tnl_addr, *addr,
1186 sizeof(struct tops_tnl_params),
1187 0);
1188 if (!desc) {
1189 ret = -EBUSY;
1190 goto dma_unmap;
1191 }
1192
1193 desc->callback = mtk_tops_tnl_sync_dma_done;
1194
1195 cookie = dmaengine_submit(desc);
1196 ret = dma_submit_error(cookie);
1197 if (ret)
1198 goto dma_terminate;
1199
1200 reinit_completion(&tops_tnl.dma_done);
1201
1202 return ret;
1203
1204dma_terminate:
1205 dmaengine_terminate_all(tops_tnl.dmachan);
1206
1207dma_unmap:
1208 dma_unmap_single(tops_dev, *addr, sizeof(struct tops_tnl_params),
1209 DMA_TO_DEVICE);
1210
1211dma_release:
1212 dma_release_channel(tops_tnl.dmachan);
1213
1214 return ret;
1215}
1216
1217static int __mtk_tops_tnl_sync_param_delete(struct tops_tnl_info *tnl_info)
1218{
1219 struct mcu_ctrl_cmd mcmd;
1220 dma_addr_t addr;
1221 int ret;
1222
1223 mcmd.e = MCU_EVENT_TYPE_SYNC_TNL;
1224 mcmd.arg[0] = TUNNEL_CTRL_EVENT_DEL;
1225 mcmd.arg[1] = tnl_info->tnl_idx;
1226 mcmd.core_mask = CORE_TOPS_MASK;
1227
1228 ret = mtk_tops_mcu_stall(&mcmd, NULL, NULL);
1229 if (ret) {
1230 TOPS_ERR("tnl sync deletion notify mcu failed: %d\n", ret);
1231 return ret;
1232 }
1233
1234 /* there shouldn't be any other reference to tnl_info right now */
1235 memset(&tnl_info->cache, 0, sizeof(struct tops_tnl_params));
1236 memset(&tnl_info->tnl_params, 0, sizeof(struct tops_tnl_params));
1237
1238 ret = mtk_tops_tnl_sync_dma_prepare(tnl_info, &addr);
1239 if (ret) {
1240 TOPS_ERR("tnl sync deletion prepare dma request failed: %d\n", ret);
1241 return ret;
1242 }
1243
1244 mtk_tops_tnl_sync_dma_start(NULL);
1245
1246 mtk_tops_tnl_sync_dma_unprepare(tnl_info, &addr);
1247
1248 return ret;
1249}
1250
1251static int mtk_tops_tnl_sync_param_delete(struct tops_tnl_info *tnl_info)
1252{
developer84f378f2023-08-24 18:26:50 +08001253 struct tops_tnl_params tnl_params;
developere5e687d2023-08-08 16:05:33 +08001254 int ret;
1255
1256 ret = mtk_tops_tnl_info_dipfilter_tear_down(tnl_info);
1257 if (ret) {
1258 TOPS_ERR("tnl sync dipfitler tear down failed: %d\n",
1259 ret);
1260 return ret;
1261 }
1262
developer84f378f2023-08-24 18:26:50 +08001263 memcpy(&tnl_params, &tnl_info->tnl_params, sizeof(struct tops_tnl_params));
developere5e687d2023-08-08 16:05:33 +08001264 ret = __mtk_tops_tnl_sync_param_delete(tnl_info);
1265 if (ret) {
1266 TOPS_ERR("tnl sync deletion failed: %d\n", ret);
1267 return ret;
1268 }
1269
developer84f378f2023-08-24 18:26:50 +08001270 ret = mtk_tops_tnl_info_cls_tear_down(tnl_info, &tnl_params);
developer15ee46c2023-08-24 16:35:34 +08001271 if (ret) {
1272 TOPS_ERR("tnl sync cls tear down faild: %d\n",
1273 ret);
1274 return ret;
1275 }
1276
developere5e687d2023-08-08 16:05:33 +08001277 mtk_tops_tnl_info_free(tnl_info);
1278
1279 return ret;
1280}
1281
1282static int __mtk_tops_tnl_sync_param_update(struct tops_tnl_info *tnl_info,
1283 bool is_new_tnl)
1284{
1285 struct mcu_ctrl_cmd mcmd;
1286 dma_addr_t addr;
1287 int ret;
1288
1289 mcmd.e = MCU_EVENT_TYPE_SYNC_TNL;
1290 mcmd.arg[1] = tnl_info->tnl_idx;
1291 mcmd.core_mask = CORE_TOPS_MASK;
1292
1293 if (is_new_tnl)
1294 mcmd.arg[0] = TUNNEL_CTRL_EVENT_NEW;
1295 else
1296 mcmd.arg[0] = TUNNEL_CTRL_EVENT_DIP_UPDATE;
1297
1298 ret = mtk_tops_tnl_sync_dma_prepare(tnl_info, &addr);
1299 if (ret) {
1300 TOPS_ERR("tnl sync update prepare dma request failed: %d\n", ret);
1301 return ret;
1302 }
1303
1304 ret = mtk_tops_mcu_stall(&mcmd, mtk_tops_tnl_sync_dma_start, NULL);
1305 if (ret)
1306 TOPS_ERR("tnl sync update notify mcu failed: %d\n", ret);
1307
1308 mtk_tops_tnl_sync_dma_unprepare(tnl_info, &addr);
1309
1310 return ret;
1311}
1312
1313static int mtk_tops_tnl_sync_param_update(struct tops_tnl_info *tnl_info,
1314 bool setup_pce, bool is_new_tnl)
1315{
1316 int ret;
1317
developer15ee46c2023-08-24 16:35:34 +08001318 if (setup_pce) {
developer84f378f2023-08-24 18:26:50 +08001319 ret = mtk_tops_tnl_info_cls_setup(tnl_info, &tnl_info->tnl_params);
developer15ee46c2023-08-24 16:35:34 +08001320 if (ret) {
1321 TOPS_ERR("tnl cls setup failed: %d\n", ret);
1322 return ret;
1323 }
1324 }
1325
developere5e687d2023-08-08 16:05:33 +08001326 ret = __mtk_tops_tnl_sync_param_update(tnl_info, is_new_tnl);
1327 if (ret) {
1328 TOPS_ERR("tnl sync failed: %d\n", ret);
developer15ee46c2023-08-24 16:35:34 +08001329 goto cls_tear_down;
developere5e687d2023-08-08 16:05:33 +08001330 }
1331
1332 tnl_info_sta_updated(tnl_info);
1333
1334 if (setup_pce) {
1335 ret = mtk_tops_tnl_info_dipfilter_setup(tnl_info);
1336 if (ret) {
1337 TOPS_ERR("tnl dipfilter setup failed: %d\n", ret);
1338 /* TODO: should undo parameter sync */
1339 return ret;
1340 }
1341 }
1342
1343 return ret;
developer15ee46c2023-08-24 16:35:34 +08001344
1345cls_tear_down:
developer84f378f2023-08-24 18:26:50 +08001346 mtk_tops_tnl_info_cls_tear_down(tnl_info, &tnl_info->tnl_params);
developer15ee46c2023-08-24 16:35:34 +08001347
1348 return ret;
developere5e687d2023-08-08 16:05:33 +08001349}
1350
1351static inline int mtk_tops_tnl_sync_param_new(struct tops_tnl_info *tnl_info,
1352 bool setup_pce)
1353{
1354 return mtk_tops_tnl_sync_param_update(tnl_info, setup_pce, true);
1355}
1356
1357static void mtk_tops_tnl_sync_get_pending_queue(void)
1358{
1359 struct list_head *tmp = tops_tnl.tnl_sync_submit;
1360 unsigned long flag = 0;
1361
1362 spin_lock_irqsave(&tops_tnl.tnl_sync_lock, flag);
1363
1364 tops_tnl.tnl_sync_submit = tops_tnl.tnl_sync_pending;
1365 tops_tnl.tnl_sync_pending = tmp;
1366
1367 tops_tnl.has_tnl_to_sync = false;
1368
1369 spin_unlock_irqrestore(&tops_tnl.tnl_sync_lock, flag);
1370}
1371
1372static void mtk_tops_tnl_sync_queue_proc(void)
1373{
1374 struct tops_tnl_info *tnl_info;
1375 struct tops_tnl_info *tmp;
1376 unsigned long flag = 0;
1377 bool is_decap = false;
1378 u32 tnl_status = 0;
1379 int ret;
1380
1381 list_for_each_entry_safe(tnl_info,
1382 tmp,
1383 tops_tnl.tnl_sync_pending,
1384 sync_node) {
1385 spin_lock_irqsave(&tnl_info->lock, flag);
1386
1387 /* tnl update is on the fly, queue tnl to next round */
1388 if (tnl_info_sta_is_updating(tnl_info)) {
1389 list_del_init(&tnl_info->sync_node);
1390
1391 tnl_info_submit_no_tnl_lock(tnl_info);
1392
1393 goto next;
1394 }
1395
1396 /*
1397 * if tnl_info is not queued, something wrong
1398 * just remove that tnl_info from the queue
1399 * maybe trigger BUG_ON()?
1400 */
1401 if (!tnl_info_sta_is_queued(tnl_info)) {
1402 list_del_init(&tnl_info->sync_node);
1403 goto next;
1404 }
1405
1406 is_decap = (!(tnl_info->tnl_params.flag & TNL_DECAP_ENABLE)
1407 && tnl_info_decap_is_enable(tnl_info));
1408
1409 tnl_status = tnl_info->status;
1410 memcpy(&tnl_info->tnl_params, &tnl_info->cache,
1411 sizeof(struct tops_tnl_params));
1412
1413 list_del_init(&tnl_info->sync_node);
1414
1415 /*
1416 * mark tnl info to updating and release tnl info's spin lock
1417 * since it is going to use dma to transfer data
1418 * and might going to sleep
1419 */
1420 tnl_info_sta_updating_no_tnl_lock(tnl_info);
1421
1422 spin_unlock_irqrestore(&tnl_info->lock, flag);
1423
1424 if (tnl_status & TNL_STA_INIT)
1425 ret = mtk_tops_tnl_sync_param_new(tnl_info, is_decap);
1426 else if (tnl_status & TNL_STA_DELETING)
1427 ret = mtk_tops_tnl_sync_param_delete(tnl_info);
1428 else
1429 ret = mtk_tops_tnl_sync_param_update(tnl_info,
1430 is_decap,
1431 false);
1432
1433 if (ret)
1434 TOPS_ERR("sync tunnel parameter failed: %d\n", ret);
1435
1436 continue;
1437
1438next:
1439 spin_unlock_irqrestore(&tnl_info->lock, flag);
1440 }
1441}
1442
1443static int tnl_sync_task(void *data)
1444{
1445 while (1) {
1446 wait_event_interruptible(tops_tnl.tnl_sync_wait,
1447 (tops_tnl.has_tnl_to_sync && mtk_tops_mcu_alive())
1448 || kthread_should_stop());
1449
1450 if (kthread_should_stop())
1451 break;
1452
1453 mtk_tops_tnl_sync_get_pending_queue();
1454
1455 mtk_tops_tnl_sync_queue_proc();
1456 }
1457
1458 return 0;
1459}
1460
1461static void mtk_tops_tnl_info_flush_ppe(struct tops_tnl_info *tnl_info)
1462{
1463 struct foe_entry *entry;
1464 u32 max_entry;
1465 u32 ppe_id;
1466 u32 eidx;
1467
1468 /* tnl info's lock should be held */
1469 lockdep_assert_held(&tnl_info->lock);
1470
1471 /* clear all TOPS related PPE entries */
1472 for (ppe_id = 0; ppe_id < MAX_PPE_NUM; ppe_id++) {
1473 max_entry = mtk_tops_netsys_ppe_get_max_entry_num(ppe_id);
1474 for (eidx = 0; eidx < max_entry; eidx++) {
1475 entry = hnat_get_foe_entry(ppe_id, eidx);
1476 if (IS_ERR(entry))
1477 break;
1478
1479 if (!entry_hnat_is_bound(entry))
1480 continue;
1481
1482 tnl_flush_ppe_entry(entry, tnl_info->tnl_idx);
1483 }
1484 }
1485 hnat_cache_ebl(1);
1486 /* make sure all data is written to dram PPE table */
1487 wmb();
1488}
1489
1490void mtk_tops_tnl_offload_netdev_down(struct net_device *ndev)
1491{
1492 struct tops_tnl_info *tnl_info;
1493 unsigned long flag;
1494 u32 bkt;
1495
1496 spin_lock_irqsave(&tops_tnl.tbl_lock, flag);
1497
1498 hash_for_each(tops_tnl.ht, bkt, tnl_info, hlist) {
1499 spin_lock(&tnl_info->lock);
1500
1501 if (tnl_info->dev == ndev) {
1502 mtk_tops_tnl_info_flush_ppe(tnl_info);
1503
1504 __mtk_tops_tnl_offload_disable(tnl_info);
1505
1506 spin_unlock(&tnl_info->lock);
1507
1508 break;
1509 }
1510
1511 spin_unlock(&tnl_info->lock);
1512 }
1513
1514 spin_unlock_irqrestore(&tops_tnl.tbl_lock, flag);
1515}
1516
1517void mtk_tops_tnl_offload_flush(void)
1518{
1519 struct tops_tnl_info *tnl_info;
1520 struct foe_entry *entry;
1521 unsigned long flag;
1522 u32 max_entry;
1523 u32 ppe_id;
1524 u32 eidx;
1525 u32 bkt;
1526
1527 /* clear all TOPS related PPE entries */
1528 for (ppe_id = 0; ppe_id < MAX_PPE_NUM; ppe_id++) {
1529 max_entry = mtk_tops_netsys_ppe_get_max_entry_num(ppe_id);
1530 for (eidx = 0; eidx < max_entry; eidx++) {
1531 entry = hnat_get_foe_entry(ppe_id, eidx);
1532 if (IS_ERR(entry))
1533 break;
1534
1535 if (!entry_hnat_is_bound(entry))
1536 continue;
1537
1538 tnl_flush_ppe_entry(entry, __TOPS_ENTRY_MAX);
1539 }
1540 }
1541 hnat_cache_ebl(1);
1542 /* make sure all data is written to dram PPE table */
1543 wmb();
1544
1545 spin_lock_irqsave(&tops_tnl.tbl_lock, flag);
1546
1547 hash_for_each(tops_tnl.ht, bkt, tnl_info, hlist) {
1548 /* clear all tunnel's synced parameters, but preserve cache */
1549 memset(&tnl_info->tnl_params, 0, sizeof(struct tops_tnl_params));
1550 /*
1551 * make tnl_info status to TNL_INIT state
1552 * so that it can be added to TOPS again
1553 */
1554 spin_lock(&tnl_info->lock);
1555
1556 tnl_info_sta_init_no_tnl_lock(tnl_info);
1557 list_del_init(&tnl_info->sync_node);
1558
1559 spin_unlock(&tnl_info->lock);
1560 }
1561
1562 spin_unlock_irqrestore(&tops_tnl.tbl_lock, flag);
1563}
1564
1565void mtk_tops_tnl_offload_recover(void)
1566{
1567 struct tops_tnl_info *tnl_info;
1568 unsigned long flag;
1569 u32 bkt;
1570
1571 spin_lock_irqsave(&tops_tnl.tbl_lock, flag);
1572
1573 hash_for_each(tops_tnl.ht, bkt, tnl_info, hlist)
1574 mtk_tops_tnl_info_submit(tnl_info);
1575
1576 spin_unlock_irqrestore(&tops_tnl.tbl_lock, flag);
1577}
1578
1579int mtk_tops_tnl_offload_init(struct platform_device *pdev)
1580{
1581 struct tops_tnl_info *tnl_info;
1582 int ret = 0;
1583 int i = 0;
1584
1585 hash_init(tops_tnl.ht);
1586
1587 tops_tnl.tnl_infos = devm_kzalloc(&pdev->dev,
1588 sizeof(struct tops_tnl_info) * CONFIG_TOPS_TNL_NUM,
1589 GFP_KERNEL);
1590 if (!tops_tnl.tnl_infos)
1591 return -ENOMEM;
1592
1593 for (i = 0; i < CONFIG_TOPS_TNL_NUM; i++) {
1594 tnl_info = &tops_tnl.tnl_infos[i];
1595 tnl_info->tnl_idx = i;
1596 tnl_info->status = TNL_STA_UNINIT;
1597 INIT_HLIST_NODE(&tnl_info->hlist);
1598 INIT_LIST_HEAD(&tnl_info->sync_node);
1599 spin_lock_init(&tnl_info->lock);
1600 }
1601
1602 ret = register_mbox_dev(MBOX_RECV, &tnl_offload_mbox_recv);
1603 if (ret) {
1604 TOPS_ERR("tnl offload recv dev register failed: %d\n",
1605 ret);
1606 return ret;
1607 }
1608
1609 init_completion(&tops_tnl.dma_done);
1610 init_waitqueue_head(&tops_tnl.tnl_sync_wait);
1611
1612 tops_tnl.tnl_sync_thread = kthread_run(tnl_sync_task, NULL,
1613 "tnl sync param task");
1614 if (IS_ERR(tops_tnl.tnl_sync_thread)) {
1615 TOPS_ERR("tnl sync thread create failed\n");
1616 ret = -ENOMEM;
1617 goto unregister_mbox;
1618 }
1619
1620 mtk_tnl_encap_offload = mtk_tops_tnl_encap_offload;
1621 mtk_tnl_decap_offload = mtk_tops_tnl_decap_offload;
1622 mtk_tnl_decap_offloadable = mtk_tops_tnl_decap_offloadable;
1623 mtk_get_tnl_dev = mtk_tops_get_tnl_dev;
1624
1625 tops_tnl.tnl_sync_submit = &tnl_sync_q1;
1626 tops_tnl.tnl_sync_pending = &tnl_sync_q2;
1627 spin_lock_init(&tops_tnl.tnl_sync_lock);
1628 spin_lock_init(&tops_tnl.tbl_lock);
1629
1630 return 0;
1631
1632unregister_mbox:
1633 unregister_mbox_dev(MBOX_RECV, &tnl_offload_mbox_recv);
1634
1635 return ret;
1636}
1637
1638void mtk_tops_tnl_offload_pce_clean_up(void)
1639{
1640 struct tops_tnl_info *tnl_info;
1641 unsigned long flag;
1642 u32 bkt;
1643
1644 spin_lock_irqsave(&tops_tnl.tbl_lock, flag);
1645
1646 hash_for_each(tops_tnl.ht, bkt, tnl_info, hlist) {
1647 mtk_tops_tnl_info_flush_ppe(tnl_info);
1648
1649 mtk_tops_tnl_info_dipfilter_tear_down(tnl_info);
developer15ee46c2023-08-24 16:35:34 +08001650
developer84f378f2023-08-24 18:26:50 +08001651 mtk_tops_tnl_info_cls_tear_down(tnl_info, &tnl_info->tnl_params);
developere5e687d2023-08-08 16:05:33 +08001652 }
1653
1654 spin_unlock_irqrestore(&tops_tnl.tbl_lock, flag);
1655}
1656
1657void mtk_tops_tnl_offload_deinit(struct platform_device *pdev)
1658{
1659 mtk_tnl_encap_offload = NULL;
1660 mtk_tnl_decap_offload = NULL;
1661 mtk_tnl_decap_offloadable = NULL;
1662 mtk_get_tnl_dev = NULL;
1663
1664 kthread_stop(tops_tnl.tnl_sync_thread);
1665
1666 mtk_tops_tnl_offload_pce_clean_up();
1667
1668 unregister_mbox_dev(MBOX_RECV, &tnl_offload_mbox_recv);
1669}
1670
1671int mtk_tops_tnl_offload_proto_setup(struct platform_device *pdev)
1672{
1673 mtk_tops_gretap_init();
1674
1675 mtk_tops_udp_l2tp_data_init();
1676
1677 return 0;
1678}
1679
1680void mtk_tops_tnl_offload_proto_teardown(struct platform_device *pdev)
1681{
1682 mtk_tops_gretap_deinit();
1683
1684 mtk_tops_udp_l2tp_data_deinit();
1685}
1686
1687struct tops_tnl_type *mtk_tops_tnl_type_get_by_name(const char *name)
1688{
1689 enum tops_entry_type tops_entry = TOPS_ENTRY_NONE + 1;
1690 struct tops_tnl_type *tnl_type;
1691
1692 if (unlikely(!name))
1693 return ERR_PTR(-EPERM);
1694
1695 for (; tops_entry < __TOPS_ENTRY_MAX; tops_entry++) {
1696 tnl_type = tops_tnl.offload_tnl_types[tops_entry];
1697 if (tnl_type && !strcmp(name, tnl_type->type_name))
1698 break;
1699 }
1700
1701 return tnl_type;
1702}
1703
1704int mtk_tops_tnl_type_register(struct tops_tnl_type *tnl_type)
1705{
1706 enum tops_entry_type tops_entry = tnl_type->tops_entry;
1707
1708 if (unlikely(tops_entry == TOPS_ENTRY_NONE
1709 || tops_entry >= __TOPS_ENTRY_MAX)) {
1710 TOPS_ERR("invalid tops_entry: %u\n", tops_entry);
1711 return -EINVAL;
1712 }
1713
1714 if (unlikely(!tnl_type))
1715 return -EINVAL;
1716
1717 if (tops_tnl.offload_tnl_types[tops_entry]) {
1718 TOPS_ERR("offload tnl type is already registered: %u\n", tops_entry);
1719 return -EBUSY;
1720 }
1721
developer15ee46c2023-08-24 16:35:34 +08001722 INIT_LIST_HEAD(&tnl_type->tcls_head);
developere5e687d2023-08-08 16:05:33 +08001723 tops_tnl.offload_tnl_types[tops_entry] = tnl_type;
1724 tops_tnl.offload_tnl_type_num++;
1725
1726 return 0;
1727}
1728
1729void mtk_tops_tnl_type_unregister(struct tops_tnl_type *tnl_type)
1730{
1731 enum tops_entry_type tops_entry = tnl_type->tops_entry;
1732
1733 if (unlikely(tops_entry == TOPS_ENTRY_NONE
1734 || tops_entry >= __TOPS_ENTRY_MAX)) {
1735 TOPS_ERR("invalid tops_entry: %u\n", tops_entry);
1736 return;
1737 }
1738
1739 if (unlikely(!tnl_type))
1740 return;
1741
1742 if (tops_tnl.offload_tnl_types[tops_entry] != tnl_type) {
1743 TOPS_ERR("offload tnl type is registered by others\n");
1744 return;
1745 }
1746
1747 tops_tnl.offload_tnl_types[tops_entry] = NULL;
1748 tops_tnl.offload_tnl_type_num--;
1749}