drivers/net/ethernet/mellanox/mlx5/core/lib/st.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/mellanox/mlx5/core/lib/st.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/lib/st.c
Extension
.c
Size
3671 bytes
Lines
186
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 mlx5_st_idx_data {
	refcount_t usecount;
	u16 tag;
};

struct mlx5_st {
	/* serialize access upon alloc/free flows */
	struct mutex lock;
	struct xa_limit index_limit;
	struct xarray idx_xa; /* key == index, value == struct mlx5_st_idx_data */
	u8 direct_mode : 1;
};

struct mlx5_st *mlx5_st_create(struct mlx5_core_dev *dev)
{
	struct pci_dev *pdev = dev->pdev;
	struct mlx5_st *st;
	u8 direct_mode = 0;
	u16 num_entries;
	u32 tbl_loc;
	int ret;

	if (!MLX5_CAP_GEN(dev, mkey_pcie_tph))
		return NULL;

#ifdef CONFIG_MLX5_SF
	if (mlx5_core_is_sf(dev))
		return dev->priv.parent_mdev->st;
#endif

	/* Checking whether the device is capable */
	if (!pdev->tph_cap)
		return NULL;

	tbl_loc = pcie_tph_get_st_table_loc(pdev);
	if (tbl_loc == PCI_TPH_LOC_NONE)
		direct_mode = 1;

	if (!direct_mode) {
		num_entries = pcie_tph_get_st_table_size(pdev);
		/* We need a reserved entry for non TPH cases */
		if (num_entries < 2)
			return NULL;
	}

	/* The OS doesn't support ST */
	ret = pcie_enable_tph(pdev, PCI_TPH_ST_DS_MODE);
	if (ret)
		return NULL;

	st = kzalloc_obj(*st);
	if (!st)
		goto end;

	mutex_init(&st->lock);
	xa_init_flags(&st->idx_xa, XA_FLAGS_ALLOC);
	st->direct_mode = direct_mode;
	if (st->direct_mode)
		return st;

	/* entry 0 is reserved for non TPH cases */
	st->index_limit.min = MLX5_MKC_PCIE_TPH_NO_STEERING_TAG_INDEX + 1;
	st->index_limit.max = num_entries - 1;

	return st;

end:
	pcie_disable_tph(dev->pdev);
	return NULL;
}

void mlx5_st_destroy(struct mlx5_core_dev *dev)
{
	struct mlx5_st *st = dev->st;

	if (mlx5_core_is_sf(dev) || !st)
		return;

	pcie_disable_tph(dev->pdev);
	WARN_ON_ONCE(!xa_empty(&st->idx_xa));
	kfree(st);
}

int mlx5_st_alloc_index(struct mlx5_core_dev *dev, enum tph_mem_type mem_type,
			unsigned int cpu_uid, u16 *st_index)
{
	struct mlx5_st_idx_data *idx_data;
	struct mlx5_st *st = dev->st;
	unsigned long index;
	u32 xa_id;

Annotation

Implementation Notes