Skip to content

Commit 377a209

Browse files
wenglianfarleon
authored andcommitted
RDMA/hns: Fix flush cqe error when racing with destroy qp
QP needs to be modified to IB_QPS_ERROR to trigger HW flush cqe. But when this process races with destroy qp, the destroy-qp process may modify the QP to IB_QPS_RESET first. In this case flush cqe will fail since it is invalid to modify qp from IB_QPS_RESET to IB_QPS_ERROR. Add lock and bit flag to make sure pending flush cqe work is completed first and no more new works will be added. Fixes: ffd541d ("RDMA/hns: Add the workqueue framework for flush cqe handler") Signed-off-by: wenglianfa <wenglianfa@huawei.com> Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com> Link: https://patch.msgid.link/20241024124000.2931869-3-huangjunxian6@hisilicon.com Reviewed-by: Zhu Yanjun <yanjun.zhu@linux.dev> Signed-off-by: Leon Romanovsky <leon@kernel.org>
1 parent 571e4ab commit 377a209

3 files changed

Lines changed: 22 additions & 2 deletions

File tree

drivers/infiniband/hw/hns/hns_roce_device.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,7 @@ struct hns_roce_dev;
593593

594594
enum {
595595
HNS_ROCE_FLUSH_FLAG = 0,
596+
HNS_ROCE_STOP_FLUSH_FLAG = 1,
596597
};
597598

598599
struct hns_roce_work {
@@ -656,6 +657,7 @@ struct hns_roce_qp {
656657
enum hns_roce_cong_type cong_type;
657658
u8 tc_mode;
658659
u8 priority;
660+
spinlock_t flush_lock;
659661
};
660662

661663
struct hns_roce_ib_iboe {

drivers/infiniband/hw/hns/hns_roce_hw_v2.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5598,8 +5598,15 @@ int hns_roce_v2_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
55985598
{
55995599
struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
56005600
struct hns_roce_qp *hr_qp = to_hr_qp(ibqp);
5601+
unsigned long flags;
56015602
int ret;
56025603

5604+
/* Make sure flush_cqe() is completed */
5605+
spin_lock_irqsave(&hr_qp->flush_lock, flags);
5606+
set_bit(HNS_ROCE_STOP_FLUSH_FLAG, &hr_qp->flush_flag);
5607+
spin_unlock_irqrestore(&hr_qp->flush_lock, flags);
5608+
flush_work(&hr_qp->flush_work.work);
5609+
56035610
ret = hns_roce_v2_destroy_qp_common(hr_dev, hr_qp, udata);
56045611
if (ret)
56055612
ibdev_err(&hr_dev->ib_dev,

drivers/infiniband/hw/hns/hns_roce_qp.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,18 @@ static void flush_work_handle(struct work_struct *work)
9090
void init_flush_work(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp)
9191
{
9292
struct hns_roce_work *flush_work = &hr_qp->flush_work;
93+
unsigned long flags;
94+
95+
spin_lock_irqsave(&hr_qp->flush_lock, flags);
96+
/* Exit directly after destroy_qp() */
97+
if (test_bit(HNS_ROCE_STOP_FLUSH_FLAG, &hr_qp->flush_flag)) {
98+
spin_unlock_irqrestore(&hr_qp->flush_lock, flags);
99+
return;
100+
}
93101

94-
flush_work->hr_dev = hr_dev;
95-
INIT_WORK(&flush_work->work, flush_work_handle);
96102
refcount_inc(&hr_qp->refcount);
97103
queue_work(hr_dev->irq_workq, &flush_work->work);
104+
spin_unlock_irqrestore(&hr_qp->flush_lock, flags);
98105
}
99106

100107
void flush_cqe(struct hns_roce_dev *dev, struct hns_roce_qp *qp)
@@ -1140,6 +1147,7 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
11401147
struct ib_udata *udata,
11411148
struct hns_roce_qp *hr_qp)
11421149
{
1150+
struct hns_roce_work *flush_work = &hr_qp->flush_work;
11431151
struct hns_roce_ib_create_qp_resp resp = {};
11441152
struct ib_device *ibdev = &hr_dev->ib_dev;
11451153
struct hns_roce_ib_create_qp ucmd = {};
@@ -1148,9 +1156,12 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
11481156
mutex_init(&hr_qp->mutex);
11491157
spin_lock_init(&hr_qp->sq.lock);
11501158
spin_lock_init(&hr_qp->rq.lock);
1159+
spin_lock_init(&hr_qp->flush_lock);
11511160

11521161
hr_qp->state = IB_QPS_RESET;
11531162
hr_qp->flush_flag = 0;
1163+
flush_work->hr_dev = hr_dev;
1164+
INIT_WORK(&flush_work->work, flush_work_handle);
11541165

11551166
if (init_attr->create_flags)
11561167
return -EOPNOTSUPP;

0 commit comments

Comments
 (0)