Linux RDMA and InfiniBand development
 help / color / mirror / Atom feed
From: Yishai Hadas <yishaih@nvidia.com>
To: <jgg@ziepe.ca>, <leon@kernel.org>
Cc: <linux-rdma@vger.kernel.org>, <selvin.xavier@broadcom.com>,
	<kalesh-anakkur.purayil@broadcom.com>,
	<chengyou@linux.alibaba.com>, <kaishen@linux.alibaba.com>,
	<tangchengchang@huawei.com>, <huangjunxian6@hisilicon.com>,
	<abhijit.gangurde@amd.com>, <allen.hubbe@amd.com>,
	<longli@microsoft.com>, <kotaranov@microsoft.com>,
	<mkalderon@marvell.com>, <bryan-bt.tan@broadcom.com>,
	<vishnu.dasa@broadcom.com>, <yishaih@nvidia.com>,
	<maorg@nvidia.com>
Subject: [PATCH rdma-next 13/15] RDMA/mlx5: Set QP event handler before firmware QPC insertion
Date: Tue, 8 Sep 2026 18:28:49 +0300	[thread overview]
Message-ID: <20260908152851.1307294-14-yishaih@nvidia.com> (raw)
In-Reply-To: <20260908152851.1307294-1-yishaih@nvidia.com>

Four QP create paths (create_xrc_tgt_qp, create_dci, create_qp's default
path for create_user_qp/create_kernel_qp, and the raw-packet QP SQ
object in create_raw_packet_qp) assigned base->container_mibqp and
base->mqp.event only after mlx5_qpc_create_qp() /
create_raw_packet_qp_sq() returned. Those functions insert the QPC into
dev->qp_table.tree, making it immediately visible to
rsc_event_notifier(). A hostile NIC can fire a QP error EQE for the new
QPN/SQN in that window, reaching qp->event() with a NULL function
pointer and causing a kernel oops. This is the same class of bug already
fixed for the raw-packet QP's RQ object in a previous commit.

Move both assignments before the firmware create call in each path so
the event handler is always valid by the time the resource is reachable
by events. to_mibqp() indirects through container_mibqp, so it must also
be set before insertion.

Add a WARN_ON_ONCE(!qp->event) guard in rsc_event_notifier() as a
belt-and-suspenders defense against any future code paths that may
re-introduce the same ordering hazard.

Also set ibqp.qp_num in mlx5_qpc_create_qp() before
create_resource_common() inserts the QP into the radix tree, so an EQE
arriving in that window does not observe qp_num == 0. create_qp() still
overrides this with 0/1 for QP0/QP1 afterwards, and DCT sets its own
identifier independently since it does not go through this function.

Fixes: e126ba97dba9 ("mlx5: Add driver for Mellanox Connect-IB adapters")
Signed-off-by: Yishai Hadas <yishaih@nvidia.com>
---
 drivers/infiniband/hw/mlx5/qp.c  | 22 ++++++++++------------
 drivers/infiniband/hw/mlx5/qpc.c | 10 ++++++++++
 2 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index 7f18ff364e62..2af599b81886 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -1624,6 +1624,8 @@ static int create_raw_packet_qp(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
 		if (err)
 			return err;
 
+		sq->base.container_mibqp = qp;
+		sq->base.mqp.event = mlx5_ib_qp_event;
 		err = create_raw_packet_qp_sq(dev, udata, attrs, sq, in, pd,
 					      to_mcq(init_attr->send_cq));
 		if (err)
@@ -1635,9 +1637,6 @@ static int create_raw_packet_qp(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
 			resp->sqn = sq->base.mqp.qpn;
 			resp->comp_mask |= MLX5_IB_CREATE_QP_RESP_MASK_SQN;
 		}
-
-		sq->base.container_mibqp = qp;
-		sq->base.mqp.event = mlx5_ib_qp_event;
 	}
 
 	if (qp->rq.wqe_cnt) {
@@ -2093,13 +2092,13 @@ static int create_xrc_tgt_qp(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
 	}
 
 	base = &qp->trans_qp.base;
+	base->container_mibqp = qp;
+	base->mqp.event = mlx5_ib_qp_event;
 	err = mlx5_qpc_create_qp(dev, &base->mqp, in, inlen, out);
 	kvfree(in);
 	if (err)
 		return err;
 
-	base->container_mibqp = qp;
-	base->mqp.event = mlx5_ib_qp_event;
 	if (MLX5_CAP_GEN(mdev, ece_support))
 		params->resp.ece_options = MLX5_GET(create_qp_out, out, ece);
 
@@ -2237,14 +2236,14 @@ static int create_dci(struct mlx5_ib_dev *dev, struct ib_pd *pd,
 		qp->flags &= ~IB_QP_CREATE_PCI_WRITE_END_PADDING;
 	}
 
+	base->container_mibqp = qp;
+	base->mqp.event = mlx5_ib_qp_event;
 	err = mlx5_qpc_create_qp(dev, &base->mqp, in, inlen, out);
 
 	kvfree(in);
 	if (err)
 		goto err_create;
 
-	base->container_mibqp = qp;
-	base->mqp.event = mlx5_ib_qp_event;
 	if (MLX5_CAP_GEN(mdev, ece_support))
 		params->resp.ece_options = MLX5_GET(create_qp_out, out, ece);
 
@@ -2433,6 +2432,8 @@ static int create_user_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd,
 		qp->flags &= ~IB_QP_CREATE_PCI_WRITE_END_PADDING;
 	}
 
