drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c
Extension
.c
Size
8630 bytes
Lines
281
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct mlxsw_sp2_acl_tcam {
	struct mlxsw_sp_acl_atcam atcam;
	u32 kvdl_index;
	unsigned int kvdl_count;
};

struct mlxsw_sp2_acl_tcam_region {
	struct mlxsw_sp_acl_atcam_region aregion;
	struct mlxsw_sp_acl_tcam_region *region;
};

struct mlxsw_sp2_acl_tcam_chunk {
	struct mlxsw_sp_acl_atcam_chunk achunk;
};

struct mlxsw_sp2_acl_tcam_entry {
	struct mlxsw_sp_acl_atcam_entry aentry;
	struct mlxsw_afa_block *act_block;
};

static int
mlxsw_sp2_acl_ctcam_region_entry_insert(struct mlxsw_sp_acl_ctcam_region *cregion,
					struct mlxsw_sp_acl_ctcam_entry *centry,
					const char *mask)
{
	struct mlxsw_sp_acl_atcam_region *aregion;
	struct mlxsw_sp_acl_atcam_entry *aentry;
	struct mlxsw_sp_acl_erp_mask *erp_mask;

	aregion = mlxsw_sp_acl_tcam_cregion_aregion(cregion);
	aentry = mlxsw_sp_acl_tcam_centry_aentry(centry);

	erp_mask = mlxsw_sp_acl_erp_mask_get(aregion, mask, true);
	if (IS_ERR(erp_mask))
		return PTR_ERR(erp_mask);
	aentry->erp_mask = erp_mask;

	return 0;
}

static void
mlxsw_sp2_acl_ctcam_region_entry_remove(struct mlxsw_sp_acl_ctcam_region *cregion,
					struct mlxsw_sp_acl_ctcam_entry *centry)
{
	struct mlxsw_sp_acl_atcam_region *aregion;
	struct mlxsw_sp_acl_atcam_entry *aentry;

	aregion = mlxsw_sp_acl_tcam_cregion_aregion(cregion);
	aentry = mlxsw_sp_acl_tcam_centry_aentry(centry);

	mlxsw_sp_acl_erp_mask_put(aregion, aentry->erp_mask);
}

static const struct mlxsw_sp_acl_ctcam_region_ops
mlxsw_sp2_acl_ctcam_region_ops = {
	.entry_insert = mlxsw_sp2_acl_ctcam_region_entry_insert,
	.entry_remove = mlxsw_sp2_acl_ctcam_region_entry_remove,
};

static int mlxsw_sp2_acl_tcam_init(struct mlxsw_sp *mlxsw_sp, void *priv,
				   struct mlxsw_sp_acl_tcam *_tcam)
{
	struct mlxsw_sp2_acl_tcam *tcam = priv;
	struct mlxsw_afa_block *afa_block;
	char pefa_pl[MLXSW_REG_PEFA_LEN];
	char pgcr_pl[MLXSW_REG_PGCR_LEN];
	char *enc_actions;
	int i;
	int err;

	/* Some TCAM regions are not exposed to the host and used internally
	 * by the device. Allocate KVDL entries for the default actions of
	 * these regions to avoid the host from overwriting them.
	 */
	tcam->kvdl_count = _tcam->max_regions;
	if (MLXSW_CORE_RES_VALID(mlxsw_sp->core, ACL_MAX_DEFAULT_ACTIONS))
		tcam->kvdl_count = MLXSW_CORE_RES_GET(mlxsw_sp->core,
						      ACL_MAX_DEFAULT_ACTIONS);
	err = mlxsw_sp_kvdl_alloc(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ACTSET,
				  tcam->kvdl_count, &tcam->kvdl_index);
	if (err)
		return err;

	/* Create flex action block, set default action (continue)
	 * but don't commit. We need just the current set encoding
	 * to be written using PEFA register to all indexes for all regions.
	 */
	afa_block = mlxsw_afa_block_create(mlxsw_sp->afa);
	if (IS_ERR(afa_block)) {
		err = PTR_ERR(afa_block);

Annotation

Implementation Notes