1a060b562SChristoph Hellwig /* 2a060b562SChristoph Hellwig * Copyright (c) 2016 HGST, a Western Digital Company. 3a060b562SChristoph Hellwig * 4a060b562SChristoph Hellwig * This program is free software; you can redistribute it and/or modify it 5a060b562SChristoph Hellwig * under the terms and conditions of the GNU General Public License, 6a060b562SChristoph Hellwig * version 2, as published by the Free Software Foundation. 7a060b562SChristoph Hellwig * 8a060b562SChristoph Hellwig * This program is distributed in the hope it will be useful, but WITHOUT 9a060b562SChristoph Hellwig * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10a060b562SChristoph Hellwig * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11a060b562SChristoph Hellwig * more details. 12a060b562SChristoph Hellwig */ 13a060b562SChristoph Hellwig #include <linux/moduleparam.h> 14a060b562SChristoph Hellwig #include <linux/slab.h> 15a060b562SChristoph Hellwig #include <rdma/mr_pool.h> 16a060b562SChristoph Hellwig #include <rdma/rw.h> 17a060b562SChristoph Hellwig 18a060b562SChristoph Hellwig enum { 19a060b562SChristoph Hellwig RDMA_RW_SINGLE_WR, 20a060b562SChristoph Hellwig RDMA_RW_MULTI_WR, 21a060b562SChristoph Hellwig RDMA_RW_MR, 22a060b562SChristoph Hellwig }; 23a060b562SChristoph Hellwig 24a060b562SChristoph Hellwig static bool rdma_rw_force_mr; 25a060b562SChristoph Hellwig module_param_named(force_mr, rdma_rw_force_mr, bool, 0); 26a060b562SChristoph Hellwig MODULE_PARM_DESC(force_mr, "Force usage of MRs for RDMA READ/WRITE operations"); 27a060b562SChristoph Hellwig 28a060b562SChristoph Hellwig /* 29a060b562SChristoph Hellwig * Check if the device might use memory registration. This is currently only 30a060b562SChristoph Hellwig * true for iWarp devices. In the future we can hopefully fine tune this based 31a060b562SChristoph Hellwig * on HCA driver input. 32a060b562SChristoph Hellwig */ 33a060b562SChristoph Hellwig static inline bool rdma_rw_can_use_mr(struct ib_device *dev, u8 port_num) 34a060b562SChristoph Hellwig { 35a060b562SChristoph Hellwig if (rdma_protocol_iwarp(dev, port_num)) 36a060b562SChristoph Hellwig return true; 37a060b562SChristoph Hellwig if (unlikely(rdma_rw_force_mr)) 38a060b562SChristoph Hellwig return true; 39a060b562SChristoph Hellwig return false; 40a060b562SChristoph Hellwig } 41a060b562SChristoph Hellwig 42a060b562SChristoph Hellwig /* 43a060b562SChristoph Hellwig * Check if the device will use memory registration for this RW operation. 44a060b562SChristoph Hellwig * We currently always use memory registrations for iWarp RDMA READs, and 45a060b562SChristoph Hellwig * have a debug option to force usage of MRs. 46a060b562SChristoph Hellwig * 47a060b562SChristoph Hellwig * XXX: In the future we can hopefully fine tune this based on HCA driver 48a060b562SChristoph Hellwig * input. 49a060b562SChristoph Hellwig */ 50a060b562SChristoph Hellwig static inline bool rdma_rw_io_needs_mr(struct ib_device *dev, u8 port_num, 51a060b562SChristoph Hellwig enum dma_data_direction dir, int dma_nents) 52a060b562SChristoph Hellwig { 53a060b562SChristoph Hellwig if (rdma_protocol_iwarp(dev, port_num) && dir == DMA_FROM_DEVICE) 54a060b562SChristoph Hellwig return true; 55a060b562SChristoph Hellwig if (unlikely(rdma_rw_force_mr)) 56a060b562SChristoph Hellwig return true; 57a060b562SChristoph Hellwig return false; 58a060b562SChristoph Hellwig } 59a060b562SChristoph Hellwig 60a060b562SChristoph Hellwig static inline u32 rdma_rw_max_sge(struct ib_device *dev, 61a060b562SChristoph Hellwig enum dma_data_direction dir) 62a060b562SChristoph Hellwig { 63a060b562SChristoph Hellwig return dir == DMA_TO_DEVICE ? 64a060b562SChristoph Hellwig dev->attrs.max_sge : dev->attrs.max_sge_rd; 65a060b562SChristoph Hellwig } 66a060b562SChristoph Hellwig 67a060b562SChristoph Hellwig static inline u32 rdma_rw_fr_page_list_len(struct ib_device *dev) 68a060b562SChristoph Hellwig { 69a060b562SChristoph Hellwig /* arbitrary limit to avoid allocating gigantic resources */ 70a060b562SChristoph Hellwig return min_t(u32, dev->attrs.max_fast_reg_page_list_len, 256); 71a060b562SChristoph Hellwig } 72a060b562SChristoph Hellwig 73a060b562SChristoph Hellwig static int rdma_rw_init_one_mr(struct ib_qp *qp, u8 port_num, 74a060b562SChristoph Hellwig struct rdma_rw_reg_ctx *reg, struct scatterlist *sg, 75a060b562SChristoph Hellwig u32 sg_cnt, u32 offset) 76a060b562SChristoph Hellwig { 77a060b562SChristoph Hellwig u32 pages_per_mr = rdma_rw_fr_page_list_len(qp->pd->device); 78a060b562SChristoph Hellwig u32 nents = min(sg_cnt, pages_per_mr); 79a060b562SChristoph Hellwig int count = 0, ret; 80a060b562SChristoph Hellwig 81a060b562SChristoph Hellwig reg->mr = ib_mr_pool_get(qp, &qp->rdma_mrs); 82a060b562SChristoph Hellwig if (!reg->mr) 83a060b562SChristoph Hellwig return -EAGAIN; 84a060b562SChristoph Hellwig 85a060b562SChristoph Hellwig if (reg->mr->need_inval) { 86a060b562SChristoph Hellwig reg->inv_wr.opcode = IB_WR_LOCAL_INV; 87a060b562SChristoph Hellwig reg->inv_wr.ex.invalidate_rkey = reg->mr->lkey; 88a060b562SChristoph Hellwig reg->inv_wr.next = ®->reg_wr.wr; 89a060b562SChristoph Hellwig count++; 90a060b562SChristoph Hellwig } else { 91a060b562SChristoph Hellwig reg->inv_wr.next = NULL; 92a060b562SChristoph Hellwig } 93a060b562SChristoph Hellwig 94a060b562SChristoph Hellwig ret = ib_map_mr_sg(reg->mr, sg, nents, offset, PAGE_SIZE); 95a060b562SChristoph Hellwig if (ret < nents) { 96a060b562SChristoph Hellwig ib_mr_pool_put(qp, &qp->rdma_mrs, reg->mr); 97a060b562SChristoph Hellwig return -EINVAL; 98a060b562SChristoph Hellwig } 99a060b562SChristoph Hellwig 100a060b562SChristoph Hellwig reg->reg_wr.wr.opcode = IB_WR_REG_MR; 101a060b562SChristoph Hellwig reg->reg_wr.mr = reg->mr; 102a060b562SChristoph Hellwig reg->reg_wr.access = IB_ACCESS_LOCAL_WRITE; 103a060b562SChristoph Hellwig if (rdma_protocol_iwarp(qp->device, port_num)) 104a060b562SChristoph Hellwig reg->reg_wr.access |= IB_ACCESS_REMOTE_WRITE; 105a060b562SChristoph Hellwig count++; 106a060b562SChristoph Hellwig 107a060b562SChristoph Hellwig reg->sge.addr = reg->mr->iova; 108a060b562SChristoph Hellwig reg->sge.length = reg->mr->length; 109a060b562SChristoph Hellwig return count; 110a060b562SChristoph Hellwig } 111a060b562SChristoph Hellwig 112a060b562SChristoph Hellwig static int rdma_rw_init_mr_wrs(struct rdma_rw_ctx *ctx, struct ib_qp *qp, 113a060b562SChristoph Hellwig u8 port_num, struct scatterlist *sg, u32 sg_cnt, u32 offset, 114a060b562SChristoph Hellwig u64 remote_addr, u32 rkey, enum dma_data_direction dir) 115a060b562SChristoph Hellwig { 116a060b562SChristoph Hellwig u32 pages_per_mr = rdma_rw_fr_page_list_len(qp->pd->device); 117a060b562SChristoph Hellwig int i, j, ret = 0, count = 0; 118a060b562SChristoph Hellwig 119a060b562SChristoph Hellwig ctx->nr_ops = (sg_cnt + pages_per_mr - 1) / pages_per_mr; 120a060b562SChristoph Hellwig ctx->reg = kcalloc(ctx->nr_ops, sizeof(*ctx->reg), GFP_KERNEL); 121a060b562SChristoph Hellwig if (!ctx->reg) { 122a060b562SChristoph Hellwig ret = -ENOMEM; 123a060b562SChristoph Hellwig goto out; 124a060b562SChristoph Hellwig } 125a060b562SChristoph Hellwig 126a060b562SChristoph Hellwig for (i = 0; i < ctx->nr_ops; i++) { 127a060b562SChristoph Hellwig struct rdma_rw_reg_ctx *prev = i ? &ctx->reg[i - 1] : NULL; 128a060b562SChristoph Hellwig struct rdma_rw_reg_ctx *reg = &ctx->reg[i]; 129a060b562SChristoph Hellwig u32 nents = min(sg_cnt, pages_per_mr); 130a060b562SChristoph Hellwig 131a060b562SChristoph Hellwig ret = rdma_rw_init_one_mr(qp, port_num, reg, sg, sg_cnt, 132a060b562SChristoph Hellwig offset); 133a060b562SChristoph Hellwig if (ret < 0) 134a060b562SChristoph Hellwig goto out_free; 135a060b562SChristoph Hellwig count += ret; 136a060b562SChristoph Hellwig 137a060b562SChristoph Hellwig if (prev) { 138a060b562SChristoph Hellwig if (reg->mr->need_inval) 139a060b562SChristoph Hellwig prev->wr.wr.next = ®->inv_wr; 140a060b562SChristoph Hellwig else 141a060b562SChristoph Hellwig prev->wr.wr.next = ®->reg_wr.wr; 142a060b562SChristoph Hellwig } 143a060b562SChristoph Hellwig 144a060b562SChristoph Hellwig reg->reg_wr.wr.next = ®->wr.wr; 145a060b562SChristoph Hellwig 146a060b562SChristoph Hellwig reg->wr.wr.sg_list = ®->sge; 147a060b562SChristoph Hellwig reg->wr.wr.num_sge = 1; 148a060b562SChristoph Hellwig reg->wr.remote_addr = remote_addr; 149a060b562SChristoph Hellwig reg->wr.rkey = rkey; 150a060b562SChristoph Hellwig if (dir == DMA_TO_DEVICE) { 151a060b562SChristoph Hellwig reg->wr.wr.opcode = IB_WR_RDMA_WRITE; 152a060b562SChristoph Hellwig } else if (!rdma_cap_read_inv(qp->device, port_num)) { 153a060b562SChristoph Hellwig reg->wr.wr.opcode = IB_WR_RDMA_READ; 154a060b562SChristoph Hellwig } else { 155a060b562SChristoph Hellwig reg->wr.wr.opcode = IB_WR_RDMA_READ_WITH_INV; 156a060b562SChristoph Hellwig reg->wr.wr.ex.invalidate_rkey = reg->mr->lkey; 157a060b562SChristoph Hellwig } 158a060b562SChristoph Hellwig count++; 159a060b562SChristoph Hellwig 160a060b562SChristoph Hellwig remote_addr += reg->sge.length; 161a060b562SChristoph Hellwig sg_cnt -= nents; 162a060b562SChristoph Hellwig for (j = 0; j < nents; j++) 163a060b562SChristoph Hellwig sg = sg_next(sg); 164a060b562SChristoph Hellwig offset = 0; 165a060b562SChristoph Hellwig } 166a060b562SChristoph Hellwig 167a060b562SChristoph Hellwig ctx->type = RDMA_RW_MR; 168a060b562SChristoph Hellwig return count; 169a060b562SChristoph Hellwig 170a060b562SChristoph Hellwig out_free: 171a060b562SChristoph Hellwig while (--i >= 0) 172a060b562SChristoph Hellwig ib_mr_pool_put(qp, &qp->rdma_mrs, ctx->reg[i].mr); 173a060b562SChristoph Hellwig kfree(ctx->reg); 174a060b562SChristoph Hellwig out: 175a060b562SChristoph Hellwig return ret; 176a060b562SChristoph Hellwig } 177a060b562SChristoph Hellwig 178a060b562SChristoph Hellwig static int rdma_rw_init_map_wrs(struct rdma_rw_ctx *ctx, struct ib_qp *qp, 179a060b562SChristoph Hellwig struct scatterlist *sg, u32 sg_cnt, u32 offset, 180a060b562SChristoph Hellwig u64 remote_addr, u32 rkey, enum dma_data_direction dir) 181a060b562SChristoph Hellwig { 182a060b562SChristoph Hellwig struct ib_device *dev = qp->pd->device; 183a060b562SChristoph Hellwig u32 max_sge = rdma_rw_max_sge(dev, dir); 184a060b562SChristoph Hellwig struct ib_sge *sge; 185a060b562SChristoph Hellwig u32 total_len = 0, i, j; 186a060b562SChristoph Hellwig 187a060b562SChristoph Hellwig ctx->nr_ops = DIV_ROUND_UP(sg_cnt, max_sge); 188a060b562SChristoph Hellwig 189a060b562SChristoph Hellwig ctx->map.sges = sge = kcalloc(sg_cnt, sizeof(*sge), GFP_KERNEL); 190a060b562SChristoph Hellwig if (!ctx->map.sges) 191a060b562SChristoph Hellwig goto out; 192a060b562SChristoph Hellwig 193a060b562SChristoph Hellwig ctx->map.wrs = kcalloc(ctx->nr_ops, sizeof(*ctx->map.wrs), GFP_KERNEL); 194a060b562SChristoph Hellwig if (!ctx->map.wrs) 195a060b562SChristoph Hellwig goto out_free_sges; 196a060b562SChristoph Hellwig 197a060b562SChristoph Hellwig for (i = 0; i < ctx->nr_ops; i++) { 198a060b562SChristoph Hellwig struct ib_rdma_wr *rdma_wr = &ctx->map.wrs[i]; 199a060b562SChristoph Hellwig u32 nr_sge = min(sg_cnt, max_sge); 200a060b562SChristoph Hellwig 201a060b562SChristoph Hellwig if (dir == DMA_TO_DEVICE) 202a060b562SChristoph Hellwig rdma_wr->wr.opcode = IB_WR_RDMA_WRITE; 203a060b562SChristoph Hellwig else 204a060b562SChristoph Hellwig rdma_wr->wr.opcode = IB_WR_RDMA_READ; 205a060b562SChristoph Hellwig rdma_wr->remote_addr = remote_addr + total_len; 206a060b562SChristoph Hellwig rdma_wr->rkey = rkey; 207a060b562SChristoph Hellwig rdma_wr->wr.sg_list = sge; 208a060b562SChristoph Hellwig 209a060b562SChristoph Hellwig for (j = 0; j < nr_sge; j++, sg = sg_next(sg)) { 210a060b562SChristoph Hellwig rdma_wr->wr.num_sge++; 211a060b562SChristoph Hellwig 212a060b562SChristoph Hellwig sge->addr = ib_sg_dma_address(dev, sg) + offset; 213a060b562SChristoph Hellwig sge->length = ib_sg_dma_len(dev, sg) - offset; 214a060b562SChristoph Hellwig sge->lkey = qp->pd->local_dma_lkey; 215a060b562SChristoph Hellwig 216a060b562SChristoph Hellwig total_len += sge->length; 217a060b562SChristoph Hellwig sge++; 218a060b562SChristoph Hellwig sg_cnt--; 219a060b562SChristoph Hellwig offset = 0; 220a060b562SChristoph Hellwig } 221a060b562SChristoph Hellwig 222a060b562SChristoph Hellwig if (i + 1 < ctx->nr_ops) 223a060b562SChristoph Hellwig rdma_wr->wr.next = &ctx->map.wrs[i + 1].wr; 224a060b562SChristoph Hellwig } 225a060b562SChristoph Hellwig 226a060b562SChristoph Hellwig ctx->type = RDMA_RW_MULTI_WR; 227a060b562SChristoph Hellwig return ctx->nr_ops; 228a060b562SChristoph Hellwig 229a060b562SChristoph Hellwig out_free_sges: 230a060b562SChristoph Hellwig kfree(ctx->map.sges); 231a060b562SChristoph Hellwig out: 232a060b562SChristoph Hellwig return -ENOMEM; 233a060b562SChristoph Hellwig } 234a060b562SChristoph Hellwig 235a060b562SChristoph Hellwig static int rdma_rw_init_single_wr(struct rdma_rw_ctx *ctx, struct ib_qp *qp, 236a060b562SChristoph Hellwig struct scatterlist *sg, u32 offset, u64 remote_addr, u32 rkey, 237a060b562SChristoph Hellwig enum dma_data_direction dir) 238a060b562SChristoph Hellwig { 239a060b562SChristoph Hellwig struct ib_device *dev = qp->pd->device; 240a060b562SChristoph Hellwig struct ib_rdma_wr *rdma_wr = &ctx->single.wr; 241a060b562SChristoph Hellwig 242a060b562SChristoph Hellwig ctx->nr_ops = 1; 243a060b562SChristoph Hellwig 244a060b562SChristoph Hellwig ctx->single.sge.lkey = qp->pd->local_dma_lkey; 245a060b562SChristoph Hellwig ctx->single.sge.addr = ib_sg_dma_address(dev, sg) + offset; 246a060b562SChristoph Hellwig ctx->single.sge.length = ib_sg_dma_len(dev, sg) - offset; 247a060b562SChristoph Hellwig 248a060b562SChristoph Hellwig memset(rdma_wr, 0, sizeof(*rdma_wr)); 249a060b562SChristoph Hellwig if (dir == DMA_TO_DEVICE) 250a060b562SChristoph Hellwig rdma_wr->wr.opcode = IB_WR_RDMA_WRITE; 251a060b562SChristoph Hellwig else 252a060b562SChristoph Hellwig rdma_wr->wr.opcode = IB_WR_RDMA_READ; 253a060b562SChristoph Hellwig rdma_wr->wr.sg_list = &ctx->single.sge; 254a060b562SChristoph Hellwig rdma_wr->wr.num_sge = 1; 255a060b562SChristoph Hellwig rdma_wr->remote_addr = remote_addr; 256a060b562SChristoph Hellwig rdma_wr->rkey = rkey; 257a060b562SChristoph Hellwig 258a060b562SChristoph Hellwig ctx->type = RDMA_RW_SINGLE_WR; 259a060b562SChristoph Hellwig return 1; 260a060b562SChristoph Hellwig } 261a060b562SChristoph Hellwig 262a060b562SChristoph Hellwig /** 263a060b562SChristoph Hellwig * rdma_rw_ctx_init - initialize a RDMA READ/WRITE context 264a060b562SChristoph Hellwig * @ctx: context to initialize 265a060b562SChristoph Hellwig * @qp: queue pair to operate on 266a060b562SChristoph Hellwig * @port_num: port num to which the connection is bound 267a060b562SChristoph Hellwig * @sg: scatterlist to READ/WRITE from/to 268a060b562SChristoph Hellwig * @sg_cnt: number of entries in @sg 269a060b562SChristoph Hellwig * @sg_offset: current byte offset into @sg 270a060b562SChristoph Hellwig * @remote_addr:remote address to read/write (relative to @rkey) 271a060b562SChristoph Hellwig * @rkey: remote key to operate on 272a060b562SChristoph Hellwig * @dir: %DMA_TO_DEVICE for RDMA WRITE, %DMA_FROM_DEVICE for RDMA READ 273a060b562SChristoph Hellwig * 274a060b562SChristoph Hellwig * Returns the number of WQEs that will be needed on the workqueue if 275a060b562SChristoph Hellwig * successful, or a negative error code. 276a060b562SChristoph Hellwig */ 277a060b562SChristoph Hellwig int rdma_rw_ctx_init(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u8 port_num, 278a060b562SChristoph Hellwig struct scatterlist *sg, u32 sg_cnt, u32 sg_offset, 279a060b562SChristoph Hellwig u64 remote_addr, u32 rkey, enum dma_data_direction dir) 280a060b562SChristoph Hellwig { 281a060b562SChristoph Hellwig struct ib_device *dev = qp->pd->device; 282a060b562SChristoph Hellwig int ret; 283a060b562SChristoph Hellwig 284a060b562SChristoph Hellwig ret = ib_dma_map_sg(dev, sg, sg_cnt, dir); 285a060b562SChristoph Hellwig if (!ret) 286a060b562SChristoph Hellwig return -ENOMEM; 287a060b562SChristoph Hellwig sg_cnt = ret; 288a060b562SChristoph Hellwig 289a060b562SChristoph Hellwig /* 290a060b562SChristoph Hellwig * Skip to the S/G entry that sg_offset falls into: 291a060b562SChristoph Hellwig */ 292a060b562SChristoph Hellwig for (;;) { 293a060b562SChristoph Hellwig u32 len = ib_sg_dma_len(dev, sg); 294a060b562SChristoph Hellwig 295a060b562SChristoph Hellwig if (sg_offset < len) 296a060b562SChristoph Hellwig break; 297a060b562SChristoph Hellwig 298a060b562SChristoph Hellwig sg = sg_next(sg); 299a060b562SChristoph Hellwig sg_offset -= len; 300a060b562SChristoph Hellwig sg_cnt--; 301a060b562SChristoph Hellwig } 302a060b562SChristoph Hellwig 303a060b562SChristoph Hellwig ret = -EIO; 304a060b562SChristoph Hellwig if (WARN_ON_ONCE(sg_cnt == 0)) 305a060b562SChristoph Hellwig goto out_unmap_sg; 306a060b562SChristoph Hellwig 307a060b562SChristoph Hellwig if (rdma_rw_io_needs_mr(qp->device, port_num, dir, sg_cnt)) { 308a060b562SChristoph Hellwig ret = rdma_rw_init_mr_wrs(ctx, qp, port_num, sg, sg_cnt, 309a060b562SChristoph Hellwig sg_offset, remote_addr, rkey, dir); 310a060b562SChristoph Hellwig } else if (sg_cnt > 1) { 311a060b562SChristoph Hellwig ret = rdma_rw_init_map_wrs(ctx, qp, sg, sg_cnt, sg_offset, 312a060b562SChristoph Hellwig remote_addr, rkey, dir); 313a060b562SChristoph Hellwig } else { 314a060b562SChristoph Hellwig ret = rdma_rw_init_single_wr(ctx, qp, sg, sg_offset, 315a060b562SChristoph Hellwig remote_addr, rkey, dir); 316a060b562SChristoph Hellwig } 317a060b562SChristoph Hellwig 318a060b562SChristoph Hellwig if (ret < 0) 319a060b562SChristoph Hellwig goto out_unmap_sg; 320a060b562SChristoph Hellwig return ret; 321a060b562SChristoph Hellwig 322a060b562SChristoph Hellwig out_unmap_sg: 323a060b562SChristoph Hellwig ib_dma_unmap_sg(dev, sg, sg_cnt, dir); 324a060b562SChristoph Hellwig return ret; 325a060b562SChristoph Hellwig } 326a060b562SChristoph Hellwig EXPORT_SYMBOL(rdma_rw_ctx_init); 327a060b562SChristoph Hellwig 328a060b562SChristoph Hellwig /* 329a060b562SChristoph Hellwig * Now that we are going to post the WRs we can update the lkey and need_inval 330a060b562SChristoph Hellwig * state on the MRs. If we were doing this at init time, we would get double 331a060b562SChristoph Hellwig * or missing invalidations if a context was initialized but not actually 332a060b562SChristoph Hellwig * posted. 333a060b562SChristoph Hellwig */ 334a060b562SChristoph Hellwig static void rdma_rw_update_lkey(struct rdma_rw_reg_ctx *reg, bool need_inval) 335a060b562SChristoph Hellwig { 336a060b562SChristoph Hellwig reg->mr->need_inval = need_inval; 337a060b562SChristoph Hellwig ib_update_fast_reg_key(reg->mr, ib_inc_rkey(reg->mr->lkey)); 338a060b562SChristoph Hellwig reg->reg_wr.key = reg->mr->lkey; 339a060b562SChristoph Hellwig reg->sge.lkey = reg->mr->lkey; 340a060b562SChristoph Hellwig } 341a060b562SChristoph Hellwig 342a060b562SChristoph Hellwig /** 343a060b562SChristoph Hellwig * rdma_rw_ctx_wrs - return chain of WRs for a RDMA READ or WRITE operation 344a060b562SChristoph Hellwig * @ctx: context to operate on 345a060b562SChristoph Hellwig * @qp: queue pair to operate on 346a060b562SChristoph Hellwig * @port_num: port num to which the connection is bound 347a060b562SChristoph Hellwig * @cqe: completion queue entry for the last WR 348a060b562SChristoph Hellwig * @chain_wr: WR to append to the posted chain 349a060b562SChristoph Hellwig * 350a060b562SChristoph Hellwig * Return the WR chain for the set of RDMA READ/WRITE operations described by 351a060b562SChristoph Hellwig * @ctx, as well as any memory registration operations needed. If @chain_wr 352a060b562SChristoph Hellwig * is non-NULL the WR it points to will be appended to the chain of WRs posted. 353a060b562SChristoph Hellwig * If @chain_wr is not set @cqe must be set so that the caller gets a 354a060b562SChristoph Hellwig * completion notification. 355a060b562SChristoph Hellwig */ 356a060b562SChristoph Hellwig struct ib_send_wr *rdma_rw_ctx_wrs(struct rdma_rw_ctx *ctx, struct ib_qp *qp, 357a060b562SChristoph Hellwig u8 port_num, struct ib_cqe *cqe, struct ib_send_wr *chain_wr) 358a060b562SChristoph Hellwig { 359a060b562SChristoph Hellwig struct ib_send_wr *first_wr, *last_wr; 360a060b562SChristoph Hellwig int i; 361a060b562SChristoph Hellwig 362a060b562SChristoph Hellwig switch (ctx->type) { 363a060b562SChristoph Hellwig case RDMA_RW_MR: 364a060b562SChristoph Hellwig for (i = 0; i < ctx->nr_ops; i++) { 365a060b562SChristoph Hellwig rdma_rw_update_lkey(&ctx->reg[i], 366a060b562SChristoph Hellwig ctx->reg[i].wr.wr.opcode != 367a060b562SChristoph Hellwig IB_WR_RDMA_READ_WITH_INV); 368a060b562SChristoph Hellwig } 369a060b562SChristoph Hellwig 370a060b562SChristoph Hellwig if (ctx->reg[0].inv_wr.next) 371a060b562SChristoph Hellwig first_wr = &ctx->reg[0].inv_wr; 372a060b562SChristoph Hellwig else 373a060b562SChristoph Hellwig first_wr = &ctx->reg[0].reg_wr.wr; 374a060b562SChristoph Hellwig last_wr = &ctx->reg[ctx->nr_ops - 1].wr.wr; 375a060b562SChristoph Hellwig break; 376a060b562SChristoph Hellwig case RDMA_RW_MULTI_WR: 377a060b562SChristoph Hellwig first_wr = &ctx->map.wrs[0].wr; 378a060b562SChristoph Hellwig last_wr = &ctx->map.wrs[ctx->nr_ops - 1].wr; 379a060b562SChristoph Hellwig break; 380a060b562SChristoph Hellwig case RDMA_RW_SINGLE_WR: 381a060b562SChristoph Hellwig first_wr = &ctx->single.wr.wr; 382a060b562SChristoph Hellwig last_wr = &ctx->single.wr.wr; 383a060b562SChristoph Hellwig break; 384a060b562SChristoph Hellwig default: 385a060b562SChristoph Hellwig BUG(); 386a060b562SChristoph Hellwig } 387a060b562SChristoph Hellwig 388a060b562SChristoph Hellwig if (chain_wr) { 389a060b562SChristoph Hellwig last_wr->next = chain_wr; 390a060b562SChristoph Hellwig } else { 391a060b562SChristoph Hellwig last_wr->wr_cqe = cqe; 392a060b562SChristoph Hellwig last_wr->send_flags |= IB_SEND_SIGNALED; 393a060b562SChristoph Hellwig } 394a060b562SChristoph Hellwig 395a060b562SChristoph Hellwig return first_wr; 396a060b562SChristoph Hellwig } 397a060b562SChristoph Hellwig EXPORT_SYMBOL(rdma_rw_ctx_wrs); 398a060b562SChristoph Hellwig 399a060b562SChristoph Hellwig /** 400a060b562SChristoph Hellwig * rdma_rw_ctx_post - post a RDMA READ or RDMA WRITE operation 401a060b562SChristoph Hellwig * @ctx: context to operate on 402a060b562SChristoph Hellwig * @qp: queue pair to operate on 403a060b562SChristoph Hellwig * @port_num: port num to which the connection is bound 404a060b562SChristoph Hellwig * @cqe: completion queue entry for the last WR 405a060b562SChristoph Hellwig * @chain_wr: WR to append to the posted chain 406a060b562SChristoph Hellwig * 407a060b562SChristoph Hellwig * Post the set of RDMA READ/WRITE operations described by @ctx, as well as 408a060b562SChristoph Hellwig * any memory registration operations needed. If @chain_wr is non-NULL the 409a060b562SChristoph Hellwig * WR it points to will be appended to the chain of WRs posted. If @chain_wr 410a060b562SChristoph Hellwig * is not set @cqe must be set so that the caller gets a completion 411a060b562SChristoph Hellwig * notification. 412a060b562SChristoph Hellwig */ 413a060b562SChristoph Hellwig int rdma_rw_ctx_post(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u8 port_num, 414a060b562SChristoph Hellwig struct ib_cqe *cqe, struct ib_send_wr *chain_wr) 415a060b562SChristoph Hellwig { 416a060b562SChristoph Hellwig struct ib_send_wr *first_wr, *bad_wr; 417a060b562SChristoph Hellwig 418a060b562SChristoph Hellwig first_wr = rdma_rw_ctx_wrs(ctx, qp, port_num, cqe, chain_wr); 419a060b562SChristoph Hellwig return ib_post_send(qp, first_wr, &bad_wr); 420a060b562SChristoph Hellwig } 421a060b562SChristoph Hellwig EXPORT_SYMBOL(rdma_rw_ctx_post); 422a060b562SChristoph Hellwig 423a060b562SChristoph Hellwig /** 424a060b562SChristoph Hellwig * rdma_rw_ctx_destroy - release all resources allocated by rdma_rw_ctx_init 425a060b562SChristoph Hellwig * @ctx: context to release 426a060b562SChristoph Hellwig * @qp: queue pair to operate on 427a060b562SChristoph Hellwig * @port_num: port num to which the connection is bound 428a060b562SChristoph Hellwig * @sg: scatterlist that was used for the READ/WRITE 429a060b562SChristoph Hellwig * @sg_cnt: number of entries in @sg 430a060b562SChristoph Hellwig * @dir: %DMA_TO_DEVICE for RDMA WRITE, %DMA_FROM_DEVICE for RDMA READ 431a060b562SChristoph Hellwig */ 432a060b562SChristoph Hellwig void rdma_rw_ctx_destroy(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u8 port_num, 433a060b562SChristoph Hellwig struct scatterlist *sg, u32 sg_cnt, enum dma_data_direction dir) 434a060b562SChristoph Hellwig { 435a060b562SChristoph Hellwig int i; 436a060b562SChristoph Hellwig 437a060b562SChristoph Hellwig switch (ctx->type) { 438a060b562SChristoph Hellwig case RDMA_RW_MR: 439a060b562SChristoph Hellwig for (i = 0; i < ctx->nr_ops; i++) 440a060b562SChristoph Hellwig ib_mr_pool_put(qp, &qp->rdma_mrs, ctx->reg[i].mr); 441a060b562SChristoph Hellwig kfree(ctx->reg); 442a060b562SChristoph Hellwig break; 443a060b562SChristoph Hellwig case RDMA_RW_MULTI_WR: 444a060b562SChristoph Hellwig kfree(ctx->map.wrs); 445a060b562SChristoph Hellwig kfree(ctx->map.sges); 446a060b562SChristoph Hellwig break; 447a060b562SChristoph Hellwig case RDMA_RW_SINGLE_WR: 448a060b562SChristoph Hellwig break; 449a060b562SChristoph Hellwig default: 450a060b562SChristoph Hellwig BUG(); 451a060b562SChristoph Hellwig break; 452a060b562SChristoph Hellwig } 453a060b562SChristoph Hellwig 454a060b562SChristoph Hellwig ib_dma_unmap_sg(qp->pd->device, sg, sg_cnt, dir); 455a060b562SChristoph Hellwig } 456a060b562SChristoph Hellwig EXPORT_SYMBOL(rdma_rw_ctx_destroy); 457a060b562SChristoph Hellwig 458a060b562SChristoph Hellwig void rdma_rw_init_qp(struct ib_device *dev, struct ib_qp_init_attr *attr) 459a060b562SChristoph Hellwig { 460a060b562SChristoph Hellwig u32 factor; 461a060b562SChristoph Hellwig 462a060b562SChristoph Hellwig WARN_ON_ONCE(attr->port_num == 0); 463a060b562SChristoph Hellwig 464a060b562SChristoph Hellwig /* 465a060b562SChristoph Hellwig * Each context needs at least one RDMA READ or WRITE WR. 466a060b562SChristoph Hellwig * 467a060b562SChristoph Hellwig * For some hardware we might need more, eventually we should ask the 468a060b562SChristoph Hellwig * HCA driver for a multiplier here. 469a060b562SChristoph Hellwig */ 470a060b562SChristoph Hellwig factor = 1; 471a060b562SChristoph Hellwig 472a060b562SChristoph Hellwig /* 473a060b562SChristoph Hellwig * If the devices needs MRs to perform RDMA READ or WRITE operations, 474a060b562SChristoph Hellwig * we'll need two additional MRs for the registrations and the 475a060b562SChristoph Hellwig * invalidation. 476a060b562SChristoph Hellwig */ 477a060b562SChristoph Hellwig if (rdma_rw_can_use_mr(dev, attr->port_num)) 478a060b562SChristoph Hellwig factor += 2; /* inv + reg */ 479a060b562SChristoph Hellwig 480a060b562SChristoph Hellwig attr->cap.max_send_wr += factor * attr->cap.max_rdma_ctxs; 481a060b562SChristoph Hellwig 482a060b562SChristoph Hellwig /* 483a060b562SChristoph Hellwig * But maybe we were just too high in the sky and the device doesn't 484a060b562SChristoph Hellwig * even support all we need, and we'll have to live with what we get.. 485a060b562SChristoph Hellwig */ 486a060b562SChristoph Hellwig attr->cap.max_send_wr = 487a060b562SChristoph Hellwig min_t(u32, attr->cap.max_send_wr, dev->attrs.max_qp_wr); 488a060b562SChristoph Hellwig } 489a060b562SChristoph Hellwig 490a060b562SChristoph Hellwig int rdma_rw_init_mrs(struct ib_qp *qp, struct ib_qp_init_attr *attr) 491a060b562SChristoph Hellwig { 492a060b562SChristoph Hellwig struct ib_device *dev = qp->pd->device; 493a060b562SChristoph Hellwig int ret = 0; 494a060b562SChristoph Hellwig 495a060b562SChristoph Hellwig if (rdma_rw_can_use_mr(dev, attr->port_num)) { 496a060b562SChristoph Hellwig ret = ib_mr_pool_init(qp, &qp->rdma_mrs, 497a060b562SChristoph Hellwig attr->cap.max_rdma_ctxs, IB_MR_TYPE_MEM_REG, 498a060b562SChristoph Hellwig rdma_rw_fr_page_list_len(dev)); 499a060b562SChristoph Hellwig if (ret) 500a060b562SChristoph Hellwig return ret; 501a060b562SChristoph Hellwig } 502a060b562SChristoph Hellwig 503a060b562SChristoph Hellwig return ret; 504a060b562SChristoph Hellwig } 505a060b562SChristoph Hellwig 506a060b562SChristoph Hellwig void rdma_rw_cleanup_mrs(struct ib_qp *qp) 507a060b562SChristoph Hellwig { 508a060b562SChristoph Hellwig ib_mr_pool_destroy(qp, &qp->rdma_mrs); 509a060b562SChristoph Hellwig } 510