| From af91e224d5417d2ce32c6806123a1cfe2ee6b742 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Sun, 4 Jan 2026 14:40:57 +0800 |
| Subject: RDMA/hns: Notify ULP of remaining soft-WCs during reset |
| |
| From: Chengchang Tang <tangchengchang@huawei.com> |
| |
| [ Upstream commit 0789f929900d85b80b343c5f04f8b9444e991384 ] |
| |
| During a reset, software-generated WCs cannot be reported via |
| interrupts. This may cause the ULP to miss some WCs. |
| |
| To avoid this, add check in the CQ arm process: if a hardware reset |
| has occurred and there are still unreported soft-WCs, notify the ULP |
| to handle the remaining WCs, thereby preventing any loss of completions. |
| |
| Fixes: 626903e9355b ("RDMA/hns: Add support for reporting wc as software mode") |
| Signed-off-by: Chengchang Tang <tangchengchang@huawei.com> |
| Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com> |
| Link: https://patch.msgid.link/20260104064057.1582216-5-huangjunxian6@hisilicon.com |
| Signed-off-by: Leon Romanovsky <leon@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 23 ++++++++++++++++++++++ |
| 1 file changed, 23 insertions(+) |
| |
| diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c |
| index 2d4b751fc709d..b50529a652741 100644 |
| --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c |
| +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c |
| @@ -3588,6 +3588,23 @@ static void hns_roce_v2_write_cqc(struct hns_roce_dev *hr_dev, |
| HNS_ROCE_V2_CQ_DEFAULT_INTERVAL); |
| } |
| |
| +static bool left_sw_wc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq) |
| +{ |
| + struct hns_roce_qp *hr_qp; |
| + |
| + list_for_each_entry(hr_qp, &hr_cq->sq_list, sq_node) { |
| + if (hr_qp->sq.head != hr_qp->sq.tail) |
| + return true; |
| + } |
| + |
| + list_for_each_entry(hr_qp, &hr_cq->rq_list, rq_node) { |
| + if (hr_qp->rq.head != hr_qp->rq.tail) |
| + return true; |
| + } |
| + |
| + return false; |
| +} |
| + |
| static int hns_roce_v2_req_notify_cq(struct ib_cq *ibcq, |
| enum ib_cq_notify_flags flags) |
| { |
| @@ -3596,6 +3613,12 @@ static int hns_roce_v2_req_notify_cq(struct ib_cq *ibcq, |
| struct hns_roce_v2_db cq_db = {}; |
| u32 notify_flag; |
| |
| + if (hr_dev->state >= HNS_ROCE_DEVICE_STATE_RST_DOWN) { |
| + if ((flags & IB_CQ_REPORT_MISSED_EVENTS) && |
| + left_sw_wc(hr_dev, hr_cq)) |
| + return 1; |
| + return 0; |
| + } |
| /* |
| * flags = 0, then notify_flag : next |
| * flags = 1, then notify flag : solocited |
| -- |
| 2.51.0 |
| |