blob: 427bc4da4c25bc329385f76427be2d381de88091 [file] [log] [blame]
developer1966afb2023-08-08 16:02:18 +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
developer5cca2e42023-08-24 17:39:15 +08008#include <linux/bitmap.h>
9#include <linux/bitops.h>
developer1966afb2023-08-08 16:02:18 +080010#include <linux/err.h>
11#include <linux/lockdep.h>
12#include <linux/spinlock.h>
13
14#include "pce/cls.h"
15#include "pce/internal.h"
16#include "pce/netsys.h"
17
developer965ff0c2024-07-26 13:39:37 +080018static RAW_NOTIFIER_HEAD(cls_notif_chain);
19
20int mtk_pce_register_cls_notifier(struct notifier_block *nb)
21{
22 int ret;
23
24 ret = raw_notifier_chain_register(&cls_notif_chain, nb);
25
26 return ret;
27}
28EXPORT_SYMBOL(mtk_pce_register_cls_notifier);
29
30int mtk_pce_unregister_cls_notifier(struct notifier_block *nb)
31{
32 int ret;
33
34 ret = raw_notifier_chain_unregister(&cls_notif_chain, nb);
35
36 return ret;
37}
38EXPORT_SYMBOL(mtk_pce_unregister_cls_notifier);
39
developer1966afb2023-08-08 16:02:18 +080040struct cls_hw {
developer5cca2e42023-08-24 17:39:15 +080041 struct cls_entry cls_tbl[FE_MEM_CLS_MAX_INDEX];
42 DECLARE_BITMAP(cls_used, FE_MEM_CLS_MAX_INDEX);
developer1966afb2023-08-08 16:02:18 +080043 spinlock_t lock;
44};
45
46struct cls_hw cls_hw;
47
48int mtk_pce_cls_enable(void)
49{
50 mtk_pce_netsys_setbits(GLO_MEM_CFG, GDM_CLS_EN);
51
52 return 0;
53}
54
55void mtk_pce_cls_disable(void)
56{
57 mtk_pce_netsys_clrbits(GLO_MEM_CFG, GDM_CLS_EN);
58}
59
60static void mtk_pce_cls_clean_up(void)
61{
62 struct fe_mem_msg msg = {
63 .cmd = FE_MEM_CMD_WRITE,
64 .type = FE_MEM_TYPE_CLS,
65 };
66 unsigned long flag;
67 int ret = 0;
68 u32 i = 0;
69
70 memset(&msg.raw, 0, sizeof(msg.raw));
71
72 spin_lock_irqsave(&cls_hw.lock, flag);
73
74 /* clean up cls table */
75 for (i = 0; i < FE_MEM_CLS_MAX_INDEX; i++) {
76 msg.index = i;
77 ret = mtk_pce_fe_mem_msg_send(&msg);
78 if (ret)
79 goto unlock;
80 }
81
82unlock:
83 spin_unlock_irqrestore(&cls_hw.lock, flag);
84}
85
86int mtk_pce_cls_init(struct platform_device *pdev)
87{
developer5cca2e42023-08-24 17:39:15 +080088 u32 i;
89
developer1966afb2023-08-08 16:02:18 +080090 spin_lock_init(&cls_hw.lock);
91
92 mtk_pce_cls_clean_up();
93
developer5cca2e42023-08-24 17:39:15 +080094 for (i = 0; i < FE_MEM_CLS_MAX_INDEX; i++)
95 cls_hw.cls_tbl[i].idx = i + 1;
96
developer1966afb2023-08-08 16:02:18 +080097 return 0;
98}
99
100void mtk_pce_cls_deinit(struct platform_device *pdev)
101{
102 mtk_pce_cls_clean_up();
103}
104
developer5cca2e42023-08-24 17:39:15 +0800105int mtk_pce_cls_desc_read(struct cls_desc *cdesc, u32 idx)
developer1966afb2023-08-08 16:02:18 +0800106{
107 struct fe_mem_msg msg;
108 int ret;
109
developer5cca2e42023-08-24 17:39:15 +0800110 if (unlikely(!cdesc || !idx || idx >= FE_MEM_CLS_MAX_INDEX))
111 return -EINVAL;
developer1966afb2023-08-08 16:02:18 +0800112
developer5cca2e42023-08-24 17:39:15 +0800113 mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_READ, FE_MEM_TYPE_CLS, idx);
developer1966afb2023-08-08 16:02:18 +0800114
115 memset(&msg.raw, 0, sizeof(msg.raw));
116
117 ret = mtk_pce_fe_mem_msg_send(&msg);
118 if (ret)
119 return ret;
120
121 memcpy(cdesc, &msg.cdesc, sizeof(struct cls_desc));
122
123 return ret;
124}
125
developer5cca2e42023-08-24 17:39:15 +0800126int mtk_pce_cls_desc_write(struct cls_desc *cdesc, u32 idx)
developer1966afb2023-08-08 16:02:18 +0800127{
128 struct fe_mem_msg msg;
129
developer5cca2e42023-08-24 17:39:15 +0800130 if (unlikely(!cdesc || !idx || idx >= FE_MEM_CLS_MAX_INDEX))
131 return -EINVAL;
developer1966afb2023-08-08 16:02:18 +0800132
developer5cca2e42023-08-24 17:39:15 +0800133 mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_WRITE, FE_MEM_TYPE_CLS, idx);
developer1966afb2023-08-08 16:02:18 +0800134
135 memset(&msg.raw, 0, sizeof(msg.raw));
136 memcpy(&msg.cdesc, cdesc, sizeof(struct cls_desc));
137
138 return mtk_pce_fe_mem_msg_send(&msg);
139}
140
developer5cca2e42023-08-24 17:39:15 +0800141int mtk_pce_cls_entry_write(struct cls_entry *cls)
developer1966afb2023-08-08 16:02:18 +0800142{
developer5cca2e42023-08-24 17:39:15 +0800143 if (unlikely(!cls))
developer1966afb2023-08-08 16:02:18 +0800144 return -EINVAL;
145
developer5cca2e42023-08-24 17:39:15 +0800146 return mtk_pce_cls_desc_write(&cls->cdesc, cls->idx);
developer1966afb2023-08-08 16:02:18 +0800147}
developer5cca2e42023-08-24 17:39:15 +0800148EXPORT_SYMBOL(mtk_pce_cls_entry_write);
developer1966afb2023-08-08 16:02:18 +0800149
developer5cca2e42023-08-24 17:39:15 +0800150struct cls_entry *mtk_pce_cls_entry_alloc(void)
developer1966afb2023-08-08 16:02:18 +0800151{
developer5cca2e42023-08-24 17:39:15 +0800152 struct cls_entry *cls;
developer1966afb2023-08-08 16:02:18 +0800153 unsigned long flag;
developer5cca2e42023-08-24 17:39:15 +0800154 u32 idx;
developer1966afb2023-08-08 16:02:18 +0800155
156 spin_lock_irqsave(&cls_hw.lock, flag);
157
developer5cca2e42023-08-24 17:39:15 +0800158 idx = find_first_zero_bit(cls_hw.cls_used, FE_MEM_CLS_MAX_INDEX);
159 if (idx == FE_MEM_CLS_MAX_INDEX) {
160 cls = ERR_PTR(-ENOMEM);
developer1966afb2023-08-08 16:02:18 +0800161 goto unlock;
162 }
163
developer5cca2e42023-08-24 17:39:15 +0800164 set_bit(idx, cls_hw.cls_used);
developer1966afb2023-08-08 16:02:18 +0800165
developer5cca2e42023-08-24 17:39:15 +0800166 cls = &cls_hw.cls_tbl[idx];
167
168 memset(&cls->cdesc, 0, sizeof(cls->cdesc));
developer1966afb2023-08-08 16:02:18 +0800169
170unlock:
171 spin_unlock_irqrestore(&cls_hw.lock, flag);
172
developer5cca2e42023-08-24 17:39:15 +0800173 return cls;
developer1966afb2023-08-08 16:02:18 +0800174}
developer5cca2e42023-08-24 17:39:15 +0800175EXPORT_SYMBOL(mtk_pce_cls_entry_alloc);
developer1966afb2023-08-08 16:02:18 +0800176
developer5cca2e42023-08-24 17:39:15 +0800177void mtk_pce_cls_entry_free(struct cls_entry *cls)
developer1966afb2023-08-08 16:02:18 +0800178{
developer1966afb2023-08-08 16:02:18 +0800179 unsigned long flag;
developer1966afb2023-08-08 16:02:18 +0800180
developer5cca2e42023-08-24 17:39:15 +0800181 if (!cls)
developer1966afb2023-08-08 16:02:18 +0800182 return;
183
developer965ff0c2024-07-26 13:39:37 +0800184 raw_notifier_call_chain(&cls_notif_chain, CLS_NOTIFY_DELETE_ENTRY, cls);
185
developer1966afb2023-08-08 16:02:18 +0800186 spin_lock_irqsave(&cls_hw.lock, flag);
developer5cca2e42023-08-24 17:39:15 +0800187 clear_bit(cls->idx - 1, cls_hw.cls_used);
developer1966afb2023-08-08 16:02:18 +0800188 spin_unlock_irqrestore(&cls_hw.lock, flag);
189}
developer5cca2e42023-08-24 17:39:15 +0800190EXPORT_SYMBOL(mtk_pce_cls_entry_free);