From nobody Thu Apr 2 22:08:39 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 41267356A1F; Fri, 13 Feb 2026 10:59:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770980396; cv=none; b=S6wxp1wRiyCr93Wdw8MfolOiFcZYpheBHMfOlZxX28GNnJbwTgU+/hAhvbNIBGREZboJz+j7irgwlU2EMkqp6KjzBMWmwG+EJ0rrJQ3yXEcd0gsr0106kcScfj5pZcworU6EwA0WVLigmZEzLwU3cjvTOt8tzPuHT7CW+7E/dVQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770980396; c=relaxed/simple; bh=uCqkDM6MRpkhJ5KrDUZXo/iZqDu91ZV3NReLY1r+Hh0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=K17zeVUUxk2L5kryLU9nuJznHmhHJCz9tgygOjMVgaisFlDvj/lZ0dcz26u2FViz7Y0sHYa4F/erk1umIL1mG834zbTbssYJDNJGO4WOgEiysXDGOZXsm3MRYLy5YYIMP+3/TNztkrWDDteumAyXeyk6gudiz2D+4C7YrYn3Xg8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Hbc+73oB; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Hbc+73oB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2AB3AC19423; Fri, 13 Feb 2026 10:59:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770980395; bh=uCqkDM6MRpkhJ5KrDUZXo/iZqDu91ZV3NReLY1r+Hh0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Hbc+73oB3BKQQD9ONRcDM9VW1dC7YNTfBBmMnZpdWy4m5sUJP0BJlAmpvtCOKRko5 wJSn7fjBP6POSnlInNlDo0D0+t7TFQeYkWiTCRe4wtsJHfYECDOu+B0NBWTyz4cO1r Ooq04DLiXDtZ7BPPdwblJhqOZEi0cBL1xkg+nsX5E7gIyOw0/VbLwR/+llqH+Y2LSU j7GxnEYxiC7Omg5iuhuUPVWwANh6YjuSh8eB88euVgV44XfXJka69sFwiXhn5jnc3U BpoFO5oRijYhBOK1mF9jItB0sOxA+lI8Os5gMu5/H7KWJDxvqHGhwXWExHtkksA3jU kfQRG1jIKBr+w== From: Leon Romanovsky To: Jason Gunthorpe , Leon Romanovsky , Selvin Xavier , Kalesh AP , Potnuri Bharat Teja , Michael Margolin , Gal Pressman , Yossi Leybovich , Cheng Xu , Kai Shen , Chengchang Tang , Junxian Huang , Abhijit Gangurde , Allen Hubbe , Krzysztof Czurylo , Tatyana Nikolova , Long Li , Konstantin Taranov , Yishai Hadas , Michal Kalderon , Bryan Tan , Vishnu Dasa , Broadcom internal kernel review list , Christian Benvenuti , Nelson Escobar , Dennis Dalessandro , Bernard Metzler , Zhu Yanjun Cc: linux-kernel@vger.kernel.org, linux-rdma@vger.kernel.org, linux-hyperv@vger.kernel.org Subject: [PATCH rdma-next 16/50] RDMA/cxgb4: Separate kernel and user CQ creation paths Date: Fri, 13 Feb 2026 12:57:52 +0200 Message-ID: <20260213-refactor-umem-v1-16-f3be85847922@nvidia.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260213-refactor-umem-v1-0-f3be85847922@nvidia.com> References: <20260213-refactor-umem-v1-0-f3be85847922@nvidia.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" X-Mailer: b4 0.15-dev-47773 Content-Transfer-Encoding: quoted-printable From: Leon Romanovsky Split the create CQ logic to clearly distinguish kernel and user flows. Signed-off-by: Leon Romanovsky --- drivers/infiniband/hw/cxgb4/cq.c | 218 ++++++++++++++++++++++-------= ---- drivers/infiniband/hw/cxgb4/iw_cxgb4.h | 2 + drivers/infiniband/hw/cxgb4/provider.c | 1 + 3 files changed, 152 insertions(+), 69 deletions(-) diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4= /cq.c index 14ced7b667fa..d263cca47432 100644 --- a/drivers/infiniband/hw/cxgb4/cq.c +++ b/drivers/infiniband/hw/cxgb4/cq.c @@ -994,8 +994,8 @@ int c4iw_destroy_cq(struct ib_cq *ib_cq, struct ib_udat= a *udata) return 0; } =20 -int c4iw_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr, - struct uverbs_attr_bundle *attrs) +int c4iw_create_user_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *= attr, + struct uverbs_attr_bundle *attrs) { struct ib_udata *udata =3D &attrs->driver_udata; struct ib_device *ibdev =3D ibcq->device; @@ -1012,25 +1012,21 @@ int c4iw_create_cq(struct ib_cq *ibcq, const struct= ib_cq_init_attr *attr, udata, struct c4iw_ucontext, ibucontext); =20 pr_debug("ib_dev %p entries %d\n", ibdev, entries); - if (attr->flags) + if (attr->flags || ibcq->umem) return -EOPNOTSUPP; =20 - if (entries < 1 || entries > ibdev->attrs.max_cqe) + if (attr->cqe > ibdev->attrs.max_cqe) return -EINVAL; =20 if (vector >=3D rhp->rdev.lldi.nciq) return -EINVAL; =20 - if (udata) { - if (udata->inlen < sizeof(ucmd)) - ucontext->is_32b_cqe =3D 1; - } + if (udata->inlen < sizeof(ucmd)) + ucontext->is_32b_cqe =3D 1; =20 chp->wr_waitp =3D c4iw_alloc_wr_wait(GFP_KERNEL); - if (!chp->wr_waitp) { - ret =3D -ENOMEM; - goto err_free_chp; - } + if (!chp->wr_waitp) + return -ENOMEM; c4iw_init_wr_wait(chp->wr_waitp); =20 wr_len =3D sizeof(struct fw_ri_res_wr) + sizeof(struct fw_ri_res); @@ -1063,22 +1059,19 @@ int c4iw_create_cq(struct ib_cq *ibcq, const struct= ib_cq_init_attr *attr, if (hwentries < 64) hwentries =3D 64; =20 - memsize =3D hwentries * ((ucontext && ucontext->is_32b_cqe) ? + memsize =3D hwentries * (ucontext->is_32b_cqe ? (sizeof(*chp->cq.queue) / 2) : sizeof(*chp->cq.queue)); =20 /* * memsize must be a multiple of the page size if its a user cq. */ - if (udata) - memsize =3D roundup(memsize, PAGE_SIZE); + memsize =3D roundup(memsize, PAGE_SIZE); =20 chp->cq.size =3D hwentries; chp->cq.memsize =3D memsize; chp->cq.vector =3D vector; =20 - ret =3D create_cq(&rhp->rdev, &chp->cq, - ucontext ? &ucontext->uctx : &rhp->rdev.uctx, - chp->wr_waitp); + ret =3D create_cq(&rhp->rdev, &chp->cq, &ucontext->uctx, chp->wr_waitp); if (ret) goto err_free_skb; =20 @@ -1093,54 +1086,52 @@ int c4iw_create_cq(struct ib_cq *ibcq, const struct= ib_cq_init_attr *attr, if (ret) goto err_destroy_cq; =20 - if (ucontext) { - ret =3D -ENOMEM; - mm =3D kmalloc(sizeof(*mm), GFP_KERNEL); - if (!mm) - goto err_remove_handle; - mm2 =3D kmalloc(sizeof(*mm2), GFP_KERNEL); - if (!mm2) - goto err_free_mm; - - memset(&uresp, 0, sizeof(uresp)); - uresp.qid_mask =3D rhp->rdev.cqmask; - uresp.cqid =3D chp->cq.cqid; - uresp.size =3D chp->cq.size; - uresp.memsize =3D chp->cq.memsize; - spin_lock(&ucontext->mmap_lock); - uresp.key =3D ucontext->key; - ucontext->key +=3D PAGE_SIZE; - uresp.gts_key =3D ucontext->key; - ucontext->key +=3D PAGE_SIZE; - /* communicate to the userspace that - * kernel driver supports 64B CQE - */ - uresp.flags |=3D C4IW_64B_CQE; - - spin_unlock(&ucontext->mmap_lock); - ret =3D ib_copy_to_udata(udata, &uresp, - ucontext->is_32b_cqe ? - sizeof(uresp) - sizeof(uresp.flags) : - sizeof(uresp)); - if (ret) - goto err_free_mm2; - - mm->key =3D uresp.key; - mm->addr =3D 0; - mm->vaddr =3D chp->cq.queue; - mm->dma_addr =3D chp->cq.dma_addr; - mm->len =3D chp->cq.memsize; - insert_flag_to_mmap(&rhp->rdev, mm, mm->addr); - insert_mmap(ucontext, mm); - - mm2->key =3D uresp.gts_key; - mm2->addr =3D chp->cq.bar2_pa; - mm2->len =3D PAGE_SIZE; - mm2->vaddr =3D NULL; - mm2->dma_addr =3D 0; - insert_flag_to_mmap(&rhp->rdev, mm2, mm2->addr); - insert_mmap(ucontext, mm2); - } + ret =3D -ENOMEM; + mm =3D kmalloc(sizeof(*mm), GFP_KERNEL); + if (!mm) + goto err_remove_handle; + mm2 =3D kmalloc(sizeof(*mm2), GFP_KERNEL); + if (!mm2) + goto err_free_mm; + + memset(&uresp, 0, sizeof(uresp)); + uresp.qid_mask =3D rhp->rdev.cqmask; + uresp.cqid =3D chp->cq.cqid; + uresp.size =3D chp->cq.size; + uresp.memsize =3D chp->cq.memsize; + spin_lock(&ucontext->mmap_lock); + uresp.key =3D ucontext->key; + ucontext->key +=3D PAGE_SIZE; + uresp.gts_key =3D ucontext->key; + ucontext->key +=3D PAGE_SIZE; + /* communicate to the userspace that + * kernel driver supports 64B CQE + */ + uresp.flags |=3D C4IW_64B_CQE; + + spin_unlock(&ucontext->mmap_lock); + ret =3D ib_copy_to_udata(udata, &uresp, + ucontext->is_32b_cqe ? + sizeof(uresp) - sizeof(uresp.flags) : + sizeof(uresp)); + if (ret) + goto err_free_mm2; + + mm->key =3D uresp.key; + mm->addr =3D 0; + mm->vaddr =3D chp->cq.queue; + mm->dma_addr =3D chp->cq.dma_addr; + mm->len =3D chp->cq.memsize; + insert_flag_to_mmap(&rhp->rdev, mm, mm->addr); + insert_mmap(ucontext, mm); + + mm2->key =3D uresp.gts_key; + mm2->addr =3D chp->cq.bar2_pa; + mm2->len =3D PAGE_SIZE; + mm2->vaddr =3D NULL; + mm2->dma_addr =3D 0; + insert_flag_to_mmap(&rhp->rdev, mm2, mm2->addr); + insert_mmap(ucontext, mm2); =20 pr_debug("cqid 0x%0x chp %p size %u memsize %zu, dma_addr %pad\n", chp->cq.cqid, chp, chp->cq.size, chp->cq.memsize, @@ -1153,14 +1144,103 @@ int c4iw_create_cq(struct ib_cq *ibcq, const struc= t ib_cq_init_attr *attr, err_remove_handle: xa_erase_irq(&rhp->cqs, chp->cq.cqid); err_destroy_cq: - destroy_cq(&chp->rhp->rdev, &chp->cq, - ucontext ? &ucontext->uctx : &rhp->rdev.uctx, + destroy_cq(&chp->rhp->rdev, &chp->cq, &ucontext->uctx, + chp->destroy_skb, chp->wr_waitp); +err_free_skb: + kfree_skb(chp->destroy_skb); +err_free_wr_wait: + c4iw_put_wr_wait(chp->wr_waitp); + return ret; +} + +int c4iw_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr, + struct uverbs_attr_bundle *attrs) +{ + struct ib_device *ibdev =3D ibcq->device; + int entries =3D attr->cqe; + int vector =3D attr->comp_vector; + struct c4iw_dev *rhp =3D to_c4iw_dev(ibcq->device); + struct c4iw_cq *chp =3D to_c4iw_cq(ibcq); + int ret, wr_len; + size_t memsize, hwentries; + + pr_debug("ib_dev %p entries %d\n", ibdev, entries); + if (attr->flags) + return -EOPNOTSUPP; + + if (attr->cqe > ibdev->attrs.max_cqe) + return -EINVAL; + + if (vector >=3D rhp->rdev.lldi.nciq) + return -EINVAL; + + chp->wr_waitp =3D c4iw_alloc_wr_wait(GFP_KERNEL); + if (!chp->wr_waitp) + return -ENOMEM; + c4iw_init_wr_wait(chp->wr_waitp); + + wr_len =3D sizeof(struct fw_ri_res_wr) + sizeof(struct fw_ri_res); + chp->destroy_skb =3D alloc_skb(wr_len, GFP_KERNEL); + if (!chp->destroy_skb) { + ret =3D -ENOMEM; + goto err_free_wr_wait; + } + + /* account for the status page. */ + entries++; + + /* IQ needs one extra entry to differentiate full vs empty. */ + entries++; + + /* + * entries must be multiple of 16 for HW. + */ + entries =3D roundup(entries, 16); + + /* + * Make actual HW queue 2x to avoid cdix_inc overflows. + */ + hwentries =3D min(entries * 2, rhp->rdev.hw_queue.t4_max_iq_size); + + /* + * Make HW queue at least 64 entries so GTS updates aren't too + * frequent. + */ + if (hwentries < 64) + hwentries =3D 64; + + memsize =3D hwentries * sizeof(*chp->cq.queue); + + chp->cq.size =3D hwentries; + chp->cq.memsize =3D memsize; + chp->cq.vector =3D vector; + + ret =3D create_cq(&rhp->rdev, &chp->cq, &rhp->rdev.uctx, chp->wr_waitp); + if (ret) + goto err_free_skb; + + chp->rhp =3D rhp; + chp->cq.size--; /* status page */ + chp->ibcq.cqe =3D entries - 2; + spin_lock_init(&chp->lock); + spin_lock_init(&chp->comp_handler_lock); + refcount_set(&chp->refcnt, 1); + init_completion(&chp->cq_rel_comp); + ret =3D xa_insert_irq(&rhp->cqs, chp->cq.cqid, chp, GFP_KERNEL); + if (ret) + goto err_destroy_cq; + + pr_debug("cqid 0x%0x chp %p size %u memsize %zu, dma_addr %pad\n", + chp->cq.cqid, chp, chp->cq.size, chp->cq.memsize, + &chp->cq.dma_addr); + return 0; +err_destroy_cq: + destroy_cq(&chp->rhp->rdev, &chp->cq, &rhp->rdev.uctx, chp->destroy_skb, chp->wr_waitp); err_free_skb: kfree_skb(chp->destroy_skb); err_free_wr_wait: c4iw_put_wr_wait(chp->wr_waitp); -err_free_chp: return ret; } =20 diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw= /cxgb4/iw_cxgb4.h index e17c1252536b..b8e3ee2a0c84 100644 --- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h +++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h @@ -1014,6 +1014,8 @@ int c4iw_destroy_cq(struct ib_cq *ib_cq, struct ib_ud= ata *udata); void c4iw_cq_rem_ref(struct c4iw_cq *chp); int c4iw_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr, struct uverbs_attr_bundle *attrs); +int c4iw_create_user_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *= attr, + struct uverbs_attr_bundle *attrs); int c4iw_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags); int c4iw_modify_srq(struct ib_srq *ib_srq, struct ib_srq_attr *attr, enum ib_srq_attr_mask srq_attr_mask, diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw= /cxgb4/provider.c index e059f92d90fd..b9c183d1389d 100644 --- a/drivers/infiniband/hw/cxgb4/provider.c +++ b/drivers/infiniband/hw/cxgb4/provider.c @@ -461,6 +461,7 @@ static const struct ib_device_ops c4iw_dev_ops =3D { .alloc_pd =3D c4iw_allocate_pd, .alloc_ucontext =3D c4iw_alloc_ucontext, .create_cq =3D c4iw_create_cq, + .create_user_cq =3D c4iw_create_user_cq, .create_qp =3D c4iw_create_qp, .create_srq =3D c4iw_create_srq, .dealloc_pd =3D c4iw_deallocate_pd, --=20 2.52.0