drivers/net/ethernet/mellanox/mlx5/core/en/mapping.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/en/mapping.c
Extension
.c
Size
5673 bytes
Lines
269
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 mapping_ctx {
	struct xarray xarray;
	DECLARE_HASHTABLE(ht, 8);
	struct mutex lock; /* Guards hashtable and xarray */
	unsigned long max_id;
	size_t data_size;
	bool delayed_removal;
	struct delayed_work dwork;
	struct list_head pending_list;
	spinlock_t pending_list_lock; /* Guards pending list */
	u8 id[MLX5_SW_IMAGE_GUID_MAX_BYTES];
	u8 id_len;
	u8 type;
	struct list_head list;
	refcount_t refcount;
};

struct mapping_item {
	struct rcu_head rcu;
	struct list_head list;
	unsigned long timeout;
	struct hlist_node node;
	int cnt;
	u32 id;
	char data[];
};

int mapping_add(struct mapping_ctx *ctx, void *data, u32 *id)
{
	struct mapping_item *mi;
	int err = -ENOMEM;
	u32 hash_key;

	mutex_lock(&ctx->lock);

	hash_key = jhash(data, ctx->data_size, 0);
	hash_for_each_possible(ctx->ht, mi, node, hash_key) {
		if (!memcmp(data, mi->data, ctx->data_size))
			goto attach;
	}

	mi = kzalloc(sizeof(*mi) + ctx->data_size, GFP_KERNEL);
	if (!mi)
		goto err_alloc;

	memcpy(mi->data, data, ctx->data_size);
	hash_add(ctx->ht, &mi->node, hash_key);

	err = xa_alloc(&ctx->xarray, &mi->id, mi, XA_LIMIT(1, ctx->max_id),
		       GFP_KERNEL);
	if (err)
		goto err_assign;
attach:
	++mi->cnt;
	*id = mi->id;

	mutex_unlock(&ctx->lock);

	return 0;

err_assign:
	hash_del(&mi->node);
	kfree(mi);
err_alloc:
	mutex_unlock(&ctx->lock);

	return err;
}

static void mapping_remove_and_free(struct mapping_ctx *ctx,
				    struct mapping_item *mi)
{
	xa_erase(&ctx->xarray, mi->id);
	kfree_rcu(mi, rcu);
}

static void mapping_free_item(struct mapping_ctx *ctx,
			      struct mapping_item *mi)
{
	if (!ctx->delayed_removal) {
		mapping_remove_and_free(ctx, mi);
		return;
	}

	mi->timeout = jiffies + msecs_to_jiffies(MAPPING_GRACE_PERIOD);

	spin_lock(&ctx->pending_list_lock);
	list_add_tail(&mi->list, &ctx->pending_list);
	spin_unlock(&ctx->pending_list_lock);

Annotation

Implementation Notes