drivers/net/ethernet/broadcom/bnge/bnge_rmem.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/broadcom/bnge/bnge_rmem.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/broadcom/bnge/bnge_rmem.c
Extension
.c
Size
12250 bytes
Lines
483
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 (rmem->nr_pages > 1 || rmem->depth > 0) {
			if (i == rmem->nr_pages - 2 &&
			    (rmem->flags & BNGE_RMEM_RING_PTE_FLAG))
				extra_bits |= PTU_PTE_NEXT_TO_LAST;
			else if (i == rmem->nr_pages - 1 &&
				 (rmem->flags & BNGE_RMEM_RING_PTE_FLAG))
				extra_bits |= PTU_PTE_LAST;
			rmem->pg_tbl[i] =
				cpu_to_le64(rmem->dma_arr[i] | extra_bits);
		}
	}

	if (rmem->vmem_size) {
		*rmem->vmem = vzalloc(rmem->vmem_size);
		if (!(*rmem->vmem))
			goto err_free_ring;
	}
	return 0;

err_free_ring:
	bnge_free_ring(bd, rmem);
	return -ENOMEM;
}

static int bnge_alloc_ctx_one_lvl(struct bnge_dev *bd,
				  struct bnge_ctx_pg_info *ctx_pg)
{
	struct bnge_ring_mem_info *rmem = &ctx_pg->ring_mem;

	rmem->page_size = BNGE_PAGE_SIZE;
	rmem->pg_arr = ctx_pg->ctx_pg_arr;
	rmem->dma_arr = ctx_pg->ctx_dma_arr;
	rmem->flags = BNGE_RMEM_VALID_PTE_FLAG;
	if (rmem->depth >= 1)
		rmem->flags |= BNGE_RMEM_USE_FULL_PAGE_FLAG;
	return bnge_alloc_ring(bd, rmem);
}

static int bnge_alloc_ctx_pg_tbls(struct bnge_dev *bd,
				  struct bnge_ctx_pg_info *ctx_pg, u32 mem_size,
				  u8 depth, struct bnge_ctx_mem_type *ctxm)
{
	struct bnge_ring_mem_info *rmem = &ctx_pg->ring_mem;
	int rc;

	if (!mem_size)
		return -EINVAL;

	ctx_pg->nr_pages = DIV_ROUND_UP(mem_size, BNGE_PAGE_SIZE);
	if (ctx_pg->nr_pages > MAX_CTX_TOTAL_PAGES) {
		ctx_pg->nr_pages = 0;
		return -EINVAL;
	}
	if (ctx_pg->nr_pages > MAX_CTX_PAGES || depth > 1) {
		int nr_tbls, i;

		rmem->depth = 2;
		ctx_pg->ctx_pg_tbl = kzalloc_objs(ctx_pg, MAX_CTX_PAGES);
		if (!ctx_pg->ctx_pg_tbl)
			return -ENOMEM;
		nr_tbls = DIV_ROUND_UP(ctx_pg->nr_pages, MAX_CTX_PAGES);
		rmem->nr_pages = nr_tbls;
		rc = bnge_alloc_ctx_one_lvl(bd, ctx_pg);
		if (rc)
			return rc;
		for (i = 0; i < nr_tbls; i++) {
			struct bnge_ctx_pg_info *pg_tbl;

			pg_tbl = kzalloc_obj(*pg_tbl);
			if (!pg_tbl)
				return -ENOMEM;
			ctx_pg->ctx_pg_tbl[i] = pg_tbl;
			rmem = &pg_tbl->ring_mem;
			rmem->pg_tbl = ctx_pg->ctx_pg_arr[i];
			rmem->dma_pg_tbl = ctx_pg->ctx_dma_arr[i];
			rmem->depth = 1;
			rmem->nr_pages = MAX_CTX_PAGES;
			rmem->ctx_mem = ctxm;
			if (i == (nr_tbls - 1)) {
				int rem = ctx_pg->nr_pages % MAX_CTX_PAGES;

				if (rem)
					rmem->nr_pages = rem;
			}
			rc = bnge_alloc_ctx_one_lvl(bd, pg_tbl);
			if (rc)
				break;
		}
	} else {
		rmem->nr_pages = DIV_ROUND_UP(mem_size, BNGE_PAGE_SIZE);

Annotation

Implementation Notes