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