mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 02:21:52 +09:00
RDMA/hns: Fix soft lockup during bt pages loop
[ Upstream commit 25655580136de59ec89f09089dd28008ea440fc9 ]
Driver runs a for-loop when allocating bt pages and mapping them with
buffer pages. When a large buffer (e.g. MR over 100GB) is being allocated,
it may require a considerable loop count. This will lead to soft lockup:
watchdog: BUG: soft lockup - CPU#27 stuck for 22s!
...
Call trace:
hem_list_alloc_mid_bt+0x124/0x394 [hns_roce_hw_v2]
hns_roce_hem_list_request+0xf8/0x160 [hns_roce_hw_v2]
hns_roce_mtr_create+0x2e4/0x360 [hns_roce_hw_v2]
alloc_mr_pbl+0xd4/0x17c [hns_roce_hw_v2]
hns_roce_reg_user_mr+0xf8/0x190 [hns_roce_hw_v2]
ib_uverbs_reg_mr+0x118/0x290
watchdog: BUG: soft lockup - CPU#35 stuck for 23s!
...
Call trace:
hns_roce_hem_list_find_mtt+0x7c/0xb0 [hns_roce_hw_v2]
mtr_map_bufs+0xc4/0x204 [hns_roce_hw_v2]
hns_roce_mtr_create+0x31c/0x3c4 [hns_roce_hw_v2]
alloc_mr_pbl+0xb0/0x160 [hns_roce_hw_v2]
hns_roce_reg_user_mr+0x108/0x1c0 [hns_roce_hw_v2]
ib_uverbs_reg_mr+0x120/0x2bc
Add a cond_resched() to fix soft lockup during these loops. In order not
to affect the allocation performance of normal-size buffer, set the loop
count of a 100GB MR as the threshold to call cond_resched().
Fixes: 38389eaa4d ("RDMA/hns: Add mtr support for mixed multihop addressing")
Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com>
Link: https://patch.msgid.link/20250311084857.3803665-3-huangjunxian6@hisilicon.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
652393caf0
commit
4104b0023f
@@ -1416,6 +1416,11 @@ static int hem_list_alloc_root_bt(struct hns_roce_dev *hr_dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* This is the bottom bt pages number of a 100G MR on 4K OS, assuming
|
||||
* the bt page size is not expanded by cal_best_bt_pg_sz()
|
||||
*/
|
||||
#define RESCHED_LOOP_CNT_THRESHOLD_ON_4K 12800
|
||||
|
||||
/* construct the base address table and link them by address hop config */
|
||||
int hns_roce_hem_list_request(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_list *hem_list,
|
||||
@@ -1424,6 +1429,7 @@ int hns_roce_hem_list_request(struct hns_roce_dev *hr_dev,
|
||||
{
|
||||
const struct hns_roce_buf_region *r;
|
||||
int ofs, end;
|
||||
int loop;
|
||||
int unit;
|
||||
int ret;
|
||||
int i;
|
||||
@@ -1441,7 +1447,10 @@ int hns_roce_hem_list_request(struct hns_roce_dev *hr_dev,
|
||||
continue;
|
||||
|
||||
end = r->offset + r->count;
|
||||
for (ofs = r->offset; ofs < end; ofs += unit) {
|
||||
for (ofs = r->offset, loop = 1; ofs < end; ofs += unit, loop++) {
|
||||
if (!(loop % RESCHED_LOOP_CNT_THRESHOLD_ON_4K))
|
||||
cond_resched();
|
||||
|
||||
ret = hem_list_alloc_mid_bt(hr_dev, r, unit, ofs,
|
||||
hem_list->mid_bt[i],
|
||||
&hem_list->btm_bt);
|
||||
@@ -1498,9 +1507,14 @@ void *hns_roce_hem_list_find_mtt(struct hns_roce_dev *hr_dev,
|
||||
struct list_head *head = &hem_list->btm_bt;
|
||||
struct hns_roce_hem_item *hem, *temp_hem;
|
||||
void *cpu_base = NULL;
|
||||
int loop = 1;
|
||||
int nr = 0;
|
||||
|
||||
list_for_each_entry_safe(hem, temp_hem, head, sibling) {
|
||||
if (!(loop % RESCHED_LOOP_CNT_THRESHOLD_ON_4K))
|
||||
cond_resched();
|
||||
loop++;
|
||||
|
||||
if (hem_list_page_is_in_range(hem, offset)) {
|
||||
nr = offset - hem->start;
|
||||
cpu_base = hem->addr + nr * BA_BYTE_LEN;
|
||||
|
||||
Reference in New Issue
Block a user