162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2022, Microsoft Corporation. All rights reserved. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include "mana_ib.h" 762306a36Sopenharmony_ci 862306a36Sopenharmony_ciint mana_ib_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr, 962306a36Sopenharmony_ci struct ib_udata *udata) 1062306a36Sopenharmony_ci{ 1162306a36Sopenharmony_ci struct mana_ib_cq *cq = container_of(ibcq, struct mana_ib_cq, ibcq); 1262306a36Sopenharmony_ci struct ib_device *ibdev = ibcq->device; 1362306a36Sopenharmony_ci struct mana_ib_create_cq ucmd = {}; 1462306a36Sopenharmony_ci struct mana_ib_dev *mdev; 1562306a36Sopenharmony_ci int err; 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci mdev = container_of(ibdev, struct mana_ib_dev, ib_dev); 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci if (udata->inlen < sizeof(ucmd)) 2062306a36Sopenharmony_ci return -EINVAL; 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci err = ib_copy_from_udata(&ucmd, udata, min(sizeof(ucmd), udata->inlen)); 2362306a36Sopenharmony_ci if (err) { 2462306a36Sopenharmony_ci ibdev_dbg(ibdev, 2562306a36Sopenharmony_ci "Failed to copy from udata for create cq, %d\n", err); 2662306a36Sopenharmony_ci return err; 2762306a36Sopenharmony_ci } 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci if (attr->cqe > MAX_SEND_BUFFERS_PER_QUEUE) { 3062306a36Sopenharmony_ci ibdev_dbg(ibdev, "CQE %d exceeding limit\n", attr->cqe); 3162306a36Sopenharmony_ci return -EINVAL; 3262306a36Sopenharmony_ci } 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci cq->cqe = attr->cqe; 3562306a36Sopenharmony_ci cq->umem = ib_umem_get(ibdev, ucmd.buf_addr, cq->cqe * COMP_ENTRY_SIZE, 3662306a36Sopenharmony_ci IB_ACCESS_LOCAL_WRITE); 3762306a36Sopenharmony_ci if (IS_ERR(cq->umem)) { 3862306a36Sopenharmony_ci err = PTR_ERR(cq->umem); 3962306a36Sopenharmony_ci ibdev_dbg(ibdev, "Failed to get umem for create cq, err %d\n", 4062306a36Sopenharmony_ci err); 4162306a36Sopenharmony_ci return err; 4262306a36Sopenharmony_ci } 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci err = mana_ib_gd_create_dma_region(mdev, cq->umem, &cq->gdma_region); 4562306a36Sopenharmony_ci if (err) { 4662306a36Sopenharmony_ci ibdev_dbg(ibdev, 4762306a36Sopenharmony_ci "Failed to create dma region for create cq, %d\n", 4862306a36Sopenharmony_ci err); 4962306a36Sopenharmony_ci goto err_release_umem; 5062306a36Sopenharmony_ci } 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci ibdev_dbg(ibdev, 5362306a36Sopenharmony_ci "mana_ib_gd_create_dma_region ret %d gdma_region 0x%llx\n", 5462306a36Sopenharmony_ci err, cq->gdma_region); 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci /* 5762306a36Sopenharmony_ci * The CQ ID is not known at this time. The ID is generated at create_qp 5862306a36Sopenharmony_ci */ 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci return 0; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cierr_release_umem: 6362306a36Sopenharmony_ci ib_umem_release(cq->umem); 6462306a36Sopenharmony_ci return err; 6562306a36Sopenharmony_ci} 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ciint mana_ib_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci struct mana_ib_cq *cq = container_of(ibcq, struct mana_ib_cq, ibcq); 7062306a36Sopenharmony_ci struct ib_device *ibdev = ibcq->device; 7162306a36Sopenharmony_ci struct mana_ib_dev *mdev; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci mdev = container_of(ibdev, struct mana_ib_dev, ib_dev); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci mana_ib_gd_destroy_dma_region(mdev, cq->gdma_region); 7662306a36Sopenharmony_ci ib_umem_release(cq->umem); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci return 0; 7962306a36Sopenharmony_ci} 80