svc_rdma_sendto.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. /*
  2. * Copyright (c) 2014 Open Grid Computing, Inc. All rights reserved.
  3. * Copyright (c) 2005-2006 Network Appliance, Inc. All rights reserved.
  4. *
  5. * This software is available to you under a choice of one of two
  6. * licenses. You may choose to be licensed under the terms of the GNU
  7. * General Public License (GPL) Version 2, available from the file
  8. * COPYING in the main directory of this source tree, or the BSD-type
  9. * license below:
  10. *
  11. * Redistribution and use in source and binary forms, with or without
  12. * modification, are permitted provided that the following conditions
  13. * are met:
  14. *
  15. * Redistributions of source code must retain the above copyright
  16. * notice, this list of conditions and the following disclaimer.
  17. *
  18. * Redistributions in binary form must reproduce the above
  19. * copyright notice, this list of conditions and the following
  20. * disclaimer in the documentation and/or other materials provided
  21. * with the distribution.
  22. *
  23. * Neither the name of the Network Appliance, Inc. nor the names of
  24. * its contributors may be used to endorse or promote products
  25. * derived from this software without specific prior written
  26. * permission.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  29. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  30. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  31. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  32. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  33. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  34. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  35. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  36. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  37. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  38. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  39. *
  40. * Author: Tom Tucker <tom@opengridcomputing.com>
  41. */
  42. #include <linux/sunrpc/debug.h>
  43. #include <linux/sunrpc/rpc_rdma.h>
  44. #include <linux/spinlock.h>
  45. #include <asm/unaligned.h>
  46. #include <rdma/ib_verbs.h>
  47. #include <rdma/rdma_cm.h>
  48. #include <linux/sunrpc/svc_rdma.h>
  49. #define RPCDBG_FACILITY RPCDBG_SVCXPRT
  50. static u32 xdr_padsize(u32 len)
  51. {
  52. return (len & 3) ? (4 - (len & 3)) : 0;
  53. }
  54. int svc_rdma_map_xdr(struct svcxprt_rdma *xprt,
  55. struct xdr_buf *xdr,
  56. struct svc_rdma_req_map *vec,
  57. bool write_chunk_present)
  58. {
  59. int sge_no;
  60. u32 sge_bytes;
  61. u32 page_bytes;
  62. u32 page_off;
  63. int page_no;
  64. if (xdr->len !=
  65. (xdr->head[0].iov_len + xdr->page_len + xdr->tail[0].iov_len)) {
  66. pr_err("svcrdma: %s: XDR buffer length error\n", __func__);
  67. return -EIO;
  68. }
  69. /* Skip the first sge, this is for the RPCRDMA header */
  70. sge_no = 1;
  71. /* Head SGE */
  72. vec->sge[sge_no].iov_base = xdr->head[0].iov_base;
  73. vec->sge[sge_no].iov_len = xdr->head[0].iov_len;
  74. sge_no++;
  75. /* pages SGE */
  76. page_no = 0;
  77. page_bytes = xdr->page_len;
  78. page_off = xdr->page_base;
  79. while (page_bytes) {
  80. vec->sge[sge_no].iov_base =
  81. page_address(xdr->pages[page_no]) + page_off;
  82. sge_bytes = min_t(u32, page_bytes, (PAGE_SIZE - page_off));
  83. page_bytes -= sge_bytes;
  84. vec->sge[sge_no].iov_len = sge_bytes;
  85. sge_no++;
  86. page_no++;
  87. page_off = 0; /* reset for next time through loop */
  88. }
  89. /* Tail SGE */
  90. if (xdr->tail[0].iov_len) {
  91. unsigned char *base = xdr->tail[0].iov_base;
  92. size_t len = xdr->tail[0].iov_len;
  93. u32 xdr_pad = xdr_padsize(xdr->page_len);
  94. if (write_chunk_present && xdr_pad) {
  95. base += xdr_pad;
  96. len -= xdr_pad;
  97. }
  98. if (len) {
  99. vec->sge[sge_no].iov_base = base;
  100. vec->sge[sge_no].iov_len = len;
  101. sge_no++;
  102. }
  103. }
  104. dprintk("svcrdma: %s: sge_no %d page_no %d "
  105. "page_base %u page_len %u head_len %zu tail_len %zu\n",
  106. __func__, sge_no, page_no, xdr->page_base, xdr->page_len,
  107. xdr->head[0].iov_len, xdr->tail[0].iov_len);
  108. vec->count = sge_no;
  109. return 0;
  110. }
  111. static dma_addr_t dma_map_xdr(struct svcxprt_rdma *xprt,
  112. struct xdr_buf *xdr,
  113. u32 xdr_off, size_t len, int dir)
  114. {
  115. struct page *page;
  116. dma_addr_t dma_addr;
  117. if (xdr_off < xdr->head[0].iov_len) {
  118. /* This offset is in the head */
  119. xdr_off += (unsigned long)xdr->head[0].iov_base & ~PAGE_MASK;
  120. page = virt_to_page(xdr->head[0].iov_base);
  121. } else {
  122. xdr_off -= xdr->head[0].iov_len;
  123. if (xdr_off < xdr->page_len) {
  124. /* This offset is in the page list */
  125. xdr_off += xdr->page_base;
  126. page = xdr->pages[xdr_off >> PAGE_SHIFT];
  127. xdr_off &= ~PAGE_MASK;
  128. } else {
  129. /* This offset is in the tail */
  130. xdr_off -= xdr->page_len;
  131. xdr_off += (unsigned long)
  132. xdr->tail[0].iov_base & ~PAGE_MASK;
  133. page = virt_to_page(xdr->tail[0].iov_base);
  134. }
  135. }
  136. dma_addr = ib_dma_map_page(xprt->sc_cm_id->device, page, xdr_off,
  137. min_t(size_t, PAGE_SIZE, len), dir);
  138. return dma_addr;
  139. }
  140. /* Parse the RPC Call's transport header.
  141. */
  142. static void svc_rdma_get_write_arrays(struct rpcrdma_msg *rmsgp,
  143. struct rpcrdma_write_array **write,
  144. struct rpcrdma_write_array **reply)
  145. {
  146. __be32 *p;
  147. p = (__be32 *)&rmsgp->rm_body.rm_chunks[0];
  148. /* Read list */
  149. while (*p++ != xdr_zero)
  150. p += 5;
  151. /* Write list */
  152. if (*p != xdr_zero) {
  153. *write = (struct rpcrdma_write_array *)p;
  154. while (*p++ != xdr_zero)
  155. p += 1 + be32_to_cpu(*p) * 4;
  156. } else {
  157. *write = NULL;
  158. p++;
  159. }
  160. /* Reply chunk */
  161. if (*p != xdr_zero)
  162. *reply = (struct rpcrdma_write_array *)p;
  163. else
  164. *reply = NULL;
  165. }
  166. /* RPC-over-RDMA Version One private extension: Remote Invalidation.
  167. * Responder's choice: requester signals it can handle Send With
  168. * Invalidate, and responder chooses one rkey to invalidate.
  169. *
  170. * Find a candidate rkey to invalidate when sending a reply. Picks the
  171. * first rkey it finds in the chunks lists.
  172. *
  173. * Returns zero if RPC's chunk lists are empty.
  174. */
  175. static u32 svc_rdma_get_inv_rkey(struct rpcrdma_msg *rdma_argp,
  176. struct rpcrdma_write_array *wr_ary,
  177. struct rpcrdma_write_array *rp_ary)
  178. {
  179. struct rpcrdma_read_chunk *rd_ary;
  180. struct rpcrdma_segment *arg_ch;
  181. rd_ary = (struct rpcrdma_read_chunk *)&rdma_argp->rm_body.rm_chunks[0];
  182. if (rd_ary->rc_discrim != xdr_zero)
  183. return be32_to_cpu(rd_ary->rc_target.rs_handle);
  184. if (wr_ary && be32_to_cpu(wr_ary->wc_nchunks)) {
  185. arg_ch = &wr_ary->wc_array[0].wc_target;
  186. return be32_to_cpu(arg_ch->rs_handle);
  187. }
  188. if (rp_ary && be32_to_cpu(rp_ary->wc_nchunks)) {
  189. arg_ch = &rp_ary->wc_array[0].wc_target;
  190. return be32_to_cpu(arg_ch->rs_handle);
  191. }
  192. return 0;
  193. }
  194. /* Assumptions:
  195. * - The specified write_len can be represented in sc_max_sge * PAGE_SIZE
  196. */
  197. static int send_write(struct svcxprt_rdma *xprt, struct svc_rqst *rqstp,
  198. u32 rmr, u64 to,
  199. u32 xdr_off, int write_len,
  200. struct svc_rdma_req_map *vec)
  201. {
  202. struct ib_rdma_wr write_wr;
  203. struct ib_sge *sge;
  204. int xdr_sge_no;
  205. int sge_no;
  206. int sge_bytes;
  207. int sge_off;
  208. int bc;
  209. struct svc_rdma_op_ctxt *ctxt;
  210. if (vec->count > RPCSVC_MAXPAGES) {
  211. pr_err("svcrdma: Too many pages (%lu)\n", vec->count);
  212. return -EIO;
  213. }
  214. dprintk("svcrdma: RDMA_WRITE rmr=%x, to=%llx, xdr_off=%d, "
  215. "write_len=%d, vec->sge=%p, vec->count=%lu\n",
  216. rmr, (unsigned long long)to, xdr_off,
  217. write_len, vec->sge, vec->count);
  218. ctxt = svc_rdma_get_context(xprt);
  219. ctxt->direction = DMA_TO_DEVICE;
  220. sge = ctxt->sge;
  221. /* Find the SGE associated with xdr_off */
  222. for (bc = xdr_off, xdr_sge_no = 1; bc && xdr_sge_no < vec->count;
  223. xdr_sge_no++) {
  224. if (vec->sge[xdr_sge_no].iov_len > bc)
  225. break;
  226. bc -= vec->sge[xdr_sge_no].iov_len;
  227. }
  228. sge_off = bc;
  229. bc = write_len;
  230. sge_no = 0;
  231. /* Copy the remaining SGE */
  232. while (bc != 0) {
  233. sge_bytes = min_t(size_t,
  234. bc, vec->sge[xdr_sge_no].iov_len-sge_off);
  235. sge[sge_no].length = sge_bytes;
  236. sge[sge_no].addr =
  237. dma_map_xdr(xprt, &rqstp->rq_res, xdr_off,
  238. sge_bytes, DMA_TO_DEVICE);
  239. xdr_off += sge_bytes;
  240. if (ib_dma_mapping_error(xprt->sc_cm_id->device,
  241. sge[sge_no].addr))
  242. goto err;
  243. svc_rdma_count_mappings(xprt, ctxt);
  244. sge[sge_no].lkey = xprt->sc_pd->local_dma_lkey;
  245. ctxt->count++;
  246. sge_off = 0;
  247. sge_no++;
  248. xdr_sge_no++;
  249. if (xdr_sge_no > vec->count) {
  250. pr_err("svcrdma: Too many sges (%d)\n", xdr_sge_no);
  251. goto err;
  252. }
  253. bc -= sge_bytes;
  254. if (sge_no == xprt->sc_max_sge)
  255. break;
  256. }
  257. /* Prepare WRITE WR */
  258. memset(&write_wr, 0, sizeof write_wr);
  259. ctxt->cqe.done = svc_rdma_wc_write;
  260. write_wr.wr.wr_cqe = &ctxt->cqe;
  261. write_wr.wr.sg_list = &sge[0];
  262. write_wr.wr.num_sge = sge_no;
  263. write_wr.wr.opcode = IB_WR_RDMA_WRITE;
  264. write_wr.wr.send_flags = IB_SEND_SIGNALED;
  265. write_wr.rkey = rmr;
  266. write_wr.remote_addr = to;
  267. /* Post It */
  268. atomic_inc(&rdma_stat_write);
  269. if (svc_rdma_send(xprt, &write_wr.wr))
  270. goto err;
  271. return write_len - bc;
  272. err:
  273. svc_rdma_unmap_dma(ctxt);
  274. svc_rdma_put_context(ctxt, 0);
  275. return -EIO;
  276. }
  277. noinline
  278. static int send_write_chunks(struct svcxprt_rdma *xprt,
  279. struct rpcrdma_write_array *wr_ary,
  280. struct rpcrdma_msg *rdma_resp,
  281. struct svc_rqst *rqstp,
  282. struct svc_rdma_req_map *vec)
  283. {
  284. u32 xfer_len = rqstp->rq_res.page_len;
  285. int write_len;
  286. u32 xdr_off;
  287. int chunk_off;
  288. int chunk_no;
  289. int nchunks;
  290. struct rpcrdma_write_array *res_ary;
  291. int ret;
  292. res_ary = (struct rpcrdma_write_array *)
  293. &rdma_resp->rm_body.rm_chunks[1];
  294. /* Write chunks start at the pagelist */
  295. nchunks = be32_to_cpu(wr_ary->wc_nchunks);
  296. for (xdr_off = rqstp->rq_res.head[0].iov_len, chunk_no = 0;
  297. xfer_len && chunk_no < nchunks;
  298. chunk_no++) {
  299. struct rpcrdma_segment *arg_ch;
  300. u64 rs_offset;
  301. arg_ch = &wr_ary->wc_array[chunk_no].wc_target;
  302. write_len = min(xfer_len, be32_to_cpu(arg_ch->rs_length));
  303. /* Prepare the response chunk given the length actually
  304. * written */
  305. xdr_decode_hyper((__be32 *)&arg_ch->rs_offset, &rs_offset);
  306. svc_rdma_xdr_encode_array_chunk(res_ary, chunk_no,
  307. arg_ch->rs_handle,
  308. arg_ch->rs_offset,
  309. write_len);
  310. chunk_off = 0;
  311. while (write_len) {
  312. ret = send_write(xprt, rqstp,
  313. be32_to_cpu(arg_ch->rs_handle),
  314. rs_offset + chunk_off,
  315. xdr_off,
  316. write_len,
  317. vec);
  318. if (ret <= 0)
  319. goto out_err;
  320. chunk_off += ret;
  321. xdr_off += ret;
  322. xfer_len -= ret;
  323. write_len -= ret;
  324. }
  325. }
  326. /* Update the req with the number of chunks actually used */
  327. svc_rdma_xdr_encode_write_list(rdma_resp, chunk_no);
  328. return rqstp->rq_res.page_len;
  329. out_err:
  330. pr_err("svcrdma: failed to send write chunks, rc=%d\n", ret);
  331. return -EIO;
  332. }
  333. noinline
  334. static int send_reply_chunks(struct svcxprt_rdma *xprt,
  335. struct rpcrdma_write_array *rp_ary,
  336. struct rpcrdma_msg *rdma_resp,
  337. struct svc_rqst *rqstp,
  338. struct svc_rdma_req_map *vec)
  339. {
  340. u32 xfer_len = rqstp->rq_res.len;
  341. int write_len;
  342. u32 xdr_off;
  343. int chunk_no;
  344. int chunk_off;
  345. int nchunks;
  346. struct rpcrdma_segment *ch;
  347. struct rpcrdma_write_array *res_ary;
  348. int ret;
  349. /* XXX: need to fix when reply lists occur with read-list and or
  350. * write-list */
  351. res_ary = (struct rpcrdma_write_array *)
  352. &rdma_resp->rm_body.rm_chunks[2];
  353. /* xdr offset starts at RPC message */
  354. nchunks = be32_to_cpu(rp_ary->wc_nchunks);
  355. for (xdr_off = 0, chunk_no = 0;
  356. xfer_len && chunk_no < nchunks;
  357. chunk_no++) {
  358. u64 rs_offset;
  359. ch = &rp_ary->wc_array[chunk_no].wc_target;
  360. write_len = min(xfer_len, be32_to_cpu(ch->rs_length));
  361. /* Prepare the reply chunk given the length actually
  362. * written */
  363. xdr_decode_hyper((__be32 *)&ch->rs_offset, &rs_offset);
  364. svc_rdma_xdr_encode_array_chunk(res_ary, chunk_no,
  365. ch->rs_handle, ch->rs_offset,
  366. write_len);
  367. chunk_off = 0;
  368. while (write_len) {
  369. ret = send_write(xprt, rqstp,
  370. be32_to_cpu(ch->rs_handle),
  371. rs_offset + chunk_off,
  372. xdr_off,
  373. write_len,
  374. vec);
  375. if (ret <= 0)
  376. goto out_err;
  377. chunk_off += ret;
  378. xdr_off += ret;
  379. xfer_len -= ret;
  380. write_len -= ret;
  381. }
  382. }
  383. /* Update the req with the number of chunks actually used */
  384. svc_rdma_xdr_encode_reply_array(res_ary, chunk_no);
  385. return rqstp->rq_res.len;
  386. out_err:
  387. pr_err("svcrdma: failed to send reply chunks, rc=%d\n", ret);
  388. return -EIO;
  389. }
  390. /* This function prepares the portion of the RPCRDMA message to be
  391. * sent in the RDMA_SEND. This function is called after data sent via
  392. * RDMA has already been transmitted. There are three cases:
  393. * - The RPCRDMA header, RPC header, and payload are all sent in a
  394. * single RDMA_SEND. This is the "inline" case.
  395. * - The RPCRDMA header and some portion of the RPC header and data
  396. * are sent via this RDMA_SEND and another portion of the data is
  397. * sent via RDMA.
  398. * - The RPCRDMA header [NOMSG] is sent in this RDMA_SEND and the RPC
  399. * header and data are all transmitted via RDMA.
  400. * In all three cases, this function prepares the RPCRDMA header in
  401. * sge[0], the 'type' parameter indicates the type to place in the
  402. * RPCRDMA header, and the 'byte_count' field indicates how much of
  403. * the XDR to include in this RDMA_SEND. NB: The offset of the payload
  404. * to send is zero in the XDR.
  405. */
  406. static int send_reply(struct svcxprt_rdma *rdma,
  407. struct svc_rqst *rqstp,
  408. struct page *page,
  409. struct rpcrdma_msg *rdma_resp,
  410. struct svc_rdma_req_map *vec,
  411. int byte_count,
  412. u32 inv_rkey)
  413. {
  414. struct svc_rdma_op_ctxt *ctxt;
  415. struct ib_send_wr send_wr;
  416. u32 xdr_off;
  417. int sge_no;
  418. int sge_bytes;
  419. int page_no;
  420. int pages;
  421. int ret = -EIO;
  422. /* Prepare the context */
  423. ctxt = svc_rdma_get_context(rdma);
  424. ctxt->direction = DMA_TO_DEVICE;
  425. ctxt->pages[0] = page;
  426. ctxt->count = 1;
  427. /* Prepare the SGE for the RPCRDMA Header */
  428. ctxt->sge[0].lkey = rdma->sc_pd->local_dma_lkey;
  429. ctxt->sge[0].length = svc_rdma_xdr_get_reply_hdr_len(rdma_resp);
  430. ctxt->sge[0].addr =
  431. ib_dma_map_page(rdma->sc_cm_id->device, page, 0,
  432. ctxt->sge[0].length, DMA_TO_DEVICE);
  433. if (ib_dma_mapping_error(rdma->sc_cm_id->device, ctxt->sge[0].addr))
  434. goto err;
  435. svc_rdma_count_mappings(rdma, ctxt);
  436. ctxt->direction = DMA_TO_DEVICE;
  437. /* Map the payload indicated by 'byte_count' */
  438. xdr_off = 0;
  439. for (sge_no = 1; byte_count && sge_no < vec->count; sge_no++) {
  440. sge_bytes = min_t(size_t, vec->sge[sge_no].iov_len, byte_count);
  441. byte_count -= sge_bytes;
  442. ctxt->sge[sge_no].addr =
  443. dma_map_xdr(rdma, &rqstp->rq_res, xdr_off,
  444. sge_bytes, DMA_TO_DEVICE);
  445. xdr_off += sge_bytes;
  446. if (ib_dma_mapping_error(rdma->sc_cm_id->device,
  447. ctxt->sge[sge_no].addr))
  448. goto err;
  449. svc_rdma_count_mappings(rdma, ctxt);
  450. ctxt->sge[sge_no].lkey = rdma->sc_pd->local_dma_lkey;
  451. ctxt->sge[sge_no].length = sge_bytes;
  452. }
  453. if (byte_count != 0) {
  454. pr_err("svcrdma: Could not map %d bytes\n", byte_count);
  455. goto err;
  456. }
  457. /* Save all respages in the ctxt and remove them from the
  458. * respages array. They are our pages until the I/O
  459. * completes.
  460. */
  461. pages = rqstp->rq_next_page - rqstp->rq_respages;
  462. for (page_no = 0; page_no < pages; page_no++) {
  463. ctxt->pages[page_no+1] = rqstp->rq_respages[page_no];
  464. ctxt->count++;
  465. rqstp->rq_respages[page_no] = NULL;
  466. }
  467. rqstp->rq_next_page = rqstp->rq_respages + 1;
  468. if (sge_no > rdma->sc_max_sge) {
  469. pr_err("svcrdma: Too many sges (%d)\n", sge_no);
  470. goto err;
  471. }
  472. memset(&send_wr, 0, sizeof send_wr);
  473. ctxt->cqe.done = svc_rdma_wc_send;
  474. send_wr.wr_cqe = &ctxt->cqe;
  475. send_wr.sg_list = ctxt->sge;
  476. send_wr.num_sge = sge_no;
  477. if (inv_rkey) {
  478. send_wr.opcode = IB_WR_SEND_WITH_INV;
  479. send_wr.ex.invalidate_rkey = inv_rkey;
  480. } else
  481. send_wr.opcode = IB_WR_SEND;
  482. send_wr.send_flags = IB_SEND_SIGNALED;
  483. ret = svc_rdma_send(rdma, &send_wr);
  484. if (ret)
  485. goto err;
  486. return 0;
  487. err:
  488. svc_rdma_unmap_dma(ctxt);
  489. svc_rdma_put_context(ctxt, 1);
  490. return ret;
  491. }
  492. void svc_rdma_prep_reply_hdr(struct svc_rqst *rqstp)
  493. {
  494. }
  495. int svc_rdma_sendto(struct svc_rqst *rqstp)
  496. {
  497. struct svc_xprt *xprt = rqstp->rq_xprt;
  498. struct svcxprt_rdma *rdma =
  499. container_of(xprt, struct svcxprt_rdma, sc_xprt);
  500. struct rpcrdma_msg *rdma_argp;
  501. struct rpcrdma_msg *rdma_resp;
  502. struct rpcrdma_write_array *wr_ary, *rp_ary;
  503. enum rpcrdma_proc reply_type;
  504. int ret;
  505. int inline_bytes;
  506. struct page *res_page;
  507. struct svc_rdma_req_map *vec;
  508. u32 inv_rkey;
  509. dprintk("svcrdma: sending response for rqstp=%p\n", rqstp);
  510. /* Get the RDMA request header. The receive logic always
  511. * places this at the start of page 0.
  512. */
  513. rdma_argp = page_address(rqstp->rq_pages[0]);
  514. svc_rdma_get_write_arrays(rdma_argp, &wr_ary, &rp_ary);
  515. inv_rkey = 0;
  516. if (rdma->sc_snd_w_inv)
  517. inv_rkey = svc_rdma_get_inv_rkey(rdma_argp, wr_ary, rp_ary);
  518. /* Build an req vec for the XDR */
  519. vec = svc_rdma_get_req_map(rdma);
  520. ret = svc_rdma_map_xdr(rdma, &rqstp->rq_res, vec, wr_ary != NULL);
  521. if (ret)
  522. goto err0;
  523. inline_bytes = rqstp->rq_res.len;
  524. /* Create the RDMA response header. xprt->xpt_mutex,
  525. * acquired in svc_send(), serializes RPC replies. The
  526. * code path below that inserts the credit grant value
  527. * into each transport header runs only inside this
  528. * critical section.
  529. */
  530. ret = -ENOMEM;
  531. res_page = alloc_page(GFP_KERNEL);
  532. if (!res_page)
  533. goto err0;
  534. rdma_resp = page_address(res_page);
  535. if (rp_ary)
  536. reply_type = RDMA_NOMSG;
  537. else
  538. reply_type = RDMA_MSG;
  539. svc_rdma_xdr_encode_reply_header(rdma, rdma_argp,
  540. rdma_resp, reply_type);
  541. /* Send any write-chunk data and build resp write-list */
  542. if (wr_ary) {
  543. ret = send_write_chunks(rdma, wr_ary, rdma_resp, rqstp, vec);
  544. if (ret < 0)
  545. goto err1;
  546. inline_bytes -= ret + xdr_padsize(ret);
  547. }
  548. /* Send any reply-list data and update resp reply-list */
  549. if (rp_ary) {
  550. ret = send_reply_chunks(rdma, rp_ary, rdma_resp, rqstp, vec);
  551. if (ret < 0)
  552. goto err1;
  553. inline_bytes -= ret;
  554. }
  555. /* Post a fresh Receive buffer _before_ sending the reply */
  556. ret = svc_rdma_post_recv(rdma, GFP_KERNEL);
  557. if (ret)
  558. goto err1;
  559. ret = send_reply(rdma, rqstp, res_page, rdma_resp, vec,
  560. inline_bytes, inv_rkey);
  561. if (ret < 0)
  562. goto err0;
  563. svc_rdma_put_req_map(rdma, vec);
  564. dprintk("svcrdma: send_reply returns %d\n", ret);
  565. return ret;
  566. err1:
  567. put_page(res_page);
  568. err0:
  569. svc_rdma_put_req_map(rdma, vec);
  570. pr_err("svcrdma: Could not send reply, err=%d. Closing transport.\n",
  571. ret);
  572. set_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags);
  573. return -ENOTCONN;
  574. }
  575. void svc_rdma_send_error(struct svcxprt_rdma *xprt, struct rpcrdma_msg *rmsgp,
  576. int status)
  577. {
  578. struct ib_send_wr err_wr;
  579. struct page *p;
  580. struct svc_rdma_op_ctxt *ctxt;
  581. enum rpcrdma_errcode err;
  582. __be32 *va;
  583. int length;
  584. int ret;
  585. ret = svc_rdma_repost_recv(xprt, GFP_KERNEL);
  586. if (ret)
  587. return;
  588. p = alloc_page(GFP_KERNEL);
  589. if (!p)
  590. return;
  591. va = page_address(p);
  592. /* XDR encode an error reply */
  593. err = ERR_CHUNK;
  594. if (status == -EPROTONOSUPPORT)
  595. err = ERR_VERS;
  596. length = svc_rdma_xdr_encode_error(xprt, rmsgp, err, va);
  597. ctxt = svc_rdma_get_context(xprt);
  598. ctxt->direction = DMA_TO_DEVICE;
  599. ctxt->count = 1;
  600. ctxt->pages[0] = p;
  601. /* Prepare SGE for local address */
  602. ctxt->sge[0].lkey = xprt->sc_pd->local_dma_lkey;
  603. ctxt->sge[0].length = length;
  604. ctxt->sge[0].addr = ib_dma_map_page(xprt->sc_cm_id->device,
  605. p, 0, length, DMA_TO_DEVICE);
  606. if (ib_dma_mapping_error(xprt->sc_cm_id->device, ctxt->sge[0].addr)) {
  607. dprintk("svcrdma: Error mapping buffer for protocol error\n");
  608. svc_rdma_put_context(ctxt, 1);
  609. return;
  610. }
  611. svc_rdma_count_mappings(xprt, ctxt);
  612. /* Prepare SEND WR */
  613. memset(&err_wr, 0, sizeof(err_wr));
  614. ctxt->cqe.done = svc_rdma_wc_send;
  615. err_wr.wr_cqe = &ctxt->cqe;
  616. err_wr.sg_list = ctxt->sge;
  617. err_wr.num_sge = 1;
  618. err_wr.opcode = IB_WR_SEND;
  619. err_wr.send_flags = IB_SEND_SIGNALED;
  620. /* Post It */
  621. ret = svc_rdma_send(xprt, &err_wr);
  622. if (ret) {
  623. dprintk("svcrdma: Error %d posting send for protocol error\n",
  624. ret);
  625. svc_rdma_unmap_dma(ctxt);
  626. svc_rdma_put_context(ctxt, 1);
  627. }
  628. }