1*8f000cacSChristoph Hellwig /* 2*8f000cacSChristoph Hellwig * NVMe over Fabrics RDMA target. 3*8f000cacSChristoph Hellwig * Copyright (c) 2015-2016 HGST, a Western Digital Company. 4*8f000cacSChristoph Hellwig * 5*8f000cacSChristoph Hellwig * This program is free software; you can redistribute it and/or modify it 6*8f000cacSChristoph Hellwig * under the terms and conditions of the GNU General Public License, 7*8f000cacSChristoph Hellwig * version 2, as published by the Free Software Foundation. 8*8f000cacSChristoph Hellwig * 9*8f000cacSChristoph Hellwig * This program is distributed in the hope it will be useful, but WITHOUT 10*8f000cacSChristoph Hellwig * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11*8f000cacSChristoph Hellwig * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12*8f000cacSChristoph Hellwig * more details. 13*8f000cacSChristoph Hellwig */ 14*8f000cacSChristoph Hellwig #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 15*8f000cacSChristoph Hellwig #include <linux/atomic.h> 16*8f000cacSChristoph Hellwig #include <linux/ctype.h> 17*8f000cacSChristoph Hellwig #include <linux/delay.h> 18*8f000cacSChristoph Hellwig #include <linux/err.h> 19*8f000cacSChristoph Hellwig #include <linux/init.h> 20*8f000cacSChristoph Hellwig #include <linux/module.h> 21*8f000cacSChristoph Hellwig #include <linux/nvme.h> 22*8f000cacSChristoph Hellwig #include <linux/slab.h> 23*8f000cacSChristoph Hellwig #include <linux/string.h> 24*8f000cacSChristoph Hellwig #include <linux/wait.h> 25*8f000cacSChristoph Hellwig #include <linux/inet.h> 26*8f000cacSChristoph Hellwig #include <asm/unaligned.h> 27*8f000cacSChristoph Hellwig 28*8f000cacSChristoph Hellwig #include <rdma/ib_verbs.h> 29*8f000cacSChristoph Hellwig #include <rdma/rdma_cm.h> 30*8f000cacSChristoph Hellwig #include <rdma/rw.h> 31*8f000cacSChristoph Hellwig 32*8f000cacSChristoph Hellwig #include <linux/nvme-rdma.h> 33*8f000cacSChristoph Hellwig #include "nvmet.h" 34*8f000cacSChristoph Hellwig 35*8f000cacSChristoph Hellwig /* 36*8f000cacSChristoph Hellwig * We allow up to a page of inline data to go with the SQE 37*8f000cacSChristoph Hellwig */ 38*8f000cacSChristoph Hellwig #define NVMET_RDMA_INLINE_DATA_SIZE PAGE_SIZE 39*8f000cacSChristoph Hellwig 40*8f000cacSChristoph Hellwig struct nvmet_rdma_cmd { 41*8f000cacSChristoph Hellwig struct ib_sge sge[2]; 42*8f000cacSChristoph Hellwig struct ib_cqe cqe; 43*8f000cacSChristoph Hellwig struct ib_recv_wr wr; 44*8f000cacSChristoph Hellwig struct scatterlist inline_sg; 45*8f000cacSChristoph Hellwig struct page *inline_page; 46*8f000cacSChristoph Hellwig struct nvme_command *nvme_cmd; 47*8f000cacSChristoph Hellwig struct nvmet_rdma_queue *queue; 48*8f000cacSChristoph Hellwig }; 49*8f000cacSChristoph Hellwig 50*8f000cacSChristoph Hellwig enum { 51*8f000cacSChristoph Hellwig NVMET_RDMA_REQ_INLINE_DATA = (1 << 0), 52*8f000cacSChristoph Hellwig NVMET_RDMA_REQ_INVALIDATE_RKEY = (1 << 1), 53*8f000cacSChristoph Hellwig }; 54*8f000cacSChristoph Hellwig 55*8f000cacSChristoph Hellwig struct nvmet_rdma_rsp { 56*8f000cacSChristoph Hellwig struct ib_sge send_sge; 57*8f000cacSChristoph Hellwig struct ib_cqe send_cqe; 58*8f000cacSChristoph Hellwig struct ib_send_wr send_wr; 59*8f000cacSChristoph Hellwig 60*8f000cacSChristoph Hellwig struct nvmet_rdma_cmd *cmd; 61*8f000cacSChristoph Hellwig struct nvmet_rdma_queue *queue; 62*8f000cacSChristoph Hellwig 63*8f000cacSChristoph Hellwig struct ib_cqe read_cqe; 64*8f000cacSChristoph Hellwig struct rdma_rw_ctx rw; 65*8f000cacSChristoph Hellwig 66*8f000cacSChristoph Hellwig struct nvmet_req req; 67*8f000cacSChristoph Hellwig 68*8f000cacSChristoph Hellwig u8 n_rdma; 69*8f000cacSChristoph Hellwig u32 flags; 70*8f000cacSChristoph Hellwig u32 invalidate_rkey; 71*8f000cacSChristoph Hellwig 72*8f000cacSChristoph Hellwig struct list_head wait_list; 73*8f000cacSChristoph Hellwig struct list_head free_list; 74*8f000cacSChristoph Hellwig }; 75*8f000cacSChristoph Hellwig 76*8f000cacSChristoph Hellwig enum nvmet_rdma_queue_state { 77*8f000cacSChristoph Hellwig NVMET_RDMA_Q_CONNECTING, 78*8f000cacSChristoph Hellwig NVMET_RDMA_Q_LIVE, 79*8f000cacSChristoph Hellwig NVMET_RDMA_Q_DISCONNECTING, 80*8f000cacSChristoph Hellwig }; 81*8f000cacSChristoph Hellwig 82*8f000cacSChristoph Hellwig struct nvmet_rdma_queue { 83*8f000cacSChristoph Hellwig struct rdma_cm_id *cm_id; 84*8f000cacSChristoph Hellwig struct nvmet_port *port; 85*8f000cacSChristoph Hellwig struct ib_cq *cq; 86*8f000cacSChristoph Hellwig atomic_t sq_wr_avail; 87*8f000cacSChristoph Hellwig struct nvmet_rdma_device *dev; 88*8f000cacSChristoph Hellwig spinlock_t state_lock; 89*8f000cacSChristoph Hellwig enum nvmet_rdma_queue_state state; 90*8f000cacSChristoph Hellwig struct nvmet_cq nvme_cq; 91*8f000cacSChristoph Hellwig struct nvmet_sq nvme_sq; 92*8f000cacSChristoph Hellwig 93*8f000cacSChristoph Hellwig struct nvmet_rdma_rsp *rsps; 94*8f000cacSChristoph Hellwig struct list_head free_rsps; 95*8f000cacSChristoph Hellwig spinlock_t rsps_lock; 96*8f000cacSChristoph Hellwig struct nvmet_rdma_cmd *cmds; 97*8f000cacSChristoph Hellwig 98*8f000cacSChristoph Hellwig struct work_struct release_work; 99*8f000cacSChristoph Hellwig struct list_head rsp_wait_list; 100*8f000cacSChristoph Hellwig struct list_head rsp_wr_wait_list; 101*8f000cacSChristoph Hellwig spinlock_t rsp_wr_wait_lock; 102*8f000cacSChristoph Hellwig 103*8f000cacSChristoph Hellwig int idx; 104*8f000cacSChristoph Hellwig int host_qid; 105*8f000cacSChristoph Hellwig int recv_queue_size; 106*8f000cacSChristoph Hellwig int send_queue_size; 107*8f000cacSChristoph Hellwig 108*8f000cacSChristoph Hellwig struct list_head queue_list; 109*8f000cacSChristoph Hellwig }; 110*8f000cacSChristoph Hellwig 111*8f000cacSChristoph Hellwig struct nvmet_rdma_device { 112*8f000cacSChristoph Hellwig struct ib_device *device; 113*8f000cacSChristoph Hellwig struct ib_pd *pd; 114*8f000cacSChristoph Hellwig struct ib_srq *srq; 115*8f000cacSChristoph Hellwig struct nvmet_rdma_cmd *srq_cmds; 116*8f000cacSChristoph Hellwig size_t srq_size; 117*8f000cacSChristoph Hellwig struct kref ref; 118*8f000cacSChristoph Hellwig struct list_head entry; 119*8f000cacSChristoph Hellwig }; 120*8f000cacSChristoph Hellwig 121*8f000cacSChristoph Hellwig static bool nvmet_rdma_use_srq; 122*8f000cacSChristoph Hellwig module_param_named(use_srq, nvmet_rdma_use_srq, bool, 0444); 123*8f000cacSChristoph Hellwig MODULE_PARM_DESC(use_srq, "Use shared receive queue."); 124*8f000cacSChristoph Hellwig 125*8f000cacSChristoph Hellwig static DEFINE_IDA(nvmet_rdma_queue_ida); 126*8f000cacSChristoph Hellwig static LIST_HEAD(nvmet_rdma_queue_list); 127*8f000cacSChristoph Hellwig static DEFINE_MUTEX(nvmet_rdma_queue_mutex); 128*8f000cacSChristoph Hellwig 129*8f000cacSChristoph Hellwig static LIST_HEAD(device_list); 130*8f000cacSChristoph Hellwig static DEFINE_MUTEX(device_list_mutex); 131*8f000cacSChristoph Hellwig 132*8f000cacSChristoph Hellwig static bool nvmet_rdma_execute_command(struct nvmet_rdma_rsp *rsp); 133*8f000cacSChristoph Hellwig static void nvmet_rdma_send_done(struct ib_cq *cq, struct ib_wc *wc); 134*8f000cacSChristoph Hellwig static void nvmet_rdma_recv_done(struct ib_cq *cq, struct ib_wc *wc); 135*8f000cacSChristoph Hellwig static void nvmet_rdma_read_data_done(struct ib_cq *cq, struct ib_wc *wc); 136*8f000cacSChristoph Hellwig static void nvmet_rdma_qp_event(struct ib_event *event, void *priv); 137*8f000cacSChristoph Hellwig static void nvmet_rdma_queue_disconnect(struct nvmet_rdma_queue *queue); 138*8f000cacSChristoph Hellwig 139*8f000cacSChristoph Hellwig static struct nvmet_fabrics_ops nvmet_rdma_ops; 140*8f000cacSChristoph Hellwig 141*8f000cacSChristoph Hellwig /* XXX: really should move to a generic header sooner or later.. */ 142*8f000cacSChristoph Hellwig static inline u32 get_unaligned_le24(const u8 *p) 143*8f000cacSChristoph Hellwig { 144*8f000cacSChristoph Hellwig return (u32)p[0] | (u32)p[1] << 8 | (u32)p[2] << 16; 145*8f000cacSChristoph Hellwig } 146*8f000cacSChristoph Hellwig 147*8f000cacSChristoph Hellwig static inline bool nvmet_rdma_need_data_in(struct nvmet_rdma_rsp *rsp) 148*8f000cacSChristoph Hellwig { 149*8f000cacSChristoph Hellwig return nvme_is_write(rsp->req.cmd) && 150*8f000cacSChristoph Hellwig rsp->req.data_len && 151*8f000cacSChristoph Hellwig !(rsp->flags & NVMET_RDMA_REQ_INLINE_DATA); 152*8f000cacSChristoph Hellwig } 153*8f000cacSChristoph Hellwig 154*8f000cacSChristoph Hellwig static inline bool nvmet_rdma_need_data_out(struct nvmet_rdma_rsp *rsp) 155*8f000cacSChristoph Hellwig { 156*8f000cacSChristoph Hellwig return !nvme_is_write(rsp->req.cmd) && 157*8f000cacSChristoph Hellwig rsp->req.data_len && 158*8f000cacSChristoph Hellwig !rsp->req.rsp->status && 159*8f000cacSChristoph Hellwig !(rsp->flags & NVMET_RDMA_REQ_INLINE_DATA); 160*8f000cacSChristoph Hellwig } 161*8f000cacSChristoph Hellwig 162*8f000cacSChristoph Hellwig static inline struct nvmet_rdma_rsp * 163*8f000cacSChristoph Hellwig nvmet_rdma_get_rsp(struct nvmet_rdma_queue *queue) 164*8f000cacSChristoph Hellwig { 165*8f000cacSChristoph Hellwig struct nvmet_rdma_rsp *rsp; 166*8f000cacSChristoph Hellwig unsigned long flags; 167*8f000cacSChristoph Hellwig 168*8f000cacSChristoph Hellwig spin_lock_irqsave(&queue->rsps_lock, flags); 169*8f000cacSChristoph Hellwig rsp = list_first_entry(&queue->free_rsps, 170*8f000cacSChristoph Hellwig struct nvmet_rdma_rsp, free_list); 171*8f000cacSChristoph Hellwig list_del(&rsp->free_list); 172*8f000cacSChristoph Hellwig spin_unlock_irqrestore(&queue->rsps_lock, flags); 173*8f000cacSChristoph Hellwig 174*8f000cacSChristoph Hellwig return rsp; 175*8f000cacSChristoph Hellwig } 176*8f000cacSChristoph Hellwig 177*8f000cacSChristoph Hellwig static inline void 178*8f000cacSChristoph Hellwig nvmet_rdma_put_rsp(struct nvmet_rdma_rsp *rsp) 179*8f000cacSChristoph Hellwig { 180*8f000cacSChristoph Hellwig unsigned long flags; 181*8f000cacSChristoph Hellwig 182*8f000cacSChristoph Hellwig spin_lock_irqsave(&rsp->queue->rsps_lock, flags); 183*8f000cacSChristoph Hellwig list_add_tail(&rsp->free_list, &rsp->queue->free_rsps); 184*8f000cacSChristoph Hellwig spin_unlock_irqrestore(&rsp->queue->rsps_lock, flags); 185*8f000cacSChristoph Hellwig } 186*8f000cacSChristoph Hellwig 187*8f000cacSChristoph Hellwig static void nvmet_rdma_free_sgl(struct scatterlist *sgl, unsigned int nents) 188*8f000cacSChristoph Hellwig { 189*8f000cacSChristoph Hellwig struct scatterlist *sg; 190*8f000cacSChristoph Hellwig int count; 191*8f000cacSChristoph Hellwig 192*8f000cacSChristoph Hellwig if (!sgl || !nents) 193*8f000cacSChristoph Hellwig return; 194*8f000cacSChristoph Hellwig 195*8f000cacSChristoph Hellwig for_each_sg(sgl, sg, nents, count) 196*8f000cacSChristoph Hellwig __free_page(sg_page(sg)); 197*8f000cacSChristoph Hellwig kfree(sgl); 198*8f000cacSChristoph Hellwig } 199*8f000cacSChristoph Hellwig 200*8f000cacSChristoph Hellwig static int nvmet_rdma_alloc_sgl(struct scatterlist **sgl, unsigned int *nents, 201*8f000cacSChristoph Hellwig u32 length) 202*8f000cacSChristoph Hellwig { 203*8f000cacSChristoph Hellwig struct scatterlist *sg; 204*8f000cacSChristoph Hellwig struct page *page; 205*8f000cacSChristoph Hellwig unsigned int nent; 206*8f000cacSChristoph Hellwig int i = 0; 207*8f000cacSChristoph Hellwig 208*8f000cacSChristoph Hellwig nent = DIV_ROUND_UP(length, PAGE_SIZE); 209*8f000cacSChristoph Hellwig sg = kmalloc_array(nent, sizeof(struct scatterlist), GFP_KERNEL); 210*8f000cacSChristoph Hellwig if (!sg) 211*8f000cacSChristoph Hellwig goto out; 212*8f000cacSChristoph Hellwig 213*8f000cacSChristoph Hellwig sg_init_table(sg, nent); 214*8f000cacSChristoph Hellwig 215*8f000cacSChristoph Hellwig while (length) { 216*8f000cacSChristoph Hellwig u32 page_len = min_t(u32, length, PAGE_SIZE); 217*8f000cacSChristoph Hellwig 218*8f000cacSChristoph Hellwig page = alloc_page(GFP_KERNEL); 219*8f000cacSChristoph Hellwig if (!page) 220*8f000cacSChristoph Hellwig goto out_free_pages; 221*8f000cacSChristoph Hellwig 222*8f000cacSChristoph Hellwig sg_set_page(&sg[i], page, page_len, 0); 223*8f000cacSChristoph Hellwig length -= page_len; 224*8f000cacSChristoph Hellwig i++; 225*8f000cacSChristoph Hellwig } 226*8f000cacSChristoph Hellwig *sgl = sg; 227*8f000cacSChristoph Hellwig *nents = nent; 228*8f000cacSChristoph Hellwig return 0; 229*8f000cacSChristoph Hellwig 230*8f000cacSChristoph Hellwig out_free_pages: 231*8f000cacSChristoph Hellwig while (i > 0) { 232*8f000cacSChristoph Hellwig i--; 233*8f000cacSChristoph Hellwig __free_page(sg_page(&sg[i])); 234*8f000cacSChristoph Hellwig } 235*8f000cacSChristoph Hellwig kfree(sg); 236*8f000cacSChristoph Hellwig out: 237*8f000cacSChristoph Hellwig return NVME_SC_INTERNAL; 238*8f000cacSChristoph Hellwig } 239*8f000cacSChristoph Hellwig 240*8f000cacSChristoph Hellwig static int nvmet_rdma_alloc_cmd(struct nvmet_rdma_device *ndev, 241*8f000cacSChristoph Hellwig struct nvmet_rdma_cmd *c, bool admin) 242*8f000cacSChristoph Hellwig { 243*8f000cacSChristoph Hellwig /* NVMe command / RDMA RECV */ 244*8f000cacSChristoph Hellwig c->nvme_cmd = kmalloc(sizeof(*c->nvme_cmd), GFP_KERNEL); 245*8f000cacSChristoph Hellwig if (!c->nvme_cmd) 246*8f000cacSChristoph Hellwig goto out; 247*8f000cacSChristoph Hellwig 248*8f000cacSChristoph Hellwig c->sge[0].addr = ib_dma_map_single(ndev->device, c->nvme_cmd, 249*8f000cacSChristoph Hellwig sizeof(*c->nvme_cmd), DMA_FROM_DEVICE); 250*8f000cacSChristoph Hellwig if (ib_dma_mapping_error(ndev->device, c->sge[0].addr)) 251*8f000cacSChristoph Hellwig goto out_free_cmd; 252*8f000cacSChristoph Hellwig 253*8f000cacSChristoph Hellwig c->sge[0].length = sizeof(*c->nvme_cmd); 254*8f000cacSChristoph Hellwig c->sge[0].lkey = ndev->pd->local_dma_lkey; 255*8f000cacSChristoph Hellwig 256*8f000cacSChristoph Hellwig if (!admin) { 257*8f000cacSChristoph Hellwig c->inline_page = alloc_pages(GFP_KERNEL, 258*8f000cacSChristoph Hellwig get_order(NVMET_RDMA_INLINE_DATA_SIZE)); 259*8f000cacSChristoph Hellwig if (!c->inline_page) 260*8f000cacSChristoph Hellwig goto out_unmap_cmd; 261*8f000cacSChristoph Hellwig c->sge[1].addr = ib_dma_map_page(ndev->device, 262*8f000cacSChristoph Hellwig c->inline_page, 0, NVMET_RDMA_INLINE_DATA_SIZE, 263*8f000cacSChristoph Hellwig DMA_FROM_DEVICE); 264*8f000cacSChristoph Hellwig if (ib_dma_mapping_error(ndev->device, c->sge[1].addr)) 265*8f000cacSChristoph Hellwig goto out_free_inline_page; 266*8f000cacSChristoph Hellwig c->sge[1].length = NVMET_RDMA_INLINE_DATA_SIZE; 267*8f000cacSChristoph Hellwig c->sge[1].lkey = ndev->pd->local_dma_lkey; 268*8f000cacSChristoph Hellwig } 269*8f000cacSChristoph Hellwig 270*8f000cacSChristoph Hellwig c->cqe.done = nvmet_rdma_recv_done; 271*8f000cacSChristoph Hellwig 272*8f000cacSChristoph Hellwig c->wr.wr_cqe = &c->cqe; 273*8f000cacSChristoph Hellwig c->wr.sg_list = c->sge; 274*8f000cacSChristoph Hellwig c->wr.num_sge = admin ? 1 : 2; 275*8f000cacSChristoph Hellwig 276*8f000cacSChristoph Hellwig return 0; 277*8f000cacSChristoph Hellwig 278*8f000cacSChristoph Hellwig out_free_inline_page: 279*8f000cacSChristoph Hellwig if (!admin) { 280*8f000cacSChristoph Hellwig __free_pages(c->inline_page, 281*8f000cacSChristoph Hellwig get_order(NVMET_RDMA_INLINE_DATA_SIZE)); 282*8f000cacSChristoph Hellwig } 283*8f000cacSChristoph Hellwig out_unmap_cmd: 284*8f000cacSChristoph Hellwig ib_dma_unmap_single(ndev->device, c->sge[0].addr, 285*8f000cacSChristoph Hellwig sizeof(*c->nvme_cmd), DMA_FROM_DEVICE); 286*8f000cacSChristoph Hellwig out_free_cmd: 287*8f000cacSChristoph Hellwig kfree(c->nvme_cmd); 288*8f000cacSChristoph Hellwig 289*8f000cacSChristoph Hellwig out: 290*8f000cacSChristoph Hellwig return -ENOMEM; 291*8f000cacSChristoph Hellwig } 292*8f000cacSChristoph Hellwig 293*8f000cacSChristoph Hellwig static void nvmet_rdma_free_cmd(struct nvmet_rdma_device *ndev, 294*8f000cacSChristoph Hellwig struct nvmet_rdma_cmd *c, bool admin) 295*8f000cacSChristoph Hellwig { 296*8f000cacSChristoph Hellwig if (!admin) { 297*8f000cacSChristoph Hellwig ib_dma_unmap_page(ndev->device, c->sge[1].addr, 298*8f000cacSChristoph Hellwig NVMET_RDMA_INLINE_DATA_SIZE, DMA_FROM_DEVICE); 299*8f000cacSChristoph Hellwig __free_pages(c->inline_page, 300*8f000cacSChristoph Hellwig get_order(NVMET_RDMA_INLINE_DATA_SIZE)); 301*8f000cacSChristoph Hellwig } 302*8f000cacSChristoph Hellwig ib_dma_unmap_single(ndev->device, c->sge[0].addr, 303*8f000cacSChristoph Hellwig sizeof(*c->nvme_cmd), DMA_FROM_DEVICE); 304*8f000cacSChristoph Hellwig kfree(c->nvme_cmd); 305*8f000cacSChristoph Hellwig } 306*8f000cacSChristoph Hellwig 307*8f000cacSChristoph Hellwig static struct nvmet_rdma_cmd * 308*8f000cacSChristoph Hellwig nvmet_rdma_alloc_cmds(struct nvmet_rdma_device *ndev, 309*8f000cacSChristoph Hellwig int nr_cmds, bool admin) 310*8f000cacSChristoph Hellwig { 311*8f000cacSChristoph Hellwig struct nvmet_rdma_cmd *cmds; 312*8f000cacSChristoph Hellwig int ret = -EINVAL, i; 313*8f000cacSChristoph Hellwig 314*8f000cacSChristoph Hellwig cmds = kcalloc(nr_cmds, sizeof(struct nvmet_rdma_cmd), GFP_KERNEL); 315*8f000cacSChristoph Hellwig if (!cmds) 316*8f000cacSChristoph Hellwig goto out; 317*8f000cacSChristoph Hellwig 318*8f000cacSChristoph Hellwig for (i = 0; i < nr_cmds; i++) { 319*8f000cacSChristoph Hellwig ret = nvmet_rdma_alloc_cmd(ndev, cmds + i, admin); 320*8f000cacSChristoph Hellwig if (ret) 321*8f000cacSChristoph Hellwig goto out_free; 322*8f000cacSChristoph Hellwig } 323*8f000cacSChristoph Hellwig 324*8f000cacSChristoph Hellwig return cmds; 325*8f000cacSChristoph Hellwig 326*8f000cacSChristoph Hellwig out_free: 327*8f000cacSChristoph Hellwig while (--i >= 0) 328*8f000cacSChristoph Hellwig nvmet_rdma_free_cmd(ndev, cmds + i, admin); 329*8f000cacSChristoph Hellwig kfree(cmds); 330*8f000cacSChristoph Hellwig out: 331*8f000cacSChristoph Hellwig return ERR_PTR(ret); 332*8f000cacSChristoph Hellwig } 333*8f000cacSChristoph Hellwig 334*8f000cacSChristoph Hellwig static void nvmet_rdma_free_cmds(struct nvmet_rdma_device *ndev, 335*8f000cacSChristoph Hellwig struct nvmet_rdma_cmd *cmds, int nr_cmds, bool admin) 336*8f000cacSChristoph Hellwig { 337*8f000cacSChristoph Hellwig int i; 338*8f000cacSChristoph Hellwig 339*8f000cacSChristoph Hellwig for (i = 0; i < nr_cmds; i++) 340*8f000cacSChristoph Hellwig nvmet_rdma_free_cmd(ndev, cmds + i, admin); 341*8f000cacSChristoph Hellwig kfree(cmds); 342*8f000cacSChristoph Hellwig } 343*8f000cacSChristoph Hellwig 344*8f000cacSChristoph Hellwig static int nvmet_rdma_alloc_rsp(struct nvmet_rdma_device *ndev, 345*8f000cacSChristoph Hellwig struct nvmet_rdma_rsp *r) 346*8f000cacSChristoph Hellwig { 347*8f000cacSChristoph Hellwig /* NVMe CQE / RDMA SEND */ 348*8f000cacSChristoph Hellwig r->req.rsp = kmalloc(sizeof(*r->req.rsp), GFP_KERNEL); 349*8f000cacSChristoph Hellwig if (!r->req.rsp) 350*8f000cacSChristoph Hellwig goto out; 351*8f000cacSChristoph Hellwig 352*8f000cacSChristoph Hellwig r->send_sge.addr = ib_dma_map_single(ndev->device, r->req.rsp, 353*8f000cacSChristoph Hellwig sizeof(*r->req.rsp), DMA_TO_DEVICE); 354*8f000cacSChristoph Hellwig if (ib_dma_mapping_error(ndev->device, r->send_sge.addr)) 355*8f000cacSChristoph Hellwig goto out_free_rsp; 356*8f000cacSChristoph Hellwig 357*8f000cacSChristoph Hellwig r->send_sge.length = sizeof(*r->req.rsp); 358*8f000cacSChristoph Hellwig r->send_sge.lkey = ndev->pd->local_dma_lkey; 359*8f000cacSChristoph Hellwig 360*8f000cacSChristoph Hellwig r->send_cqe.done = nvmet_rdma_send_done; 361*8f000cacSChristoph Hellwig 362*8f000cacSChristoph Hellwig r->send_wr.wr_cqe = &r->send_cqe; 363*8f000cacSChristoph Hellwig r->send_wr.sg_list = &r->send_sge; 364*8f000cacSChristoph Hellwig r->send_wr.num_sge = 1; 365*8f000cacSChristoph Hellwig r->send_wr.send_flags = IB_SEND_SIGNALED; 366*8f000cacSChristoph Hellwig 367*8f000cacSChristoph Hellwig /* Data In / RDMA READ */ 368*8f000cacSChristoph Hellwig r->read_cqe.done = nvmet_rdma_read_data_done; 369*8f000cacSChristoph Hellwig return 0; 370*8f000cacSChristoph Hellwig 371*8f000cacSChristoph Hellwig out_free_rsp: 372*8f000cacSChristoph Hellwig kfree(r->req.rsp); 373*8f000cacSChristoph Hellwig out: 374*8f000cacSChristoph Hellwig return -ENOMEM; 375*8f000cacSChristoph Hellwig } 376*8f000cacSChristoph Hellwig 377*8f000cacSChristoph Hellwig static void nvmet_rdma_free_rsp(struct nvmet_rdma_device *ndev, 378*8f000cacSChristoph Hellwig struct nvmet_rdma_rsp *r) 379*8f000cacSChristoph Hellwig { 380*8f000cacSChristoph Hellwig ib_dma_unmap_single(ndev->device, r->send_sge.addr, 381*8f000cacSChristoph Hellwig sizeof(*r->req.rsp), DMA_TO_DEVICE); 382*8f000cacSChristoph Hellwig kfree(r->req.rsp); 383*8f000cacSChristoph Hellwig } 384*8f000cacSChristoph Hellwig 385*8f000cacSChristoph Hellwig static int 386*8f000cacSChristoph Hellwig nvmet_rdma_alloc_rsps(struct nvmet_rdma_queue *queue) 387*8f000cacSChristoph Hellwig { 388*8f000cacSChristoph Hellwig struct nvmet_rdma_device *ndev = queue->dev; 389*8f000cacSChristoph Hellwig int nr_rsps = queue->recv_queue_size * 2; 390*8f000cacSChristoph Hellwig int ret = -EINVAL, i; 391*8f000cacSChristoph Hellwig 392*8f000cacSChristoph Hellwig queue->rsps = kcalloc(nr_rsps, sizeof(struct nvmet_rdma_rsp), 393*8f000cacSChristoph Hellwig GFP_KERNEL); 394*8f000cacSChristoph Hellwig if (!queue->rsps) 395*8f000cacSChristoph Hellwig goto out; 396*8f000cacSChristoph Hellwig 397*8f000cacSChristoph Hellwig for (i = 0; i < nr_rsps; i++) { 398*8f000cacSChristoph Hellwig struct nvmet_rdma_rsp *rsp = &queue->rsps[i]; 399*8f000cacSChristoph Hellwig 400*8f000cacSChristoph Hellwig ret = nvmet_rdma_alloc_rsp(ndev, rsp); 401*8f000cacSChristoph Hellwig if (ret) 402*8f000cacSChristoph Hellwig goto out_free; 403*8f000cacSChristoph Hellwig 404*8f000cacSChristoph Hellwig list_add_tail(&rsp->free_list, &queue->free_rsps); 405*8f000cacSChristoph Hellwig } 406*8f000cacSChristoph Hellwig 407*8f000cacSChristoph Hellwig return 0; 408*8f000cacSChristoph Hellwig 409*8f000cacSChristoph Hellwig out_free: 410*8f000cacSChristoph Hellwig while (--i >= 0) { 411*8f000cacSChristoph Hellwig struct nvmet_rdma_rsp *rsp = &queue->rsps[i]; 412*8f000cacSChristoph Hellwig 413*8f000cacSChristoph Hellwig list_del(&rsp->free_list); 414*8f000cacSChristoph Hellwig nvmet_rdma_free_rsp(ndev, rsp); 415*8f000cacSChristoph Hellwig } 416*8f000cacSChristoph Hellwig kfree(queue->rsps); 417*8f000cacSChristoph Hellwig out: 418*8f000cacSChristoph Hellwig return ret; 419*8f000cacSChristoph Hellwig } 420*8f000cacSChristoph Hellwig 421*8f000cacSChristoph Hellwig static void nvmet_rdma_free_rsps(struct nvmet_rdma_queue *queue) 422*8f000cacSChristoph Hellwig { 423*8f000cacSChristoph Hellwig struct nvmet_rdma_device *ndev = queue->dev; 424*8f000cacSChristoph Hellwig int i, nr_rsps = queue->recv_queue_size * 2; 425*8f000cacSChristoph Hellwig 426*8f000cacSChristoph Hellwig for (i = 0; i < nr_rsps; i++) { 427*8f000cacSChristoph Hellwig struct nvmet_rdma_rsp *rsp = &queue->rsps[i]; 428*8f000cacSChristoph Hellwig 429*8f000cacSChristoph Hellwig list_del(&rsp->free_list); 430*8f000cacSChristoph Hellwig nvmet_rdma_free_rsp(ndev, rsp); 431*8f000cacSChristoph Hellwig } 432*8f000cacSChristoph Hellwig kfree(queue->rsps); 433*8f000cacSChristoph Hellwig } 434*8f000cacSChristoph Hellwig 435*8f000cacSChristoph Hellwig static int nvmet_rdma_post_recv(struct nvmet_rdma_device *ndev, 436*8f000cacSChristoph Hellwig struct nvmet_rdma_cmd *cmd) 437*8f000cacSChristoph Hellwig { 438*8f000cacSChristoph Hellwig struct ib_recv_wr *bad_wr; 439*8f000cacSChristoph Hellwig 440*8f000cacSChristoph Hellwig if (ndev->srq) 441*8f000cacSChristoph Hellwig return ib_post_srq_recv(ndev->srq, &cmd->wr, &bad_wr); 442*8f000cacSChristoph Hellwig return ib_post_recv(cmd->queue->cm_id->qp, &cmd->wr, &bad_wr); 443*8f000cacSChristoph Hellwig } 444*8f000cacSChristoph Hellwig 445*8f000cacSChristoph Hellwig static void nvmet_rdma_process_wr_wait_list(struct nvmet_rdma_queue *queue) 446*8f000cacSChristoph Hellwig { 447*8f000cacSChristoph Hellwig spin_lock(&queue->rsp_wr_wait_lock); 448*8f000cacSChristoph Hellwig while (!list_empty(&queue->rsp_wr_wait_list)) { 449*8f000cacSChristoph Hellwig struct nvmet_rdma_rsp *rsp; 450*8f000cacSChristoph Hellwig bool ret; 451*8f000cacSChristoph Hellwig 452*8f000cacSChristoph Hellwig rsp = list_entry(queue->rsp_wr_wait_list.next, 453*8f000cacSChristoph Hellwig struct nvmet_rdma_rsp, wait_list); 454*8f000cacSChristoph Hellwig list_del(&rsp->wait_list); 455*8f000cacSChristoph Hellwig 456*8f000cacSChristoph Hellwig spin_unlock(&queue->rsp_wr_wait_lock); 457*8f000cacSChristoph Hellwig ret = nvmet_rdma_execute_command(rsp); 458*8f000cacSChristoph Hellwig spin_lock(&queue->rsp_wr_wait_lock); 459*8f000cacSChristoph Hellwig 460*8f000cacSChristoph Hellwig if (!ret) { 461*8f000cacSChristoph Hellwig list_add(&rsp->wait_list, &queue->rsp_wr_wait_list); 462*8f000cacSChristoph Hellwig break; 463*8f000cacSChristoph Hellwig } 464*8f000cacSChristoph Hellwig } 465*8f000cacSChristoph Hellwig spin_unlock(&queue->rsp_wr_wait_lock); 466*8f000cacSChristoph Hellwig } 467*8f000cacSChristoph Hellwig 468*8f000cacSChristoph Hellwig 469*8f000cacSChristoph Hellwig static void nvmet_rdma_release_rsp(struct nvmet_rdma_rsp *rsp) 470*8f000cacSChristoph Hellwig { 471*8f000cacSChristoph Hellwig struct nvmet_rdma_queue *queue = rsp->queue; 472*8f000cacSChristoph Hellwig 473*8f000cacSChristoph Hellwig atomic_add(1 + rsp->n_rdma, &queue->sq_wr_avail); 474*8f000cacSChristoph Hellwig 475*8f000cacSChristoph Hellwig if (rsp->n_rdma) { 476*8f000cacSChristoph Hellwig rdma_rw_ctx_destroy(&rsp->rw, queue->cm_id->qp, 477*8f000cacSChristoph Hellwig queue->cm_id->port_num, rsp->req.sg, 478*8f000cacSChristoph Hellwig rsp->req.sg_cnt, nvmet_data_dir(&rsp->req)); 479*8f000cacSChristoph Hellwig } 480*8f000cacSChristoph Hellwig 481*8f000cacSChristoph Hellwig if (rsp->req.sg != &rsp->cmd->inline_sg) 482*8f000cacSChristoph Hellwig nvmet_rdma_free_sgl(rsp->req.sg, rsp->req.sg_cnt); 483*8f000cacSChristoph Hellwig 484*8f000cacSChristoph Hellwig if (unlikely(!list_empty_careful(&queue->rsp_wr_wait_list))) 485*8f000cacSChristoph Hellwig nvmet_rdma_process_wr_wait_list(queue); 486*8f000cacSChristoph Hellwig 487*8f000cacSChristoph Hellwig nvmet_rdma_put_rsp(rsp); 488*8f000cacSChristoph Hellwig } 489*8f000cacSChristoph Hellwig 490*8f000cacSChristoph Hellwig static void nvmet_rdma_error_comp(struct nvmet_rdma_queue *queue) 491*8f000cacSChristoph Hellwig { 492*8f000cacSChristoph Hellwig if (queue->nvme_sq.ctrl) { 493*8f000cacSChristoph Hellwig nvmet_ctrl_fatal_error(queue->nvme_sq.ctrl); 494*8f000cacSChristoph Hellwig } else { 495*8f000cacSChristoph Hellwig /* 496*8f000cacSChristoph Hellwig * we didn't setup the controller yet in case 497*8f000cacSChristoph Hellwig * of admin connect error, just disconnect and 498*8f000cacSChristoph Hellwig * cleanup the queue 499*8f000cacSChristoph Hellwig */ 500*8f000cacSChristoph Hellwig nvmet_rdma_queue_disconnect(queue); 501*8f000cacSChristoph Hellwig } 502*8f000cacSChristoph Hellwig } 503*8f000cacSChristoph Hellwig 504*8f000cacSChristoph Hellwig static void nvmet_rdma_send_done(struct ib_cq *cq, struct ib_wc *wc) 505*8f000cacSChristoph Hellwig { 506*8f000cacSChristoph Hellwig struct nvmet_rdma_rsp *rsp = 507*8f000cacSChristoph Hellwig container_of(wc->wr_cqe, struct nvmet_rdma_rsp, send_cqe); 508*8f000cacSChristoph Hellwig 509*8f000cacSChristoph Hellwig nvmet_rdma_release_rsp(rsp); 510*8f000cacSChristoph Hellwig 511*8f000cacSChristoph Hellwig if (unlikely(wc->status != IB_WC_SUCCESS && 512*8f000cacSChristoph Hellwig wc->status != IB_WC_WR_FLUSH_ERR)) { 513*8f000cacSChristoph Hellwig pr_err("SEND for CQE 0x%p failed with status %s (%d).\n", 514*8f000cacSChristoph Hellwig wc->wr_cqe, ib_wc_status_msg(wc->status), wc->status); 515*8f000cacSChristoph Hellwig nvmet_rdma_error_comp(rsp->queue); 516*8f000cacSChristoph Hellwig } 517*8f000cacSChristoph Hellwig } 518*8f000cacSChristoph Hellwig 519*8f000cacSChristoph Hellwig static void nvmet_rdma_queue_response(struct nvmet_req *req) 520*8f000cacSChristoph Hellwig { 521*8f000cacSChristoph Hellwig struct nvmet_rdma_rsp *rsp = 522*8f000cacSChristoph Hellwig container_of(req, struct nvmet_rdma_rsp, req); 523*8f000cacSChristoph Hellwig struct rdma_cm_id *cm_id = rsp->queue->cm_id; 524*8f000cacSChristoph Hellwig struct ib_send_wr *first_wr, *bad_wr; 525*8f000cacSChristoph Hellwig 526*8f000cacSChristoph Hellwig if (rsp->flags & NVMET_RDMA_REQ_INVALIDATE_RKEY) { 527*8f000cacSChristoph Hellwig rsp->send_wr.opcode = IB_WR_SEND_WITH_INV; 528*8f000cacSChristoph Hellwig rsp->send_wr.ex.invalidate_rkey = rsp->invalidate_rkey; 529*8f000cacSChristoph Hellwig } else { 530*8f000cacSChristoph Hellwig rsp->send_wr.opcode = IB_WR_SEND; 531*8f000cacSChristoph Hellwig } 532*8f000cacSChristoph Hellwig 533*8f000cacSChristoph Hellwig if (nvmet_rdma_need_data_out(rsp)) 534*8f000cacSChristoph Hellwig first_wr = rdma_rw_ctx_wrs(&rsp->rw, cm_id->qp, 535*8f000cacSChristoph Hellwig cm_id->port_num, NULL, &rsp->send_wr); 536*8f000cacSChristoph Hellwig else 537*8f000cacSChristoph Hellwig first_wr = &rsp->send_wr; 538*8f000cacSChristoph Hellwig 539*8f000cacSChristoph Hellwig nvmet_rdma_post_recv(rsp->queue->dev, rsp->cmd); 540*8f000cacSChristoph Hellwig if (ib_post_send(cm_id->qp, first_wr, &bad_wr)) { 541*8f000cacSChristoph Hellwig pr_err("sending cmd response failed\n"); 542*8f000cacSChristoph Hellwig nvmet_rdma_release_rsp(rsp); 543*8f000cacSChristoph Hellwig } 544*8f000cacSChristoph Hellwig } 545*8f000cacSChristoph Hellwig 546*8f000cacSChristoph Hellwig static void nvmet_rdma_read_data_done(struct ib_cq *cq, struct ib_wc *wc) 547*8f000cacSChristoph Hellwig { 548*8f000cacSChristoph Hellwig struct nvmet_rdma_rsp *rsp = 549*8f000cacSChristoph Hellwig container_of(wc->wr_cqe, struct nvmet_rdma_rsp, read_cqe); 550*8f000cacSChristoph Hellwig struct nvmet_rdma_queue *queue = cq->cq_context; 551*8f000cacSChristoph Hellwig 552*8f000cacSChristoph Hellwig WARN_ON(rsp->n_rdma <= 0); 553*8f000cacSChristoph Hellwig atomic_add(rsp->n_rdma, &queue->sq_wr_avail); 554*8f000cacSChristoph Hellwig rdma_rw_ctx_destroy(&rsp->rw, queue->cm_id->qp, 555*8f000cacSChristoph Hellwig queue->cm_id->port_num, rsp->req.sg, 556*8f000cacSChristoph Hellwig rsp->req.sg_cnt, nvmet_data_dir(&rsp->req)); 557*8f000cacSChristoph Hellwig rsp->n_rdma = 0; 558*8f000cacSChristoph Hellwig 559*8f000cacSChristoph Hellwig if (unlikely(wc->status != IB_WC_SUCCESS)) { 560*8f000cacSChristoph Hellwig nvmet_rdma_release_rsp(rsp); 561*8f000cacSChristoph Hellwig if (wc->status != IB_WC_WR_FLUSH_ERR) { 562*8f000cacSChristoph Hellwig pr_info("RDMA READ for CQE 0x%p failed with status %s (%d).\n", 563*8f000cacSChristoph Hellwig wc->wr_cqe, ib_wc_status_msg(wc->status), wc->status); 564*8f000cacSChristoph Hellwig nvmet_rdma_error_comp(queue); 565*8f000cacSChristoph Hellwig } 566*8f000cacSChristoph Hellwig return; 567*8f000cacSChristoph Hellwig } 568*8f000cacSChristoph Hellwig 569*8f000cacSChristoph Hellwig rsp->req.execute(&rsp->req); 570*8f000cacSChristoph Hellwig } 571*8f000cacSChristoph Hellwig 572*8f000cacSChristoph Hellwig static void nvmet_rdma_use_inline_sg(struct nvmet_rdma_rsp *rsp, u32 len, 573*8f000cacSChristoph Hellwig u64 off) 574*8f000cacSChristoph Hellwig { 575*8f000cacSChristoph Hellwig sg_init_table(&rsp->cmd->inline_sg, 1); 576*8f000cacSChristoph Hellwig sg_set_page(&rsp->cmd->inline_sg, rsp->cmd->inline_page, len, off); 577*8f000cacSChristoph Hellwig rsp->req.sg = &rsp->cmd->inline_sg; 578*8f000cacSChristoph Hellwig rsp->req.sg_cnt = 1; 579*8f000cacSChristoph Hellwig } 580*8f000cacSChristoph Hellwig 581*8f000cacSChristoph Hellwig static u16 nvmet_rdma_map_sgl_inline(struct nvmet_rdma_rsp *rsp) 582*8f000cacSChristoph Hellwig { 583*8f000cacSChristoph Hellwig struct nvme_sgl_desc *sgl = &rsp->req.cmd->common.dptr.sgl; 584*8f000cacSChristoph Hellwig u64 off = le64_to_cpu(sgl->addr); 585*8f000cacSChristoph Hellwig u32 len = le32_to_cpu(sgl->length); 586*8f000cacSChristoph Hellwig 587*8f000cacSChristoph Hellwig if (!nvme_is_write(rsp->req.cmd)) 588*8f000cacSChristoph Hellwig return NVME_SC_INVALID_FIELD | NVME_SC_DNR; 589*8f000cacSChristoph Hellwig 590*8f000cacSChristoph Hellwig if (off + len > NVMET_RDMA_INLINE_DATA_SIZE) { 591*8f000cacSChristoph Hellwig pr_err("invalid inline data offset!\n"); 592*8f000cacSChristoph Hellwig return NVME_SC_SGL_INVALID_OFFSET | NVME_SC_DNR; 593*8f000cacSChristoph Hellwig } 594*8f000cacSChristoph Hellwig 595*8f000cacSChristoph Hellwig /* no data command? */ 596*8f000cacSChristoph Hellwig if (!len) 597*8f000cacSChristoph Hellwig return 0; 598*8f000cacSChristoph Hellwig 599*8f000cacSChristoph Hellwig nvmet_rdma_use_inline_sg(rsp, len, off); 600*8f000cacSChristoph Hellwig rsp->flags |= NVMET_RDMA_REQ_INLINE_DATA; 601*8f000cacSChristoph Hellwig return 0; 602*8f000cacSChristoph Hellwig } 603*8f000cacSChristoph Hellwig 604*8f000cacSChristoph Hellwig static u16 nvmet_rdma_map_sgl_keyed(struct nvmet_rdma_rsp *rsp, 605*8f000cacSChristoph Hellwig struct nvme_keyed_sgl_desc *sgl, bool invalidate) 606*8f000cacSChristoph Hellwig { 607*8f000cacSChristoph Hellwig struct rdma_cm_id *cm_id = rsp->queue->cm_id; 608*8f000cacSChristoph Hellwig u64 addr = le64_to_cpu(sgl->addr); 609*8f000cacSChristoph Hellwig u32 len = get_unaligned_le24(sgl->length); 610*8f000cacSChristoph Hellwig u32 key = get_unaligned_le32(sgl->key); 611*8f000cacSChristoph Hellwig int ret; 612*8f000cacSChristoph Hellwig u16 status; 613*8f000cacSChristoph Hellwig 614*8f000cacSChristoph Hellwig /* no data command? */ 615*8f000cacSChristoph Hellwig if (!len) 616*8f000cacSChristoph Hellwig return 0; 617*8f000cacSChristoph Hellwig 618*8f000cacSChristoph Hellwig /* use the already allocated data buffer if possible */ 619*8f000cacSChristoph Hellwig if (len <= NVMET_RDMA_INLINE_DATA_SIZE && rsp->queue->host_qid) { 620*8f000cacSChristoph Hellwig nvmet_rdma_use_inline_sg(rsp, len, 0); 621*8f000cacSChristoph Hellwig } else { 622*8f000cacSChristoph Hellwig status = nvmet_rdma_alloc_sgl(&rsp->req.sg, &rsp->req.sg_cnt, 623*8f000cacSChristoph Hellwig len); 624*8f000cacSChristoph Hellwig if (status) 625*8f000cacSChristoph Hellwig return status; 626*8f000cacSChristoph Hellwig } 627*8f000cacSChristoph Hellwig 628*8f000cacSChristoph Hellwig ret = rdma_rw_ctx_init(&rsp->rw, cm_id->qp, cm_id->port_num, 629*8f000cacSChristoph Hellwig rsp->req.sg, rsp->req.sg_cnt, 0, addr, key, 630*8f000cacSChristoph Hellwig nvmet_data_dir(&rsp->req)); 631*8f000cacSChristoph Hellwig if (ret < 0) 632*8f000cacSChristoph Hellwig return NVME_SC_INTERNAL; 633*8f000cacSChristoph Hellwig rsp->n_rdma += ret; 634*8f000cacSChristoph Hellwig 635*8f000cacSChristoph Hellwig if (invalidate) { 636*8f000cacSChristoph Hellwig rsp->invalidate_rkey = key; 637*8f000cacSChristoph Hellwig rsp->flags |= NVMET_RDMA_REQ_INVALIDATE_RKEY; 638*8f000cacSChristoph Hellwig } 639*8f000cacSChristoph Hellwig 640*8f000cacSChristoph Hellwig return 0; 641*8f000cacSChristoph Hellwig } 642*8f000cacSChristoph Hellwig 643*8f000cacSChristoph Hellwig static u16 nvmet_rdma_map_sgl(struct nvmet_rdma_rsp *rsp) 644*8f000cacSChristoph Hellwig { 645*8f000cacSChristoph Hellwig struct nvme_keyed_sgl_desc *sgl = &rsp->req.cmd->common.dptr.ksgl; 646*8f000cacSChristoph Hellwig 647*8f000cacSChristoph Hellwig switch (sgl->type >> 4) { 648*8f000cacSChristoph Hellwig case NVME_SGL_FMT_DATA_DESC: 649*8f000cacSChristoph Hellwig switch (sgl->type & 0xf) { 650*8f000cacSChristoph Hellwig case NVME_SGL_FMT_OFFSET: 651*8f000cacSChristoph Hellwig return nvmet_rdma_map_sgl_inline(rsp); 652*8f000cacSChristoph Hellwig default: 653*8f000cacSChristoph Hellwig pr_err("invalid SGL subtype: %#x\n", sgl->type); 654*8f000cacSChristoph Hellwig return NVME_SC_INVALID_FIELD | NVME_SC_DNR; 655*8f000cacSChristoph Hellwig } 656*8f000cacSChristoph Hellwig case NVME_KEY_SGL_FMT_DATA_DESC: 657*8f000cacSChristoph Hellwig switch (sgl->type & 0xf) { 658*8f000cacSChristoph Hellwig case NVME_SGL_FMT_ADDRESS | NVME_SGL_FMT_INVALIDATE: 659*8f000cacSChristoph Hellwig return nvmet_rdma_map_sgl_keyed(rsp, sgl, true); 660*8f000cacSChristoph Hellwig case NVME_SGL_FMT_ADDRESS: 661*8f000cacSChristoph Hellwig return nvmet_rdma_map_sgl_keyed(rsp, sgl, false); 662*8f000cacSChristoph Hellwig default: 663*8f000cacSChristoph Hellwig pr_err("invalid SGL subtype: %#x\n", sgl->type); 664*8f000cacSChristoph Hellwig return NVME_SC_INVALID_FIELD | NVME_SC_DNR; 665*8f000cacSChristoph Hellwig } 666*8f000cacSChristoph Hellwig default: 667*8f000cacSChristoph Hellwig pr_err("invalid SGL type: %#x\n", sgl->type); 668*8f000cacSChristoph Hellwig return NVME_SC_SGL_INVALID_TYPE | NVME_SC_DNR; 669*8f000cacSChristoph Hellwig } 670*8f000cacSChristoph Hellwig } 671*8f000cacSChristoph Hellwig 672*8f000cacSChristoph Hellwig static bool nvmet_rdma_execute_command(struct nvmet_rdma_rsp *rsp) 673*8f000cacSChristoph Hellwig { 674*8f000cacSChristoph Hellwig struct nvmet_rdma_queue *queue = rsp->queue; 675*8f000cacSChristoph Hellwig 676*8f000cacSChristoph Hellwig if (unlikely(atomic_sub_return(1 + rsp->n_rdma, 677*8f000cacSChristoph Hellwig &queue->sq_wr_avail) < 0)) { 678*8f000cacSChristoph Hellwig pr_debug("IB send queue full (needed %d): queue %u cntlid %u\n", 679*8f000cacSChristoph Hellwig 1 + rsp->n_rdma, queue->idx, 680*8f000cacSChristoph Hellwig queue->nvme_sq.ctrl->cntlid); 681*8f000cacSChristoph Hellwig atomic_add(1 + rsp->n_rdma, &queue->sq_wr_avail); 682*8f000cacSChristoph Hellwig return false; 683*8f000cacSChristoph Hellwig } 684*8f000cacSChristoph Hellwig 685*8f000cacSChristoph Hellwig if (nvmet_rdma_need_data_in(rsp)) { 686*8f000cacSChristoph Hellwig if (rdma_rw_ctx_post(&rsp->rw, queue->cm_id->qp, 687*8f000cacSChristoph Hellwig queue->cm_id->port_num, &rsp->read_cqe, NULL)) 688*8f000cacSChristoph Hellwig nvmet_req_complete(&rsp->req, NVME_SC_DATA_XFER_ERROR); 689*8f000cacSChristoph Hellwig } else { 690*8f000cacSChristoph Hellwig rsp->req.execute(&rsp->req); 691*8f000cacSChristoph Hellwig } 692*8f000cacSChristoph Hellwig 693*8f000cacSChristoph Hellwig return true; 694*8f000cacSChristoph Hellwig } 695*8f000cacSChristoph Hellwig 696*8f000cacSChristoph Hellwig static void nvmet_rdma_handle_command(struct nvmet_rdma_queue *queue, 697*8f000cacSChristoph Hellwig struct nvmet_rdma_rsp *cmd) 698*8f000cacSChristoph Hellwig { 699*8f000cacSChristoph Hellwig u16 status; 700*8f000cacSChristoph Hellwig 701*8f000cacSChristoph Hellwig cmd->queue = queue; 702*8f000cacSChristoph Hellwig cmd->n_rdma = 0; 703*8f000cacSChristoph Hellwig cmd->req.port = queue->port; 704*8f000cacSChristoph Hellwig 705*8f000cacSChristoph Hellwig if (!nvmet_req_init(&cmd->req, &queue->nvme_cq, 706*8f000cacSChristoph Hellwig &queue->nvme_sq, &nvmet_rdma_ops)) 707*8f000cacSChristoph Hellwig return; 708*8f000cacSChristoph Hellwig 709*8f000cacSChristoph Hellwig status = nvmet_rdma_map_sgl(cmd); 710*8f000cacSChristoph Hellwig if (status) 711*8f000cacSChristoph Hellwig goto out_err; 712*8f000cacSChristoph Hellwig 713*8f000cacSChristoph Hellwig if (unlikely(!nvmet_rdma_execute_command(cmd))) { 714*8f000cacSChristoph Hellwig spin_lock(&queue->rsp_wr_wait_lock); 715*8f000cacSChristoph Hellwig list_add_tail(&cmd->wait_list, &queue->rsp_wr_wait_list); 716*8f000cacSChristoph Hellwig spin_unlock(&queue->rsp_wr_wait_lock); 717*8f000cacSChristoph Hellwig } 718*8f000cacSChristoph Hellwig 719*8f000cacSChristoph Hellwig return; 720*8f000cacSChristoph Hellwig 721*8f000cacSChristoph Hellwig out_err: 722*8f000cacSChristoph Hellwig nvmet_req_complete(&cmd->req, status); 723*8f000cacSChristoph Hellwig } 724*8f000cacSChristoph Hellwig 725*8f000cacSChristoph Hellwig static void nvmet_rdma_recv_done(struct ib_cq *cq, struct ib_wc *wc) 726*8f000cacSChristoph Hellwig { 727*8f000cacSChristoph Hellwig struct nvmet_rdma_cmd *cmd = 728*8f000cacSChristoph Hellwig container_of(wc->wr_cqe, struct nvmet_rdma_cmd, cqe); 729*8f000cacSChristoph Hellwig struct nvmet_rdma_queue *queue = cq->cq_context; 730*8f000cacSChristoph Hellwig struct nvmet_rdma_rsp *rsp; 731*8f000cacSChristoph Hellwig 732*8f000cacSChristoph Hellwig if (unlikely(wc->status != IB_WC_SUCCESS)) { 733*8f000cacSChristoph Hellwig if (wc->status != IB_WC_WR_FLUSH_ERR) { 734*8f000cacSChristoph Hellwig pr_err("RECV for CQE 0x%p failed with status %s (%d)\n", 735*8f000cacSChristoph Hellwig wc->wr_cqe, ib_wc_status_msg(wc->status), 736*8f000cacSChristoph Hellwig wc->status); 737*8f000cacSChristoph Hellwig nvmet_rdma_error_comp(queue); 738*8f000cacSChristoph Hellwig } 739*8f000cacSChristoph Hellwig return; 740*8f000cacSChristoph Hellwig } 741*8f000cacSChristoph Hellwig 742*8f000cacSChristoph Hellwig if (unlikely(wc->byte_len < sizeof(struct nvme_command))) { 743*8f000cacSChristoph Hellwig pr_err("Ctrl Fatal Error: capsule size less than 64 bytes\n"); 744*8f000cacSChristoph Hellwig nvmet_rdma_error_comp(queue); 745*8f000cacSChristoph Hellwig return; 746*8f000cacSChristoph Hellwig } 747*8f000cacSChristoph Hellwig 748*8f000cacSChristoph Hellwig cmd->queue = queue; 749*8f000cacSChristoph Hellwig rsp = nvmet_rdma_get_rsp(queue); 750*8f000cacSChristoph Hellwig rsp->cmd = cmd; 751*8f000cacSChristoph Hellwig rsp->flags = 0; 752*8f000cacSChristoph Hellwig rsp->req.cmd = cmd->nvme_cmd; 753*8f000cacSChristoph Hellwig 754*8f000cacSChristoph Hellwig if (unlikely(queue->state != NVMET_RDMA_Q_LIVE)) { 755*8f000cacSChristoph Hellwig unsigned long flags; 756*8f000cacSChristoph Hellwig 757*8f000cacSChristoph Hellwig spin_lock_irqsave(&queue->state_lock, flags); 758*8f000cacSChristoph Hellwig if (queue->state == NVMET_RDMA_Q_CONNECTING) 759*8f000cacSChristoph Hellwig list_add_tail(&rsp->wait_list, &queue->rsp_wait_list); 760*8f000cacSChristoph Hellwig else 761*8f000cacSChristoph Hellwig nvmet_rdma_put_rsp(rsp); 762*8f000cacSChristoph Hellwig spin_unlock_irqrestore(&queue->state_lock, flags); 763*8f000cacSChristoph Hellwig return; 764*8f000cacSChristoph Hellwig } 765*8f000cacSChristoph Hellwig 766*8f000cacSChristoph Hellwig nvmet_rdma_handle_command(queue, rsp); 767*8f000cacSChristoph Hellwig } 768*8f000cacSChristoph Hellwig 769*8f000cacSChristoph Hellwig static void nvmet_rdma_destroy_srq(struct nvmet_rdma_device *ndev) 770*8f000cacSChristoph Hellwig { 771*8f000cacSChristoph Hellwig if (!ndev->srq) 772*8f000cacSChristoph Hellwig return; 773*8f000cacSChristoph Hellwig 774*8f000cacSChristoph Hellwig nvmet_rdma_free_cmds(ndev, ndev->srq_cmds, ndev->srq_size, false); 775*8f000cacSChristoph Hellwig ib_destroy_srq(ndev->srq); 776*8f000cacSChristoph Hellwig } 777*8f000cacSChristoph Hellwig 778*8f000cacSChristoph Hellwig static int nvmet_rdma_init_srq(struct nvmet_rdma_device *ndev) 779*8f000cacSChristoph Hellwig { 780*8f000cacSChristoph Hellwig struct ib_srq_init_attr srq_attr = { NULL, }; 781*8f000cacSChristoph Hellwig struct ib_srq *srq; 782*8f000cacSChristoph Hellwig size_t srq_size; 783*8f000cacSChristoph Hellwig int ret, i; 784*8f000cacSChristoph Hellwig 785*8f000cacSChristoph Hellwig srq_size = 4095; /* XXX: tune */ 786*8f000cacSChristoph Hellwig 787*8f000cacSChristoph Hellwig srq_attr.attr.max_wr = srq_size; 788*8f000cacSChristoph Hellwig srq_attr.attr.max_sge = 2; 789*8f000cacSChristoph Hellwig srq_attr.attr.srq_limit = 0; 790*8f000cacSChristoph Hellwig srq_attr.srq_type = IB_SRQT_BASIC; 791*8f000cacSChristoph Hellwig srq = ib_create_srq(ndev->pd, &srq_attr); 792*8f000cacSChristoph Hellwig if (IS_ERR(srq)) { 793*8f000cacSChristoph Hellwig /* 794*8f000cacSChristoph Hellwig * If SRQs aren't supported we just go ahead and use normal 795*8f000cacSChristoph Hellwig * non-shared receive queues. 796*8f000cacSChristoph Hellwig */ 797*8f000cacSChristoph Hellwig pr_info("SRQ requested but not supported.\n"); 798*8f000cacSChristoph Hellwig return 0; 799*8f000cacSChristoph Hellwig } 800*8f000cacSChristoph Hellwig 801*8f000cacSChristoph Hellwig ndev->srq_cmds = nvmet_rdma_alloc_cmds(ndev, srq_size, false); 802*8f000cacSChristoph Hellwig if (IS_ERR(ndev->srq_cmds)) { 803*8f000cacSChristoph Hellwig ret = PTR_ERR(ndev->srq_cmds); 804*8f000cacSChristoph Hellwig goto out_destroy_srq; 805*8f000cacSChristoph Hellwig } 806*8f000cacSChristoph Hellwig 807*8f000cacSChristoph Hellwig ndev->srq = srq; 808*8f000cacSChristoph Hellwig ndev->srq_size = srq_size; 809*8f000cacSChristoph Hellwig 810*8f000cacSChristoph Hellwig for (i = 0; i < srq_size; i++) 811*8f000cacSChristoph Hellwig nvmet_rdma_post_recv(ndev, &ndev->srq_cmds[i]); 812*8f000cacSChristoph Hellwig 813*8f000cacSChristoph Hellwig return 0; 814*8f000cacSChristoph Hellwig 815*8f000cacSChristoph Hellwig out_destroy_srq: 816*8f000cacSChristoph Hellwig ib_destroy_srq(srq); 817*8f000cacSChristoph Hellwig return ret; 818*8f000cacSChristoph Hellwig } 819*8f000cacSChristoph Hellwig 820*8f000cacSChristoph Hellwig static void nvmet_rdma_free_dev(struct kref *ref) 821*8f000cacSChristoph Hellwig { 822*8f000cacSChristoph Hellwig struct nvmet_rdma_device *ndev = 823*8f000cacSChristoph Hellwig container_of(ref, struct nvmet_rdma_device, ref); 824*8f000cacSChristoph Hellwig 825*8f000cacSChristoph Hellwig mutex_lock(&device_list_mutex); 826*8f000cacSChristoph Hellwig list_del(&ndev->entry); 827*8f000cacSChristoph Hellwig mutex_unlock(&device_list_mutex); 828*8f000cacSChristoph Hellwig 829*8f000cacSChristoph Hellwig nvmet_rdma_destroy_srq(ndev); 830*8f000cacSChristoph Hellwig ib_dealloc_pd(ndev->pd); 831*8f000cacSChristoph Hellwig 832*8f000cacSChristoph Hellwig kfree(ndev); 833*8f000cacSChristoph Hellwig } 834*8f000cacSChristoph Hellwig 835*8f000cacSChristoph Hellwig static struct nvmet_rdma_device * 836*8f000cacSChristoph Hellwig nvmet_rdma_find_get_device(struct rdma_cm_id *cm_id) 837*8f000cacSChristoph Hellwig { 838*8f000cacSChristoph Hellwig struct nvmet_rdma_device *ndev; 839*8f000cacSChristoph Hellwig int ret; 840*8f000cacSChristoph Hellwig 841*8f000cacSChristoph Hellwig mutex_lock(&device_list_mutex); 842*8f000cacSChristoph Hellwig list_for_each_entry(ndev, &device_list, entry) { 843*8f000cacSChristoph Hellwig if (ndev->device->node_guid == cm_id->device->node_guid && 844*8f000cacSChristoph Hellwig kref_get_unless_zero(&ndev->ref)) 845*8f000cacSChristoph Hellwig goto out_unlock; 846*8f000cacSChristoph Hellwig } 847*8f000cacSChristoph Hellwig 848*8f000cacSChristoph Hellwig ndev = kzalloc(sizeof(*ndev), GFP_KERNEL); 849*8f000cacSChristoph Hellwig if (!ndev) 850*8f000cacSChristoph Hellwig goto out_err; 851*8f000cacSChristoph Hellwig 852*8f000cacSChristoph Hellwig ndev->device = cm_id->device; 853*8f000cacSChristoph Hellwig kref_init(&ndev->ref); 854*8f000cacSChristoph Hellwig 855*8f000cacSChristoph Hellwig ndev->pd = ib_alloc_pd(ndev->device); 856*8f000cacSChristoph Hellwig if (IS_ERR(ndev->pd)) 857*8f000cacSChristoph Hellwig goto out_free_dev; 858*8f000cacSChristoph Hellwig 859*8f000cacSChristoph Hellwig if (nvmet_rdma_use_srq) { 860*8f000cacSChristoph Hellwig ret = nvmet_rdma_init_srq(ndev); 861*8f000cacSChristoph Hellwig if (ret) 862*8f000cacSChristoph Hellwig goto out_free_pd; 863*8f000cacSChristoph Hellwig } 864*8f000cacSChristoph Hellwig 865*8f000cacSChristoph Hellwig list_add(&ndev->entry, &device_list); 866*8f000cacSChristoph Hellwig out_unlock: 867*8f000cacSChristoph Hellwig mutex_unlock(&device_list_mutex); 868*8f000cacSChristoph Hellwig pr_debug("added %s.\n", ndev->device->name); 869*8f000cacSChristoph Hellwig return ndev; 870*8f000cacSChristoph Hellwig 871*8f000cacSChristoph Hellwig out_free_pd: 872*8f000cacSChristoph Hellwig ib_dealloc_pd(ndev->pd); 873*8f000cacSChristoph Hellwig out_free_dev: 874*8f000cacSChristoph Hellwig kfree(ndev); 875*8f000cacSChristoph Hellwig out_err: 876*8f000cacSChristoph Hellwig mutex_unlock(&device_list_mutex); 877*8f000cacSChristoph Hellwig return NULL; 878*8f000cacSChristoph Hellwig } 879*8f000cacSChristoph Hellwig 880*8f000cacSChristoph Hellwig static int nvmet_rdma_create_queue_ib(struct nvmet_rdma_queue *queue) 881*8f000cacSChristoph Hellwig { 882*8f000cacSChristoph Hellwig struct ib_qp_init_attr qp_attr; 883*8f000cacSChristoph Hellwig struct nvmet_rdma_device *ndev = queue->dev; 884*8f000cacSChristoph Hellwig int comp_vector, nr_cqe, ret, i; 885*8f000cacSChristoph Hellwig 886*8f000cacSChristoph Hellwig /* 887*8f000cacSChristoph Hellwig * Spread the io queues across completion vectors, 888*8f000cacSChristoph Hellwig * but still keep all admin queues on vector 0. 889*8f000cacSChristoph Hellwig */ 890*8f000cacSChristoph Hellwig comp_vector = !queue->host_qid ? 0 : 891*8f000cacSChristoph Hellwig queue->idx % ndev->device->num_comp_vectors; 892*8f000cacSChristoph Hellwig 893*8f000cacSChristoph Hellwig /* 894*8f000cacSChristoph Hellwig * Reserve CQ slots for RECV + RDMA_READ/RDMA_WRITE + RDMA_SEND. 895*8f000cacSChristoph Hellwig */ 896*8f000cacSChristoph Hellwig nr_cqe = queue->recv_queue_size + 2 * queue->send_queue_size; 897*8f000cacSChristoph Hellwig 898*8f000cacSChristoph Hellwig queue->cq = ib_alloc_cq(ndev->device, queue, 899*8f000cacSChristoph Hellwig nr_cqe + 1, comp_vector, 900*8f000cacSChristoph Hellwig IB_POLL_WORKQUEUE); 901*8f000cacSChristoph Hellwig if (IS_ERR(queue->cq)) { 902*8f000cacSChristoph Hellwig ret = PTR_ERR(queue->cq); 903*8f000cacSChristoph Hellwig pr_err("failed to create CQ cqe= %d ret= %d\n", 904*8f000cacSChristoph Hellwig nr_cqe + 1, ret); 905*8f000cacSChristoph Hellwig goto out; 906*8f000cacSChristoph Hellwig } 907*8f000cacSChristoph Hellwig 908*8f000cacSChristoph Hellwig memset(&qp_attr, 0, sizeof(qp_attr)); 909*8f000cacSChristoph Hellwig qp_attr.qp_context = queue; 910*8f000cacSChristoph Hellwig qp_attr.event_handler = nvmet_rdma_qp_event; 911*8f000cacSChristoph Hellwig qp_attr.send_cq = queue->cq; 912*8f000cacSChristoph Hellwig qp_attr.recv_cq = queue->cq; 913*8f000cacSChristoph Hellwig qp_attr.sq_sig_type = IB_SIGNAL_REQ_WR; 914*8f000cacSChristoph Hellwig qp_attr.qp_type = IB_QPT_RC; 915*8f000cacSChristoph Hellwig /* +1 for drain */ 916*8f000cacSChristoph Hellwig qp_attr.cap.max_send_wr = queue->send_queue_size + 1; 917*8f000cacSChristoph Hellwig qp_attr.cap.max_rdma_ctxs = queue->send_queue_size; 918*8f000cacSChristoph Hellwig qp_attr.cap.max_send_sge = max(ndev->device->attrs.max_sge_rd, 919*8f000cacSChristoph Hellwig ndev->device->attrs.max_sge); 920*8f000cacSChristoph Hellwig 921*8f000cacSChristoph Hellwig if (ndev->srq) { 922*8f000cacSChristoph Hellwig qp_attr.srq = ndev->srq; 923*8f000cacSChristoph Hellwig } else { 924*8f000cacSChristoph Hellwig /* +1 for drain */ 925*8f000cacSChristoph Hellwig qp_attr.cap.max_recv_wr = 1 + queue->recv_queue_size; 926*8f000cacSChristoph Hellwig qp_attr.cap.max_recv_sge = 2; 927*8f000cacSChristoph Hellwig } 928*8f000cacSChristoph Hellwig 929*8f000cacSChristoph Hellwig ret = rdma_create_qp(queue->cm_id, ndev->pd, &qp_attr); 930*8f000cacSChristoph Hellwig if (ret) { 931*8f000cacSChristoph Hellwig pr_err("failed to create_qp ret= %d\n", ret); 932*8f000cacSChristoph Hellwig goto err_destroy_cq; 933*8f000cacSChristoph Hellwig } 934*8f000cacSChristoph Hellwig 935*8f000cacSChristoph Hellwig atomic_set(&queue->sq_wr_avail, qp_attr.cap.max_send_wr); 936*8f000cacSChristoph Hellwig 937*8f000cacSChristoph Hellwig pr_debug("%s: max_cqe= %d max_sge= %d sq_size = %d cm_id= %p\n", 938*8f000cacSChristoph Hellwig __func__, queue->cq->cqe, qp_attr.cap.max_send_sge, 939*8f000cacSChristoph Hellwig qp_attr.cap.max_send_wr, queue->cm_id); 940*8f000cacSChristoph Hellwig 941*8f000cacSChristoph Hellwig if (!ndev->srq) { 942*8f000cacSChristoph Hellwig for (i = 0; i < queue->recv_queue_size; i++) { 943*8f000cacSChristoph Hellwig queue->cmds[i].queue = queue; 944*8f000cacSChristoph Hellwig nvmet_rdma_post_recv(ndev, &queue->cmds[i]); 945*8f000cacSChristoph Hellwig } 946*8f000cacSChristoph Hellwig } 947*8f000cacSChristoph Hellwig 948*8f000cacSChristoph Hellwig out: 949*8f000cacSChristoph Hellwig return ret; 950*8f000cacSChristoph Hellwig 951*8f000cacSChristoph Hellwig err_destroy_cq: 952*8f000cacSChristoph Hellwig ib_free_cq(queue->cq); 953*8f000cacSChristoph Hellwig goto out; 954*8f000cacSChristoph Hellwig } 955*8f000cacSChristoph Hellwig 956*8f000cacSChristoph Hellwig static void nvmet_rdma_destroy_queue_ib(struct nvmet_rdma_queue *queue) 957*8f000cacSChristoph Hellwig { 958*8f000cacSChristoph Hellwig rdma_destroy_qp(queue->cm_id); 959*8f000cacSChristoph Hellwig ib_free_cq(queue->cq); 960*8f000cacSChristoph Hellwig } 961*8f000cacSChristoph Hellwig 962*8f000cacSChristoph Hellwig static void nvmet_rdma_free_queue(struct nvmet_rdma_queue *queue) 963*8f000cacSChristoph Hellwig { 964*8f000cacSChristoph Hellwig pr_info("freeing queue %d\n", queue->idx); 965*8f000cacSChristoph Hellwig 966*8f000cacSChristoph Hellwig nvmet_sq_destroy(&queue->nvme_sq); 967*8f000cacSChristoph Hellwig 968*8f000cacSChristoph Hellwig nvmet_rdma_destroy_queue_ib(queue); 969*8f000cacSChristoph Hellwig if (!queue->dev->srq) { 970*8f000cacSChristoph Hellwig nvmet_rdma_free_cmds(queue->dev, queue->cmds, 971*8f000cacSChristoph Hellwig queue->recv_queue_size, 972*8f000cacSChristoph Hellwig !queue->host_qid); 973*8f000cacSChristoph Hellwig } 974*8f000cacSChristoph Hellwig nvmet_rdma_free_rsps(queue); 975*8f000cacSChristoph Hellwig ida_simple_remove(&nvmet_rdma_queue_ida, queue->idx); 976*8f000cacSChristoph Hellwig kfree(queue); 977*8f000cacSChristoph Hellwig } 978*8f000cacSChristoph Hellwig 979*8f000cacSChristoph Hellwig static void nvmet_rdma_release_queue_work(struct work_struct *w) 980*8f000cacSChristoph Hellwig { 981*8f000cacSChristoph Hellwig struct nvmet_rdma_queue *queue = 982*8f000cacSChristoph Hellwig container_of(w, struct nvmet_rdma_queue, release_work); 983*8f000cacSChristoph Hellwig struct rdma_cm_id *cm_id = queue->cm_id; 984*8f000cacSChristoph Hellwig struct nvmet_rdma_device *dev = queue->dev; 985*8f000cacSChristoph Hellwig 986*8f000cacSChristoph Hellwig nvmet_rdma_free_queue(queue); 987*8f000cacSChristoph Hellwig rdma_destroy_id(cm_id); 988*8f000cacSChristoph Hellwig kref_put(&dev->ref, nvmet_rdma_free_dev); 989*8f000cacSChristoph Hellwig } 990*8f000cacSChristoph Hellwig 991*8f000cacSChristoph Hellwig static int 992*8f000cacSChristoph Hellwig nvmet_rdma_parse_cm_connect_req(struct rdma_conn_param *conn, 993*8f000cacSChristoph Hellwig struct nvmet_rdma_queue *queue) 994*8f000cacSChristoph Hellwig { 995*8f000cacSChristoph Hellwig struct nvme_rdma_cm_req *req; 996*8f000cacSChristoph Hellwig 997*8f000cacSChristoph Hellwig req = (struct nvme_rdma_cm_req *)conn->private_data; 998*8f000cacSChristoph Hellwig if (!req || conn->private_data_len == 0) 999*8f000cacSChristoph Hellwig return NVME_RDMA_CM_INVALID_LEN; 1000*8f000cacSChristoph Hellwig 1001*8f000cacSChristoph Hellwig if (le16_to_cpu(req->recfmt) != NVME_RDMA_CM_FMT_1_0) 1002*8f000cacSChristoph Hellwig return NVME_RDMA_CM_INVALID_RECFMT; 1003*8f000cacSChristoph Hellwig 1004*8f000cacSChristoph Hellwig queue->host_qid = le16_to_cpu(req->qid); 1005*8f000cacSChristoph Hellwig 1006*8f000cacSChristoph Hellwig /* 1007*8f000cacSChristoph Hellwig * req->hsqsize corresponds to our recv queue size 1008*8f000cacSChristoph Hellwig * req->hrqsize corresponds to our send queue size 1009*8f000cacSChristoph Hellwig */ 1010*8f000cacSChristoph Hellwig queue->recv_queue_size = le16_to_cpu(req->hsqsize); 1011*8f000cacSChristoph Hellwig queue->send_queue_size = le16_to_cpu(req->hrqsize); 1012*8f000cacSChristoph Hellwig 1013*8f000cacSChristoph Hellwig if (!queue->host_qid && queue->recv_queue_size > NVMF_AQ_DEPTH) 1014*8f000cacSChristoph Hellwig return NVME_RDMA_CM_INVALID_HSQSIZE; 1015*8f000cacSChristoph Hellwig 1016*8f000cacSChristoph Hellwig /* XXX: Should we enforce some kind of max for IO queues? */ 1017*8f000cacSChristoph Hellwig 1018*8f000cacSChristoph Hellwig return 0; 1019*8f000cacSChristoph Hellwig } 1020*8f000cacSChristoph Hellwig 1021*8f000cacSChristoph Hellwig static int nvmet_rdma_cm_reject(struct rdma_cm_id *cm_id, 1022*8f000cacSChristoph Hellwig enum nvme_rdma_cm_status status) 1023*8f000cacSChristoph Hellwig { 1024*8f000cacSChristoph Hellwig struct nvme_rdma_cm_rej rej; 1025*8f000cacSChristoph Hellwig 1026*8f000cacSChristoph Hellwig rej.recfmt = cpu_to_le16(NVME_RDMA_CM_FMT_1_0); 1027*8f000cacSChristoph Hellwig rej.sts = cpu_to_le16(status); 1028*8f000cacSChristoph Hellwig 1029*8f000cacSChristoph Hellwig return rdma_reject(cm_id, (void *)&rej, sizeof(rej)); 1030*8f000cacSChristoph Hellwig } 1031*8f000cacSChristoph Hellwig 1032*8f000cacSChristoph Hellwig static struct nvmet_rdma_queue * 1033*8f000cacSChristoph Hellwig nvmet_rdma_alloc_queue(struct nvmet_rdma_device *ndev, 1034*8f000cacSChristoph Hellwig struct rdma_cm_id *cm_id, 1035*8f000cacSChristoph Hellwig struct rdma_cm_event *event) 1036*8f000cacSChristoph Hellwig { 1037*8f000cacSChristoph Hellwig struct nvmet_rdma_queue *queue; 1038*8f000cacSChristoph Hellwig int ret; 1039*8f000cacSChristoph Hellwig 1040*8f000cacSChristoph Hellwig queue = kzalloc(sizeof(*queue), GFP_KERNEL); 1041*8f000cacSChristoph Hellwig if (!queue) { 1042*8f000cacSChristoph Hellwig ret = NVME_RDMA_CM_NO_RSC; 1043*8f000cacSChristoph Hellwig goto out_reject; 1044*8f000cacSChristoph Hellwig } 1045*8f000cacSChristoph Hellwig 1046*8f000cacSChristoph Hellwig ret = nvmet_sq_init(&queue->nvme_sq); 1047*8f000cacSChristoph Hellwig if (ret) 1048*8f000cacSChristoph Hellwig goto out_free_queue; 1049*8f000cacSChristoph Hellwig 1050*8f000cacSChristoph Hellwig ret = nvmet_rdma_parse_cm_connect_req(&event->param.conn, queue); 1051*8f000cacSChristoph Hellwig if (ret) 1052*8f000cacSChristoph Hellwig goto out_destroy_sq; 1053*8f000cacSChristoph Hellwig 1054*8f000cacSChristoph Hellwig /* 1055*8f000cacSChristoph Hellwig * Schedules the actual release because calling rdma_destroy_id from 1056*8f000cacSChristoph Hellwig * inside a CM callback would trigger a deadlock. (great API design..) 1057*8f000cacSChristoph Hellwig */ 1058*8f000cacSChristoph Hellwig INIT_WORK(&queue->release_work, nvmet_rdma_release_queue_work); 1059*8f000cacSChristoph Hellwig queue->dev = ndev; 1060*8f000cacSChristoph Hellwig queue->cm_id = cm_id; 1061*8f000cacSChristoph Hellwig 1062*8f000cacSChristoph Hellwig spin_lock_init(&queue->state_lock); 1063*8f000cacSChristoph Hellwig queue->state = NVMET_RDMA_Q_CONNECTING; 1064*8f000cacSChristoph Hellwig INIT_LIST_HEAD(&queue->rsp_wait_list); 1065*8f000cacSChristoph Hellwig INIT_LIST_HEAD(&queue->rsp_wr_wait_list); 1066*8f000cacSChristoph Hellwig spin_lock_init(&queue->rsp_wr_wait_lock); 1067*8f000cacSChristoph Hellwig INIT_LIST_HEAD(&queue->free_rsps); 1068*8f000cacSChristoph Hellwig spin_lock_init(&queue->rsps_lock); 1069*8f000cacSChristoph Hellwig 1070*8f000cacSChristoph Hellwig queue->idx = ida_simple_get(&nvmet_rdma_queue_ida, 0, 0, GFP_KERNEL); 1071*8f000cacSChristoph Hellwig if (queue->idx < 0) { 1072*8f000cacSChristoph Hellwig ret = NVME_RDMA_CM_NO_RSC; 1073*8f000cacSChristoph Hellwig goto out_free_queue; 1074*8f000cacSChristoph Hellwig } 1075*8f000cacSChristoph Hellwig 1076*8f000cacSChristoph Hellwig ret = nvmet_rdma_alloc_rsps(queue); 1077*8f000cacSChristoph Hellwig if (ret) { 1078*8f000cacSChristoph Hellwig ret = NVME_RDMA_CM_NO_RSC; 1079*8f000cacSChristoph Hellwig goto out_ida_remove; 1080*8f000cacSChristoph Hellwig } 1081*8f000cacSChristoph Hellwig 1082*8f000cacSChristoph Hellwig if (!ndev->srq) { 1083*8f000cacSChristoph Hellwig queue->cmds = nvmet_rdma_alloc_cmds(ndev, 1084*8f000cacSChristoph Hellwig queue->recv_queue_size, 1085*8f000cacSChristoph Hellwig !queue->host_qid); 1086*8f000cacSChristoph Hellwig if (IS_ERR(queue->cmds)) { 1087*8f000cacSChristoph Hellwig ret = NVME_RDMA_CM_NO_RSC; 1088*8f000cacSChristoph Hellwig goto out_free_responses; 1089*8f000cacSChristoph Hellwig } 1090*8f000cacSChristoph Hellwig } 1091*8f000cacSChristoph Hellwig 1092*8f000cacSChristoph Hellwig ret = nvmet_rdma_create_queue_ib(queue); 1093*8f000cacSChristoph Hellwig if (ret) { 1094*8f000cacSChristoph Hellwig pr_err("%s: creating RDMA queue failed (%d).\n", 1095*8f000cacSChristoph Hellwig __func__, ret); 1096*8f000cacSChristoph Hellwig ret = NVME_RDMA_CM_NO_RSC; 1097*8f000cacSChristoph Hellwig goto out_free_cmds; 1098*8f000cacSChristoph Hellwig } 1099*8f000cacSChristoph Hellwig 1100*8f000cacSChristoph Hellwig return queue; 1101*8f000cacSChristoph Hellwig 1102*8f000cacSChristoph Hellwig out_free_cmds: 1103*8f000cacSChristoph Hellwig if (!ndev->srq) { 1104*8f000cacSChristoph Hellwig nvmet_rdma_free_cmds(queue->dev, queue->cmds, 1105*8f000cacSChristoph Hellwig queue->recv_queue_size, 1106*8f000cacSChristoph Hellwig !queue->host_qid); 1107*8f000cacSChristoph Hellwig } 1108*8f000cacSChristoph Hellwig out_free_responses: 1109*8f000cacSChristoph Hellwig nvmet_rdma_free_rsps(queue); 1110*8f000cacSChristoph Hellwig out_ida_remove: 1111*8f000cacSChristoph Hellwig ida_simple_remove(&nvmet_rdma_queue_ida, queue->idx); 1112*8f000cacSChristoph Hellwig out_destroy_sq: 1113*8f000cacSChristoph Hellwig nvmet_sq_destroy(&queue->nvme_sq); 1114*8f000cacSChristoph Hellwig out_free_queue: 1115*8f000cacSChristoph Hellwig kfree(queue); 1116*8f000cacSChristoph Hellwig out_reject: 1117*8f000cacSChristoph Hellwig nvmet_rdma_cm_reject(cm_id, ret); 1118*8f000cacSChristoph Hellwig return NULL; 1119*8f000cacSChristoph Hellwig } 1120*8f000cacSChristoph Hellwig 1121*8f000cacSChristoph Hellwig static void nvmet_rdma_qp_event(struct ib_event *event, void *priv) 1122*8f000cacSChristoph Hellwig { 1123*8f000cacSChristoph Hellwig struct nvmet_rdma_queue *queue = priv; 1124*8f000cacSChristoph Hellwig 1125*8f000cacSChristoph Hellwig switch (event->event) { 1126*8f000cacSChristoph Hellwig case IB_EVENT_COMM_EST: 1127*8f000cacSChristoph Hellwig rdma_notify(queue->cm_id, event->event); 1128*8f000cacSChristoph Hellwig break; 1129*8f000cacSChristoph Hellwig default: 1130*8f000cacSChristoph Hellwig pr_err("received unrecognized IB QP event %d\n", event->event); 1131*8f000cacSChristoph Hellwig break; 1132*8f000cacSChristoph Hellwig } 1133*8f000cacSChristoph Hellwig } 1134*8f000cacSChristoph Hellwig 1135*8f000cacSChristoph Hellwig static int nvmet_rdma_cm_accept(struct rdma_cm_id *cm_id, 1136*8f000cacSChristoph Hellwig struct nvmet_rdma_queue *queue, 1137*8f000cacSChristoph Hellwig struct rdma_conn_param *p) 1138*8f000cacSChristoph Hellwig { 1139*8f000cacSChristoph Hellwig struct rdma_conn_param param = { }; 1140*8f000cacSChristoph Hellwig struct nvme_rdma_cm_rep priv = { }; 1141*8f000cacSChristoph Hellwig int ret = -ENOMEM; 1142*8f000cacSChristoph Hellwig 1143*8f000cacSChristoph Hellwig param.rnr_retry_count = 7; 1144*8f000cacSChristoph Hellwig param.flow_control = 1; 1145*8f000cacSChristoph Hellwig param.initiator_depth = min_t(u8, p->initiator_depth, 1146*8f000cacSChristoph Hellwig queue->dev->device->attrs.max_qp_init_rd_atom); 1147*8f000cacSChristoph Hellwig param.private_data = &priv; 1148*8f000cacSChristoph Hellwig param.private_data_len = sizeof(priv); 1149*8f000cacSChristoph Hellwig priv.recfmt = cpu_to_le16(NVME_RDMA_CM_FMT_1_0); 1150*8f000cacSChristoph Hellwig priv.crqsize = cpu_to_le16(queue->recv_queue_size); 1151*8f000cacSChristoph Hellwig 1152*8f000cacSChristoph Hellwig ret = rdma_accept(cm_id, ¶m); 1153*8f000cacSChristoph Hellwig if (ret) 1154*8f000cacSChristoph Hellwig pr_err("rdma_accept failed (error code = %d)\n", ret); 1155*8f000cacSChristoph Hellwig 1156*8f000cacSChristoph Hellwig return ret; 1157*8f000cacSChristoph Hellwig } 1158*8f000cacSChristoph Hellwig 1159*8f000cacSChristoph Hellwig static int nvmet_rdma_queue_connect(struct rdma_cm_id *cm_id, 1160*8f000cacSChristoph Hellwig struct rdma_cm_event *event) 1161*8f000cacSChristoph Hellwig { 1162*8f000cacSChristoph Hellwig struct nvmet_rdma_device *ndev; 1163*8f000cacSChristoph Hellwig struct nvmet_rdma_queue *queue; 1164*8f000cacSChristoph Hellwig int ret = -EINVAL; 1165*8f000cacSChristoph Hellwig 1166*8f000cacSChristoph Hellwig ndev = nvmet_rdma_find_get_device(cm_id); 1167*8f000cacSChristoph Hellwig if (!ndev) { 1168*8f000cacSChristoph Hellwig pr_err("no client data!\n"); 1169*8f000cacSChristoph Hellwig nvmet_rdma_cm_reject(cm_id, NVME_RDMA_CM_NO_RSC); 1170*8f000cacSChristoph Hellwig return -ECONNREFUSED; 1171*8f000cacSChristoph Hellwig } 1172*8f000cacSChristoph Hellwig 1173*8f000cacSChristoph Hellwig queue = nvmet_rdma_alloc_queue(ndev, cm_id, event); 1174*8f000cacSChristoph Hellwig if (!queue) { 1175*8f000cacSChristoph Hellwig ret = -ENOMEM; 1176*8f000cacSChristoph Hellwig goto put_device; 1177*8f000cacSChristoph Hellwig } 1178*8f000cacSChristoph Hellwig queue->port = cm_id->context; 1179*8f000cacSChristoph Hellwig 1180*8f000cacSChristoph Hellwig ret = nvmet_rdma_cm_accept(cm_id, queue, &event->param.conn); 1181*8f000cacSChristoph Hellwig if (ret) 1182*8f000cacSChristoph Hellwig goto release_queue; 1183*8f000cacSChristoph Hellwig 1184*8f000cacSChristoph Hellwig mutex_lock(&nvmet_rdma_queue_mutex); 1185*8f000cacSChristoph Hellwig list_add_tail(&queue->queue_list, &nvmet_rdma_queue_list); 1186*8f000cacSChristoph Hellwig mutex_unlock(&nvmet_rdma_queue_mutex); 1187*8f000cacSChristoph Hellwig 1188*8f000cacSChristoph Hellwig return 0; 1189*8f000cacSChristoph Hellwig 1190*8f000cacSChristoph Hellwig release_queue: 1191*8f000cacSChristoph Hellwig nvmet_rdma_free_queue(queue); 1192*8f000cacSChristoph Hellwig put_device: 1193*8f000cacSChristoph Hellwig kref_put(&ndev->ref, nvmet_rdma_free_dev); 1194*8f000cacSChristoph Hellwig 1195*8f000cacSChristoph Hellwig return ret; 1196*8f000cacSChristoph Hellwig } 1197*8f000cacSChristoph Hellwig 1198*8f000cacSChristoph Hellwig static void nvmet_rdma_queue_established(struct nvmet_rdma_queue *queue) 1199*8f000cacSChristoph Hellwig { 1200*8f000cacSChristoph Hellwig unsigned long flags; 1201*8f000cacSChristoph Hellwig 1202*8f000cacSChristoph Hellwig spin_lock_irqsave(&queue->state_lock, flags); 1203*8f000cacSChristoph Hellwig if (queue->state != NVMET_RDMA_Q_CONNECTING) { 1204*8f000cacSChristoph Hellwig pr_warn("trying to establish a connected queue\n"); 1205*8f000cacSChristoph Hellwig goto out_unlock; 1206*8f000cacSChristoph Hellwig } 1207*8f000cacSChristoph Hellwig queue->state = NVMET_RDMA_Q_LIVE; 1208*8f000cacSChristoph Hellwig 1209*8f000cacSChristoph Hellwig while (!list_empty(&queue->rsp_wait_list)) { 1210*8f000cacSChristoph Hellwig struct nvmet_rdma_rsp *cmd; 1211*8f000cacSChristoph Hellwig 1212*8f000cacSChristoph Hellwig cmd = list_first_entry(&queue->rsp_wait_list, 1213*8f000cacSChristoph Hellwig struct nvmet_rdma_rsp, wait_list); 1214*8f000cacSChristoph Hellwig list_del(&cmd->wait_list); 1215*8f000cacSChristoph Hellwig 1216*8f000cacSChristoph Hellwig spin_unlock_irqrestore(&queue->state_lock, flags); 1217*8f000cacSChristoph Hellwig nvmet_rdma_handle_command(queue, cmd); 1218*8f000cacSChristoph Hellwig spin_lock_irqsave(&queue->state_lock, flags); 1219*8f000cacSChristoph Hellwig } 1220*8f000cacSChristoph Hellwig 1221*8f000cacSChristoph Hellwig out_unlock: 1222*8f000cacSChristoph Hellwig spin_unlock_irqrestore(&queue->state_lock, flags); 1223*8f000cacSChristoph Hellwig } 1224*8f000cacSChristoph Hellwig 1225*8f000cacSChristoph Hellwig static void __nvmet_rdma_queue_disconnect(struct nvmet_rdma_queue *queue) 1226*8f000cacSChristoph Hellwig { 1227*8f000cacSChristoph Hellwig bool disconnect = false; 1228*8f000cacSChristoph Hellwig unsigned long flags; 1229*8f000cacSChristoph Hellwig 1230*8f000cacSChristoph Hellwig pr_debug("cm_id= %p queue->state= %d\n", queue->cm_id, queue->state); 1231*8f000cacSChristoph Hellwig 1232*8f000cacSChristoph Hellwig spin_lock_irqsave(&queue->state_lock, flags); 1233*8f000cacSChristoph Hellwig switch (queue->state) { 1234*8f000cacSChristoph Hellwig case NVMET_RDMA_Q_CONNECTING: 1235*8f000cacSChristoph Hellwig case NVMET_RDMA_Q_LIVE: 1236*8f000cacSChristoph Hellwig disconnect = true; 1237*8f000cacSChristoph Hellwig queue->state = NVMET_RDMA_Q_DISCONNECTING; 1238*8f000cacSChristoph Hellwig break; 1239*8f000cacSChristoph Hellwig case NVMET_RDMA_Q_DISCONNECTING: 1240*8f000cacSChristoph Hellwig break; 1241*8f000cacSChristoph Hellwig } 1242*8f000cacSChristoph Hellwig spin_unlock_irqrestore(&queue->state_lock, flags); 1243*8f000cacSChristoph Hellwig 1244*8f000cacSChristoph Hellwig if (disconnect) { 1245*8f000cacSChristoph Hellwig rdma_disconnect(queue->cm_id); 1246*8f000cacSChristoph Hellwig ib_drain_qp(queue->cm_id->qp); 1247*8f000cacSChristoph Hellwig schedule_work(&queue->release_work); 1248*8f000cacSChristoph Hellwig } 1249*8f000cacSChristoph Hellwig } 1250*8f000cacSChristoph Hellwig 1251*8f000cacSChristoph Hellwig static void nvmet_rdma_queue_disconnect(struct nvmet_rdma_queue *queue) 1252*8f000cacSChristoph Hellwig { 1253*8f000cacSChristoph Hellwig bool disconnect = false; 1254*8f000cacSChristoph Hellwig 1255*8f000cacSChristoph Hellwig mutex_lock(&nvmet_rdma_queue_mutex); 1256*8f000cacSChristoph Hellwig if (!list_empty(&queue->queue_list)) { 1257*8f000cacSChristoph Hellwig list_del_init(&queue->queue_list); 1258*8f000cacSChristoph Hellwig disconnect = true; 1259*8f000cacSChristoph Hellwig } 1260*8f000cacSChristoph Hellwig mutex_unlock(&nvmet_rdma_queue_mutex); 1261*8f000cacSChristoph Hellwig 1262*8f000cacSChristoph Hellwig if (disconnect) 1263*8f000cacSChristoph Hellwig __nvmet_rdma_queue_disconnect(queue); 1264*8f000cacSChristoph Hellwig } 1265*8f000cacSChristoph Hellwig 1266*8f000cacSChristoph Hellwig static void nvmet_rdma_queue_connect_fail(struct rdma_cm_id *cm_id, 1267*8f000cacSChristoph Hellwig struct nvmet_rdma_queue *queue) 1268*8f000cacSChristoph Hellwig { 1269*8f000cacSChristoph Hellwig WARN_ON_ONCE(queue->state != NVMET_RDMA_Q_CONNECTING); 1270*8f000cacSChristoph Hellwig 1271*8f000cacSChristoph Hellwig pr_err("failed to connect queue\n"); 1272*8f000cacSChristoph Hellwig schedule_work(&queue->release_work); 1273*8f000cacSChristoph Hellwig } 1274*8f000cacSChristoph Hellwig 1275*8f000cacSChristoph Hellwig static int nvmet_rdma_cm_handler(struct rdma_cm_id *cm_id, 1276*8f000cacSChristoph Hellwig struct rdma_cm_event *event) 1277*8f000cacSChristoph Hellwig { 1278*8f000cacSChristoph Hellwig struct nvmet_rdma_queue *queue = NULL; 1279*8f000cacSChristoph Hellwig int ret = 0; 1280*8f000cacSChristoph Hellwig 1281*8f000cacSChristoph Hellwig if (cm_id->qp) 1282*8f000cacSChristoph Hellwig queue = cm_id->qp->qp_context; 1283*8f000cacSChristoph Hellwig 1284*8f000cacSChristoph Hellwig pr_debug("%s (%d): status %d id %p\n", 1285*8f000cacSChristoph Hellwig rdma_event_msg(event->event), event->event, 1286*8f000cacSChristoph Hellwig event->status, cm_id); 1287*8f000cacSChristoph Hellwig 1288*8f000cacSChristoph Hellwig switch (event->event) { 1289*8f000cacSChristoph Hellwig case RDMA_CM_EVENT_CONNECT_REQUEST: 1290*8f000cacSChristoph Hellwig ret = nvmet_rdma_queue_connect(cm_id, event); 1291*8f000cacSChristoph Hellwig break; 1292*8f000cacSChristoph Hellwig case RDMA_CM_EVENT_ESTABLISHED: 1293*8f000cacSChristoph Hellwig nvmet_rdma_queue_established(queue); 1294*8f000cacSChristoph Hellwig break; 1295*8f000cacSChristoph Hellwig case RDMA_CM_EVENT_ADDR_CHANGE: 1296*8f000cacSChristoph Hellwig case RDMA_CM_EVENT_DISCONNECTED: 1297*8f000cacSChristoph Hellwig case RDMA_CM_EVENT_DEVICE_REMOVAL: 1298*8f000cacSChristoph Hellwig case RDMA_CM_EVENT_TIMEWAIT_EXIT: 1299*8f000cacSChristoph Hellwig /* 1300*8f000cacSChristoph Hellwig * We can get the device removal callback even for a 1301*8f000cacSChristoph Hellwig * CM ID that we aren't actually using. In that case 1302*8f000cacSChristoph Hellwig * the context pointer is NULL, so we shouldn't try 1303*8f000cacSChristoph Hellwig * to disconnect a non-existing queue. But we also 1304*8f000cacSChristoph Hellwig * need to return 1 so that the core will destroy 1305*8f000cacSChristoph Hellwig * it's own ID. What a great API design.. 1306*8f000cacSChristoph Hellwig */ 1307*8f000cacSChristoph Hellwig if (queue) 1308*8f000cacSChristoph Hellwig nvmet_rdma_queue_disconnect(queue); 1309*8f000cacSChristoph Hellwig else 1310*8f000cacSChristoph Hellwig ret = 1; 1311*8f000cacSChristoph Hellwig break; 1312*8f000cacSChristoph Hellwig case RDMA_CM_EVENT_REJECTED: 1313*8f000cacSChristoph Hellwig case RDMA_CM_EVENT_UNREACHABLE: 1314*8f000cacSChristoph Hellwig case RDMA_CM_EVENT_CONNECT_ERROR: 1315*8f000cacSChristoph Hellwig nvmet_rdma_queue_connect_fail(cm_id, queue); 1316*8f000cacSChristoph Hellwig break; 1317*8f000cacSChristoph Hellwig default: 1318*8f000cacSChristoph Hellwig pr_err("received unrecognized RDMA CM event %d\n", 1319*8f000cacSChristoph Hellwig event->event); 1320*8f000cacSChristoph Hellwig break; 1321*8f000cacSChristoph Hellwig } 1322*8f000cacSChristoph Hellwig 1323*8f000cacSChristoph Hellwig return ret; 1324*8f000cacSChristoph Hellwig } 1325*8f000cacSChristoph Hellwig 1326*8f000cacSChristoph Hellwig static void nvmet_rdma_delete_ctrl(struct nvmet_ctrl *ctrl) 1327*8f000cacSChristoph Hellwig { 1328*8f000cacSChristoph Hellwig struct nvmet_rdma_queue *queue; 1329*8f000cacSChristoph Hellwig 1330*8f000cacSChristoph Hellwig restart: 1331*8f000cacSChristoph Hellwig mutex_lock(&nvmet_rdma_queue_mutex); 1332*8f000cacSChristoph Hellwig list_for_each_entry(queue, &nvmet_rdma_queue_list, queue_list) { 1333*8f000cacSChristoph Hellwig if (queue->nvme_sq.ctrl == ctrl) { 1334*8f000cacSChristoph Hellwig list_del_init(&queue->queue_list); 1335*8f000cacSChristoph Hellwig mutex_unlock(&nvmet_rdma_queue_mutex); 1336*8f000cacSChristoph Hellwig 1337*8f000cacSChristoph Hellwig __nvmet_rdma_queue_disconnect(queue); 1338*8f000cacSChristoph Hellwig goto restart; 1339*8f000cacSChristoph Hellwig } 1340*8f000cacSChristoph Hellwig } 1341*8f000cacSChristoph Hellwig mutex_unlock(&nvmet_rdma_queue_mutex); 1342*8f000cacSChristoph Hellwig } 1343*8f000cacSChristoph Hellwig 1344*8f000cacSChristoph Hellwig static int nvmet_rdma_add_port(struct nvmet_port *port) 1345*8f000cacSChristoph Hellwig { 1346*8f000cacSChristoph Hellwig struct rdma_cm_id *cm_id; 1347*8f000cacSChristoph Hellwig struct sockaddr_in addr_in; 1348*8f000cacSChristoph Hellwig u16 port_in; 1349*8f000cacSChristoph Hellwig int ret; 1350*8f000cacSChristoph Hellwig 1351*8f000cacSChristoph Hellwig switch (port->disc_addr.adrfam) { 1352*8f000cacSChristoph Hellwig case NVMF_ADDR_FAMILY_IP4: 1353*8f000cacSChristoph Hellwig break; 1354*8f000cacSChristoph Hellwig default: 1355*8f000cacSChristoph Hellwig pr_err("address family %d not supported\n", 1356*8f000cacSChristoph Hellwig port->disc_addr.adrfam); 1357*8f000cacSChristoph Hellwig return -EINVAL; 1358*8f000cacSChristoph Hellwig } 1359*8f000cacSChristoph Hellwig 1360*8f000cacSChristoph Hellwig ret = kstrtou16(port->disc_addr.trsvcid, 0, &port_in); 1361*8f000cacSChristoph Hellwig if (ret) 1362*8f000cacSChristoph Hellwig return ret; 1363*8f000cacSChristoph Hellwig 1364*8f000cacSChristoph Hellwig addr_in.sin_family = AF_INET; 1365*8f000cacSChristoph Hellwig addr_in.sin_addr.s_addr = in_aton(port->disc_addr.traddr); 1366*8f000cacSChristoph Hellwig addr_in.sin_port = htons(port_in); 1367*8f000cacSChristoph Hellwig 1368*8f000cacSChristoph Hellwig cm_id = rdma_create_id(&init_net, nvmet_rdma_cm_handler, port, 1369*8f000cacSChristoph Hellwig RDMA_PS_TCP, IB_QPT_RC); 1370*8f000cacSChristoph Hellwig if (IS_ERR(cm_id)) { 1371*8f000cacSChristoph Hellwig pr_err("CM ID creation failed\n"); 1372*8f000cacSChristoph Hellwig return PTR_ERR(cm_id); 1373*8f000cacSChristoph Hellwig } 1374*8f000cacSChristoph Hellwig 1375*8f000cacSChristoph Hellwig ret = rdma_bind_addr(cm_id, (struct sockaddr *)&addr_in); 1376*8f000cacSChristoph Hellwig if (ret) { 1377*8f000cacSChristoph Hellwig pr_err("binding CM ID to %pISpc failed (%d)\n", &addr_in, ret); 1378*8f000cacSChristoph Hellwig goto out_destroy_id; 1379*8f000cacSChristoph Hellwig } 1380*8f000cacSChristoph Hellwig 1381*8f000cacSChristoph Hellwig ret = rdma_listen(cm_id, 128); 1382*8f000cacSChristoph Hellwig if (ret) { 1383*8f000cacSChristoph Hellwig pr_err("listening to %pISpc failed (%d)\n", &addr_in, ret); 1384*8f000cacSChristoph Hellwig goto out_destroy_id; 1385*8f000cacSChristoph Hellwig } 1386*8f000cacSChristoph Hellwig 1387*8f000cacSChristoph Hellwig pr_info("enabling port %d (%pISpc)\n", 1388*8f000cacSChristoph Hellwig le16_to_cpu(port->disc_addr.portid), &addr_in); 1389*8f000cacSChristoph Hellwig port->priv = cm_id; 1390*8f000cacSChristoph Hellwig return 0; 1391*8f000cacSChristoph Hellwig 1392*8f000cacSChristoph Hellwig out_destroy_id: 1393*8f000cacSChristoph Hellwig rdma_destroy_id(cm_id); 1394*8f000cacSChristoph Hellwig return ret; 1395*8f000cacSChristoph Hellwig } 1396*8f000cacSChristoph Hellwig 1397*8f000cacSChristoph Hellwig static void nvmet_rdma_remove_port(struct nvmet_port *port) 1398*8f000cacSChristoph Hellwig { 1399*8f000cacSChristoph Hellwig struct rdma_cm_id *cm_id = port->priv; 1400*8f000cacSChristoph Hellwig 1401*8f000cacSChristoph Hellwig rdma_destroy_id(cm_id); 1402*8f000cacSChristoph Hellwig } 1403*8f000cacSChristoph Hellwig 1404*8f000cacSChristoph Hellwig static struct nvmet_fabrics_ops nvmet_rdma_ops = { 1405*8f000cacSChristoph Hellwig .owner = THIS_MODULE, 1406*8f000cacSChristoph Hellwig .type = NVMF_TRTYPE_RDMA, 1407*8f000cacSChristoph Hellwig .sqe_inline_size = NVMET_RDMA_INLINE_DATA_SIZE, 1408*8f000cacSChristoph Hellwig .msdbd = 1, 1409*8f000cacSChristoph Hellwig .has_keyed_sgls = 1, 1410*8f000cacSChristoph Hellwig .add_port = nvmet_rdma_add_port, 1411*8f000cacSChristoph Hellwig .remove_port = nvmet_rdma_remove_port, 1412*8f000cacSChristoph Hellwig .queue_response = nvmet_rdma_queue_response, 1413*8f000cacSChristoph Hellwig .delete_ctrl = nvmet_rdma_delete_ctrl, 1414*8f000cacSChristoph Hellwig }; 1415*8f000cacSChristoph Hellwig 1416*8f000cacSChristoph Hellwig static int __init nvmet_rdma_init(void) 1417*8f000cacSChristoph Hellwig { 1418*8f000cacSChristoph Hellwig return nvmet_register_transport(&nvmet_rdma_ops); 1419*8f000cacSChristoph Hellwig } 1420*8f000cacSChristoph Hellwig 1421*8f000cacSChristoph Hellwig static void __exit nvmet_rdma_exit(void) 1422*8f000cacSChristoph Hellwig { 1423*8f000cacSChristoph Hellwig struct nvmet_rdma_queue *queue; 1424*8f000cacSChristoph Hellwig 1425*8f000cacSChristoph Hellwig nvmet_unregister_transport(&nvmet_rdma_ops); 1426*8f000cacSChristoph Hellwig 1427*8f000cacSChristoph Hellwig flush_scheduled_work(); 1428*8f000cacSChristoph Hellwig 1429*8f000cacSChristoph Hellwig mutex_lock(&nvmet_rdma_queue_mutex); 1430*8f000cacSChristoph Hellwig while ((queue = list_first_entry_or_null(&nvmet_rdma_queue_list, 1431*8f000cacSChristoph Hellwig struct nvmet_rdma_queue, queue_list))) { 1432*8f000cacSChristoph Hellwig list_del_init(&queue->queue_list); 1433*8f000cacSChristoph Hellwig 1434*8f000cacSChristoph Hellwig mutex_unlock(&nvmet_rdma_queue_mutex); 1435*8f000cacSChristoph Hellwig __nvmet_rdma_queue_disconnect(queue); 1436*8f000cacSChristoph Hellwig mutex_lock(&nvmet_rdma_queue_mutex); 1437*8f000cacSChristoph Hellwig } 1438*8f000cacSChristoph Hellwig mutex_unlock(&nvmet_rdma_queue_mutex); 1439*8f000cacSChristoph Hellwig 1440*8f000cacSChristoph Hellwig flush_scheduled_work(); 1441*8f000cacSChristoph Hellwig ida_destroy(&nvmet_rdma_queue_ida); 1442*8f000cacSChristoph Hellwig } 1443*8f000cacSChristoph Hellwig 1444*8f000cacSChristoph Hellwig module_init(nvmet_rdma_init); 1445*8f000cacSChristoph Hellwig module_exit(nvmet_rdma_exit); 1446*8f000cacSChristoph Hellwig 1447*8f000cacSChristoph Hellwig MODULE_LICENSE("GPL v2"); 1448*8f000cacSChristoph Hellwig MODULE_ALIAS("nvmet-transport-1"); /* 1 == NVMF_TRTYPE_RDMA */ 1449