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