drivers/net/ethernet/mellanox/mlx5/core/uar.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/uar.c
Extension
.c
Size
8834 bytes
Lines
328
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

if (!up->map) {
			err = -EAGAIN;
			goto error2;
		}
	} else {
		up->map = ioremap(pfn << PAGE_SHIFT, PAGE_SIZE);
		if (!up->map) {
			err = -ENOMEM;
			goto error2;
		}
	}
	kref_init(&up->ref_count);
	mlx5_core_dbg(mdev, "allocated UAR page: index %d, total bfregs %d\n",
		      up->index, up->bfregs);
	return up;

error2:
	if (mlx5_cmd_free_uar(mdev, up->index))
		mlx5_core_warn(mdev, "failed to free uar index %d\n", up->index);
error1:
	bitmap_free(up->fp_bitmap);
	bitmap_free(up->reg_bitmap);
	kfree(up);
	return ERR_PTR(err);
}

struct mlx5_uars_page *mlx5_get_uars_page(struct mlx5_core_dev *mdev)
{
	struct mlx5_uars_page *ret;

	mutex_lock(&mdev->priv.bfregs.reg_head.lock);
	if (!list_empty(&mdev->priv.bfregs.reg_head.list)) {
		ret = list_first_entry(&mdev->priv.bfregs.reg_head.list,
				       struct mlx5_uars_page, list);
		kref_get(&ret->ref_count);
		goto out;
	}
	ret = alloc_uars_page(mdev, false);
	if (IS_ERR(ret))
		goto out;
	list_add(&ret->list, &mdev->priv.bfregs.reg_head.list);
out:
	mutex_unlock(&mdev->priv.bfregs.reg_head.lock);

	return ret;
}
EXPORT_SYMBOL(mlx5_get_uars_page);

void mlx5_put_uars_page(struct mlx5_core_dev *mdev, struct mlx5_uars_page *up)
{
	mutex_lock(&mdev->priv.bfregs.reg_head.lock);
	kref_put(&up->ref_count, up_rel_func);
	mutex_unlock(&mdev->priv.bfregs.reg_head.lock);
}
EXPORT_SYMBOL(mlx5_put_uars_page);

static unsigned long map_offset(struct mlx5_core_dev *mdev, int dbi)
{
	/* return the offset in bytes from the start of the page to the
	 * blue flame area of the UAR
	 */
	return dbi / MLX5_BFREGS_PER_UAR * MLX5_ADAPTER_PAGE_SIZE +
	       (dbi % MLX5_BFREGS_PER_UAR) *
	       (1 << MLX5_CAP_GEN(mdev, log_bf_reg_size)) + MLX5_BF_OFFSET;
}

static int alloc_bfreg(struct mlx5_core_dev *mdev, struct mlx5_sq_bfreg *bfreg,
		       bool map_wc, bool fast_path)
{
	struct mlx5_bfreg_data *bfregs;
	struct mlx5_uars_page *up;
	struct list_head *head;
	unsigned long *bitmap;
	unsigned int *avail;
	struct mutex *lock;  /* pointer to right mutex */
	int dbi;

	bfregs = &mdev->priv.bfregs;
	if (map_wc) {
		head = &bfregs->wc_head.list;
		lock = &bfregs->wc_head.lock;
	} else {
		head = &bfregs->reg_head.list;
		lock = &bfregs->reg_head.lock;
	}
	mutex_lock(lock);
	if (list_empty(head)) {
		up = alloc_uars_page(mdev, map_wc);
		if (IS_ERR(up)) {
			mutex_unlock(lock);

Annotation

Implementation Notes