blob: 45fb646a6d362469c3be88e298cdb2240f6e49ff [file] [log] [blame]
Chuck Levera0ce85f2015-03-30 14:34:21 -04001/*
2 * Copyright (c) 2015 Oracle. All rights reserved.
3 * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved.
4 */
5
6/* Lightweight memory registration using Fast Memory Regions (FMR).
7 * Referred to sometimes as MTHCAFMR mode.
8 *
9 * FMR uses synchronous memory registration and deregistration.
10 * FMR registration is known to be fast, but FMR deregistration
11 * can take tens of usecs to complete.
12 */
13
14#include "xprt_rdma.h"
15
16#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
17# define RPCDBG_FACILITY RPCDBG_TRANS
18#endif
19
Chuck Lever1c9351e2015-03-30 14:34:30 -040020/* Maximum scatter/gather per FMR */
21#define RPCRDMA_MAX_FMR_SGES (64)
22
23/* FMR mode conveys up to 64 pages of payload per chunk segment.
24 */
25static size_t
26fmr_op_maxpages(struct rpcrdma_xprt *r_xprt)
27{
28 return min_t(unsigned int, RPCRDMA_MAX_DATA_SEGS,
29 rpcrdma_max_segments(r_xprt) * RPCRDMA_MAX_FMR_SGES);
30}
31
Chuck Lever9c1b4d72015-03-30 14:34:39 -040032/* Use the ib_map_phys_fmr() verb to register a memory region
33 * for remote access via RDMA READ or RDMA WRITE.
34 */
35static int
36fmr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
37 int nsegs, bool writing)
38{
39 struct rpcrdma_ia *ia = &r_xprt->rx_ia;
40 struct rpcrdma_mr_seg *seg1 = seg;
41 struct rpcrdma_mw *mw = seg1->rl_mw;
42 u64 physaddrs[RPCRDMA_MAX_DATA_SEGS];
43 int len, pageoff, i, rc;
44
45 pageoff = offset_in_page(seg1->mr_offset);
46 seg1->mr_offset -= pageoff; /* start of page */
47 seg1->mr_len += pageoff;
48 len = -pageoff;
49 if (nsegs > RPCRDMA_MAX_FMR_SGES)
50 nsegs = RPCRDMA_MAX_FMR_SGES;
51 for (i = 0; i < nsegs;) {
52 rpcrdma_map_one(ia, seg, writing);
53 physaddrs[i] = seg->mr_dma;
54 len += seg->mr_len;
55 ++seg;
56 ++i;
57 /* Check for holes */
58 if ((i < nsegs && offset_in_page(seg->mr_offset)) ||
59 offset_in_page((seg-1)->mr_offset + (seg-1)->mr_len))
60 break;
61 }
62
63 rc = ib_map_phys_fmr(mw->r.fmr, physaddrs, i, seg1->mr_dma);
64 if (rc)
65 goto out_maperr;
66
67 seg1->mr_rkey = mw->r.fmr->rkey;
68 seg1->mr_base = seg1->mr_dma + pageoff;
69 seg1->mr_nsegs = i;
70 seg1->mr_len = len;
71 return i;
72
73out_maperr:
74 dprintk("RPC: %s: ib_map_phys_fmr %u@0x%llx+%i (%d) status %i\n",
75 __func__, len, (unsigned long long)seg1->mr_dma,
76 pageoff, i, rc);
77 while (i--)
78 rpcrdma_unmap_one(ia, --seg);
79 return rc;
80}
81
Chuck Levera0ce85f2015-03-30 14:34:21 -040082const struct rpcrdma_memreg_ops rpcrdma_fmr_memreg_ops = {
Chuck Lever9c1b4d72015-03-30 14:34:39 -040083 .ro_map = fmr_op_map,
Chuck Lever1c9351e2015-03-30 14:34:30 -040084 .ro_maxpages = fmr_op_maxpages,
Chuck Levera0ce85f2015-03-30 14:34:21 -040085 .ro_displayname = "fmr",
86};