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
15struct 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
28size_t mlxsw_sp_acl_tcam_priv_size(struct mlxsw_sp *mlxsw_sp);
29int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,
30			   struct mlxsw_sp_acl_tcam *tcam);
31void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp,
32			    struct mlxsw_sp_acl_tcam *tcam);
33int 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
37struct 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
62const struct mlxsw_sp_acl_profile_ops *
63mlxsw_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
74struct mlxsw_sp_acl_tcam_group;
75struct mlxsw_sp_acl_tcam_vregion;
76
77struct 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
90struct 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
96struct mlxsw_sp_acl_ctcam_chunk {
97	struct parman_prio parman_prio;
98};
99
100struct mlxsw_sp_acl_ctcam_entry {
101	struct parman_item parman_item;
102};
103
104struct 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
112int
113mlxsw_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);
117void mlxsw_sp_acl_ctcam_region_fini(struct mlxsw_sp_acl_ctcam_region *cregion);
118void 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);
121void mlxsw_sp_acl_ctcam_chunk_fini(struct mlxsw_sp_acl_ctcam_chunk *cchunk);
122int 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);
128void 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);
132int 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);
136static inline unsigned int
137mlxsw_sp_acl_ctcam_entry_offset(struct mlxsw_sp_acl_ctcam_entry *centry)
138{
139	return centry->parman_item.index;
140}
141
142enum 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
153struct mlxsw_sp_acl_atcam {
154	struct mlxsw_sp_acl_erp_core *erp_core;
155};
156
157struct 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
169struct mlxsw_sp_acl_atcam_entry_ht_key {
170	char full_enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded
171								 * key.
172								 */
173	u8 erp_id;
174};
175
176struct mlxsw_sp_acl_atcam_chunk {
177	struct mlxsw_sp_acl_ctcam_chunk cchunk;
178};
179
180struct 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	char enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded key,
185							    * minus delta bits.
186							    */
187	struct {
188		u16 start;
189		u8 mask;
190		u8 value;
191	} delta_info;
192	struct mlxsw_sp_acl_ctcam_entry centry;
193	struct mlxsw_sp_acl_atcam_lkey_id *lkey_id;
194	struct mlxsw_sp_acl_erp_mask *erp_mask;
195};
196
197static inline struct mlxsw_sp_acl_atcam_region *
198mlxsw_sp_acl_tcam_cregion_aregion(struct mlxsw_sp_acl_ctcam_region *cregion)
199{
200	return container_of(cregion, struct mlxsw_sp_acl_atcam_region, cregion);
201}
202
203static inline struct mlxsw_sp_acl_atcam_entry *
204mlxsw_sp_acl_tcam_centry_aentry(struct mlxsw_sp_acl_ctcam_entry *centry)
205{
206	return container_of(centry, struct mlxsw_sp_acl_atcam_entry, centry);
207}
208
209int mlxsw_sp_acl_atcam_region_associate(struct mlxsw_sp *mlxsw_sp,
210					u16 region_id);
211int
212mlxsw_sp_acl_atcam_region_init(struct mlxsw_sp *mlxsw_sp,
213			       struct mlxsw_sp_acl_atcam *atcam,
214			       struct mlxsw_sp_acl_atcam_region *aregion,
215			       struct mlxsw_sp_acl_tcam_region *region,
216			       void *hints_priv,
217			       const struct mlxsw_sp_acl_ctcam_region_ops *ops);
218void mlxsw_sp_acl_atcam_region_fini(struct mlxsw_sp_acl_atcam_region *aregion);
219void mlxsw_sp_acl_atcam_chunk_init(struct mlxsw_sp_acl_atcam_region *aregion,
220				   struct mlxsw_sp_acl_atcam_chunk *achunk,
221				   unsigned int priority);
222void mlxsw_sp_acl_atcam_chunk_fini(struct mlxsw_sp_acl_atcam_chunk *achunk);
223int mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp,
224				 struct mlxsw_sp_acl_atcam_region *aregion,
225				 struct mlxsw_sp_acl_atcam_chunk *achunk,
226				 struct mlxsw_sp_acl_atcam_entry *aentry,
227				 struct mlxsw_sp_acl_rule_info *rulei);
228void mlxsw_sp_acl_atcam_entry_del(struct mlxsw_sp *mlxsw_sp,
229				  struct mlxsw_sp_acl_atcam_region *aregion,
230				  struct mlxsw_sp_acl_atcam_chunk *achunk,
231				  struct mlxsw_sp_acl_atcam_entry *aentry);
232int mlxsw_sp_acl_atcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
233					    struct mlxsw_sp_acl_atcam_region *aregion,
234					    struct mlxsw_sp_acl_atcam_entry *aentry,
235					    struct mlxsw_sp_acl_rule_info *rulei);
236int mlxsw_sp_acl_atcam_init(struct mlxsw_sp *mlxsw_sp,
237			    struct mlxsw_sp_acl_atcam *atcam);
238void mlxsw_sp_acl_atcam_fini(struct mlxsw_sp *mlxsw_sp,
239			     struct mlxsw_sp_acl_atcam *atcam);
240void *
241mlxsw_sp_acl_atcam_rehash_hints_get(struct mlxsw_sp_acl_atcam_region *aregion);
242void mlxsw_sp_acl_atcam_rehash_hints_put(void *hints_priv);
243
244struct mlxsw_sp_acl_erp_delta;
245
246u16 mlxsw_sp_acl_erp_delta_start(const struct mlxsw_sp_acl_erp_delta *delta);
247u8 mlxsw_sp_acl_erp_delta_mask(const struct mlxsw_sp_acl_erp_delta *delta);
248u8 mlxsw_sp_acl_erp_delta_value(const struct mlxsw_sp_acl_erp_delta *delta,
249				const char *enc_key);
250void mlxsw_sp_acl_erp_delta_clear(const struct mlxsw_sp_acl_erp_delta *delta,
251				  const char *enc_key);
252
253struct mlxsw_sp_acl_erp_mask;
254
255bool
256mlxsw_sp_acl_erp_mask_is_ctcam(const struct mlxsw_sp_acl_erp_mask *erp_mask);
257u8 mlxsw_sp_acl_erp_mask_erp_id(const struct mlxsw_sp_acl_erp_mask *erp_mask);
258const struct mlxsw_sp_acl_erp_delta *
259mlxsw_sp_acl_erp_delta(const struct mlxsw_sp_acl_erp_mask *erp_mask);
260struct mlxsw_sp_acl_erp_mask *
261mlxsw_sp_acl_erp_mask_get(struct mlxsw_sp_acl_atcam_region *aregion,
262			  const char *mask, bool ctcam);
263void mlxsw_sp_acl_erp_mask_put(struct mlxsw_sp_acl_atcam_region *aregion,
264			       struct mlxsw_sp_acl_erp_mask *erp_mask);
265int mlxsw_sp_acl_erp_bf_insert(struct mlxsw_sp *mlxsw_sp,
266			       struct mlxsw_sp_acl_atcam_region *aregion,
267			       struct mlxsw_sp_acl_erp_mask *erp_mask,
268			       struct mlxsw_sp_acl_atcam_entry *aentry);
269void mlxsw_sp_acl_erp_bf_remove(struct mlxsw_sp *mlxsw_sp,
270				struct mlxsw_sp_acl_atcam_region *aregion,
271				struct mlxsw_sp_acl_erp_mask *erp_mask,
272				struct mlxsw_sp_acl_atcam_entry *aentry);
273void *
274mlxsw_sp_acl_erp_rehash_hints_get(struct mlxsw_sp_acl_atcam_region *aregion);
275void mlxsw_sp_acl_erp_rehash_hints_put(void *hints_priv);
276int mlxsw_sp_acl_erp_region_init(struct mlxsw_sp_acl_atcam_region *aregion,
277				 void *hints_priv);
278void mlxsw_sp_acl_erp_region_fini(struct mlxsw_sp_acl_atcam_region *aregion);
279int mlxsw_sp_acl_erps_init(struct mlxsw_sp *mlxsw_sp,
280			   struct mlxsw_sp_acl_atcam *atcam);
281void mlxsw_sp_acl_erps_fini(struct mlxsw_sp *mlxsw_sp,
282			    struct mlxsw_sp_acl_atcam *atcam);
283
284struct mlxsw_sp_acl_bf;
285
286struct mlxsw_sp_acl_bf_ops {
287	unsigned int (*index_get)(struct mlxsw_sp_acl_bf *bf,
288				  struct mlxsw_sp_acl_atcam_region *aregion,
289				  struct mlxsw_sp_acl_atcam_entry *aentry);
290};
291
292int
293mlxsw_sp_acl_bf_entry_add(struct mlxsw_sp *mlxsw_sp,
294			  struct mlxsw_sp_acl_bf *bf,
295			  struct mlxsw_sp_acl_atcam_region *aregion,
296			  unsigned int erp_bank,
297			  struct mlxsw_sp_acl_atcam_entry *aentry);
298void
299mlxsw_sp_acl_bf_entry_del(struct mlxsw_sp *mlxsw_sp,
300			  struct mlxsw_sp_acl_bf *bf,
301			  struct mlxsw_sp_acl_atcam_region *aregion,
302			  unsigned int erp_bank,
303			  struct mlxsw_sp_acl_atcam_entry *aentry);
304struct mlxsw_sp_acl_bf *
305mlxsw_sp_acl_bf_init(struct mlxsw_sp *mlxsw_sp, unsigned int num_erp_banks);
306void mlxsw_sp_acl_bf_fini(struct mlxsw_sp_acl_bf *bf);
307
308#endif
309