1 | /* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */ |
2 | /* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */ |
3 | |
4 | #ifndef _MLXSW_SPECTRUM_ACL_TCAM_H |
5 | #define _MLXSW_SPECTRUM_ACL_TCAM_H |
6 | |
7 | #include <linux/list.h> |
8 | #include <linux/parman.h> |
9 | |
10 | #include "reg.h" |
11 | #include "spectrum.h" |
12 | #include "core_acl_flex_keys.h" |
13 | |
14 | struct mlxsw_sp_acl_tcam { |
15 | unsigned long *used_regions; /* bit array */ |
16 | unsigned int max_regions; |
17 | unsigned long *used_groups; /* bit array */ |
18 | unsigned int max_groups; |
19 | unsigned int max_group_size; |
20 | struct mutex lock; /* guards vregion list */ |
21 | struct list_head vregion_list; |
22 | u32 vregion_rehash_intrvl; /* ms */ |
23 | unsigned long priv[]; |
24 | /* priv has to be always the last item */ |
25 | }; |
26 | |
27 | size_t mlxsw_sp_acl_tcam_priv_size(struct mlxsw_sp *mlxsw_sp); |
28 | int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp, |
29 | struct mlxsw_sp_acl_tcam *tcam); |
30 | void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp, |
31 | struct mlxsw_sp_acl_tcam *tcam); |
32 | int mlxsw_sp_acl_tcam_priority_get(struct mlxsw_sp *mlxsw_sp, |
33 | struct mlxsw_sp_acl_rule_info *rulei, |
34 | u32 *priority, bool fillup_priority); |
35 | |
36 | struct mlxsw_sp_acl_profile_ops { |
37 | size_t ruleset_priv_size; |
38 | int (*ruleset_add)(struct mlxsw_sp *mlxsw_sp, |
39 | struct mlxsw_sp_acl_tcam *tcam, void *ruleset_priv, |
40 | struct mlxsw_afk_element_usage *tmplt_elusage, |
41 | unsigned int *p_min_prio, unsigned int *p_max_prio); |
42 | void (*ruleset_del)(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv); |
43 | int (*ruleset_bind)(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv, |
44 | struct mlxsw_sp_port *mlxsw_sp_port, |
45 | bool ingress); |
46 | void (*ruleset_unbind)(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv, |
47 | struct mlxsw_sp_port *mlxsw_sp_port, |
48 | bool ingress); |
49 | u16 (*ruleset_group_id)(void *ruleset_priv); |
50 | size_t rule_priv_size; |
51 | int (*rule_add)(struct mlxsw_sp *mlxsw_sp, |
52 | void *ruleset_priv, void *rule_priv, |
53 | struct mlxsw_sp_acl_rule_info *rulei); |
54 | void (*rule_del)(struct mlxsw_sp *mlxsw_sp, void *rule_priv); |
55 | int (*rule_action_replace)(struct mlxsw_sp *mlxsw_sp, void *rule_priv, |
56 | struct mlxsw_sp_acl_rule_info *rulei); |
57 | int (*rule_activity_get)(struct mlxsw_sp *mlxsw_sp, void *rule_priv, |
58 | bool *activity); |
59 | }; |
60 | |
61 | const struct mlxsw_sp_acl_profile_ops * |
62 | mlxsw_sp_acl_tcam_profile_ops(struct mlxsw_sp *mlxsw_sp, |
63 | enum mlxsw_sp_acl_profile profile); |
64 | |
65 | #define MLXSW_SP_ACL_TCAM_REGION_BASE_COUNT 16 |
66 | #define MLXSW_SP_ACL_TCAM_REGION_RESIZE_STEP 16 |
67 | |
68 | #define MLXSW_SP_ACL_TCAM_CATCHALL_PRIO (~0U) |
69 | |
70 | #define MLXSW_SP_ACL_TCAM_MASK_LEN \ |
71 | (MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN * BITS_PER_BYTE) |
72 | |
73 | struct mlxsw_sp_acl_tcam_group; |
74 | struct mlxsw_sp_acl_tcam_vregion; |
75 | |
76 | struct mlxsw_sp_acl_tcam_region { |
77 | struct mlxsw_sp_acl_tcam_vregion *vregion; |
78 | struct mlxsw_sp_acl_tcam_group *group; |
79 | struct list_head list; /* Member of a TCAM group */ |
80 | enum mlxsw_reg_ptar_key_type key_type; |
81 | u16 id; /* ACL ID and region ID - they are same */ |
82 | char tcam_region_info[MLXSW_REG_PXXX_TCAM_REGION_INFO_LEN]; |
83 | struct mlxsw_afk_key_info *key_info; |
84 | struct mlxsw_sp *mlxsw_sp; |
85 | unsigned long priv[]; |
86 | /* priv has to be always the last item */ |
87 | }; |
88 | |
89 | struct mlxsw_sp_acl_ctcam_region { |
90 | struct parman *parman; |
91 | const struct mlxsw_sp_acl_ctcam_region_ops *ops; |
92 | struct mlxsw_sp_acl_tcam_region *region; |
93 | }; |
94 | |
95 | struct mlxsw_sp_acl_ctcam_chunk { |
96 | struct parman_prio parman_prio; |
97 | }; |
98 | |
99 | struct mlxsw_sp_acl_ctcam_entry { |
100 | struct parman_item parman_item; |
101 | }; |
102 | |
103 | struct mlxsw_sp_acl_ctcam_region_ops { |
104 | int (*entry_insert)(struct mlxsw_sp_acl_ctcam_region *cregion, |
105 | struct mlxsw_sp_acl_ctcam_entry *centry, |
106 | const char *mask); |
107 | void (*entry_remove)(struct mlxsw_sp_acl_ctcam_region *cregion, |
108 | struct mlxsw_sp_acl_ctcam_entry *centry); |
109 | }; |
110 | |
111 | int |
112 | mlxsw_sp_acl_ctcam_region_init(struct mlxsw_sp *mlxsw_sp, |
113 | struct mlxsw_sp_acl_ctcam_region *cregion, |
114 | struct mlxsw_sp_acl_tcam_region *region, |
115 | const struct mlxsw_sp_acl_ctcam_region_ops *ops); |
116 | void mlxsw_sp_acl_ctcam_region_fini(struct mlxsw_sp_acl_ctcam_region *cregion); |
117 | void mlxsw_sp_acl_ctcam_chunk_init(struct mlxsw_sp_acl_ctcam_region *cregion, |
118 | struct mlxsw_sp_acl_ctcam_chunk *cchunk, |
119 | unsigned int priority); |
120 | void mlxsw_sp_acl_ctcam_chunk_fini(struct mlxsw_sp_acl_ctcam_chunk *cchunk); |
121 | int mlxsw_sp_acl_ctcam_entry_add(struct mlxsw_sp *mlxsw_sp, |
122 | struct mlxsw_sp_acl_ctcam_region *cregion, |
123 | struct mlxsw_sp_acl_ctcam_chunk *cchunk, |
124 | struct mlxsw_sp_acl_ctcam_entry *centry, |
125 | struct mlxsw_sp_acl_rule_info *rulei, |
126 | bool fillup_priority); |
127 | void mlxsw_sp_acl_ctcam_entry_del(struct mlxsw_sp *mlxsw_sp, |
128 | struct mlxsw_sp_acl_ctcam_region *cregion, |
129 | struct mlxsw_sp_acl_ctcam_chunk *cchunk, |
130 | struct mlxsw_sp_acl_ctcam_entry *centry); |
131 | int mlxsw_sp_acl_ctcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp, |
132 | struct mlxsw_sp_acl_ctcam_region *cregion, |
133 | struct mlxsw_sp_acl_ctcam_entry *centry, |
134 | struct mlxsw_sp_acl_rule_info *rulei); |
135 | static inline unsigned int |
136 | mlxsw_sp_acl_ctcam_entry_offset(struct mlxsw_sp_acl_ctcam_entry *centry) |
137 | { |
138 | return centry->parman_item.index; |
139 | } |
140 | |
141 | enum mlxsw_sp_acl_atcam_region_type { |
142 | MLXSW_SP_ACL_ATCAM_REGION_TYPE_2KB, |
143 | MLXSW_SP_ACL_ATCAM_REGION_TYPE_4KB, |
144 | MLXSW_SP_ACL_ATCAM_REGION_TYPE_8KB, |
145 | MLXSW_SP_ACL_ATCAM_REGION_TYPE_12KB, |
146 | __MLXSW_SP_ACL_ATCAM_REGION_TYPE_MAX, |
147 | }; |
148 | |
149 | #define MLXSW_SP_ACL_ATCAM_REGION_TYPE_MAX \ |
150 | (__MLXSW_SP_ACL_ATCAM_REGION_TYPE_MAX - 1) |
151 | |
152 | struct mlxsw_sp_acl_atcam { |
153 | struct mlxsw_sp_acl_erp_core *erp_core; |
154 | }; |
155 | |
156 | struct mlxsw_sp_acl_atcam_region { |
157 | struct rhashtable entries_ht; /* A-TCAM only */ |
158 | struct list_head entries_list; /* A-TCAM only */ |
159 | struct mlxsw_sp_acl_ctcam_region cregion; |
160 | const struct mlxsw_sp_acl_atcam_region_ops *ops; |
161 | struct mlxsw_sp_acl_tcam_region *region; |
162 | struct mlxsw_sp_acl_atcam *atcam; |
163 | enum mlxsw_sp_acl_atcam_region_type type; |
164 | struct mlxsw_sp_acl_erp_table *erp_table; |
165 | void *priv; |
166 | }; |
167 | |
168 | struct mlxsw_sp_acl_atcam_entry_ht_key { |
169 | char full_enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded |
170 | * key. |
171 | */ |
172 | u8 erp_id; |
173 | }; |
174 | |
175 | struct mlxsw_sp_acl_atcam_chunk { |
176 | struct mlxsw_sp_acl_ctcam_chunk cchunk; |
177 | }; |
178 | |
179 | struct mlxsw_sp_acl_atcam_entry { |
180 | struct rhash_head ht_node; |
181 | struct list_head list; /* Member in entries_list */ |
182 | struct mlxsw_sp_acl_atcam_entry_ht_key ht_key; |
183 | char enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded key, |
184 | * minus delta bits. |
185 | */ |
186 | struct { |
187 | u16 start; |
188 | u8 mask; |
189 | u8 value; |
190 | } delta_info; |
191 | struct mlxsw_sp_acl_ctcam_entry centry; |
192 | struct mlxsw_sp_acl_atcam_lkey_id *lkey_id; |
193 | struct mlxsw_sp_acl_erp_mask *erp_mask; |
194 | }; |
195 | |
196 | static inline struct mlxsw_sp_acl_atcam_region * |
197 | mlxsw_sp_acl_tcam_cregion_aregion(struct mlxsw_sp_acl_ctcam_region *cregion) |
198 | { |
199 | return container_of(cregion, struct mlxsw_sp_acl_atcam_region, cregion); |
200 | } |
201 | |
202 | static inline struct mlxsw_sp_acl_atcam_entry * |
203 | mlxsw_sp_acl_tcam_centry_aentry(struct mlxsw_sp_acl_ctcam_entry *centry) |
204 | { |
205 | return container_of(centry, struct mlxsw_sp_acl_atcam_entry, centry); |
206 | } |
207 | |
208 | int mlxsw_sp_acl_atcam_region_associate(struct mlxsw_sp *mlxsw_sp, |
209 | u16 region_id); |
210 | int |
211 | mlxsw_sp_acl_atcam_region_init(struct mlxsw_sp *mlxsw_sp, |
212 | struct mlxsw_sp_acl_atcam *atcam, |
213 | struct mlxsw_sp_acl_atcam_region *aregion, |
214 | struct mlxsw_sp_acl_tcam_region *region, |
215 | void *hints_priv, |
216 | const struct mlxsw_sp_acl_ctcam_region_ops *ops); |
217 | void mlxsw_sp_acl_atcam_region_fini(struct mlxsw_sp_acl_atcam_region *aregion); |
218 | void mlxsw_sp_acl_atcam_chunk_init(struct mlxsw_sp_acl_atcam_region *aregion, |
219 | struct mlxsw_sp_acl_atcam_chunk *achunk, |
220 | unsigned int priority); |
221 | void mlxsw_sp_acl_atcam_chunk_fini(struct mlxsw_sp_acl_atcam_chunk *achunk); |
222 | int mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp, |
223 | struct mlxsw_sp_acl_atcam_region *aregion, |
224 | struct mlxsw_sp_acl_atcam_chunk *achunk, |
225 | struct mlxsw_sp_acl_atcam_entry *aentry, |
226 | struct mlxsw_sp_acl_rule_info *rulei); |
227 | void mlxsw_sp_acl_atcam_entry_del(struct mlxsw_sp *mlxsw_sp, |
228 | struct mlxsw_sp_acl_atcam_region *aregion, |
229 | struct mlxsw_sp_acl_atcam_chunk *achunk, |
230 | struct mlxsw_sp_acl_atcam_entry *aentry); |
231 | int mlxsw_sp_acl_atcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp, |
232 | struct mlxsw_sp_acl_atcam_region *aregion, |
233 | struct mlxsw_sp_acl_atcam_entry *aentry, |
234 | struct mlxsw_sp_acl_rule_info *rulei); |
235 | int mlxsw_sp_acl_atcam_init(struct mlxsw_sp *mlxsw_sp, |
236 | struct mlxsw_sp_acl_atcam *atcam); |
237 | void mlxsw_sp_acl_atcam_fini(struct mlxsw_sp *mlxsw_sp, |
238 | struct mlxsw_sp_acl_atcam *atcam); |
239 | void * |
240 | mlxsw_sp_acl_atcam_rehash_hints_get(struct mlxsw_sp_acl_atcam_region *aregion); |
241 | void mlxsw_sp_acl_atcam_rehash_hints_put(void *hints_priv); |
242 | |
243 | struct mlxsw_sp_acl_erp_delta; |
244 | |
245 | u16 mlxsw_sp_acl_erp_delta_start(const struct mlxsw_sp_acl_erp_delta *delta); |
246 | u8 mlxsw_sp_acl_erp_delta_mask(const struct mlxsw_sp_acl_erp_delta *delta); |
247 | u8 mlxsw_sp_acl_erp_delta_value(const struct mlxsw_sp_acl_erp_delta *delta, |
248 | const char *enc_key); |
249 | void mlxsw_sp_acl_erp_delta_clear(const struct mlxsw_sp_acl_erp_delta *delta, |
250 | const char *enc_key); |
251 | |
252 | struct mlxsw_sp_acl_erp_mask; |
253 | |
254 | bool |
255 | mlxsw_sp_acl_erp_mask_is_ctcam(const struct mlxsw_sp_acl_erp_mask *erp_mask); |
256 | u8 mlxsw_sp_acl_erp_mask_erp_id(const struct mlxsw_sp_acl_erp_mask *erp_mask); |
257 | const struct mlxsw_sp_acl_erp_delta * |
258 | mlxsw_sp_acl_erp_delta(const struct mlxsw_sp_acl_erp_mask *erp_mask); |
259 | struct mlxsw_sp_acl_erp_mask * |
260 | mlxsw_sp_acl_erp_mask_get(struct mlxsw_sp_acl_atcam_region *aregion, |
261 | const char *mask, bool ctcam); |
262 | void mlxsw_sp_acl_erp_mask_put(struct mlxsw_sp_acl_atcam_region *aregion, |
263 | struct mlxsw_sp_acl_erp_mask *erp_mask); |
264 | int mlxsw_sp_acl_erp_bf_insert(struct mlxsw_sp *mlxsw_sp, |
265 | struct mlxsw_sp_acl_atcam_region *aregion, |
266 | struct mlxsw_sp_acl_erp_mask *erp_mask, |
267 | struct mlxsw_sp_acl_atcam_entry *aentry); |
268 | void mlxsw_sp_acl_erp_bf_remove(struct mlxsw_sp *mlxsw_sp, |
269 | struct mlxsw_sp_acl_atcam_region *aregion, |
270 | struct mlxsw_sp_acl_erp_mask *erp_mask, |
271 | struct mlxsw_sp_acl_atcam_entry *aentry); |
272 | void * |
273 | mlxsw_sp_acl_erp_rehash_hints_get(struct mlxsw_sp_acl_atcam_region *aregion); |
274 | void mlxsw_sp_acl_erp_rehash_hints_put(void *hints_priv); |
275 | int mlxsw_sp_acl_erp_region_init(struct mlxsw_sp_acl_atcam_region *aregion, |
276 | void *hints_priv); |
277 | void mlxsw_sp_acl_erp_region_fini(struct mlxsw_sp_acl_atcam_region *aregion); |
278 | int mlxsw_sp_acl_erps_init(struct mlxsw_sp *mlxsw_sp, |
279 | struct mlxsw_sp_acl_atcam *atcam); |
280 | void mlxsw_sp_acl_erps_fini(struct mlxsw_sp *mlxsw_sp, |
281 | struct mlxsw_sp_acl_atcam *atcam); |
282 | |
283 | struct mlxsw_sp_acl_bf; |
284 | |
285 | struct mlxsw_sp_acl_bf_ops { |
286 | unsigned int (*index_get)(struct mlxsw_sp_acl_bf *bf, |
287 | struct mlxsw_sp_acl_atcam_region *aregion, |
288 | struct mlxsw_sp_acl_atcam_entry *aentry); |
289 | }; |
290 | |
291 | int |
292 | mlxsw_sp_acl_bf_entry_add(struct mlxsw_sp *mlxsw_sp, |
293 | struct mlxsw_sp_acl_bf *bf, |
294 | struct mlxsw_sp_acl_atcam_region *aregion, |
295 | unsigned int erp_bank, |
296 | struct mlxsw_sp_acl_atcam_entry *aentry); |
297 | void |
298 | mlxsw_sp_acl_bf_entry_del(struct mlxsw_sp *mlxsw_sp, |
299 | struct mlxsw_sp_acl_bf *bf, |
300 | struct mlxsw_sp_acl_atcam_region *aregion, |
301 | unsigned int erp_bank, |
302 | struct mlxsw_sp_acl_atcam_entry *aentry); |
303 | struct mlxsw_sp_acl_bf * |
304 | mlxsw_sp_acl_bf_init(struct mlxsw_sp *mlxsw_sp, unsigned int num_erp_banks); |
305 | void mlxsw_sp_acl_bf_fini(struct mlxsw_sp_acl_bf *bf); |
306 | |
307 | #endif |
308 | |