18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2004, 2005, 2006 Voltaire, Inc. All rights reserved. 38c2ecf20Sopenharmony_ci * Copyright (c) 2013-2014 Mellanox Technologies. All rights reserved. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two 68c2ecf20Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 78c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 88c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the 98c2ecf20Sopenharmony_ci * OpenIB.org BSD license below: 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or 128c2ecf20Sopenharmony_ci * without modification, are permitted provided that the following 138c2ecf20Sopenharmony_ci * conditions are met: 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * - Redistributions of source code must retain the above 168c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 178c2ecf20Sopenharmony_ci * disclaimer. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * - Redistributions in binary form must reproduce the above 208c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 218c2ecf20Sopenharmony_ci * disclaimer in the documentation and/or other materials 228c2ecf20Sopenharmony_ci * provided with the distribution. 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 258c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 268c2ecf20Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 278c2ecf20Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 288c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 298c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 308c2ecf20Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 318c2ecf20Sopenharmony_ci * SOFTWARE. 328c2ecf20Sopenharmony_ci */ 338c2ecf20Sopenharmony_ci#include <linux/module.h> 348c2ecf20Sopenharmony_ci#include <linux/kernel.h> 358c2ecf20Sopenharmony_ci#include <linux/slab.h> 368c2ecf20Sopenharmony_ci#include <linux/mm.h> 378c2ecf20Sopenharmony_ci#include <linux/highmem.h> 388c2ecf20Sopenharmony_ci#include <linux/scatterlist.h> 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#include "iscsi_iser.h" 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_civoid iser_reg_comp(struct ib_cq *cq, struct ib_wc *wc) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci iser_err_comp(wc, "memreg"); 458c2ecf20Sopenharmony_ci} 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cistatic struct iser_fr_desc * 488c2ecf20Sopenharmony_ciiser_reg_desc_get_fr(struct ib_conn *ib_conn) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci struct iser_fr_pool *fr_pool = &ib_conn->fr_pool; 518c2ecf20Sopenharmony_ci struct iser_fr_desc *desc; 528c2ecf20Sopenharmony_ci unsigned long flags; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci spin_lock_irqsave(&fr_pool->lock, flags); 558c2ecf20Sopenharmony_ci desc = list_first_entry(&fr_pool->list, 568c2ecf20Sopenharmony_ci struct iser_fr_desc, list); 578c2ecf20Sopenharmony_ci list_del(&desc->list); 588c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&fr_pool->lock, flags); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci return desc; 618c2ecf20Sopenharmony_ci} 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cistatic void 648c2ecf20Sopenharmony_ciiser_reg_desc_put_fr(struct ib_conn *ib_conn, 658c2ecf20Sopenharmony_ci struct iser_fr_desc *desc) 668c2ecf20Sopenharmony_ci{ 678c2ecf20Sopenharmony_ci struct iser_fr_pool *fr_pool = &ib_conn->fr_pool; 688c2ecf20Sopenharmony_ci unsigned long flags; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci spin_lock_irqsave(&fr_pool->lock, flags); 718c2ecf20Sopenharmony_ci list_add(&desc->list, &fr_pool->list); 728c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&fr_pool->lock, flags); 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ciint iser_dma_map_task_data(struct iscsi_iser_task *iser_task, 768c2ecf20Sopenharmony_ci struct iser_data_buf *data, 778c2ecf20Sopenharmony_ci enum iser_data_dir iser_dir, 788c2ecf20Sopenharmony_ci enum dma_data_direction dma_dir) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci struct ib_device *dev; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci iser_task->dir[iser_dir] = 1; 838c2ecf20Sopenharmony_ci dev = iser_task->iser_conn->ib_conn.device->ib_device; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci data->dma_nents = ib_dma_map_sg(dev, data->sg, data->size, dma_dir); 868c2ecf20Sopenharmony_ci if (unlikely(data->dma_nents == 0)) { 878c2ecf20Sopenharmony_ci iser_err("dma_map_sg failed!!!\n"); 888c2ecf20Sopenharmony_ci return -EINVAL; 898c2ecf20Sopenharmony_ci } 908c2ecf20Sopenharmony_ci return 0; 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_civoid iser_dma_unmap_task_data(struct iscsi_iser_task *iser_task, 948c2ecf20Sopenharmony_ci struct iser_data_buf *data, 958c2ecf20Sopenharmony_ci enum dma_data_direction dir) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci struct ib_device *dev; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci dev = iser_task->iser_conn->ib_conn.device->ib_device; 1008c2ecf20Sopenharmony_ci ib_dma_unmap_sg(dev, data->sg, data->size, dir); 1018c2ecf20Sopenharmony_ci} 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cistatic int 1048c2ecf20Sopenharmony_ciiser_reg_dma(struct iser_device *device, struct iser_data_buf *mem, 1058c2ecf20Sopenharmony_ci struct iser_mem_reg *reg) 1068c2ecf20Sopenharmony_ci{ 1078c2ecf20Sopenharmony_ci struct scatterlist *sg = mem->sg; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci reg->sge.lkey = device->pd->local_dma_lkey; 1108c2ecf20Sopenharmony_ci /* 1118c2ecf20Sopenharmony_ci * FIXME: rework the registration code path to differentiate 1128c2ecf20Sopenharmony_ci * rkey/lkey use cases 1138c2ecf20Sopenharmony_ci */ 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci if (device->pd->flags & IB_PD_UNSAFE_GLOBAL_RKEY) 1168c2ecf20Sopenharmony_ci reg->rkey = device->pd->unsafe_global_rkey; 1178c2ecf20Sopenharmony_ci else 1188c2ecf20Sopenharmony_ci reg->rkey = 0; 1198c2ecf20Sopenharmony_ci reg->sge.addr = sg_dma_address(&sg[0]); 1208c2ecf20Sopenharmony_ci reg->sge.length = sg_dma_len(&sg[0]); 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci iser_dbg("Single DMA entry: lkey=0x%x, rkey=0x%x, addr=0x%llx," 1238c2ecf20Sopenharmony_ci " length=0x%x\n", reg->sge.lkey, reg->rkey, 1248c2ecf20Sopenharmony_ci reg->sge.addr, reg->sge.length); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci return 0; 1278c2ecf20Sopenharmony_ci} 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_civoid iser_unreg_mem_fastreg(struct iscsi_iser_task *iser_task, 1308c2ecf20Sopenharmony_ci enum iser_data_dir cmd_dir) 1318c2ecf20Sopenharmony_ci{ 1328c2ecf20Sopenharmony_ci struct iser_mem_reg *reg = &iser_task->rdma_reg[cmd_dir]; 1338c2ecf20Sopenharmony_ci struct iser_fr_desc *desc; 1348c2ecf20Sopenharmony_ci struct ib_mr_status mr_status; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci desc = reg->mem_h; 1378c2ecf20Sopenharmony_ci if (!desc) 1388c2ecf20Sopenharmony_ci return; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci /* 1418c2ecf20Sopenharmony_ci * The signature MR cannot be invalidated and reused without checking. 1428c2ecf20Sopenharmony_ci * libiscsi calls the check_protection transport handler only if 1438c2ecf20Sopenharmony_ci * SCSI-Response is received. And the signature MR is not checked if 1448c2ecf20Sopenharmony_ci * the task is completed for some other reason like a timeout or error 1458c2ecf20Sopenharmony_ci * handling. That's why we must check the signature MR here before 1468c2ecf20Sopenharmony_ci * putting it to the free pool. 1478c2ecf20Sopenharmony_ci */ 1488c2ecf20Sopenharmony_ci if (unlikely(desc->sig_protected)) { 1498c2ecf20Sopenharmony_ci desc->sig_protected = false; 1508c2ecf20Sopenharmony_ci ib_check_mr_status(desc->rsc.sig_mr, IB_MR_CHECK_SIG_STATUS, 1518c2ecf20Sopenharmony_ci &mr_status); 1528c2ecf20Sopenharmony_ci } 1538c2ecf20Sopenharmony_ci iser_reg_desc_put_fr(&iser_task->iser_conn->ib_conn, reg->mem_h); 1548c2ecf20Sopenharmony_ci reg->mem_h = NULL; 1558c2ecf20Sopenharmony_ci} 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cistatic void 1588c2ecf20Sopenharmony_ciiser_set_dif_domain(struct scsi_cmnd *sc, struct ib_sig_domain *domain) 1598c2ecf20Sopenharmony_ci{ 1608c2ecf20Sopenharmony_ci domain->sig_type = IB_SIG_TYPE_T10_DIF; 1618c2ecf20Sopenharmony_ci domain->sig.dif.pi_interval = scsi_prot_interval(sc); 1628c2ecf20Sopenharmony_ci domain->sig.dif.ref_tag = t10_pi_ref_tag(sc->request); 1638c2ecf20Sopenharmony_ci /* 1648c2ecf20Sopenharmony_ci * At the moment we hard code those, but in the future 1658c2ecf20Sopenharmony_ci * we will take them from sc. 1668c2ecf20Sopenharmony_ci */ 1678c2ecf20Sopenharmony_ci domain->sig.dif.apptag_check_mask = 0xffff; 1688c2ecf20Sopenharmony_ci domain->sig.dif.app_escape = true; 1698c2ecf20Sopenharmony_ci domain->sig.dif.ref_escape = true; 1708c2ecf20Sopenharmony_ci if (sc->prot_flags & SCSI_PROT_REF_INCREMENT) 1718c2ecf20Sopenharmony_ci domain->sig.dif.ref_remap = true; 1728c2ecf20Sopenharmony_ci}; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_cistatic int 1758c2ecf20Sopenharmony_ciiser_set_sig_attrs(struct scsi_cmnd *sc, struct ib_sig_attrs *sig_attrs) 1768c2ecf20Sopenharmony_ci{ 1778c2ecf20Sopenharmony_ci switch (scsi_get_prot_op(sc)) { 1788c2ecf20Sopenharmony_ci case SCSI_PROT_WRITE_INSERT: 1798c2ecf20Sopenharmony_ci case SCSI_PROT_READ_STRIP: 1808c2ecf20Sopenharmony_ci sig_attrs->mem.sig_type = IB_SIG_TYPE_NONE; 1818c2ecf20Sopenharmony_ci iser_set_dif_domain(sc, &sig_attrs->wire); 1828c2ecf20Sopenharmony_ci sig_attrs->wire.sig.dif.bg_type = IB_T10DIF_CRC; 1838c2ecf20Sopenharmony_ci break; 1848c2ecf20Sopenharmony_ci case SCSI_PROT_READ_INSERT: 1858c2ecf20Sopenharmony_ci case SCSI_PROT_WRITE_STRIP: 1868c2ecf20Sopenharmony_ci sig_attrs->wire.sig_type = IB_SIG_TYPE_NONE; 1878c2ecf20Sopenharmony_ci iser_set_dif_domain(sc, &sig_attrs->mem); 1888c2ecf20Sopenharmony_ci sig_attrs->mem.sig.dif.bg_type = sc->prot_flags & SCSI_PROT_IP_CHECKSUM ? 1898c2ecf20Sopenharmony_ci IB_T10DIF_CSUM : IB_T10DIF_CRC; 1908c2ecf20Sopenharmony_ci break; 1918c2ecf20Sopenharmony_ci case SCSI_PROT_READ_PASS: 1928c2ecf20Sopenharmony_ci case SCSI_PROT_WRITE_PASS: 1938c2ecf20Sopenharmony_ci iser_set_dif_domain(sc, &sig_attrs->wire); 1948c2ecf20Sopenharmony_ci sig_attrs->wire.sig.dif.bg_type = IB_T10DIF_CRC; 1958c2ecf20Sopenharmony_ci iser_set_dif_domain(sc, &sig_attrs->mem); 1968c2ecf20Sopenharmony_ci sig_attrs->mem.sig.dif.bg_type = sc->prot_flags & SCSI_PROT_IP_CHECKSUM ? 1978c2ecf20Sopenharmony_ci IB_T10DIF_CSUM : IB_T10DIF_CRC; 1988c2ecf20Sopenharmony_ci break; 1998c2ecf20Sopenharmony_ci default: 2008c2ecf20Sopenharmony_ci iser_err("Unsupported PI operation %d\n", 2018c2ecf20Sopenharmony_ci scsi_get_prot_op(sc)); 2028c2ecf20Sopenharmony_ci return -EINVAL; 2038c2ecf20Sopenharmony_ci } 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci return 0; 2068c2ecf20Sopenharmony_ci} 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_cistatic inline void 2098c2ecf20Sopenharmony_ciiser_set_prot_checks(struct scsi_cmnd *sc, u8 *mask) 2108c2ecf20Sopenharmony_ci{ 2118c2ecf20Sopenharmony_ci *mask = 0; 2128c2ecf20Sopenharmony_ci if (sc->prot_flags & SCSI_PROT_REF_CHECK) 2138c2ecf20Sopenharmony_ci *mask |= IB_SIG_CHECK_REFTAG; 2148c2ecf20Sopenharmony_ci if (sc->prot_flags & SCSI_PROT_GUARD_CHECK) 2158c2ecf20Sopenharmony_ci *mask |= IB_SIG_CHECK_GUARD; 2168c2ecf20Sopenharmony_ci} 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_cistatic inline void 2198c2ecf20Sopenharmony_ciiser_inv_rkey(struct ib_send_wr *inv_wr, 2208c2ecf20Sopenharmony_ci struct ib_mr *mr, 2218c2ecf20Sopenharmony_ci struct ib_cqe *cqe, 2228c2ecf20Sopenharmony_ci struct ib_send_wr *next_wr) 2238c2ecf20Sopenharmony_ci{ 2248c2ecf20Sopenharmony_ci inv_wr->opcode = IB_WR_LOCAL_INV; 2258c2ecf20Sopenharmony_ci inv_wr->wr_cqe = cqe; 2268c2ecf20Sopenharmony_ci inv_wr->ex.invalidate_rkey = mr->rkey; 2278c2ecf20Sopenharmony_ci inv_wr->send_flags = 0; 2288c2ecf20Sopenharmony_ci inv_wr->num_sge = 0; 2298c2ecf20Sopenharmony_ci inv_wr->next = next_wr; 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_cistatic int 2338c2ecf20Sopenharmony_ciiser_reg_sig_mr(struct iscsi_iser_task *iser_task, 2348c2ecf20Sopenharmony_ci struct iser_data_buf *mem, 2358c2ecf20Sopenharmony_ci struct iser_data_buf *sig_mem, 2368c2ecf20Sopenharmony_ci struct iser_reg_resources *rsc, 2378c2ecf20Sopenharmony_ci struct iser_mem_reg *sig_reg) 2388c2ecf20Sopenharmony_ci{ 2398c2ecf20Sopenharmony_ci struct iser_tx_desc *tx_desc = &iser_task->desc; 2408c2ecf20Sopenharmony_ci struct ib_cqe *cqe = &iser_task->iser_conn->ib_conn.reg_cqe; 2418c2ecf20Sopenharmony_ci struct ib_mr *mr = rsc->sig_mr; 2428c2ecf20Sopenharmony_ci struct ib_sig_attrs *sig_attrs = mr->sig_attrs; 2438c2ecf20Sopenharmony_ci struct ib_reg_wr *wr = &tx_desc->reg_wr; 2448c2ecf20Sopenharmony_ci int ret; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci memset(sig_attrs, 0, sizeof(*sig_attrs)); 2478c2ecf20Sopenharmony_ci ret = iser_set_sig_attrs(iser_task->sc, sig_attrs); 2488c2ecf20Sopenharmony_ci if (ret) 2498c2ecf20Sopenharmony_ci goto err; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci iser_set_prot_checks(iser_task->sc, &sig_attrs->check_mask); 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci if (rsc->sig_mr->need_inval) 2548c2ecf20Sopenharmony_ci iser_inv_rkey(&tx_desc->inv_wr, mr, cqe, &wr->wr); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci ib_update_fast_reg_key(mr, ib_inc_rkey(mr->rkey)); 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci ret = ib_map_mr_sg_pi(mr, mem->sg, mem->dma_nents, NULL, 2598c2ecf20Sopenharmony_ci sig_mem->sg, sig_mem->dma_nents, NULL, SZ_4K); 2608c2ecf20Sopenharmony_ci if (unlikely(ret)) { 2618c2ecf20Sopenharmony_ci iser_err("failed to map PI sg (%d)\n", 2628c2ecf20Sopenharmony_ci mem->dma_nents + sig_mem->dma_nents); 2638c2ecf20Sopenharmony_ci goto err; 2648c2ecf20Sopenharmony_ci } 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci memset(wr, 0, sizeof(*wr)); 2678c2ecf20Sopenharmony_ci wr->wr.next = &tx_desc->send_wr; 2688c2ecf20Sopenharmony_ci wr->wr.opcode = IB_WR_REG_MR_INTEGRITY; 2698c2ecf20Sopenharmony_ci wr->wr.wr_cqe = cqe; 2708c2ecf20Sopenharmony_ci wr->wr.num_sge = 0; 2718c2ecf20Sopenharmony_ci wr->wr.send_flags = 0; 2728c2ecf20Sopenharmony_ci wr->mr = mr; 2738c2ecf20Sopenharmony_ci wr->key = mr->rkey; 2748c2ecf20Sopenharmony_ci wr->access = IB_ACCESS_LOCAL_WRITE | 2758c2ecf20Sopenharmony_ci IB_ACCESS_REMOTE_READ | 2768c2ecf20Sopenharmony_ci IB_ACCESS_REMOTE_WRITE; 2778c2ecf20Sopenharmony_ci rsc->sig_mr->need_inval = true; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci sig_reg->sge.lkey = mr->lkey; 2808c2ecf20Sopenharmony_ci sig_reg->rkey = mr->rkey; 2818c2ecf20Sopenharmony_ci sig_reg->sge.addr = mr->iova; 2828c2ecf20Sopenharmony_ci sig_reg->sge.length = mr->length; 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci iser_dbg("lkey=0x%x rkey=0x%x addr=0x%llx length=%u\n", 2858c2ecf20Sopenharmony_ci sig_reg->sge.lkey, sig_reg->rkey, sig_reg->sge.addr, 2868c2ecf20Sopenharmony_ci sig_reg->sge.length); 2878c2ecf20Sopenharmony_cierr: 2888c2ecf20Sopenharmony_ci return ret; 2898c2ecf20Sopenharmony_ci} 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_cistatic int iser_fast_reg_mr(struct iscsi_iser_task *iser_task, 2928c2ecf20Sopenharmony_ci struct iser_data_buf *mem, 2938c2ecf20Sopenharmony_ci struct iser_reg_resources *rsc, 2948c2ecf20Sopenharmony_ci struct iser_mem_reg *reg) 2958c2ecf20Sopenharmony_ci{ 2968c2ecf20Sopenharmony_ci struct iser_tx_desc *tx_desc = &iser_task->desc; 2978c2ecf20Sopenharmony_ci struct ib_cqe *cqe = &iser_task->iser_conn->ib_conn.reg_cqe; 2988c2ecf20Sopenharmony_ci struct ib_mr *mr = rsc->mr; 2998c2ecf20Sopenharmony_ci struct ib_reg_wr *wr = &tx_desc->reg_wr; 3008c2ecf20Sopenharmony_ci int n; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci if (rsc->mr->need_inval) 3038c2ecf20Sopenharmony_ci iser_inv_rkey(&tx_desc->inv_wr, mr, cqe, &wr->wr); 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci ib_update_fast_reg_key(mr, ib_inc_rkey(mr->rkey)); 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci n = ib_map_mr_sg(mr, mem->sg, mem->dma_nents, NULL, SZ_4K); 3088c2ecf20Sopenharmony_ci if (unlikely(n != mem->dma_nents)) { 3098c2ecf20Sopenharmony_ci iser_err("failed to map sg (%d/%d)\n", 3108c2ecf20Sopenharmony_ci n, mem->dma_nents); 3118c2ecf20Sopenharmony_ci return n < 0 ? n : -EINVAL; 3128c2ecf20Sopenharmony_ci } 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci wr->wr.next = &tx_desc->send_wr; 3158c2ecf20Sopenharmony_ci wr->wr.opcode = IB_WR_REG_MR; 3168c2ecf20Sopenharmony_ci wr->wr.wr_cqe = cqe; 3178c2ecf20Sopenharmony_ci wr->wr.send_flags = 0; 3188c2ecf20Sopenharmony_ci wr->wr.num_sge = 0; 3198c2ecf20Sopenharmony_ci wr->mr = mr; 3208c2ecf20Sopenharmony_ci wr->key = mr->rkey; 3218c2ecf20Sopenharmony_ci wr->access = IB_ACCESS_LOCAL_WRITE | 3228c2ecf20Sopenharmony_ci IB_ACCESS_REMOTE_WRITE | 3238c2ecf20Sopenharmony_ci IB_ACCESS_REMOTE_READ; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci rsc->mr->need_inval = true; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci reg->sge.lkey = mr->lkey; 3288c2ecf20Sopenharmony_ci reg->rkey = mr->rkey; 3298c2ecf20Sopenharmony_ci reg->sge.addr = mr->iova; 3308c2ecf20Sopenharmony_ci reg->sge.length = mr->length; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci iser_dbg("lkey=0x%x rkey=0x%x addr=0x%llx length=0x%x\n", 3338c2ecf20Sopenharmony_ci reg->sge.lkey, reg->rkey, reg->sge.addr, reg->sge.length); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci return 0; 3368c2ecf20Sopenharmony_ci} 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_cistatic int 3398c2ecf20Sopenharmony_ciiser_reg_data_sg(struct iscsi_iser_task *task, 3408c2ecf20Sopenharmony_ci struct iser_data_buf *mem, 3418c2ecf20Sopenharmony_ci struct iser_fr_desc *desc, 3428c2ecf20Sopenharmony_ci bool use_dma_key, 3438c2ecf20Sopenharmony_ci struct iser_mem_reg *reg) 3448c2ecf20Sopenharmony_ci{ 3458c2ecf20Sopenharmony_ci struct iser_device *device = task->iser_conn->ib_conn.device; 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci if (use_dma_key) 3488c2ecf20Sopenharmony_ci return iser_reg_dma(device, mem, reg); 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci return iser_fast_reg_mr(task, mem, &desc->rsc, reg); 3518c2ecf20Sopenharmony_ci} 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ciint iser_reg_mem_fastreg(struct iscsi_iser_task *task, 3548c2ecf20Sopenharmony_ci enum iser_data_dir dir, 3558c2ecf20Sopenharmony_ci bool all_imm) 3568c2ecf20Sopenharmony_ci{ 3578c2ecf20Sopenharmony_ci struct ib_conn *ib_conn = &task->iser_conn->ib_conn; 3588c2ecf20Sopenharmony_ci struct iser_data_buf *mem = &task->data[dir]; 3598c2ecf20Sopenharmony_ci struct iser_mem_reg *reg = &task->rdma_reg[dir]; 3608c2ecf20Sopenharmony_ci struct iser_fr_desc *desc = NULL; 3618c2ecf20Sopenharmony_ci bool use_dma_key; 3628c2ecf20Sopenharmony_ci int err; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci use_dma_key = mem->dma_nents == 1 && (all_imm || !iser_always_reg) && 3658c2ecf20Sopenharmony_ci scsi_get_prot_op(task->sc) == SCSI_PROT_NORMAL; 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci if (!use_dma_key) { 3688c2ecf20Sopenharmony_ci desc = iser_reg_desc_get_fr(ib_conn); 3698c2ecf20Sopenharmony_ci reg->mem_h = desc; 3708c2ecf20Sopenharmony_ci } 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci if (scsi_get_prot_op(task->sc) == SCSI_PROT_NORMAL) { 3738c2ecf20Sopenharmony_ci err = iser_reg_data_sg(task, mem, desc, use_dma_key, reg); 3748c2ecf20Sopenharmony_ci if (unlikely(err)) 3758c2ecf20Sopenharmony_ci goto err_reg; 3768c2ecf20Sopenharmony_ci } else { 3778c2ecf20Sopenharmony_ci err = iser_reg_sig_mr(task, mem, &task->prot[dir], 3788c2ecf20Sopenharmony_ci &desc->rsc, reg); 3798c2ecf20Sopenharmony_ci if (unlikely(err)) 3808c2ecf20Sopenharmony_ci goto err_reg; 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci desc->sig_protected = true; 3838c2ecf20Sopenharmony_ci } 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci return 0; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_cierr_reg: 3888c2ecf20Sopenharmony_ci if (desc) 3898c2ecf20Sopenharmony_ci iser_reg_desc_put_fr(ib_conn, desc); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci return err; 3928c2ecf20Sopenharmony_ci} 3938c2ecf20Sopenharmony_ci 394