drivers/infiniband/sw/rxe/rxe_odp.c

Source file repositories/reference/linux-study-clean/drivers/infiniband/sw/rxe/rxe_odp.c

File Facts

System
Linux kernel
Corpus path
drivers/infiniband/sw/rxe/rxe_odp.c
Extension
.c
Size
13550 bytes
Lines
579
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

struct prefetch_mr_work {
	struct work_struct work;
	u32 pf_flags;
	u32 num_sge;
	struct {
		u64 io_virt;
		struct rxe_mr *mr;
		size_t length;
	} frags[];
};

static void rxe_ib_prefetch_mr_work(struct work_struct *w)
{
	struct prefetch_mr_work *work =
		container_of(w, struct prefetch_mr_work, work);
	int ret;
	u32 i;

	/*
	 * We rely on IB/core that work is executed
	 * if we have num_sge != 0 only.
	 */
	WARN_ON(!work->num_sge);
	for (i = 0; i < work->num_sge; ++i) {
		struct ib_umem_odp *umem_odp;

		ret = rxe_odp_do_pagefault_and_lock(work->frags[i].mr,
						    work->frags[i].io_virt,
						    work->frags[i].length,
						    work->pf_flags);
		if (ret < 0) {
			rxe_dbg_mr(work->frags[i].mr,
				   "failed to prefetch the mr\n");
			goto deref;
		}

		umem_odp = to_ib_umem_odp(work->frags[i].mr->umem);
		mutex_unlock(&umem_odp->umem_mutex);

deref:
		rxe_put(work->frags[i].mr);
	}

	kvfree(work);
}

static int rxe_ib_prefetch_sg_list(struct ib_pd *ibpd,
				   enum ib_uverbs_advise_mr_advice advice,
				   u32 pf_flags, struct ib_sge *sg_list,
				   u32 num_sge)
{
	struct rxe_pd *pd = container_of(ibpd, struct rxe_pd, ibpd);
	int ret = 0;
	u32 i;

	for (i = 0; i < num_sge; ++i) {
		struct rxe_mr *mr;
		struct ib_umem_odp *umem_odp;

		mr = lookup_mr(pd, IB_ACCESS_LOCAL_WRITE,
			       sg_list[i].lkey, RXE_LOOKUP_LOCAL);

		if (!mr) {
			rxe_dbg_pd(pd, "mr with lkey %x not found\n",
				   sg_list[i].lkey);
			return -EINVAL;
		}

		if (advice == IB_UVERBS_ADVISE_MR_ADVICE_PREFETCH_WRITE &&
		    !mr->umem->writable) {
			rxe_dbg_mr(mr, "missing write permission\n");
			rxe_put(mr);
			return -EPERM;
		}

		ret = rxe_odp_do_pagefault_and_lock(
			mr, sg_list[i].addr, sg_list[i].length, pf_flags);
		if (ret < 0) {
			rxe_dbg_mr(mr, "failed to prefetch the mr\n");
			rxe_put(mr);
			return ret;
		}

		umem_odp = to_ib_umem_odp(mr->umem);
		mutex_unlock(&umem_odp->umem_mutex);

		rxe_put(mr);
	}

	return 0;

Annotation

Implementation Notes