Commit bd7ed1d1 authored by Tom Talpey's avatar Tom Talpey Committed by Trond Myklebust

RPC/RDMA: check selected memory registration mode at runtime.

At transport creation, check for, and use, any local dma lkey.
Then, check that the selected memory registration mode is in fact
supported by the RDMA adapter selected for the mount. Fall back
to best alternative if not.
Signed-off-by: default avatarTom Talpey <talpey@netapp.com>
Acked-by: default avatarTom Tucker <tom@opengridcomputing.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent fe9053b3
...@@ -423,7 +423,8 @@ rpcrdma_clean_cq(struct ib_cq *cq) ...@@ -423,7 +423,8 @@ rpcrdma_clean_cq(struct ib_cq *cq)
int int
rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg) rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg)
{ {
int rc; int rc, mem_priv;
struct ib_device_attr devattr;
struct rpcrdma_ia *ia = &xprt->rx_ia; struct rpcrdma_ia *ia = &xprt->rx_ia;
init_completion(&ia->ri_done); init_completion(&ia->ri_done);
...@@ -442,6 +443,53 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg) ...@@ -442,6 +443,53 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg)
goto out2; goto out2;
} }
/*
* Query the device to determine if the requested memory
* registration strategy is supported. If it isn't, set the
* strategy to a globally supported model.
*/
rc = ib_query_device(ia->ri_id->device, &devattr);
if (rc) {
dprintk("RPC: %s: ib_query_device failed %d\n",
__func__, rc);
goto out2;
}
if (devattr.device_cap_flags & IB_DEVICE_LOCAL_DMA_LKEY) {
ia->ri_have_dma_lkey = 1;
ia->ri_dma_lkey = ia->ri_id->device->local_dma_lkey;
}
switch (memreg) {
case RPCRDMA_MEMWINDOWS:
case RPCRDMA_MEMWINDOWS_ASYNC:
if (!(devattr.device_cap_flags & IB_DEVICE_MEM_WINDOW)) {
dprintk("RPC: %s: MEMWINDOWS registration "
"specified but not supported by adapter, "
"using slower RPCRDMA_REGISTER\n",
__func__);
memreg = RPCRDMA_REGISTER;
}
break;
case RPCRDMA_MTHCAFMR:
if (!ia->ri_id->device->alloc_fmr) {
#if RPCRDMA_PERSISTENT_REGISTRATION
dprintk("RPC: %s: MTHCAFMR registration "
"specified but not supported by adapter, "
"using riskier RPCRDMA_ALLPHYSICAL\n",
__func__);
memreg = RPCRDMA_ALLPHYSICAL;
#else
dprintk("RPC: %s: MTHCAFMR registration "
"specified but not supported by adapter, "
"using slower RPCRDMA_REGISTER\n",
__func__);
memreg = RPCRDMA_REGISTER;
#endif
}
break;
}
/* /*
* Optionally obtain an underlying physical identity mapping in * Optionally obtain an underlying physical identity mapping in
* order to do a memory window-based bind. This base registration * order to do a memory window-based bind. This base registration
...@@ -450,22 +498,27 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg) ...@@ -450,22 +498,27 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg)
* revoked after the corresponding completion similar to a storage * revoked after the corresponding completion similar to a storage
* adapter. * adapter.
*/ */
if (memreg > RPCRDMA_REGISTER) { switch (memreg) {
int mem_priv = IB_ACCESS_LOCAL_WRITE; case RPCRDMA_BOUNCEBUFFERS:
switch (memreg) { case RPCRDMA_REGISTER:
break;
#if RPCRDMA_PERSISTENT_REGISTRATION #if RPCRDMA_PERSISTENT_REGISTRATION
case RPCRDMA_ALLPHYSICAL: case RPCRDMA_ALLPHYSICAL:
mem_priv |= IB_ACCESS_REMOTE_WRITE; mem_priv = IB_ACCESS_LOCAL_WRITE |
mem_priv |= IB_ACCESS_REMOTE_READ; IB_ACCESS_REMOTE_WRITE |
break; IB_ACCESS_REMOTE_READ;
goto register_setup;
#endif #endif
case RPCRDMA_MEMWINDOWS_ASYNC: case RPCRDMA_MEMWINDOWS_ASYNC:
case RPCRDMA_MEMWINDOWS: case RPCRDMA_MEMWINDOWS:
mem_priv |= IB_ACCESS_MW_BIND; mem_priv = IB_ACCESS_LOCAL_WRITE |
break; IB_ACCESS_MW_BIND;
default: goto register_setup;
case RPCRDMA_MTHCAFMR:
if (ia->ri_have_dma_lkey)
break; break;
} mem_priv = IB_ACCESS_LOCAL_WRITE;
register_setup:
ia->ri_bind_mem = ib_get_dma_mr(ia->ri_pd, mem_priv); ia->ri_bind_mem = ib_get_dma_mr(ia->ri_pd, mem_priv);
if (IS_ERR(ia->ri_bind_mem)) { if (IS_ERR(ia->ri_bind_mem)) {
printk(KERN_ALERT "%s: ib_get_dma_mr for " printk(KERN_ALERT "%s: ib_get_dma_mr for "
...@@ -475,7 +528,15 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg) ...@@ -475,7 +528,15 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg)
memreg = RPCRDMA_REGISTER; memreg = RPCRDMA_REGISTER;
ia->ri_bind_mem = NULL; ia->ri_bind_mem = NULL;
} }
break;
default:
printk(KERN_ERR "%s: invalid memory registration mode %d\n",
__func__, memreg);
rc = -EINVAL;
goto out2;
} }
dprintk("RPC: %s: memory registration strategy is %d\n",
__func__, memreg);
/* Else will do memory reg/dereg for each chunk */ /* Else will do memory reg/dereg for each chunk */
ia->ri_memreg_strategy = memreg; ia->ri_memreg_strategy = memreg;
...@@ -1248,7 +1309,11 @@ rpcrdma_register_internal(struct rpcrdma_ia *ia, void *va, int len, ...@@ -1248,7 +1309,11 @@ rpcrdma_register_internal(struct rpcrdma_ia *ia, void *va, int len,
va, len, DMA_BIDIRECTIONAL); va, len, DMA_BIDIRECTIONAL);
iov->length = len; iov->length = len;
if (ia->ri_bind_mem != NULL) { if (ia->ri_have_dma_lkey) {
*mrp = NULL;
iov->lkey = ia->ri_dma_lkey;
return 0;
} else if (ia->ri_bind_mem != NULL) {
*mrp = NULL; *mrp = NULL;
iov->lkey = ia->ri_bind_mem->lkey; iov->lkey = ia->ri_bind_mem->lkey;
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment