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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx4/icm.c
Extension
.c
Size
11946 bytes
Lines
493
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 (!chunk) {
			chunk = kzalloc_node(sizeof(*chunk),
					     gfp_mask & ~(__GFP_HIGHMEM |
							  __GFP_NOWARN),
					     dev->numa_node);
			if (!chunk) {
				chunk = kzalloc_obj(*chunk,
						    gfp_mask & ~(__GFP_HIGHMEM | __GFP_NOWARN));
				if (!chunk)
					goto fail;
			}
			chunk->coherent = coherent;

			if (!coherent)
				sg_init_table(chunk->sg, MLX4_ICM_CHUNK_LEN);
			list_add_tail(&chunk->list, &icm->chunk_list);
		}

		while (1 << cur_order > npages)
			--cur_order;

		mask = gfp_mask;
		if (cur_order)
			mask &= ~__GFP_DIRECT_RECLAIM;

		if (coherent)
			ret = mlx4_alloc_icm_coherent(&dev->persist->pdev->dev,
						&chunk->buf[chunk->npages],
						cur_order, mask);
		else
			ret = mlx4_alloc_icm_pages(&chunk->sg[chunk->npages],
						   cur_order, mask,
						   dev->numa_node);

		if (ret) {
			if (--cur_order < 0)
				goto fail;
			else
				continue;
		}

		++chunk->npages;

		if (coherent)
			++chunk->nsg;
		else if (chunk->npages == MLX4_ICM_CHUNK_LEN) {
			chunk->nsg = dma_map_sg(&dev->persist->pdev->dev,
						chunk->sg, chunk->npages,
						DMA_BIDIRECTIONAL);

			if (!chunk->nsg)
				goto fail;
		}

		if (chunk->npages == MLX4_ICM_CHUNK_LEN)
			chunk = NULL;

		npages -= 1 << cur_order;
	}

	if (!coherent && chunk) {
		chunk->nsg = dma_map_sg(&dev->persist->pdev->dev, chunk->sg,
					chunk->npages, DMA_BIDIRECTIONAL);

		if (!chunk->nsg)
			goto fail;
	}

	return icm;

fail:
	mlx4_free_icm(dev, icm, coherent);
	return NULL;
}

static int mlx4_MAP_ICM(struct mlx4_dev *dev, struct mlx4_icm *icm, u64 virt)
{
	return mlx4_map_cmd(dev, MLX4_CMD_MAP_ICM, icm, virt);
}

static int mlx4_UNMAP_ICM(struct mlx4_dev *dev, u64 virt, u32 page_count)
{
	return mlx4_cmd(dev, virt, page_count, 0, MLX4_CMD_UNMAP_ICM,
			MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
}

int mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm)
{
	return mlx4_map_cmd(dev, MLX4_CMD_MAP_ICM_AUX, icm, -1);
}

Annotation

Implementation Notes