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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlxsw/spectrum_policer.c
Extension
.c
Size
12875 bytes
Lines
469
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_sp_policer_family {
	enum mlxsw_sp_policer_type type;
	enum mlxsw_reg_qpcr_g qpcr_type;
	struct mlxsw_sp *mlxsw_sp;
	u16 start_index; /* Inclusive */
	u16 end_index; /* Exclusive */
	struct idr policer_idr;
	struct mutex lock; /* Protects policer_idr */
	atomic_t policers_count;
	const struct mlxsw_sp_policer_family_ops *ops;
};

struct mlxsw_sp_policer {
	struct mlxsw_sp_policer_params params;
	u16 index;
};

struct mlxsw_sp_policer_family_ops {
	int (*init)(struct mlxsw_sp_policer_family *family);
	void (*fini)(struct mlxsw_sp_policer_family *family);
	int (*policer_index_alloc)(struct mlxsw_sp_policer_family *family,
				   struct mlxsw_sp_policer *policer);
	struct mlxsw_sp_policer * (*policer_index_free)(struct mlxsw_sp_policer_family *family,
							u16 policer_index);
	int (*policer_init)(struct mlxsw_sp_policer_family *family,
			    const struct mlxsw_sp_policer *policer);
	int (*policer_params_check)(const struct mlxsw_sp_policer_family *family,
				    const struct mlxsw_sp_policer_params *params,
				    struct netlink_ext_ack *extack);
};

struct mlxsw_sp_policer_core {
	struct mlxsw_sp_policer_family *family_arr[MLXSW_SP_POLICER_TYPE_MAX + 1];
	const struct mlxsw_sp_policer_core_ops *ops;
	u8 lowest_bs_bits;
	u8 highest_bs_bits;
};

struct mlxsw_sp_policer_core_ops {
	int (*init)(struct mlxsw_sp_policer_core *policer_core);
};

static u64 mlxsw_sp_policer_rate_bytes_ps_kbps(u64 rate_bytes_ps)
{
	return div_u64(rate_bytes_ps, 1000) * BITS_PER_BYTE;
}

static u8 mlxsw_sp_policer_burst_bytes_hw_units(u64 burst_bytes)
{
	/* Provided burst size is in bytes. The ASIC burst size value is
	 * (2 ^ bs) * 512 bits. Convert the provided size to 512-bit units.
	 */
	u64 bs512 = div_u64(burst_bytes, 64);

	if (!bs512)
		return 0;

	return fls64(bs512) - 1;
}

static u64 mlxsw_sp_policer_single_rate_occ_get(void *priv)
{
	struct mlxsw_sp_policer_family *family = priv;

	return atomic_read(&family->policers_count);
}

static int
mlxsw_sp_policer_single_rate_family_init(struct mlxsw_sp_policer_family *family)
{
	struct mlxsw_core *core = family->mlxsw_sp->core;
	struct devlink *devlink;

	/* CPU policers are allocated from the first N policers in the global
	 * range, so skip them.
	 */
	if (!MLXSW_CORE_RES_VALID(core, MAX_GLOBAL_POLICERS) ||
	    !MLXSW_CORE_RES_VALID(core, MAX_CPU_POLICERS))
		return -EIO;

	family->start_index = MLXSW_CORE_RES_GET(core, MAX_CPU_POLICERS);
	family->end_index = MLXSW_CORE_RES_GET(core, MAX_GLOBAL_POLICERS);

	atomic_set(&family->policers_count, 0);
	devlink = priv_to_devlink(core);
	devl_resource_occ_get_register(devlink,
				       MLXSW_SP_RESOURCE_SINGLE_RATE_POLICERS,
				       mlxsw_sp_policer_single_rate_occ_get,
				       family);

Annotation

Implementation Notes