drivers/infiniband/core/rw.c
Source file repositories/reference/linux-study-clean/drivers/infiniband/core/rw.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/infiniband/core/rw.c- Extension
.c- Size
- 34263 bytes
- Lines
- 1192
- Domain
- Driver Families
- Bucket
- drivers/infiniband
- 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.
- 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.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/memremap.hlinux/moduleparam.hlinux/slab.hlinux/pci-p2pdma.hrdma/mr_pool.hrdma/rw.h
Detected Declarations
function rdma_rw_can_use_mrfunction rdma_rw_io_needs_mrfunction rdma_rw_fr_page_list_lenfunction rdma_rw_inv_keyfunction rdma_rw_init_one_mrfunction rdma_rw_init_reg_wrfunction rdma_rw_init_mr_wrsfunction rdma_rw_init_mr_wrs_bvecfunction rdma_rw_init_map_wrsfunction rdma_rw_init_single_wrfunction rdma_rw_init_single_wr_bvecfunction rdma_rw_init_map_wrs_bvecfunction WQEsfunction rdma_rw_ctx_initfunction rdma_rw_ctx_init_bvecfunction rdma_rw_ctx_signature_initfunction rdma_rw_update_lkeyfunction rdma_rw_ctx_postfunction rdma_rw_ctx_destroyfunction rdma_rw_ctx_init_bvecfunction rdma_rw_ctx_destroy_signaturefunction rdma_rw_mr_factorfunction rdma_rw_max_send_wrfunction rdma_rw_init_qpfunction rdma_rw_init_mrsfunction rdma_rw_cleanup_mrsexport rdma_rw_ctx_initexport rdma_rw_ctx_init_bvecexport rdma_rw_ctx_signature_initexport rdma_rw_ctx_wrsexport rdma_rw_ctx_postexport rdma_rw_ctx_destroyexport rdma_rw_ctx_destroy_bvecexport rdma_rw_ctx_destroy_signatureexport rdma_rw_mr_factorexport rdma_rw_max_send_wr
Annotated Snippet
if (nents >= nr_bvec) {
ret = -EINVAL;
goto out_free_sgl;
}
sg_set_page(sg, bv.bv_page, bv.bv_len, bv.bv_offset);
bvec_iter_advance(bvecs, iter, bv.bv_len);
nents++;
}
sg_mark_end(sg_last(ctx->reg[0].sgt.sgl, nents));
ctx->reg[0].sgt.orig_nents = nents;
/* DMA map the scatterlist */
ret = ib_dma_map_sgtable_attrs(dev, &ctx->reg[0].sgt, dir, 0);
if (ret)
goto out_free_sgl;
ctx->nr_ops = DIV_ROUND_UP(ctx->reg[0].sgt.nents, pages_per_mr);
sg = ctx->reg[0].sgt.sgl;
nents = ctx->reg[0].sgt.nents;
for (i = 0; i < ctx->nr_ops; i++) {
struct rdma_rw_reg_ctx *reg = &ctx->reg[i];
u32 sge_cnt = min(nents, pages_per_mr);
ret = rdma_rw_init_one_mr(qp, port_num, reg, sg, sge_cnt, 0);
if (ret < 0)
goto out_free_mrs;
count += ret;
count += rdma_rw_init_reg_wr(reg, prev, qp, port_num,
remote_addr, rkey, dir);
remote_addr += reg->sge.length;
nents -= sge_cnt;
sg += sge_cnt;
prev = reg;
}
if (prev)
prev->wr.wr.next = NULL;
ctx->type = RDMA_RW_MR;
return count;
out_free_mrs:
while (--i >= 0)
ib_mr_pool_put(qp, &qp->rdma_mrs, ctx->reg[i].mr);
ib_dma_unmap_sgtable_attrs(dev, &ctx->reg[0].sgt, dir, 0);
out_free_sgl:
kfree(ctx->reg[0].sgt.sgl);
out_free_reg:
kfree(ctx->reg);
return ret;
}
static int rdma_rw_init_map_wrs(struct rdma_rw_ctx *ctx, struct ib_qp *qp,
struct scatterlist *sg, u32 sg_cnt, u32 offset,
u64 remote_addr, u32 rkey, enum dma_data_direction dir)
{
u32 max_sge = dir == DMA_TO_DEVICE ? qp->max_write_sge :
qp->max_read_sge;
struct ib_sge *sge;
u32 total_len = 0, i, j;
ctx->nr_ops = DIV_ROUND_UP(sg_cnt, max_sge);
ctx->map.sges = sge = kzalloc_objs(*sge, sg_cnt);
if (!ctx->map.sges)
goto out;
ctx->map.wrs = kzalloc_objs(*ctx->map.wrs, ctx->nr_ops);
if (!ctx->map.wrs)
goto out_free_sges;
for (i = 0; i < ctx->nr_ops; i++) {
struct ib_rdma_wr *rdma_wr = &ctx->map.wrs[i];
u32 nr_sge = min(sg_cnt, max_sge);
if (dir == DMA_TO_DEVICE)
rdma_wr->wr.opcode = IB_WR_RDMA_WRITE;
else
rdma_wr->wr.opcode = IB_WR_RDMA_READ;
rdma_wr->remote_addr = remote_addr + total_len;
rdma_wr->rkey = rkey;
rdma_wr->wr.num_sge = nr_sge;
rdma_wr->wr.sg_list = sge;
for (j = 0; j < nr_sge; j++, sg = sg_next(sg)) {
sge->addr = sg_dma_address(sg) + offset;
sge->length = sg_dma_len(sg) - offset;
sge->lkey = qp->pd->local_dma_lkey;
Annotation
- Immediate include surface: `linux/memremap.h`, `linux/moduleparam.h`, `linux/slab.h`, `linux/pci-p2pdma.h`, `rdma/mr_pool.h`, `rdma/rw.h`.
- Detected declarations: `function rdma_rw_can_use_mr`, `function rdma_rw_io_needs_mr`, `function rdma_rw_fr_page_list_len`, `function rdma_rw_inv_key`, `function rdma_rw_init_one_mr`, `function rdma_rw_init_reg_wr`, `function rdma_rw_init_mr_wrs`, `function rdma_rw_init_mr_wrs_bvec`, `function rdma_rw_init_map_wrs`, `function rdma_rw_init_single_wr`.
- Atlas domain: Driver Families / drivers/infiniband.
- Implementation status: integration implementation candidate.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.