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