blob: 427bc4da4c25bc329385f76427be2d381de88091 [file] [log] [blame]
developerf2f1b882023-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
developera4177cd2023-08-24 17:39:15 +08008#include <linux/bitmap.h>
9#include <linux/bitops.h>
developerf2f1b882023-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
developer732266e2024-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
developerf2f1b882023-08-08 16:02:18 +080040struct cls_hw {
developera4177cd2023-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);
developerf2f1b882023-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{
developera4177cd2023-08-24 17:39:15 +080088 u32 i;
89
developerf2f1b882023-08-08 16:02:18 +080090 spin_lock_init(&cls_hw.lock);
91
92 mtk_pce_cls_clean_up();
93
developera4177cd2023-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
developerf2f1b882023-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
developera4177cd2023-08-24 17:39:15 +0800105int mtk_pce_cls_desc_read(struct cls_desc *cdesc, u32 idx)
developerf2f1b882023-08-08 16:02:18 +0800106{
107 struct fe_mem_msg msg;
108 int ret;
109
developera4177cd2023-08-24 17:39:15 +0800110 if (unlikely(!cdesc || !idx || idx >= FE_MEM_CLS_MAX_INDEX))
111 return -EINVAL;
developerf2f1b882023-08-08 16:02:18 +0800112
developera4177cd2023-08-24 17:39:15 +0800113 mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_READ, FE_MEM_TYPE_CLS, idx);
developerf2f1b882023-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
developera4177cd2023-08-24 17:39:15 +0800126int mtk_pce_cls_desc_write(struct cls_desc *cdesc, u32 idx)
developerf2f1b882023-08-08 16:02:18 +0800127{
128 struct fe_mem_msg msg;
129
developera4177cd2023-08-24 17:39:15 +0800130 if (unlikely(!cdesc || !idx || idx >= FE_MEM_CLS_MAX_INDEX))
131 return -EINVAL;
developerf2f1b882023-08-08 16:02:18 +0800132
developera4177cd2023-08-24 17:39:15 +0800133 mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_WRITE, FE_MEM_TYPE_CLS, idx);
developerf2f1b882023-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
developera4177cd2023-08-24 17:39:15 +0800141int mtk_pce_cls_entry_write(struct cls_entry *cls)
developerf2f1b882023-08-08 16:02:18 +0800142{
developera4177cd2023-08-24 17:39:15 +0800143 if (unlikely(!cls))
developerf2f1b882023-08-08 16:02:18 +0800144 return -EINVAL;
145
developera4177cd2023-08-24 17:39:15 +0800146 return mtk_pce_cls_desc_write(&cls->cdesc, cls->idx);
developerf2f1b882023-08-08 16:02:18 +0800147}
developera4177cd2023-08-24 17:39:15 +0800148EXPORT_SYMBOL(mtk_pce_cls_entry_write);
developerf2f1b882023-08-08 16:02:18 +0800149
developera4177cd2023-08-24 17:39:15 +0800150struct cls_entry *mtk_pce_cls_entry_alloc(void)
developerf2f1b882023-08-08 16:02:18 +0800151{
developera4177cd2023-08-24 17:39:15 +0800152 struct cls_entry *cls;
developerf2f1b882023-08-08 16:02:18 +0800153 unsigned long flag;
developera4177cd2023-08-24 17:39:15 +0800154 u32 idx;
developerf2f1b882023-08-08 16:02:18 +0800155
156 spin_lock_irqsave(&cls_hw.lock, flag);
157
developera4177cd2023-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);
developerf2f1b882023-08-08 16:02:18 +0800161 goto unlock;
162 }
163
developera4177cd2023-08-24 17:39:15 +0800164 set_bit(idx, cls_hw.cls_used);
developerf2f1b882023-08-08 16:02:18 +0800165
developera4177cd2023-08-24 17:39:15 +0800166 cls = &cls_hw.cls_tbl[idx];
167
168 memset(&cls->cdesc, 0, sizeof(cls->cdesc));
developerf2f1b882023-08-08 16:02:18 +0800169
170unlock:
171 spin_unlock_irqrestore(&cls_hw.lock, flag);
172
developera4177cd2023-08-24 17:39:15 +0800173 return cls;
developerf2f1b882023-08-08 16:02:18 +0800174}
developera4177cd2023-08-24 17:39:15 +0800175EXPORT_SYMBOL(mtk_pce_cls_entry_alloc);
developerf2f1b882023-08-08 16:02:18 +0800176
developera4177cd2023-08-24 17:39:15 +0800177void mtk_pce_cls_entry_free(struct cls_entry *cls)
developerf2f1b882023-08-08 16:02:18 +0800178{
developerf2f1b882023-08-08 16:02:18 +0800179 unsigned long flag;
developerf2f1b882023-08-08 16:02:18 +0800180
developera4177cd2023-08-24 17:39:15 +0800181 if (!cls)
developerf2f1b882023-08-08 16:02:18 +0800182 return;
183
developer732266e2024-07-26 13:39:37 +0800184 raw_notifier_call_chain(&cls_notif_chain, CLS_NOTIFY_DELETE_ENTRY, cls);
185
developerf2f1b882023-08-08 16:02:18 +0800186 spin_lock_irqsave(&cls_hw.lock, flag);
developera4177cd2023-08-24 17:39:15 +0800187 clear_bit(cls->idx - 1, cls_hw.cls_used);
developerf2f1b882023-08-08 16:02:18 +0800188 spin_unlock_irqrestore(&cls_hw.lock, flag);
189}
developera4177cd2023-08-24 17:39:15 +0800190EXPORT_SYMBOL(mtk_pce_cls_entry_free);