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