drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_buddy.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_buddy.c
Extension
.c
Size
4164 bytes
Lines
165
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

// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2004 Topspin Communications. All rights reserved.
 * Copyright (c) 2005 - 2008 Mellanox Technologies. All rights reserved.
 * Copyright (c) 2006 - 2007 Cisco Systems, Inc. All rights reserved.
 * Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved.
 */

#include "dr_types.h"

int mlx5dr_buddy_init(struct mlx5dr_icm_buddy_mem *buddy,
		      unsigned int max_order)
{
	int i;

	buddy->max_order = max_order;

	INIT_LIST_HEAD(&buddy->list_node);

	buddy->bitmap = kzalloc_objs(*buddy->bitmap, buddy->max_order + 1);
	buddy->num_free = kzalloc_objs(*buddy->num_free, buddy->max_order + 1);

	if (!buddy->bitmap || !buddy->num_free)
		goto err_free_all;

	/* Allocating max_order bitmaps, one for each order */

	for (i = 0; i <= buddy->max_order; ++i) {
		unsigned int size = 1 << (buddy->max_order - i);

		buddy->bitmap[i] = bitmap_zalloc(size, GFP_KERNEL);
		if (!buddy->bitmap[i])
			goto err_out_free_each_bit_per_order;
	}

	/* In the beginning, we have only one order that is available for
	 * use (the biggest one), so mark the first bit in both bitmaps.
	 */

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

	buddy->num_free[buddy->max_order] = 1;

	return 0;

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

err_free_all:
	kfree(buddy->num_free);
	kfree(buddy->bitmap);
	return -ENOMEM;
}

void mlx5dr_buddy_cleanup(struct mlx5dr_icm_buddy_mem *buddy)
{
	int i;

	list_del(&buddy->list_node);

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

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

static int dr_buddy_find_free_seg(struct mlx5dr_icm_buddy_mem *buddy,
				  unsigned int start_order,
				  unsigned int *segment,
				  unsigned int *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;
	}

Annotation

Implementation Notes