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
14struct 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
27size_t mlxsw_sp_acl_tcam_priv_size(struct mlxsw_sp *mlxsw_sp);
28int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,
29 struct mlxsw_sp_acl_tcam *tcam);
30void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp,
31 struct mlxsw_sp_acl_tcam *tcam);
32int 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
36struct 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
61const struct mlxsw_sp_acl_profile_ops *
62mlxsw_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
73struct mlxsw_sp_acl_tcam_group;
74struct mlxsw_sp_acl_tcam_vregion;
75
76struct 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
89struct 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
95struct mlxsw_sp_acl_ctcam_chunk {
96 struct parman_prio parman_prio;
97};
98
99struct mlxsw_sp_acl_ctcam_entry {
100 struct parman_item parman_item;
101};
102
103struct 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
111int
112mlxsw_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);
116void mlxsw_sp_acl_ctcam_region_fini(struct mlxsw_sp_acl_ctcam_region *cregion);
117void 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);
120void mlxsw_sp_acl_ctcam_chunk_fini(struct mlxsw_sp_acl_ctcam_chunk *cchunk);
121int 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);
127void 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);
131int 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);
135static inline unsigned int
136mlxsw_sp_acl_ctcam_entry_offset(struct mlxsw_sp_acl_ctcam_entry *centry)
137{
138 return centry->parman_item.index;
139}
140
141enum 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
152struct mlxsw_sp_acl_atcam {
153 struct mlxsw_sp_acl_erp_core *erp_core;
154};
155
156struct 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
168struct 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
175struct mlxsw_sp_acl_atcam_chunk {
176 struct mlxsw_sp_acl_ctcam_chunk cchunk;
177};
178
179struct 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
196static inline struct mlxsw_sp_acl_atcam_region *
197mlxsw_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
202static inline struct mlxsw_sp_acl_atcam_entry *
203mlxsw_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
208int mlxsw_sp_acl_atcam_region_associate(struct mlxsw_sp *mlxsw_sp,
209 u16 region_id);
210int
211mlxsw_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);
217void mlxsw_sp_acl_atcam_region_fini(struct mlxsw_sp_acl_atcam_region *aregion);
218void 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);
221void mlxsw_sp_acl_atcam_chunk_fini(struct mlxsw_sp_acl_atcam_chunk *achunk);
222int 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);
227void 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);
231int 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);
235int mlxsw_sp_acl_atcam_init(struct mlxsw_sp *mlxsw_sp,
236 struct mlxsw_sp_acl_atcam *atcam);
237void mlxsw_sp_acl_atcam_fini(struct mlxsw_sp *mlxsw_sp,
238 struct mlxsw_sp_acl_atcam *atcam);
239void *
240mlxsw_sp_acl_atcam_rehash_hints_get(struct mlxsw_sp_acl_atcam_region *aregion);
241void mlxsw_sp_acl_atcam_rehash_hints_put(void *hints_priv);
242
243struct mlxsw_sp_acl_erp_delta;
244
245u16 mlxsw_sp_acl_erp_delta_start(const struct mlxsw_sp_acl_erp_delta *delta);
246u8 mlxsw_sp_acl_erp_delta_mask(const struct mlxsw_sp_acl_erp_delta *delta);
247u8 mlxsw_sp_acl_erp_delta_value(const struct mlxsw_sp_acl_erp_delta *delta,
248 const char *enc_key);
249void mlxsw_sp_acl_erp_delta_clear(const struct mlxsw_sp_acl_erp_delta *delta,
250 const char *enc_key);
251
252struct mlxsw_sp_acl_erp_mask;
253
254bool
255mlxsw_sp_acl_erp_mask_is_ctcam(const struct mlxsw_sp_acl_erp_mask *erp_mask);
256u8 mlxsw_sp_acl_erp_mask_erp_id(const struct mlxsw_sp_acl_erp_mask *erp_mask);
257const struct mlxsw_sp_acl_erp_delta *
258mlxsw_sp_acl_erp_delta(const struct mlxsw_sp_acl_erp_mask *erp_mask);
259struct mlxsw_sp_acl_erp_mask *
260mlxsw_sp_acl_erp_mask_get(struct mlxsw_sp_acl_atcam_region *aregion,
261 const char *mask, bool ctcam);
262void mlxsw_sp_acl_erp_mask_put(struct mlxsw_sp_acl_atcam_region *aregion,
263 struct mlxsw_sp_acl_erp_mask *erp_mask);
264int 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);
268void 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);
272void *
273mlxsw_sp_acl_erp_rehash_hints_get(struct mlxsw_sp_acl_atcam_region *aregion);
274void mlxsw_sp_acl_erp_rehash_hints_put(void *hints_priv);
275int mlxsw_sp_acl_erp_region_init(struct mlxsw_sp_acl_atcam_region *aregion,
276 void *hints_priv);
277void mlxsw_sp_acl_erp_region_fini(struct mlxsw_sp_acl_atcam_region *aregion);
278int mlxsw_sp_acl_erps_init(struct mlxsw_sp *mlxsw_sp,
279 struct mlxsw_sp_acl_atcam *atcam);
280void mlxsw_sp_acl_erps_fini(struct mlxsw_sp *mlxsw_sp,
281 struct mlxsw_sp_acl_atcam *atcam);
282
283struct mlxsw_sp_acl_bf;
284
285struct 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
291int
292mlxsw_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);
297void
298mlxsw_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);
303struct mlxsw_sp_acl_bf *
304mlxsw_sp_acl_bf_init(struct mlxsw_sp *mlxsw_sp, unsigned int num_erp_banks);
305void mlxsw_sp_acl_bf_fini(struct mlxsw_sp_acl_bf *bf);
306
307#endif
308

source code of linux/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h