IB/iser: Bump version to 1.6
[linux-2.6-block.git] / drivers / infiniband / ulp / iser / iser_memory.c
CommitLineData
6461f64a
OG
1/*
2 * Copyright (c) 2004, 2005, 2006 Voltaire, Inc. All rights reserved.
3ee07d27 3 * Copyright (c) 2013-2014 Mellanox Technologies. All rights reserved.
6461f64a
OG
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
9 * OpenIB.org BSD license below:
10 *
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
13 * conditions are met:
14 *
15 * - Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer.
18 *
19 * - Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials
22 * provided with the distribution.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 * SOFTWARE.
6461f64a
OG
32 */
33#include <linux/module.h>
34#include <linux/kernel.h>
35#include <linux/slab.h>
36#include <linux/mm.h>
a1f8e7f7 37#include <linux/highmem.h>
6461f64a
OG
38#include <linux/scatterlist.h>
39
40#include "iscsi_iser.h"
41
42#define ISER_KMALLOC_THRESHOLD 0x20000 /* 128K - kmalloc limit */
8dfa0876 43
bd8b944e
SG
44struct fast_reg_descriptor *
45iser_reg_desc_get(struct ib_conn *ib_conn)
46{
47 struct fast_reg_descriptor *desc;
48 unsigned long flags;
49
50 spin_lock_irqsave(&ib_conn->lock, flags);
51 desc = list_first_entry(&ib_conn->fastreg.pool,
52 struct fast_reg_descriptor, list);
53 list_del(&desc->list);
54 spin_unlock_irqrestore(&ib_conn->lock, flags);
55
56 return desc;
57}
58
59void
60iser_reg_desc_put(struct ib_conn *ib_conn,
61 struct fast_reg_descriptor *desc)
62{
63 unsigned long flags;
64
65 spin_lock_irqsave(&ib_conn->lock, flags);
8b95aa2c 66 list_add(&desc->list, &ib_conn->fastreg.pool);
bd8b944e
SG
67 spin_unlock_irqrestore(&ib_conn->lock, flags);
68}
69
6461f64a
OG
70/**
71 * iser_start_rdma_unaligned_sg
72 */
2261ec3d 73static int iser_start_rdma_unaligned_sg(struct iscsi_iser_task *iser_task,
5f588e3d 74 struct iser_data_buf *data,
41179e2d 75 enum iser_data_dir cmd_dir)
6461f64a 76{
a4ee3539 77 struct ib_device *dev = iser_task->iser_conn->ib_conn.device->ib_device;
e3784bd1 78 struct scatterlist *sgl = data->sg;
5f588e3d 79 struct scatterlist *sg;
6461f64a 80 char *mem = NULL;
ecc3993a 81 unsigned long cmd_data_len = data->data_len;
5f588e3d
SG
82 int dma_nents, i;
83
6461f64a 84 if (cmd_data_len > ISER_KMALLOC_THRESHOLD)
528f4e8c 85 mem = (void *)__get_free_pages(GFP_ATOMIC,
f0d1b0b3 86 ilog2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT);
6461f64a 87 else
528f4e8c 88 mem = kmalloc(cmd_data_len, GFP_ATOMIC);
6461f64a
OG
89
90 if (mem == NULL) {
91 iser_err("Failed to allocate mem size %d %d for copying sglist\n",
5f588e3d 92 data->size, (int)cmd_data_len);
6461f64a
OG
93 return -ENOMEM;
94 }
95
96 if (cmd_dir == ISER_DIR_OUT) {
97 /* copy the unaligned sg the buffer which is used for RDMA */
6461f64a
OG
98 char *p, *from;
99
e3784bd1 100 sgl = data->sg;
53d412fc
JA
101 p = mem;
102 for_each_sg(sgl, sg, data->size, i) {
2a156d09 103 from = kmap_atomic(sg_page(sg));
6461f64a 104 memcpy(p,
53d412fc
JA
105 from + sg->offset,
106 sg->length);
2a156d09 107 kunmap_atomic(from);
53d412fc 108 p += sg->length;
6461f64a
OG
109 }
110 }
111
e3784bd1
SG
112 sg_init_one(&data->sg_single, mem, cmd_data_len);
113 data->orig_sg = data->sg;
114 data->sg = &data->sg_single;
115 data->copy_buf = mem;
116 dma_nents = ib_dma_map_sg(dev, data->sg, 1,
5180311f
RC
117 (cmd_dir == ISER_DIR_OUT) ?
118 DMA_TO_DEVICE : DMA_FROM_DEVICE);
6461f64a
OG
119 BUG_ON(dma_nents == 0);
120
e3784bd1 121 data->dma_nents = dma_nents;
5f588e3d 122
6461f64a
OG
123 return 0;
124}
125
126/**
127 * iser_finalize_rdma_unaligned_sg
128 */
9a8b08fa 129
2261ec3d 130void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_task *iser_task,
9a8b08fa 131 struct iser_data_buf *data,
9a8b08fa 132 enum iser_data_dir cmd_dir)
6461f64a 133{
5180311f 134 struct ib_device *dev;
6461f64a
OG
135 unsigned long cmd_data_len;
136
a4ee3539 137 dev = iser_task->iser_conn->ib_conn.device->ib_device;
6461f64a 138
e3784bd1 139 ib_dma_unmap_sg(dev, data->sg, 1,
5180311f
RC
140 (cmd_dir == ISER_DIR_OUT) ?
141 DMA_TO_DEVICE : DMA_FROM_DEVICE);
6461f64a
OG
142
143 if (cmd_dir == ISER_DIR_IN) {
144 char *mem;
53d412fc 145 struct scatterlist *sgl, *sg;
6461f64a
OG
146 unsigned char *p, *to;
147 unsigned int sg_size;
148 int i;
149
150 /* copy back read RDMA to unaligned sg */
e3784bd1 151 mem = data->copy_buf;
6461f64a 152
e3784bd1 153 sgl = data->sg;
9a8b08fa 154 sg_size = data->size;
6461f64a 155
53d412fc
JA
156 p = mem;
157 for_each_sg(sgl, sg, sg_size, i) {
2a156d09 158 to = kmap_atomic(sg_page(sg));
53d412fc 159 memcpy(to + sg->offset,
6461f64a 160 p,
53d412fc 161 sg->length);
2a156d09 162 kunmap_atomic(to);
53d412fc 163 p += sg->length;
6461f64a
OG
164 }
165 }
166
9a8b08fa 167 cmd_data_len = data->data_len;
6461f64a
OG
168
169 if (cmd_data_len > ISER_KMALLOC_THRESHOLD)
e3784bd1 170 free_pages((unsigned long)data->copy_buf,
f0d1b0b3 171 ilog2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT);
6461f64a 172 else
e3784bd1 173 kfree(data->copy_buf);
6461f64a 174
e3784bd1 175 data->copy_buf = NULL;
6461f64a
OG
176}
177
c1ccaf24
OG
178#define IS_4K_ALIGNED(addr) ((((unsigned long)addr) & ~MASK_4K) == 0)
179
6461f64a
OG
180/**
181 * iser_sg_to_page_vec - Translates scatterlist entries to physical addresses
182 * and returns the length of resulting physical address array (may be less than
183 * the original due to possible compaction).
184 *
185 * we build a "page vec" under the assumption that the SG meets the RDMA
186 * alignment requirements. Other then the first and last SG elements, all
187 * the "internal" elements can be compacted into a list whose elements are
188 * dma addresses of physical pages. The code supports also the weird case
189 * where --few fragments of the same page-- are present in the SG as
190 * consecutive elements. Also, it handles one entry SG.
191 */
c1ccaf24 192
6461f64a 193static int iser_sg_to_page_vec(struct iser_data_buf *data,
919fc274
SG
194 struct ib_device *ibdev, u64 *pages,
195 int *offset, int *data_size)
6461f64a 196{
e3784bd1 197 struct scatterlist *sg, *sgl = data->sg;
c1ccaf24 198 u64 start_addr, end_addr, page, chunk_start = 0;
6461f64a 199 unsigned long total_sz = 0;
c1ccaf24
OG
200 unsigned int dma_len;
201 int i, new_chunk, cur_page, last_ent = data->dma_nents - 1;
6461f64a
OG
202
203 /* compute the offset of first element */
919fc274 204 *offset = (u64) sgl[0].offset & ~MASK_4K;
6461f64a 205
c1ccaf24
OG
206 new_chunk = 1;
207 cur_page = 0;
53d412fc 208 for_each_sg(sgl, sg, data->dma_nents, i) {
c1ccaf24
OG
209 start_addr = ib_sg_dma_address(ibdev, sg);
210 if (new_chunk)
211 chunk_start = start_addr;
212 dma_len = ib_sg_dma_len(ibdev, sg);
213 end_addr = start_addr + dma_len;
5180311f 214 total_sz += dma_len;
6461f64a 215
c1ccaf24
OG
216 /* collect page fragments until aligned or end of SG list */
217 if (!IS_4K_ALIGNED(end_addr) && i < last_ent) {
218 new_chunk = 0;
219 continue;
6461f64a 220 }
c1ccaf24
OG
221 new_chunk = 1;
222
223 /* address of the first page in the contiguous chunk;
224 masking relevant for the very first SG entry,
225 which might be unaligned */
226 page = chunk_start & MASK_4K;
227 do {
919fc274 228 pages[cur_page++] = page;
8dfa0876 229 page += SIZE_4K;
c1ccaf24 230 } while (page < end_addr);
6461f64a 231 }
c1ccaf24 232
919fc274
SG
233 *data_size = total_sz;
234 iser_dbg("page_vec->data_size:%d cur_page %d\n",
235 *data_size, cur_page);
6461f64a
OG
236 return cur_page;
237}
238
6461f64a
OG
239
240/**
241 * iser_data_buf_aligned_len - Tries to determine the maximal correctly aligned
242 * for RDMA sub-list of a scatter-gather list of memory buffers, and returns
243 * the number of entries which are aligned correctly. Supports the case where
244 * consecutive SG elements are actually fragments of the same physcial page.
245 */
c1ccaf24
OG
246static int iser_data_buf_aligned_len(struct iser_data_buf *data,
247 struct ib_device *ibdev)
6461f64a 248{
e3784bd1 249 struct scatterlist *sg, *sgl, *next_sg = NULL;
c1ccaf24
OG
250 u64 start_addr, end_addr;
251 int i, ret_len, start_check = 0;
252
253 if (data->dma_nents == 1)
254 return 1;
6461f64a 255
e3784bd1 256 sgl = data->sg;
c1ccaf24 257 start_addr = ib_sg_dma_address(ibdev, sgl);
6461f64a 258
53d412fc 259 for_each_sg(sgl, sg, data->dma_nents, i) {
c1ccaf24
OG
260 if (start_check && !IS_4K_ALIGNED(start_addr))
261 break;
262
263 next_sg = sg_next(sg);
264 if (!next_sg)
265 break;
266
267 end_addr = start_addr + ib_sg_dma_len(ibdev, sg);
268 start_addr = ib_sg_dma_address(ibdev, next_sg);
269
270 if (end_addr == start_addr) {
271 start_check = 0;
272 continue;
273 } else
274 start_check = 1;
275
276 if (!IS_4K_ALIGNED(end_addr))
277 break;
6461f64a 278 }
c1ccaf24 279 ret_len = (next_sg) ? i : i+1;
6461f64a
OG
280 iser_dbg("Found %d aligned entries out of %d in sg:0x%p\n",
281 ret_len, data->dma_nents, data);
282 return ret_len;
283}
284
5180311f
RC
285static void iser_data_buf_dump(struct iser_data_buf *data,
286 struct ib_device *ibdev)
6461f64a 287{
53d412fc 288 struct scatterlist *sg;
6461f64a
OG
289 int i;
290
e3784bd1 291 for_each_sg(data->sg, sg, data->dma_nents, i)
f91424cf 292 iser_dbg("sg[%d] dma_addr:0x%lX page:0x%p "
e981f1d4 293 "off:0x%x sz:0x%x dma_len:0x%x\n",
53d412fc 294 i, (unsigned long)ib_sg_dma_address(ibdev, sg),
45711f1a 295 sg_page(sg), sg->offset,
53d412fc 296 sg->length, ib_sg_dma_len(ibdev, sg));
6461f64a
OG
297}
298
299static void iser_dump_page_vec(struct iser_page_vec *page_vec)
300{
301 int i;
302
303 iser_err("page vec length %d data size %d\n",
304 page_vec->length, page_vec->data_size);
305 for (i = 0; i < page_vec->length; i++)
306 iser_err("%d %lx\n",i,(unsigned long)page_vec->pages[i]);
307}
308
2261ec3d
MC
309int iser_dma_map_task_data(struct iscsi_iser_task *iser_task,
310 struct iser_data_buf *data,
311 enum iser_data_dir iser_dir,
312 enum dma_data_direction dma_dir)
74a20780 313{
5180311f 314 struct ib_device *dev;
74a20780 315
2261ec3d 316 iser_task->dir[iser_dir] = 1;
a4ee3539 317 dev = iser_task->iser_conn->ib_conn.device->ib_device;
74a20780 318
e3784bd1 319 data->dma_nents = ib_dma_map_sg(dev, data->sg, data->size, dma_dir);
74a20780
EZ
320 if (data->dma_nents == 0) {
321 iser_err("dma_map_sg failed!!!\n");
322 return -EINVAL;
323 }
324 return 0;
325}
326
9a8b08fa 327void iser_dma_unmap_task_data(struct iscsi_iser_task *iser_task,
c6c95ef4
RD
328 struct iser_data_buf *data,
329 enum dma_data_direction dir)
74a20780 330{
5180311f 331 struct ib_device *dev;
74a20780 332
a4ee3539 333 dev = iser_task->iser_conn->ib_conn.device->ib_device;
e3784bd1 334 ib_dma_unmap_sg(dev, data->sg, data->size, dir);
74a20780
EZ
335}
336
ad1e5672
SG
337static int
338iser_reg_dma(struct iser_device *device, struct iser_data_buf *mem,
339 struct iser_mem_reg *reg)
340{
341 struct scatterlist *sg = mem->sg;
342
343 reg->sge.lkey = device->mr->lkey;
344 reg->rkey = device->mr->rkey;
345 reg->sge.addr = ib_sg_dma_address(device->ib_device, &sg[0]);
346 reg->sge.length = ib_sg_dma_len(device->ib_device, &sg[0]);
347
348 iser_dbg("Single DMA entry: lkey=0x%x, rkey=0x%x, addr=0x%llx,"
349 " length=0x%x\n", reg->sge.lkey, reg->rkey,
350 reg->sge.addr, reg->sge.length);
351
352 return 0;
353}
354
919fc274 355static int fall_to_bounce_buf(struct iscsi_iser_task *iser_task,
5f588e3d 356 struct iser_data_buf *mem,
919fc274
SG
357 enum iser_data_dir cmd_dir,
358 int aligned_len)
359{
56408325
SG
360 struct iscsi_conn *iscsi_conn = iser_task->iser_conn->iscsi_conn;
361 struct iser_device *device = iser_task->iser_conn->ib_conn.device;
919fc274
SG
362
363 iscsi_conn->fmr_unalign_cnt++;
364 iser_warn("rdma alignment violation (%d/%d aligned) or FMR not supported\n",
365 aligned_len, mem->size);
366
367 if (iser_debug_level > 0)
56408325 368 iser_data_buf_dump(mem, device->ib_device);
919fc274
SG
369
370 /* unmap the command data before accessing it */
c6c95ef4
RD
371 iser_dma_unmap_task_data(iser_task, mem,
372 (cmd_dir == ISER_DIR_OUT) ?
373 DMA_TO_DEVICE : DMA_FROM_DEVICE);
919fc274
SG
374
375 /* allocate copy buf, if we are writing, copy the */
376 /* unaligned scatterlist, dma map the copy */
e3784bd1 377 if (iser_start_rdma_unaligned_sg(iser_task, mem, cmd_dir) != 0)
5f588e3d 378 return -ENOMEM;
919fc274
SG
379
380 return 0;
381}
382
d03e61d0
SG
383/**
384 * iser_reg_page_vec - Register physical memory
385 *
386 * returns: 0 on success, errno code on failure
387 */
388static
f0e35c27
SG
389int iser_reg_page_vec(struct iscsi_iser_task *iser_task,
390 struct iser_data_buf *mem,
d03e61d0 391 struct iser_page_vec *page_vec,
f0e35c27 392 struct iser_mem_reg *mem_reg)
d03e61d0 393{
f0e35c27
SG
394 struct ib_conn *ib_conn = &iser_task->iser_conn->ib_conn;
395 struct iser_device *device = ib_conn->device;
396 struct ib_pool_fmr *fmr;
397 int ret, plen;
398
399 plen = iser_sg_to_page_vec(mem, device->ib_device,
400 page_vec->pages,
401 &page_vec->offset,
402 &page_vec->data_size);
403 page_vec->length = plen;
404 if (plen * SIZE_4K < page_vec->data_size) {
405 iser_err("page vec too short to hold this SG\n");
406 iser_data_buf_dump(mem, device->ib_device);
407 iser_dump_page_vec(page_vec);
408 return -EINVAL;
409 }
d03e61d0 410
f0e35c27
SG
411 fmr = ib_fmr_pool_map_phys(ib_conn->fmr.pool,
412 page_vec->pages,
d03e61d0 413 page_vec->length,
f0e35c27
SG
414 page_vec->pages[0]);
415 if (IS_ERR(fmr)) {
416 ret = PTR_ERR(fmr);
417 iser_err("ib_fmr_pool_map_phys failed: %d\n", ret);
418 return ret;
d03e61d0
SG
419 }
420
90a6684c 421 mem_reg->sge.lkey = fmr->fmr->lkey;
f0e35c27 422 mem_reg->rkey = fmr->fmr->rkey;
90a6684c
SG
423 mem_reg->sge.addr = page_vec->pages[0] + page_vec->offset;
424 mem_reg->sge.length = page_vec->data_size;
f0e35c27
SG
425 mem_reg->mem_h = fmr;
426
d03e61d0
SG
427 return 0;
428}
429
430/**
431 * Unregister (previosuly registered using FMR) memory.
432 * If memory is non-FMR does nothing.
433 */
434void iser_unreg_mem_fmr(struct iscsi_iser_task *iser_task,
435 enum iser_data_dir cmd_dir)
436{
b130eded 437 struct iser_mem_reg *reg = &iser_task->rdma_reg[cmd_dir];
d03e61d0
SG
438 int ret;
439
440 if (!reg->mem_h)
441 return;
442
443 iser_dbg("PHYSICAL Mem.Unregister mem_h %p\n", reg->mem_h);
444
445 ret = ib_fmr_pool_unmap((struct ib_pool_fmr *)reg->mem_h);
446 if (ret)
447 iser_err("ib_fmr_pool_unmap failed %d\n", ret);
448
449 reg->mem_h = NULL;
450}
451
452void iser_unreg_mem_fastreg(struct iscsi_iser_task *iser_task,
453 enum iser_data_dir cmd_dir)
454{
b130eded 455 struct iser_mem_reg *reg = &iser_task->rdma_reg[cmd_dir];
d03e61d0 456
bd8b944e 457 if (!reg->mem_h)
d03e61d0
SG
458 return;
459
bd8b944e
SG
460 iser_reg_desc_put(&iser_task->iser_conn->ib_conn,
461 reg->mem_h);
d03e61d0 462 reg->mem_h = NULL;
d03e61d0
SG
463}
464
6461f64a 465/**
e657571b
SG
466 * iser_reg_rdma_mem_fmr - Registers memory intended for RDMA,
467 * using FMR (if possible) obtaining rkey and va
6461f64a
OG
468 *
469 * returns 0 on success, errno code on failure
470 */
e657571b
SG
471int iser_reg_rdma_mem_fmr(struct iscsi_iser_task *iser_task,
472 enum iser_data_dir cmd_dir)
6461f64a 473{
a4ee3539
SG
474 struct ib_conn *ib_conn = &iser_task->iser_conn->ib_conn;
475 struct iser_device *device = ib_conn->device;
5180311f 476 struct ib_device *ibdev = device->ib_device;
2261ec3d 477 struct iser_data_buf *mem = &iser_task->data[cmd_dir];
b130eded 478 struct iser_mem_reg *mem_reg;
6461f64a
OG
479 int aligned_len;
480 int err;
e981f1d4 481 int i;
6461f64a 482
b130eded 483 mem_reg = &iser_task->rdma_reg[cmd_dir];
6461f64a 484
5180311f 485 aligned_len = iser_data_buf_aligned_len(mem, ibdev);
5587856c 486 if (aligned_len != mem->dma_nents) {
56408325 487 err = fall_to_bounce_buf(iser_task, mem,
919fc274
SG
488 cmd_dir, aligned_len);
489 if (err) {
490 iser_err("failed to allocate bounce buffer\n");
491 return err;
492 }
6461f64a
OG
493 }
494
d8111028
EZ
495 /* if there a single dma entry, FMR is not needed */
496 if (mem->dma_nents == 1) {
ad1e5672 497 return iser_reg_dma(device, mem, mem_reg);
d8111028 498 } else { /* use FMR for multiple dma entries */
f0e35c27 499 err = iser_reg_page_vec(iser_task, mem, ib_conn->fmr.page_vec,
b130eded 500 mem_reg);
819a0873 501 if (err && err != -EAGAIN) {
5180311f 502 iser_data_buf_dump(mem, ibdev);
2261ec3d
MC
503 iser_err("mem->dma_nents = %d (dlength = 0x%x)\n",
504 mem->dma_nents,
505 ntoh24(iser_task->desc.iscsi_header.dlength));
d8111028 506 iser_err("page_vec: data_size = 0x%x, length = %d, offset = 0x%x\n",
a4ee3539
SG
507 ib_conn->fmr.page_vec->data_size,
508 ib_conn->fmr.page_vec->length,
509 ib_conn->fmr.page_vec->offset);
510 for (i = 0; i < ib_conn->fmr.page_vec->length; i++)
d8111028 511 iser_err("page_vec[%d] = 0x%llx\n", i,
a4ee3539 512 (unsigned long long)ib_conn->fmr.page_vec->pages[i]);
e981f1d4 513 }
450d1e40
OG
514 if (err)
515 return err;
e981f1d4 516 }
6461f64a
OG
517 return 0;
518}
5587856c 519
5bb6e543 520static void
92792c0a
SG
521iser_set_dif_domain(struct scsi_cmnd *sc, struct ib_sig_attrs *sig_attrs,
522 struct ib_sig_domain *domain)
523{
78eda2bb 524 domain->sig_type = IB_SIG_TYPE_T10_DIF;
5bb6e543
SG
525 domain->sig.dif.pi_interval = scsi_prot_interval(sc);
526 domain->sig.dif.ref_tag = scsi_prot_ref_tag(sc);
78eda2bb
SG
527 /*
528 * At the moment we hard code those, but in the future
529 * we will take them from sc.
530 */
531 domain->sig.dif.apptag_check_mask = 0xffff;
532 domain->sig.dif.app_escape = true;
533 domain->sig.dif.ref_escape = true;
5bb6e543 534 if (sc->prot_flags & SCSI_PROT_REF_INCREMENT)
78eda2bb 535 domain->sig.dif.ref_remap = true;
92792c0a 536};
177e31bd
SG
537
538static int
539iser_set_sig_attrs(struct scsi_cmnd *sc, struct ib_sig_attrs *sig_attrs)
540{
177e31bd
SG
541 switch (scsi_get_prot_op(sc)) {
542 case SCSI_PROT_WRITE_INSERT:
543 case SCSI_PROT_READ_STRIP:
78eda2bb 544 sig_attrs->mem.sig_type = IB_SIG_TYPE_NONE;
92792c0a 545 iser_set_dif_domain(sc, sig_attrs, &sig_attrs->wire);
177e31bd 546 sig_attrs->wire.sig.dif.bg_type = IB_T10DIF_CRC;
177e31bd
SG
547 break;
548 case SCSI_PROT_READ_INSERT:
549 case SCSI_PROT_WRITE_STRIP:
78eda2bb 550 sig_attrs->wire.sig_type = IB_SIG_TYPE_NONE;
92792c0a 551 iser_set_dif_domain(sc, sig_attrs, &sig_attrs->mem);
5bb6e543
SG
552 sig_attrs->mem.sig.dif.bg_type = sc->prot_flags & SCSI_PROT_IP_CHECKSUM ?
553 IB_T10DIF_CSUM : IB_T10DIF_CRC;
177e31bd
SG
554 break;
555 case SCSI_PROT_READ_PASS:
556 case SCSI_PROT_WRITE_PASS:
92792c0a 557 iser_set_dif_domain(sc, sig_attrs, &sig_attrs->wire);
177e31bd 558 sig_attrs->wire.sig.dif.bg_type = IB_T10DIF_CRC;
92792c0a 559 iser_set_dif_domain(sc, sig_attrs, &sig_attrs->mem);
5bb6e543
SG
560 sig_attrs->mem.sig.dif.bg_type = sc->prot_flags & SCSI_PROT_IP_CHECKSUM ?
561 IB_T10DIF_CSUM : IB_T10DIF_CRC;
177e31bd
SG
562 break;
563 default:
564 iser_err("Unsupported PI operation %d\n",
565 scsi_get_prot_op(sc));
566 return -EINVAL;
567 }
78eda2bb 568
177e31bd
SG
569 return 0;
570}
571
5bb6e543 572static inline void
177e31bd
SG
573iser_set_prot_checks(struct scsi_cmnd *sc, u8 *mask)
574{
5bb6e543
SG
575 *mask = 0;
576 if (sc->prot_flags & SCSI_PROT_REF_CHECK)
577 *mask |= ISER_CHECK_REFTAG;
578 if (sc->prot_flags & SCSI_PROT_GUARD_CHECK)
579 *mask |= ISER_CHECK_GUARD;
177e31bd
SG
580}
581
a11b3e69
SG
582static void
583iser_inv_rkey(struct ib_send_wr *inv_wr, struct ib_mr *mr)
584{
585 u32 rkey;
586
587 memset(inv_wr, 0, sizeof(*inv_wr));
588 inv_wr->opcode = IB_WR_LOCAL_INV;
589 inv_wr->wr_id = ISER_FASTREG_LI_WRID;
590 inv_wr->ex.invalidate_rkey = mr->rkey;
591
592 rkey = ib_inc_rkey(mr->rkey);
593 ib_update_fast_reg_key(mr, rkey);
594}
595
177e31bd
SG
596static int
597iser_reg_sig_mr(struct iscsi_iser_task *iser_task,
6ef8bb83
SG
598 struct fast_reg_descriptor *desc,
599 struct iser_mem_reg *data_reg,
600 struct iser_mem_reg *prot_reg,
601 struct iser_mem_reg *sig_reg)
177e31bd 602{
a4ee3539 603 struct ib_conn *ib_conn = &iser_task->iser_conn->ib_conn;
177e31bd
SG
604 struct iser_pi_context *pi_ctx = desc->pi_ctx;
605 struct ib_send_wr sig_wr, inv_wr;
606 struct ib_send_wr *bad_wr, *wr = NULL;
607 struct ib_sig_attrs sig_attrs;
608 int ret;
177e31bd
SG
609
610 memset(&sig_attrs, 0, sizeof(sig_attrs));
611 ret = iser_set_sig_attrs(iser_task->sc, &sig_attrs);
612 if (ret)
613 goto err;
614
5bb6e543 615 iser_set_prot_checks(iser_task->sc, &sig_attrs.check_mask);
177e31bd
SG
616
617 if (!(desc->reg_indicators & ISER_SIG_KEY_VALID)) {
a11b3e69 618 iser_inv_rkey(&inv_wr, pi_ctx->sig_mr);
177e31bd 619 wr = &inv_wr;
177e31bd
SG
620 }
621
622 memset(&sig_wr, 0, sizeof(sig_wr));
623 sig_wr.opcode = IB_WR_REG_SIG_MR;
624 sig_wr.wr_id = ISER_FASTREG_LI_WRID;
6ef8bb83 625 sig_wr.sg_list = &data_reg->sge;
177e31bd
SG
626 sig_wr.num_sge = 1;
627 sig_wr.wr.sig_handover.sig_attrs = &sig_attrs;
628 sig_wr.wr.sig_handover.sig_mr = pi_ctx->sig_mr;
629 if (scsi_prot_sg_count(iser_task->sc))
6ef8bb83 630 sig_wr.wr.sig_handover.prot = &prot_reg->sge;
177e31bd
SG
631 sig_wr.wr.sig_handover.access_flags = IB_ACCESS_LOCAL_WRITE |
632 IB_ACCESS_REMOTE_READ |
633 IB_ACCESS_REMOTE_WRITE;
634
635 if (!wr)
636 wr = &sig_wr;
637 else
638 wr->next = &sig_wr;
639
a4ee3539 640 ret = ib_post_send(ib_conn->qp, wr, &bad_wr);
177e31bd
SG
641 if (ret) {
642 iser_err("reg_sig_mr failed, ret:%d\n", ret);
643 goto err;
644 }
645 desc->reg_indicators &= ~ISER_SIG_KEY_VALID;
646
6ef8bb83
SG
647 sig_reg->sge.lkey = pi_ctx->sig_mr->lkey;
648 sig_reg->rkey = pi_ctx->sig_mr->rkey;
649 sig_reg->sge.addr = 0;
650 sig_reg->sge.length = scsi_transfer_length(iser_task->sc);
177e31bd 651
6ef8bb83
SG
652 iser_dbg("sig_sge: lkey: 0x%x, rkey: 0x%x, addr: 0x%llx, length: %u\n",
653 sig_reg->sge.lkey, sig_reg->rkey, sig_reg->sge.addr,
654 sig_reg->sge.length);
177e31bd
SG
655err:
656 return ret;
657}
658
d11ec4ec 659static int iser_fast_reg_mr(struct iscsi_iser_task *iser_task,
d11ec4ec 660 struct iser_data_buf *mem,
6ef8bb83 661 struct fast_reg_descriptor *desc,
177e31bd 662 enum iser_reg_indicator ind,
6ef8bb83 663 struct iser_mem_reg *reg)
5587856c 664{
a4ee3539
SG
665 struct ib_conn *ib_conn = &iser_task->iser_conn->ib_conn;
666 struct iser_device *device = ib_conn->device;
177e31bd
SG
667 struct ib_mr *mr;
668 struct ib_fast_reg_page_list *frpl;
5587856c
SG
669 struct ib_send_wr fastreg_wr, inv_wr;
670 struct ib_send_wr *bad_wr, *wr = NULL;
d11ec4ec
SG
671 int ret, offset, size, plen;
672
673 /* if there a single dma entry, dma mr suffices */
ad1e5672
SG
674 if (mem->dma_nents == 1)
675 return iser_reg_dma(device, mem, reg);
d11ec4ec 676
177e31bd
SG
677 if (ind == ISER_DATA_KEY_VALID) {
678 mr = desc->data_mr;
679 frpl = desc->data_frpl;
680 } else {
681 mr = desc->pi_ctx->prot_mr;
682 frpl = desc->pi_ctx->prot_frpl;
683 }
684
685 plen = iser_sg_to_page_vec(mem, device->ib_device, frpl->page_list,
d11ec4ec
SG
686 &offset, &size);
687 if (plen * SIZE_4K < size) {
688 iser_err("fast reg page_list too short to hold this SG\n");
689 return -EINVAL;
690 }
5587856c 691
177e31bd 692 if (!(desc->reg_indicators & ind)) {
a11b3e69 693 iser_inv_rkey(&inv_wr, mr);
5587856c 694 wr = &inv_wr;
5587856c
SG
695 }
696
697 /* Prepare FASTREG WR */
698 memset(&fastreg_wr, 0, sizeof(fastreg_wr));
7306b8fa 699 fastreg_wr.wr_id = ISER_FASTREG_LI_WRID;
5587856c 700 fastreg_wr.opcode = IB_WR_FAST_REG_MR;
177e31bd
SG
701 fastreg_wr.wr.fast_reg.iova_start = frpl->page_list[0] + offset;
702 fastreg_wr.wr.fast_reg.page_list = frpl;
d11ec4ec 703 fastreg_wr.wr.fast_reg.page_list_len = plen;
5587856c 704 fastreg_wr.wr.fast_reg.page_shift = SHIFT_4K;
d11ec4ec 705 fastreg_wr.wr.fast_reg.length = size;
177e31bd 706 fastreg_wr.wr.fast_reg.rkey = mr->rkey;
5587856c
SG
707 fastreg_wr.wr.fast_reg.access_flags = (IB_ACCESS_LOCAL_WRITE |
708 IB_ACCESS_REMOTE_WRITE |
709 IB_ACCESS_REMOTE_READ);
710
db523b8d 711 if (!wr)
5587856c 712 wr = &fastreg_wr;
db523b8d 713 else
5587856c 714 wr->next = &fastreg_wr;
5587856c 715
a4ee3539 716 ret = ib_post_send(ib_conn->qp, wr, &bad_wr);
5587856c 717 if (ret) {
5587856c
SG
718 iser_err("fast registration failed, ret:%d\n", ret);
719 return ret;
720 }
177e31bd 721 desc->reg_indicators &= ~ind;
5587856c 722
6ef8bb83
SG
723 reg->sge.lkey = mr->lkey;
724 reg->rkey = mr->rkey;
725 reg->sge.addr = frpl->page_list[0] + offset;
726 reg->sge.length = size;
5587856c
SG
727
728 return ret;
729}
730
731/**
7306b8fa 732 * iser_reg_rdma_mem_fastreg - Registers memory intended for RDMA,
5587856c
SG
733 * using Fast Registration WR (if possible) obtaining rkey and va
734 *
735 * returns 0 on success, errno code on failure
736 */
7306b8fa
SG
737int iser_reg_rdma_mem_fastreg(struct iscsi_iser_task *iser_task,
738 enum iser_data_dir cmd_dir)
5587856c 739{
a4ee3539
SG
740 struct ib_conn *ib_conn = &iser_task->iser_conn->ib_conn;
741 struct iser_device *device = ib_conn->device;
5587856c
SG
742 struct ib_device *ibdev = device->ib_device;
743 struct iser_data_buf *mem = &iser_task->data[cmd_dir];
b130eded 744 struct iser_mem_reg *mem_reg = &iser_task->rdma_reg[cmd_dir];
d11ec4ec 745 struct fast_reg_descriptor *desc = NULL;
5587856c 746 int err, aligned_len;
5587856c
SG
747
748 aligned_len = iser_data_buf_aligned_len(mem, ibdev);
749 if (aligned_len != mem->dma_nents) {
56408325 750 err = fall_to_bounce_buf(iser_task, mem,
5587856c
SG
751 cmd_dir, aligned_len);
752 if (err) {
753 iser_err("failed to allocate bounce buffer\n");
754 return err;
755 }
5587856c
SG
756 }
757
177e31bd
SG
758 if (mem->dma_nents != 1 ||
759 scsi_get_prot_op(iser_task->sc) != SCSI_PROT_NORMAL) {
bd8b944e 760 desc = iser_reg_desc_get(ib_conn);
b130eded 761 mem_reg->mem_h = desc;
d11ec4ec 762 }
5587856c 763
6ef8bb83
SG
764 err = iser_fast_reg_mr(iser_task, mem, desc,
765 ISER_DATA_KEY_VALID, mem_reg);
d11ec4ec
SG
766 if (err)
767 goto err_reg;
768
177e31bd 769 if (scsi_get_prot_op(iser_task->sc) != SCSI_PROT_NORMAL) {
6ef8bb83 770 struct iser_mem_reg prot_reg;
177e31bd 771
6ef8bb83 772 memset(&prot_reg, 0, sizeof(prot_reg));
177e31bd
SG
773 if (scsi_prot_sg_count(iser_task->sc)) {
774 mem = &iser_task->prot[cmd_dir];
775 aligned_len = iser_data_buf_aligned_len(mem, ibdev);
776 if (aligned_len != mem->dma_nents) {
56408325 777 err = fall_to_bounce_buf(iser_task, mem,
177e31bd
SG
778 cmd_dir, aligned_len);
779 if (err) {
780 iser_err("failed to allocate bounce buffer\n");
781 return err;
782 }
177e31bd
SG
783 }
784
6ef8bb83
SG
785 err = iser_fast_reg_mr(iser_task, mem, desc,
786 ISER_PROT_KEY_VALID, &prot_reg);
177e31bd
SG
787 if (err)
788 goto err_reg;
789 }
790
6ef8bb83
SG
791 err = iser_reg_sig_mr(iser_task, desc, mem_reg,
792 &prot_reg, mem_reg);
177e31bd
SG
793 if (err) {
794 iser_err("Failed to register signature mr\n");
795 return err;
796 }
797 desc->reg_indicators |= ISER_FASTREG_PROTECTED;
177e31bd 798 }
d11ec4ec 799
5587856c
SG
800 return 0;
801err_reg:
bd8b944e
SG
802 if (desc)
803 iser_reg_desc_put(ib_conn, desc);
d11ec4ec 804
5587856c
SG
805 return err;
806}