diff options
| -rw-r--r-- | include/linux/sunrpc/svc_rdma.h | 1 | ||||
| -rw-r--r-- | net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 83 |
2 files changed, 39 insertions, 45 deletions
diff --git a/include/linux/sunrpc/svc_rdma.h b/include/linux/sunrpc/svc_rdma.h index bd8749cc8084..fd5e8a1c17de 100644 --- a/include/linux/sunrpc/svc_rdma.h +++ b/include/linux/sunrpc/svc_rdma.h | |||
| @@ -72,6 +72,7 @@ extern atomic_t rdma_stat_sq_prod; | |||
| 72 | */ | 72 | */ |
| 73 | struct svc_rdma_op_ctxt { | 73 | struct svc_rdma_op_ctxt { |
| 74 | struct svc_rdma_op_ctxt *read_hdr; | 74 | struct svc_rdma_op_ctxt *read_hdr; |
| 75 | int hdr_count; | ||
| 75 | struct list_head free_list; | 76 | struct list_head free_list; |
| 76 | struct xdr_buf arg; | 77 | struct xdr_buf arg; |
| 77 | struct list_head dto_q; | 78 | struct list_head dto_q; |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c index 06ab4841537b..d25971b42a74 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | |||
| @@ -112,11 +112,6 @@ static void rdma_build_arg_xdr(struct svc_rqst *rqstp, | |||
| 112 | rqstp->rq_arg.tail[0].iov_len = 0; | 112 | rqstp->rq_arg.tail[0].iov_len = 0; |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | struct chunk_sge { | ||
| 116 | int start; /* sge no for this chunk */ | ||
| 117 | int count; /* sge count for this chunk */ | ||
| 118 | }; | ||
| 119 | |||
| 120 | /* Encode a read-chunk-list as an array of IB SGE | 115 | /* Encode a read-chunk-list as an array of IB SGE |
| 121 | * | 116 | * |
| 122 | * Assumptions: | 117 | * Assumptions: |
| @@ -134,8 +129,8 @@ static int rdma_rcl_to_sge(struct svcxprt_rdma *xprt, | |||
| 134 | struct svc_rqst *rqstp, | 129 | struct svc_rqst *rqstp, |
| 135 | struct svc_rdma_op_ctxt *head, | 130 | struct svc_rdma_op_ctxt *head, |
| 136 | struct rpcrdma_msg *rmsgp, | 131 | struct rpcrdma_msg *rmsgp, |
| 137 | struct ib_sge *sge, | 132 | struct svc_rdma_req_map *rpl_map, |
| 138 | struct chunk_sge *ch_sge_ary, | 133 | struct svc_rdma_req_map *chl_map, |
| 139 | int ch_count, | 134 | int ch_count, |
| 140 | int byte_count) | 135 | int byte_count) |
| 141 | { | 136 | { |
| @@ -156,22 +151,18 @@ static int rdma_rcl_to_sge(struct svcxprt_rdma *xprt, | |||
| 156 | head->arg.head[0] = rqstp->rq_arg.head[0]; | 151 | head->arg.head[0] = rqstp->rq_arg.head[0]; |
| 157 | head->arg.tail[0] = rqstp->rq_arg.tail[0]; | 152 | head->arg.tail[0] = rqstp->rq_arg.tail[0]; |
| 158 | head->arg.pages = &head->pages[head->count]; | 153 | head->arg.pages = &head->pages[head->count]; |
| 159 | head->sge[0].length = head->count; /* save count of hdr pages */ | 154 | head->hdr_count = head->count; /* save count of hdr pages */ |
| 160 | head->arg.page_base = 0; | 155 | head->arg.page_base = 0; |
| 161 | head->arg.page_len = ch_bytes; | 156 | head->arg.page_len = ch_bytes; |
| 162 | head->arg.len = rqstp->rq_arg.len + ch_bytes; | 157 | head->arg.len = rqstp->rq_arg.len + ch_bytes; |
| 163 | head->arg.buflen = rqstp->rq_arg.buflen + ch_bytes; | 158 | head->arg.buflen = rqstp->rq_arg.buflen + ch_bytes; |
| 164 | head->count++; | 159 | head->count++; |
| 165 | ch_sge_ary[0].start = 0; | 160 | chl_map->ch[0].start = 0; |
| 166 | while (byte_count) { | 161 | while (byte_count) { |
| 162 | rpl_map->sge[sge_no].iov_base = | ||
| 163 | page_address(rqstp->rq_arg.pages[page_no]) + page_off; | ||
| 167 | sge_bytes = min_t(int, PAGE_SIZE-page_off, ch_bytes); | 164 | sge_bytes = min_t(int, PAGE_SIZE-page_off, ch_bytes); |
| 168 | sge[sge_no].addr = | 165 | rpl_map->sge[sge_no].iov_len = sge_bytes; |
| 169 | ib_dma_map_page(xprt->sc_cm_id->device, | ||
| 170 | rqstp->rq_arg.pages[page_no], | ||
| 171 | page_off, sge_bytes, | ||
| 172 | DMA_FROM_DEVICE); | ||
| 173 | sge[sge_no].length = sge_bytes; | ||
| 174 | sge[sge_no].lkey = xprt->sc_phys_mr->lkey; | ||
| 175 | /* | 166 | /* |
| 176 | * Don't bump head->count here because the same page | 167 | * Don't bump head->count here because the same page |
| 177 | * may be used by multiple SGE. | 168 | * may be used by multiple SGE. |
| @@ -187,11 +178,11 @@ static int rdma_rcl_to_sge(struct svcxprt_rdma *xprt, | |||
| 187 | * SGE, move to the next SGE | 178 | * SGE, move to the next SGE |
| 188 | */ | 179 | */ |
| 189 | if (ch_bytes == 0) { | 180 | if (ch_bytes == 0) { |
| 190 | ch_sge_ary[ch_no].count = | 181 | chl_map->ch[ch_no].count = |
| 191 | sge_no - ch_sge_ary[ch_no].start; | 182 | sge_no - chl_map->ch[ch_no].start; |
| 192 | ch_no++; | 183 | ch_no++; |
| 193 | ch++; | 184 | ch++; |
| 194 | ch_sge_ary[ch_no].start = sge_no; | 185 | chl_map->ch[ch_no].start = sge_no; |
| 195 | ch_bytes = ch->rc_target.rs_length; | 186 | ch_bytes = ch->rc_target.rs_length; |
| 196 | /* If bytes remaining account for next chunk */ | 187 | /* If bytes remaining account for next chunk */ |
| 197 | if (byte_count) { | 188 | if (byte_count) { |
| @@ -220,18 +211,24 @@ static int rdma_rcl_to_sge(struct svcxprt_rdma *xprt, | |||
| 220 | return sge_no; | 211 | return sge_no; |
| 221 | } | 212 | } |
| 222 | 213 | ||
| 223 | static void rdma_set_ctxt_sge(struct svc_rdma_op_ctxt *ctxt, | 214 | static void rdma_set_ctxt_sge(struct svcxprt_rdma *xprt, |
| 224 | struct ib_sge *sge, | 215 | struct svc_rdma_op_ctxt *ctxt, |
| 216 | struct kvec *vec, | ||
| 225 | u64 *sgl_offset, | 217 | u64 *sgl_offset, |
| 226 | int count) | 218 | int count) |
| 227 | { | 219 | { |
| 228 | int i; | 220 | int i; |
| 229 | 221 | ||
| 230 | ctxt->count = count; | 222 | ctxt->count = count; |
| 223 | ctxt->direction = DMA_FROM_DEVICE; | ||
| 231 | for (i = 0; i < count; i++) { | 224 | for (i = 0; i < count; i++) { |
| 232 | ctxt->sge[i].addr = sge[i].addr; | 225 | ctxt->sge[i].addr = |
| 233 | ctxt->sge[i].length = sge[i].length; | 226 | ib_dma_map_single(xprt->sc_cm_id->device, |
| 234 | *sgl_offset = *sgl_offset + sge[i].length; | 227 | vec[i].iov_base, vec[i].iov_len, |
| 228 | DMA_FROM_DEVICE); | ||
| 229 | ctxt->sge[i].length = vec[i].iov_len; | ||
| 230 | ctxt->sge[i].lkey = xprt->sc_phys_mr->lkey; | ||
| 231 | *sgl_offset = *sgl_offset + vec[i].iov_len; | ||
| 235 | } | 232 | } |
| 236 | } | 233 | } |
| 237 | 234 | ||
| @@ -282,34 +279,29 @@ static int rdma_read_xdr(struct svcxprt_rdma *xprt, | |||
| 282 | struct ib_send_wr read_wr; | 279 | struct ib_send_wr read_wr; |
| 283 | int err = 0; | 280 | int err = 0; |
| 284 | int ch_no; | 281 | int ch_no; |
| 285 | struct ib_sge *sge; | ||
| 286 | int ch_count; | 282 | int ch_count; |
| 287 | int byte_count; | 283 | int byte_count; |
| 288 | int sge_count; | 284 | int sge_count; |
| 289 | u64 sgl_offset; | 285 | u64 sgl_offset; |
| 290 | struct rpcrdma_read_chunk *ch; | 286 | struct rpcrdma_read_chunk *ch; |
| 291 | struct svc_rdma_op_ctxt *ctxt = NULL; | 287 | struct svc_rdma_op_ctxt *ctxt = NULL; |
| 292 | struct svc_rdma_op_ctxt *tmp_sge_ctxt; | 288 | struct svc_rdma_req_map *rpl_map; |
| 293 | struct svc_rdma_op_ctxt *tmp_ch_ctxt; | 289 | struct svc_rdma_req_map *chl_map; |
| 294 | struct chunk_sge *ch_sge_ary; | ||
| 295 | 290 | ||
| 296 | /* If no read list is present, return 0 */ | 291 | /* If no read list is present, return 0 */ |
| 297 | ch = svc_rdma_get_read_chunk(rmsgp); | 292 | ch = svc_rdma_get_read_chunk(rmsgp); |
| 298 | if (!ch) | 293 | if (!ch) |
| 299 | return 0; | 294 | return 0; |
| 300 | 295 | ||
| 301 | /* Allocate temporary contexts to keep SGE */ | 296 | /* Allocate temporary reply and chunk maps */ |
| 302 | BUG_ON(sizeof(struct ib_sge) < sizeof(struct chunk_sge)); | 297 | rpl_map = svc_rdma_get_req_map(); |
| 303 | tmp_sge_ctxt = svc_rdma_get_context(xprt); | 298 | chl_map = svc_rdma_get_req_map(); |
| 304 | sge = tmp_sge_ctxt->sge; | ||
| 305 | tmp_ch_ctxt = svc_rdma_get_context(xprt); | ||
| 306 | ch_sge_ary = (struct chunk_sge *)tmp_ch_ctxt->sge; | ||
| 307 | 299 | ||
| 308 | svc_rdma_rcl_chunk_counts(ch, &ch_count, &byte_count); | 300 | svc_rdma_rcl_chunk_counts(ch, &ch_count, &byte_count); |
| 309 | if (ch_count > RPCSVC_MAXPAGES) | 301 | if (ch_count > RPCSVC_MAXPAGES) |
| 310 | return -EINVAL; | 302 | return -EINVAL; |
| 311 | sge_count = rdma_rcl_to_sge(xprt, rqstp, hdr_ctxt, rmsgp, | 303 | sge_count = rdma_rcl_to_sge(xprt, rqstp, hdr_ctxt, rmsgp, |
| 312 | sge, ch_sge_ary, | 304 | rpl_map, chl_map, |
| 313 | ch_count, byte_count); | 305 | ch_count, byte_count); |
| 314 | sgl_offset = 0; | 306 | sgl_offset = 0; |
| 315 | ch_no = 0; | 307 | ch_no = 0; |
| @@ -331,14 +323,15 @@ next_sge: | |||
| 331 | read_wr.wr.rdma.remote_addr = | 323 | read_wr.wr.rdma.remote_addr = |
| 332 | get_unaligned(&(ch->rc_target.rs_offset)) + | 324 | get_unaligned(&(ch->rc_target.rs_offset)) + |
| 333 | sgl_offset; | 325 | sgl_offset; |
| 334 | read_wr.sg_list = &sge[ch_sge_ary[ch_no].start]; | 326 | read_wr.sg_list = ctxt->sge; |
| 335 | read_wr.num_sge = | 327 | read_wr.num_sge = |
| 336 | rdma_read_max_sge(xprt, ch_sge_ary[ch_no].count); | 328 | rdma_read_max_sge(xprt, chl_map->ch[ch_no].count); |
| 337 | rdma_set_ctxt_sge(ctxt, &sge[ch_sge_ary[ch_no].start], | 329 | rdma_set_ctxt_sge(xprt, ctxt, |
| 330 | &rpl_map->sge[chl_map->ch[ch_no].start], | ||
| 338 | &sgl_offset, | 331 | &sgl_offset, |
| 339 | read_wr.num_sge); | 332 | read_wr.num_sge); |
| 340 | if (((ch+1)->rc_discrim == 0) && | 333 | if (((ch+1)->rc_discrim == 0) && |
| 341 | (read_wr.num_sge == ch_sge_ary[ch_no].count)) { | 334 | (read_wr.num_sge == chl_map->ch[ch_no].count)) { |
| 342 | /* | 335 | /* |
| 343 | * Mark the last RDMA_READ with a bit to | 336 | * Mark the last RDMA_READ with a bit to |
| 344 | * indicate all RPC data has been fetched from | 337 | * indicate all RPC data has been fetched from |
| @@ -358,9 +351,9 @@ next_sge: | |||
| 358 | } | 351 | } |
| 359 | atomic_inc(&rdma_stat_read); | 352 | atomic_inc(&rdma_stat_read); |
| 360 | 353 | ||
| 361 | if (read_wr.num_sge < ch_sge_ary[ch_no].count) { | 354 | if (read_wr.num_sge < chl_map->ch[ch_no].count) { |
| 362 | ch_sge_ary[ch_no].count -= read_wr.num_sge; | 355 | chl_map->ch[ch_no].count -= read_wr.num_sge; |
| 363 | ch_sge_ary[ch_no].start += read_wr.num_sge; | 356 | chl_map->ch[ch_no].start += read_wr.num_sge; |
| 364 | goto next_sge; | 357 | goto next_sge; |
| 365 | } | 358 | } |
| 366 | sgl_offset = 0; | 359 | sgl_offset = 0; |
| @@ -368,8 +361,8 @@ next_sge: | |||
| 368 | } | 361 | } |
| 369 | 362 | ||
| 370 | out: | 363 | out: |
| 371 | svc_rdma_put_context(tmp_sge_ctxt, 0); | 364 | svc_rdma_put_req_map(rpl_map); |
| 372 | svc_rdma_put_context(tmp_ch_ctxt, 0); | 365 | svc_rdma_put_req_map(chl_map); |
| 373 | 366 | ||
| 374 | /* Detach arg pages. svc_recv will replenish them */ | 367 | /* Detach arg pages. svc_recv will replenish them */ |
| 375 | for (ch_no = 0; &rqstp->rq_pages[ch_no] < rqstp->rq_respages; ch_no++) | 368 | for (ch_no = 0; &rqstp->rq_pages[ch_no] < rqstp->rq_respages; ch_no++) |
| @@ -399,7 +392,7 @@ static int rdma_read_complete(struct svc_rqst *rqstp, | |||
| 399 | rqstp->rq_pages[page_no] = head->pages[page_no]; | 392 | rqstp->rq_pages[page_no] = head->pages[page_no]; |
| 400 | } | 393 | } |
| 401 | /* Point rq_arg.pages past header */ | 394 | /* Point rq_arg.pages past header */ |
| 402 | rqstp->rq_arg.pages = &rqstp->rq_pages[head->sge[0].length]; | 395 | rqstp->rq_arg.pages = &rqstp->rq_pages[head->hdr_count]; |
| 403 | rqstp->rq_arg.page_len = head->arg.page_len; | 396 | rqstp->rq_arg.page_len = head->arg.page_len; |
| 404 | rqstp->rq_arg.page_base = head->arg.page_base; | 397 | rqstp->rq_arg.page_base = head->arg.page_base; |
| 405 | 398 | ||
