linux/drivers/infiniband/ulp/iser/iser_memory.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2004, 2005, 2006 Voltaire, Inc. All rights reserved.
   3 * Copyright (c) 2013-2014 Mellanox Technologies. 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
   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.
  32 */
  33#include <linux/module.h>
  34#include <linux/kernel.h>
  35#include <linux/slab.h>
  36#include <linux/mm.h>
  37#include <linux/highmem.h>
  38#include <linux/scatterlist.h>
  39
  40#include "iscsi_iser.h"
  41static
  42int iser_fast_reg_fmr(struct iscsi_iser_task *iser_task,
  43                      struct iser_data_buf *mem,
  44                      struct iser_reg_resources *rsc,
  45                      struct iser_mem_reg *mem_reg);
  46static
  47int iser_fast_reg_mr(struct iscsi_iser_task *iser_task,
  48                     struct iser_data_buf *mem,
  49                     struct iser_reg_resources *rsc,
  50                     struct iser_mem_reg *mem_reg);
  51
  52static const struct iser_reg_ops fastreg_ops = {
  53        .alloc_reg_res  = iser_alloc_fastreg_pool,
  54        .free_reg_res   = iser_free_fastreg_pool,
  55        .reg_mem        = iser_fast_reg_mr,
  56        .unreg_mem      = iser_unreg_mem_fastreg,
  57        .reg_desc_get   = iser_reg_desc_get_fr,
  58        .reg_desc_put   = iser_reg_desc_put_fr,
  59};
  60
  61static const struct iser_reg_ops fmr_ops = {
  62        .alloc_reg_res  = iser_alloc_fmr_pool,
  63        .free_reg_res   = iser_free_fmr_pool,
  64        .reg_mem        = iser_fast_reg_fmr,
  65        .unreg_mem      = iser_unreg_mem_fmr,
  66        .reg_desc_get   = iser_reg_desc_get_fmr,
  67        .reg_desc_put   = iser_reg_desc_put_fmr,
  68};
  69
  70void iser_reg_comp(struct ib_cq *cq, struct ib_wc *wc)
  71{
  72        iser_err_comp(wc, "memreg");
  73}
  74
  75int iser_assign_reg_ops(struct iser_device *device)
  76{
  77        struct ib_device *ib_dev = device->ib_device;
  78
  79        /* Assign function handles  - based on FMR support */
  80        if (ib_dev->alloc_fmr && ib_dev->dealloc_fmr &&
  81            ib_dev->map_phys_fmr && ib_dev->unmap_fmr) {
  82                iser_info("FMR supported, using FMR for registration\n");
  83                device->reg_ops = &fmr_ops;
  84        } else if (ib_dev->attrs.device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS) {
  85                iser_info("FastReg supported, using FastReg for registration\n");
  86                device->reg_ops = &fastreg_ops;
  87                device->remote_inv_sup = iser_always_reg;
  88        } else {
  89                iser_err("IB device does not support FMRs nor FastRegs, can't register memory\n");
  90                return -1;
  91        }
  92
  93        return 0;
  94}
  95
  96struct iser_fr_desc *
  97iser_reg_desc_get_fr(struct ib_conn *ib_conn)
  98{
  99        struct iser_fr_pool *fr_pool = &ib_conn->fr_pool;
 100        struct iser_fr_desc *desc;
 101        unsigned long flags;
 102
 103        spin_lock_irqsave(&fr_pool->lock, flags);
 104        desc = list_first_entry(&fr_pool->list,
 105                                struct iser_fr_desc, list);
 106        list_del(&desc->list);
 107        spin_unlock_irqrestore(&fr_pool->lock, flags);
 108
 109        return desc;
 110}
 111
 112void
 113iser_reg_desc_put_fr(struct ib_conn *ib_conn,
 114                     struct iser_fr_desc *desc)
 115{
 116        struct iser_fr_pool *fr_pool = &ib_conn->fr_pool;
 117        unsigned long flags;
 118
 119        spin_lock_irqsave(&fr_pool->lock, flags);
 120        list_add(&desc->list, &fr_pool->list);
 121        spin_unlock_irqrestore(&fr_pool->lock, flags);
 122}
 123
 124struct iser_fr_desc *
 125iser_reg_desc_get_fmr(struct ib_conn *ib_conn)
 126{
 127        struct iser_fr_pool *fr_pool = &ib_conn->fr_pool;
 128
 129        return list_first_entry(&fr_pool->list,
 130                                struct iser_fr_desc, list);
 131}
 132
 133void
 134iser_reg_desc_put_fmr(struct ib_conn *ib_conn,
 135                      struct iser_fr_desc *desc)
 136{
 137}
 138
 139static void iser_data_buf_dump(struct iser_data_buf *data,
 140                               struct ib_device *ibdev)
 141{
 142        struct scatterlist *sg;
 143        int i;
 144
 145        for_each_sg(data->sg, sg, data->dma_nents, i)
 146                iser_dbg("sg[%d] dma_addr:0x%lX page:0x%p "
 147                         "off:0x%x sz:0x%x dma_len:0x%x\n",
 148                         i, (unsigned long)ib_sg_dma_address(ibdev, sg),
 149                         sg_page(sg), sg->offset,
 150                         sg->length, ib_sg_dma_len(ibdev, sg));
 151}
 152
 153static void iser_dump_page_vec(struct iser_page_vec *page_vec)
 154{
 155        int i;
 156
 157        iser_err("page vec npages %d data length %lld\n",
 158                 page_vec->npages, page_vec->fake_mr.length);
 159        for (i = 0; i < page_vec->npages; i++)
 160                iser_err("vec[%d]: %llx\n", i, page_vec->pages[i]);
 161}
 162
 163int iser_dma_map_task_data(struct iscsi_iser_task *iser_task,
 164                            struct iser_data_buf *data,
 165                            enum iser_data_dir iser_dir,
 166                            enum dma_data_direction dma_dir)
 167{
 168        struct ib_device *dev;
 169
 170        iser_task->dir[iser_dir] = 1;
 171        dev = iser_task->iser_conn->ib_conn.device->ib_device;
 172
 173        data->dma_nents = ib_dma_map_sg(dev, data->sg, data->size, dma_dir);
 174        if (data->dma_nents == 0) {
 175                iser_err("dma_map_sg failed!!!\n");
 176                return -EINVAL;
 177        }
 178        return 0;
 179}
 180
 181void iser_dma_unmap_task_data(struct iscsi_iser_task *iser_task,
 182                              struct iser_data_buf *data,
 183                              enum dma_data_direction dir)
 184{
 185        struct ib_device *dev;
 186
 187        dev = iser_task->iser_conn->ib_conn.device->ib_device;
 188        ib_dma_unmap_sg(dev, data->sg, data->size, dir);
 189}
 190
 191static int
 192iser_reg_dma(struct iser_device *device, struct iser_data_buf *mem,
 193             struct iser_mem_reg *reg)
 194{
 195        struct scatterlist *sg = mem->sg;
 196
 197        reg->sge.lkey = device->pd->local_dma_lkey;
 198        /*
 199         * FIXME: rework the registration code path to differentiate
 200         * rkey/lkey use cases
 201         */
 202
 203        if (device->pd->flags & IB_PD_UNSAFE_GLOBAL_RKEY)
 204                reg->rkey = device->pd->unsafe_global_rkey;
 205        else
 206                reg->rkey = 0;
 207        reg->sge.addr = ib_sg_dma_address(device->ib_device, &sg[0]);
 208        reg->sge.length = ib_sg_dma_len(device->ib_device, &sg[0]);
 209
 210        iser_dbg("Single DMA entry: lkey=0x%x, rkey=0x%x, addr=0x%llx,"
 211                 " length=0x%x\n", reg->sge.lkey, reg->rkey,
 212                 reg->sge.addr, reg->sge.length);
 213
 214        return 0;
 215}
 216
 217static int iser_set_page(struct ib_mr *mr, u64 addr)
 218{
 219        struct iser_page_vec *page_vec =
 220                container_of(mr, struct iser_page_vec, fake_mr);
 221
 222        page_vec->pages[page_vec->npages++] = addr;
 223
 224        return 0;
 225}
 226
 227static
 228int iser_fast_reg_fmr(struct iscsi_iser_task *iser_task,
 229                      struct iser_data_buf *mem,
 230                      struct iser_reg_resources *rsc,
 231                      struct iser_mem_reg *reg)
 232{
 233        struct ib_conn *ib_conn = &iser_task->iser_conn->ib_conn;
 234        struct iser_device *device = ib_conn->device;
 235        struct iser_page_vec *page_vec = rsc->page_vec;
 236        struct ib_fmr_pool *fmr_pool = rsc->fmr_pool;
 237        struct ib_pool_fmr *fmr;
 238        int ret, plen;
 239
 240        page_vec->npages = 0;
 241        page_vec->fake_mr.page_size = SIZE_4K;
 242        plen = ib_sg_to_pages(&page_vec->fake_mr, mem->sg,
 243                              mem->size, NULL, iser_set_page);
 244        if (unlikely(plen < mem->size)) {
 245                iser_err("page vec too short to hold this SG\n");
 246                iser_data_buf_dump(mem, device->ib_device);
 247                iser_dump_page_vec(page_vec);
 248                return -EINVAL;
 249        }
 250
 251        fmr  = ib_fmr_pool_map_phys(fmr_pool, page_vec->pages,
 252                                    page_vec->npages, page_vec->pages[0]);
 253        if (IS_ERR(fmr)) {
 254                ret = PTR_ERR(fmr);
 255                iser_err("ib_fmr_pool_map_phys failed: %d\n", ret);
 256                return ret;
 257        }
 258
 259        reg->sge.lkey = fmr->fmr->lkey;
 260        reg->rkey = fmr->fmr->rkey;
 261        reg->sge.addr = page_vec->fake_mr.iova;
 262        reg->sge.length = page_vec->fake_mr.length;
 263        reg->mem_h = fmr;
 264
 265        iser_dbg("fmr reg: lkey=0x%x, rkey=0x%x, addr=0x%llx,"
 266                 " length=0x%x\n", reg->sge.lkey, reg->rkey,
 267                 reg->sge.addr, reg->sge.length);
 268
 269        return 0;
 270}
 271
 272/**
 273 * Unregister (previosuly registered using FMR) memory.
 274 * If memory is non-FMR does nothing.
 275 */
 276void iser_unreg_mem_fmr(struct iscsi_iser_task *iser_task,
 277                        enum iser_data_dir cmd_dir)
 278{
 279        struct iser_mem_reg *reg = &iser_task->rdma_reg[cmd_dir];
 280        int ret;
 281
 282        if (!reg->mem_h)
 283                return;
 284
 285        iser_dbg("PHYSICAL Mem.Unregister mem_h %p\n", reg->mem_h);
 286
 287        ret = ib_fmr_pool_unmap((struct ib_pool_fmr *)reg->mem_h);
 288        if (ret)
 289                iser_err("ib_fmr_pool_unmap failed %d\n", ret);
 290
 291        reg->mem_h = NULL;
 292}
 293
 294void iser_unreg_mem_fastreg(struct iscsi_iser_task *iser_task,
 295                            enum iser_data_dir cmd_dir)
 296{
 297        struct iser_device *device = iser_task->iser_conn->ib_conn.device;
 298        struct iser_mem_reg *reg = &iser_task->rdma_reg[cmd_dir];
 299
 300        if (!reg->mem_h)
 301                return;
 302
 303        device->reg_ops->reg_desc_put(&iser_task->iser_conn->ib_conn,
 304                                     reg->mem_h);
 305        reg->mem_h = NULL;
 306}
 307
 308static void
 309iser_set_dif_domain(struct scsi_cmnd *sc, struct ib_sig_attrs *sig_attrs,
 310                    struct ib_sig_domain *domain)
 311{
 312        domain->sig_type = IB_SIG_TYPE_T10_DIF;
 313        domain->sig.dif.pi_interval = scsi_prot_interval(sc);
 314        domain->sig.dif.ref_tag = scsi_prot_ref_tag(sc);
 315        /*
 316         * At the moment we hard code those, but in the future
 317         * we will take them from sc.
 318         */
 319        domain->sig.dif.apptag_check_mask = 0xffff;
 320        domain->sig.dif.app_escape = true;
 321        domain->sig.dif.ref_escape = true;
 322        if (sc->prot_flags & SCSI_PROT_REF_INCREMENT)
 323                domain->sig.dif.ref_remap = true;
 324};
 325
 326static int
 327iser_set_sig_attrs(struct scsi_cmnd *sc, struct ib_sig_attrs *sig_attrs)
 328{
 329        switch (scsi_get_prot_op(sc)) {
 330        case SCSI_PROT_WRITE_INSERT:
 331        case SCSI_PROT_READ_STRIP:
 332                sig_attrs->mem.sig_type = IB_SIG_TYPE_NONE;
 333                iser_set_dif_domain(sc, sig_attrs, &sig_attrs->wire);
 334                sig_attrs->wire.sig.dif.bg_type = IB_T10DIF_CRC;
 335                break;
 336        case SCSI_PROT_READ_INSERT:
 337        case SCSI_PROT_WRITE_STRIP:
 338                sig_attrs->wire.sig_type = IB_SIG_TYPE_NONE;
 339                iser_set_dif_domain(sc, sig_attrs, &sig_attrs->mem);
 340                sig_attrs->mem.sig.dif.bg_type = sc->prot_flags & SCSI_PROT_IP_CHECKSUM ?
 341                                                IB_T10DIF_CSUM : IB_T10DIF_CRC;
 342                break;
 343        case SCSI_PROT_READ_PASS:
 344        case SCSI_PROT_WRITE_PASS:
 345                iser_set_dif_domain(sc, sig_attrs, &sig_attrs->wire);
 346                sig_attrs->wire.sig.dif.bg_type = IB_T10DIF_CRC;
 347                iser_set_dif_domain(sc, sig_attrs, &sig_attrs->mem);
 348                sig_attrs->mem.sig.dif.bg_type = sc->prot_flags & SCSI_PROT_IP_CHECKSUM ?
 349                                                IB_T10DIF_CSUM : IB_T10DIF_CRC;
 350                break;
 351        default:
 352                iser_err("Unsupported PI operation %d\n",
 353                         scsi_get_prot_op(sc));
 354                return -EINVAL;
 355        }
 356
 357        return 0;
 358}
 359
 360static inline void
 361iser_set_prot_checks(struct scsi_cmnd *sc, u8 *mask)
 362{
 363        *mask = 0;
 364        if (sc->prot_flags & SCSI_PROT_REF_CHECK)
 365                *mask |= IB_SIG_CHECK_REFTAG;
 366        if (sc->prot_flags & SCSI_PROT_GUARD_CHECK)
 367                *mask |= IB_SIG_CHECK_GUARD;
 368}
 369
 370static inline void
 371iser_inv_rkey(struct ib_send_wr *inv_wr,
 372              struct ib_mr *mr,
 373              struct ib_cqe *cqe)
 374{
 375        inv_wr->opcode = IB_WR_LOCAL_INV;
 376        inv_wr->wr_cqe = cqe;
 377        inv_wr->ex.invalidate_rkey = mr->rkey;
 378        inv_wr->send_flags = 0;
 379        inv_wr->num_sge = 0;
 380}
 381
 382static int
 383iser_reg_sig_mr(struct iscsi_iser_task *iser_task,
 384                struct iser_pi_context *pi_ctx,
 385                struct iser_mem_reg *data_reg,
 386                struct iser_mem_reg *prot_reg,
 387                struct iser_mem_reg *sig_reg)
 388{
 389        struct iser_tx_desc *tx_desc = &iser_task->desc;
 390        struct ib_sig_attrs *sig_attrs = &tx_desc->sig_attrs;
 391        struct ib_cqe *cqe = &iser_task->iser_conn->ib_conn.reg_cqe;
 392        struct ib_sig_handover_wr *wr;
 393        struct ib_mr *mr = pi_ctx->sig_mr;
 394        int ret;
 395
 396        memset(sig_attrs, 0, sizeof(*sig_attrs));
 397        ret = iser_set_sig_attrs(iser_task->sc, sig_attrs);
 398        if (ret)
 399                goto err;
 400
 401        iser_set_prot_checks(iser_task->sc, &sig_attrs->check_mask);
 402
 403        if (pi_ctx->sig_mr_valid)
 404                iser_inv_rkey(iser_tx_next_wr(tx_desc), mr, cqe);
 405
 406        ib_update_fast_reg_key(mr, ib_inc_rkey(mr->rkey));
 407
 408        wr = sig_handover_wr(iser_tx_next_wr(tx_desc));
 409        wr->wr.opcode = IB_WR_REG_SIG_MR;
 410        wr->wr.wr_cqe = cqe;
 411        wr->wr.sg_list = &data_reg->sge;
 412        wr->wr.num_sge = 1;
 413        wr->wr.send_flags = 0;
 414        wr->sig_attrs = sig_attrs;
 415        wr->sig_mr = mr;
 416        if (scsi_prot_sg_count(iser_task->sc))
 417                wr->prot = &prot_reg->sge;
 418        else
 419                wr->prot = NULL;
 420        wr->access_flags = IB_ACCESS_LOCAL_WRITE |
 421                           IB_ACCESS_REMOTE_READ |
 422                           IB_ACCESS_REMOTE_WRITE;
 423        pi_ctx->sig_mr_valid = 1;
 424
 425        sig_reg->sge.lkey = mr->lkey;
 426        sig_reg->rkey = mr->rkey;
 427        sig_reg->sge.addr = 0;
 428        sig_reg->sge.length = scsi_transfer_length(iser_task->sc);
 429
 430        iser_dbg("lkey=0x%x rkey=0x%x addr=0x%llx length=%u\n",
 431                 sig_reg->sge.lkey, sig_reg->rkey, sig_reg->sge.addr,
 432                 sig_reg->sge.length);
 433err:
 434        return ret;
 435}
 436
 437static int iser_fast_reg_mr(struct iscsi_iser_task *iser_task,
 438                            struct iser_data_buf *mem,
 439                            struct iser_reg_resources *rsc,
 440                            struct iser_mem_reg *reg)
 441{
 442        struct iser_tx_desc *tx_desc = &iser_task->desc;
 443        struct ib_cqe *cqe = &iser_task->iser_conn->ib_conn.reg_cqe;
 444        struct ib_mr *mr = rsc->mr;
 445        struct ib_reg_wr *wr;
 446        int n;
 447
 448        if (rsc->mr_valid)
 449                iser_inv_rkey(iser_tx_next_wr(tx_desc), mr, cqe);
 450
 451        ib_update_fast_reg_key(mr, ib_inc_rkey(mr->rkey));
 452
 453        n = ib_map_mr_sg(mr, mem->sg, mem->size, NULL, SIZE_4K);
 454        if (unlikely(n != mem->size)) {
 455                iser_err("failed to map sg (%d/%d)\n",
 456                         n, mem->size);
 457                return n < 0 ? n : -EINVAL;
 458        }
 459
 460        wr = reg_wr(iser_tx_next_wr(tx_desc));
 461        wr->wr.opcode = IB_WR_REG_MR;
 462        wr->wr.wr_cqe = cqe;
 463        wr->wr.send_flags = 0;
 464        wr->wr.num_sge = 0;
 465        wr->mr = mr;
 466        wr->key = mr->rkey;
 467        wr->access = IB_ACCESS_LOCAL_WRITE  |
 468                     IB_ACCESS_REMOTE_WRITE |
 469                     IB_ACCESS_REMOTE_READ;
 470
 471        rsc->mr_valid = 1;
 472
 473        reg->sge.lkey = mr->lkey;
 474        reg->rkey = mr->rkey;
 475        reg->sge.addr = mr->iova;
 476        reg->sge.length = mr->length;
 477
 478        iser_dbg("lkey=0x%x rkey=0x%x addr=0x%llx length=0x%x\n",
 479                 reg->sge.lkey, reg->rkey, reg->sge.addr, reg->sge.length);
 480
 481        return 0;
 482}
 483
 484static int
 485iser_reg_prot_sg(struct iscsi_iser_task *task,
 486                 struct iser_data_buf *mem,
 487                 struct iser_fr_desc *desc,
 488                 bool use_dma_key,
 489                 struct iser_mem_reg *reg)
 490{
 491        struct iser_device *device = task->iser_conn->ib_conn.device;
 492
 493        if (use_dma_key)
 494                return iser_reg_dma(device, mem, reg);
 495
 496        return device->reg_ops->reg_mem(task, mem, &desc->pi_ctx->rsc, reg);
 497}
 498
 499static int
 500iser_reg_data_sg(struct iscsi_iser_task *task,
 501                 struct iser_data_buf *mem,
 502                 struct iser_fr_desc *desc,
 503                 bool use_dma_key,
 504                 struct iser_mem_reg *reg)
 505{
 506        struct iser_device *device = task->iser_conn->ib_conn.device;
 507
 508        if (use_dma_key)
 509                return iser_reg_dma(device, mem, reg);
 510
 511        return device->reg_ops->reg_mem(task, mem, &desc->rsc, reg);
 512}
 513
 514int iser_reg_rdma_mem(struct iscsi_iser_task *task,
 515                      enum iser_data_dir dir,
 516                      bool all_imm)
 517{
 518        struct ib_conn *ib_conn = &task->iser_conn->ib_conn;
 519        struct iser_device *device = ib_conn->device;
 520        struct iser_data_buf *mem = &task->data[dir];
 521        struct iser_mem_reg *reg = &task->rdma_reg[dir];
 522        struct iser_mem_reg *data_reg;
 523        struct iser_fr_desc *desc = NULL;
 524        bool use_dma_key;
 525        int err;
 526
 527        use_dma_key = mem->dma_nents == 1 && (all_imm || !iser_always_reg) &&
 528                      scsi_get_prot_op(task->sc) == SCSI_PROT_NORMAL;
 529
 530        if (!use_dma_key) {
 531                desc = device->reg_ops->reg_desc_get(ib_conn);
 532                reg->mem_h = desc;
 533        }
 534
 535        if (scsi_get_prot_op(task->sc) == SCSI_PROT_NORMAL)
 536                data_reg = reg;
 537        else
 538                data_reg = &task->desc.data_reg;
 539
 540        err = iser_reg_data_sg(task, mem, desc, use_dma_key, data_reg);
 541        if (unlikely(err))
 542                goto err_reg;
 543
 544        if (scsi_get_prot_op(task->sc) != SCSI_PROT_NORMAL) {
 545                struct iser_mem_reg *prot_reg = &task->desc.prot_reg;
 546
 547                if (scsi_prot_sg_count(task->sc)) {
 548                        mem = &task->prot[dir];
 549                        err = iser_reg_prot_sg(task, mem, desc,
 550                                               use_dma_key, prot_reg);
 551                        if (unlikely(err))
 552                                goto err_reg;
 553                }
 554
 555                err = iser_reg_sig_mr(task, desc->pi_ctx, data_reg,
 556                                      prot_reg, reg);
 557                if (unlikely(err))
 558                        goto err_reg;
 559
 560                desc->pi_ctx->sig_protected = 1;
 561        }
 562
 563        return 0;
 564
 565err_reg:
 566        if (desc)
 567                device->reg_ops->reg_desc_put(ib_conn, desc);
 568
 569        return err;
 570}
 571
 572void iser_unreg_rdma_mem(struct iscsi_iser_task *task,
 573                         enum iser_data_dir dir)
 574{
 575        struct iser_device *device = task->iser_conn->ib_conn.device;
 576
 577        device->reg_ops->unreg_mem(task, dir);
 578}
 579