1*f3bdbd42SAbhijit Gangurde // SPDX-License-Identifier: GPL-2.0 2*f3bdbd42SAbhijit Gangurde /* Copyright (C) 2018-2025, Advanced Micro Devices, Inc. */ 3*f3bdbd42SAbhijit Gangurde 4*f3bdbd42SAbhijit Gangurde #include "ionic_ibdev.h" 5*f3bdbd42SAbhijit Gangurde 6*f3bdbd42SAbhijit Gangurde static int ionic_validate_qdesc(struct ionic_qdesc *q) 7*f3bdbd42SAbhijit Gangurde { 8*f3bdbd42SAbhijit Gangurde if (!q->addr || !q->size || !q->mask || 9*f3bdbd42SAbhijit Gangurde !q->depth_log2 || !q->stride_log2) 10*f3bdbd42SAbhijit Gangurde return -EINVAL; 11*f3bdbd42SAbhijit Gangurde 12*f3bdbd42SAbhijit Gangurde if (q->addr & (PAGE_SIZE - 1)) 13*f3bdbd42SAbhijit Gangurde return -EINVAL; 14*f3bdbd42SAbhijit Gangurde 15*f3bdbd42SAbhijit Gangurde if (q->mask != BIT(q->depth_log2) - 1) 16*f3bdbd42SAbhijit Gangurde return -EINVAL; 17*f3bdbd42SAbhijit Gangurde 18*f3bdbd42SAbhijit Gangurde if (q->size < BIT_ULL(q->depth_log2 + q->stride_log2)) 19*f3bdbd42SAbhijit Gangurde return -EINVAL; 20*f3bdbd42SAbhijit Gangurde 21*f3bdbd42SAbhijit Gangurde return 0; 22*f3bdbd42SAbhijit Gangurde } 23*f3bdbd42SAbhijit Gangurde 24*f3bdbd42SAbhijit Gangurde static u32 ionic_get_eqid(struct ionic_ibdev *dev, u32 comp_vector, u8 udma_idx) 25*f3bdbd42SAbhijit Gangurde { 26*f3bdbd42SAbhijit Gangurde /* EQ per vector per udma, and the first eqs reserved for async events. 27*f3bdbd42SAbhijit Gangurde * The rest of the vectors can be requested for completions. 28*f3bdbd42SAbhijit Gangurde */ 29*f3bdbd42SAbhijit Gangurde u32 comp_vec_count = dev->lif_cfg.eq_count / dev->lif_cfg.udma_count - 1; 30*f3bdbd42SAbhijit Gangurde 31*f3bdbd42SAbhijit Gangurde return (comp_vector % comp_vec_count + 1) * dev->lif_cfg.udma_count + udma_idx; 32*f3bdbd42SAbhijit Gangurde } 33*f3bdbd42SAbhijit Gangurde 34*f3bdbd42SAbhijit Gangurde static int ionic_get_cqid(struct ionic_ibdev *dev, u32 *cqid, u8 udma_idx) 35*f3bdbd42SAbhijit Gangurde { 36*f3bdbd42SAbhijit Gangurde unsigned int size, base, bound; 37*f3bdbd42SAbhijit Gangurde int rc; 38*f3bdbd42SAbhijit Gangurde 39*f3bdbd42SAbhijit Gangurde size = dev->lif_cfg.cq_count / dev->lif_cfg.udma_count; 40*f3bdbd42SAbhijit Gangurde base = size * udma_idx; 41*f3bdbd42SAbhijit Gangurde bound = base + size; 42*f3bdbd42SAbhijit Gangurde 43*f3bdbd42SAbhijit Gangurde rc = ionic_resid_get_shared(&dev->inuse_cqid, base, bound); 44*f3bdbd42SAbhijit Gangurde if (rc >= 0) { 45*f3bdbd42SAbhijit Gangurde /* cq_base is zero or a multiple of two queue groups */ 46*f3bdbd42SAbhijit Gangurde *cqid = dev->lif_cfg.cq_base + 47*f3bdbd42SAbhijit Gangurde ionic_bitid_to_qid(rc, dev->lif_cfg.udma_qgrp_shift, 48*f3bdbd42SAbhijit Gangurde dev->half_cqid_udma_shift); 49*f3bdbd42SAbhijit Gangurde 50*f3bdbd42SAbhijit Gangurde rc = 0; 51*f3bdbd42SAbhijit Gangurde } 52*f3bdbd42SAbhijit Gangurde 53*f3bdbd42SAbhijit Gangurde return rc; 54*f3bdbd42SAbhijit Gangurde } 55*f3bdbd42SAbhijit Gangurde 56*f3bdbd42SAbhijit Gangurde static void ionic_put_cqid(struct ionic_ibdev *dev, u32 cqid) 57*f3bdbd42SAbhijit Gangurde { 58*f3bdbd42SAbhijit Gangurde u32 bitid = ionic_qid_to_bitid(cqid - dev->lif_cfg.cq_base, 59*f3bdbd42SAbhijit Gangurde dev->lif_cfg.udma_qgrp_shift, 60*f3bdbd42SAbhijit Gangurde dev->half_cqid_udma_shift); 61*f3bdbd42SAbhijit Gangurde 62*f3bdbd42SAbhijit Gangurde ionic_resid_put(&dev->inuse_cqid, bitid); 63*f3bdbd42SAbhijit Gangurde } 64*f3bdbd42SAbhijit Gangurde 65*f3bdbd42SAbhijit Gangurde int ionic_create_cq_common(struct ionic_vcq *vcq, 66*f3bdbd42SAbhijit Gangurde struct ionic_tbl_buf *buf, 67*f3bdbd42SAbhijit Gangurde const struct ib_cq_init_attr *attr, 68*f3bdbd42SAbhijit Gangurde struct ionic_ctx *ctx, 69*f3bdbd42SAbhijit Gangurde struct ib_udata *udata, 70*f3bdbd42SAbhijit Gangurde struct ionic_qdesc *req_cq, 71*f3bdbd42SAbhijit Gangurde __u32 *resp_cqid, 72*f3bdbd42SAbhijit Gangurde int udma_idx) 73*f3bdbd42SAbhijit Gangurde { 74*f3bdbd42SAbhijit Gangurde struct ionic_ibdev *dev = to_ionic_ibdev(vcq->ibcq.device); 75*f3bdbd42SAbhijit Gangurde struct ionic_cq *cq = &vcq->cq[udma_idx]; 76*f3bdbd42SAbhijit Gangurde void *entry; 77*f3bdbd42SAbhijit Gangurde int rc; 78*f3bdbd42SAbhijit Gangurde 79*f3bdbd42SAbhijit Gangurde cq->vcq = vcq; 80*f3bdbd42SAbhijit Gangurde 81*f3bdbd42SAbhijit Gangurde if (attr->cqe < 1 || attr->cqe + IONIC_CQ_GRACE > 0xffff) { 82*f3bdbd42SAbhijit Gangurde rc = -EINVAL; 83*f3bdbd42SAbhijit Gangurde goto err_args; 84*f3bdbd42SAbhijit Gangurde } 85*f3bdbd42SAbhijit Gangurde 86*f3bdbd42SAbhijit Gangurde rc = ionic_get_cqid(dev, &cq->cqid, udma_idx); 87*f3bdbd42SAbhijit Gangurde if (rc) 88*f3bdbd42SAbhijit Gangurde goto err_args; 89*f3bdbd42SAbhijit Gangurde 90*f3bdbd42SAbhijit Gangurde cq->eqid = ionic_get_eqid(dev, attr->comp_vector, udma_idx); 91*f3bdbd42SAbhijit Gangurde 92*f3bdbd42SAbhijit Gangurde spin_lock_init(&cq->lock); 93*f3bdbd42SAbhijit Gangurde INIT_LIST_HEAD(&cq->poll_sq); 94*f3bdbd42SAbhijit Gangurde INIT_LIST_HEAD(&cq->flush_sq); 95*f3bdbd42SAbhijit Gangurde INIT_LIST_HEAD(&cq->flush_rq); 96*f3bdbd42SAbhijit Gangurde 97*f3bdbd42SAbhijit Gangurde if (udata) { 98*f3bdbd42SAbhijit Gangurde rc = ionic_validate_qdesc(req_cq); 99*f3bdbd42SAbhijit Gangurde if (rc) 100*f3bdbd42SAbhijit Gangurde goto err_qdesc; 101*f3bdbd42SAbhijit Gangurde 102*f3bdbd42SAbhijit Gangurde cq->umem = ib_umem_get(&dev->ibdev, req_cq->addr, req_cq->size, 103*f3bdbd42SAbhijit Gangurde IB_ACCESS_LOCAL_WRITE); 104*f3bdbd42SAbhijit Gangurde if (IS_ERR(cq->umem)) { 105*f3bdbd42SAbhijit Gangurde rc = PTR_ERR(cq->umem); 106*f3bdbd42SAbhijit Gangurde goto err_qdesc; 107*f3bdbd42SAbhijit Gangurde } 108*f3bdbd42SAbhijit Gangurde 109*f3bdbd42SAbhijit Gangurde cq->q.ptr = NULL; 110*f3bdbd42SAbhijit Gangurde cq->q.size = req_cq->size; 111*f3bdbd42SAbhijit Gangurde cq->q.mask = req_cq->mask; 112*f3bdbd42SAbhijit Gangurde cq->q.depth_log2 = req_cq->depth_log2; 113*f3bdbd42SAbhijit Gangurde cq->q.stride_log2 = req_cq->stride_log2; 114*f3bdbd42SAbhijit Gangurde 115*f3bdbd42SAbhijit Gangurde *resp_cqid = cq->cqid; 116*f3bdbd42SAbhijit Gangurde } else { 117*f3bdbd42SAbhijit Gangurde rc = ionic_queue_init(&cq->q, dev->lif_cfg.hwdev, 118*f3bdbd42SAbhijit Gangurde attr->cqe + IONIC_CQ_GRACE, 119*f3bdbd42SAbhijit Gangurde sizeof(struct ionic_v1_cqe)); 120*f3bdbd42SAbhijit Gangurde if (rc) 121*f3bdbd42SAbhijit Gangurde goto err_q_init; 122*f3bdbd42SAbhijit Gangurde 123*f3bdbd42SAbhijit Gangurde ionic_queue_dbell_init(&cq->q, cq->cqid); 124*f3bdbd42SAbhijit Gangurde cq->color = true; 125*f3bdbd42SAbhijit Gangurde cq->credit = cq->q.mask; 126*f3bdbd42SAbhijit Gangurde } 127*f3bdbd42SAbhijit Gangurde 128*f3bdbd42SAbhijit Gangurde rc = ionic_pgtbl_init(dev, buf, cq->umem, cq->q.dma, 1, PAGE_SIZE); 129*f3bdbd42SAbhijit Gangurde if (rc) 130*f3bdbd42SAbhijit Gangurde goto err_pgtbl_init; 131*f3bdbd42SAbhijit Gangurde 132*f3bdbd42SAbhijit Gangurde init_completion(&cq->cq_rel_comp); 133*f3bdbd42SAbhijit Gangurde kref_init(&cq->cq_kref); 134*f3bdbd42SAbhijit Gangurde 135*f3bdbd42SAbhijit Gangurde entry = xa_store_irq(&dev->cq_tbl, cq->cqid, cq, GFP_KERNEL); 136*f3bdbd42SAbhijit Gangurde if (entry) { 137*f3bdbd42SAbhijit Gangurde if (!xa_is_err(entry)) 138*f3bdbd42SAbhijit Gangurde rc = -EINVAL; 139*f3bdbd42SAbhijit Gangurde else 140*f3bdbd42SAbhijit Gangurde rc = xa_err(entry); 141*f3bdbd42SAbhijit Gangurde 142*f3bdbd42SAbhijit Gangurde goto err_xa; 143*f3bdbd42SAbhijit Gangurde } 144*f3bdbd42SAbhijit Gangurde 145*f3bdbd42SAbhijit Gangurde return 0; 146*f3bdbd42SAbhijit Gangurde 147*f3bdbd42SAbhijit Gangurde err_xa: 148*f3bdbd42SAbhijit Gangurde ionic_pgtbl_unbuf(dev, buf); 149*f3bdbd42SAbhijit Gangurde err_pgtbl_init: 150*f3bdbd42SAbhijit Gangurde if (!udata) 151*f3bdbd42SAbhijit Gangurde ionic_queue_destroy(&cq->q, dev->lif_cfg.hwdev); 152*f3bdbd42SAbhijit Gangurde err_q_init: 153*f3bdbd42SAbhijit Gangurde if (cq->umem) 154*f3bdbd42SAbhijit Gangurde ib_umem_release(cq->umem); 155*f3bdbd42SAbhijit Gangurde err_qdesc: 156*f3bdbd42SAbhijit Gangurde ionic_put_cqid(dev, cq->cqid); 157*f3bdbd42SAbhijit Gangurde err_args: 158*f3bdbd42SAbhijit Gangurde cq->vcq = NULL; 159*f3bdbd42SAbhijit Gangurde 160*f3bdbd42SAbhijit Gangurde return rc; 161*f3bdbd42SAbhijit Gangurde } 162*f3bdbd42SAbhijit Gangurde 163*f3bdbd42SAbhijit Gangurde void ionic_destroy_cq_common(struct ionic_ibdev *dev, struct ionic_cq *cq) 164*f3bdbd42SAbhijit Gangurde { 165*f3bdbd42SAbhijit Gangurde if (!cq->vcq) 166*f3bdbd42SAbhijit Gangurde return; 167*f3bdbd42SAbhijit Gangurde 168*f3bdbd42SAbhijit Gangurde xa_erase_irq(&dev->cq_tbl, cq->cqid); 169*f3bdbd42SAbhijit Gangurde 170*f3bdbd42SAbhijit Gangurde kref_put(&cq->cq_kref, ionic_cq_complete); 171*f3bdbd42SAbhijit Gangurde wait_for_completion(&cq->cq_rel_comp); 172*f3bdbd42SAbhijit Gangurde 173*f3bdbd42SAbhijit Gangurde if (cq->umem) 174*f3bdbd42SAbhijit Gangurde ib_umem_release(cq->umem); 175*f3bdbd42SAbhijit Gangurde else 176*f3bdbd42SAbhijit Gangurde ionic_queue_destroy(&cq->q, dev->lif_cfg.hwdev); 177*f3bdbd42SAbhijit Gangurde 178*f3bdbd42SAbhijit Gangurde ionic_put_cqid(dev, cq->cqid); 179*f3bdbd42SAbhijit Gangurde 180*f3bdbd42SAbhijit Gangurde cq->vcq = NULL; 181*f3bdbd42SAbhijit Gangurde } 182