> diff --git a/drivers/infiniband/hw/mana/cq.c b/drivers/infiniband/hw/mana/cq.c
> index 2dce1b677115..605122ecf9f9 100644
> --- a/drivers/infiniband/hw/mana/cq.c
> +++ b/drivers/infiniband/hw/mana/cq.c
> @@ -5,8 +5,8 @@
>
> #include "mana_ib.h"
>
> -int mana_ib_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
> - struct uverbs_attr_bundle *attrs)
> +int mana_ib_create_user_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr
> *attr,
> + struct uverbs_attr_bundle *attrs)
> {
> struct ib_udata *udata = &attrs->driver_udata;
> struct mana_ib_cq *cq = container_of(ibcq, struct mana_ib_cq, ibcq);
> @@ -17,7 +17,6 @@ int mana_ib_create_cq(struct ib_cq *ibcq, const struct
> ib_cq_init_attr *attr,
> struct mana_ib_dev *mdev;
> bool is_rnic_cq;
> u32 doorbell;
> - u32 buf_size;
> int err;
>
> mdev = container_of(ibdev, struct mana_ib_dev, ib_dev); @@ -26,44
> +25,100 @@ int mana_ib_create_cq(struct ib_cq *ibcq, const struct
> ib_cq_init_attr *attr,
> cq->cq_handle = INVALID_MANA_HANDLE;
> is_rnic_cq = mana_ib_is_rnic(mdev);
>
> - if (udata) {
> - if (udata->inlen < offsetof(struct mana_ib_create_cq, flags))
> - return -EINVAL;
> + if (udata->inlen < offsetof(struct mana_ib_create_cq, flags))
> + return -EINVAL;
>
> - err = ib_copy_from_udata(&ucmd, udata, min(sizeof(ucmd),
> udata->inlen));
> - if (err) {
> - ibdev_dbg(ibdev, "Failed to copy from udata for create
> cq, %d\n", err);
> - return err;
> - }
> + err = ib_copy_from_udata(&ucmd, udata, min(sizeof(ucmd), udata-
> >inlen));
> + if (err) {
> + ibdev_dbg(ibdev, "Failed to copy from udata for create
> cq, %d\n", err);
> + return err;
> + }
>
> - if ((!is_rnic_cq && attr->cqe > mdev-
> >adapter_caps.max_qp_wr) ||
> - attr->cqe > U32_MAX / COMP_ENTRY_SIZE) {
> - ibdev_dbg(ibdev, "CQE %d exceeding limit\n", attr-
> >cqe);
> - return -EINVAL;
> - }
> + if ((!is_rnic_cq && attr->cqe > mdev->adapter_caps.max_qp_wr) ||
> + attr->cqe > U32_MAX / COMP_ENTRY_SIZE) {
> + ibdev_dbg(ibdev, "CQE %d exceeding limit\n", attr->cqe);
> + return -EINVAL;
> + }
> +
> + cq->cqe = attr->cqe;
> + if (!ibcq->umem)
> + ibcq->umem = ib_umem_get(ibdev, ucmd.buf_addr,
> + cq->cqe * COMP_ENTRY_SIZE,
> + IB_ACCESS_LOCAL_WRITE);
> + if (IS_ERR(ibcq->umem))
> + return PTR_ERR(ibcq->umem);
> + cq->queue.umem = ibcq->umem;
> +
> + err = mana_ib_create_queue(mdev, &cq->queue);
> + if (err)
> + return err;
Should we call ib_umem_release() on this err?
>
> diff --git a/drivers/infiniband/hw/mana/qp.c
> b/drivers/infiniband/hw/mana/qp.c index 48c1f4977f21..b08dbc675741
> 100644
> --- a/drivers/infiniband/hw/mana/qp.c
> +++ b/drivers/infiniband/hw/mana/qp.c
> @@ -326,11 +326,20 @@ static int mana_ib_create_qp_raw(struct ib_qp
> *ibqp, struct ib_pd *ibpd,
> ibdev_dbg(&mdev->ib_dev, "ucmd sq_buf_addr 0x%llx port %u\n",
> ucmd.sq_buf_addr, ucmd.port);
>
> - err = mana_ib_create_queue(mdev, ucmd.sq_buf_addr,
> ucmd.sq_buf_size, &qp->raw_sq);
> + qp->raw_sq.umem = ib_umem_get(&mdev->ib_dev, ucmd.sq_buf_addr,
> + ucmd.sq_buf_size,
> IB_ACCESS_LOCAL_WRITE);
> + if (IS_ERR(qp->raw_sq.umem)) {
> + err = PTR_ERR(qp->raw_sq.umem);
> + ibdev_dbg(&mdev->ib_dev,
> + "Failed to get umem for qp-raw, err %d\n", err);
> + goto err_free_vport;
> + }
> +
> + err = mana_ib_create_queue(mdev, &qp->raw_sq);
> if (err) {
> ibdev_dbg(&mdev->ib_dev,
> "Failed to create queue for create qp-raw, err %d\n",
> err);
> - goto err_free_vport;
> + goto err_release_umem;
> }
>
> /* Create a WQ on the same port handle used by the Ethernet */ @@ -
> 391,6 +400,10 @@ static int mana_ib_create_qp_raw(struct ib_qp *ibqp,
> struct ib_pd *ibpd,
>
> err_destroy_queue:
> mana_ib_destroy_queue(mdev, &qp->raw_sq);
> + return err;
Should remove this "return err", the error handling code should fall through.
> +
> +err_release_umem:
> + ib_umem_release(qp->raw_sq.umem);
>
> err_free_vport:
> mana_ib_uncfg_vport(mdev, pd, port);
> @@ -553,13 +566,25 @@ static int mana_ib_create_rc_qp(struct ib_qp *ibqp,
> struct ib_pd *ibpd,
> if (i == MANA_RC_SEND_QUEUE_FMR) {
> qp->rc_qp.queues[i].id = INVALID_QUEUE_ID;
> qp->rc_qp.queues[i].gdma_region =
> GDMA_INVALID_DMA_REGION;
> + qp->rc_qp.queues[i].umem = NULL;
> continue;
> }
> - err = mana_ib_create_queue(mdev, ucmd.queue_buf[j],
> ucmd.queue_size[j],
> - &qp->rc_qp.queues[i]);
> + qp->rc_qp.queues[i].umem = ib_umem_get(&mdev->ib_dev,
> + ucmd.queue_buf[j],
> + ucmd.queue_size[j],
> +
> IB_ACCESS_LOCAL_WRITE);
> + if (IS_ERR(qp->rc_qp.queues[i].umem)) {
> + err = PTR_ERR(qp->rc_qp.queues[i].umem);
> + ibdev_err(&mdev->ib_dev, "Failed to get umem for
> queue %d, err %d\n",
> + i, err);
> + goto release_umems;
mana_ib_create_queue() may already have created some queues, need to clean them
up or we have a leak.
Maybe use destroy_queues: to call ib_umem_release()?
Another issue: there is a call to ib_umem_release(queue->umem) in
mana_ib_destroy_queue(), should we remove that as well?
Thanks,
Long