drivers/infiniband/hw/bng_re/bng_res.c

Source file repositories/reference/linux-study-clean/drivers/infiniband/hw/bng_re/bng_res.c

File Facts

System
Linux kernel
Corpus path
drivers/infiniband/hw/bng_re/bng_res.c
Extension
.c
Size
6987 bytes
Lines
280
Domain
Driver Families
Bucket
drivers/infiniband
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 (npages > MAX_PBL_LVL_1_PGS) {
			u32 flag = PTU_PTE_VALID;
			/* 2 levels of indirection */
			npbl = npages >> MAX_PBL_LVL_1_PGS_SHIFT;
			if (npages % BIT(MAX_PBL_LVL_1_PGS_SHIFT))
				npbl++;
			npde = npbl >> MAX_PDL_LVL_SHIFT;
			if (npbl % BIT(MAX_PDL_LVL_SHIFT))
				npde++;
			/* Alloc PDE pages */
			sginfo.pgsize = npde * pg_size;
			sginfo.npages = 1;
			rc = bng_alloc_pbl(res, &hwq->pbl[BNG_PBL_LVL_0], &sginfo);
			if (rc)
				goto fail;

			/* Alloc PBL pages */
			sginfo.npages = npbl;
			sginfo.pgsize = PAGE_SIZE;
			rc = bng_alloc_pbl(res, &hwq->pbl[BNG_PBL_LVL_1], &sginfo);
			if (rc)
				goto fail;
			/* Fill PDL with PBL page pointers */
			dst_virt_ptr =
				(dma_addr_t **)hwq->pbl[BNG_PBL_LVL_0].pg_arr;
			src_phys_ptr = hwq->pbl[BNG_PBL_LVL_1].pg_map_arr;
			for (i = 0; i < hwq->pbl[BNG_PBL_LVL_1].pg_count; i++)
				dst_virt_ptr[0][i] = src_phys_ptr[i] | flag;

			/* Alloc or init PTEs */
			rc = bng_alloc_pbl(res, &hwq->pbl[BNG_PBL_LVL_2],
					 hwq_attr->sginfo);
			if (rc)
				goto fail;
			hwq->level = BNG_PBL_LVL_2;
			if (hwq_attr->sginfo->nopte)
				goto done;
			/* Fill PBLs with PTE pointers */
			dst_virt_ptr =
				(dma_addr_t **)hwq->pbl[BNG_PBL_LVL_1].pg_arr;
			src_phys_ptr = hwq->pbl[BNG_PBL_LVL_2].pg_map_arr;
			for (i = 0; i < hwq->pbl[BNG_PBL_LVL_2].pg_count; i++) {
				dst_virt_ptr[PTR_PG(i)][PTR_IDX(i)] =
					src_phys_ptr[i] | PTU_PTE_VALID;
			}
			if (hwq_attr->type == BNG_HWQ_TYPE_QUEUE) {
				/* Find the last pg of the size */
				i = hwq->pbl[BNG_PBL_LVL_2].pg_count;
				dst_virt_ptr[PTR_PG(i - 1)][PTR_IDX(i - 1)] |=
								  PTU_PTE_LAST;
				if (i > 1)
					dst_virt_ptr[PTR_PG(i - 2)]
						    [PTR_IDX(i - 2)] |=
						    PTU_PTE_NEXT_TO_LAST;
			}
		} else { /* pages < 512 npbl = 1, npde = 0 */
			u32 flag = PTU_PTE_VALID;

			/* 1 level of indirection */
			npbl = npages >> MAX_PBL_LVL_1_PGS_SHIFT;
			if (npages % BIT(MAX_PBL_LVL_1_PGS_SHIFT))
				npbl++;
			sginfo.npages = npbl;
			sginfo.pgsize = PAGE_SIZE;
			/* Alloc PBL page */
			rc = bng_alloc_pbl(res, &hwq->pbl[BNG_PBL_LVL_0], &sginfo);
			if (rc)
				goto fail;
			/* Alloc or init  PTEs */
			rc = bng_alloc_pbl(res, &hwq->pbl[BNG_PBL_LVL_1],
					 hwq_attr->sginfo);
			if (rc)
				goto fail;
			hwq->level = BNG_PBL_LVL_1;
			if (hwq_attr->sginfo->nopte)
				goto done;
			/* Fill PBL with PTE pointers */
			dst_virt_ptr =
				(dma_addr_t **)hwq->pbl[BNG_PBL_LVL_0].pg_arr;
			src_phys_ptr = hwq->pbl[BNG_PBL_LVL_1].pg_map_arr;
			for (i = 0; i < hwq->pbl[BNG_PBL_LVL_1].pg_count; i++)
				dst_virt_ptr[PTR_PG(i)][PTR_IDX(i)] =
					src_phys_ptr[i] | flag;
			if (hwq_attr->type == BNG_HWQ_TYPE_QUEUE) {
				/* Find the last pg of the size */
				i = hwq->pbl[BNG_PBL_LVL_1].pg_count;
				dst_virt_ptr[PTR_PG(i - 1)][PTR_IDX(i - 1)] |=
								  PTU_PTE_LAST;
				if (i > 1)
					dst_virt_ptr[PTR_PG(i - 2)]

Annotation

Implementation Notes