]>
Commit | Line | Data |
---|---|---|
6461f64a OG |
1 | /* |
2 | * Copyright (c) 2004, 2005, 2006 Voltaire, Inc. All rights reserved. | |
3 | * | |
4 | * This software is available to you under a choice of one of two | |
5 | * licenses. You may choose to be licensed under the terms of the GNU | |
6 | * General Public License (GPL) Version 2, available from the file | |
7 | * COPYING in the main directory of this source tree, or the | |
8 | * OpenIB.org BSD license below: | |
9 | * | |
10 | * Redistribution and use in source and binary forms, with or | |
11 | * without modification, are permitted provided that the following | |
12 | * conditions are met: | |
13 | * | |
14 | * - Redistributions of source code must retain the above | |
15 | * copyright notice, this list of conditions and the following | |
16 | * 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 | |
21 | * provided with the distribution. | |
22 | * | |
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
25 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
26 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |
27 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |
28 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
29 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
30 | * SOFTWARE. | |
31 | * | |
32 | * $Id: iser_memory.c 6964 2006-05-07 11:11:43Z ogerlitz $ | |
33 | */ | |
34 | #include <linux/module.h> | |
35 | #include <linux/kernel.h> | |
36 | #include <linux/slab.h> | |
37 | #include <linux/mm.h> | |
a1f8e7f7 | 38 | #include <linux/highmem.h> |
6461f64a OG |
39 | #include <linux/scatterlist.h> |
40 | ||
41 | #include "iscsi_iser.h" | |
42 | ||
43 | #define ISER_KMALLOC_THRESHOLD 0x20000 /* 128K - kmalloc limit */ | |
8dfa0876 | 44 | |
6461f64a OG |
45 | /** |
46 | * Decrements the reference count for the | |
47 | * registered buffer & releases it | |
48 | * | |
49 | * returns 0 if released, 1 if deferred | |
50 | */ | |
51 | int iser_regd_buff_release(struct iser_regd_buf *regd_buf) | |
52 | { | |
5180311f | 53 | struct ib_device *dev; |
6461f64a OG |
54 | |
55 | if ((atomic_read(®d_buf->ref_count) == 0) || | |
56 | atomic_dec_and_test(®d_buf->ref_count)) { | |
57 | /* if we used the dma mr, unreg is just NOP */ | |
d8111028 | 58 | if (regd_buf->reg.is_fmr) |
6461f64a OG |
59 | iser_unreg_mem(®d_buf->reg); |
60 | ||
61 | if (regd_buf->dma_addr) { | |
5180311f RC |
62 | dev = regd_buf->device->ib_device; |
63 | ib_dma_unmap_single(dev, | |
6461f64a OG |
64 | regd_buf->dma_addr, |
65 | regd_buf->data_size, | |
66 | regd_buf->direction); | |
67 | } | |
68 | /* else this regd buf is associated with task which we */ | |
69 | /* dma_unmap_single/sg later */ | |
70 | return 0; | |
71 | } else { | |
72 | iser_dbg("Release deferred, regd.buff: 0x%p\n", regd_buf); | |
73 | return 1; | |
74 | } | |
75 | } | |
76 | ||
77 | /** | |
78 | * iser_reg_single - fills registered buffer descriptor with | |
79 | * registration information | |
80 | */ | |
81 | void iser_reg_single(struct iser_device *device, | |
82 | struct iser_regd_buf *regd_buf, | |
83 | enum dma_data_direction direction) | |
84 | { | |
5180311f | 85 | u64 dma_addr; |
6461f64a | 86 | |
5180311f RC |
87 | dma_addr = ib_dma_map_single(device->ib_device, |
88 | regd_buf->virt_addr, | |
89 | regd_buf->data_size, direction); | |
90 | BUG_ON(ib_dma_mapping_error(device->ib_device, dma_addr)); | |
6461f64a OG |
91 | |
92 | regd_buf->reg.lkey = device->mr->lkey; | |
6461f64a OG |
93 | regd_buf->reg.len = regd_buf->data_size; |
94 | regd_buf->reg.va = dma_addr; | |
d8111028 | 95 | regd_buf->reg.is_fmr = 0; |
6461f64a OG |
96 | |
97 | regd_buf->dma_addr = dma_addr; | |
98 | regd_buf->direction = direction; | |
99 | } | |
100 | ||
101 | /** | |
102 | * iser_start_rdma_unaligned_sg | |
103 | */ | |
2261ec3d | 104 | static int iser_start_rdma_unaligned_sg(struct iscsi_iser_task *iser_task, |
41179e2d | 105 | enum iser_data_dir cmd_dir) |
6461f64a OG |
106 | { |
107 | int dma_nents; | |
5180311f | 108 | struct ib_device *dev; |
6461f64a | 109 | char *mem = NULL; |
2261ec3d | 110 | struct iser_data_buf *data = &iser_task->data[cmd_dir]; |
6461f64a OG |
111 | unsigned long cmd_data_len = data->data_len; |
112 | ||
113 | if (cmd_data_len > ISER_KMALLOC_THRESHOLD) | |
114 | mem = (void *)__get_free_pages(GFP_NOIO, | |
f0d1b0b3 | 115 | ilog2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT); |
6461f64a OG |
116 | else |
117 | mem = kmalloc(cmd_data_len, GFP_NOIO); | |
118 | ||
119 | if (mem == NULL) { | |
120 | iser_err("Failed to allocate mem size %d %d for copying sglist\n", | |
121 | data->size,(int)cmd_data_len); | |
122 | return -ENOMEM; | |
123 | } | |
124 | ||
125 | if (cmd_dir == ISER_DIR_OUT) { | |
126 | /* copy the unaligned sg the buffer which is used for RDMA */ | |
53d412fc JA |
127 | struct scatterlist *sgl = (struct scatterlist *)data->buf; |
128 | struct scatterlist *sg; | |
6461f64a OG |
129 | int i; |
130 | char *p, *from; | |
131 | ||
53d412fc JA |
132 | p = mem; |
133 | for_each_sg(sgl, sg, data->size, i) { | |
45711f1a | 134 | from = kmap_atomic(sg_page(sg), KM_USER0); |
6461f64a | 135 | memcpy(p, |
53d412fc JA |
136 | from + sg->offset, |
137 | sg->length); | |
6461f64a | 138 | kunmap_atomic(from, KM_USER0); |
53d412fc | 139 | p += sg->length; |
6461f64a OG |
140 | } |
141 | } | |
142 | ||
2261ec3d MC |
143 | sg_init_one(&iser_task->data_copy[cmd_dir].sg_single, mem, cmd_data_len); |
144 | iser_task->data_copy[cmd_dir].buf = | |
145 | &iser_task->data_copy[cmd_dir].sg_single; | |
146 | iser_task->data_copy[cmd_dir].size = 1; | |
6461f64a | 147 | |
2261ec3d | 148 | iser_task->data_copy[cmd_dir].copy_buf = mem; |
6461f64a | 149 | |
2261ec3d | 150 | dev = iser_task->iser_conn->ib_conn->device->ib_device; |
5180311f | 151 | dma_nents = ib_dma_map_sg(dev, |
2261ec3d | 152 | &iser_task->data_copy[cmd_dir].sg_single, |
5180311f RC |
153 | 1, |
154 | (cmd_dir == ISER_DIR_OUT) ? | |
155 | DMA_TO_DEVICE : DMA_FROM_DEVICE); | |
6461f64a OG |
156 | BUG_ON(dma_nents == 0); |
157 | ||
2261ec3d | 158 | iser_task->data_copy[cmd_dir].dma_nents = dma_nents; |
6461f64a OG |
159 | return 0; |
160 | } | |
161 | ||
162 | /** | |
163 | * iser_finalize_rdma_unaligned_sg | |
164 | */ | |
2261ec3d | 165 | void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_task *iser_task, |
6461f64a OG |
166 | enum iser_data_dir cmd_dir) |
167 | { | |
5180311f | 168 | struct ib_device *dev; |
6461f64a OG |
169 | struct iser_data_buf *mem_copy; |
170 | unsigned long cmd_data_len; | |
171 | ||
2261ec3d MC |
172 | dev = iser_task->iser_conn->ib_conn->device->ib_device; |
173 | mem_copy = &iser_task->data_copy[cmd_dir]; | |
6461f64a | 174 | |
5180311f RC |
175 | ib_dma_unmap_sg(dev, &mem_copy->sg_single, 1, |
176 | (cmd_dir == ISER_DIR_OUT) ? | |
177 | DMA_TO_DEVICE : DMA_FROM_DEVICE); | |
6461f64a OG |
178 | |
179 | if (cmd_dir == ISER_DIR_IN) { | |
180 | char *mem; | |
53d412fc | 181 | struct scatterlist *sgl, *sg; |
6461f64a OG |
182 | unsigned char *p, *to; |
183 | unsigned int sg_size; | |
184 | int i; | |
185 | ||
186 | /* copy back read RDMA to unaligned sg */ | |
187 | mem = mem_copy->copy_buf; | |
188 | ||
2261ec3d MC |
189 | sgl = (struct scatterlist *)iser_task->data[ISER_DIR_IN].buf; |
190 | sg_size = iser_task->data[ISER_DIR_IN].size; | |
6461f64a | 191 | |
53d412fc JA |
192 | p = mem; |
193 | for_each_sg(sgl, sg, sg_size, i) { | |
45711f1a | 194 | to = kmap_atomic(sg_page(sg), KM_SOFTIRQ0); |
53d412fc | 195 | memcpy(to + sg->offset, |
6461f64a | 196 | p, |
53d412fc | 197 | sg->length); |
6461f64a | 198 | kunmap_atomic(to, KM_SOFTIRQ0); |
53d412fc | 199 | p += sg->length; |
6461f64a OG |
200 | } |
201 | } | |
202 | ||
2261ec3d | 203 | cmd_data_len = iser_task->data[cmd_dir].data_len; |
6461f64a OG |
204 | |
205 | if (cmd_data_len > ISER_KMALLOC_THRESHOLD) | |
206 | free_pages((unsigned long)mem_copy->copy_buf, | |
f0d1b0b3 | 207 | ilog2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT); |
6461f64a OG |
208 | else |
209 | kfree(mem_copy->copy_buf); | |
210 | ||
211 | mem_copy->copy_buf = NULL; | |
212 | } | |
213 | ||
214 | /** | |
215 | * iser_sg_to_page_vec - Translates scatterlist entries to physical addresses | |
216 | * and returns the length of resulting physical address array (may be less than | |
217 | * the original due to possible compaction). | |
218 | * | |
219 | * we build a "page vec" under the assumption that the SG meets the RDMA | |
220 | * alignment requirements. Other then the first and last SG elements, all | |
221 | * the "internal" elements can be compacted into a list whose elements are | |
222 | * dma addresses of physical pages. The code supports also the weird case | |
223 | * where --few fragments of the same page-- are present in the SG as | |
224 | * consecutive elements. Also, it handles one entry SG. | |
225 | */ | |
226 | static int iser_sg_to_page_vec(struct iser_data_buf *data, | |
5180311f RC |
227 | struct iser_page_vec *page_vec, |
228 | struct ib_device *ibdev) | |
6461f64a | 229 | { |
53d412fc JA |
230 | struct scatterlist *sgl = (struct scatterlist *)data->buf; |
231 | struct scatterlist *sg; | |
5180311f | 232 | u64 first_addr, last_addr, page; |
dee234f4 | 233 | int end_aligned; |
6461f64a OG |
234 | unsigned int cur_page = 0; |
235 | unsigned long total_sz = 0; | |
236 | int i; | |
237 | ||
238 | /* compute the offset of first element */ | |
53d412fc | 239 | page_vec->offset = (u64) sgl[0].offset & ~MASK_4K; |
6461f64a | 240 | |
53d412fc JA |
241 | for_each_sg(sgl, sg, data->dma_nents, i) { |
242 | unsigned int dma_len = ib_sg_dma_len(ibdev, sg); | |
5180311f RC |
243 | |
244 | total_sz += dma_len; | |
6461f64a | 245 | |
53d412fc | 246 | first_addr = ib_sg_dma_address(ibdev, sg); |
5180311f | 247 | last_addr = first_addr + dma_len; |
6461f64a | 248 | |
8dfa0876 | 249 | end_aligned = !(last_addr & ~MASK_4K); |
6461f64a OG |
250 | |
251 | /* continue to collect page fragments till aligned or SG ends */ | |
252 | while (!end_aligned && (i + 1 < data->dma_nents)) { | |
53d412fc | 253 | sg = sg_next(sg); |
6461f64a | 254 | i++; |
53d412fc | 255 | dma_len = ib_sg_dma_len(ibdev, sg); |
5180311f | 256 | total_sz += dma_len; |
53d412fc | 257 | last_addr = ib_sg_dma_address(ibdev, sg) + dma_len; |
8dfa0876 | 258 | end_aligned = !(last_addr & ~MASK_4K); |
6461f64a OG |
259 | } |
260 | ||
8dfa0876 EZ |
261 | /* handle the 1st page in the 1st DMA element */ |
262 | if (cur_page == 0) { | |
263 | page = first_addr & MASK_4K; | |
264 | page_vec->pages[cur_page] = page; | |
265 | cur_page++; | |
266 | page += SIZE_4K; | |
267 | } else | |
268 | page = first_addr; | |
269 | ||
270 | for (; page < last_addr; page += SIZE_4K) { | |
271 | page_vec->pages[cur_page] = page; | |
272 | cur_page++; | |
273 | } | |
6461f64a OG |
274 | |
275 | } | |
276 | page_vec->data_size = total_sz; | |
277 | iser_dbg("page_vec->data_size:%d cur_page %d\n", page_vec->data_size,cur_page); | |
278 | return cur_page; | |
279 | } | |
280 | ||
8dfa0876 | 281 | #define IS_4K_ALIGNED(addr) ((((unsigned long)addr) & ~MASK_4K) == 0) |
6461f64a OG |
282 | |
283 | /** | |
284 | * iser_data_buf_aligned_len - Tries to determine the maximal correctly aligned | |
285 | * for RDMA sub-list of a scatter-gather list of memory buffers, and returns | |
286 | * the number of entries which are aligned correctly. Supports the case where | |
287 | * consecutive SG elements are actually fragments of the same physcial page. | |
288 | */ | |
5180311f RC |
289 | static unsigned int iser_data_buf_aligned_len(struct iser_data_buf *data, |
290 | struct ib_device *ibdev) | |
6461f64a | 291 | { |
53d412fc | 292 | struct scatterlist *sgl, *sg; |
5180311f | 293 | u64 end_addr, next_addr; |
6461f64a OG |
294 | int i, cnt; |
295 | unsigned int ret_len = 0; | |
296 | ||
53d412fc | 297 | sgl = (struct scatterlist *)data->buf; |
6461f64a | 298 | |
53d412fc JA |
299 | cnt = 0; |
300 | for_each_sg(sgl, sg, data->dma_nents, i) { | |
6461f64a OG |
301 | /* iser_dbg("Checking sg iobuf [%d]: phys=0x%08lX " |
302 | "offset: %ld sz: %ld\n", i, | |
45711f1a | 303 | (unsigned long)sg_phys(sg), |
53d412fc JA |
304 | (unsigned long)sg->offset, |
305 | (unsigned long)sg->length); */ | |
306 | end_addr = ib_sg_dma_address(ibdev, sg) + | |
307 | ib_sg_dma_len(ibdev, sg); | |
6461f64a OG |
308 | /* iser_dbg("Checking sg iobuf end address " |
309 | "0x%08lX\n", end_addr); */ | |
310 | if (i + 1 < data->dma_nents) { | |
53d412fc | 311 | next_addr = ib_sg_dma_address(ibdev, sg_next(sg)); |
6461f64a | 312 | /* are i, i+1 fragments of the same page? */ |
a316b79c EZ |
313 | if (end_addr == next_addr) { |
314 | cnt++; | |
6461f64a | 315 | continue; |
a316b79c | 316 | } else if (!IS_4K_ALIGNED(end_addr)) { |
6461f64a OG |
317 | ret_len = cnt + 1; |
318 | break; | |
319 | } | |
320 | } | |
a316b79c | 321 | cnt++; |
6461f64a OG |
322 | } |
323 | if (i == data->dma_nents) | |
324 | ret_len = cnt; /* loop ended */ | |
325 | iser_dbg("Found %d aligned entries out of %d in sg:0x%p\n", | |
326 | ret_len, data->dma_nents, data); | |
327 | return ret_len; | |
328 | } | |
329 | ||
5180311f RC |
330 | static void iser_data_buf_dump(struct iser_data_buf *data, |
331 | struct ib_device *ibdev) | |
6461f64a | 332 | { |
53d412fc JA |
333 | struct scatterlist *sgl = (struct scatterlist *)data->buf; |
334 | struct scatterlist *sg; | |
6461f64a OG |
335 | int i; |
336 | ||
6f735e36 ED |
337 | if (iser_debug_level == 0) |
338 | return; | |
339 | ||
53d412fc | 340 | for_each_sg(sgl, sg, data->dma_nents, i) |
6f735e36 | 341 | iser_warn("sg[%d] dma_addr:0x%lX page:0x%p " |
e981f1d4 | 342 | "off:0x%x sz:0x%x dma_len:0x%x\n", |
53d412fc | 343 | i, (unsigned long)ib_sg_dma_address(ibdev, sg), |
45711f1a | 344 | sg_page(sg), sg->offset, |
53d412fc | 345 | sg->length, ib_sg_dma_len(ibdev, sg)); |
6461f64a OG |
346 | } |
347 | ||
348 | static void iser_dump_page_vec(struct iser_page_vec *page_vec) | |
349 | { | |
350 | int i; | |
351 | ||
352 | iser_err("page vec length %d data size %d\n", | |
353 | page_vec->length, page_vec->data_size); | |
354 | for (i = 0; i < page_vec->length; i++) | |
355 | iser_err("%d %lx\n",i,(unsigned long)page_vec->pages[i]); | |
356 | } | |
357 | ||
358 | static void iser_page_vec_build(struct iser_data_buf *data, | |
5180311f RC |
359 | struct iser_page_vec *page_vec, |
360 | struct ib_device *ibdev) | |
6461f64a OG |
361 | { |
362 | int page_vec_len = 0; | |
363 | ||
364 | page_vec->length = 0; | |
365 | page_vec->offset = 0; | |
366 | ||
367 | iser_dbg("Translating sg sz: %d\n", data->dma_nents); | |
5180311f | 368 | page_vec_len = iser_sg_to_page_vec(data, page_vec, ibdev); |
6461f64a OG |
369 | iser_dbg("sg len %d page_vec_len %d\n", data->dma_nents,page_vec_len); |
370 | ||
371 | page_vec->length = page_vec_len; | |
372 | ||
8dfa0876 | 373 | if (page_vec_len * SIZE_4K < page_vec->data_size) { |
6461f64a | 374 | iser_err("page_vec too short to hold this SG\n"); |
5180311f | 375 | iser_data_buf_dump(data, ibdev); |
6461f64a OG |
376 | iser_dump_page_vec(page_vec); |
377 | BUG(); | |
378 | } | |
379 | } | |
380 | ||
2261ec3d MC |
381 | int iser_dma_map_task_data(struct iscsi_iser_task *iser_task, |
382 | struct iser_data_buf *data, | |
383 | enum iser_data_dir iser_dir, | |
384 | enum dma_data_direction dma_dir) | |
74a20780 | 385 | { |
5180311f | 386 | struct ib_device *dev; |
74a20780 | 387 | |
2261ec3d MC |
388 | iser_task->dir[iser_dir] = 1; |
389 | dev = iser_task->iser_conn->ib_conn->device->ib_device; | |
74a20780 | 390 | |
5180311f | 391 | data->dma_nents = ib_dma_map_sg(dev, data->buf, data->size, dma_dir); |
74a20780 EZ |
392 | if (data->dma_nents == 0) { |
393 | iser_err("dma_map_sg failed!!!\n"); | |
394 | return -EINVAL; | |
395 | } | |
396 | return 0; | |
397 | } | |
398 | ||
2261ec3d | 399 | void iser_dma_unmap_task_data(struct iscsi_iser_task *iser_task) |
74a20780 | 400 | { |
5180311f | 401 | struct ib_device *dev; |
74a20780 EZ |
402 | struct iser_data_buf *data; |
403 | ||
2261ec3d | 404 | dev = iser_task->iser_conn->ib_conn->device->ib_device; |
74a20780 | 405 | |
2261ec3d MC |
406 | if (iser_task->dir[ISER_DIR_IN]) { |
407 | data = &iser_task->data[ISER_DIR_IN]; | |
5180311f | 408 | ib_dma_unmap_sg(dev, data->buf, data->size, DMA_FROM_DEVICE); |
74a20780 EZ |
409 | } |
410 | ||
2261ec3d MC |
411 | if (iser_task->dir[ISER_DIR_OUT]) { |
412 | data = &iser_task->data[ISER_DIR_OUT]; | |
5180311f | 413 | ib_dma_unmap_sg(dev, data->buf, data->size, DMA_TO_DEVICE); |
74a20780 EZ |
414 | } |
415 | } | |
416 | ||
6461f64a OG |
417 | /** |
418 | * iser_reg_rdma_mem - Registers memory intended for RDMA, | |
419 | * obtaining rkey and va | |
420 | * | |
421 | * returns 0 on success, errno code on failure | |
422 | */ | |
2261ec3d | 423 | int iser_reg_rdma_mem(struct iscsi_iser_task *iser_task, |
6461f64a OG |
424 | enum iser_data_dir cmd_dir) |
425 | { | |
2261ec3d MC |
426 | struct iscsi_conn *iscsi_conn = iser_task->iser_conn->iscsi_conn; |
427 | struct iser_conn *ib_conn = iser_task->iser_conn->ib_conn; | |
d8111028 | 428 | struct iser_device *device = ib_conn->device; |
5180311f | 429 | struct ib_device *ibdev = device->ib_device; |
2261ec3d | 430 | struct iser_data_buf *mem = &iser_task->data[cmd_dir]; |
6461f64a OG |
431 | struct iser_regd_buf *regd_buf; |
432 | int aligned_len; | |
433 | int err; | |
e981f1d4 | 434 | int i; |
d8111028 | 435 | struct scatterlist *sg; |
6461f64a | 436 | |
2261ec3d | 437 | regd_buf = &iser_task->rdma_regd[cmd_dir]; |
6461f64a | 438 | |
5180311f | 439 | aligned_len = iser_data_buf_aligned_len(mem, ibdev); |
777a71dd | 440 | if (aligned_len != mem->dma_nents) { |
87528227 | 441 | iscsi_conn->fmr_unalign_cnt++; |
6f735e36 | 442 | iser_warn("rdma alignment violation %d/%d aligned\n", |
6461f64a | 443 | aligned_len, mem->size); |
5180311f | 444 | iser_data_buf_dump(mem, ibdev); |
74a20780 EZ |
445 | |
446 | /* unmap the command data before accessing it */ | |
2261ec3d | 447 | iser_dma_unmap_task_data(iser_task); |
74a20780 | 448 | |
6461f64a OG |
449 | /* allocate copy buf, if we are writing, copy the */ |
450 | /* unaligned scatterlist, dma map the copy */ | |
2261ec3d | 451 | if (iser_start_rdma_unaligned_sg(iser_task, cmd_dir) != 0) |
6461f64a | 452 | return -ENOMEM; |
2261ec3d | 453 | mem = &iser_task->data_copy[cmd_dir]; |
6461f64a OG |
454 | } |
455 | ||
d8111028 EZ |
456 | /* if there a single dma entry, FMR is not needed */ |
457 | if (mem->dma_nents == 1) { | |
458 | sg = (struct scatterlist *)mem->buf; | |
459 | ||
460 | regd_buf->reg.lkey = device->mr->lkey; | |
461 | regd_buf->reg.rkey = device->mr->rkey; | |
5180311f RC |
462 | regd_buf->reg.len = ib_sg_dma_len(ibdev, &sg[0]); |
463 | regd_buf->reg.va = ib_sg_dma_address(ibdev, &sg[0]); | |
d8111028 EZ |
464 | regd_buf->reg.is_fmr = 0; |
465 | ||
466 | iser_dbg("PHYSICAL Mem.register: lkey: 0x%08X rkey: 0x%08X " | |
467 | "va: 0x%08lX sz: %ld]\n", | |
468 | (unsigned int)regd_buf->reg.lkey, | |
469 | (unsigned int)regd_buf->reg.rkey, | |
470 | (unsigned long)regd_buf->reg.va, | |
471 | (unsigned long)regd_buf->reg.len); | |
472 | } else { /* use FMR for multiple dma entries */ | |
5180311f | 473 | iser_page_vec_build(mem, ib_conn->page_vec, ibdev); |
d8111028 EZ |
474 | err = iser_reg_page_vec(ib_conn, ib_conn->page_vec, ®d_buf->reg); |
475 | if (err) { | |
5180311f | 476 | iser_data_buf_dump(mem, ibdev); |
2261ec3d MC |
477 | iser_err("mem->dma_nents = %d (dlength = 0x%x)\n", |
478 | mem->dma_nents, | |
479 | ntoh24(iser_task->desc.iscsi_header.dlength)); | |
d8111028 EZ |
480 | iser_err("page_vec: data_size = 0x%x, length = %d, offset = 0x%x\n", |
481 | ib_conn->page_vec->data_size, ib_conn->page_vec->length, | |
482 | ib_conn->page_vec->offset); | |
483 | for (i=0 ; i<ib_conn->page_vec->length ; i++) | |
484 | iser_err("page_vec[%d] = 0x%llx\n", i, | |
485 | (unsigned long long) ib_conn->page_vec->pages[i]); | |
486 | return err; | |
e981f1d4 | 487 | } |
e981f1d4 | 488 | } |
6461f64a OG |
489 | |
490 | /* take a reference on this regd buf such that it will not be released * | |
491 | * (eg in send dto completion) before we get the scsi response */ | |
492 | atomic_inc(®d_buf->ref_count); | |
493 | return 0; | |
494 | } |