[PATCH for-next 2/3] RDMA/hns: Fix missing CQE when UD QP use different SL

From: hginjgerx

Date: Thu Jun 04 2026 - 07:48:37 EST


From: Chengchang Tang <tangchengchang@xxxxxxxxxx>

Due to the HW issue, CQE may be dropped if UD QP use multiple SLs.

Fixes: 926a01dc000d ("RDMA/hns: Add QP operations support for hip08 SoC")
Signed-off-by: Chengchang Tang <tangchengchang@xxxxxxxxxx>
Signed-off-by: Junxian Huang <huangjunxian6@xxxxxxxxxxxxx>
---
drivers/infiniband/hw/hns/hns_roce_device.h | 1 +
drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 15 ++++++++++-----
2 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h
index eb7b1865e4c7..686610642c0a 100644
--- a/drivers/infiniband/hw/hns/hns_roce_device.h
+++ b/drivers/infiniband/hw/hns/hns_roce_device.h
@@ -654,6 +654,7 @@ struct hns_roce_qp {
u8 priority;
spinlock_t flush_lock;
struct hns_roce_dip *dip;
+ bool ud_sl_set;
};

struct hns_roce_ib_iboe {
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
index fe3c658d8c08..6dd56a85d890 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
@@ -431,7 +431,8 @@ static int set_ud_opcode(struct hns_roce_v2_ud_send_wqe *ud_sq_wqe,
return 0;
}

-static int fill_ud_av(struct hns_roce_v2_ud_send_wqe *ud_sq_wqe,
+static int fill_ud_av(struct hns_roce_qp *qp,
+ struct hns_roce_v2_ud_send_wqe *ud_sq_wqe,
struct hns_roce_ah *ah)
{
struct ib_device *ib_dev = ah->ibah.device;
@@ -441,7 +442,12 @@ static int fill_ud_av(struct hns_roce_v2_ud_send_wqe *ud_sq_wqe,
hr_reg_write(ud_sq_wqe, UD_SEND_WQE_HOPLIMIT, ah->av.hop_limit);
hr_reg_write(ud_sq_wqe, UD_SEND_WQE_TCLASS, ah->av.tclass);
hr_reg_write(ud_sq_wqe, UD_SEND_WQE_FLOW_LABEL, ah->av.flowlabel);
- hr_reg_write(ud_sq_wqe, UD_SEND_WQE_SL, ah->av.sl);
+ if (!qp->ud_sl_set) {
+ qp->sl = ah->av.sl;
+ qp->ud_sl_set = true;
+ }
+
+ hr_reg_write(ud_sq_wqe, UD_SEND_WQE_SL, qp->sl);

ud_sq_wqe->sgid_index = ah->av.gid_index;

@@ -491,12 +497,10 @@ static inline int set_ud_wqe(struct hns_roce_qp *qp,
qp->qkey : ud_wr(wr)->remote_qkey);
hr_reg_write(ud_sq_wqe, UD_SEND_WQE_DQPN, ud_wr(wr)->remote_qpn);

- ret = fill_ud_av(ud_sq_wqe, ah);
+ ret = fill_ud_av(qp, ud_sq_wqe, ah);
if (ret)
return ret;

- qp->sl = to_hr_ah(ud_wr(wr)->ah)->av.sl;
-
set_extend_sge(qp, wr->sg_list, &curr_idx, valid_num_sge);

/*
@@ -5606,6 +5610,7 @@ static void v2_set_flushed_fields(struct ib_qp *ibqp,
hr_reg_write(context, QPC_SQ_PRODUCER_IDX, hr_qp->sq.head);
hr_reg_clear(qpc_mask, QPC_SQ_PRODUCER_IDX);
hr_qp->state = IB_QPS_ERR;
+ hr_qp->ud_sl_set = false;
spin_unlock_irqrestore(&hr_qp->sq.lock, sq_flag);

if (ibqp->srq || ibqp->qp_type == IB_QPT_XRC_INI) /* no RQ */
--
2.33.0