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