1f3bdbd42SAbhijit Gangurde // SPDX-License-Identifier: GPL-2.0 2f3bdbd42SAbhijit Gangurde /* Copyright (C) 2018-2025, Advanced Micro Devices, Inc. */ 3f3bdbd42SAbhijit Gangurde 4*e8521822SAbhijit Gangurde #include <linux/module.h> 5*e8521822SAbhijit Gangurde #include <linux/printk.h> 6*e8521822SAbhijit Gangurde #include <rdma/ib_addr.h> 7*e8521822SAbhijit Gangurde #include <rdma/ib_cache.h> 8*e8521822SAbhijit Gangurde #include <rdma/ib_user_verbs.h> 9*e8521822SAbhijit Gangurde #include <ionic_api.h> 10*e8521822SAbhijit Gangurde 11*e8521822SAbhijit Gangurde #include "ionic_fw.h" 12f3bdbd42SAbhijit Gangurde #include "ionic_ibdev.h" 13f3bdbd42SAbhijit Gangurde 14*e8521822SAbhijit Gangurde #define ionic_set_ecn(tos) (((tos) | 2u) & ~1u) 15*e8521822SAbhijit Gangurde #define ionic_clear_ecn(tos) ((tos) & ~3u) 16*e8521822SAbhijit Gangurde 17f3bdbd42SAbhijit Gangurde static int ionic_validate_qdesc(struct ionic_qdesc *q) 18f3bdbd42SAbhijit Gangurde { 19f3bdbd42SAbhijit Gangurde if (!q->addr || !q->size || !q->mask || 20f3bdbd42SAbhijit Gangurde !q->depth_log2 || !q->stride_log2) 21f3bdbd42SAbhijit Gangurde return -EINVAL; 22f3bdbd42SAbhijit Gangurde 23f3bdbd42SAbhijit Gangurde if (q->addr & (PAGE_SIZE - 1)) 24f3bdbd42SAbhijit Gangurde return -EINVAL; 25f3bdbd42SAbhijit Gangurde 26f3bdbd42SAbhijit Gangurde if (q->mask != BIT(q->depth_log2) - 1) 27f3bdbd42SAbhijit Gangurde return -EINVAL; 28f3bdbd42SAbhijit Gangurde 29f3bdbd42SAbhijit Gangurde if (q->size < BIT_ULL(q->depth_log2 + q->stride_log2)) 30f3bdbd42SAbhijit Gangurde return -EINVAL; 31f3bdbd42SAbhijit Gangurde 32f3bdbd42SAbhijit Gangurde return 0; 33f3bdbd42SAbhijit Gangurde } 34f3bdbd42SAbhijit Gangurde 35f3bdbd42SAbhijit Gangurde static u32 ionic_get_eqid(struct ionic_ibdev *dev, u32 comp_vector, u8 udma_idx) 36f3bdbd42SAbhijit Gangurde { 37f3bdbd42SAbhijit Gangurde /* EQ per vector per udma, and the first eqs reserved for async events. 38f3bdbd42SAbhijit Gangurde * The rest of the vectors can be requested for completions. 39f3bdbd42SAbhijit Gangurde */ 40f3bdbd42SAbhijit Gangurde u32 comp_vec_count = dev->lif_cfg.eq_count / dev->lif_cfg.udma_count - 1; 41f3bdbd42SAbhijit Gangurde 42f3bdbd42SAbhijit Gangurde return (comp_vector % comp_vec_count + 1) * dev->lif_cfg.udma_count + udma_idx; 43f3bdbd42SAbhijit Gangurde } 44f3bdbd42SAbhijit Gangurde 45f3bdbd42SAbhijit Gangurde static int ionic_get_cqid(struct ionic_ibdev *dev, u32 *cqid, u8 udma_idx) 46f3bdbd42SAbhijit Gangurde { 47f3bdbd42SAbhijit Gangurde unsigned int size, base, bound; 48f3bdbd42SAbhijit Gangurde int rc; 49f3bdbd42SAbhijit Gangurde 50f3bdbd42SAbhijit Gangurde size = dev->lif_cfg.cq_count / dev->lif_cfg.udma_count; 51f3bdbd42SAbhijit Gangurde base = size * udma_idx; 52f3bdbd42SAbhijit Gangurde bound = base + size; 53f3bdbd42SAbhijit Gangurde 54f3bdbd42SAbhijit Gangurde rc = ionic_resid_get_shared(&dev->inuse_cqid, base, bound); 55f3bdbd42SAbhijit Gangurde if (rc >= 0) { 56f3bdbd42SAbhijit Gangurde /* cq_base is zero or a multiple of two queue groups */ 57f3bdbd42SAbhijit Gangurde *cqid = dev->lif_cfg.cq_base + 58f3bdbd42SAbhijit Gangurde ionic_bitid_to_qid(rc, dev->lif_cfg.udma_qgrp_shift, 59f3bdbd42SAbhijit Gangurde dev->half_cqid_udma_shift); 60f3bdbd42SAbhijit Gangurde 61f3bdbd42SAbhijit Gangurde rc = 0; 62f3bdbd42SAbhijit Gangurde } 63f3bdbd42SAbhijit Gangurde 64f3bdbd42SAbhijit Gangurde return rc; 65f3bdbd42SAbhijit Gangurde } 66f3bdbd42SAbhijit Gangurde 67f3bdbd42SAbhijit Gangurde static void ionic_put_cqid(struct ionic_ibdev *dev, u32 cqid) 68f3bdbd42SAbhijit Gangurde { 69f3bdbd42SAbhijit Gangurde u32 bitid = ionic_qid_to_bitid(cqid - dev->lif_cfg.cq_base, 70f3bdbd42SAbhijit Gangurde dev->lif_cfg.udma_qgrp_shift, 71f3bdbd42SAbhijit Gangurde dev->half_cqid_udma_shift); 72f3bdbd42SAbhijit Gangurde 73f3bdbd42SAbhijit Gangurde ionic_resid_put(&dev->inuse_cqid, bitid); 74f3bdbd42SAbhijit Gangurde } 75f3bdbd42SAbhijit Gangurde 76f3bdbd42SAbhijit Gangurde int ionic_create_cq_common(struct ionic_vcq *vcq, 77f3bdbd42SAbhijit Gangurde struct ionic_tbl_buf *buf, 78f3bdbd42SAbhijit Gangurde const struct ib_cq_init_attr *attr, 79f3bdbd42SAbhijit Gangurde struct ionic_ctx *ctx, 80f3bdbd42SAbhijit Gangurde struct ib_udata *udata, 81f3bdbd42SAbhijit Gangurde struct ionic_qdesc *req_cq, 82f3bdbd42SAbhijit Gangurde __u32 *resp_cqid, 83f3bdbd42SAbhijit Gangurde int udma_idx) 84f3bdbd42SAbhijit Gangurde { 85f3bdbd42SAbhijit Gangurde struct ionic_ibdev *dev = to_ionic_ibdev(vcq->ibcq.device); 86f3bdbd42SAbhijit Gangurde struct ionic_cq *cq = &vcq->cq[udma_idx]; 87f3bdbd42SAbhijit Gangurde void *entry; 88f3bdbd42SAbhijit Gangurde int rc; 89f3bdbd42SAbhijit Gangurde 90f3bdbd42SAbhijit Gangurde cq->vcq = vcq; 91f3bdbd42SAbhijit Gangurde 92f3bdbd42SAbhijit Gangurde if (attr->cqe < 1 || attr->cqe + IONIC_CQ_GRACE > 0xffff) { 93f3bdbd42SAbhijit Gangurde rc = -EINVAL; 94f3bdbd42SAbhijit Gangurde goto err_args; 95f3bdbd42SAbhijit Gangurde } 96f3bdbd42SAbhijit Gangurde 97f3bdbd42SAbhijit Gangurde rc = ionic_get_cqid(dev, &cq->cqid, udma_idx); 98f3bdbd42SAbhijit Gangurde if (rc) 99f3bdbd42SAbhijit Gangurde goto err_args; 100f3bdbd42SAbhijit Gangurde 101f3bdbd42SAbhijit Gangurde cq->eqid = ionic_get_eqid(dev, attr->comp_vector, udma_idx); 102f3bdbd42SAbhijit Gangurde 103f3bdbd42SAbhijit Gangurde spin_lock_init(&cq->lock); 104f3bdbd42SAbhijit Gangurde INIT_LIST_HEAD(&cq->poll_sq); 105f3bdbd42SAbhijit Gangurde INIT_LIST_HEAD(&cq->flush_sq); 106f3bdbd42SAbhijit Gangurde INIT_LIST_HEAD(&cq->flush_rq); 107f3bdbd42SAbhijit Gangurde 108f3bdbd42SAbhijit Gangurde if (udata) { 109f3bdbd42SAbhijit Gangurde rc = ionic_validate_qdesc(req_cq); 110f3bdbd42SAbhijit Gangurde if (rc) 111f3bdbd42SAbhijit Gangurde goto err_qdesc; 112f3bdbd42SAbhijit Gangurde 113f3bdbd42SAbhijit Gangurde cq->umem = ib_umem_get(&dev->ibdev, req_cq->addr, req_cq->size, 114f3bdbd42SAbhijit Gangurde IB_ACCESS_LOCAL_WRITE); 115f3bdbd42SAbhijit Gangurde if (IS_ERR(cq->umem)) { 116f3bdbd42SAbhijit Gangurde rc = PTR_ERR(cq->umem); 117f3bdbd42SAbhijit Gangurde goto err_qdesc; 118f3bdbd42SAbhijit Gangurde } 119f3bdbd42SAbhijit Gangurde 120f3bdbd42SAbhijit Gangurde cq->q.ptr = NULL; 121f3bdbd42SAbhijit Gangurde cq->q.size = req_cq->size; 122f3bdbd42SAbhijit Gangurde cq->q.mask = req_cq->mask; 123f3bdbd42SAbhijit Gangurde cq->q.depth_log2 = req_cq->depth_log2; 124f3bdbd42SAbhijit Gangurde cq->q.stride_log2 = req_cq->stride_log2; 125f3bdbd42SAbhijit Gangurde 126f3bdbd42SAbhijit Gangurde *resp_cqid = cq->cqid; 127f3bdbd42SAbhijit Gangurde } else { 128f3bdbd42SAbhijit Gangurde rc = ionic_queue_init(&cq->q, dev->lif_cfg.hwdev, 129f3bdbd42SAbhijit Gangurde attr->cqe + IONIC_CQ_GRACE, 130f3bdbd42SAbhijit Gangurde sizeof(struct ionic_v1_cqe)); 131f3bdbd42SAbhijit Gangurde if (rc) 132f3bdbd42SAbhijit Gangurde goto err_q_init; 133f3bdbd42SAbhijit Gangurde 134f3bdbd42SAbhijit Gangurde ionic_queue_dbell_init(&cq->q, cq->cqid); 135f3bdbd42SAbhijit Gangurde cq->color = true; 136f3bdbd42SAbhijit Gangurde cq->credit = cq->q.mask; 137f3bdbd42SAbhijit Gangurde } 138f3bdbd42SAbhijit Gangurde 139f3bdbd42SAbhijit Gangurde rc = ionic_pgtbl_init(dev, buf, cq->umem, cq->q.dma, 1, PAGE_SIZE); 140f3bdbd42SAbhijit Gangurde if (rc) 141f3bdbd42SAbhijit Gangurde goto err_pgtbl_init; 142f3bdbd42SAbhijit Gangurde 143f3bdbd42SAbhijit Gangurde init_completion(&cq->cq_rel_comp); 144f3bdbd42SAbhijit Gangurde kref_init(&cq->cq_kref); 145f3bdbd42SAbhijit Gangurde 146f3bdbd42SAbhijit Gangurde entry = xa_store_irq(&dev->cq_tbl, cq->cqid, cq, GFP_KERNEL); 147f3bdbd42SAbhijit Gangurde if (entry) { 148f3bdbd42SAbhijit Gangurde if (!xa_is_err(entry)) 149f3bdbd42SAbhijit Gangurde rc = -EINVAL; 150f3bdbd42SAbhijit Gangurde else 151f3bdbd42SAbhijit Gangurde rc = xa_err(entry); 152f3bdbd42SAbhijit Gangurde 153f3bdbd42SAbhijit Gangurde goto err_xa; 154f3bdbd42SAbhijit Gangurde } 155f3bdbd42SAbhijit Gangurde 156f3bdbd42SAbhijit Gangurde return 0; 157f3bdbd42SAbhijit Gangurde 158f3bdbd42SAbhijit Gangurde err_xa: 159f3bdbd42SAbhijit Gangurde ionic_pgtbl_unbuf(dev, buf); 160f3bdbd42SAbhijit Gangurde err_pgtbl_init: 161f3bdbd42SAbhijit Gangurde if (!udata) 162f3bdbd42SAbhijit Gangurde ionic_queue_destroy(&cq->q, dev->lif_cfg.hwdev); 163f3bdbd42SAbhijit Gangurde err_q_init: 164f3bdbd42SAbhijit Gangurde if (cq->umem) 165f3bdbd42SAbhijit Gangurde ib_umem_release(cq->umem); 166f3bdbd42SAbhijit Gangurde err_qdesc: 167f3bdbd42SAbhijit Gangurde ionic_put_cqid(dev, cq->cqid); 168f3bdbd42SAbhijit Gangurde err_args: 169f3bdbd42SAbhijit Gangurde cq->vcq = NULL; 170f3bdbd42SAbhijit Gangurde 171f3bdbd42SAbhijit Gangurde return rc; 172f3bdbd42SAbhijit Gangurde } 173f3bdbd42SAbhijit Gangurde 174f3bdbd42SAbhijit Gangurde void ionic_destroy_cq_common(struct ionic_ibdev *dev, struct ionic_cq *cq) 175f3bdbd42SAbhijit Gangurde { 176f3bdbd42SAbhijit Gangurde if (!cq->vcq) 177f3bdbd42SAbhijit Gangurde return; 178f3bdbd42SAbhijit Gangurde 179f3bdbd42SAbhijit Gangurde xa_erase_irq(&dev->cq_tbl, cq->cqid); 180f3bdbd42SAbhijit Gangurde 181f3bdbd42SAbhijit Gangurde kref_put(&cq->cq_kref, ionic_cq_complete); 182f3bdbd42SAbhijit Gangurde wait_for_completion(&cq->cq_rel_comp); 183f3bdbd42SAbhijit Gangurde 184f3bdbd42SAbhijit Gangurde if (cq->umem) 185f3bdbd42SAbhijit Gangurde ib_umem_release(cq->umem); 186f3bdbd42SAbhijit Gangurde else 187f3bdbd42SAbhijit Gangurde ionic_queue_destroy(&cq->q, dev->lif_cfg.hwdev); 188f3bdbd42SAbhijit Gangurde 189f3bdbd42SAbhijit Gangurde ionic_put_cqid(dev, cq->cqid); 190f3bdbd42SAbhijit Gangurde 191f3bdbd42SAbhijit Gangurde cq->vcq = NULL; 192f3bdbd42SAbhijit Gangurde } 193*e8521822SAbhijit Gangurde 194*e8521822SAbhijit Gangurde static int ionic_validate_qdesc_zero(struct ionic_qdesc *q) 195*e8521822SAbhijit Gangurde { 196*e8521822SAbhijit Gangurde if (q->addr || q->size || q->mask || q->depth_log2 || q->stride_log2) 197*e8521822SAbhijit Gangurde return -EINVAL; 198*e8521822SAbhijit Gangurde 199*e8521822SAbhijit Gangurde return 0; 200*e8521822SAbhijit Gangurde } 201*e8521822SAbhijit Gangurde 202*e8521822SAbhijit Gangurde static int ionic_get_pdid(struct ionic_ibdev *dev, u32 *pdid) 203*e8521822SAbhijit Gangurde { 204*e8521822SAbhijit Gangurde int rc; 205*e8521822SAbhijit Gangurde 206*e8521822SAbhijit Gangurde rc = ionic_resid_get(&dev->inuse_pdid); 207*e8521822SAbhijit Gangurde if (rc < 0) 208*e8521822SAbhijit Gangurde return rc; 209*e8521822SAbhijit Gangurde 210*e8521822SAbhijit Gangurde *pdid = rc; 211*e8521822SAbhijit Gangurde return 0; 212*e8521822SAbhijit Gangurde } 213*e8521822SAbhijit Gangurde 214*e8521822SAbhijit Gangurde static int ionic_get_ahid(struct ionic_ibdev *dev, u32 *ahid) 215*e8521822SAbhijit Gangurde { 216*e8521822SAbhijit Gangurde int rc; 217*e8521822SAbhijit Gangurde 218*e8521822SAbhijit Gangurde rc = ionic_resid_get(&dev->inuse_ahid); 219*e8521822SAbhijit Gangurde if (rc < 0) 220*e8521822SAbhijit Gangurde return rc; 221*e8521822SAbhijit Gangurde 222*e8521822SAbhijit Gangurde *ahid = rc; 223*e8521822SAbhijit Gangurde return 0; 224*e8521822SAbhijit Gangurde } 225*e8521822SAbhijit Gangurde 226*e8521822SAbhijit Gangurde static int ionic_get_mrid(struct ionic_ibdev *dev, u32 *mrid) 227*e8521822SAbhijit Gangurde { 228*e8521822SAbhijit Gangurde int rc; 229*e8521822SAbhijit Gangurde 230*e8521822SAbhijit Gangurde /* wrap to 1, skip reserved lkey */ 231*e8521822SAbhijit Gangurde rc = ionic_resid_get_shared(&dev->inuse_mrid, 1, 232*e8521822SAbhijit Gangurde dev->inuse_mrid.inuse_size); 233*e8521822SAbhijit Gangurde if (rc < 0) 234*e8521822SAbhijit Gangurde return rc; 235*e8521822SAbhijit Gangurde 236*e8521822SAbhijit Gangurde *mrid = ionic_mrid(rc, dev->next_mrkey++); 237*e8521822SAbhijit Gangurde return 0; 238*e8521822SAbhijit Gangurde } 239*e8521822SAbhijit Gangurde 240*e8521822SAbhijit Gangurde static int ionic_get_gsi_qpid(struct ionic_ibdev *dev, u32 *qpid) 241*e8521822SAbhijit Gangurde { 242*e8521822SAbhijit Gangurde int rc = 0; 243*e8521822SAbhijit Gangurde 244*e8521822SAbhijit Gangurde rc = ionic_resid_get_shared(&dev->inuse_qpid, IB_QPT_GSI, IB_QPT_GSI + 1); 245*e8521822SAbhijit Gangurde if (rc < 0) 246*e8521822SAbhijit Gangurde return rc; 247*e8521822SAbhijit Gangurde 248*e8521822SAbhijit Gangurde *qpid = IB_QPT_GSI; 249*e8521822SAbhijit Gangurde return 0; 250*e8521822SAbhijit Gangurde } 251*e8521822SAbhijit Gangurde 252*e8521822SAbhijit Gangurde static int ionic_get_qpid(struct ionic_ibdev *dev, u32 *qpid, 253*e8521822SAbhijit Gangurde u8 *udma_idx, u8 udma_mask) 254*e8521822SAbhijit Gangurde { 255*e8521822SAbhijit Gangurde unsigned int size, base, bound; 256*e8521822SAbhijit Gangurde int udma_i, udma_x, udma_ix; 257*e8521822SAbhijit Gangurde int rc = -EINVAL; 258*e8521822SAbhijit Gangurde 259*e8521822SAbhijit Gangurde udma_x = dev->next_qpid_udma_idx; 260*e8521822SAbhijit Gangurde 261*e8521822SAbhijit Gangurde dev->next_qpid_udma_idx ^= dev->lif_cfg.udma_count - 1; 262*e8521822SAbhijit Gangurde 263*e8521822SAbhijit Gangurde for (udma_i = 0; udma_i < dev->lif_cfg.udma_count; ++udma_i) { 264*e8521822SAbhijit Gangurde udma_ix = udma_i ^ udma_x; 265*e8521822SAbhijit Gangurde 266*e8521822SAbhijit Gangurde if (!(udma_mask & BIT(udma_ix))) 267*e8521822SAbhijit Gangurde continue; 268*e8521822SAbhijit Gangurde 269*e8521822SAbhijit Gangurde size = dev->lif_cfg.qp_count / dev->lif_cfg.udma_count; 270*e8521822SAbhijit Gangurde base = size * udma_ix; 271*e8521822SAbhijit Gangurde bound = base + size; 272*e8521822SAbhijit Gangurde 273*e8521822SAbhijit Gangurde /* skip reserved SMI and GSI qpids in group zero */ 274*e8521822SAbhijit Gangurde if (!base) 275*e8521822SAbhijit Gangurde base = 2; 276*e8521822SAbhijit Gangurde 277*e8521822SAbhijit Gangurde rc = ionic_resid_get_shared(&dev->inuse_qpid, base, bound); 278*e8521822SAbhijit Gangurde if (rc >= 0) { 279*e8521822SAbhijit Gangurde *qpid = ionic_bitid_to_qid(rc, 280*e8521822SAbhijit Gangurde dev->lif_cfg.udma_qgrp_shift, 281*e8521822SAbhijit Gangurde dev->half_qpid_udma_shift); 282*e8521822SAbhijit Gangurde *udma_idx = udma_ix; 283*e8521822SAbhijit Gangurde 284*e8521822SAbhijit Gangurde rc = 0; 285*e8521822SAbhijit Gangurde break; 286*e8521822SAbhijit Gangurde } 287*e8521822SAbhijit Gangurde } 288*e8521822SAbhijit Gangurde 289*e8521822SAbhijit Gangurde return rc; 290*e8521822SAbhijit Gangurde } 291*e8521822SAbhijit Gangurde 292*e8521822SAbhijit Gangurde static int ionic_get_dbid(struct ionic_ibdev *dev, u32 *dbid, phys_addr_t *addr) 293*e8521822SAbhijit Gangurde { 294*e8521822SAbhijit Gangurde int rc, dbpage_num; 295*e8521822SAbhijit Gangurde 296*e8521822SAbhijit Gangurde /* wrap to 1, skip kernel reserved */ 297*e8521822SAbhijit Gangurde rc = ionic_resid_get_shared(&dev->inuse_dbid, 1, 298*e8521822SAbhijit Gangurde dev->inuse_dbid.inuse_size); 299*e8521822SAbhijit Gangurde if (rc < 0) 300*e8521822SAbhijit Gangurde return rc; 301*e8521822SAbhijit Gangurde 302*e8521822SAbhijit Gangurde dbpage_num = (dev->lif_cfg.lif_hw_index * dev->lif_cfg.dbid_count) + rc; 303*e8521822SAbhijit Gangurde *addr = dev->lif_cfg.db_phys + ((phys_addr_t)dbpage_num << PAGE_SHIFT); 304*e8521822SAbhijit Gangurde 305*e8521822SAbhijit Gangurde *dbid = rc; 306*e8521822SAbhijit Gangurde 307*e8521822SAbhijit Gangurde return 0; 308*e8521822SAbhijit Gangurde } 309*e8521822SAbhijit Gangurde 310*e8521822SAbhijit Gangurde static void ionic_put_pdid(struct ionic_ibdev *dev, u32 pdid) 311*e8521822SAbhijit Gangurde { 312*e8521822SAbhijit Gangurde ionic_resid_put(&dev->inuse_pdid, pdid); 313*e8521822SAbhijit Gangurde } 314*e8521822SAbhijit Gangurde 315*e8521822SAbhijit Gangurde static void ionic_put_ahid(struct ionic_ibdev *dev, u32 ahid) 316*e8521822SAbhijit Gangurde { 317*e8521822SAbhijit Gangurde ionic_resid_put(&dev->inuse_ahid, ahid); 318*e8521822SAbhijit Gangurde } 319*e8521822SAbhijit Gangurde 320*e8521822SAbhijit Gangurde static void ionic_put_mrid(struct ionic_ibdev *dev, u32 mrid) 321*e8521822SAbhijit Gangurde { 322*e8521822SAbhijit Gangurde ionic_resid_put(&dev->inuse_mrid, ionic_mrid_index(mrid)); 323*e8521822SAbhijit Gangurde } 324*e8521822SAbhijit Gangurde 325*e8521822SAbhijit Gangurde static void ionic_put_qpid(struct ionic_ibdev *dev, u32 qpid) 326*e8521822SAbhijit Gangurde { 327*e8521822SAbhijit Gangurde u32 bitid = ionic_qid_to_bitid(qpid, 328*e8521822SAbhijit Gangurde dev->lif_cfg.udma_qgrp_shift, 329*e8521822SAbhijit Gangurde dev->half_qpid_udma_shift); 330*e8521822SAbhijit Gangurde 331*e8521822SAbhijit Gangurde ionic_resid_put(&dev->inuse_qpid, bitid); 332*e8521822SAbhijit Gangurde } 333*e8521822SAbhijit Gangurde 334*e8521822SAbhijit Gangurde static void ionic_put_dbid(struct ionic_ibdev *dev, u32 dbid) 335*e8521822SAbhijit Gangurde { 336*e8521822SAbhijit Gangurde ionic_resid_put(&dev->inuse_dbid, dbid); 337*e8521822SAbhijit Gangurde } 338*e8521822SAbhijit Gangurde 339*e8521822SAbhijit Gangurde static struct rdma_user_mmap_entry* 340*e8521822SAbhijit Gangurde ionic_mmap_entry_insert(struct ionic_ctx *ctx, unsigned long size, 341*e8521822SAbhijit Gangurde unsigned long pfn, u8 mmap_flags, u64 *offset) 342*e8521822SAbhijit Gangurde { 343*e8521822SAbhijit Gangurde struct ionic_mmap_entry *entry; 344*e8521822SAbhijit Gangurde int rc; 345*e8521822SAbhijit Gangurde 346*e8521822SAbhijit Gangurde entry = kzalloc(sizeof(*entry), GFP_KERNEL); 347*e8521822SAbhijit Gangurde if (!entry) 348*e8521822SAbhijit Gangurde return NULL; 349*e8521822SAbhijit Gangurde 350*e8521822SAbhijit Gangurde entry->size = size; 351*e8521822SAbhijit Gangurde entry->pfn = pfn; 352*e8521822SAbhijit Gangurde entry->mmap_flags = mmap_flags; 353*e8521822SAbhijit Gangurde 354*e8521822SAbhijit Gangurde rc = rdma_user_mmap_entry_insert(&ctx->ibctx, &entry->rdma_entry, 355*e8521822SAbhijit Gangurde entry->size); 356*e8521822SAbhijit Gangurde if (rc) { 357*e8521822SAbhijit Gangurde kfree(entry); 358*e8521822SAbhijit Gangurde return NULL; 359*e8521822SAbhijit Gangurde } 360*e8521822SAbhijit Gangurde 361*e8521822SAbhijit Gangurde if (offset) 362*e8521822SAbhijit Gangurde *offset = rdma_user_mmap_get_offset(&entry->rdma_entry); 363*e8521822SAbhijit Gangurde 364*e8521822SAbhijit Gangurde return &entry->rdma_entry; 365*e8521822SAbhijit Gangurde } 366*e8521822SAbhijit Gangurde 367*e8521822SAbhijit Gangurde int ionic_alloc_ucontext(struct ib_ucontext *ibctx, struct ib_udata *udata) 368*e8521822SAbhijit Gangurde { 369*e8521822SAbhijit Gangurde struct ionic_ibdev *dev = to_ionic_ibdev(ibctx->device); 370*e8521822SAbhijit Gangurde struct ionic_ctx *ctx = to_ionic_ctx(ibctx); 371*e8521822SAbhijit Gangurde struct ionic_ctx_resp resp = {}; 372*e8521822SAbhijit Gangurde struct ionic_ctx_req req; 373*e8521822SAbhijit Gangurde phys_addr_t db_phys = 0; 374*e8521822SAbhijit Gangurde int rc; 375*e8521822SAbhijit Gangurde 376*e8521822SAbhijit Gangurde rc = ib_copy_from_udata(&req, udata, sizeof(req)); 377*e8521822SAbhijit Gangurde if (rc) 378*e8521822SAbhijit Gangurde return rc; 379*e8521822SAbhijit Gangurde 380*e8521822SAbhijit Gangurde /* try to allocate dbid for user ctx */ 381*e8521822SAbhijit Gangurde rc = ionic_get_dbid(dev, &ctx->dbid, &db_phys); 382*e8521822SAbhijit Gangurde if (rc < 0) 383*e8521822SAbhijit Gangurde return rc; 384*e8521822SAbhijit Gangurde 385*e8521822SAbhijit Gangurde ibdev_dbg(&dev->ibdev, "user space dbid %u\n", ctx->dbid); 386*e8521822SAbhijit Gangurde 387*e8521822SAbhijit Gangurde ctx->mmap_dbell = ionic_mmap_entry_insert(ctx, PAGE_SIZE, 388*e8521822SAbhijit Gangurde PHYS_PFN(db_phys), 0, NULL); 389*e8521822SAbhijit Gangurde if (!ctx->mmap_dbell) { 390*e8521822SAbhijit Gangurde rc = -ENOMEM; 391*e8521822SAbhijit Gangurde goto err_mmap_dbell; 392*e8521822SAbhijit Gangurde } 393*e8521822SAbhijit Gangurde 394*e8521822SAbhijit Gangurde resp.page_shift = PAGE_SHIFT; 395*e8521822SAbhijit Gangurde 396*e8521822SAbhijit Gangurde resp.dbell_offset = db_phys & ~PAGE_MASK; 397*e8521822SAbhijit Gangurde 398*e8521822SAbhijit Gangurde resp.version = dev->lif_cfg.rdma_version; 399*e8521822SAbhijit Gangurde resp.qp_opcodes = dev->lif_cfg.qp_opcodes; 400*e8521822SAbhijit Gangurde resp.admin_opcodes = dev->lif_cfg.admin_opcodes; 401*e8521822SAbhijit Gangurde 402*e8521822SAbhijit Gangurde resp.sq_qtype = dev->lif_cfg.sq_qtype; 403*e8521822SAbhijit Gangurde resp.rq_qtype = dev->lif_cfg.rq_qtype; 404*e8521822SAbhijit Gangurde resp.cq_qtype = dev->lif_cfg.cq_qtype; 405*e8521822SAbhijit Gangurde resp.admin_qtype = dev->lif_cfg.aq_qtype; 406*e8521822SAbhijit Gangurde resp.max_stride = dev->lif_cfg.max_stride; 407*e8521822SAbhijit Gangurde resp.max_spec = IONIC_SPEC_HIGH; 408*e8521822SAbhijit Gangurde 409*e8521822SAbhijit Gangurde resp.udma_count = dev->lif_cfg.udma_count; 410*e8521822SAbhijit Gangurde resp.expdb_mask = dev->lif_cfg.expdb_mask; 411*e8521822SAbhijit Gangurde 412*e8521822SAbhijit Gangurde if (dev->lif_cfg.sq_expdb) 413*e8521822SAbhijit Gangurde resp.expdb_qtypes |= IONIC_EXPDB_SQ; 414*e8521822SAbhijit Gangurde if (dev->lif_cfg.rq_expdb) 415*e8521822SAbhijit Gangurde resp.expdb_qtypes |= IONIC_EXPDB_RQ; 416*e8521822SAbhijit Gangurde 417*e8521822SAbhijit Gangurde rc = ib_copy_to_udata(udata, &resp, sizeof(resp)); 418*e8521822SAbhijit Gangurde if (rc) 419*e8521822SAbhijit Gangurde goto err_resp; 420*e8521822SAbhijit Gangurde 421*e8521822SAbhijit Gangurde return 0; 422*e8521822SAbhijit Gangurde 423*e8521822SAbhijit Gangurde err_resp: 424*e8521822SAbhijit Gangurde rdma_user_mmap_entry_remove(ctx->mmap_dbell); 425*e8521822SAbhijit Gangurde err_mmap_dbell: 426*e8521822SAbhijit Gangurde ionic_put_dbid(dev, ctx->dbid); 427*e8521822SAbhijit Gangurde 428*e8521822SAbhijit Gangurde return rc; 429*e8521822SAbhijit Gangurde } 430*e8521822SAbhijit Gangurde 431*e8521822SAbhijit Gangurde void ionic_dealloc_ucontext(struct ib_ucontext *ibctx) 432*e8521822SAbhijit Gangurde { 433*e8521822SAbhijit Gangurde struct ionic_ibdev *dev = to_ionic_ibdev(ibctx->device); 434*e8521822SAbhijit Gangurde struct ionic_ctx *ctx = to_ionic_ctx(ibctx); 435*e8521822SAbhijit Gangurde 436*e8521822SAbhijit Gangurde rdma_user_mmap_entry_remove(ctx->mmap_dbell); 437*e8521822SAbhijit Gangurde ionic_put_dbid(dev, ctx->dbid); 438*e8521822SAbhijit Gangurde } 439*e8521822SAbhijit Gangurde 440*e8521822SAbhijit Gangurde int ionic_mmap(struct ib_ucontext *ibctx, struct vm_area_struct *vma) 441*e8521822SAbhijit Gangurde { 442*e8521822SAbhijit Gangurde struct ionic_ibdev *dev = to_ionic_ibdev(ibctx->device); 443*e8521822SAbhijit Gangurde struct ionic_ctx *ctx = to_ionic_ctx(ibctx); 444*e8521822SAbhijit Gangurde struct rdma_user_mmap_entry *rdma_entry; 445*e8521822SAbhijit Gangurde struct ionic_mmap_entry *ionic_entry; 446*e8521822SAbhijit Gangurde int rc = 0; 447*e8521822SAbhijit Gangurde 448*e8521822SAbhijit Gangurde rdma_entry = rdma_user_mmap_entry_get(&ctx->ibctx, vma); 449*e8521822SAbhijit Gangurde if (!rdma_entry) { 450*e8521822SAbhijit Gangurde ibdev_dbg(&dev->ibdev, "not found %#lx\n", 451*e8521822SAbhijit Gangurde vma->vm_pgoff << PAGE_SHIFT); 452*e8521822SAbhijit Gangurde return -EINVAL; 453*e8521822SAbhijit Gangurde } 454*e8521822SAbhijit Gangurde 455*e8521822SAbhijit Gangurde ionic_entry = container_of(rdma_entry, struct ionic_mmap_entry, 456*e8521822SAbhijit Gangurde rdma_entry); 457*e8521822SAbhijit Gangurde 458*e8521822SAbhijit Gangurde ibdev_dbg(&dev->ibdev, "writecombine? %d\n", 459*e8521822SAbhijit Gangurde ionic_entry->mmap_flags & IONIC_MMAP_WC); 460*e8521822SAbhijit Gangurde if (ionic_entry->mmap_flags & IONIC_MMAP_WC) 461*e8521822SAbhijit Gangurde vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); 462*e8521822SAbhijit Gangurde else 463*e8521822SAbhijit Gangurde vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 464*e8521822SAbhijit Gangurde 465*e8521822SAbhijit Gangurde ibdev_dbg(&dev->ibdev, "remap st %#lx pf %#lx sz %#lx\n", 466*e8521822SAbhijit Gangurde vma->vm_start, ionic_entry->pfn, ionic_entry->size); 467*e8521822SAbhijit Gangurde rc = rdma_user_mmap_io(&ctx->ibctx, vma, ionic_entry->pfn, 468*e8521822SAbhijit Gangurde ionic_entry->size, vma->vm_page_prot, 469*e8521822SAbhijit Gangurde rdma_entry); 470*e8521822SAbhijit Gangurde if (rc) 471*e8521822SAbhijit Gangurde ibdev_dbg(&dev->ibdev, "remap failed %d\n", rc); 472*e8521822SAbhijit Gangurde 473*e8521822SAbhijit Gangurde rdma_user_mmap_entry_put(rdma_entry); 474*e8521822SAbhijit Gangurde return rc; 475*e8521822SAbhijit Gangurde } 476*e8521822SAbhijit Gangurde 477*e8521822SAbhijit Gangurde void ionic_mmap_free(struct rdma_user_mmap_entry *rdma_entry) 478*e8521822SAbhijit Gangurde { 479*e8521822SAbhijit Gangurde struct ionic_mmap_entry *ionic_entry; 480*e8521822SAbhijit Gangurde 481*e8521822SAbhijit Gangurde ionic_entry = container_of(rdma_entry, struct ionic_mmap_entry, 482*e8521822SAbhijit Gangurde rdma_entry); 483*e8521822SAbhijit Gangurde kfree(ionic_entry); 484*e8521822SAbhijit Gangurde } 485*e8521822SAbhijit Gangurde 486*e8521822SAbhijit Gangurde int ionic_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata) 487*e8521822SAbhijit Gangurde { 488*e8521822SAbhijit Gangurde struct ionic_ibdev *dev = to_ionic_ibdev(ibpd->device); 489*e8521822SAbhijit Gangurde struct ionic_pd *pd = to_ionic_pd(ibpd); 490*e8521822SAbhijit Gangurde 491*e8521822SAbhijit Gangurde return ionic_get_pdid(dev, &pd->pdid); 492*e8521822SAbhijit Gangurde } 493*e8521822SAbhijit Gangurde 494*e8521822SAbhijit Gangurde int ionic_dealloc_pd(struct ib_pd *ibpd, struct ib_udata *udata) 495*e8521822SAbhijit Gangurde { 496*e8521822SAbhijit Gangurde struct ionic_ibdev *dev = to_ionic_ibdev(ibpd->device); 497*e8521822SAbhijit Gangurde struct ionic_pd *pd = to_ionic_pd(ibpd); 498*e8521822SAbhijit Gangurde 499*e8521822SAbhijit Gangurde ionic_put_pdid(dev, pd->pdid); 500*e8521822SAbhijit Gangurde 501*e8521822SAbhijit Gangurde return 0; 502*e8521822SAbhijit Gangurde } 503*e8521822SAbhijit Gangurde 504*e8521822SAbhijit Gangurde static int ionic_build_hdr(struct ionic_ibdev *dev, 505*e8521822SAbhijit Gangurde struct ib_ud_header *hdr, 506*e8521822SAbhijit Gangurde const struct rdma_ah_attr *attr, 507*e8521822SAbhijit Gangurde u16 sport, bool want_ecn) 508*e8521822SAbhijit Gangurde { 509*e8521822SAbhijit Gangurde const struct ib_global_route *grh; 510*e8521822SAbhijit Gangurde enum rdma_network_type net; 511*e8521822SAbhijit Gangurde u16 vlan; 512*e8521822SAbhijit Gangurde int rc; 513*e8521822SAbhijit Gangurde 514*e8521822SAbhijit Gangurde if (attr->ah_flags != IB_AH_GRH) 515*e8521822SAbhijit Gangurde return -EINVAL; 516*e8521822SAbhijit Gangurde if (attr->type != RDMA_AH_ATTR_TYPE_ROCE) 517*e8521822SAbhijit Gangurde return -EINVAL; 518*e8521822SAbhijit Gangurde 519*e8521822SAbhijit Gangurde grh = rdma_ah_read_grh(attr); 520*e8521822SAbhijit Gangurde 521*e8521822SAbhijit Gangurde rc = rdma_read_gid_l2_fields(grh->sgid_attr, &vlan, &hdr->eth.smac_h[0]); 522*e8521822SAbhijit Gangurde if (rc) 523*e8521822SAbhijit Gangurde return rc; 524*e8521822SAbhijit Gangurde 525*e8521822SAbhijit Gangurde net = rdma_gid_attr_network_type(grh->sgid_attr); 526*e8521822SAbhijit Gangurde 527*e8521822SAbhijit Gangurde rc = ib_ud_header_init(0, /* no payload */ 528*e8521822SAbhijit Gangurde 0, /* no lrh */ 529*e8521822SAbhijit Gangurde 1, /* yes eth */ 530*e8521822SAbhijit Gangurde vlan != 0xffff, 531*e8521822SAbhijit Gangurde 0, /* no grh */ 532*e8521822SAbhijit Gangurde net == RDMA_NETWORK_IPV4 ? 4 : 6, 533*e8521822SAbhijit Gangurde 1, /* yes udp */ 534*e8521822SAbhijit Gangurde 0, /* no imm */ 535*e8521822SAbhijit Gangurde hdr); 536*e8521822SAbhijit Gangurde if (rc) 537*e8521822SAbhijit Gangurde return rc; 538*e8521822SAbhijit Gangurde 539*e8521822SAbhijit Gangurde ether_addr_copy(hdr->eth.dmac_h, attr->roce.dmac); 540*e8521822SAbhijit Gangurde 541*e8521822SAbhijit Gangurde if (net == RDMA_NETWORK_IPV4) { 542*e8521822SAbhijit Gangurde hdr->eth.type = cpu_to_be16(ETH_P_IP); 543*e8521822SAbhijit Gangurde hdr->ip4.frag_off = cpu_to_be16(0x4000); /* don't fragment */ 544*e8521822SAbhijit Gangurde hdr->ip4.ttl = grh->hop_limit; 545*e8521822SAbhijit Gangurde hdr->ip4.tot_len = cpu_to_be16(0xffff); 546*e8521822SAbhijit Gangurde hdr->ip4.saddr = 547*e8521822SAbhijit Gangurde *(const __be32 *)(grh->sgid_attr->gid.raw + 12); 548*e8521822SAbhijit Gangurde hdr->ip4.daddr = *(const __be32 *)(grh->dgid.raw + 12); 549*e8521822SAbhijit Gangurde 550*e8521822SAbhijit Gangurde if (want_ecn) 551*e8521822SAbhijit Gangurde hdr->ip4.tos = ionic_set_ecn(grh->traffic_class); 552*e8521822SAbhijit Gangurde else 553*e8521822SAbhijit Gangurde hdr->ip4.tos = ionic_clear_ecn(grh->traffic_class); 554*e8521822SAbhijit Gangurde } else { 555*e8521822SAbhijit Gangurde hdr->eth.type = cpu_to_be16(ETH_P_IPV6); 556*e8521822SAbhijit Gangurde hdr->grh.flow_label = cpu_to_be32(grh->flow_label); 557*e8521822SAbhijit Gangurde hdr->grh.hop_limit = grh->hop_limit; 558*e8521822SAbhijit Gangurde hdr->grh.source_gid = grh->sgid_attr->gid; 559*e8521822SAbhijit Gangurde hdr->grh.destination_gid = grh->dgid; 560*e8521822SAbhijit Gangurde 561*e8521822SAbhijit Gangurde if (want_ecn) 562*e8521822SAbhijit Gangurde hdr->grh.traffic_class = 563*e8521822SAbhijit Gangurde ionic_set_ecn(grh->traffic_class); 564*e8521822SAbhijit Gangurde else 565*e8521822SAbhijit Gangurde hdr->grh.traffic_class = 566*e8521822SAbhijit Gangurde ionic_clear_ecn(grh->traffic_class); 567*e8521822SAbhijit Gangurde } 568*e8521822SAbhijit Gangurde 569*e8521822SAbhijit Gangurde if (vlan != 0xffff) { 570*e8521822SAbhijit Gangurde vlan |= rdma_ah_get_sl(attr) << VLAN_PRIO_SHIFT; 571*e8521822SAbhijit Gangurde hdr->vlan.tag = cpu_to_be16(vlan); 572*e8521822SAbhijit Gangurde hdr->vlan.type = hdr->eth.type; 573*e8521822SAbhijit Gangurde hdr->eth.type = cpu_to_be16(ETH_P_8021Q); 574*e8521822SAbhijit Gangurde } 575*e8521822SAbhijit Gangurde 576*e8521822SAbhijit Gangurde hdr->udp.sport = cpu_to_be16(sport); 577*e8521822SAbhijit Gangurde hdr->udp.dport = cpu_to_be16(ROCE_V2_UDP_DPORT); 578*e8521822SAbhijit Gangurde 579*e8521822SAbhijit Gangurde return 0; 580*e8521822SAbhijit Gangurde } 581*e8521822SAbhijit Gangurde 582*e8521822SAbhijit Gangurde static void ionic_set_ah_attr(struct ionic_ibdev *dev, 583*e8521822SAbhijit Gangurde struct rdma_ah_attr *ah_attr, 584*e8521822SAbhijit Gangurde struct ib_ud_header *hdr, 585*e8521822SAbhijit Gangurde int sgid_index) 586*e8521822SAbhijit Gangurde { 587*e8521822SAbhijit Gangurde u32 flow_label; 588*e8521822SAbhijit Gangurde u16 vlan = 0; 589*e8521822SAbhijit Gangurde u8 tos, ttl; 590*e8521822SAbhijit Gangurde 591*e8521822SAbhijit Gangurde if (hdr->vlan_present) 592*e8521822SAbhijit Gangurde vlan = be16_to_cpu(hdr->vlan.tag); 593*e8521822SAbhijit Gangurde 594*e8521822SAbhijit Gangurde if (hdr->ipv4_present) { 595*e8521822SAbhijit Gangurde flow_label = 0; 596*e8521822SAbhijit Gangurde ttl = hdr->ip4.ttl; 597*e8521822SAbhijit Gangurde tos = hdr->ip4.tos; 598*e8521822SAbhijit Gangurde *(__be16 *)(hdr->grh.destination_gid.raw + 10) = cpu_to_be16(0xffff); 599*e8521822SAbhijit Gangurde *(__be32 *)(hdr->grh.destination_gid.raw + 12) = hdr->ip4.daddr; 600*e8521822SAbhijit Gangurde } else { 601*e8521822SAbhijit Gangurde flow_label = be32_to_cpu(hdr->grh.flow_label); 602*e8521822SAbhijit Gangurde ttl = hdr->grh.hop_limit; 603*e8521822SAbhijit Gangurde tos = hdr->grh.traffic_class; 604*e8521822SAbhijit Gangurde } 605*e8521822SAbhijit Gangurde 606*e8521822SAbhijit Gangurde memset(ah_attr, 0, sizeof(*ah_attr)); 607*e8521822SAbhijit Gangurde ah_attr->type = RDMA_AH_ATTR_TYPE_ROCE; 608*e8521822SAbhijit Gangurde if (hdr->eth_present) 609*e8521822SAbhijit Gangurde memcpy(&ah_attr->roce.dmac, &hdr->eth.dmac_h, ETH_ALEN); 610*e8521822SAbhijit Gangurde rdma_ah_set_sl(ah_attr, vlan >> VLAN_PRIO_SHIFT); 611*e8521822SAbhijit Gangurde rdma_ah_set_port_num(ah_attr, 1); 612*e8521822SAbhijit Gangurde rdma_ah_set_grh(ah_attr, NULL, flow_label, sgid_index, ttl, tos); 613*e8521822SAbhijit Gangurde rdma_ah_set_dgid_raw(ah_attr, &hdr->grh.destination_gid); 614*e8521822SAbhijit Gangurde } 615*e8521822SAbhijit Gangurde 616*e8521822SAbhijit Gangurde static int ionic_create_ah_cmd(struct ionic_ibdev *dev, 617*e8521822SAbhijit Gangurde struct ionic_ah *ah, 618*e8521822SAbhijit Gangurde struct ionic_pd *pd, 619*e8521822SAbhijit Gangurde struct rdma_ah_attr *attr, 620*e8521822SAbhijit Gangurde u32 flags) 621*e8521822SAbhijit Gangurde { 622*e8521822SAbhijit Gangurde struct ionic_admin_wr wr = { 623*e8521822SAbhijit Gangurde .work = COMPLETION_INITIALIZER_ONSTACK(wr.work), 624*e8521822SAbhijit Gangurde .wqe = { 625*e8521822SAbhijit Gangurde .op = IONIC_V1_ADMIN_CREATE_AH, 626*e8521822SAbhijit Gangurde .len = cpu_to_le16(IONIC_ADMIN_CREATE_AH_IN_V1_LEN), 627*e8521822SAbhijit Gangurde .cmd.create_ah = { 628*e8521822SAbhijit Gangurde .pd_id = cpu_to_le32(pd->pdid), 629*e8521822SAbhijit Gangurde .dbid_flags = cpu_to_le16(dev->lif_cfg.dbid), 630*e8521822SAbhijit Gangurde .id_ver = cpu_to_le32(ah->ahid), 631*e8521822SAbhijit Gangurde } 632*e8521822SAbhijit Gangurde } 633*e8521822SAbhijit Gangurde }; 634*e8521822SAbhijit Gangurde enum ionic_admin_flags admin_flags = 0; 635*e8521822SAbhijit Gangurde dma_addr_t hdr_dma = 0; 636*e8521822SAbhijit Gangurde void *hdr_buf; 637*e8521822SAbhijit Gangurde gfp_t gfp = GFP_ATOMIC; 638*e8521822SAbhijit Gangurde int rc, hdr_len = 0; 639*e8521822SAbhijit Gangurde 640*e8521822SAbhijit Gangurde if (dev->lif_cfg.admin_opcodes <= IONIC_V1_ADMIN_CREATE_AH) 641*e8521822SAbhijit Gangurde return -EBADRQC; 642*e8521822SAbhijit Gangurde 643*e8521822SAbhijit Gangurde if (flags & RDMA_CREATE_AH_SLEEPABLE) 644*e8521822SAbhijit Gangurde gfp = GFP_KERNEL; 645*e8521822SAbhijit Gangurde else 646*e8521822SAbhijit Gangurde admin_flags |= IONIC_ADMIN_F_BUSYWAIT; 647*e8521822SAbhijit Gangurde 648*e8521822SAbhijit Gangurde rc = ionic_build_hdr(dev, &ah->hdr, attr, IONIC_ROCE_UDP_SPORT, false); 649*e8521822SAbhijit Gangurde if (rc) 650*e8521822SAbhijit Gangurde return rc; 651*e8521822SAbhijit Gangurde 652*e8521822SAbhijit Gangurde if (ah->hdr.eth.type == cpu_to_be16(ETH_P_8021Q)) { 653*e8521822SAbhijit Gangurde if (ah->hdr.vlan.type == cpu_to_be16(ETH_P_IP)) 654*e8521822SAbhijit Gangurde wr.wqe.cmd.create_ah.csum_profile = 655*e8521822SAbhijit Gangurde IONIC_TFP_CSUM_PROF_ETH_QTAG_IPV4_UDP; 656*e8521822SAbhijit Gangurde else 657*e8521822SAbhijit Gangurde wr.wqe.cmd.create_ah.csum_profile = 658*e8521822SAbhijit Gangurde IONIC_TFP_CSUM_PROF_ETH_QTAG_IPV6_UDP; 659*e8521822SAbhijit Gangurde } else { 660*e8521822SAbhijit Gangurde if (ah->hdr.eth.type == cpu_to_be16(ETH_P_IP)) 661*e8521822SAbhijit Gangurde wr.wqe.cmd.create_ah.csum_profile = 662*e8521822SAbhijit Gangurde IONIC_TFP_CSUM_PROF_ETH_IPV4_UDP; 663*e8521822SAbhijit Gangurde else 664*e8521822SAbhijit Gangurde wr.wqe.cmd.create_ah.csum_profile = 665*e8521822SAbhijit Gangurde IONIC_TFP_CSUM_PROF_ETH_IPV6_UDP; 666*e8521822SAbhijit Gangurde } 667*e8521822SAbhijit Gangurde 668*e8521822SAbhijit Gangurde ah->sgid_index = rdma_ah_read_grh(attr)->sgid_index; 669*e8521822SAbhijit Gangurde 670*e8521822SAbhijit Gangurde hdr_buf = kmalloc(PAGE_SIZE, gfp); 671*e8521822SAbhijit Gangurde if (!hdr_buf) 672*e8521822SAbhijit Gangurde return -ENOMEM; 673*e8521822SAbhijit Gangurde 674*e8521822SAbhijit Gangurde hdr_len = ib_ud_header_pack(&ah->hdr, hdr_buf); 675*e8521822SAbhijit Gangurde hdr_len -= IB_BTH_BYTES; 676*e8521822SAbhijit Gangurde hdr_len -= IB_DETH_BYTES; 677*e8521822SAbhijit Gangurde ibdev_dbg(&dev->ibdev, "roce packet header template\n"); 678*e8521822SAbhijit Gangurde print_hex_dump_debug("hdr ", DUMP_PREFIX_OFFSET, 16, 1, 679*e8521822SAbhijit Gangurde hdr_buf, hdr_len, true); 680*e8521822SAbhijit Gangurde 681*e8521822SAbhijit Gangurde hdr_dma = dma_map_single(dev->lif_cfg.hwdev, hdr_buf, hdr_len, 682*e8521822SAbhijit Gangurde DMA_TO_DEVICE); 683*e8521822SAbhijit Gangurde 684*e8521822SAbhijit Gangurde rc = dma_mapping_error(dev->lif_cfg.hwdev, hdr_dma); 685*e8521822SAbhijit Gangurde if (rc) 686*e8521822SAbhijit Gangurde goto err_dma; 687*e8521822SAbhijit Gangurde 688*e8521822SAbhijit Gangurde wr.wqe.cmd.create_ah.dma_addr = cpu_to_le64(hdr_dma); 689*e8521822SAbhijit Gangurde wr.wqe.cmd.create_ah.length = cpu_to_le32(hdr_len); 690*e8521822SAbhijit Gangurde 691*e8521822SAbhijit Gangurde ionic_admin_post(dev, &wr); 692*e8521822SAbhijit Gangurde rc = ionic_admin_wait(dev, &wr, admin_flags); 693*e8521822SAbhijit Gangurde 694*e8521822SAbhijit Gangurde dma_unmap_single(dev->lif_cfg.hwdev, hdr_dma, hdr_len, 695*e8521822SAbhijit Gangurde DMA_TO_DEVICE); 696*e8521822SAbhijit Gangurde err_dma: 697*e8521822SAbhijit Gangurde kfree(hdr_buf); 698*e8521822SAbhijit Gangurde 699*e8521822SAbhijit Gangurde return rc; 700*e8521822SAbhijit Gangurde } 701*e8521822SAbhijit Gangurde 702*e8521822SAbhijit Gangurde static int ionic_destroy_ah_cmd(struct ionic_ibdev *dev, u32 ahid, u32 flags) 703*e8521822SAbhijit Gangurde { 704*e8521822SAbhijit Gangurde struct ionic_admin_wr wr = { 705*e8521822SAbhijit Gangurde .work = COMPLETION_INITIALIZER_ONSTACK(wr.work), 706*e8521822SAbhijit Gangurde .wqe = { 707*e8521822SAbhijit Gangurde .op = IONIC_V1_ADMIN_DESTROY_AH, 708*e8521822SAbhijit Gangurde .len = cpu_to_le16(IONIC_ADMIN_DESTROY_AH_IN_V1_LEN), 709*e8521822SAbhijit Gangurde .cmd.destroy_ah = { 710*e8521822SAbhijit Gangurde .ah_id = cpu_to_le32(ahid), 711*e8521822SAbhijit Gangurde }, 712*e8521822SAbhijit Gangurde } 713*e8521822SAbhijit Gangurde }; 714*e8521822SAbhijit Gangurde enum ionic_admin_flags admin_flags = IONIC_ADMIN_F_TEARDOWN; 715*e8521822SAbhijit Gangurde 716*e8521822SAbhijit Gangurde if (dev->lif_cfg.admin_opcodes <= IONIC_V1_ADMIN_DESTROY_AH) 717*e8521822SAbhijit Gangurde return -EBADRQC; 718*e8521822SAbhijit Gangurde 719*e8521822SAbhijit Gangurde if (!(flags & RDMA_CREATE_AH_SLEEPABLE)) 720*e8521822SAbhijit Gangurde admin_flags |= IONIC_ADMIN_F_BUSYWAIT; 721*e8521822SAbhijit Gangurde 722*e8521822SAbhijit Gangurde ionic_admin_post(dev, &wr); 723*e8521822SAbhijit Gangurde ionic_admin_wait(dev, &wr, admin_flags); 724*e8521822SAbhijit Gangurde 725*e8521822SAbhijit Gangurde /* No host-memory resource is associated with ah, so it is ok 726*e8521822SAbhijit Gangurde * to "succeed" and complete this destroy ah on the host. 727*e8521822SAbhijit Gangurde */ 728*e8521822SAbhijit Gangurde return 0; 729*e8521822SAbhijit Gangurde } 730*e8521822SAbhijit Gangurde 731*e8521822SAbhijit Gangurde int ionic_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr, 732*e8521822SAbhijit Gangurde struct ib_udata *udata) 733*e8521822SAbhijit Gangurde { 734*e8521822SAbhijit Gangurde struct ionic_ibdev *dev = to_ionic_ibdev(ibah->device); 735*e8521822SAbhijit Gangurde struct rdma_ah_attr *attr = init_attr->ah_attr; 736*e8521822SAbhijit Gangurde struct ionic_pd *pd = to_ionic_pd(ibah->pd); 737*e8521822SAbhijit Gangurde struct ionic_ah *ah = to_ionic_ah(ibah); 738*e8521822SAbhijit Gangurde struct ionic_ah_resp resp = {}; 739*e8521822SAbhijit Gangurde u32 flags = init_attr->flags; 740*e8521822SAbhijit Gangurde int rc; 741*e8521822SAbhijit Gangurde 742*e8521822SAbhijit Gangurde rc = ionic_get_ahid(dev, &ah->ahid); 743*e8521822SAbhijit Gangurde if (rc) 744*e8521822SAbhijit Gangurde return rc; 745*e8521822SAbhijit Gangurde 746*e8521822SAbhijit Gangurde rc = ionic_create_ah_cmd(dev, ah, pd, attr, flags); 747*e8521822SAbhijit Gangurde if (rc) 748*e8521822SAbhijit Gangurde goto err_cmd; 749*e8521822SAbhijit Gangurde 750*e8521822SAbhijit Gangurde if (udata) { 751*e8521822SAbhijit Gangurde resp.ahid = ah->ahid; 752*e8521822SAbhijit Gangurde 753*e8521822SAbhijit Gangurde rc = ib_copy_to_udata(udata, &resp, sizeof(resp)); 754*e8521822SAbhijit Gangurde if (rc) 755*e8521822SAbhijit Gangurde goto err_resp; 756*e8521822SAbhijit Gangurde } 757*e8521822SAbhijit Gangurde 758*e8521822SAbhijit Gangurde return 0; 759*e8521822SAbhijit Gangurde 760*e8521822SAbhijit Gangurde err_resp: 761*e8521822SAbhijit Gangurde ionic_destroy_ah_cmd(dev, ah->ahid, flags); 762*e8521822SAbhijit Gangurde err_cmd: 763*e8521822SAbhijit Gangurde ionic_put_ahid(dev, ah->ahid); 764*e8521822SAbhijit Gangurde return rc; 765*e8521822SAbhijit Gangurde } 766*e8521822SAbhijit Gangurde 767*e8521822SAbhijit Gangurde int ionic_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr) 768*e8521822SAbhijit Gangurde { 769*e8521822SAbhijit Gangurde struct ionic_ibdev *dev = to_ionic_ibdev(ibah->device); 770*e8521822SAbhijit Gangurde struct ionic_ah *ah = to_ionic_ah(ibah); 771*e8521822SAbhijit Gangurde 772*e8521822SAbhijit Gangurde ionic_set_ah_attr(dev, ah_attr, &ah->hdr, ah->sgid_index); 773*e8521822SAbhijit Gangurde 774*e8521822SAbhijit Gangurde return 0; 775*e8521822SAbhijit Gangurde } 776*e8521822SAbhijit Gangurde 777*e8521822SAbhijit Gangurde int ionic_destroy_ah(struct ib_ah *ibah, u32 flags) 778*e8521822SAbhijit Gangurde { 779*e8521822SAbhijit Gangurde struct ionic_ibdev *dev = to_ionic_ibdev(ibah->device); 780*e8521822SAbhijit Gangurde struct ionic_ah *ah = to_ionic_ah(ibah); 781*e8521822SAbhijit Gangurde int rc; 782*e8521822SAbhijit Gangurde 783*e8521822SAbhijit Gangurde rc = ionic_destroy_ah_cmd(dev, ah->ahid, flags); 784*e8521822SAbhijit Gangurde if (rc) 785*e8521822SAbhijit Gangurde return rc; 786*e8521822SAbhijit Gangurde 787*e8521822SAbhijit Gangurde ionic_put_ahid(dev, ah->ahid); 788*e8521822SAbhijit Gangurde 789*e8521822SAbhijit Gangurde return 0; 790*e8521822SAbhijit Gangurde } 791*e8521822SAbhijit Gangurde 792*e8521822SAbhijit Gangurde static int ionic_create_mr_cmd(struct ionic_ibdev *dev, 793*e8521822SAbhijit Gangurde struct ionic_pd *pd, 794*e8521822SAbhijit Gangurde struct ionic_mr *mr, 795*e8521822SAbhijit Gangurde u64 addr, 796*e8521822SAbhijit Gangurde u64 length) 797*e8521822SAbhijit Gangurde { 798*e8521822SAbhijit Gangurde struct ionic_admin_wr wr = { 799*e8521822SAbhijit Gangurde .work = COMPLETION_INITIALIZER_ONSTACK(wr.work), 800*e8521822SAbhijit Gangurde .wqe = { 801*e8521822SAbhijit Gangurde .op = IONIC_V1_ADMIN_CREATE_MR, 802*e8521822SAbhijit Gangurde .len = cpu_to_le16(IONIC_ADMIN_CREATE_MR_IN_V1_LEN), 803*e8521822SAbhijit Gangurde .cmd.create_mr = { 804*e8521822SAbhijit Gangurde .va = cpu_to_le64(addr), 805*e8521822SAbhijit Gangurde .length = cpu_to_le64(length), 806*e8521822SAbhijit Gangurde .pd_id = cpu_to_le32(pd->pdid), 807*e8521822SAbhijit Gangurde .page_size_log2 = mr->buf.page_size_log2, 808*e8521822SAbhijit Gangurde .tbl_index = cpu_to_le32(~0), 809*e8521822SAbhijit Gangurde .map_count = cpu_to_le32(mr->buf.tbl_pages), 810*e8521822SAbhijit Gangurde .dma_addr = ionic_pgtbl_dma(&mr->buf, addr), 811*e8521822SAbhijit Gangurde .dbid_flags = cpu_to_le16(mr->flags), 812*e8521822SAbhijit Gangurde .id_ver = cpu_to_le32(mr->mrid), 813*e8521822SAbhijit Gangurde } 814*e8521822SAbhijit Gangurde } 815*e8521822SAbhijit Gangurde }; 816*e8521822SAbhijit Gangurde int rc; 817*e8521822SAbhijit Gangurde 818*e8521822SAbhijit Gangurde if (dev->lif_cfg.admin_opcodes <= IONIC_V1_ADMIN_CREATE_MR) 819*e8521822SAbhijit Gangurde return -EBADRQC; 820*e8521822SAbhijit Gangurde 821*e8521822SAbhijit Gangurde ionic_admin_post(dev, &wr); 822*e8521822SAbhijit Gangurde rc = ionic_admin_wait(dev, &wr, 0); 823*e8521822SAbhijit Gangurde if (!rc) 824*e8521822SAbhijit Gangurde mr->created = true; 825*e8521822SAbhijit Gangurde 826*e8521822SAbhijit Gangurde return rc; 827*e8521822SAbhijit Gangurde } 828*e8521822SAbhijit Gangurde 829*e8521822SAbhijit Gangurde static int ionic_destroy_mr_cmd(struct ionic_ibdev *dev, u32 mrid) 830*e8521822SAbhijit Gangurde { 831*e8521822SAbhijit Gangurde struct ionic_admin_wr wr = { 832*e8521822SAbhijit Gangurde .work = COMPLETION_INITIALIZER_ONSTACK(wr.work), 833*e8521822SAbhijit Gangurde .wqe = { 834*e8521822SAbhijit Gangurde .op = IONIC_V1_ADMIN_DESTROY_MR, 835*e8521822SAbhijit Gangurde .len = cpu_to_le16(IONIC_ADMIN_DESTROY_MR_IN_V1_LEN), 836*e8521822SAbhijit Gangurde .cmd.destroy_mr = { 837*e8521822SAbhijit Gangurde .mr_id = cpu_to_le32(mrid), 838*e8521822SAbhijit Gangurde }, 839*e8521822SAbhijit Gangurde } 840*e8521822SAbhijit Gangurde }; 841*e8521822SAbhijit Gangurde 842*e8521822SAbhijit Gangurde if (dev->lif_cfg.admin_opcodes <= IONIC_V1_ADMIN_DESTROY_MR) 843*e8521822SAbhijit Gangurde return -EBADRQC; 844*e8521822SAbhijit Gangurde 845*e8521822SAbhijit Gangurde ionic_admin_post(dev, &wr); 846*e8521822SAbhijit Gangurde 847*e8521822SAbhijit Gangurde return ionic_admin_wait(dev, &wr, IONIC_ADMIN_F_TEARDOWN); 848*e8521822SAbhijit Gangurde } 849*e8521822SAbhijit Gangurde 850*e8521822SAbhijit Gangurde struct ib_mr *ionic_get_dma_mr(struct ib_pd *ibpd, int access) 851*e8521822SAbhijit Gangurde { 852*e8521822SAbhijit Gangurde struct ionic_pd *pd = to_ionic_pd(ibpd); 853*e8521822SAbhijit Gangurde struct ionic_mr *mr; 854*e8521822SAbhijit Gangurde 855*e8521822SAbhijit Gangurde mr = kzalloc(sizeof(*mr), GFP_KERNEL); 856*e8521822SAbhijit Gangurde if (!mr) 857*e8521822SAbhijit Gangurde return ERR_PTR(-ENOMEM); 858*e8521822SAbhijit Gangurde 859*e8521822SAbhijit Gangurde mr->ibmr.lkey = IONIC_DMA_LKEY; 860*e8521822SAbhijit Gangurde mr->ibmr.rkey = IONIC_DMA_RKEY; 861*e8521822SAbhijit Gangurde 862*e8521822SAbhijit Gangurde if (pd) 863*e8521822SAbhijit Gangurde pd->flags |= IONIC_QPF_PRIVILEGED; 864*e8521822SAbhijit Gangurde 865*e8521822SAbhijit Gangurde return &mr->ibmr; 866*e8521822SAbhijit Gangurde } 867*e8521822SAbhijit Gangurde 868*e8521822SAbhijit Gangurde struct ib_mr *ionic_reg_user_mr(struct ib_pd *ibpd, u64 start, u64 length, 869*e8521822SAbhijit Gangurde u64 addr, int access, struct ib_dmah *dmah, 870*e8521822SAbhijit Gangurde struct ib_udata *udata) 871*e8521822SAbhijit Gangurde { 872*e8521822SAbhijit Gangurde struct ionic_ibdev *dev = to_ionic_ibdev(ibpd->device); 873*e8521822SAbhijit Gangurde struct ionic_pd *pd = to_ionic_pd(ibpd); 874*e8521822SAbhijit Gangurde struct ionic_mr *mr; 875*e8521822SAbhijit Gangurde unsigned long pg_sz; 876*e8521822SAbhijit Gangurde int rc; 877*e8521822SAbhijit Gangurde 878*e8521822SAbhijit Gangurde if (dmah) 879*e8521822SAbhijit Gangurde return ERR_PTR(-EOPNOTSUPP); 880*e8521822SAbhijit Gangurde 881*e8521822SAbhijit Gangurde mr = kzalloc(sizeof(*mr), GFP_KERNEL); 882*e8521822SAbhijit Gangurde if (!mr) 883*e8521822SAbhijit Gangurde return ERR_PTR(-ENOMEM); 884*e8521822SAbhijit Gangurde 885*e8521822SAbhijit Gangurde rc = ionic_get_mrid(dev, &mr->mrid); 886*e8521822SAbhijit Gangurde if (rc) 887*e8521822SAbhijit Gangurde goto err_mrid; 888*e8521822SAbhijit Gangurde 889*e8521822SAbhijit Gangurde mr->ibmr.lkey = mr->mrid; 890*e8521822SAbhijit Gangurde mr->ibmr.rkey = mr->mrid; 891*e8521822SAbhijit Gangurde mr->ibmr.iova = addr; 892*e8521822SAbhijit Gangurde mr->ibmr.length = length; 893*e8521822SAbhijit Gangurde 894*e8521822SAbhijit Gangurde mr->flags = IONIC_MRF_USER_MR | to_ionic_mr_flags(access); 895*e8521822SAbhijit Gangurde 896*e8521822SAbhijit Gangurde mr->umem = ib_umem_get(&dev->ibdev, start, length, access); 897*e8521822SAbhijit Gangurde if (IS_ERR(mr->umem)) { 898*e8521822SAbhijit Gangurde rc = PTR_ERR(mr->umem); 899*e8521822SAbhijit Gangurde goto err_umem; 900*e8521822SAbhijit Gangurde } 901*e8521822SAbhijit Gangurde 902*e8521822SAbhijit Gangurde pg_sz = ib_umem_find_best_pgsz(mr->umem, 903*e8521822SAbhijit Gangurde dev->lif_cfg.page_size_supported, 904*e8521822SAbhijit Gangurde addr); 905*e8521822SAbhijit Gangurde if (!pg_sz) { 906*e8521822SAbhijit Gangurde rc = -EINVAL; 907*e8521822SAbhijit Gangurde goto err_pgtbl; 908*e8521822SAbhijit Gangurde } 909*e8521822SAbhijit Gangurde 910*e8521822SAbhijit Gangurde rc = ionic_pgtbl_init(dev, &mr->buf, mr->umem, 0, 1, pg_sz); 911*e8521822SAbhijit Gangurde if (rc) 912*e8521822SAbhijit Gangurde goto err_pgtbl; 913*e8521822SAbhijit Gangurde 914*e8521822SAbhijit Gangurde rc = ionic_create_mr_cmd(dev, pd, mr, addr, length); 915*e8521822SAbhijit Gangurde if (rc) 916*e8521822SAbhijit Gangurde goto err_cmd; 917*e8521822SAbhijit Gangurde 918*e8521822SAbhijit Gangurde ionic_pgtbl_unbuf(dev, &mr->buf); 919*e8521822SAbhijit Gangurde 920*e8521822SAbhijit Gangurde return &mr->ibmr; 921*e8521822SAbhijit Gangurde 922*e8521822SAbhijit Gangurde err_cmd: 923*e8521822SAbhijit Gangurde ionic_pgtbl_unbuf(dev, &mr->buf); 924*e8521822SAbhijit Gangurde err_pgtbl: 925*e8521822SAbhijit Gangurde ib_umem_release(mr->umem); 926*e8521822SAbhijit Gangurde err_umem: 927*e8521822SAbhijit Gangurde ionic_put_mrid(dev, mr->mrid); 928*e8521822SAbhijit Gangurde err_mrid: 929*e8521822SAbhijit Gangurde kfree(mr); 930*e8521822SAbhijit Gangurde return ERR_PTR(rc); 931*e8521822SAbhijit Gangurde } 932*e8521822SAbhijit Gangurde 933*e8521822SAbhijit Gangurde struct ib_mr *ionic_reg_user_mr_dmabuf(struct ib_pd *ibpd, u64 offset, 934*e8521822SAbhijit Gangurde u64 length, u64 addr, int fd, int access, 935*e8521822SAbhijit Gangurde struct ib_dmah *dmah, 936*e8521822SAbhijit Gangurde struct uverbs_attr_bundle *attrs) 937*e8521822SAbhijit Gangurde { 938*e8521822SAbhijit Gangurde struct ionic_ibdev *dev = to_ionic_ibdev(ibpd->device); 939*e8521822SAbhijit Gangurde struct ionic_pd *pd = to_ionic_pd(ibpd); 940*e8521822SAbhijit Gangurde struct ib_umem_dmabuf *umem_dmabuf; 941*e8521822SAbhijit Gangurde struct ionic_mr *mr; 942*e8521822SAbhijit Gangurde u64 pg_sz; 943*e8521822SAbhijit Gangurde int rc; 944*e8521822SAbhijit Gangurde 945*e8521822SAbhijit Gangurde if (dmah) 946*e8521822SAbhijit Gangurde return ERR_PTR(-EOPNOTSUPP); 947*e8521822SAbhijit Gangurde 948*e8521822SAbhijit Gangurde mr = kzalloc(sizeof(*mr), GFP_KERNEL); 949*e8521822SAbhijit Gangurde if (!mr) 950*e8521822SAbhijit Gangurde return ERR_PTR(-ENOMEM); 951*e8521822SAbhijit Gangurde 952*e8521822SAbhijit Gangurde rc = ionic_get_mrid(dev, &mr->mrid); 953*e8521822SAbhijit Gangurde if (rc) 954*e8521822SAbhijit Gangurde goto err_mrid; 955*e8521822SAbhijit Gangurde 956*e8521822SAbhijit Gangurde mr->ibmr.lkey = mr->mrid; 957*e8521822SAbhijit Gangurde mr->ibmr.rkey = mr->mrid; 958*e8521822SAbhijit Gangurde mr->ibmr.iova = addr; 959*e8521822SAbhijit Gangurde mr->ibmr.length = length; 960*e8521822SAbhijit Gangurde 961*e8521822SAbhijit Gangurde mr->flags = IONIC_MRF_USER_MR | to_ionic_mr_flags(access); 962*e8521822SAbhijit Gangurde 963*e8521822SAbhijit Gangurde umem_dmabuf = ib_umem_dmabuf_get_pinned(&dev->ibdev, offset, length, 964*e8521822SAbhijit Gangurde fd, access); 965*e8521822SAbhijit Gangurde if (IS_ERR(umem_dmabuf)) { 966*e8521822SAbhijit Gangurde rc = PTR_ERR(umem_dmabuf); 967*e8521822SAbhijit Gangurde goto err_umem; 968*e8521822SAbhijit Gangurde } 969*e8521822SAbhijit Gangurde 970*e8521822SAbhijit Gangurde mr->umem = &umem_dmabuf->umem; 971*e8521822SAbhijit Gangurde 972*e8521822SAbhijit Gangurde pg_sz = ib_umem_find_best_pgsz(mr->umem, 973*e8521822SAbhijit Gangurde dev->lif_cfg.page_size_supported, 974*e8521822SAbhijit Gangurde addr); 975*e8521822SAbhijit Gangurde if (!pg_sz) { 976*e8521822SAbhijit Gangurde rc = -EINVAL; 977*e8521822SAbhijit Gangurde goto err_pgtbl; 978*e8521822SAbhijit Gangurde } 979*e8521822SAbhijit Gangurde 980*e8521822SAbhijit Gangurde rc = ionic_pgtbl_init(dev, &mr->buf, mr->umem, 0, 1, pg_sz); 981*e8521822SAbhijit Gangurde if (rc) 982*e8521822SAbhijit Gangurde goto err_pgtbl; 983*e8521822SAbhijit Gangurde 984*e8521822SAbhijit Gangurde rc = ionic_create_mr_cmd(dev, pd, mr, addr, length); 985*e8521822SAbhijit Gangurde if (rc) 986*e8521822SAbhijit Gangurde goto err_cmd; 987*e8521822SAbhijit Gangurde 988*e8521822SAbhijit Gangurde ionic_pgtbl_unbuf(dev, &mr->buf); 989*e8521822SAbhijit Gangurde 990*e8521822SAbhijit Gangurde return &mr->ibmr; 991*e8521822SAbhijit Gangurde 992*e8521822SAbhijit Gangurde err_cmd: 993*e8521822SAbhijit Gangurde ionic_pgtbl_unbuf(dev, &mr->buf); 994*e8521822SAbhijit Gangurde err_pgtbl: 995*e8521822SAbhijit Gangurde ib_umem_release(mr->umem); 996*e8521822SAbhijit Gangurde err_umem: 997*e8521822SAbhijit Gangurde ionic_put_mrid(dev, mr->mrid); 998*e8521822SAbhijit Gangurde err_mrid: 999*e8521822SAbhijit Gangurde kfree(mr); 1000*e8521822SAbhijit Gangurde return ERR_PTR(rc); 1001*e8521822SAbhijit Gangurde } 1002*e8521822SAbhijit Gangurde 1003*e8521822SAbhijit Gangurde int ionic_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata) 1004*e8521822SAbhijit Gangurde { 1005*e8521822SAbhijit Gangurde struct ionic_ibdev *dev = to_ionic_ibdev(ibmr->device); 1006*e8521822SAbhijit Gangurde struct ionic_mr *mr = to_ionic_mr(ibmr); 1007*e8521822SAbhijit Gangurde int rc; 1008*e8521822SAbhijit Gangurde 1009*e8521822SAbhijit Gangurde if (!mr->ibmr.lkey) 1010*e8521822SAbhijit Gangurde goto out; 1011*e8521822SAbhijit Gangurde 1012*e8521822SAbhijit Gangurde if (mr->created) { 1013*e8521822SAbhijit Gangurde rc = ionic_destroy_mr_cmd(dev, mr->mrid); 1014*e8521822SAbhijit Gangurde if (rc) 1015*e8521822SAbhijit Gangurde return rc; 1016*e8521822SAbhijit Gangurde } 1017*e8521822SAbhijit Gangurde 1018*e8521822SAbhijit Gangurde ionic_pgtbl_unbuf(dev, &mr->buf); 1019*e8521822SAbhijit Gangurde 1020*e8521822SAbhijit Gangurde if (mr->umem) 1021*e8521822SAbhijit Gangurde ib_umem_release(mr->umem); 1022*e8521822SAbhijit Gangurde 1023*e8521822SAbhijit Gangurde ionic_put_mrid(dev, mr->mrid); 1024*e8521822SAbhijit Gangurde 1025*e8521822SAbhijit Gangurde out: 1026*e8521822SAbhijit Gangurde kfree(mr); 1027*e8521822SAbhijit Gangurde 1028*e8521822SAbhijit Gangurde return 0; 1029*e8521822SAbhijit Gangurde } 1030*e8521822SAbhijit Gangurde 1031*e8521822SAbhijit Gangurde struct ib_mr *ionic_alloc_mr(struct ib_pd *ibpd, enum ib_mr_type type, 1032*e8521822SAbhijit Gangurde u32 max_sg) 1033*e8521822SAbhijit Gangurde { 1034*e8521822SAbhijit Gangurde struct ionic_ibdev *dev = to_ionic_ibdev(ibpd->device); 1035*e8521822SAbhijit Gangurde struct ionic_pd *pd = to_ionic_pd(ibpd); 1036*e8521822SAbhijit Gangurde struct ionic_mr *mr; 1037*e8521822SAbhijit Gangurde int rc; 1038*e8521822SAbhijit Gangurde 1039*e8521822SAbhijit Gangurde if (type != IB_MR_TYPE_MEM_REG) 1040*e8521822SAbhijit Gangurde return ERR_PTR(-EINVAL); 1041*e8521822SAbhijit Gangurde 1042*e8521822SAbhijit Gangurde mr = kzalloc(sizeof(*mr), GFP_KERNEL); 1043*e8521822SAbhijit Gangurde if (!mr) 1044*e8521822SAbhijit Gangurde return ERR_PTR(-ENOMEM); 1045*e8521822SAbhijit Gangurde 1046*e8521822SAbhijit Gangurde rc = ionic_get_mrid(dev, &mr->mrid); 1047*e8521822SAbhijit Gangurde if (rc) 1048*e8521822SAbhijit Gangurde goto err_mrid; 1049*e8521822SAbhijit Gangurde 1050*e8521822SAbhijit Gangurde mr->ibmr.lkey = mr->mrid; 1051*e8521822SAbhijit Gangurde mr->ibmr.rkey = mr->mrid; 1052*e8521822SAbhijit Gangurde 1053*e8521822SAbhijit Gangurde mr->flags = IONIC_MRF_PHYS_MR; 1054*e8521822SAbhijit Gangurde 1055*e8521822SAbhijit Gangurde rc = ionic_pgtbl_init(dev, &mr->buf, mr->umem, 0, max_sg, PAGE_SIZE); 1056*e8521822SAbhijit Gangurde if (rc) 1057*e8521822SAbhijit Gangurde goto err_pgtbl; 1058*e8521822SAbhijit Gangurde 1059*e8521822SAbhijit Gangurde mr->buf.tbl_pages = 0; 1060*e8521822SAbhijit Gangurde 1061*e8521822SAbhijit Gangurde rc = ionic_create_mr_cmd(dev, pd, mr, 0, 0); 1062*e8521822SAbhijit Gangurde if (rc) 1063*e8521822SAbhijit Gangurde goto err_cmd; 1064*e8521822SAbhijit Gangurde 1065*e8521822SAbhijit Gangurde return &mr->ibmr; 1066*e8521822SAbhijit Gangurde 1067*e8521822SAbhijit Gangurde err_cmd: 1068*e8521822SAbhijit Gangurde ionic_pgtbl_unbuf(dev, &mr->buf); 1069*e8521822SAbhijit Gangurde err_pgtbl: 1070*e8521822SAbhijit Gangurde ionic_put_mrid(dev, mr->mrid); 1071*e8521822SAbhijit Gangurde err_mrid: 1072*e8521822SAbhijit Gangurde kfree(mr); 1073*e8521822SAbhijit Gangurde return ERR_PTR(rc); 1074*e8521822SAbhijit Gangurde } 1075*e8521822SAbhijit Gangurde 1076*e8521822SAbhijit Gangurde static int ionic_map_mr_page(struct ib_mr *ibmr, u64 dma) 1077*e8521822SAbhijit Gangurde { 1078*e8521822SAbhijit Gangurde struct ionic_ibdev *dev = to_ionic_ibdev(ibmr->device); 1079*e8521822SAbhijit Gangurde struct ionic_mr *mr = to_ionic_mr(ibmr); 1080*e8521822SAbhijit Gangurde 1081*e8521822SAbhijit Gangurde ibdev_dbg(&dev->ibdev, "dma %p\n", (void *)dma); 1082*e8521822SAbhijit Gangurde return ionic_pgtbl_page(&mr->buf, dma); 1083*e8521822SAbhijit Gangurde } 1084*e8521822SAbhijit Gangurde 1085*e8521822SAbhijit Gangurde int ionic_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents, 1086*e8521822SAbhijit Gangurde unsigned int *sg_offset) 1087*e8521822SAbhijit Gangurde { 1088*e8521822SAbhijit Gangurde struct ionic_ibdev *dev = to_ionic_ibdev(ibmr->device); 1089*e8521822SAbhijit Gangurde struct ionic_mr *mr = to_ionic_mr(ibmr); 1090*e8521822SAbhijit Gangurde int rc; 1091*e8521822SAbhijit Gangurde 1092*e8521822SAbhijit Gangurde /* mr must be allocated using ib_alloc_mr() */ 1093*e8521822SAbhijit Gangurde if (unlikely(!mr->buf.tbl_limit)) 1094*e8521822SAbhijit Gangurde return -EINVAL; 1095*e8521822SAbhijit Gangurde 1096*e8521822SAbhijit Gangurde mr->buf.tbl_pages = 0; 1097*e8521822SAbhijit Gangurde 1098*e8521822SAbhijit Gangurde if (mr->buf.tbl_buf) 1099*e8521822SAbhijit Gangurde dma_sync_single_for_cpu(dev->lif_cfg.hwdev, mr->buf.tbl_dma, 1100*e8521822SAbhijit Gangurde mr->buf.tbl_size, DMA_TO_DEVICE); 1101*e8521822SAbhijit Gangurde 1102*e8521822SAbhijit Gangurde ibdev_dbg(&dev->ibdev, "sg %p nent %d\n", sg, sg_nents); 1103*e8521822SAbhijit Gangurde rc = ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset, ionic_map_mr_page); 1104*e8521822SAbhijit Gangurde 1105*e8521822SAbhijit Gangurde mr->buf.page_size_log2 = order_base_2(ibmr->page_size); 1106*e8521822SAbhijit Gangurde 1107*e8521822SAbhijit Gangurde if (mr->buf.tbl_buf) 1108*e8521822SAbhijit Gangurde dma_sync_single_for_device(dev->lif_cfg.hwdev, mr->buf.tbl_dma, 1109*e8521822SAbhijit Gangurde mr->buf.tbl_size, DMA_TO_DEVICE); 1110*e8521822SAbhijit Gangurde 1111*e8521822SAbhijit Gangurde return rc; 1112*e8521822SAbhijit Gangurde } 1113*e8521822SAbhijit Gangurde 1114*e8521822SAbhijit Gangurde int ionic_alloc_mw(struct ib_mw *ibmw, struct ib_udata *udata) 1115*e8521822SAbhijit Gangurde { 1116*e8521822SAbhijit Gangurde struct ionic_ibdev *dev = to_ionic_ibdev(ibmw->device); 1117*e8521822SAbhijit Gangurde struct ionic_pd *pd = to_ionic_pd(ibmw->pd); 1118*e8521822SAbhijit Gangurde struct ionic_mr *mr = to_ionic_mw(ibmw); 1119*e8521822SAbhijit Gangurde int rc; 1120*e8521822SAbhijit Gangurde 1121*e8521822SAbhijit Gangurde rc = ionic_get_mrid(dev, &mr->mrid); 1122*e8521822SAbhijit Gangurde if (rc) 1123*e8521822SAbhijit Gangurde return rc; 1124*e8521822SAbhijit Gangurde 1125*e8521822SAbhijit Gangurde mr->ibmw.rkey = mr->mrid; 1126*e8521822SAbhijit Gangurde 1127*e8521822SAbhijit Gangurde if (mr->ibmw.type == IB_MW_TYPE_1) 1128*e8521822SAbhijit Gangurde mr->flags = IONIC_MRF_MW_1; 1129*e8521822SAbhijit Gangurde else 1130*e8521822SAbhijit Gangurde mr->flags = IONIC_MRF_MW_2; 1131*e8521822SAbhijit Gangurde 1132*e8521822SAbhijit Gangurde rc = ionic_create_mr_cmd(dev, pd, mr, 0, 0); 1133*e8521822SAbhijit Gangurde if (rc) 1134*e8521822SAbhijit Gangurde goto err_cmd; 1135*e8521822SAbhijit Gangurde 1136*e8521822SAbhijit Gangurde return 0; 1137*e8521822SAbhijit Gangurde 1138*e8521822SAbhijit Gangurde err_cmd: 1139*e8521822SAbhijit Gangurde ionic_put_mrid(dev, mr->mrid); 1140*e8521822SAbhijit Gangurde return rc; 1141*e8521822SAbhijit Gangurde } 1142*e8521822SAbhijit Gangurde 1143*e8521822SAbhijit Gangurde int ionic_dealloc_mw(struct ib_mw *ibmw) 1144*e8521822SAbhijit Gangurde { 1145*e8521822SAbhijit Gangurde struct ionic_ibdev *dev = to_ionic_ibdev(ibmw->device); 1146*e8521822SAbhijit Gangurde struct ionic_mr *mr = to_ionic_mw(ibmw); 1147*e8521822SAbhijit Gangurde int rc; 1148*e8521822SAbhijit Gangurde 1149*e8521822SAbhijit Gangurde rc = ionic_destroy_mr_cmd(dev, mr->mrid); 1150*e8521822SAbhijit Gangurde if (rc) 1151*e8521822SAbhijit Gangurde return rc; 1152*e8521822SAbhijit Gangurde 1153*e8521822SAbhijit Gangurde ionic_put_mrid(dev, mr->mrid); 1154*e8521822SAbhijit Gangurde 1155*e8521822SAbhijit Gangurde return 0; 1156*e8521822SAbhijit Gangurde } 1157*e8521822SAbhijit Gangurde 1158*e8521822SAbhijit Gangurde static int ionic_create_cq_cmd(struct ionic_ibdev *dev, 1159*e8521822SAbhijit Gangurde struct ionic_ctx *ctx, 1160*e8521822SAbhijit Gangurde struct ionic_cq *cq, 1161*e8521822SAbhijit Gangurde struct ionic_tbl_buf *buf) 1162*e8521822SAbhijit Gangurde { 1163*e8521822SAbhijit Gangurde const u16 dbid = ionic_ctx_dbid(dev, ctx); 1164*e8521822SAbhijit Gangurde struct ionic_admin_wr wr = { 1165*e8521822SAbhijit Gangurde .work = COMPLETION_INITIALIZER_ONSTACK(wr.work), 1166*e8521822SAbhijit Gangurde .wqe = { 1167*e8521822SAbhijit Gangurde .op = IONIC_V1_ADMIN_CREATE_CQ, 1168*e8521822SAbhijit Gangurde .len = cpu_to_le16(IONIC_ADMIN_CREATE_CQ_IN_V1_LEN), 1169*e8521822SAbhijit Gangurde .cmd.create_cq = { 1170*e8521822SAbhijit Gangurde .eq_id = cpu_to_le32(cq->eqid), 1171*e8521822SAbhijit Gangurde .depth_log2 = cq->q.depth_log2, 1172*e8521822SAbhijit Gangurde .stride_log2 = cq->q.stride_log2, 1173*e8521822SAbhijit Gangurde .page_size_log2 = buf->page_size_log2, 1174*e8521822SAbhijit Gangurde .tbl_index = cpu_to_le32(~0), 1175*e8521822SAbhijit Gangurde .map_count = cpu_to_le32(buf->tbl_pages), 1176*e8521822SAbhijit Gangurde .dma_addr = ionic_pgtbl_dma(buf, 0), 1177*e8521822SAbhijit Gangurde .dbid_flags = cpu_to_le16(dbid), 1178*e8521822SAbhijit Gangurde .id_ver = cpu_to_le32(cq->cqid), 1179*e8521822SAbhijit Gangurde } 1180*e8521822SAbhijit Gangurde } 1181*e8521822SAbhijit Gangurde }; 1182*e8521822SAbhijit Gangurde 1183*e8521822SAbhijit Gangurde if (dev->lif_cfg.admin_opcodes <= IONIC_V1_ADMIN_CREATE_CQ) 1184*e8521822SAbhijit Gangurde return -EBADRQC; 1185*e8521822SAbhijit Gangurde 1186*e8521822SAbhijit Gangurde ionic_admin_post(dev, &wr); 1187*e8521822SAbhijit Gangurde 1188*e8521822SAbhijit Gangurde return ionic_admin_wait(dev, &wr, 0); 1189*e8521822SAbhijit Gangurde } 1190*e8521822SAbhijit Gangurde 1191*e8521822SAbhijit Gangurde static int ionic_destroy_cq_cmd(struct ionic_ibdev *dev, u32 cqid) 1192*e8521822SAbhijit Gangurde { 1193*e8521822SAbhijit Gangurde struct ionic_admin_wr wr = { 1194*e8521822SAbhijit Gangurde .work = COMPLETION_INITIALIZER_ONSTACK(wr.work), 1195*e8521822SAbhijit Gangurde .wqe = { 1196*e8521822SAbhijit Gangurde .op = IONIC_V1_ADMIN_DESTROY_CQ, 1197*e8521822SAbhijit Gangurde .len = cpu_to_le16(IONIC_ADMIN_DESTROY_CQ_IN_V1_LEN), 1198*e8521822SAbhijit Gangurde .cmd.destroy_cq = { 1199*e8521822SAbhijit Gangurde .cq_id = cpu_to_le32(cqid), 1200*e8521822SAbhijit Gangurde }, 1201*e8521822SAbhijit Gangurde } 1202*e8521822SAbhijit Gangurde }; 1203*e8521822SAbhijit Gangurde 1204*e8521822SAbhijit Gangurde if (dev->lif_cfg.admin_opcodes <= IONIC_V1_ADMIN_DESTROY_CQ) 1205*e8521822SAbhijit Gangurde return -EBADRQC; 1206*e8521822SAbhijit Gangurde 1207*e8521822SAbhijit Gangurde ionic_admin_post(dev, &wr); 1208*e8521822SAbhijit Gangurde 1209*e8521822SAbhijit Gangurde return ionic_admin_wait(dev, &wr, IONIC_ADMIN_F_TEARDOWN); 1210*e8521822SAbhijit Gangurde } 1211*e8521822SAbhijit Gangurde 1212*e8521822SAbhijit Gangurde int ionic_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr, 1213*e8521822SAbhijit Gangurde struct uverbs_attr_bundle *attrs) 1214*e8521822SAbhijit Gangurde { 1215*e8521822SAbhijit Gangurde struct ionic_ibdev *dev = to_ionic_ibdev(ibcq->device); 1216*e8521822SAbhijit Gangurde struct ib_udata *udata = &attrs->driver_udata; 1217*e8521822SAbhijit Gangurde struct ionic_ctx *ctx = 1218*e8521822SAbhijit Gangurde rdma_udata_to_drv_context(udata, struct ionic_ctx, ibctx); 1219*e8521822SAbhijit Gangurde struct ionic_vcq *vcq = to_ionic_vcq(ibcq); 1220*e8521822SAbhijit Gangurde struct ionic_tbl_buf buf = {}; 1221*e8521822SAbhijit Gangurde struct ionic_cq_resp resp; 1222*e8521822SAbhijit Gangurde struct ionic_cq_req req; 1223*e8521822SAbhijit Gangurde int udma_idx = 0, rc; 1224*e8521822SAbhijit Gangurde 1225*e8521822SAbhijit Gangurde if (udata) { 1226*e8521822SAbhijit Gangurde rc = ib_copy_from_udata(&req, udata, sizeof(req)); 1227*e8521822SAbhijit Gangurde if (rc) 1228*e8521822SAbhijit Gangurde return rc; 1229*e8521822SAbhijit Gangurde } 1230*e8521822SAbhijit Gangurde 1231*e8521822SAbhijit Gangurde vcq->udma_mask = BIT(dev->lif_cfg.udma_count) - 1; 1232*e8521822SAbhijit Gangurde 1233*e8521822SAbhijit Gangurde if (udata) 1234*e8521822SAbhijit Gangurde vcq->udma_mask &= req.udma_mask; 1235*e8521822SAbhijit Gangurde 1236*e8521822SAbhijit Gangurde if (!vcq->udma_mask) { 1237*e8521822SAbhijit Gangurde rc = -EINVAL; 1238*e8521822SAbhijit Gangurde goto err_init; 1239*e8521822SAbhijit Gangurde } 1240*e8521822SAbhijit Gangurde 1241*e8521822SAbhijit Gangurde for (; udma_idx < dev->lif_cfg.udma_count; ++udma_idx) { 1242*e8521822SAbhijit Gangurde if (!(vcq->udma_mask & BIT(udma_idx))) 1243*e8521822SAbhijit Gangurde continue; 1244*e8521822SAbhijit Gangurde 1245*e8521822SAbhijit Gangurde rc = ionic_create_cq_common(vcq, &buf, attr, ctx, udata, 1246*e8521822SAbhijit Gangurde &req.cq[udma_idx], 1247*e8521822SAbhijit Gangurde &resp.cqid[udma_idx], 1248*e8521822SAbhijit Gangurde udma_idx); 1249*e8521822SAbhijit Gangurde if (rc) 1250*e8521822SAbhijit Gangurde goto err_init; 1251*e8521822SAbhijit Gangurde 1252*e8521822SAbhijit Gangurde rc = ionic_create_cq_cmd(dev, ctx, &vcq->cq[udma_idx], &buf); 1253*e8521822SAbhijit Gangurde if (rc) 1254*e8521822SAbhijit Gangurde goto err_cmd; 1255*e8521822SAbhijit Gangurde 1256*e8521822SAbhijit Gangurde ionic_pgtbl_unbuf(dev, &buf); 1257*e8521822SAbhijit Gangurde } 1258*e8521822SAbhijit Gangurde 1259*e8521822SAbhijit Gangurde vcq->ibcq.cqe = attr->cqe; 1260*e8521822SAbhijit Gangurde 1261*e8521822SAbhijit Gangurde if (udata) { 1262*e8521822SAbhijit Gangurde resp.udma_mask = vcq->udma_mask; 1263*e8521822SAbhijit Gangurde 1264*e8521822SAbhijit Gangurde rc = ib_copy_to_udata(udata, &resp, sizeof(resp)); 1265*e8521822SAbhijit Gangurde if (rc) 1266*e8521822SAbhijit Gangurde goto err_resp; 1267*e8521822SAbhijit Gangurde } 1268*e8521822SAbhijit Gangurde 1269*e8521822SAbhijit Gangurde return 0; 1270*e8521822SAbhijit Gangurde 1271*e8521822SAbhijit Gangurde err_resp: 1272*e8521822SAbhijit Gangurde while (udma_idx) { 1273*e8521822SAbhijit Gangurde --udma_idx; 1274*e8521822SAbhijit Gangurde if (!(vcq->udma_mask & BIT(udma_idx))) 1275*e8521822SAbhijit Gangurde continue; 1276*e8521822SAbhijit Gangurde ionic_destroy_cq_cmd(dev, vcq->cq[udma_idx].cqid); 1277*e8521822SAbhijit Gangurde err_cmd: 1278*e8521822SAbhijit Gangurde ionic_pgtbl_unbuf(dev, &buf); 1279*e8521822SAbhijit Gangurde ionic_destroy_cq_common(dev, &vcq->cq[udma_idx]); 1280*e8521822SAbhijit Gangurde err_init: 1281*e8521822SAbhijit Gangurde ; 1282*e8521822SAbhijit Gangurde } 1283*e8521822SAbhijit Gangurde 1284*e8521822SAbhijit Gangurde return rc; 1285*e8521822SAbhijit Gangurde } 1286*e8521822SAbhijit Gangurde 1287*e8521822SAbhijit Gangurde int ionic_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata) 1288*e8521822SAbhijit Gangurde { 1289*e8521822SAbhijit Gangurde struct ionic_ibdev *dev = to_ionic_ibdev(ibcq->device); 1290*e8521822SAbhijit Gangurde struct ionic_vcq *vcq = to_ionic_vcq(ibcq); 1291*e8521822SAbhijit Gangurde int udma_idx, rc_tmp, rc = 0; 1292*e8521822SAbhijit Gangurde 1293*e8521822SAbhijit Gangurde for (udma_idx = dev->lif_cfg.udma_count; udma_idx; ) { 1294*e8521822SAbhijit Gangurde --udma_idx; 1295*e8521822SAbhijit Gangurde 1296*e8521822SAbhijit Gangurde if (!(vcq->udma_mask & BIT(udma_idx))) 1297*e8521822SAbhijit Gangurde continue; 1298*e8521822SAbhijit Gangurde 1299*e8521822SAbhijit Gangurde rc_tmp = ionic_destroy_cq_cmd(dev, vcq->cq[udma_idx].cqid); 1300*e8521822SAbhijit Gangurde if (rc_tmp) { 1301*e8521822SAbhijit Gangurde if (!rc) 1302*e8521822SAbhijit Gangurde rc = rc_tmp; 1303*e8521822SAbhijit Gangurde 1304*e8521822SAbhijit Gangurde continue; 1305*e8521822SAbhijit Gangurde } 1306*e8521822SAbhijit Gangurde 1307*e8521822SAbhijit Gangurde ionic_destroy_cq_common(dev, &vcq->cq[udma_idx]); 1308*e8521822SAbhijit Gangurde } 1309*e8521822SAbhijit Gangurde 1310*e8521822SAbhijit Gangurde return rc; 1311*e8521822SAbhijit Gangurde } 1312*e8521822SAbhijit Gangurde 1313*e8521822SAbhijit Gangurde static bool pd_remote_privileged(struct ib_pd *pd) 1314*e8521822SAbhijit Gangurde { 1315*e8521822SAbhijit Gangurde return pd->flags & IB_PD_UNSAFE_GLOBAL_RKEY; 1316*e8521822SAbhijit Gangurde } 1317*e8521822SAbhijit Gangurde 1318*e8521822SAbhijit Gangurde static int ionic_create_qp_cmd(struct ionic_ibdev *dev, 1319*e8521822SAbhijit Gangurde struct ionic_pd *pd, 1320*e8521822SAbhijit Gangurde struct ionic_cq *send_cq, 1321*e8521822SAbhijit Gangurde struct ionic_cq *recv_cq, 1322*e8521822SAbhijit Gangurde struct ionic_qp *qp, 1323*e8521822SAbhijit Gangurde struct ionic_tbl_buf *sq_buf, 1324*e8521822SAbhijit Gangurde struct ionic_tbl_buf *rq_buf, 1325*e8521822SAbhijit Gangurde struct ib_qp_init_attr *attr) 1326*e8521822SAbhijit Gangurde { 1327*e8521822SAbhijit Gangurde const u16 dbid = ionic_obj_dbid(dev, pd->ibpd.uobject); 1328*e8521822SAbhijit Gangurde const u32 flags = to_ionic_qp_flags(0, 0, 1329*e8521822SAbhijit Gangurde qp->sq_cmb & IONIC_CMB_ENABLE, 1330*e8521822SAbhijit Gangurde qp->rq_cmb & IONIC_CMB_ENABLE, 1331*e8521822SAbhijit Gangurde qp->sq_spec, qp->rq_spec, 1332*e8521822SAbhijit Gangurde pd->flags & IONIC_QPF_PRIVILEGED, 1333*e8521822SAbhijit Gangurde pd_remote_privileged(&pd->ibpd)); 1334*e8521822SAbhijit Gangurde struct ionic_admin_wr wr = { 1335*e8521822SAbhijit Gangurde .work = COMPLETION_INITIALIZER_ONSTACK(wr.work), 1336*e8521822SAbhijit Gangurde .wqe = { 1337*e8521822SAbhijit Gangurde .op = IONIC_V1_ADMIN_CREATE_QP, 1338*e8521822SAbhijit Gangurde .len = cpu_to_le16(IONIC_ADMIN_CREATE_QP_IN_V1_LEN), 1339*e8521822SAbhijit Gangurde .cmd.create_qp = { 1340*e8521822SAbhijit Gangurde .pd_id = cpu_to_le32(pd->pdid), 1341*e8521822SAbhijit Gangurde .priv_flags = cpu_to_be32(flags), 1342*e8521822SAbhijit Gangurde .type_state = to_ionic_qp_type(attr->qp_type), 1343*e8521822SAbhijit Gangurde .dbid_flags = cpu_to_le16(dbid), 1344*e8521822SAbhijit Gangurde .id_ver = cpu_to_le32(qp->qpid), 1345*e8521822SAbhijit Gangurde } 1346*e8521822SAbhijit Gangurde } 1347*e8521822SAbhijit Gangurde }; 1348*e8521822SAbhijit Gangurde 1349*e8521822SAbhijit Gangurde if (dev->lif_cfg.admin_opcodes <= IONIC_V1_ADMIN_CREATE_QP) 1350*e8521822SAbhijit Gangurde return -EBADRQC; 1351*e8521822SAbhijit Gangurde 1352*e8521822SAbhijit Gangurde if (qp->has_sq) { 1353*e8521822SAbhijit Gangurde wr.wqe.cmd.create_qp.sq_cq_id = cpu_to_le32(send_cq->cqid); 1354*e8521822SAbhijit Gangurde wr.wqe.cmd.create_qp.sq_depth_log2 = qp->sq.depth_log2; 1355*e8521822SAbhijit Gangurde wr.wqe.cmd.create_qp.sq_stride_log2 = qp->sq.stride_log2; 1356*e8521822SAbhijit Gangurde wr.wqe.cmd.create_qp.sq_page_size_log2 = sq_buf->page_size_log2; 1357*e8521822SAbhijit Gangurde wr.wqe.cmd.create_qp.sq_tbl_index_xrcd_id = cpu_to_le32(~0); 1358*e8521822SAbhijit Gangurde wr.wqe.cmd.create_qp.sq_map_count = 1359*e8521822SAbhijit Gangurde cpu_to_le32(sq_buf->tbl_pages); 1360*e8521822SAbhijit Gangurde wr.wqe.cmd.create_qp.sq_dma_addr = ionic_pgtbl_dma(sq_buf, 0); 1361*e8521822SAbhijit Gangurde } 1362*e8521822SAbhijit Gangurde 1363*e8521822SAbhijit Gangurde if (qp->has_rq) { 1364*e8521822SAbhijit Gangurde wr.wqe.cmd.create_qp.rq_cq_id = cpu_to_le32(recv_cq->cqid); 1365*e8521822SAbhijit Gangurde wr.wqe.cmd.create_qp.rq_depth_log2 = qp->rq.depth_log2; 1366*e8521822SAbhijit Gangurde wr.wqe.cmd.create_qp.rq_stride_log2 = qp->rq.stride_log2; 1367*e8521822SAbhijit Gangurde wr.wqe.cmd.create_qp.rq_page_size_log2 = rq_buf->page_size_log2; 1368*e8521822SAbhijit Gangurde wr.wqe.cmd.create_qp.rq_tbl_index_srq_id = cpu_to_le32(~0); 1369*e8521822SAbhijit Gangurde wr.wqe.cmd.create_qp.rq_map_count = 1370*e8521822SAbhijit Gangurde cpu_to_le32(rq_buf->tbl_pages); 1371*e8521822SAbhijit Gangurde wr.wqe.cmd.create_qp.rq_dma_addr = ionic_pgtbl_dma(rq_buf, 0); 1372*e8521822SAbhijit Gangurde } 1373*e8521822SAbhijit Gangurde 1374*e8521822SAbhijit Gangurde ionic_admin_post(dev, &wr); 1375*e8521822SAbhijit Gangurde 1376*e8521822SAbhijit Gangurde return ionic_admin_wait(dev, &wr, 0); 1377*e8521822SAbhijit Gangurde } 1378*e8521822SAbhijit Gangurde 1379*e8521822SAbhijit Gangurde static int ionic_modify_qp_cmd(struct ionic_ibdev *dev, 1380*e8521822SAbhijit Gangurde struct ionic_pd *pd, 1381*e8521822SAbhijit Gangurde struct ionic_qp *qp, 1382*e8521822SAbhijit Gangurde struct ib_qp_attr *attr, 1383*e8521822SAbhijit Gangurde int mask) 1384*e8521822SAbhijit Gangurde { 1385*e8521822SAbhijit Gangurde const u32 flags = to_ionic_qp_flags(attr->qp_access_flags, 1386*e8521822SAbhijit Gangurde attr->en_sqd_async_notify, 1387*e8521822SAbhijit Gangurde qp->sq_cmb & IONIC_CMB_ENABLE, 1388*e8521822SAbhijit Gangurde qp->rq_cmb & IONIC_CMB_ENABLE, 1389*e8521822SAbhijit Gangurde qp->sq_spec, qp->rq_spec, 1390*e8521822SAbhijit Gangurde pd->flags & IONIC_QPF_PRIVILEGED, 1391*e8521822SAbhijit Gangurde pd_remote_privileged(qp->ibqp.pd)); 1392*e8521822SAbhijit Gangurde const u8 state = to_ionic_qp_modify_state(attr->qp_state, 1393*e8521822SAbhijit Gangurde attr->cur_qp_state); 1394*e8521822SAbhijit Gangurde struct ionic_admin_wr wr = { 1395*e8521822SAbhijit Gangurde .work = COMPLETION_INITIALIZER_ONSTACK(wr.work), 1396*e8521822SAbhijit Gangurde .wqe = { 1397*e8521822SAbhijit Gangurde .op = IONIC_V1_ADMIN_MODIFY_QP, 1398*e8521822SAbhijit Gangurde .len = cpu_to_le16(IONIC_ADMIN_MODIFY_QP_IN_V1_LEN), 1399*e8521822SAbhijit Gangurde .cmd.mod_qp = { 1400*e8521822SAbhijit Gangurde .attr_mask = cpu_to_be32(mask), 1401*e8521822SAbhijit Gangurde .access_flags = cpu_to_be16(flags), 1402*e8521822SAbhijit Gangurde .rq_psn = cpu_to_le32(attr->rq_psn), 1403*e8521822SAbhijit Gangurde .sq_psn = cpu_to_le32(attr->sq_psn), 1404*e8521822SAbhijit Gangurde .rate_limit_kbps = 1405*e8521822SAbhijit Gangurde cpu_to_le32(attr->rate_limit), 1406*e8521822SAbhijit Gangurde .pmtu = (attr->path_mtu + 7), 1407*e8521822SAbhijit Gangurde .retry = (attr->retry_cnt | 1408*e8521822SAbhijit Gangurde (attr->rnr_retry << 4)), 1409*e8521822SAbhijit Gangurde .rnr_timer = attr->min_rnr_timer, 1410*e8521822SAbhijit Gangurde .retry_timeout = attr->timeout, 1411*e8521822SAbhijit Gangurde .type_state = state, 1412*e8521822SAbhijit Gangurde .id_ver = cpu_to_le32(qp->qpid), 1413*e8521822SAbhijit Gangurde } 1414*e8521822SAbhijit Gangurde } 1415*e8521822SAbhijit Gangurde }; 1416*e8521822SAbhijit Gangurde const struct ib_global_route *grh = rdma_ah_read_grh(&attr->ah_attr); 1417*e8521822SAbhijit Gangurde void *hdr_buf = NULL; 1418*e8521822SAbhijit Gangurde dma_addr_t hdr_dma = 0; 1419*e8521822SAbhijit Gangurde int rc, hdr_len = 0; 1420*e8521822SAbhijit Gangurde u16 sport; 1421*e8521822SAbhijit Gangurde 1422*e8521822SAbhijit Gangurde if (dev->lif_cfg.admin_opcodes <= IONIC_V1_ADMIN_MODIFY_QP) 1423*e8521822SAbhijit Gangurde return -EBADRQC; 1424*e8521822SAbhijit Gangurde 1425*e8521822SAbhijit Gangurde if ((mask & IB_QP_MAX_DEST_RD_ATOMIC) && attr->max_dest_rd_atomic) { 1426*e8521822SAbhijit Gangurde /* Note, round up/down was already done for allocating 1427*e8521822SAbhijit Gangurde * resources on the device. The allocation order is in cache 1428*e8521822SAbhijit Gangurde * line size. We can't use the order of the resource 1429*e8521822SAbhijit Gangurde * allocation to determine the order wqes here, because for 1430*e8521822SAbhijit Gangurde * queue length <= one cache line it is not distinct. 1431*e8521822SAbhijit Gangurde * 1432*e8521822SAbhijit Gangurde * Therefore, order wqes is computed again here. 1433*e8521822SAbhijit Gangurde * 1434*e8521822SAbhijit Gangurde * Account for hole and round up to the next order. 1435*e8521822SAbhijit Gangurde */ 1436*e8521822SAbhijit Gangurde wr.wqe.cmd.mod_qp.rsq_depth = 1437*e8521822SAbhijit Gangurde order_base_2(attr->max_dest_rd_atomic + 1); 1438*e8521822SAbhijit Gangurde wr.wqe.cmd.mod_qp.rsq_index = cpu_to_le32(~0); 1439*e8521822SAbhijit Gangurde } 1440*e8521822SAbhijit Gangurde 1441*e8521822SAbhijit Gangurde if ((mask & IB_QP_MAX_QP_RD_ATOMIC) && attr->max_rd_atomic) { 1442*e8521822SAbhijit Gangurde /* Account for hole and round down to the next order */ 1443*e8521822SAbhijit Gangurde wr.wqe.cmd.mod_qp.rrq_depth = 1444*e8521822SAbhijit Gangurde order_base_2(attr->max_rd_atomic + 2) - 1; 1445*e8521822SAbhijit Gangurde wr.wqe.cmd.mod_qp.rrq_index = cpu_to_le32(~0); 1446*e8521822SAbhijit Gangurde } 1447*e8521822SAbhijit Gangurde 1448*e8521822SAbhijit Gangurde if (qp->ibqp.qp_type == IB_QPT_RC || qp->ibqp.qp_type == IB_QPT_UC) 1449*e8521822SAbhijit Gangurde wr.wqe.cmd.mod_qp.qkey_dest_qpn = 1450*e8521822SAbhijit Gangurde cpu_to_le32(attr->dest_qp_num); 1451*e8521822SAbhijit Gangurde else 1452*e8521822SAbhijit Gangurde wr.wqe.cmd.mod_qp.qkey_dest_qpn = cpu_to_le32(attr->qkey); 1453*e8521822SAbhijit Gangurde 1454*e8521822SAbhijit Gangurde if (mask & IB_QP_AV) { 1455*e8521822SAbhijit Gangurde if (!qp->hdr) 1456*e8521822SAbhijit Gangurde return -ENOMEM; 1457*e8521822SAbhijit Gangurde 1458*e8521822SAbhijit Gangurde sport = rdma_get_udp_sport(grh->flow_label, 1459*e8521822SAbhijit Gangurde qp->qpid, 1460*e8521822SAbhijit Gangurde attr->dest_qp_num); 1461*e8521822SAbhijit Gangurde 1462*e8521822SAbhijit Gangurde rc = ionic_build_hdr(dev, qp->hdr, &attr->ah_attr, sport, true); 1463*e8521822SAbhijit Gangurde if (rc) 1464*e8521822SAbhijit Gangurde return rc; 1465*e8521822SAbhijit Gangurde 1466*e8521822SAbhijit Gangurde qp->sgid_index = grh->sgid_index; 1467*e8521822SAbhijit Gangurde 1468*e8521822SAbhijit Gangurde hdr_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 1469*e8521822SAbhijit Gangurde if (!hdr_buf) 1470*e8521822SAbhijit Gangurde return -ENOMEM; 1471*e8521822SAbhijit Gangurde 1472*e8521822SAbhijit Gangurde hdr_len = ib_ud_header_pack(qp->hdr, hdr_buf); 1473*e8521822SAbhijit Gangurde hdr_len -= IB_BTH_BYTES; 1474*e8521822SAbhijit Gangurde hdr_len -= IB_DETH_BYTES; 1475*e8521822SAbhijit Gangurde ibdev_dbg(&dev->ibdev, "roce packet header template\n"); 1476*e8521822SAbhijit Gangurde print_hex_dump_debug("hdr ", DUMP_PREFIX_OFFSET, 16, 1, 1477*e8521822SAbhijit Gangurde hdr_buf, hdr_len, true); 1478*e8521822SAbhijit Gangurde 1479*e8521822SAbhijit Gangurde hdr_dma = dma_map_single(dev->lif_cfg.hwdev, hdr_buf, hdr_len, 1480*e8521822SAbhijit Gangurde DMA_TO_DEVICE); 1481*e8521822SAbhijit Gangurde 1482*e8521822SAbhijit Gangurde rc = dma_mapping_error(dev->lif_cfg.hwdev, hdr_dma); 1483*e8521822SAbhijit Gangurde if (rc) 1484*e8521822SAbhijit Gangurde goto err_dma; 1485*e8521822SAbhijit Gangurde 1486*e8521822SAbhijit Gangurde if (qp->hdr->ipv4_present) { 1487*e8521822SAbhijit Gangurde wr.wqe.cmd.mod_qp.tfp_csum_profile = 1488*e8521822SAbhijit Gangurde qp->hdr->vlan_present ? 1489*e8521822SAbhijit Gangurde IONIC_TFP_CSUM_PROF_ETH_QTAG_IPV4_UDP : 1490*e8521822SAbhijit Gangurde IONIC_TFP_CSUM_PROF_ETH_IPV4_UDP; 1491*e8521822SAbhijit Gangurde } else { 1492*e8521822SAbhijit Gangurde wr.wqe.cmd.mod_qp.tfp_csum_profile = 1493*e8521822SAbhijit Gangurde qp->hdr->vlan_present ? 1494*e8521822SAbhijit Gangurde IONIC_TFP_CSUM_PROF_ETH_QTAG_IPV6_UDP : 1495*e8521822SAbhijit Gangurde IONIC_TFP_CSUM_PROF_ETH_IPV6_UDP; 1496*e8521822SAbhijit Gangurde } 1497*e8521822SAbhijit Gangurde 1498*e8521822SAbhijit Gangurde wr.wqe.cmd.mod_qp.ah_id_len = 1499*e8521822SAbhijit Gangurde cpu_to_le32(qp->ahid | (hdr_len << 24)); 1500*e8521822SAbhijit Gangurde wr.wqe.cmd.mod_qp.dma_addr = cpu_to_le64(hdr_dma); 1501*e8521822SAbhijit Gangurde 1502*e8521822SAbhijit Gangurde wr.wqe.cmd.mod_qp.en_pcp = attr->ah_attr.sl; 1503*e8521822SAbhijit Gangurde wr.wqe.cmd.mod_qp.ip_dscp = grh->traffic_class >> 2; 1504*e8521822SAbhijit Gangurde } 1505*e8521822SAbhijit Gangurde 1506*e8521822SAbhijit Gangurde ionic_admin_post(dev, &wr); 1507*e8521822SAbhijit Gangurde 1508*e8521822SAbhijit Gangurde rc = ionic_admin_wait(dev, &wr, 0); 1509*e8521822SAbhijit Gangurde 1510*e8521822SAbhijit Gangurde if (mask & IB_QP_AV) 1511*e8521822SAbhijit Gangurde dma_unmap_single(dev->lif_cfg.hwdev, hdr_dma, hdr_len, 1512*e8521822SAbhijit Gangurde DMA_TO_DEVICE); 1513*e8521822SAbhijit Gangurde err_dma: 1514*e8521822SAbhijit Gangurde if (mask & IB_QP_AV) 1515*e8521822SAbhijit Gangurde kfree(hdr_buf); 1516*e8521822SAbhijit Gangurde 1517*e8521822SAbhijit Gangurde return rc; 1518*e8521822SAbhijit Gangurde } 1519*e8521822SAbhijit Gangurde 1520*e8521822SAbhijit Gangurde static int ionic_query_qp_cmd(struct ionic_ibdev *dev, 1521*e8521822SAbhijit Gangurde struct ionic_qp *qp, 1522*e8521822SAbhijit Gangurde struct ib_qp_attr *attr, 1523*e8521822SAbhijit Gangurde int mask) 1524*e8521822SAbhijit Gangurde { 1525*e8521822SAbhijit Gangurde struct ionic_admin_wr wr = { 1526*e8521822SAbhijit Gangurde .work = COMPLETION_INITIALIZER_ONSTACK(wr.work), 1527*e8521822SAbhijit Gangurde .wqe = { 1528*e8521822SAbhijit Gangurde .op = IONIC_V1_ADMIN_QUERY_QP, 1529*e8521822SAbhijit Gangurde .len = cpu_to_le16(IONIC_ADMIN_QUERY_QP_IN_V1_LEN), 1530*e8521822SAbhijit Gangurde .cmd.query_qp = { 1531*e8521822SAbhijit Gangurde .id_ver = cpu_to_le32(qp->qpid), 1532*e8521822SAbhijit Gangurde }, 1533*e8521822SAbhijit Gangurde } 1534*e8521822SAbhijit Gangurde }; 1535*e8521822SAbhijit Gangurde struct ionic_v1_admin_query_qp_sq *query_sqbuf; 1536*e8521822SAbhijit Gangurde struct ionic_v1_admin_query_qp_rq *query_rqbuf; 1537*e8521822SAbhijit Gangurde dma_addr_t query_sqdma; 1538*e8521822SAbhijit Gangurde dma_addr_t query_rqdma; 1539*e8521822SAbhijit Gangurde dma_addr_t hdr_dma = 0; 1540*e8521822SAbhijit Gangurde void *hdr_buf = NULL; 1541*e8521822SAbhijit Gangurde int flags, rc; 1542*e8521822SAbhijit Gangurde 1543*e8521822SAbhijit Gangurde if (dev->lif_cfg.admin_opcodes <= IONIC_V1_ADMIN_QUERY_QP) 1544*e8521822SAbhijit Gangurde return -EBADRQC; 1545*e8521822SAbhijit Gangurde 1546*e8521822SAbhijit Gangurde if (qp->has_sq) { 1547*e8521822SAbhijit Gangurde bool expdb = !!(qp->sq_cmb & IONIC_CMB_EXPDB); 1548*e8521822SAbhijit Gangurde 1549*e8521822SAbhijit Gangurde attr->cap.max_send_sge = 1550*e8521822SAbhijit Gangurde ionic_v1_send_wqe_max_sge(qp->sq.stride_log2, 1551*e8521822SAbhijit Gangurde qp->sq_spec, 1552*e8521822SAbhijit Gangurde expdb); 1553*e8521822SAbhijit Gangurde attr->cap.max_inline_data = 1554*e8521822SAbhijit Gangurde ionic_v1_send_wqe_max_data(qp->sq.stride_log2, expdb); 1555*e8521822SAbhijit Gangurde } 1556*e8521822SAbhijit Gangurde 1557*e8521822SAbhijit Gangurde if (qp->has_rq) { 1558*e8521822SAbhijit Gangurde attr->cap.max_recv_sge = 1559*e8521822SAbhijit Gangurde ionic_v1_recv_wqe_max_sge(qp->rq.stride_log2, 1560*e8521822SAbhijit Gangurde qp->rq_spec, 1561*e8521822SAbhijit Gangurde qp->rq_cmb & IONIC_CMB_EXPDB); 1562*e8521822SAbhijit Gangurde } 1563*e8521822SAbhijit Gangurde 1564*e8521822SAbhijit Gangurde query_sqbuf = kzalloc(PAGE_SIZE, GFP_KERNEL); 1565*e8521822SAbhijit Gangurde if (!query_sqbuf) 1566*e8521822SAbhijit Gangurde return -ENOMEM; 1567*e8521822SAbhijit Gangurde 1568*e8521822SAbhijit Gangurde query_rqbuf = kzalloc(PAGE_SIZE, GFP_KERNEL); 1569*e8521822SAbhijit Gangurde if (!query_rqbuf) { 1570*e8521822SAbhijit Gangurde rc = -ENOMEM; 1571*e8521822SAbhijit Gangurde goto err_rqbuf; 1572*e8521822SAbhijit Gangurde } 1573*e8521822SAbhijit Gangurde 1574*e8521822SAbhijit Gangurde query_sqdma = dma_map_single(dev->lif_cfg.hwdev, query_sqbuf, PAGE_SIZE, 1575*e8521822SAbhijit Gangurde DMA_FROM_DEVICE); 1576*e8521822SAbhijit Gangurde rc = dma_mapping_error(dev->lif_cfg.hwdev, query_sqdma); 1577*e8521822SAbhijit Gangurde if (rc) 1578*e8521822SAbhijit Gangurde goto err_sqdma; 1579*e8521822SAbhijit Gangurde 1580*e8521822SAbhijit Gangurde query_rqdma = dma_map_single(dev->lif_cfg.hwdev, query_rqbuf, PAGE_SIZE, 1581*e8521822SAbhijit Gangurde DMA_FROM_DEVICE); 1582*e8521822SAbhijit Gangurde rc = dma_mapping_error(dev->lif_cfg.hwdev, query_rqdma); 1583*e8521822SAbhijit Gangurde if (rc) 1584*e8521822SAbhijit Gangurde goto err_rqdma; 1585*e8521822SAbhijit Gangurde 1586*e8521822SAbhijit Gangurde if (mask & IB_QP_AV) { 1587*e8521822SAbhijit Gangurde hdr_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 1588*e8521822SAbhijit Gangurde if (!hdr_buf) { 1589*e8521822SAbhijit Gangurde rc = -ENOMEM; 1590*e8521822SAbhijit Gangurde goto err_hdrbuf; 1591*e8521822SAbhijit Gangurde } 1592*e8521822SAbhijit Gangurde 1593*e8521822SAbhijit Gangurde hdr_dma = dma_map_single(dev->lif_cfg.hwdev, hdr_buf, 1594*e8521822SAbhijit Gangurde PAGE_SIZE, DMA_FROM_DEVICE); 1595*e8521822SAbhijit Gangurde rc = dma_mapping_error(dev->lif_cfg.hwdev, hdr_dma); 1596*e8521822SAbhijit Gangurde if (rc) 1597*e8521822SAbhijit Gangurde goto err_hdrdma; 1598*e8521822SAbhijit Gangurde } 1599*e8521822SAbhijit Gangurde 1600*e8521822SAbhijit Gangurde wr.wqe.cmd.query_qp.sq_dma_addr = cpu_to_le64(query_sqdma); 1601*e8521822SAbhijit Gangurde wr.wqe.cmd.query_qp.rq_dma_addr = cpu_to_le64(query_rqdma); 1602*e8521822SAbhijit Gangurde wr.wqe.cmd.query_qp.hdr_dma_addr = cpu_to_le64(hdr_dma); 1603*e8521822SAbhijit Gangurde wr.wqe.cmd.query_qp.ah_id = cpu_to_le32(qp->ahid); 1604*e8521822SAbhijit Gangurde 1605*e8521822SAbhijit Gangurde ionic_admin_post(dev, &wr); 1606*e8521822SAbhijit Gangurde 1607*e8521822SAbhijit Gangurde rc = ionic_admin_wait(dev, &wr, 0); 1608*e8521822SAbhijit Gangurde 1609*e8521822SAbhijit Gangurde if (rc) 1610*e8521822SAbhijit Gangurde goto err_hdrdma; 1611*e8521822SAbhijit Gangurde 1612*e8521822SAbhijit Gangurde flags = be16_to_cpu(query_sqbuf->access_perms_flags | 1613*e8521822SAbhijit Gangurde query_rqbuf->access_perms_flags); 1614*e8521822SAbhijit Gangurde 1615*e8521822SAbhijit Gangurde print_hex_dump_debug("sqbuf ", DUMP_PREFIX_OFFSET, 16, 1, 1616*e8521822SAbhijit Gangurde query_sqbuf, sizeof(*query_sqbuf), true); 1617*e8521822SAbhijit Gangurde print_hex_dump_debug("rqbuf ", DUMP_PREFIX_OFFSET, 16, 1, 1618*e8521822SAbhijit Gangurde query_rqbuf, sizeof(*query_rqbuf), true); 1619*e8521822SAbhijit Gangurde ibdev_dbg(&dev->ibdev, "query qp %u state_pmtu %#x flags %#x", 1620*e8521822SAbhijit Gangurde qp->qpid, query_rqbuf->state_pmtu, flags); 1621*e8521822SAbhijit Gangurde 1622*e8521822SAbhijit Gangurde attr->qp_state = from_ionic_qp_state(query_rqbuf->state_pmtu >> 4); 1623*e8521822SAbhijit Gangurde attr->cur_qp_state = attr->qp_state; 1624*e8521822SAbhijit Gangurde attr->path_mtu = (query_rqbuf->state_pmtu & 0xf) - 7; 1625*e8521822SAbhijit Gangurde attr->path_mig_state = IB_MIG_MIGRATED; 1626*e8521822SAbhijit Gangurde attr->qkey = be32_to_cpu(query_sqbuf->qkey_dest_qpn); 1627*e8521822SAbhijit Gangurde attr->rq_psn = be32_to_cpu(query_sqbuf->rq_psn); 1628*e8521822SAbhijit Gangurde attr->sq_psn = be32_to_cpu(query_rqbuf->sq_psn); 1629*e8521822SAbhijit Gangurde attr->dest_qp_num = attr->qkey; 1630*e8521822SAbhijit Gangurde attr->qp_access_flags = from_ionic_qp_flags(flags); 1631*e8521822SAbhijit Gangurde attr->pkey_index = 0; 1632*e8521822SAbhijit Gangurde attr->alt_pkey_index = 0; 1633*e8521822SAbhijit Gangurde attr->en_sqd_async_notify = !!(flags & IONIC_QPF_SQD_NOTIFY); 1634*e8521822SAbhijit Gangurde attr->sq_draining = !!(flags & IONIC_QPF_SQ_DRAINING); 1635*e8521822SAbhijit Gangurde attr->max_rd_atomic = BIT(query_rqbuf->rrq_depth) - 1; 1636*e8521822SAbhijit Gangurde attr->max_dest_rd_atomic = BIT(query_rqbuf->rsq_depth) - 1; 1637*e8521822SAbhijit Gangurde attr->min_rnr_timer = query_sqbuf->rnr_timer; 1638*e8521822SAbhijit Gangurde attr->port_num = 0; 1639*e8521822SAbhijit Gangurde attr->timeout = query_sqbuf->retry_timeout; 1640*e8521822SAbhijit Gangurde attr->retry_cnt = query_rqbuf->retry_rnrtry & 0xf; 1641*e8521822SAbhijit Gangurde attr->rnr_retry = query_rqbuf->retry_rnrtry >> 4; 1642*e8521822SAbhijit Gangurde attr->alt_port_num = 0; 1643*e8521822SAbhijit Gangurde attr->alt_timeout = 0; 1644*e8521822SAbhijit Gangurde attr->rate_limit = be32_to_cpu(query_sqbuf->rate_limit_kbps); 1645*e8521822SAbhijit Gangurde 1646*e8521822SAbhijit Gangurde if (mask & IB_QP_AV) 1647*e8521822SAbhijit Gangurde ionic_set_ah_attr(dev, &attr->ah_attr, 1648*e8521822SAbhijit Gangurde qp->hdr, qp->sgid_index); 1649*e8521822SAbhijit Gangurde 1650*e8521822SAbhijit Gangurde err_hdrdma: 1651*e8521822SAbhijit Gangurde if (mask & IB_QP_AV) { 1652*e8521822SAbhijit Gangurde dma_unmap_single(dev->lif_cfg.hwdev, hdr_dma, 1653*e8521822SAbhijit Gangurde PAGE_SIZE, DMA_FROM_DEVICE); 1654*e8521822SAbhijit Gangurde kfree(hdr_buf); 1655*e8521822SAbhijit Gangurde } 1656*e8521822SAbhijit Gangurde err_hdrbuf: 1657*e8521822SAbhijit Gangurde dma_unmap_single(dev->lif_cfg.hwdev, query_rqdma, sizeof(*query_rqbuf), 1658*e8521822SAbhijit Gangurde DMA_FROM_DEVICE); 1659*e8521822SAbhijit Gangurde err_rqdma: 1660*e8521822SAbhijit Gangurde dma_unmap_single(dev->lif_cfg.hwdev, query_sqdma, sizeof(*query_sqbuf), 1661*e8521822SAbhijit Gangurde DMA_FROM_DEVICE); 1662*e8521822SAbhijit Gangurde err_sqdma: 1663*e8521822SAbhijit Gangurde kfree(query_rqbuf); 1664*e8521822SAbhijit Gangurde err_rqbuf: 1665*e8521822SAbhijit Gangurde kfree(query_sqbuf); 1666*e8521822SAbhijit Gangurde 1667*e8521822SAbhijit Gangurde return rc; 1668*e8521822SAbhijit Gangurde } 1669*e8521822SAbhijit Gangurde 1670*e8521822SAbhijit Gangurde static int ionic_destroy_qp_cmd(struct ionic_ibdev *dev, u32 qpid) 1671*e8521822SAbhijit Gangurde { 1672*e8521822SAbhijit Gangurde struct ionic_admin_wr wr = { 1673*e8521822SAbhijit Gangurde .work = COMPLETION_INITIALIZER_ONSTACK(wr.work), 1674*e8521822SAbhijit Gangurde .wqe = { 1675*e8521822SAbhijit Gangurde .op = IONIC_V1_ADMIN_DESTROY_QP, 1676*e8521822SAbhijit Gangurde .len = cpu_to_le16(IONIC_ADMIN_DESTROY_QP_IN_V1_LEN), 1677*e8521822SAbhijit Gangurde .cmd.destroy_qp = { 1678*e8521822SAbhijit Gangurde .qp_id = cpu_to_le32(qpid), 1679*e8521822SAbhijit Gangurde }, 1680*e8521822SAbhijit Gangurde } 1681*e8521822SAbhijit Gangurde }; 1682*e8521822SAbhijit Gangurde 1683*e8521822SAbhijit Gangurde if (dev->lif_cfg.admin_opcodes <= IONIC_V1_ADMIN_DESTROY_QP) 1684*e8521822SAbhijit Gangurde return -EBADRQC; 1685*e8521822SAbhijit Gangurde 1686*e8521822SAbhijit Gangurde ionic_admin_post(dev, &wr); 1687*e8521822SAbhijit Gangurde 1688*e8521822SAbhijit Gangurde return ionic_admin_wait(dev, &wr, IONIC_ADMIN_F_TEARDOWN); 1689*e8521822SAbhijit Gangurde } 1690*e8521822SAbhijit Gangurde 1691*e8521822SAbhijit Gangurde static bool ionic_expdb_wqe_size_supported(struct ionic_ibdev *dev, 1692*e8521822SAbhijit Gangurde uint32_t wqe_size) 1693*e8521822SAbhijit Gangurde { 1694*e8521822SAbhijit Gangurde switch (wqe_size) { 1695*e8521822SAbhijit Gangurde case 64: return dev->lif_cfg.expdb_mask & IONIC_EXPDB_64; 1696*e8521822SAbhijit Gangurde case 128: return dev->lif_cfg.expdb_mask & IONIC_EXPDB_128; 1697*e8521822SAbhijit Gangurde case 256: return dev->lif_cfg.expdb_mask & IONIC_EXPDB_256; 1698*e8521822SAbhijit Gangurde case 512: return dev->lif_cfg.expdb_mask & IONIC_EXPDB_512; 1699*e8521822SAbhijit Gangurde } 1700*e8521822SAbhijit Gangurde 1701*e8521822SAbhijit Gangurde return false; 1702*e8521822SAbhijit Gangurde } 1703*e8521822SAbhijit Gangurde 1704*e8521822SAbhijit Gangurde static void ionic_qp_sq_init_cmb(struct ionic_ibdev *dev, 1705*e8521822SAbhijit Gangurde struct ionic_qp *qp, 1706*e8521822SAbhijit Gangurde struct ib_udata *udata, 1707*e8521822SAbhijit Gangurde int max_data) 1708*e8521822SAbhijit Gangurde { 1709*e8521822SAbhijit Gangurde u8 expdb_stride_log2 = 0; 1710*e8521822SAbhijit Gangurde bool expdb; 1711*e8521822SAbhijit Gangurde int rc; 1712*e8521822SAbhijit Gangurde 1713*e8521822SAbhijit Gangurde if (!(qp->sq_cmb & IONIC_CMB_ENABLE)) 1714*e8521822SAbhijit Gangurde goto not_in_cmb; 1715*e8521822SAbhijit Gangurde 1716*e8521822SAbhijit Gangurde if (qp->sq_cmb & ~IONIC_CMB_SUPPORTED) { 1717*e8521822SAbhijit Gangurde if (qp->sq_cmb & IONIC_CMB_REQUIRE) 1718*e8521822SAbhijit Gangurde goto not_in_cmb; 1719*e8521822SAbhijit Gangurde 1720*e8521822SAbhijit Gangurde qp->sq_cmb &= IONIC_CMB_SUPPORTED; 1721*e8521822SAbhijit Gangurde } 1722*e8521822SAbhijit Gangurde 1723*e8521822SAbhijit Gangurde if ((qp->sq_cmb & IONIC_CMB_EXPDB) && !dev->lif_cfg.sq_expdb) { 1724*e8521822SAbhijit Gangurde if (qp->sq_cmb & IONIC_CMB_REQUIRE) 1725*e8521822SAbhijit Gangurde goto not_in_cmb; 1726*e8521822SAbhijit Gangurde 1727*e8521822SAbhijit Gangurde qp->sq_cmb &= ~IONIC_CMB_EXPDB; 1728*e8521822SAbhijit Gangurde } 1729*e8521822SAbhijit Gangurde 1730*e8521822SAbhijit Gangurde qp->sq_cmb_order = order_base_2(qp->sq.size / PAGE_SIZE); 1731*e8521822SAbhijit Gangurde 1732*e8521822SAbhijit Gangurde if (qp->sq_cmb_order >= IONIC_SQCMB_ORDER) 1733*e8521822SAbhijit Gangurde goto not_in_cmb; 1734*e8521822SAbhijit Gangurde 1735*e8521822SAbhijit Gangurde if (qp->sq_cmb & IONIC_CMB_EXPDB) 1736*e8521822SAbhijit Gangurde expdb_stride_log2 = qp->sq.stride_log2; 1737*e8521822SAbhijit Gangurde 1738*e8521822SAbhijit Gangurde rc = ionic_get_cmb(dev->lif_cfg.lif, &qp->sq_cmb_pgid, 1739*e8521822SAbhijit Gangurde &qp->sq_cmb_addr, qp->sq_cmb_order, 1740*e8521822SAbhijit Gangurde expdb_stride_log2, &expdb); 1741*e8521822SAbhijit Gangurde if (rc) 1742*e8521822SAbhijit Gangurde goto not_in_cmb; 1743*e8521822SAbhijit Gangurde 1744*e8521822SAbhijit Gangurde if ((qp->sq_cmb & IONIC_CMB_EXPDB) && !expdb) { 1745*e8521822SAbhijit Gangurde if (qp->sq_cmb & IONIC_CMB_REQUIRE) 1746*e8521822SAbhijit Gangurde goto err_map; 1747*e8521822SAbhijit Gangurde 1748*e8521822SAbhijit Gangurde qp->sq_cmb &= ~IONIC_CMB_EXPDB; 1749*e8521822SAbhijit Gangurde } 1750*e8521822SAbhijit Gangurde 1751*e8521822SAbhijit Gangurde return; 1752*e8521822SAbhijit Gangurde 1753*e8521822SAbhijit Gangurde err_map: 1754*e8521822SAbhijit Gangurde ionic_put_cmb(dev->lif_cfg.lif, qp->sq_cmb_pgid, qp->sq_cmb_order); 1755*e8521822SAbhijit Gangurde not_in_cmb: 1756*e8521822SAbhijit Gangurde if (qp->sq_cmb & IONIC_CMB_REQUIRE) 1757*e8521822SAbhijit Gangurde ibdev_dbg(&dev->ibdev, "could not place sq in cmb as required\n"); 1758*e8521822SAbhijit Gangurde 1759*e8521822SAbhijit Gangurde qp->sq_cmb = 0; 1760*e8521822SAbhijit Gangurde qp->sq_cmb_order = IONIC_RES_INVALID; 1761*e8521822SAbhijit Gangurde qp->sq_cmb_pgid = 0; 1762*e8521822SAbhijit Gangurde qp->sq_cmb_addr = 0; 1763*e8521822SAbhijit Gangurde } 1764*e8521822SAbhijit Gangurde 1765*e8521822SAbhijit Gangurde static void ionic_qp_sq_destroy_cmb(struct ionic_ibdev *dev, 1766*e8521822SAbhijit Gangurde struct ionic_ctx *ctx, 1767*e8521822SAbhijit Gangurde struct ionic_qp *qp) 1768*e8521822SAbhijit Gangurde { 1769*e8521822SAbhijit Gangurde if (!(qp->sq_cmb & IONIC_CMB_ENABLE)) 1770*e8521822SAbhijit Gangurde return; 1771*e8521822SAbhijit Gangurde 1772*e8521822SAbhijit Gangurde if (ctx) 1773*e8521822SAbhijit Gangurde rdma_user_mmap_entry_remove(qp->mmap_sq_cmb); 1774*e8521822SAbhijit Gangurde 1775*e8521822SAbhijit Gangurde ionic_put_cmb(dev->lif_cfg.lif, qp->sq_cmb_pgid, qp->sq_cmb_order); 1776*e8521822SAbhijit Gangurde } 1777*e8521822SAbhijit Gangurde 1778*e8521822SAbhijit Gangurde static int ionic_qp_sq_init(struct ionic_ibdev *dev, struct ionic_ctx *ctx, 1779*e8521822SAbhijit Gangurde struct ionic_qp *qp, struct ionic_qdesc *sq, 1780*e8521822SAbhijit Gangurde struct ionic_tbl_buf *buf, int max_wr, int max_sge, 1781*e8521822SAbhijit Gangurde int max_data, int sq_spec, struct ib_udata *udata) 1782*e8521822SAbhijit Gangurde { 1783*e8521822SAbhijit Gangurde u32 wqe_size; 1784*e8521822SAbhijit Gangurde int rc = 0; 1785*e8521822SAbhijit Gangurde 1786*e8521822SAbhijit Gangurde qp->sq_msn_prod = 0; 1787*e8521822SAbhijit Gangurde qp->sq_msn_cons = 0; 1788*e8521822SAbhijit Gangurde 1789*e8521822SAbhijit Gangurde if (!qp->has_sq) { 1790*e8521822SAbhijit Gangurde if (buf) { 1791*e8521822SAbhijit Gangurde buf->tbl_buf = NULL; 1792*e8521822SAbhijit Gangurde buf->tbl_limit = 0; 1793*e8521822SAbhijit Gangurde buf->tbl_pages = 0; 1794*e8521822SAbhijit Gangurde } 1795*e8521822SAbhijit Gangurde if (udata) 1796*e8521822SAbhijit Gangurde rc = ionic_validate_qdesc_zero(sq); 1797*e8521822SAbhijit Gangurde 1798*e8521822SAbhijit Gangurde return rc; 1799*e8521822SAbhijit Gangurde } 1800*e8521822SAbhijit Gangurde 1801*e8521822SAbhijit Gangurde rc = -EINVAL; 1802*e8521822SAbhijit Gangurde 1803*e8521822SAbhijit Gangurde if (max_wr < 0 || max_wr > 0xffff) 1804*e8521822SAbhijit Gangurde return rc; 1805*e8521822SAbhijit Gangurde 1806*e8521822SAbhijit Gangurde if (max_sge < 1) 1807*e8521822SAbhijit Gangurde return rc; 1808*e8521822SAbhijit Gangurde 1809*e8521822SAbhijit Gangurde if (max_sge > min(ionic_v1_send_wqe_max_sge(dev->lif_cfg.max_stride, 0, 1810*e8521822SAbhijit Gangurde qp->sq_cmb & 1811*e8521822SAbhijit Gangurde IONIC_CMB_EXPDB), 1812*e8521822SAbhijit Gangurde IONIC_SPEC_HIGH)) 1813*e8521822SAbhijit Gangurde return rc; 1814*e8521822SAbhijit Gangurde 1815*e8521822SAbhijit Gangurde if (max_data < 0) 1816*e8521822SAbhijit Gangurde return rc; 1817*e8521822SAbhijit Gangurde 1818*e8521822SAbhijit Gangurde if (max_data > ionic_v1_send_wqe_max_data(dev->lif_cfg.max_stride, 1819*e8521822SAbhijit Gangurde qp->sq_cmb & IONIC_CMB_EXPDB)) 1820*e8521822SAbhijit Gangurde return rc; 1821*e8521822SAbhijit Gangurde 1822*e8521822SAbhijit Gangurde if (udata) { 1823*e8521822SAbhijit Gangurde rc = ionic_validate_qdesc(sq); 1824*e8521822SAbhijit Gangurde if (rc) 1825*e8521822SAbhijit Gangurde return rc; 1826*e8521822SAbhijit Gangurde 1827*e8521822SAbhijit Gangurde qp->sq_spec = sq_spec; 1828*e8521822SAbhijit Gangurde 1829*e8521822SAbhijit Gangurde qp->sq.ptr = NULL; 1830*e8521822SAbhijit Gangurde qp->sq.size = sq->size; 1831*e8521822SAbhijit Gangurde qp->sq.mask = sq->mask; 1832*e8521822SAbhijit Gangurde qp->sq.depth_log2 = sq->depth_log2; 1833*e8521822SAbhijit Gangurde qp->sq.stride_log2 = sq->stride_log2; 1834*e8521822SAbhijit Gangurde 1835*e8521822SAbhijit Gangurde qp->sq_meta = NULL; 1836*e8521822SAbhijit Gangurde qp->sq_msn_idx = NULL; 1837*e8521822SAbhijit Gangurde 1838*e8521822SAbhijit Gangurde qp->sq_umem = ib_umem_get(&dev->ibdev, sq->addr, sq->size, 0); 1839*e8521822SAbhijit Gangurde if (IS_ERR(qp->sq_umem)) 1840*e8521822SAbhijit Gangurde return PTR_ERR(qp->sq_umem); 1841*e8521822SAbhijit Gangurde } else { 1842*e8521822SAbhijit Gangurde qp->sq_umem = NULL; 1843*e8521822SAbhijit Gangurde 1844*e8521822SAbhijit Gangurde qp->sq_spec = ionic_v1_use_spec_sge(max_sge, sq_spec); 1845*e8521822SAbhijit Gangurde if (sq_spec && !qp->sq_spec) 1846*e8521822SAbhijit Gangurde ibdev_dbg(&dev->ibdev, 1847*e8521822SAbhijit Gangurde "init sq: max_sge %u disables spec\n", 1848*e8521822SAbhijit Gangurde max_sge); 1849*e8521822SAbhijit Gangurde 1850*e8521822SAbhijit Gangurde if (qp->sq_cmb & IONIC_CMB_EXPDB) { 1851*e8521822SAbhijit Gangurde wqe_size = ionic_v1_send_wqe_min_size(max_sge, max_data, 1852*e8521822SAbhijit Gangurde qp->sq_spec, 1853*e8521822SAbhijit Gangurde true); 1854*e8521822SAbhijit Gangurde 1855*e8521822SAbhijit Gangurde if (!ionic_expdb_wqe_size_supported(dev, wqe_size)) 1856*e8521822SAbhijit Gangurde qp->sq_cmb &= ~IONIC_CMB_EXPDB; 1857*e8521822SAbhijit Gangurde } 1858*e8521822SAbhijit Gangurde 1859*e8521822SAbhijit Gangurde if (!(qp->sq_cmb & IONIC_CMB_EXPDB)) 1860*e8521822SAbhijit Gangurde wqe_size = ionic_v1_send_wqe_min_size(max_sge, max_data, 1861*e8521822SAbhijit Gangurde qp->sq_spec, 1862*e8521822SAbhijit Gangurde false); 1863*e8521822SAbhijit Gangurde 1864*e8521822SAbhijit Gangurde rc = ionic_queue_init(&qp->sq, dev->lif_cfg.hwdev, 1865*e8521822SAbhijit Gangurde max_wr, wqe_size); 1866*e8521822SAbhijit Gangurde if (rc) 1867*e8521822SAbhijit Gangurde return rc; 1868*e8521822SAbhijit Gangurde 1869*e8521822SAbhijit Gangurde ionic_queue_dbell_init(&qp->sq, qp->qpid); 1870*e8521822SAbhijit Gangurde 1871*e8521822SAbhijit Gangurde qp->sq_meta = kmalloc_array((u32)qp->sq.mask + 1, 1872*e8521822SAbhijit Gangurde sizeof(*qp->sq_meta), 1873*e8521822SAbhijit Gangurde GFP_KERNEL); 1874*e8521822SAbhijit Gangurde if (!qp->sq_meta) { 1875*e8521822SAbhijit Gangurde rc = -ENOMEM; 1876*e8521822SAbhijit Gangurde goto err_sq_meta; 1877*e8521822SAbhijit Gangurde } 1878*e8521822SAbhijit Gangurde 1879*e8521822SAbhijit Gangurde qp->sq_msn_idx = kmalloc_array((u32)qp->sq.mask + 1, 1880*e8521822SAbhijit Gangurde sizeof(*qp->sq_msn_idx), 1881*e8521822SAbhijit Gangurde GFP_KERNEL); 1882*e8521822SAbhijit Gangurde if (!qp->sq_msn_idx) { 1883*e8521822SAbhijit Gangurde rc = -ENOMEM; 1884*e8521822SAbhijit Gangurde goto err_sq_msn; 1885*e8521822SAbhijit Gangurde } 1886*e8521822SAbhijit Gangurde } 1887*e8521822SAbhijit Gangurde 1888*e8521822SAbhijit Gangurde ionic_qp_sq_init_cmb(dev, qp, udata, max_data); 1889*e8521822SAbhijit Gangurde 1890*e8521822SAbhijit Gangurde if (qp->sq_cmb & IONIC_CMB_ENABLE) 1891*e8521822SAbhijit Gangurde rc = ionic_pgtbl_init(dev, buf, NULL, 1892*e8521822SAbhijit Gangurde (u64)qp->sq_cmb_pgid << PAGE_SHIFT, 1893*e8521822SAbhijit Gangurde 1, PAGE_SIZE); 1894*e8521822SAbhijit Gangurde else 1895*e8521822SAbhijit Gangurde rc = ionic_pgtbl_init(dev, buf, 1896*e8521822SAbhijit Gangurde qp->sq_umem, qp->sq.dma, 1, PAGE_SIZE); 1897*e8521822SAbhijit Gangurde if (rc) 1898*e8521822SAbhijit Gangurde goto err_sq_tbl; 1899*e8521822SAbhijit Gangurde 1900*e8521822SAbhijit Gangurde return 0; 1901*e8521822SAbhijit Gangurde 1902*e8521822SAbhijit Gangurde err_sq_tbl: 1903*e8521822SAbhijit Gangurde ionic_qp_sq_destroy_cmb(dev, ctx, qp); 1904*e8521822SAbhijit Gangurde kfree(qp->sq_msn_idx); 1905*e8521822SAbhijit Gangurde err_sq_msn: 1906*e8521822SAbhijit Gangurde kfree(qp->sq_meta); 1907*e8521822SAbhijit Gangurde err_sq_meta: 1908*e8521822SAbhijit Gangurde if (qp->sq_umem) 1909*e8521822SAbhijit Gangurde ib_umem_release(qp->sq_umem); 1910*e8521822SAbhijit Gangurde else 1911*e8521822SAbhijit Gangurde ionic_queue_destroy(&qp->sq, dev->lif_cfg.hwdev); 1912*e8521822SAbhijit Gangurde return rc; 1913*e8521822SAbhijit Gangurde } 1914*e8521822SAbhijit Gangurde 1915*e8521822SAbhijit Gangurde static void ionic_qp_sq_destroy(struct ionic_ibdev *dev, 1916*e8521822SAbhijit Gangurde struct ionic_ctx *ctx, 1917*e8521822SAbhijit Gangurde struct ionic_qp *qp) 1918*e8521822SAbhijit Gangurde { 1919*e8521822SAbhijit Gangurde if (!qp->has_sq) 1920*e8521822SAbhijit Gangurde return; 1921*e8521822SAbhijit Gangurde 1922*e8521822SAbhijit Gangurde ionic_qp_sq_destroy_cmb(dev, ctx, qp); 1923*e8521822SAbhijit Gangurde 1924*e8521822SAbhijit Gangurde kfree(qp->sq_msn_idx); 1925*e8521822SAbhijit Gangurde kfree(qp->sq_meta); 1926*e8521822SAbhijit Gangurde 1927*e8521822SAbhijit Gangurde if (qp->sq_umem) 1928*e8521822SAbhijit Gangurde ib_umem_release(qp->sq_umem); 1929*e8521822SAbhijit Gangurde else 1930*e8521822SAbhijit Gangurde ionic_queue_destroy(&qp->sq, dev->lif_cfg.hwdev); 1931*e8521822SAbhijit Gangurde } 1932*e8521822SAbhijit Gangurde 1933*e8521822SAbhijit Gangurde static void ionic_qp_rq_init_cmb(struct ionic_ibdev *dev, 1934*e8521822SAbhijit Gangurde struct ionic_qp *qp, 1935*e8521822SAbhijit Gangurde struct ib_udata *udata) 1936*e8521822SAbhijit Gangurde { 1937*e8521822SAbhijit Gangurde u8 expdb_stride_log2 = 0; 1938*e8521822SAbhijit Gangurde bool expdb; 1939*e8521822SAbhijit Gangurde int rc; 1940*e8521822SAbhijit Gangurde 1941*e8521822SAbhijit Gangurde if (!(qp->rq_cmb & IONIC_CMB_ENABLE)) 1942*e8521822SAbhijit Gangurde goto not_in_cmb; 1943*e8521822SAbhijit Gangurde 1944*e8521822SAbhijit Gangurde if (qp->rq_cmb & ~IONIC_CMB_SUPPORTED) { 1945*e8521822SAbhijit Gangurde if (qp->rq_cmb & IONIC_CMB_REQUIRE) 1946*e8521822SAbhijit Gangurde goto not_in_cmb; 1947*e8521822SAbhijit Gangurde 1948*e8521822SAbhijit Gangurde qp->rq_cmb &= IONIC_CMB_SUPPORTED; 1949*e8521822SAbhijit Gangurde } 1950*e8521822SAbhijit Gangurde 1951*e8521822SAbhijit Gangurde if ((qp->rq_cmb & IONIC_CMB_EXPDB) && !dev->lif_cfg.rq_expdb) { 1952*e8521822SAbhijit Gangurde if (qp->rq_cmb & IONIC_CMB_REQUIRE) 1953*e8521822SAbhijit Gangurde goto not_in_cmb; 1954*e8521822SAbhijit Gangurde 1955*e8521822SAbhijit Gangurde qp->rq_cmb &= ~IONIC_CMB_EXPDB; 1956*e8521822SAbhijit Gangurde } 1957*e8521822SAbhijit Gangurde 1958*e8521822SAbhijit Gangurde qp->rq_cmb_order = order_base_2(qp->rq.size / PAGE_SIZE); 1959*e8521822SAbhijit Gangurde 1960*e8521822SAbhijit Gangurde if (qp->rq_cmb_order >= IONIC_RQCMB_ORDER) 1961*e8521822SAbhijit Gangurde goto not_in_cmb; 1962*e8521822SAbhijit Gangurde 1963*e8521822SAbhijit Gangurde if (qp->rq_cmb & IONIC_CMB_EXPDB) 1964*e8521822SAbhijit Gangurde expdb_stride_log2 = qp->rq.stride_log2; 1965*e8521822SAbhijit Gangurde 1966*e8521822SAbhijit Gangurde rc = ionic_get_cmb(dev->lif_cfg.lif, &qp->rq_cmb_pgid, 1967*e8521822SAbhijit Gangurde &qp->rq_cmb_addr, qp->rq_cmb_order, 1968*e8521822SAbhijit Gangurde expdb_stride_log2, &expdb); 1969*e8521822SAbhijit Gangurde if (rc) 1970*e8521822SAbhijit Gangurde goto not_in_cmb; 1971*e8521822SAbhijit Gangurde 1972*e8521822SAbhijit Gangurde if ((qp->rq_cmb & IONIC_CMB_EXPDB) && !expdb) { 1973*e8521822SAbhijit Gangurde if (qp->rq_cmb & IONIC_CMB_REQUIRE) 1974*e8521822SAbhijit Gangurde goto err_map; 1975*e8521822SAbhijit Gangurde 1976*e8521822SAbhijit Gangurde qp->rq_cmb &= ~IONIC_CMB_EXPDB; 1977*e8521822SAbhijit Gangurde } 1978*e8521822SAbhijit Gangurde 1979*e8521822SAbhijit Gangurde return; 1980*e8521822SAbhijit Gangurde 1981*e8521822SAbhijit Gangurde err_map: 1982*e8521822SAbhijit Gangurde ionic_put_cmb(dev->lif_cfg.lif, qp->rq_cmb_pgid, qp->rq_cmb_order); 1983*e8521822SAbhijit Gangurde not_in_cmb: 1984*e8521822SAbhijit Gangurde if (qp->rq_cmb & IONIC_CMB_REQUIRE) 1985*e8521822SAbhijit Gangurde ibdev_dbg(&dev->ibdev, "could not place rq in cmb as required\n"); 1986*e8521822SAbhijit Gangurde 1987*e8521822SAbhijit Gangurde qp->rq_cmb = 0; 1988*e8521822SAbhijit Gangurde qp->rq_cmb_order = IONIC_RES_INVALID; 1989*e8521822SAbhijit Gangurde qp->rq_cmb_pgid = 0; 1990*e8521822SAbhijit Gangurde qp->rq_cmb_addr = 0; 1991*e8521822SAbhijit Gangurde } 1992*e8521822SAbhijit Gangurde 1993*e8521822SAbhijit Gangurde static void ionic_qp_rq_destroy_cmb(struct ionic_ibdev *dev, 1994*e8521822SAbhijit Gangurde struct ionic_ctx *ctx, 1995*e8521822SAbhijit Gangurde struct ionic_qp *qp) 1996*e8521822SAbhijit Gangurde { 1997*e8521822SAbhijit Gangurde if (!(qp->rq_cmb & IONIC_CMB_ENABLE)) 1998*e8521822SAbhijit Gangurde return; 1999*e8521822SAbhijit Gangurde 2000*e8521822SAbhijit Gangurde if (ctx) 2001*e8521822SAbhijit Gangurde rdma_user_mmap_entry_remove(qp->mmap_rq_cmb); 2002*e8521822SAbhijit Gangurde 2003*e8521822SAbhijit Gangurde ionic_put_cmb(dev->lif_cfg.lif, qp->rq_cmb_pgid, qp->rq_cmb_order); 2004*e8521822SAbhijit Gangurde } 2005*e8521822SAbhijit Gangurde 2006*e8521822SAbhijit Gangurde static int ionic_qp_rq_init(struct ionic_ibdev *dev, struct ionic_ctx *ctx, 2007*e8521822SAbhijit Gangurde struct ionic_qp *qp, struct ionic_qdesc *rq, 2008*e8521822SAbhijit Gangurde struct ionic_tbl_buf *buf, int max_wr, int max_sge, 2009*e8521822SAbhijit Gangurde int rq_spec, struct ib_udata *udata) 2010*e8521822SAbhijit Gangurde { 2011*e8521822SAbhijit Gangurde int rc = 0, i; 2012*e8521822SAbhijit Gangurde u32 wqe_size; 2013*e8521822SAbhijit Gangurde 2014*e8521822SAbhijit Gangurde if (!qp->has_rq) { 2015*e8521822SAbhijit Gangurde if (buf) { 2016*e8521822SAbhijit Gangurde buf->tbl_buf = NULL; 2017*e8521822SAbhijit Gangurde buf->tbl_limit = 0; 2018*e8521822SAbhijit Gangurde buf->tbl_pages = 0; 2019*e8521822SAbhijit Gangurde } 2020*e8521822SAbhijit Gangurde if (udata) 2021*e8521822SAbhijit Gangurde rc = ionic_validate_qdesc_zero(rq); 2022*e8521822SAbhijit Gangurde 2023*e8521822SAbhijit Gangurde return rc; 2024*e8521822SAbhijit Gangurde } 2025*e8521822SAbhijit Gangurde 2026*e8521822SAbhijit Gangurde rc = -EINVAL; 2027*e8521822SAbhijit Gangurde 2028*e8521822SAbhijit Gangurde if (max_wr < 0 || max_wr > 0xffff) 2029*e8521822SAbhijit Gangurde return rc; 2030*e8521822SAbhijit Gangurde 2031*e8521822SAbhijit Gangurde if (max_sge < 1) 2032*e8521822SAbhijit Gangurde return rc; 2033*e8521822SAbhijit Gangurde 2034*e8521822SAbhijit Gangurde if (max_sge > min(ionic_v1_recv_wqe_max_sge(dev->lif_cfg.max_stride, 0, false), 2035*e8521822SAbhijit Gangurde IONIC_SPEC_HIGH)) 2036*e8521822SAbhijit Gangurde return rc; 2037*e8521822SAbhijit Gangurde 2038*e8521822SAbhijit Gangurde if (udata) { 2039*e8521822SAbhijit Gangurde rc = ionic_validate_qdesc(rq); 2040*e8521822SAbhijit Gangurde if (rc) 2041*e8521822SAbhijit Gangurde return rc; 2042*e8521822SAbhijit Gangurde 2043*e8521822SAbhijit Gangurde qp->rq_spec = rq_spec; 2044*e8521822SAbhijit Gangurde 2045*e8521822SAbhijit Gangurde qp->rq.ptr = NULL; 2046*e8521822SAbhijit Gangurde qp->rq.size = rq->size; 2047*e8521822SAbhijit Gangurde qp->rq.mask = rq->mask; 2048*e8521822SAbhijit Gangurde qp->rq.depth_log2 = rq->depth_log2; 2049*e8521822SAbhijit Gangurde qp->rq.stride_log2 = rq->stride_log2; 2050*e8521822SAbhijit Gangurde 2051*e8521822SAbhijit Gangurde qp->rq_meta = NULL; 2052*e8521822SAbhijit Gangurde 2053*e8521822SAbhijit Gangurde qp->rq_umem = ib_umem_get(&dev->ibdev, rq->addr, rq->size, 0); 2054*e8521822SAbhijit Gangurde if (IS_ERR(qp->rq_umem)) 2055*e8521822SAbhijit Gangurde return PTR_ERR(qp->rq_umem); 2056*e8521822SAbhijit Gangurde } else { 2057*e8521822SAbhijit Gangurde qp->rq_umem = NULL; 2058*e8521822SAbhijit Gangurde 2059*e8521822SAbhijit Gangurde qp->rq_spec = ionic_v1_use_spec_sge(max_sge, rq_spec); 2060*e8521822SAbhijit Gangurde if (rq_spec && !qp->rq_spec) 2061*e8521822SAbhijit Gangurde ibdev_dbg(&dev->ibdev, 2062*e8521822SAbhijit Gangurde "init rq: max_sge %u disables spec\n", 2063*e8521822SAbhijit Gangurde max_sge); 2064*e8521822SAbhijit Gangurde 2065*e8521822SAbhijit Gangurde if (qp->rq_cmb & IONIC_CMB_EXPDB) { 2066*e8521822SAbhijit Gangurde wqe_size = ionic_v1_recv_wqe_min_size(max_sge, 2067*e8521822SAbhijit Gangurde qp->rq_spec, 2068*e8521822SAbhijit Gangurde true); 2069*e8521822SAbhijit Gangurde 2070*e8521822SAbhijit Gangurde if (!ionic_expdb_wqe_size_supported(dev, wqe_size)) 2071*e8521822SAbhijit Gangurde qp->rq_cmb &= ~IONIC_CMB_EXPDB; 2072*e8521822SAbhijit Gangurde } 2073*e8521822SAbhijit Gangurde 2074*e8521822SAbhijit Gangurde if (!(qp->rq_cmb & IONIC_CMB_EXPDB)) 2075*e8521822SAbhijit Gangurde wqe_size = ionic_v1_recv_wqe_min_size(max_sge, 2076*e8521822SAbhijit Gangurde qp->rq_spec, 2077*e8521822SAbhijit Gangurde false); 2078*e8521822SAbhijit Gangurde 2079*e8521822SAbhijit Gangurde rc = ionic_queue_init(&qp->rq, dev->lif_cfg.hwdev, 2080*e8521822SAbhijit Gangurde max_wr, wqe_size); 2081*e8521822SAbhijit Gangurde if (rc) 2082*e8521822SAbhijit Gangurde return rc; 2083*e8521822SAbhijit Gangurde 2084*e8521822SAbhijit Gangurde ionic_queue_dbell_init(&qp->rq, qp->qpid); 2085*e8521822SAbhijit Gangurde 2086*e8521822SAbhijit Gangurde qp->rq_meta = kmalloc_array((u32)qp->rq.mask + 1, 2087*e8521822SAbhijit Gangurde sizeof(*qp->rq_meta), 2088*e8521822SAbhijit Gangurde GFP_KERNEL); 2089*e8521822SAbhijit Gangurde if (!qp->rq_meta) { 2090*e8521822SAbhijit Gangurde rc = -ENOMEM; 2091*e8521822SAbhijit Gangurde goto err_rq_meta; 2092*e8521822SAbhijit Gangurde } 2093*e8521822SAbhijit Gangurde 2094*e8521822SAbhijit Gangurde for (i = 0; i < qp->rq.mask; ++i) 2095*e8521822SAbhijit Gangurde qp->rq_meta[i].next = &qp->rq_meta[i + 1]; 2096*e8521822SAbhijit Gangurde qp->rq_meta[i].next = IONIC_META_LAST; 2097*e8521822SAbhijit Gangurde qp->rq_meta_head = &qp->rq_meta[0]; 2098*e8521822SAbhijit Gangurde } 2099*e8521822SAbhijit Gangurde 2100*e8521822SAbhijit Gangurde ionic_qp_rq_init_cmb(dev, qp, udata); 2101*e8521822SAbhijit Gangurde 2102*e8521822SAbhijit Gangurde if (qp->rq_cmb & IONIC_CMB_ENABLE) 2103*e8521822SAbhijit Gangurde rc = ionic_pgtbl_init(dev, buf, NULL, 2104*e8521822SAbhijit Gangurde (u64)qp->rq_cmb_pgid << PAGE_SHIFT, 2105*e8521822SAbhijit Gangurde 1, PAGE_SIZE); 2106*e8521822SAbhijit Gangurde else 2107*e8521822SAbhijit Gangurde rc = ionic_pgtbl_init(dev, buf, 2108*e8521822SAbhijit Gangurde qp->rq_umem, qp->rq.dma, 1, PAGE_SIZE); 2109*e8521822SAbhijit Gangurde if (rc) 2110*e8521822SAbhijit Gangurde goto err_rq_tbl; 2111*e8521822SAbhijit Gangurde 2112*e8521822SAbhijit Gangurde return 0; 2113*e8521822SAbhijit Gangurde 2114*e8521822SAbhijit Gangurde err_rq_tbl: 2115*e8521822SAbhijit Gangurde ionic_qp_rq_destroy_cmb(dev, ctx, qp); 2116*e8521822SAbhijit Gangurde kfree(qp->rq_meta); 2117*e8521822SAbhijit Gangurde err_rq_meta: 2118*e8521822SAbhijit Gangurde if (qp->rq_umem) 2119*e8521822SAbhijit Gangurde ib_umem_release(qp->rq_umem); 2120*e8521822SAbhijit Gangurde else 2121*e8521822SAbhijit Gangurde ionic_queue_destroy(&qp->rq, dev->lif_cfg.hwdev); 2122*e8521822SAbhijit Gangurde return rc; 2123*e8521822SAbhijit Gangurde } 2124*e8521822SAbhijit Gangurde 2125*e8521822SAbhijit Gangurde static void ionic_qp_rq_destroy(struct ionic_ibdev *dev, 2126*e8521822SAbhijit Gangurde struct ionic_ctx *ctx, 2127*e8521822SAbhijit Gangurde struct ionic_qp *qp) 2128*e8521822SAbhijit Gangurde { 2129*e8521822SAbhijit Gangurde if (!qp->has_rq) 2130*e8521822SAbhijit Gangurde return; 2131*e8521822SAbhijit Gangurde 2132*e8521822SAbhijit Gangurde ionic_qp_rq_destroy_cmb(dev, ctx, qp); 2133*e8521822SAbhijit Gangurde 2134*e8521822SAbhijit Gangurde kfree(qp->rq_meta); 2135*e8521822SAbhijit Gangurde 2136*e8521822SAbhijit Gangurde if (qp->rq_umem) 2137*e8521822SAbhijit Gangurde ib_umem_release(qp->rq_umem); 2138*e8521822SAbhijit Gangurde else 2139*e8521822SAbhijit Gangurde ionic_queue_destroy(&qp->rq, dev->lif_cfg.hwdev); 2140*e8521822SAbhijit Gangurde } 2141*e8521822SAbhijit Gangurde 2142*e8521822SAbhijit Gangurde int ionic_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attr, 2143*e8521822SAbhijit Gangurde struct ib_udata *udata) 2144*e8521822SAbhijit Gangurde { 2145*e8521822SAbhijit Gangurde struct ionic_ibdev *dev = to_ionic_ibdev(ibqp->device); 2146*e8521822SAbhijit Gangurde struct ionic_tbl_buf sq_buf = {}, rq_buf = {}; 2147*e8521822SAbhijit Gangurde struct ionic_pd *pd = to_ionic_pd(ibqp->pd); 2148*e8521822SAbhijit Gangurde struct ionic_qp *qp = to_ionic_qp(ibqp); 2149*e8521822SAbhijit Gangurde struct ionic_ctx *ctx = 2150*e8521822SAbhijit Gangurde rdma_udata_to_drv_context(udata, struct ionic_ctx, ibctx); 2151*e8521822SAbhijit Gangurde struct ionic_qp_resp resp = {}; 2152*e8521822SAbhijit Gangurde struct ionic_qp_req req = {}; 2153*e8521822SAbhijit Gangurde struct ionic_cq *cq; 2154*e8521822SAbhijit Gangurde u8 udma_mask; 2155*e8521822SAbhijit Gangurde void *entry; 2156*e8521822SAbhijit Gangurde int rc; 2157*e8521822SAbhijit Gangurde 2158*e8521822SAbhijit Gangurde if (udata) { 2159*e8521822SAbhijit Gangurde rc = ib_copy_from_udata(&req, udata, sizeof(req)); 2160*e8521822SAbhijit Gangurde if (rc) 2161*e8521822SAbhijit Gangurde return rc; 2162*e8521822SAbhijit Gangurde } else { 2163*e8521822SAbhijit Gangurde req.sq_spec = IONIC_SPEC_HIGH; 2164*e8521822SAbhijit Gangurde req.rq_spec = IONIC_SPEC_HIGH; 2165*e8521822SAbhijit Gangurde } 2166*e8521822SAbhijit Gangurde 2167*e8521822SAbhijit Gangurde if (attr->qp_type == IB_QPT_SMI || attr->qp_type > IB_QPT_UD) 2168*e8521822SAbhijit Gangurde return -EOPNOTSUPP; 2169*e8521822SAbhijit Gangurde 2170*e8521822SAbhijit Gangurde qp->state = IB_QPS_RESET; 2171*e8521822SAbhijit Gangurde 2172*e8521822SAbhijit Gangurde INIT_LIST_HEAD(&qp->cq_poll_sq); 2173*e8521822SAbhijit Gangurde INIT_LIST_HEAD(&qp->cq_flush_sq); 2174*e8521822SAbhijit Gangurde INIT_LIST_HEAD(&qp->cq_flush_rq); 2175*e8521822SAbhijit Gangurde 2176*e8521822SAbhijit Gangurde spin_lock_init(&qp->sq_lock); 2177*e8521822SAbhijit Gangurde spin_lock_init(&qp->rq_lock); 2178*e8521822SAbhijit Gangurde 2179*e8521822SAbhijit Gangurde qp->has_sq = 1; 2180*e8521822SAbhijit Gangurde qp->has_rq = 1; 2181*e8521822SAbhijit Gangurde 2182*e8521822SAbhijit Gangurde if (attr->qp_type == IB_QPT_GSI) { 2183*e8521822SAbhijit Gangurde rc = ionic_get_gsi_qpid(dev, &qp->qpid); 2184*e8521822SAbhijit Gangurde } else { 2185*e8521822SAbhijit Gangurde udma_mask = BIT(dev->lif_cfg.udma_count) - 1; 2186*e8521822SAbhijit Gangurde 2187*e8521822SAbhijit Gangurde if (qp->has_sq) 2188*e8521822SAbhijit Gangurde udma_mask &= to_ionic_vcq(attr->send_cq)->udma_mask; 2189*e8521822SAbhijit Gangurde 2190*e8521822SAbhijit Gangurde if (qp->has_rq) 2191*e8521822SAbhijit Gangurde udma_mask &= to_ionic_vcq(attr->recv_cq)->udma_mask; 2192*e8521822SAbhijit Gangurde 2193*e8521822SAbhijit Gangurde if (udata && req.udma_mask) 2194*e8521822SAbhijit Gangurde udma_mask &= req.udma_mask; 2195*e8521822SAbhijit Gangurde 2196*e8521822SAbhijit Gangurde if (!udma_mask) 2197*e8521822SAbhijit Gangurde return -EINVAL; 2198*e8521822SAbhijit Gangurde 2199*e8521822SAbhijit Gangurde rc = ionic_get_qpid(dev, &qp->qpid, &qp->udma_idx, udma_mask); 2200*e8521822SAbhijit Gangurde } 2201*e8521822SAbhijit Gangurde if (rc) 2202*e8521822SAbhijit Gangurde return rc; 2203*e8521822SAbhijit Gangurde 2204*e8521822SAbhijit Gangurde qp->sig_all = attr->sq_sig_type == IB_SIGNAL_ALL_WR; 2205*e8521822SAbhijit Gangurde qp->has_ah = attr->qp_type == IB_QPT_RC; 2206*e8521822SAbhijit Gangurde 2207*e8521822SAbhijit Gangurde if (qp->has_ah) { 2208*e8521822SAbhijit Gangurde qp->hdr = kzalloc(sizeof(*qp->hdr), GFP_KERNEL); 2209*e8521822SAbhijit Gangurde if (!qp->hdr) { 2210*e8521822SAbhijit Gangurde rc = -ENOMEM; 2211*e8521822SAbhijit Gangurde goto err_ah_alloc; 2212*e8521822SAbhijit Gangurde } 2213*e8521822SAbhijit Gangurde 2214*e8521822SAbhijit Gangurde rc = ionic_get_ahid(dev, &qp->ahid); 2215*e8521822SAbhijit Gangurde if (rc) 2216*e8521822SAbhijit Gangurde goto err_ahid; 2217*e8521822SAbhijit Gangurde } 2218*e8521822SAbhijit Gangurde 2219*e8521822SAbhijit Gangurde if (udata) { 2220*e8521822SAbhijit Gangurde if (req.rq_cmb & IONIC_CMB_ENABLE) 2221*e8521822SAbhijit Gangurde qp->rq_cmb = req.rq_cmb; 2222*e8521822SAbhijit Gangurde 2223*e8521822SAbhijit Gangurde if (req.sq_cmb & IONIC_CMB_ENABLE) 2224*e8521822SAbhijit Gangurde qp->sq_cmb = req.sq_cmb; 2225*e8521822SAbhijit Gangurde } 2226*e8521822SAbhijit Gangurde 2227*e8521822SAbhijit Gangurde rc = ionic_qp_sq_init(dev, ctx, qp, &req.sq, &sq_buf, 2228*e8521822SAbhijit Gangurde attr->cap.max_send_wr, attr->cap.max_send_sge, 2229*e8521822SAbhijit Gangurde attr->cap.max_inline_data, req.sq_spec, udata); 2230*e8521822SAbhijit Gangurde if (rc) 2231*e8521822SAbhijit Gangurde goto err_sq; 2232*e8521822SAbhijit Gangurde 2233*e8521822SAbhijit Gangurde rc = ionic_qp_rq_init(dev, ctx, qp, &req.rq, &rq_buf, 2234*e8521822SAbhijit Gangurde attr->cap.max_recv_wr, attr->cap.max_recv_sge, 2235*e8521822SAbhijit Gangurde req.rq_spec, udata); 2236*e8521822SAbhijit Gangurde if (rc) 2237*e8521822SAbhijit Gangurde goto err_rq; 2238*e8521822SAbhijit Gangurde 2239*e8521822SAbhijit Gangurde rc = ionic_create_qp_cmd(dev, pd, 2240*e8521822SAbhijit Gangurde to_ionic_vcq_cq(attr->send_cq, qp->udma_idx), 2241*e8521822SAbhijit Gangurde to_ionic_vcq_cq(attr->recv_cq, qp->udma_idx), 2242*e8521822SAbhijit Gangurde qp, &sq_buf, &rq_buf, attr); 2243*e8521822SAbhijit Gangurde if (rc) 2244*e8521822SAbhijit Gangurde goto err_cmd; 2245*e8521822SAbhijit Gangurde 2246*e8521822SAbhijit Gangurde if (udata) { 2247*e8521822SAbhijit Gangurde resp.qpid = qp->qpid; 2248*e8521822SAbhijit Gangurde resp.udma_idx = qp->udma_idx; 2249*e8521822SAbhijit Gangurde 2250*e8521822SAbhijit Gangurde if (qp->sq_cmb & IONIC_CMB_ENABLE) { 2251*e8521822SAbhijit Gangurde bool wc; 2252*e8521822SAbhijit Gangurde 2253*e8521822SAbhijit Gangurde if ((qp->sq_cmb & (IONIC_CMB_WC | IONIC_CMB_UC)) == 2254*e8521822SAbhijit Gangurde (IONIC_CMB_WC | IONIC_CMB_UC)) { 2255*e8521822SAbhijit Gangurde ibdev_dbg(&dev->ibdev, 2256*e8521822SAbhijit Gangurde "Both sq_cmb flags IONIC_CMB_WC and IONIC_CMB_UC are set, using default driver mapping\n"); 2257*e8521822SAbhijit Gangurde qp->sq_cmb &= ~(IONIC_CMB_WC | IONIC_CMB_UC); 2258*e8521822SAbhijit Gangurde } 2259*e8521822SAbhijit Gangurde 2260*e8521822SAbhijit Gangurde wc = (qp->sq_cmb & (IONIC_CMB_WC | IONIC_CMB_UC)) 2261*e8521822SAbhijit Gangurde != IONIC_CMB_UC; 2262*e8521822SAbhijit Gangurde 2263*e8521822SAbhijit Gangurde /* let userspace know the mapping */ 2264*e8521822SAbhijit Gangurde if (wc) 2265*e8521822SAbhijit Gangurde qp->sq_cmb |= IONIC_CMB_WC; 2266*e8521822SAbhijit Gangurde else 2267*e8521822SAbhijit Gangurde qp->sq_cmb |= IONIC_CMB_UC; 2268*e8521822SAbhijit Gangurde 2269*e8521822SAbhijit Gangurde qp->mmap_sq_cmb = 2270*e8521822SAbhijit Gangurde ionic_mmap_entry_insert(ctx, 2271*e8521822SAbhijit Gangurde qp->sq.size, 2272*e8521822SAbhijit Gangurde PHYS_PFN(qp->sq_cmb_addr), 2273*e8521822SAbhijit Gangurde wc ? IONIC_MMAP_WC : 0, 2274*e8521822SAbhijit Gangurde &resp.sq_cmb_offset); 2275*e8521822SAbhijit Gangurde if (!qp->mmap_sq_cmb) { 2276*e8521822SAbhijit Gangurde rc = -ENOMEM; 2277*e8521822SAbhijit Gangurde goto err_mmap_sq; 2278*e8521822SAbhijit Gangurde } 2279*e8521822SAbhijit Gangurde 2280*e8521822SAbhijit Gangurde resp.sq_cmb = qp->sq_cmb; 2281*e8521822SAbhijit Gangurde } 2282*e8521822SAbhijit Gangurde 2283*e8521822SAbhijit Gangurde if (qp->rq_cmb & IONIC_CMB_ENABLE) { 2284*e8521822SAbhijit Gangurde bool wc; 2285*e8521822SAbhijit Gangurde 2286*e8521822SAbhijit Gangurde if ((qp->rq_cmb & (IONIC_CMB_WC | IONIC_CMB_UC)) == 2287*e8521822SAbhijit Gangurde (IONIC_CMB_WC | IONIC_CMB_UC)) { 2288*e8521822SAbhijit Gangurde ibdev_dbg(&dev->ibdev, 2289*e8521822SAbhijit Gangurde "Both rq_cmb flags IONIC_CMB_WC and IONIC_CMB_UC are set, using default driver mapping\n"); 2290*e8521822SAbhijit Gangurde qp->rq_cmb &= ~(IONIC_CMB_WC | IONIC_CMB_UC); 2291*e8521822SAbhijit Gangurde } 2292*e8521822SAbhijit Gangurde 2293*e8521822SAbhijit Gangurde if (qp->rq_cmb & IONIC_CMB_EXPDB) 2294*e8521822SAbhijit Gangurde wc = (qp->rq_cmb & (IONIC_CMB_WC | IONIC_CMB_UC)) 2295*e8521822SAbhijit Gangurde == IONIC_CMB_WC; 2296*e8521822SAbhijit Gangurde else 2297*e8521822SAbhijit Gangurde wc = (qp->rq_cmb & (IONIC_CMB_WC | IONIC_CMB_UC)) 2298*e8521822SAbhijit Gangurde != IONIC_CMB_UC; 2299*e8521822SAbhijit Gangurde 2300*e8521822SAbhijit Gangurde /* let userspace know the mapping */ 2301*e8521822SAbhijit Gangurde if (wc) 2302*e8521822SAbhijit Gangurde qp->rq_cmb |= IONIC_CMB_WC; 2303*e8521822SAbhijit Gangurde else 2304*e8521822SAbhijit Gangurde qp->rq_cmb |= IONIC_CMB_UC; 2305*e8521822SAbhijit Gangurde 2306*e8521822SAbhijit Gangurde qp->mmap_rq_cmb = 2307*e8521822SAbhijit Gangurde ionic_mmap_entry_insert(ctx, 2308*e8521822SAbhijit Gangurde qp->rq.size, 2309*e8521822SAbhijit Gangurde PHYS_PFN(qp->rq_cmb_addr), 2310*e8521822SAbhijit Gangurde wc ? IONIC_MMAP_WC : 0, 2311*e8521822SAbhijit Gangurde &resp.rq_cmb_offset); 2312*e8521822SAbhijit Gangurde if (!qp->mmap_rq_cmb) { 2313*e8521822SAbhijit Gangurde rc = -ENOMEM; 2314*e8521822SAbhijit Gangurde goto err_mmap_rq; 2315*e8521822SAbhijit Gangurde } 2316*e8521822SAbhijit Gangurde 2317*e8521822SAbhijit Gangurde resp.rq_cmb = qp->rq_cmb; 2318*e8521822SAbhijit Gangurde } 2319*e8521822SAbhijit Gangurde 2320*e8521822SAbhijit Gangurde rc = ib_copy_to_udata(udata, &resp, sizeof(resp)); 2321*e8521822SAbhijit Gangurde if (rc) 2322*e8521822SAbhijit Gangurde goto err_resp; 2323*e8521822SAbhijit Gangurde } 2324*e8521822SAbhijit Gangurde 2325*e8521822SAbhijit Gangurde ionic_pgtbl_unbuf(dev, &rq_buf); 2326*e8521822SAbhijit Gangurde ionic_pgtbl_unbuf(dev, &sq_buf); 2327*e8521822SAbhijit Gangurde 2328*e8521822SAbhijit Gangurde qp->ibqp.qp_num = qp->qpid; 2329*e8521822SAbhijit Gangurde 2330*e8521822SAbhijit Gangurde init_completion(&qp->qp_rel_comp); 2331*e8521822SAbhijit Gangurde kref_init(&qp->qp_kref); 2332*e8521822SAbhijit Gangurde 2333*e8521822SAbhijit Gangurde entry = xa_store_irq(&dev->qp_tbl, qp->qpid, qp, GFP_KERNEL); 2334*e8521822SAbhijit Gangurde if (entry) { 2335*e8521822SAbhijit Gangurde if (!xa_is_err(entry)) 2336*e8521822SAbhijit Gangurde rc = -EINVAL; 2337*e8521822SAbhijit Gangurde else 2338*e8521822SAbhijit Gangurde rc = xa_err(entry); 2339*e8521822SAbhijit Gangurde 2340*e8521822SAbhijit Gangurde goto err_resp; 2341*e8521822SAbhijit Gangurde } 2342*e8521822SAbhijit Gangurde 2343*e8521822SAbhijit Gangurde if (qp->has_sq) { 2344*e8521822SAbhijit Gangurde cq = to_ionic_vcq_cq(attr->send_cq, qp->udma_idx); 2345*e8521822SAbhijit Gangurde 2346*e8521822SAbhijit Gangurde attr->cap.max_send_wr = qp->sq.mask; 2347*e8521822SAbhijit Gangurde attr->cap.max_send_sge = 2348*e8521822SAbhijit Gangurde ionic_v1_send_wqe_max_sge(qp->sq.stride_log2, 2349*e8521822SAbhijit Gangurde qp->sq_spec, 2350*e8521822SAbhijit Gangurde qp->sq_cmb & IONIC_CMB_EXPDB); 2351*e8521822SAbhijit Gangurde attr->cap.max_inline_data = 2352*e8521822SAbhijit Gangurde ionic_v1_send_wqe_max_data(qp->sq.stride_log2, 2353*e8521822SAbhijit Gangurde qp->sq_cmb & 2354*e8521822SAbhijit Gangurde IONIC_CMB_EXPDB); 2355*e8521822SAbhijit Gangurde qp->sq_cqid = cq->cqid; 2356*e8521822SAbhijit Gangurde } 2357*e8521822SAbhijit Gangurde 2358*e8521822SAbhijit Gangurde if (qp->has_rq) { 2359*e8521822SAbhijit Gangurde cq = to_ionic_vcq_cq(attr->recv_cq, qp->udma_idx); 2360*e8521822SAbhijit Gangurde 2361*e8521822SAbhijit Gangurde attr->cap.max_recv_wr = qp->rq.mask; 2362*e8521822SAbhijit Gangurde attr->cap.max_recv_sge = 2363*e8521822SAbhijit Gangurde ionic_v1_recv_wqe_max_sge(qp->rq.stride_log2, 2364*e8521822SAbhijit Gangurde qp->rq_spec, 2365*e8521822SAbhijit Gangurde qp->rq_cmb & IONIC_CMB_EXPDB); 2366*e8521822SAbhijit Gangurde qp->rq_cqid = cq->cqid; 2367*e8521822SAbhijit Gangurde } 2368*e8521822SAbhijit Gangurde 2369*e8521822SAbhijit Gangurde return 0; 2370*e8521822SAbhijit Gangurde 2371*e8521822SAbhijit Gangurde err_resp: 2372*e8521822SAbhijit Gangurde if (udata && (qp->rq_cmb & IONIC_CMB_ENABLE)) 2373*e8521822SAbhijit Gangurde rdma_user_mmap_entry_remove(qp->mmap_rq_cmb); 2374*e8521822SAbhijit Gangurde err_mmap_rq: 2375*e8521822SAbhijit Gangurde if (udata && (qp->sq_cmb & IONIC_CMB_ENABLE)) 2376*e8521822SAbhijit Gangurde rdma_user_mmap_entry_remove(qp->mmap_sq_cmb); 2377*e8521822SAbhijit Gangurde err_mmap_sq: 2378*e8521822SAbhijit Gangurde ionic_destroy_qp_cmd(dev, qp->qpid); 2379*e8521822SAbhijit Gangurde err_cmd: 2380*e8521822SAbhijit Gangurde ionic_pgtbl_unbuf(dev, &rq_buf); 2381*e8521822SAbhijit Gangurde ionic_qp_rq_destroy(dev, ctx, qp); 2382*e8521822SAbhijit Gangurde err_rq: 2383*e8521822SAbhijit Gangurde ionic_pgtbl_unbuf(dev, &sq_buf); 2384*e8521822SAbhijit Gangurde ionic_qp_sq_destroy(dev, ctx, qp); 2385*e8521822SAbhijit Gangurde err_sq: 2386*e8521822SAbhijit Gangurde if (qp->has_ah) 2387*e8521822SAbhijit Gangurde ionic_put_ahid(dev, qp->ahid); 2388*e8521822SAbhijit Gangurde err_ahid: 2389*e8521822SAbhijit Gangurde kfree(qp->hdr); 2390*e8521822SAbhijit Gangurde err_ah_alloc: 2391*e8521822SAbhijit Gangurde ionic_put_qpid(dev, qp->qpid); 2392*e8521822SAbhijit Gangurde return rc; 2393*e8521822SAbhijit Gangurde } 2394*e8521822SAbhijit Gangurde 2395*e8521822SAbhijit Gangurde void ionic_notify_flush_cq(struct ionic_cq *cq) 2396*e8521822SAbhijit Gangurde { 2397*e8521822SAbhijit Gangurde if (cq->flush && cq->vcq->ibcq.comp_handler) 2398*e8521822SAbhijit Gangurde cq->vcq->ibcq.comp_handler(&cq->vcq->ibcq, 2399*e8521822SAbhijit Gangurde cq->vcq->ibcq.cq_context); 2400*e8521822SAbhijit Gangurde } 2401*e8521822SAbhijit Gangurde 2402*e8521822SAbhijit Gangurde static void ionic_notify_qp_cqs(struct ionic_ibdev *dev, struct ionic_qp *qp) 2403*e8521822SAbhijit Gangurde { 2404*e8521822SAbhijit Gangurde if (qp->ibqp.send_cq) 2405*e8521822SAbhijit Gangurde ionic_notify_flush_cq(to_ionic_vcq_cq(qp->ibqp.send_cq, 2406*e8521822SAbhijit Gangurde qp->udma_idx)); 2407*e8521822SAbhijit Gangurde if (qp->ibqp.recv_cq && qp->ibqp.recv_cq != qp->ibqp.send_cq) 2408*e8521822SAbhijit Gangurde ionic_notify_flush_cq(to_ionic_vcq_cq(qp->ibqp.recv_cq, 2409*e8521822SAbhijit Gangurde qp->udma_idx)); 2410*e8521822SAbhijit Gangurde } 2411*e8521822SAbhijit Gangurde 2412*e8521822SAbhijit Gangurde void ionic_flush_qp(struct ionic_ibdev *dev, struct ionic_qp *qp) 2413*e8521822SAbhijit Gangurde { 2414*e8521822SAbhijit Gangurde unsigned long irqflags; 2415*e8521822SAbhijit Gangurde struct ionic_cq *cq; 2416*e8521822SAbhijit Gangurde 2417*e8521822SAbhijit Gangurde if (qp->ibqp.send_cq) { 2418*e8521822SAbhijit Gangurde cq = to_ionic_vcq_cq(qp->ibqp.send_cq, qp->udma_idx); 2419*e8521822SAbhijit Gangurde 2420*e8521822SAbhijit Gangurde /* Hold the CQ lock and QP sq_lock to set up flush */ 2421*e8521822SAbhijit Gangurde spin_lock_irqsave(&cq->lock, irqflags); 2422*e8521822SAbhijit Gangurde spin_lock(&qp->sq_lock); 2423*e8521822SAbhijit Gangurde qp->sq_flush = true; 2424*e8521822SAbhijit Gangurde if (!ionic_queue_empty(&qp->sq)) { 2425*e8521822SAbhijit Gangurde cq->flush = true; 2426*e8521822SAbhijit Gangurde list_move_tail(&qp->cq_flush_sq, &cq->flush_sq); 2427*e8521822SAbhijit Gangurde } 2428*e8521822SAbhijit Gangurde spin_unlock(&qp->sq_lock); 2429*e8521822SAbhijit Gangurde spin_unlock_irqrestore(&cq->lock, irqflags); 2430*e8521822SAbhijit Gangurde } 2431*e8521822SAbhijit Gangurde 2432*e8521822SAbhijit Gangurde if (qp->ibqp.recv_cq) { 2433*e8521822SAbhijit Gangurde cq = to_ionic_vcq_cq(qp->ibqp.recv_cq, qp->udma_idx); 2434*e8521822SAbhijit Gangurde 2435*e8521822SAbhijit Gangurde /* Hold the CQ lock and QP rq_lock to set up flush */ 2436*e8521822SAbhijit Gangurde spin_lock_irqsave(&cq->lock, irqflags); 2437*e8521822SAbhijit Gangurde spin_lock(&qp->rq_lock); 2438*e8521822SAbhijit Gangurde qp->rq_flush = true; 2439*e8521822SAbhijit Gangurde if (!ionic_queue_empty(&qp->rq)) { 2440*e8521822SAbhijit Gangurde cq->flush = true; 2441*e8521822SAbhijit Gangurde list_move_tail(&qp->cq_flush_rq, &cq->flush_rq); 2442*e8521822SAbhijit Gangurde } 2443*e8521822SAbhijit Gangurde spin_unlock(&qp->rq_lock); 2444*e8521822SAbhijit Gangurde spin_unlock_irqrestore(&cq->lock, irqflags); 2445*e8521822SAbhijit Gangurde } 2446*e8521822SAbhijit Gangurde } 2447*e8521822SAbhijit Gangurde 2448*e8521822SAbhijit Gangurde static void ionic_clean_cq(struct ionic_cq *cq, u32 qpid) 2449*e8521822SAbhijit Gangurde { 2450*e8521822SAbhijit Gangurde struct ionic_v1_cqe *qcqe; 2451*e8521822SAbhijit Gangurde int prod, qtf, qid, type; 2452*e8521822SAbhijit Gangurde bool color; 2453*e8521822SAbhijit Gangurde 2454*e8521822SAbhijit Gangurde if (!cq->q.ptr) 2455*e8521822SAbhijit Gangurde return; 2456*e8521822SAbhijit Gangurde 2457*e8521822SAbhijit Gangurde color = cq->color; 2458*e8521822SAbhijit Gangurde prod = cq->q.prod; 2459*e8521822SAbhijit Gangurde qcqe = ionic_queue_at(&cq->q, prod); 2460*e8521822SAbhijit Gangurde 2461*e8521822SAbhijit Gangurde while (color == ionic_v1_cqe_color(qcqe)) { 2462*e8521822SAbhijit Gangurde qtf = ionic_v1_cqe_qtf(qcqe); 2463*e8521822SAbhijit Gangurde qid = ionic_v1_cqe_qtf_qid(qtf); 2464*e8521822SAbhijit Gangurde type = ionic_v1_cqe_qtf_type(qtf); 2465*e8521822SAbhijit Gangurde 2466*e8521822SAbhijit Gangurde if (qid == qpid && type != IONIC_V1_CQE_TYPE_ADMIN) 2467*e8521822SAbhijit Gangurde ionic_v1_cqe_clean(qcqe); 2468*e8521822SAbhijit Gangurde 2469*e8521822SAbhijit Gangurde prod = ionic_queue_next(&cq->q, prod); 2470*e8521822SAbhijit Gangurde qcqe = ionic_queue_at(&cq->q, prod); 2471*e8521822SAbhijit Gangurde color = ionic_color_wrap(prod, color); 2472*e8521822SAbhijit Gangurde } 2473*e8521822SAbhijit Gangurde } 2474*e8521822SAbhijit Gangurde 2475*e8521822SAbhijit Gangurde static void ionic_reset_qp(struct ionic_ibdev *dev, struct ionic_qp *qp) 2476*e8521822SAbhijit Gangurde { 2477*e8521822SAbhijit Gangurde unsigned long irqflags; 2478*e8521822SAbhijit Gangurde struct ionic_cq *cq; 2479*e8521822SAbhijit Gangurde int i; 2480*e8521822SAbhijit Gangurde 2481*e8521822SAbhijit Gangurde local_irq_save(irqflags); 2482*e8521822SAbhijit Gangurde 2483*e8521822SAbhijit Gangurde if (qp->ibqp.send_cq) { 2484*e8521822SAbhijit Gangurde cq = to_ionic_vcq_cq(qp->ibqp.send_cq, qp->udma_idx); 2485*e8521822SAbhijit Gangurde spin_lock(&cq->lock); 2486*e8521822SAbhijit Gangurde ionic_clean_cq(cq, qp->qpid); 2487*e8521822SAbhijit Gangurde spin_unlock(&cq->lock); 2488*e8521822SAbhijit Gangurde } 2489*e8521822SAbhijit Gangurde 2490*e8521822SAbhijit Gangurde if (qp->ibqp.recv_cq) { 2491*e8521822SAbhijit Gangurde cq = to_ionic_vcq_cq(qp->ibqp.recv_cq, qp->udma_idx); 2492*e8521822SAbhijit Gangurde spin_lock(&cq->lock); 2493*e8521822SAbhijit Gangurde ionic_clean_cq(cq, qp->qpid); 2494*e8521822SAbhijit Gangurde spin_unlock(&cq->lock); 2495*e8521822SAbhijit Gangurde } 2496*e8521822SAbhijit Gangurde 2497*e8521822SAbhijit Gangurde if (qp->has_sq) { 2498*e8521822SAbhijit Gangurde spin_lock(&qp->sq_lock); 2499*e8521822SAbhijit Gangurde qp->sq_flush = false; 2500*e8521822SAbhijit Gangurde qp->sq_flush_rcvd = false; 2501*e8521822SAbhijit Gangurde qp->sq_msn_prod = 0; 2502*e8521822SAbhijit Gangurde qp->sq_msn_cons = 0; 2503*e8521822SAbhijit Gangurde qp->sq.prod = 0; 2504*e8521822SAbhijit Gangurde qp->sq.cons = 0; 2505*e8521822SAbhijit Gangurde spin_unlock(&qp->sq_lock); 2506*e8521822SAbhijit Gangurde } 2507*e8521822SAbhijit Gangurde 2508*e8521822SAbhijit Gangurde if (qp->has_rq) { 2509*e8521822SAbhijit Gangurde spin_lock(&qp->rq_lock); 2510*e8521822SAbhijit Gangurde qp->rq_flush = false; 2511*e8521822SAbhijit Gangurde qp->rq.prod = 0; 2512*e8521822SAbhijit Gangurde qp->rq.cons = 0; 2513*e8521822SAbhijit Gangurde if (qp->rq_meta) { 2514*e8521822SAbhijit Gangurde for (i = 0; i < qp->rq.mask; ++i) 2515*e8521822SAbhijit Gangurde qp->rq_meta[i].next = &qp->rq_meta[i + 1]; 2516*e8521822SAbhijit Gangurde qp->rq_meta[i].next = IONIC_META_LAST; 2517*e8521822SAbhijit Gangurde } 2518*e8521822SAbhijit Gangurde qp->rq_meta_head = &qp->rq_meta[0]; 2519*e8521822SAbhijit Gangurde spin_unlock(&qp->rq_lock); 2520*e8521822SAbhijit Gangurde } 2521*e8521822SAbhijit Gangurde 2522*e8521822SAbhijit Gangurde local_irq_restore(irqflags); 2523*e8521822SAbhijit Gangurde } 2524*e8521822SAbhijit Gangurde 2525*e8521822SAbhijit Gangurde static bool ionic_qp_cur_state_is_ok(enum ib_qp_state q_state, 2526*e8521822SAbhijit Gangurde enum ib_qp_state attr_state) 2527*e8521822SAbhijit Gangurde { 2528*e8521822SAbhijit Gangurde if (q_state == attr_state) 2529*e8521822SAbhijit Gangurde return true; 2530*e8521822SAbhijit Gangurde 2531*e8521822SAbhijit Gangurde if (attr_state == IB_QPS_ERR) 2532*e8521822SAbhijit Gangurde return true; 2533*e8521822SAbhijit Gangurde 2534*e8521822SAbhijit Gangurde if (attr_state == IB_QPS_SQE) 2535*e8521822SAbhijit Gangurde return q_state == IB_QPS_RTS || q_state == IB_QPS_SQD; 2536*e8521822SAbhijit Gangurde 2537*e8521822SAbhijit Gangurde return false; 2538*e8521822SAbhijit Gangurde } 2539*e8521822SAbhijit Gangurde 2540*e8521822SAbhijit Gangurde static int ionic_check_modify_qp(struct ionic_qp *qp, struct ib_qp_attr *attr, 2541*e8521822SAbhijit Gangurde int mask) 2542*e8521822SAbhijit Gangurde { 2543*e8521822SAbhijit Gangurde enum ib_qp_state cur_state = (mask & IB_QP_CUR_STATE) ? 2544*e8521822SAbhijit Gangurde attr->cur_qp_state : qp->state; 2545*e8521822SAbhijit Gangurde enum ib_qp_state next_state = (mask & IB_QP_STATE) ? 2546*e8521822SAbhijit Gangurde attr->qp_state : cur_state; 2547*e8521822SAbhijit Gangurde 2548*e8521822SAbhijit Gangurde if ((mask & IB_QP_CUR_STATE) && 2549*e8521822SAbhijit Gangurde !ionic_qp_cur_state_is_ok(qp->state, attr->cur_qp_state)) 2550*e8521822SAbhijit Gangurde return -EINVAL; 2551*e8521822SAbhijit Gangurde 2552*e8521822SAbhijit Gangurde if (!ib_modify_qp_is_ok(cur_state, next_state, qp->ibqp.qp_type, mask)) 2553*e8521822SAbhijit Gangurde return -EINVAL; 2554*e8521822SAbhijit Gangurde 2555*e8521822SAbhijit Gangurde /* unprivileged qp not allowed privileged qkey */ 2556*e8521822SAbhijit Gangurde if ((mask & IB_QP_QKEY) && (attr->qkey & 0x80000000) && 2557*e8521822SAbhijit Gangurde qp->ibqp.uobject) 2558*e8521822SAbhijit Gangurde return -EPERM; 2559*e8521822SAbhijit Gangurde 2560*e8521822SAbhijit Gangurde return 0; 2561*e8521822SAbhijit Gangurde } 2562*e8521822SAbhijit Gangurde 2563*e8521822SAbhijit Gangurde int ionic_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int mask, 2564*e8521822SAbhijit Gangurde struct ib_udata *udata) 2565*e8521822SAbhijit Gangurde { 2566*e8521822SAbhijit Gangurde struct ionic_ibdev *dev = to_ionic_ibdev(ibqp->device); 2567*e8521822SAbhijit Gangurde struct ionic_pd *pd = to_ionic_pd(ibqp->pd); 2568*e8521822SAbhijit Gangurde struct ionic_qp *qp = to_ionic_qp(ibqp); 2569*e8521822SAbhijit Gangurde int rc; 2570*e8521822SAbhijit Gangurde 2571*e8521822SAbhijit Gangurde rc = ionic_check_modify_qp(qp, attr, mask); 2572*e8521822SAbhijit Gangurde if (rc) 2573*e8521822SAbhijit Gangurde return rc; 2574*e8521822SAbhijit Gangurde 2575*e8521822SAbhijit Gangurde if (mask & IB_QP_CAP) 2576*e8521822SAbhijit Gangurde return -EINVAL; 2577*e8521822SAbhijit Gangurde 2578*e8521822SAbhijit Gangurde rc = ionic_modify_qp_cmd(dev, pd, qp, attr, mask); 2579*e8521822SAbhijit Gangurde if (rc) 2580*e8521822SAbhijit Gangurde return rc; 2581*e8521822SAbhijit Gangurde 2582*e8521822SAbhijit Gangurde if (mask & IB_QP_STATE) { 2583*e8521822SAbhijit Gangurde qp->state = attr->qp_state; 2584*e8521822SAbhijit Gangurde 2585*e8521822SAbhijit Gangurde if (attr->qp_state == IB_QPS_ERR) { 2586*e8521822SAbhijit Gangurde ionic_flush_qp(dev, qp); 2587*e8521822SAbhijit Gangurde ionic_notify_qp_cqs(dev, qp); 2588*e8521822SAbhijit Gangurde } else if (attr->qp_state == IB_QPS_RESET) { 2589*e8521822SAbhijit Gangurde ionic_reset_qp(dev, qp); 2590*e8521822SAbhijit Gangurde } 2591*e8521822SAbhijit Gangurde } 2592*e8521822SAbhijit Gangurde 2593*e8521822SAbhijit Gangurde return 0; 2594*e8521822SAbhijit Gangurde } 2595*e8521822SAbhijit Gangurde 2596*e8521822SAbhijit Gangurde int ionic_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, 2597*e8521822SAbhijit Gangurde int mask, struct ib_qp_init_attr *init_attr) 2598*e8521822SAbhijit Gangurde { 2599*e8521822SAbhijit Gangurde struct ionic_ibdev *dev = to_ionic_ibdev(ibqp->device); 2600*e8521822SAbhijit Gangurde struct ionic_qp *qp = to_ionic_qp(ibqp); 2601*e8521822SAbhijit Gangurde int rc; 2602*e8521822SAbhijit Gangurde 2603*e8521822SAbhijit Gangurde memset(attr, 0, sizeof(*attr)); 2604*e8521822SAbhijit Gangurde memset(init_attr, 0, sizeof(*init_attr)); 2605*e8521822SAbhijit Gangurde 2606*e8521822SAbhijit Gangurde rc = ionic_query_qp_cmd(dev, qp, attr, mask); 2607*e8521822SAbhijit Gangurde if (rc) 2608*e8521822SAbhijit Gangurde return rc; 2609*e8521822SAbhijit Gangurde 2610*e8521822SAbhijit Gangurde if (qp->has_sq) 2611*e8521822SAbhijit Gangurde attr->cap.max_send_wr = qp->sq.mask; 2612*e8521822SAbhijit Gangurde 2613*e8521822SAbhijit Gangurde if (qp->has_rq) 2614*e8521822SAbhijit Gangurde attr->cap.max_recv_wr = qp->rq.mask; 2615*e8521822SAbhijit Gangurde 2616*e8521822SAbhijit Gangurde init_attr->event_handler = ibqp->event_handler; 2617*e8521822SAbhijit Gangurde init_attr->qp_context = ibqp->qp_context; 2618*e8521822SAbhijit Gangurde init_attr->send_cq = ibqp->send_cq; 2619*e8521822SAbhijit Gangurde init_attr->recv_cq = ibqp->recv_cq; 2620*e8521822SAbhijit Gangurde init_attr->srq = ibqp->srq; 2621*e8521822SAbhijit Gangurde init_attr->xrcd = ibqp->xrcd; 2622*e8521822SAbhijit Gangurde init_attr->cap = attr->cap; 2623*e8521822SAbhijit Gangurde init_attr->sq_sig_type = qp->sig_all ? 2624*e8521822SAbhijit Gangurde IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR; 2625*e8521822SAbhijit Gangurde init_attr->qp_type = ibqp->qp_type; 2626*e8521822SAbhijit Gangurde init_attr->create_flags = 0; 2627*e8521822SAbhijit Gangurde init_attr->port_num = 0; 2628*e8521822SAbhijit Gangurde init_attr->rwq_ind_tbl = ibqp->rwq_ind_tbl; 2629*e8521822SAbhijit Gangurde init_attr->source_qpn = 0; 2630*e8521822SAbhijit Gangurde 2631*e8521822SAbhijit Gangurde return rc; 2632*e8521822SAbhijit Gangurde } 2633*e8521822SAbhijit Gangurde 2634*e8521822SAbhijit Gangurde int ionic_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata) 2635*e8521822SAbhijit Gangurde { 2636*e8521822SAbhijit Gangurde struct ionic_ctx *ctx = 2637*e8521822SAbhijit Gangurde rdma_udata_to_drv_context(udata, struct ionic_ctx, ibctx); 2638*e8521822SAbhijit Gangurde struct ionic_ibdev *dev = to_ionic_ibdev(ibqp->device); 2639*e8521822SAbhijit Gangurde struct ionic_qp *qp = to_ionic_qp(ibqp); 2640*e8521822SAbhijit Gangurde unsigned long irqflags; 2641*e8521822SAbhijit Gangurde struct ionic_cq *cq; 2642*e8521822SAbhijit Gangurde int rc; 2643*e8521822SAbhijit Gangurde 2644*e8521822SAbhijit Gangurde rc = ionic_destroy_qp_cmd(dev, qp->qpid); 2645*e8521822SAbhijit Gangurde if (rc) 2646*e8521822SAbhijit Gangurde return rc; 2647*e8521822SAbhijit Gangurde 2648*e8521822SAbhijit Gangurde xa_erase_irq(&dev->qp_tbl, qp->qpid); 2649*e8521822SAbhijit Gangurde 2650*e8521822SAbhijit Gangurde kref_put(&qp->qp_kref, ionic_qp_complete); 2651*e8521822SAbhijit Gangurde wait_for_completion(&qp->qp_rel_comp); 2652*e8521822SAbhijit Gangurde 2653*e8521822SAbhijit Gangurde if (qp->ibqp.send_cq) { 2654*e8521822SAbhijit Gangurde cq = to_ionic_vcq_cq(qp->ibqp.send_cq, qp->udma_idx); 2655*e8521822SAbhijit Gangurde spin_lock_irqsave(&cq->lock, irqflags); 2656*e8521822SAbhijit Gangurde ionic_clean_cq(cq, qp->qpid); 2657*e8521822SAbhijit Gangurde list_del(&qp->cq_poll_sq); 2658*e8521822SAbhijit Gangurde list_del(&qp->cq_flush_sq); 2659*e8521822SAbhijit Gangurde spin_unlock_irqrestore(&cq->lock, irqflags); 2660*e8521822SAbhijit Gangurde } 2661*e8521822SAbhijit Gangurde 2662*e8521822SAbhijit Gangurde if (qp->ibqp.recv_cq) { 2663*e8521822SAbhijit Gangurde cq = to_ionic_vcq_cq(qp->ibqp.recv_cq, qp->udma_idx); 2664*e8521822SAbhijit Gangurde spin_lock_irqsave(&cq->lock, irqflags); 2665*e8521822SAbhijit Gangurde ionic_clean_cq(cq, qp->qpid); 2666*e8521822SAbhijit Gangurde list_del(&qp->cq_flush_rq); 2667*e8521822SAbhijit Gangurde spin_unlock_irqrestore(&cq->lock, irqflags); 2668*e8521822SAbhijit Gangurde } 2669*e8521822SAbhijit Gangurde 2670*e8521822SAbhijit Gangurde ionic_qp_rq_destroy(dev, ctx, qp); 2671*e8521822SAbhijit Gangurde ionic_qp_sq_destroy(dev, ctx, qp); 2672*e8521822SAbhijit Gangurde if (qp->has_ah) { 2673*e8521822SAbhijit Gangurde ionic_put_ahid(dev, qp->ahid); 2674*e8521822SAbhijit Gangurde kfree(qp->hdr); 2675*e8521822SAbhijit Gangurde } 2676*e8521822SAbhijit Gangurde ionic_put_qpid(dev, qp->qpid); 2677*e8521822SAbhijit Gangurde 2678*e8521822SAbhijit Gangurde return 0; 2679*e8521822SAbhijit Gangurde } 2680