]> git.karo-electronics.de Git - karo-tx-linux.git/blob - net/sunrpc/xprtrdma/frwr_ops.c
xprtrdma: Add "reset MRs" memreg op
[karo-tx-linux.git] / net / sunrpc / xprtrdma / frwr_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 Registration Work
7  * Requests (FRWR). Also referred to sometimes as FRMR mode.
8  *
9  * FRWR features ordered asynchronous registration and deregistration
10  * of arbitrarily sized memory regions. This is the fastest and safest
11  * but most complex memory registration mode.
12  */
13
14 #include "xprt_rdma.h"
15
16 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
17 # define RPCDBG_FACILITY        RPCDBG_TRANS
18 #endif
19
20 static int
21 __frwr_init(struct rpcrdma_mw *r, struct ib_pd *pd, struct ib_device *device,
22             unsigned int depth)
23 {
24         struct rpcrdma_frmr *f = &r->r.frmr;
25         int rc;
26
27         f->fr_mr = ib_alloc_fast_reg_mr(pd, depth);
28         if (IS_ERR(f->fr_mr))
29                 goto out_mr_err;
30         f->fr_pgl = ib_alloc_fast_reg_page_list(device, depth);
31         if (IS_ERR(f->fr_pgl))
32                 goto out_list_err;
33         return 0;
34
35 out_mr_err:
36         rc = PTR_ERR(f->fr_mr);
37         dprintk("RPC:       %s: ib_alloc_fast_reg_mr status %i\n",
38                 __func__, rc);
39         return rc;
40
41 out_list_err:
42         rc = PTR_ERR(f->fr_pgl);
43         dprintk("RPC:       %s: ib_alloc_fast_reg_page_list status %i\n",
44                 __func__, rc);
45         ib_dereg_mr(f->fr_mr);
46         return rc;
47 }
48
49 static void
50 __frwr_release(struct rpcrdma_mw *r)
51 {
52         int rc;
53
54         rc = ib_dereg_mr(r->r.frmr.fr_mr);
55         if (rc)
56                 dprintk("RPC:       %s: ib_dereg_mr status %i\n",
57                         __func__, rc);
58         ib_free_fast_reg_page_list(r->r.frmr.fr_pgl);
59 }
60
61 /* FRWR mode conveys a list of pages per chunk segment. The
62  * maximum length of that list is the FRWR page list depth.
63  */
64 static size_t
65 frwr_op_maxpages(struct rpcrdma_xprt *r_xprt)
66 {
67         struct rpcrdma_ia *ia = &r_xprt->rx_ia;
68
69         return min_t(unsigned int, RPCRDMA_MAX_DATA_SEGS,
70                      rpcrdma_max_segments(r_xprt) * ia->ri_max_frmr_depth);
71 }
72
73 static int
74 frwr_op_init(struct rpcrdma_xprt *r_xprt)
75 {
76         struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
77         struct ib_device *device = r_xprt->rx_ia.ri_id->device;
78         unsigned int depth = r_xprt->rx_ia.ri_max_frmr_depth;
79         struct ib_pd *pd = r_xprt->rx_ia.ri_pd;
80         int i;
81
82         INIT_LIST_HEAD(&buf->rb_mws);
83         INIT_LIST_HEAD(&buf->rb_all);
84
85         i = (buf->rb_max_requests + 1) * RPCRDMA_MAX_SEGS;
86         dprintk("RPC:       %s: initalizing %d FRMRs\n", __func__, i);
87
88         while (i--) {
89                 struct rpcrdma_mw *r;
90                 int rc;
91
92                 r = kzalloc(sizeof(*r), GFP_KERNEL);
93                 if (!r)
94                         return -ENOMEM;
95
96                 rc = __frwr_init(r, pd, device, depth);
97                 if (rc) {
98                         kfree(r);
99                         return rc;
100                 }
101
102                 list_add(&r->mw_list, &buf->rb_mws);
103                 list_add(&r->mw_all, &buf->rb_all);
104         }
105
106         return 0;
107 }
108
109 /* Post a FAST_REG Work Request to register a memory region
110  * for remote access via RDMA READ or RDMA WRITE.
111  */
112 static int
113 frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
114             int nsegs, bool writing)
115 {
116         struct rpcrdma_ia *ia = &r_xprt->rx_ia;
117         struct rpcrdma_mr_seg *seg1 = seg;
118         struct rpcrdma_mw *mw = seg1->rl_mw;
119         struct rpcrdma_frmr *frmr = &mw->r.frmr;
120         struct ib_mr *mr = frmr->fr_mr;
121         struct ib_send_wr fastreg_wr, *bad_wr;
122         u8 key;
123         int len, pageoff;
124         int i, rc;
125         int seg_len;
126         u64 pa;
127         int page_no;
128
129         pageoff = offset_in_page(seg1->mr_offset);
130         seg1->mr_offset -= pageoff;     /* start of page */
131         seg1->mr_len += pageoff;
132         len = -pageoff;
133         if (nsegs > ia->ri_max_frmr_depth)
134                 nsegs = ia->ri_max_frmr_depth;
135         for (page_no = i = 0; i < nsegs;) {
136                 rpcrdma_map_one(ia, seg, writing);
137                 pa = seg->mr_dma;
138                 for (seg_len = seg->mr_len; seg_len > 0; seg_len -= PAGE_SIZE) {
139                         frmr->fr_pgl->page_list[page_no++] = pa;
140                         pa += PAGE_SIZE;
141                 }
142                 len += seg->mr_len;
143                 ++seg;
144                 ++i;
145                 /* Check for holes */
146                 if ((i < nsegs && offset_in_page(seg->mr_offset)) ||
147                     offset_in_page((seg-1)->mr_offset + (seg-1)->mr_len))
148                         break;
149         }
150         dprintk("RPC:       %s: Using frmr %p to map %d segments (%d bytes)\n",
151                 __func__, mw, i, len);
152
153         frmr->fr_state = FRMR_IS_VALID;
154
155         memset(&fastreg_wr, 0, sizeof(fastreg_wr));
156         fastreg_wr.wr_id = (unsigned long)(void *)mw;
157         fastreg_wr.opcode = IB_WR_FAST_REG_MR;
158         fastreg_wr.wr.fast_reg.iova_start = seg1->mr_dma + pageoff;
159         fastreg_wr.wr.fast_reg.page_list = frmr->fr_pgl;
160         fastreg_wr.wr.fast_reg.page_shift = PAGE_SHIFT;
161         fastreg_wr.wr.fast_reg.page_list_len = page_no;
162         fastreg_wr.wr.fast_reg.length = len;
163         fastreg_wr.wr.fast_reg.access_flags = writing ?
164                                 IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE :
165                                 IB_ACCESS_REMOTE_READ;
166         key = (u8)(mr->rkey & 0x000000FF);
167         ib_update_fast_reg_key(mr, ++key);
168         fastreg_wr.wr.fast_reg.rkey = mr->rkey;
169
170         DECR_CQCOUNT(&r_xprt->rx_ep);
171         rc = ib_post_send(ia->ri_id->qp, &fastreg_wr, &bad_wr);
172         if (rc)
173                 goto out_senderr;
174
175         seg1->mr_rkey = mr->rkey;
176         seg1->mr_base = seg1->mr_dma + pageoff;
177         seg1->mr_nsegs = i;
178         seg1->mr_len = len;
179         return i;
180
181 out_senderr:
182         dprintk("RPC:       %s: ib_post_send status %i\n", __func__, rc);
183         ib_update_fast_reg_key(mr, --key);
184         frmr->fr_state = FRMR_IS_INVALID;
185         while (i--)
186                 rpcrdma_unmap_one(ia, --seg);
187         return rc;
188 }
189
190 /* Post a LOCAL_INV Work Request to prevent further remote access
191  * via RDMA READ or RDMA WRITE.
192  */
193 static int
194 frwr_op_unmap(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg)
195 {
196         struct rpcrdma_mr_seg *seg1 = seg;
197         struct rpcrdma_ia *ia = &r_xprt->rx_ia;
198         struct ib_send_wr invalidate_wr, *bad_wr;
199         int rc, nsegs = seg->mr_nsegs;
200
201         seg1->rl_mw->r.frmr.fr_state = FRMR_IS_INVALID;
202
203         memset(&invalidate_wr, 0, sizeof(invalidate_wr));
204         invalidate_wr.wr_id = (unsigned long)(void *)seg1->rl_mw;
205         invalidate_wr.opcode = IB_WR_LOCAL_INV;
206         invalidate_wr.ex.invalidate_rkey = seg1->rl_mw->r.frmr.fr_mr->rkey;
207         DECR_CQCOUNT(&r_xprt->rx_ep);
208
209         read_lock(&ia->ri_qplock);
210         while (seg1->mr_nsegs--)
211                 rpcrdma_unmap_one(ia, seg++);
212         rc = ib_post_send(ia->ri_id->qp, &invalidate_wr, &bad_wr);
213         read_unlock(&ia->ri_qplock);
214         if (rc)
215                 goto out_err;
216         return nsegs;
217
218 out_err:
219         /* Force rpcrdma_buffer_get() to retry */
220         seg1->rl_mw->r.frmr.fr_state = FRMR_IS_STALE;
221         dprintk("RPC:       %s: ib_post_send status %i\n", __func__, rc);
222         return nsegs;
223 }
224
225 /* After a disconnect, a flushed FAST_REG_MR can leave an FRMR in
226  * an unusable state. Find FRMRs in this state and dereg / reg
227  * each.  FRMRs that are VALID and attached to an rpcrdma_req are
228  * also torn down.
229  *
230  * This gives all in-use FRMRs a fresh rkey and leaves them INVALID.
231  *
232  * This is invoked only in the transport connect worker in order
233  * to serialize with rpcrdma_register_frmr_external().
234  */
235 static void
236 frwr_op_reset(struct rpcrdma_xprt *r_xprt)
237 {
238         struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
239         struct ib_device *device = r_xprt->rx_ia.ri_id->device;
240         unsigned int depth = r_xprt->rx_ia.ri_max_frmr_depth;
241         struct ib_pd *pd = r_xprt->rx_ia.ri_pd;
242         struct rpcrdma_mw *r;
243         int rc;
244
245         list_for_each_entry(r, &buf->rb_all, mw_all) {
246                 if (r->r.frmr.fr_state == FRMR_IS_INVALID)
247                         continue;
248
249                 __frwr_release(r);
250                 rc = __frwr_init(r, pd, device, depth);
251                 if (rc) {
252                         dprintk("RPC:       %s: mw %p left %s\n",
253                                 __func__, r,
254                                 (r->r.frmr.fr_state == FRMR_IS_STALE ?
255                                         "stale" : "valid"));
256                         continue;
257                 }
258
259                 r->r.frmr.fr_state = FRMR_IS_INVALID;
260         }
261 }
262
263 const struct rpcrdma_memreg_ops rpcrdma_frwr_memreg_ops = {
264         .ro_map                         = frwr_op_map,
265         .ro_unmap                       = frwr_op_unmap,
266         .ro_maxpages                    = frwr_op_maxpages,
267         .ro_init                        = frwr_op_init,
268         .ro_reset                       = frwr_op_reset,
269         .ro_displayname                 = "frwr",
270 };