/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */ /* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */ #ifndef _MLXSW_SPECTRUM_ACL_TCAM_H #define _MLXSW_SPECTRUM_ACL_TCAM_H #include #include #include "reg.h" #include "spectrum.h" #include "core_acl_flex_keys.h" struct mlxsw_sp_acl_tcam { unsigned long *used_regions; /* bit array */ unsigned int max_regions; unsigned long *used_groups; /* bit array */ unsigned int max_groups; unsigned int max_group_size; struct mutex lock; /* guards vregion list */ struct list_head vregion_list; u32 vregion_rehash_intrvl; /* ms */ unsigned long priv[0]; /* priv has to be always the last item */ }; size_t mlxsw_sp_acl_tcam_priv_size(struct mlxsw_sp *mlxsw_sp); int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam *tcam); void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam *tcam); u32 mlxsw_sp_acl_tcam_vregion_rehash_intrvl_get(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam *tcam); int mlxsw_sp_acl_tcam_vregion_rehash_intrvl_set(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam *tcam, u32 val); int mlxsw_sp_acl_tcam_priority_get(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_rule_info *rulei, u32 *priority, bool fillup_priority); struct mlxsw_sp_acl_profile_ops { size_t ruleset_priv_size; int (*ruleset_add)(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam *tcam, void *ruleset_priv, struct mlxsw_afk_element_usage *tmplt_elusage); void (*ruleset_del)(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv); int (*ruleset_bind)(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv, struct mlxsw_sp_port *mlxsw_sp_port, bool ingress); void (*ruleset_unbind)(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv, struct mlxsw_sp_port *mlxsw_sp_port, bool ingress); u16 (*ruleset_group_id)(void *ruleset_priv); size_t rule_priv_size; int (*rule_add)(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv, void *rule_priv, struct mlxsw_sp_acl_rule_info *rulei); void (*rule_del)(struct mlxsw_sp *mlxsw_sp, void *rule_priv); int (*rule_action_replace)(struct mlxsw_sp *mlxsw_sp, void *rule_priv, struct mlxsw_sp_acl_rule_info *rulei); int (*rule_activity_get)(struct mlxsw_sp *mlxsw_sp, void *rule_priv, bool *activity); }; const struct mlxsw_sp_acl_profile_ops * mlxsw_sp_acl_tcam_profile_ops(struct mlxsw_sp *mlxsw_sp, enum mlxsw_sp_acl_profile profile); #define MLXSW_SP_ACL_TCAM_REGION_BASE_COUNT 16 #define MLXSW_SP_ACL_TCAM_REGION_RESIZE_STEP 16 #define MLXSW_SP_ACL_TCAM_CATCHALL_PRIO (~0U) #define MLXSW_SP_ACL_TCAM_MASK_LEN \ (MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN * BITS_PER_BYTE) struct mlxsw_sp_acl_tcam_group; struct mlxsw_sp_acl_tcam_vregion; struct mlxsw_sp_acl_tcam_region { struct mlxsw_sp_acl_tcam_vregion *vregion; struct mlxsw_sp_acl_tcam_group *group; struct list_head list; /* Member of a TCAM group */ enum mlxsw_reg_ptar_key_type key_type; u16 id; /* ACL ID and region ID - they are same */ char tcam_region_info[MLXSW_REG_PXXX_TCAM_REGION_INFO_LEN]; struct mlxsw_afk_key_info *key_info; struct mlxsw_sp *mlxsw_sp; unsigned long priv[0]; /* priv has to be always the last item */ }; struct mlxsw_sp_acl_ctcam_region { struct parman *parman; const struct mlxsw_sp_acl_ctcam_region_ops *ops; struct mlxsw_sp_acl_tcam_region *region; }; struct mlxsw_sp_acl_ctcam_chunk { struct parman_prio parman_prio; }; struct mlxsw_sp_acl_ctcam_entry { struct parman_item parman_item; }; struct mlxsw_sp_acl_ctcam_region_ops { int (*entry_insert)(struct mlxsw_sp_acl_ctcam_region *cregion, struct mlxsw_sp_acl_ctcam_entry *centry, const char *mask); void (*entry_remove)(struct mlxsw_sp_acl_ctcam_region *cregion, struct mlxsw_sp_acl_ctcam_entry *centry); }; int mlxsw_sp_acl_ctcam_region_init(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_ctcam_region *cregion, struct mlxsw_sp_acl_tcam_region *region, const struct mlxsw_sp_acl_ctcam_region_ops *ops); void mlxsw_sp_acl_ctcam_region_fini(struct mlxsw_sp_acl_ctcam_region *cregion); void mlxsw_sp_acl_ctcam_chunk_init(struct mlxsw_sp_acl_ctcam_region *cregion, struct mlxsw_sp_acl_ctcam_chunk *cchunk, unsigned int priority); void mlxsw_sp_acl_ctcam_chunk_fini(struct mlxsw_sp_acl_ctcam_chunk *cchunk); int mlxsw_sp_acl_ctcam_entry_add(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_ctcam_region *cregion, struct mlxsw_sp_acl_ctcam_chunk *cchunk, struct mlxsw_sp_acl_ctcam_entry *centry, struct mlxsw_sp_acl_rule_info *rulei, bool fillup_priority); void mlxsw_sp_acl_ctcam_entry_del(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_ctcam_region *cregion, struct mlxsw_sp_acl_ctcam_chunk *cchunk, struct mlxsw_sp_acl_ctcam_entry *centry); int mlxsw_sp_acl_ctcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_ctcam_region *cregion, struct mlxsw_sp_acl_ctcam_entry *centry, struct mlxsw_sp_acl_rule_info *rulei); static inline unsigned int mlxsw_sp_acl_ctcam_entry_offset(struct mlxsw_sp_acl_ctcam_entry *centry) { return centry->parman_item.index; } enum mlxsw_sp_acl_atcam_region_type { MLXSW_SP_ACL_ATCAM_REGION_TYPE_2KB, MLXSW_SP_ACL_ATCAM_REGION_TYPE_4KB, MLXSW_SP_ACL_ATCAM_REGION_TYPE_8KB, MLXSW_SP_ACL_ATCAM_REGION_TYPE_12KB, __MLXSW_SP_ACL_ATCAM_REGION_TYPE_MAX, }; #define MLXSW_SP_ACL_ATCAM_REGION_TYPE_MAX \ (__MLXSW_SP_ACL_ATCAM_REGION_TYPE_MAX - 1) struct mlxsw_sp_acl_atcam { struct mlxsw_sp_acl_erp_core *erp_core; }; struct mlxsw_sp_acl_atcam_region { struct rhashtable entries_ht; /* A-TCAM only */ struct list_head entries_list; /* A-TCAM only */ struct mlxsw_sp_acl_ctcam_region cregion; const struct mlxsw_sp_acl_atcam_region_ops *ops; struct mlxsw_sp_acl_tcam_region *region; struct mlxsw_sp_acl_atcam *atcam; enum mlxsw_sp_acl_atcam_region_type type; struct mlxsw_sp_acl_erp_table *erp_table; void *priv; }; struct mlxsw_sp_acl_atcam_entry_ht_key { char full_enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded * key. */ u8 erp_id; }; struct mlxsw_sp_acl_atcam_chunk { struct mlxsw_sp_acl_ctcam_chunk cchunk; }; struct mlxsw_sp_acl_atcam_entry { struct rhash_head ht_node; struct list_head list; /* Member in entries_list */ struct mlxsw_sp_acl_atcam_entry_ht_key ht_key; char enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded key, * minus delta bits. */ struct { u16 start; u8 mask; u8 value; } delta_info; struct mlxsw_sp_acl_ctcam_entry centry; struct mlxsw_sp_acl_atcam_lkey_id *lkey_id; struct mlxsw_sp_acl_erp_mask *erp_mask; }; static inline struct mlxsw_sp_acl_atcam_region * mlxsw_sp_acl_tcam_cregion_aregion(struct mlxsw_sp_acl_ctcam_region *cregion) { return container_of(cregion, struct mlxsw_sp_acl_atcam_region, cregion); } static inline struct mlxsw_sp_acl_atcam_entry * mlxsw_sp_acl_tcam_centry_aentry(struct mlxsw_sp_acl_ctcam_entry *centry) { return container_of(centry, struct mlxsw_sp_acl_atcam_entry, centry); } int mlxsw_sp_acl_atcam_region_associate(struct mlxsw_sp *mlxsw_sp, u16 region_id); int mlxsw_sp_acl_atcam_region_init(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam *atcam, struct mlxsw_sp_acl_atcam_region *aregion, struct mlxsw_sp_acl_tcam_region *region, void *hints_priv, const struct mlxsw_sp_acl_ctcam_region_ops *ops); void mlxsw_sp_acl_atcam_region_fini(struct mlxsw_sp_acl_atcam_region *aregion); void mlxsw_sp_acl_atcam_chunk_init(struct mlxsw_sp_acl_atcam_region *aregion, struct mlxsw_sp_acl_atcam_chunk *achunk, unsigned int priority); void mlxsw_sp_acl_atcam_chunk_fini(struct mlxsw_sp_acl_atcam_chunk *achunk); int mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam_region *aregion, struct mlxsw_sp_acl_atcam_chunk *achunk, struct mlxsw_sp_acl_atcam_entry *aentry, struct mlxsw_sp_acl_rule_info *rulei); void mlxsw_sp_acl_atcam_entry_del(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam_region *aregion, struct mlxsw_sp_acl_atcam_chunk *achunk, struct mlxsw_sp_acl_atcam_entry *aentry); int mlxsw_sp_acl_atcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam_region *aregion, struct mlxsw_sp_acl_atcam_entry *aentry, struct mlxsw_sp_acl_rule_info *rulei); int mlxsw_sp_acl_atcam_init(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam *atcam); void mlxsw_sp_acl_atcam_fini(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam *atcam); void * mlxsw_sp_acl_atcam_rehash_hints_get(struct mlxsw_sp_acl_atcam_region *aregion); void mlxsw_sp_acl_atcam_rehash_hints_put(void *hints_priv); struct mlxsw_sp_acl_erp_delta; u16 mlxsw_sp_acl_erp_delta_start(const struct mlxsw_sp_acl_erp_delta *delta); u8 mlxsw_sp_acl_erp_delta_mask(const struct mlxsw_sp_acl_erp_delta *delta); u8 mlxsw_sp_acl_erp_delta_value(const struct mlxsw_sp_acl_erp_delta *delta, const char *enc_key); void mlxsw_sp_acl_erp_delta_clear(const struct mlxsw_sp_acl_erp_delta *delta, const char *enc_key); struct mlxsw_sp_acl_erp_mask; bool mlxsw_sp_acl_erp_mask_is_ctcam(const struct mlxsw_sp_acl_erp_mask *erp_mask); u8 mlxsw_sp_acl_erp_mask_erp_id(const struct mlxsw_sp_acl_erp_mask *erp_mask); const struct mlxsw_sp_acl_erp_delta * mlxsw_sp_acl_erp_delta(const struct mlxsw_sp_acl_erp_mask *erp_mask); struct mlxsw_sp_acl_erp_mask * mlxsw_sp_acl_erp_mask_get(struct mlxsw_sp_acl_atcam_region *aregion, const char *mask, bool ctcam); void mlxsw_sp_acl_erp_mask_put(struct mlxsw_sp_acl_atcam_region *aregion, struct mlxsw_sp_acl_erp_mask *erp_mask); int mlxsw_sp_acl_erp_bf_insert(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam_region *aregion, struct mlxsw_sp_acl_erp_mask *erp_mask, struct mlxsw_sp_acl_atcam_entry *aentry); void mlxsw_sp_acl_erp_bf_remove(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam_region *aregion, struct mlxsw_sp_acl_erp_mask *erp_mask, struct mlxsw_sp_acl_atcam_entry *aentry); void * mlxsw_sp_acl_erp_rehash_hints_get(struct mlxsw_sp_acl_atcam_region *aregion); void mlxsw_sp_acl_erp_rehash_hints_put(void *hints_priv); int mlxsw_sp_acl_erp_region_init(struct mlxsw_sp_acl_atcam_region *aregion, void *hints_priv); void mlxsw_sp_acl_erp_region_fini(struct mlxsw_sp_acl_atcam_region *aregion); int mlxsw_sp_acl_erps_init(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam *atcam); void mlxsw_sp_acl_erps_fini(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam *atcam); struct mlxsw_sp_acl_bf; int mlxsw_sp_acl_bf_entry_add(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_bf *bf, struct mlxsw_sp_acl_atcam_region *aregion, unsigned int erp_bank, struct mlxsw_sp_acl_atcam_entry *aentry); void mlxsw_sp_acl_bf_entry_del(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_bf *bf, struct mlxsw_sp_acl_atcam_region *aregion, unsigned int erp_bank, struct mlxsw_sp_acl_atcam_entry *aentry); struct mlxsw_sp_acl_bf * mlxsw_sp_acl_bf_init(struct mlxsw_sp *mlxsw_sp, unsigned int num_erp_banks); void mlxsw_sp_acl_bf_fini(struct mlxsw_sp_acl_bf *bf); #endif