+	base->container_mibqp = qp;
+	base->mqp.event = mlx5_ib_qp_event;
 	if (init_attr->qp_type == IB_QPT_RAW_PACKET ||
 	    qp->flags & IB_QP_CREATE_SOURCE_QPN) {
 		qp->raw_packet_qp.sq.ubuffer.buf_addr = ucmd->sq_buf_addr;
@@ -2447,8 +2448,6 @@ static int create_user_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd,
 	if (err)
 		goto err_create;
 
-	base->container_mibqp = qp;
-	base->mqp.event = mlx5_ib_qp_event;
 	if (MLX5_CAP_GEN(mdev, ece_support))
 		params->resp.ece_options = MLX5_GET(create_qp_out, out, ece);
 
@@ -2578,14 +2577,13 @@ static int create_kernel_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd,
 	    MLX5_CAP_GEN(mdev, go_back_n))
 		MLX5_SET(qpc, qpc, retry_mode, MLX5_QP_RM_GO_BACK_N);
 
+	base->container_mibqp = qp;
+	base->mqp.event = mlx5_ib_qp_event;
 	err = mlx5_qpc_create_qp(dev, &base->mqp, in, inlen, out);
 	kvfree(in);
 	if (err)
 		goto err_create;
 
-	base->container_mibqp = qp;
-	base->mqp.event = mlx5_ib_qp_event;
-
 	get_cqs(qp->type, attr->send_cq, attr->recv_cq,
 		&send_cq, &recv_cq);
 	spin_lock_irqsave(&dev->reset_flow_resource_lock, flags);
