net/sunrpc/xprtrdma/svc_rdma_sendto.c

Source file repositories/reference/linux-study-clean/net/sunrpc/xprtrdma/svc_rdma_sendto.c

File Facts

System
Linux kernel
Corpus path
net/sunrpc/xprtrdma/svc_rdma_sendto.c
Extension
.c
Size
36979 bytes
Lines
1240
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

struct svc_rdma_map_data {
	struct svcxprt_rdma		*md_rdma;
	struct svc_rdma_send_ctxt	*md_ctxt;
};

/**
 * svc_rdma_page_dma_map - DMA map one page
 * @data: pointer to arguments
 * @page: struct page to DMA map
 * @offset: offset into the page
 * @len: number of bytes to map
 *
 * Returns:
 *   %0 if DMA mapping was successful
 *   %-EIO if the page cannot be DMA mapped
 */
static int svc_rdma_page_dma_map(void *data, struct page *page,
				 unsigned long offset, unsigned int len)
{
	struct svc_rdma_map_data *args = data;
	struct svcxprt_rdma *rdma = args->md_rdma;
	struct svc_rdma_send_ctxt *ctxt = args->md_ctxt;
	struct ib_device *dev = rdma->sc_cm_id->device;
	dma_addr_t dma_addr;

	++ctxt->sc_cur_sge_no;

	dma_addr = ib_dma_map_page(dev, page, offset, len, DMA_TO_DEVICE);
	if (ib_dma_mapping_error(dev, dma_addr))
		goto out_maperr;

	trace_svcrdma_dma_map_page(&ctxt->sc_cid, dma_addr, len);
	ctxt->sc_sges[ctxt->sc_cur_sge_no].addr = dma_addr;
	ctxt->sc_sges[ctxt->sc_cur_sge_no].length = len;
	ctxt->sc_send_wr.num_sge++;
	return 0;

out_maperr:
	trace_svcrdma_dma_map_err(&ctxt->sc_cid, dma_addr, len);
	return -EIO;
}

/**
 * svc_rdma_iov_dma_map - DMA map an iovec
 * @data: pointer to arguments
 * @iov: kvec to DMA map
 *
 * ib_dma_map_page() is used here because svc_rdma_dma_unmap()
 * handles DMA-unmap and it uses ib_dma_unmap_page() exclusively.
 *
 * Returns:
 *   %0 if DMA mapping was successful
 *   %-EIO if the iovec cannot be DMA mapped
 */
static int svc_rdma_iov_dma_map(void *data, const struct kvec *iov)
{
	if (!iov->iov_len)
		return 0;
	return svc_rdma_page_dma_map(data, virt_to_page(iov->iov_base),
				     offset_in_page(iov->iov_base),
				     iov->iov_len);
}

/**
 * svc_rdma_xb_dma_map - DMA map all segments of an xdr_buf
 * @xdr: xdr_buf containing portion of an RPC message to transmit
 * @data: pointer to arguments
 *
 * Returns:
 *   %0 if DMA mapping was successful
 *   %-EIO if DMA mapping failed
 *
 * On failure, any DMA mappings that have been already done must be
 * unmapped by the caller.
 */
static int svc_rdma_xb_dma_map(const struct xdr_buf *xdr, void *data)
{
	unsigned int len, remaining;
	unsigned long pageoff;
	struct page **ppages;
	int ret;

	ret = svc_rdma_iov_dma_map(data, &xdr->head[0]);
	if (ret < 0)
		return ret;

	ppages = xdr->pages + (xdr->page_base >> PAGE_SHIFT);
	pageoff = offset_in_page(xdr->page_base);
	remaining = xdr->page_len;
	while (remaining) {

Annotation

Implementation Notes