aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2016-11-29 10:52:24 -0500
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2016-11-29 16:45:44 -0500
commit5e9fc6a06bba9e6821ce964067fcf4401496bc29 (patch)
treea6878d11ea8b32ae4b6da2977ecb72b74c6fd9d7
parent8d38de65644d900199f035277aa5f3da4aa9fc17 (diff)
xprtrdma: Support for SG_GAP devices
Some devices (such as the Mellanox CX-4) can register, under a single R_key, a set of memory regions that are not contiguous. When this is done, all the segments in a Reply list, say, can then be invalidated in a single LocalInv Work Request (or via Remote Invalidation, which can invalidate exactly one R_key when completing a Receive). This means a single FastReg WR is used to register, and one or zero LocalInv WRs can invalidate, the memory involved with RDMA transfers on behalf of an RPC. In addition, xprtrdma constructs some Reply chunks from three or more segments. By registering them with SG_GAP, only one segment is needed for the Reply chunk, allowing the whole chunk to be invalidated remotely. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
-rw-r--r--net/sunrpc/xprtrdma/frwr_ops.c20
-rw-r--r--net/sunrpc/xprtrdma/xprt_rdma.h1
2 files changed, 14 insertions, 7 deletions
diff --git a/net/sunrpc/xprtrdma/frwr_ops.c b/net/sunrpc/xprtrdma/frwr_ops.c
index adbf52c6df83..e99bf6180136 100644
--- a/net/sunrpc/xprtrdma/frwr_ops.c
+++ b/net/sunrpc/xprtrdma/frwr_ops.c
@@ -101,7 +101,7 @@ frwr_op_init_mr(struct rpcrdma_ia *ia, struct rpcrdma_mw *r)
101 struct rpcrdma_frmr *f = &r->frmr; 101 struct rpcrdma_frmr *f = &r->frmr;
102 int rc; 102 int rc;
103 103
104 f->fr_mr = ib_alloc_mr(ia->ri_pd, IB_MR_TYPE_MEM_REG, depth); 104 f->fr_mr = ib_alloc_mr(ia->ri_pd, ia->ri_mrtype, depth);
105 if (IS_ERR(f->fr_mr)) 105 if (IS_ERR(f->fr_mr))
106 goto out_mr_err; 106 goto out_mr_err;
107 107
@@ -157,7 +157,7 @@ __frwr_reset_mr(struct rpcrdma_ia *ia, struct rpcrdma_mw *r)
157 return rc; 157 return rc;
158 } 158 }
159 159
160 f->fr_mr = ib_alloc_mr(ia->ri_pd, IB_MR_TYPE_MEM_REG, 160 f->fr_mr = ib_alloc_mr(ia->ri_pd, ia->ri_mrtype,
161 ia->ri_max_frmr_depth); 161 ia->ri_max_frmr_depth);
162 if (IS_ERR(f->fr_mr)) { 162 if (IS_ERR(f->fr_mr)) {
163 pr_warn("rpcrdma: ib_alloc_mr status %ld, frwr %p orphaned\n", 163 pr_warn("rpcrdma: ib_alloc_mr status %ld, frwr %p orphaned\n",
@@ -210,11 +210,16 @@ static int
210frwr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep, 210frwr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep,
211 struct rpcrdma_create_data_internal *cdata) 211 struct rpcrdma_create_data_internal *cdata)
212{ 212{
213 struct ib_device_attr *attrs = &ia->ri_device->attrs;
213 int depth, delta; 214 int depth, delta;
214 215
216 ia->ri_mrtype = IB_MR_TYPE_MEM_REG;
217 if (attrs->device_cap_flags & IB_DEVICE_SG_GAPS_REG)
218 ia->ri_mrtype = IB_MR_TYPE_SG_GAPS;
219
215 ia->ri_max_frmr_depth = 220 ia->ri_max_frmr_depth =
216 min_t(unsigned int, RPCRDMA_MAX_DATA_SEGS, 221 min_t(unsigned int, RPCRDMA_MAX_DATA_SEGS,
217 ia->ri_device->attrs.max_fast_reg_page_list_len); 222 attrs->max_fast_reg_page_list_len);
218 dprintk("RPC: %s: device's max FR page list len = %u\n", 223 dprintk("RPC: %s: device's max FR page list len = %u\n",
219 __func__, ia->ri_max_frmr_depth); 224 __func__, ia->ri_max_frmr_depth);
220 225
@@ -241,8 +246,8 @@ frwr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep,
241 } 246 }
242 247
243 ep->rep_attr.cap.max_send_wr *= depth; 248 ep->rep_attr.cap.max_send_wr *= depth;
244 if (ep->rep_attr.cap.max_send_wr > ia->ri_device->attrs.max_qp_wr) { 249 if (ep->rep_attr.cap.max_send_wr > attrs->max_qp_wr) {
245 cdata->max_requests = ia->ri_device->attrs.max_qp_wr / depth; 250 cdata->max_requests = attrs->max_qp_wr / depth;
246 if (!cdata->max_requests) 251 if (!cdata->max_requests)
247 return -EINVAL; 252 return -EINVAL;
248 ep->rep_attr.cap.max_send_wr = cdata->max_requests * 253 ep->rep_attr.cap.max_send_wr = cdata->max_requests *
@@ -348,6 +353,7 @@ frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
348 int nsegs, bool writing, struct rpcrdma_mw **out) 353 int nsegs, bool writing, struct rpcrdma_mw **out)
349{ 354{
350 struct rpcrdma_ia *ia = &r_xprt->rx_ia; 355 struct rpcrdma_ia *ia = &r_xprt->rx_ia;
356 bool holes_ok = ia->ri_mrtype == IB_MR_TYPE_SG_GAPS;
351 struct rpcrdma_mw *mw; 357 struct rpcrdma_mw *mw;
352 struct rpcrdma_frmr *frmr; 358 struct rpcrdma_frmr *frmr;
353 struct ib_mr *mr; 359 struct ib_mr *mr;
@@ -383,8 +389,8 @@ frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
383 389
384 ++seg; 390 ++seg;
385 ++i; 391 ++i;
386 392 if (holes_ok)
387 /* Check for holes */ 393 continue;
388 if ((i < nsegs && offset_in_page(seg->mr_offset)) || 394 if ((i < nsegs && offset_in_page(seg->mr_offset)) ||
389 offset_in_page((seg-1)->mr_offset + (seg-1)->mr_len)) 395 offset_in_page((seg-1)->mr_offset + (seg-1)->mr_len))
390 break; 396 break;
diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h
index f6ae1b22da47..b8424fa47d29 100644
--- a/net/sunrpc/xprtrdma/xprt_rdma.h
+++ b/net/sunrpc/xprtrdma/xprt_rdma.h
@@ -75,6 +75,7 @@ struct rpcrdma_ia {
75 unsigned int ri_max_inline_write; 75 unsigned int ri_max_inline_write;
76 unsigned int ri_max_inline_read; 76 unsigned int ri_max_inline_read;
77 bool ri_reminv_expected; 77 bool ri_reminv_expected;
78 enum ib_mr_type ri_mrtype;
78 struct ib_qp_attr ri_qp_attr; 79 struct ib_qp_attr ri_qp_attr;
79 struct ib_qp_init_attr ri_qp_init_attr; 80 struct ib_qp_init_attr ri_qp_init_attr;
80}; 81};