xprtrdma: Allocate MRs on demand
[linux-2.6-block.git] / net / sunrpc / xprtrdma / fmr_ops.c
1 /*
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 /* Normal operation
15  *
16  * A Memory Region is prepared for RDMA READ or WRITE using the
17  * ib_map_phys_fmr verb (fmr_op_map). When the RDMA operation is
18  * finished, the Memory Region is unmapped using the ib_unmap_fmr
19  * verb (fmr_op_unmap).
20  */
21
22 #include "xprt_rdma.h"
23
24 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
25 # define RPCDBG_FACILITY        RPCDBG_TRANS
26 #endif
27
28 /* Maximum scatter/gather per FMR */
29 #define RPCRDMA_MAX_FMR_SGES    (64)
30
31 /* Access mode of externally registered pages */
32 enum {
33         RPCRDMA_FMR_ACCESS_FLAGS        = IB_ACCESS_REMOTE_WRITE |
34                                           IB_ACCESS_REMOTE_READ,
35 };
36
37 bool
38 fmr_is_supported(struct rpcrdma_ia *ia)
39 {
40         if (!ia->ri_device->alloc_fmr) {
41                 pr_info("rpcrdma: 'fmr' mode is not supported by device %s\n",
42                         ia->ri_device->name);
43                 return false;
44         }
45         return true;
46 }
47
48 static int
49 fmr_op_init_mr(struct rpcrdma_ia *ia, struct rpcrdma_mw *mw)
50 {
51         static struct ib_fmr_attr fmr_attr = {
52                 .max_pages      = RPCRDMA_MAX_FMR_SGES,
53                 .max_maps       = 1,
54                 .page_shift     = PAGE_SHIFT
55         };
56
57         mw->fmr.fm_physaddrs = kcalloc(RPCRDMA_MAX_FMR_SGES,
58                                        sizeof(u64), GFP_KERNEL);
59         if (!mw->fmr.fm_physaddrs)
60                 goto out_free;
61
62         mw->mw_sg = kcalloc(RPCRDMA_MAX_FMR_SGES,
63                             sizeof(*mw->mw_sg), GFP_KERNEL);
64         if (!mw->mw_sg)
65                 goto out_free;
66
67         sg_init_table(mw->mw_sg, RPCRDMA_MAX_FMR_SGES);
68
69         mw->fmr.fm_mr = ib_alloc_fmr(ia->ri_pd, RPCRDMA_FMR_ACCESS_FLAGS,
70                                      &fmr_attr);
71         if (IS_ERR(mw->fmr.fm_mr))
72                 goto out_fmr_err;
73
74         return 0;
75
76 out_fmr_err:
77         dprintk("RPC:       %s: ib_alloc_fmr returned %ld\n", __func__,
78                 PTR_ERR(mw->fmr.fm_mr));
79
80 out_free:
81         kfree(mw->mw_sg);
82         kfree(mw->fmr.fm_physaddrs);
83         return -ENOMEM;
84 }
85
86 static int
87 __fmr_unmap(struct rpcrdma_mw *mw)
88 {
89         LIST_HEAD(l);
90         int rc;
91
92         list_add(&mw->fmr.fm_mr->list, &l);
93         rc = ib_unmap_fmr(&l);
94         list_del_init(&mw->fmr.fm_mr->list);
95         return rc;
96 }
97
98 static void
99 fmr_op_release_mr(struct rpcrdma_mw *r)
100 {
101         LIST_HEAD(unmap_list);
102         int rc;
103
104         kfree(r->fmr.fm_physaddrs);
105         kfree(r->mw_sg);
106
107         /* In case this one was left mapped, try to unmap it
108          * to prevent dealloc_fmr from failing with EBUSY
109          */
110         rc = __fmr_unmap(r);
111         if (rc)
112                 pr_err("rpcrdma: final ib_unmap_fmr for %p failed %i\n",
113                        r, rc);
114
115         rc = ib_dealloc_fmr(r->fmr.fm_mr);
116         if (rc)
117                 pr_err("rpcrdma: final ib_dealloc_fmr for %p returned %i\n",
118                        r, rc);
119
120         kfree(r);
121 }
122
123 /* Reset of a single FMR.
124  */
125 static void
126 fmr_op_recover_mr(struct rpcrdma_mw *mw)
127 {
128         struct rpcrdma_xprt *r_xprt = mw->mw_xprt;
129         int rc;
130
131         /* ORDER: invalidate first */
132         rc = __fmr_unmap(mw);
133
134         /* ORDER: then DMA unmap */
135         ib_dma_unmap_sg(r_xprt->rx_ia.ri_device,
136                         mw->mw_sg, mw->mw_nents, mw->mw_dir);
137         if (rc) {
138                 pr_err("rpcrdma: FMR reset status %d, %p orphaned\n",
139                        rc, mw);
140                 r_xprt->rx_stats.mrs_orphaned++;
141                 return;
142         }
143
144         rpcrdma_put_mw(r_xprt, mw);
145         r_xprt->rx_stats.mrs_recovered++;
146 }
147
148 static int
149 fmr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep,
150             struct rpcrdma_create_data_internal *cdata)
151 {
152         rpcrdma_set_max_header_sizes(ia, cdata, max_t(unsigned int, 1,
153                                                       RPCRDMA_MAX_DATA_SEGS /
154                                                       RPCRDMA_MAX_FMR_SGES));
155         return 0;
156 }
157
158 /* FMR mode conveys up to 64 pages of payload per chunk segment.
159  */
160 static size_t
161 fmr_op_maxpages(struct rpcrdma_xprt *r_xprt)
162 {
163         return min_t(unsigned int, RPCRDMA_MAX_DATA_SEGS,
164                      RPCRDMA_MAX_HDR_SEGS * RPCRDMA_MAX_FMR_SGES);
165 }
166
167 /* Use the ib_map_phys_fmr() verb to register a memory region
168  * for remote access via RDMA READ or RDMA WRITE.
169  */
170 static int
171 fmr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
172            int nsegs, bool writing)
173 {
174         struct rpcrdma_mr_seg *seg1 = seg;
175         int len, pageoff, i, rc;
176         struct rpcrdma_mw *mw;
177         u64 *dma_pages;
178
179         mw = seg1->rl_mw;
180         seg1->rl_mw = NULL;
181         if (mw)
182                 rpcrdma_defer_mr_recovery(mw);
183         mw = rpcrdma_get_mw(r_xprt);
184         if (!mw)
185                 return -ENOBUFS;
186
187         pageoff = offset_in_page(seg1->mr_offset);
188         seg1->mr_offset -= pageoff;     /* start of page */
189         seg1->mr_len += pageoff;
190         len = -pageoff;
191         if (nsegs > RPCRDMA_MAX_FMR_SGES)
192                 nsegs = RPCRDMA_MAX_FMR_SGES;
193         for (i = 0; i < nsegs;) {
194                 if (seg->mr_page)
195                         sg_set_page(&mw->mw_sg[i],
196                                     seg->mr_page,
197                                     seg->mr_len,
198                                     offset_in_page(seg->mr_offset));
199                 else
200                         sg_set_buf(&mw->mw_sg[i], seg->mr_offset,
201                                    seg->mr_len);
202                 len += seg->mr_len;
203                 ++seg;
204                 ++i;
205                 /* Check for holes */
206                 if ((i < nsegs && offset_in_page(seg->mr_offset)) ||
207                     offset_in_page((seg-1)->mr_offset + (seg-1)->mr_len))
208                         break;
209         }
210         mw->mw_nents = i;
211         mw->mw_dir = rpcrdma_data_dir(writing);
212         if (i == 0)
213                 goto out_dmamap_err;
214
215         if (!ib_dma_map_sg(r_xprt->rx_ia.ri_device,
216                            mw->mw_sg, mw->mw_nents, mw->mw_dir))
217                 goto out_dmamap_err;
218
219         for (i = 0, dma_pages = mw->fmr.fm_physaddrs; i < mw->mw_nents; i++)
220                 dma_pages[i] = sg_dma_address(&mw->mw_sg[i]);
221         rc = ib_map_phys_fmr(mw->fmr.fm_mr, dma_pages, mw->mw_nents,
222                              dma_pages[0]);
223         if (rc)
224                 goto out_maperr;
225
226         seg1->rl_mw = mw;
227         seg1->mr_rkey = mw->fmr.fm_mr->rkey;
228         seg1->mr_base = dma_pages[0] + pageoff;
229         seg1->mr_nsegs = mw->mw_nents;
230         seg1->mr_len = len;
231         return mw->mw_nents;
232
233 out_dmamap_err:
234         pr_err("rpcrdma: failed to dma map sg %p sg_nents %u\n",
235                mw->mw_sg, mw->mw_nents);
236         rpcrdma_defer_mr_recovery(mw);
237         return -EIO;
238
239 out_maperr:
240         pr_err("rpcrdma: ib_map_phys_fmr %u@0x%llx+%i (%d) status %i\n",
241                len, (unsigned long long)dma_pages[0],
242                pageoff, mw->mw_nents, rc);
243         rpcrdma_defer_mr_recovery(mw);
244         return -EIO;
245 }
246
247 /* Invalidate all memory regions that were registered for "req".
248  *
249  * Sleeps until it is safe for the host CPU to access the
250  * previously mapped memory regions.
251  */
252 static void
253 fmr_op_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
254 {
255         struct rpcrdma_mr_seg *seg;
256         unsigned int i, nchunks;
257         struct rpcrdma_mw *mw;
258         LIST_HEAD(unmap_list);
259         int rc;
260
261         dprintk("RPC:       %s: req %p\n", __func__, req);
262
263         /* ORDER: Invalidate all of the req's MRs first
264          *
265          * ib_unmap_fmr() is slow, so use a single call instead
266          * of one call per mapped FMR.
267          */
268         for (i = 0, nchunks = req->rl_nchunks; nchunks; nchunks--) {
269                 seg = &req->rl_segments[i];
270                 mw = seg->rl_mw;
271
272                 list_add_tail(&mw->fmr.fm_mr->list, &unmap_list);
273
274                 i += seg->mr_nsegs;
275         }
276         rc = ib_unmap_fmr(&unmap_list);
277         if (rc)
278                 goto out_reset;
279
280         /* ORDER: Now DMA unmap all of the req's MRs, and return
281          * them to the free MW list.
282          */
283         for (i = 0, nchunks = req->rl_nchunks; nchunks; nchunks--) {
284                 seg = &req->rl_segments[i];
285                 mw = seg->rl_mw;
286
287                 list_del_init(&mw->fmr.fm_mr->list);
288                 ib_dma_unmap_sg(r_xprt->rx_ia.ri_device,
289                                 mw->mw_sg, mw->mw_nents, mw->mw_dir);
290                 rpcrdma_put_mw(r_xprt, mw);
291
292                 i += seg->mr_nsegs;
293                 seg->mr_nsegs = 0;
294                 seg->rl_mw = NULL;
295         }
296
297         req->rl_nchunks = 0;
298         return;
299
300 out_reset:
301         pr_err("rpcrdma: ib_unmap_fmr failed (%i)\n", rc);
302
303         for (i = 0, nchunks = req->rl_nchunks; nchunks; nchunks--) {
304                 seg = &req->rl_segments[i];
305                 mw = seg->rl_mw;
306
307                 list_del_init(&mw->fmr.fm_mr->list);
308                 fmr_op_recover_mr(mw);
309
310                 i += seg->mr_nsegs;
311         }
312 }
313
314 /* Use a slow, safe mechanism to invalidate all memory regions
315  * that were registered for "req".
316  */
317 static void
318 fmr_op_unmap_safe(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req,
319                   bool sync)
320 {
321         struct rpcrdma_mr_seg *seg;
322         struct rpcrdma_mw *mw;
323         unsigned int i;
324
325         for (i = 0; req->rl_nchunks; req->rl_nchunks--) {
326                 seg = &req->rl_segments[i];
327                 mw = seg->rl_mw;
328
329                 if (sync)
330                         fmr_op_recover_mr(mw);
331                 else
332                         rpcrdma_defer_mr_recovery(mw);
333
334                 i += seg->mr_nsegs;
335                 seg->mr_nsegs = 0;
336                 seg->rl_mw = NULL;
337         }
338 }
339
340 const struct rpcrdma_memreg_ops rpcrdma_fmr_memreg_ops = {
341         .ro_map                         = fmr_op_map,
342         .ro_unmap_sync                  = fmr_op_unmap_sync,
343         .ro_unmap_safe                  = fmr_op_unmap_safe,
344         .ro_recover_mr                  = fmr_op_recover_mr,
345         .ro_open                        = fmr_op_open,
346         .ro_maxpages                    = fmr_op_maxpages,
347         .ro_init_mr                     = fmr_op_init_mr,
348         .ro_release_mr                  = fmr_op_release_mr,
349         .ro_displayname                 = "fmr",
350 };