diff --git a/drivers/infiniband/hw/mlx5/qpc.c b/drivers/infiniband/hw/mlx5/qpc.c
index a7a4f9420271..77ddab666ecd 100644
--- a/drivers/infiniband/hw/mlx5/qpc.c
+++ b/drivers/infiniband/hw/mlx5/qpc.c
@@ -146,6 +146,8 @@ static int rsc_event_notifier(struct notifier_block *nb,
 	case MLX5_RES_RQ:
 	case MLX5_RES_SQ:
 		qp = (struct mlx5_core_qp *)common;
+		if (WARN_ON_ONCE(!qp->event))
+			goto out;
 		qp->event(qp, event_type);
 		/* Need to put resource in event handler */
 		return NOTIFY_OK;
@@ -258,6 +260,14 @@ int mlx5_qpc_create_qp(struct mlx5_ib_dev *dev, struct mlx5_core_qp *qp,
 
 	qp->uid = MLX5_GET(create_qp_in, in, uid);
 	qp->qpn = MLX5_GET(create_qp_out, out, qpn);
+	/* Set ibqp.qp_num before create_resource_common() inserts the QP into
+	 * the radix tree and makes it visible to EQE processing.  The
+	 * assignment in create_qp() happens only after this function returns,
+	 * leaving a window where an arriving EQE would observe qp_num == 0.
+	 * create_qp() still overrides this with 0/1 for QP0/QP1, and sets it
+	 * independently for DCT (which does not go through this function).
+	 */
+	to_mibqp(qp)->ibqp.qp_num = qp->qpn;
 
 	err = create_resource_common(dev, qp, MLX5_RES_QP);
 	if (err)
-- 
2.18.1


  parent reply	other threads:[~2026-09-08 15:31 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-08 15:28 [PATCH rdma-next 00/15] DMA direction and mlx5 driver correctness fixes Yishai Hadas
2026-09-08 15:28 ` [PATCH rdma-next 01/15] RDMA/erdma: Pin CQ buffer writable to match device DMA write access Yishai Hadas
2026-09-08 15:28 ` [PATCH rdma-next 02/15] RDMA/hns: " Yishai Hadas
2026-09-08 15:28 ` [PATCH rdma-next 03/15] RDMA/vmw_pvrdma: Pin QP and SRQ rings " Yishai Hadas
2026-09-08 15:28 ` [PATCH rdma-next 04/15] RDMA/umem: Reuse ib_umem_get_cq_buf_or_va() for VA-only CQ pinning Yishai Hadas
2026-09-08 15:28 ` [PATCH rdma-next 05/15] RDMA/umem: Support an explicit DMA direction other than DMA_BIDIRECTIONAL Yishai Hadas
2026-09-08 15:28 ` [PATCH rdma-next 06/15] RDMA/umem: Map CQ buffers DMA_FROM_DEVICE Yishai Hadas
2026-09-08 15:28 ` [PATCH rdma-next 07/15] RDMA/umem: Derive DMA direction from IB access flags Yishai Hadas
2026-09-08 15:28 ` [PATCH rdma-next 08/15] RDMA/mlx5: Fix mlx5_ib_dev_res_init() failure when XRC cap is absent Yishai Hadas
2026-09-08 15:28 ` [PATCH rdma-next 09/15] RDMA/mlx5: Put resource reference in mlx5_ib_wq_event() Yishai Hadas
2026-09-08 15:28 ` [PATCH rdma-next 10/15] RDMA/mlx5: Set WQ event handler before firmware RQ insertion Yishai Hadas
2026-09-08 15:28 ` [PATCH rdma-next 11/15] RDMA/mlx5: Set SRQ event handler before xarray insertion Yishai Hadas
2026-09-08 15:28 ` [PATCH rdma-next 12/15] RDMA/mlx5: Set RQ event handler for raw-packet QP Yishai Hadas
2026-09-08 15:28 ` Yishai Hadas [this message]
2026-09-08 15:28 ` [PATCH rdma-next 14/15] RDMA/mlx5: Initialize QP/RQ/SQ resource refcount before publishing it Yishai Hadas
2026-09-08 15:28 ` [PATCH rdma-next 15/15] RDMA/mlx5: Fix signed integer overflow in EQE qp_srq type shift Yishai Hadas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260908152851.1307294-14-yishaih@nvidia.com \
    --to=yishaih@nvidia.com \
    --cc=abhijit.gangurde@amd.com \
    --cc=allen.hubbe@amd.com \
    --cc=bryan-bt.tan@broadcom.com \
    --cc=chengyou@linux.alibaba.com \
    --cc=huangjunxian6@hisilicon.com \
    --cc=jgg@ziepe.ca \
    --cc=kaishen@linux.alibaba.com \
    --cc=kalesh-anakkur.purayil@broadcom.com \
    --cc=kotaranov@microsoft.com \
    --cc=leon@kernel.org \
    --cc=linux-rdma@vger.kernel.org \
    --cc=longli@microsoft.com \
    --cc=maorg@nvidia.com \
    --cc=mkalderon@marvell.com \
    --cc=selvin.xavier@broadcom.com \
    --cc=tangchengchang@huawei.com \
    --cc=vishnu.dasa@broadcom.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox