drivers/net/ethernet/mellanox/mlx4/alloc.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/mellanox/mlx4/alloc.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx4/alloc.c
Extension
.c
Size
18345 bytes
Lines
796
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 mlx4_zone_allocator {
	struct list_head		entries;
	struct list_head		prios;
	u32				last_uid;
	u32				mask;
	/* protect the zone_allocator from concurrent accesses */
	spinlock_t			lock;
	enum mlx4_zone_alloc_flags	flags;
};

struct mlx4_zone_entry {
	struct list_head		list;
	struct list_head		prio_list;
	u32				uid;
	struct mlx4_zone_allocator	*allocator;
	struct mlx4_bitmap		*bitmap;
	int				use_rr;
	int				priority;
	int				offset;
	enum mlx4_zone_flags		flags;
};

struct mlx4_zone_allocator *mlx4_zone_allocator_create(enum mlx4_zone_alloc_flags flags)
{
	struct mlx4_zone_allocator *zones = kmalloc_obj(*zones);

	if (NULL == zones)
		return NULL;

	INIT_LIST_HEAD(&zones->entries);
	INIT_LIST_HEAD(&zones->prios);
	spin_lock_init(&zones->lock);
	zones->last_uid = 0;
	zones->mask = 0;
	zones->flags = flags;

	return zones;
}

int mlx4_zone_add_one(struct mlx4_zone_allocator *zone_alloc,
		      struct mlx4_bitmap *bitmap,
		      u32 flags,
		      int priority,
		      int offset,
		      u32 *puid)
{
	u32 mask = mlx4_bitmap_masked_value(bitmap, (u32)-1);
	struct mlx4_zone_entry *it;
	struct mlx4_zone_entry *zone = kmalloc_obj(*zone);

	if (NULL == zone)
		return -ENOMEM;

	zone->flags = flags;
	zone->bitmap = bitmap;
	zone->use_rr = (flags & MLX4_ZONE_USE_RR) ? MLX4_USE_RR : 0;
	zone->priority = priority;
	zone->offset = offset;

	spin_lock(&zone_alloc->lock);

	zone->uid = zone_alloc->last_uid++;
	zone->allocator = zone_alloc;

	if (zone_alloc->mask < mask)
		zone_alloc->mask = mask;

	list_for_each_entry(it, &zone_alloc->prios, prio_list)
		if (it->priority >= priority)
			break;

	if (&it->prio_list == &zone_alloc->prios || it->priority > priority)
		list_add_tail(&zone->prio_list, &it->prio_list);
	list_add_tail(&zone->list, &it->list);

	spin_unlock(&zone_alloc->lock);

	*puid = zone->uid;

	return 0;
}

/* Should be called under a lock */
static void __mlx4_zone_remove_one_entry(struct mlx4_zone_entry *entry)
{
	struct mlx4_zone_allocator *zone_alloc = entry->allocator;

	if (!list_empty(&entry->prio_list)) {
		/* Check if we need to add an alternative node to the prio list */
		if (!list_is_last(&entry->list, &zone_alloc->entries)) {

Annotation

Implementation Notes