IB/iser: Do not use FMR for a single dma entry sg

Fast Memory Registration (fmr) is used to register for rdma an sg whose
elements are not linearly sequential after dma mapping.

The IB verbs layer provides an "all dma memory MR (memory region)" which
can be used for RDMA-ing a dma linearly sequential buffer.

Change the code to use the dma mr instead of doing fmr when dma mapping
produces a single dma entry sg.

Signed-off-by: Erez Zilber <erezz@voltaire.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
This commit is contained in:
Erez Zilber 2006-09-11 12:26:33 +03:00 committed by Roland Dreier
parent e981f1d4b8
commit d81110285f
3 changed files with 39 additions and 16 deletions

View File

@ -175,6 +175,7 @@ struct iser_mem_reg {
u64 va; u64 va;
u64 len; u64 len;
void *mem_h; void *mem_h;
int is_fmr;
}; };
struct iser_regd_buf { struct iser_regd_buf {

View File

@ -56,7 +56,7 @@ int iser_regd_buff_release(struct iser_regd_buf *regd_buf)
if ((atomic_read(&regd_buf->ref_count) == 0) || if ((atomic_read(&regd_buf->ref_count) == 0) ||
atomic_dec_and_test(&regd_buf->ref_count)) { atomic_dec_and_test(&regd_buf->ref_count)) {
/* if we used the dma mr, unreg is just NOP */ /* if we used the dma mr, unreg is just NOP */
if (regd_buf->reg.rkey != 0) if (regd_buf->reg.is_fmr)
iser_unreg_mem(&regd_buf->reg); iser_unreg_mem(&regd_buf->reg);
if (regd_buf->dma_addr) { if (regd_buf->dma_addr) {
@ -91,9 +91,9 @@ void iser_reg_single(struct iser_device *device,
BUG_ON(dma_mapping_error(dma_addr)); BUG_ON(dma_mapping_error(dma_addr));
regd_buf->reg.lkey = device->mr->lkey; regd_buf->reg.lkey = device->mr->lkey;
regd_buf->reg.rkey = 0; /* indicate there's no need to unreg */
regd_buf->reg.len = regd_buf->data_size; regd_buf->reg.len = regd_buf->data_size;
regd_buf->reg.va = dma_addr; regd_buf->reg.va = dma_addr;
regd_buf->reg.is_fmr = 0;
regd_buf->dma_addr = dma_addr; regd_buf->dma_addr = dma_addr;
regd_buf->direction = direction; regd_buf->direction = direction;
@ -379,11 +379,13 @@ int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask,
enum iser_data_dir cmd_dir) enum iser_data_dir cmd_dir)
{ {
struct iser_conn *ib_conn = iser_ctask->iser_conn->ib_conn; struct iser_conn *ib_conn = iser_ctask->iser_conn->ib_conn;
struct iser_device *device = ib_conn->device;
struct iser_data_buf *mem = &iser_ctask->data[cmd_dir]; struct iser_data_buf *mem = &iser_ctask->data[cmd_dir];
struct iser_regd_buf *regd_buf; struct iser_regd_buf *regd_buf;
int aligned_len; int aligned_len;
int err; int err;
int i; int i;
struct scatterlist *sg;
regd_buf = &iser_ctask->rdma_regd[cmd_dir]; regd_buf = &iser_ctask->rdma_regd[cmd_dir];
@ -399,6 +401,23 @@ int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask,
mem = &iser_ctask->data_copy[cmd_dir]; mem = &iser_ctask->data_copy[cmd_dir];
} }
/* if there a single dma entry, FMR is not needed */
if (mem->dma_nents == 1) {
sg = (struct scatterlist *)mem->buf;
regd_buf->reg.lkey = device->mr->lkey;
regd_buf->reg.rkey = device->mr->rkey;
regd_buf->reg.len = sg_dma_len(&sg[0]);
regd_buf->reg.va = sg_dma_address(&sg[0]);
regd_buf->reg.is_fmr = 0;
iser_dbg("PHYSICAL Mem.register: lkey: 0x%08X rkey: 0x%08X "
"va: 0x%08lX sz: %ld]\n",
(unsigned int)regd_buf->reg.lkey,
(unsigned int)regd_buf->reg.rkey,
(unsigned long)regd_buf->reg.va,
(unsigned long)regd_buf->reg.len);
} else { /* use FMR for multiple dma entries */
iser_page_vec_build(mem, ib_conn->page_vec); iser_page_vec_build(mem, ib_conn->page_vec);
err = iser_reg_page_vec(ib_conn, ib_conn->page_vec, &regd_buf->reg); err = iser_reg_page_vec(ib_conn, ib_conn->page_vec, &regd_buf->reg);
if (err) { if (err) {
@ -408,11 +427,12 @@ int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask,
iser_err("page_vec: data_size = 0x%x, length = %d, offset = 0x%x\n", iser_err("page_vec: data_size = 0x%x, length = %d, offset = 0x%x\n",
ib_conn->page_vec->data_size, ib_conn->page_vec->length, ib_conn->page_vec->data_size, ib_conn->page_vec->length,
ib_conn->page_vec->offset); ib_conn->page_vec->offset);
for (i=0 ; i<ib_conn->page_vec->length ; i++) { for (i=0 ; i<ib_conn->page_vec->length ; i++)
iser_err("page_vec[%d] = 0x%lx\n", i, ib_conn->page_vec->pages[i]); iser_err("page_vec[%d] = 0x%llx\n", i,
} (unsigned long long) ib_conn->page_vec->pages[i]);
return err; return err;
} }
}
/* take a reference on this regd buf such that it will not be released * /* take a reference on this regd buf such that it will not be released *
* (eg in send dto completion) before we get the scsi response */ * (eg in send dto completion) before we get the scsi response */

View File

@ -88,8 +88,9 @@ static int iser_create_device_ib_res(struct iser_device *device)
iser_cq_tasklet_fn, iser_cq_tasklet_fn,
(unsigned long)device); (unsigned long)device);
device->mr = ib_get_dma_mr(device->pd, device->mr = ib_get_dma_mr(device->pd, IB_ACCESS_LOCAL_WRITE |
IB_ACCESS_LOCAL_WRITE); IB_ACCESS_REMOTE_WRITE |
IB_ACCESS_REMOTE_READ);
if (IS_ERR(device->mr)) if (IS_ERR(device->mr))
goto dma_mr_err; goto dma_mr_err;
@ -606,6 +607,7 @@ int iser_reg_page_vec(struct iser_conn *ib_conn,
mem_reg->rkey = mem->fmr->rkey; mem_reg->rkey = mem->fmr->rkey;
mem_reg->len = page_vec->length * SIZE_4K; mem_reg->len = page_vec->length * SIZE_4K;
mem_reg->va = io_addr; mem_reg->va = io_addr;
mem_reg->is_fmr = 1;
mem_reg->mem_h = (void *)mem; mem_reg->mem_h = (void *)mem;
mem_reg->va += page_vec->offset; mem_reg->va += page_vec->offset;