306 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			306 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* 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 <linux/list.h>
 | |
| #include <linux/parman.h>
 | |
| #include <linux/idr.h>
 | |
| 
 | |
| #include "reg.h"
 | |
| #include "spectrum.h"
 | |
| #include "core_acl_flex_keys.h"
 | |
| 
 | |
| struct mlxsw_sp_acl_tcam {
 | |
| 	struct ida used_regions;
 | |
| 	unsigned int max_regions;
 | |
| 	struct ida used_groups;
 | |
| 	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[];
 | |
| 	/* 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);
 | |
| 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,
 | |
| 			   unsigned int *p_min_prio, unsigned int *p_max_prio);
 | |
| 	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[];
 | |
| 	/* 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 enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded key, minus
 | |
| 							    * delta bits.
 | |
| 							    */
 | |
| 	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;
 | |
| 	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;
 | |
| 
 | |
| struct mlxsw_sp_acl_bf_ops {
 | |
| 	unsigned int (*index_get)(struct mlxsw_sp_acl_bf *bf,
 | |
| 				  struct mlxsw_sp_acl_atcam_region *aregion,
 | |
| 				  struct mlxsw_sp_acl_atcam_entry *aentry);
 | |
| };
 | |
| 
 | |
| 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
 |