drivers/net/ethernet/mellanox/mlx5/core/steering/hws/buddy.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/steering/hws/buddy.c
Extension
.c
Size
3001 bytes
Lines
150
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

if (!buddy->bitmap[i]) {
			ret = -ENOMEM;
			goto err_out_free_num_free;
		}
	}

	bitmap_set(buddy->bitmap[buddy->max_order], 0, 1);
	buddy->num_free[buddy->max_order] = 1;

	return 0;

err_out_free_num_free:
	for (i = 0; i <= (int)buddy->max_order; ++i)
		bitmap_free(buddy->bitmap[i]);

	kfree(buddy->num_free);

err_out_free_bits:
	kfree(buddy->bitmap);
	return ret;
}

struct mlx5hws_buddy_mem *mlx5hws_buddy_create(u32 max_order)
{
	struct mlx5hws_buddy_mem *buddy;

	buddy = kzalloc_obj(*buddy);
	if (!buddy)
		return NULL;

	if (hws_buddy_init(buddy, max_order))
		goto free_buddy;

	return buddy;

free_buddy:
	kfree(buddy);
	return NULL;
}

void mlx5hws_buddy_cleanup(struct mlx5hws_buddy_mem *buddy)
{
	int i;

	for (i = 0; i <= (int)buddy->max_order; ++i)
		bitmap_free(buddy->bitmap[i]);

	kfree(buddy->num_free);
	kfree(buddy->bitmap);
}

static int hws_buddy_find_free_seg(struct mlx5hws_buddy_mem *buddy,
				   u32 start_order,
				   u32 *segment,
				   u32 *order)
{
	unsigned int seg, order_iter, m;

	for (order_iter = start_order;
	     order_iter <= buddy->max_order; ++order_iter) {
		if (!buddy->num_free[order_iter])
			continue;

		m = 1 << (buddy->max_order - order_iter);
		seg = find_first_bit(buddy->bitmap[order_iter], m);

		if (WARN(seg >= m,
			 "ICM Buddy: failed finding free mem for order %d\n",
			 order_iter))
			return -ENOMEM;

		break;
	}

	if (order_iter > buddy->max_order)
		return -ENOMEM;

	*segment = seg;
	*order = order_iter;
	return 0;
}

int mlx5hws_buddy_alloc_mem(struct mlx5hws_buddy_mem *buddy, u32 order)
{
	u32 seg, order_iter, err;

	err = hws_buddy_find_free_seg(buddy, order, &seg, &order_iter);
	if (err)
		return err;

Annotation

Implementation Notes