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