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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
Extension
.c
Size
48396 bytes
Lines
1743
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_span {
	struct work_struct work;
	struct mlxsw_sp *mlxsw_sp;
	const struct mlxsw_sp_span_trigger_ops **span_trigger_ops_arr;
	const struct mlxsw_sp_span_entry_ops **span_entry_ops_arr;
	size_t span_entry_ops_arr_size;
	struct list_head analyzed_ports_list;
	struct mutex analyzed_ports_lock; /* Protects analyzed_ports_list */
	struct list_head trigger_entries_list;
	u16 policer_id_base;
	refcount_t policer_id_base_ref_count;
	atomic_t active_entries_count;
	int entries_count;
	struct mlxsw_sp_span_entry entries[] __counted_by(entries_count);
};

struct mlxsw_sp_span_analyzed_port {
	struct list_head list; /* Member of analyzed_ports_list */
	refcount_t ref_count;
	u16 local_port;
	bool ingress;
};

struct mlxsw_sp_span_trigger_entry {
	struct list_head list; /* Member of trigger_entries_list */
	struct mlxsw_sp_span *span;
	const struct mlxsw_sp_span_trigger_ops *ops;
	refcount_t ref_count;
	u16 local_port;
	enum mlxsw_sp_span_trigger trigger;
	struct mlxsw_sp_span_trigger_parms parms;
};

enum mlxsw_sp_span_trigger_type {
	MLXSW_SP_SPAN_TRIGGER_TYPE_PORT,
	MLXSW_SP_SPAN_TRIGGER_TYPE_GLOBAL,
};

struct mlxsw_sp_span_trigger_ops {
	int (*bind)(struct mlxsw_sp_span_trigger_entry *trigger_entry);
	void (*unbind)(struct mlxsw_sp_span_trigger_entry *trigger_entry);
	bool (*matches)(struct mlxsw_sp_span_trigger_entry *trigger_entry,
			enum mlxsw_sp_span_trigger trigger,
			struct mlxsw_sp_port *mlxsw_sp_port);
	int (*enable)(struct mlxsw_sp_span_trigger_entry *trigger_entry,
		      struct mlxsw_sp_port *mlxsw_sp_port, u8 tc);
	void (*disable)(struct mlxsw_sp_span_trigger_entry *trigger_entry,
			struct mlxsw_sp_port *mlxsw_sp_port, u8 tc);
};

static void mlxsw_sp_span_respin_work(struct work_struct *work);

static u64 mlxsw_sp_span_occ_get(void *priv)
{
	const struct mlxsw_sp *mlxsw_sp = priv;

	return atomic_read(&mlxsw_sp->span->active_entries_count);
}

int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp)
{
	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
	struct mlxsw_sp_span *span;
	int i, entries_count, err;

	if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_SPAN))
		return -EIO;

	entries_count = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_SPAN);
	span = kzalloc_flex(*span, entries, entries_count);
	if (!span)
		return -ENOMEM;
	refcount_set(&span->policer_id_base_ref_count, 0);
	span->entries_count = entries_count;
	atomic_set(&span->active_entries_count, 0);
	mutex_init(&span->analyzed_ports_lock);
	INIT_LIST_HEAD(&span->analyzed_ports_list);
	INIT_LIST_HEAD(&span->trigger_entries_list);
	span->mlxsw_sp = mlxsw_sp;
	mlxsw_sp->span = span;

	for (i = 0; i < mlxsw_sp->span->entries_count; i++)
		mlxsw_sp->span->entries[i].id = i;

	err = mlxsw_sp->span_ops->init(mlxsw_sp);
	if (err)
		goto err_init;

	devl_resource_occ_get_register(devlink, MLXSW_SP_RESOURCE_SPAN,
				       mlxsw_sp_span_occ_get, mlxsw_sp);

Annotation

Implementation Notes