Skip to content

Commit 9747c0c

Browse files
Junxian Huangrleon
authored andcommitted
RDMA/hns: Fix mbox timing out by adding retry mechanism
If a QP is modified to error state and a flush CQE process is triggered, the subsequent QP destruction mbox can still be successfully posted but will be blocked in HW until the flush CQE process finishes. This causes further mbox posting timeouts in driver. The blocking time is related to QP depth. Considering an extreme case where SQ depth and RQ depth are both 32K, the blocking time can reach about 135ms. This patch adds a retry mechanism for mbox posting. For each try, FW waits 15ms for HW to complete the previous mbox, otherwise return a timeout error code to driver. Counting other time consumption in FW, set 8 tries for mbox posting and a 5ms time gap before each retry to increase to a sufficient timeout limit. Fixes: 0425e3e ("RDMA/hns: Support flush cqe for hip08 in kernel space") Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com> Link: https://patch.msgid.link/20250208105930.522796-1-huangjunxian6@hisilicon.com Signed-off-by: Leon Romanovsky <leon@kernel.org>
1 parent ee9d161 commit 9747c0c

File tree

2 files changed

+50
-16
lines changed

2 files changed

+50
-16
lines changed

drivers/infiniband/hw/hns/hns_roce_hw_v2.c

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1286,10 +1286,8 @@ static u32 hns_roce_cmdq_tx_timeout(u16 opcode, u32 tx_timeout)
12861286
return tx_timeout;
12871287
}
12881288

1289-
static void hns_roce_wait_csq_done(struct hns_roce_dev *hr_dev, u16 opcode)
1289+
static void hns_roce_wait_csq_done(struct hns_roce_dev *hr_dev, u32 tx_timeout)
12901290
{
1291-
struct hns_roce_v2_priv *priv = hr_dev->priv;
1292-
u32 tx_timeout = hns_roce_cmdq_tx_timeout(opcode, priv->cmq.tx_timeout);
12931291
u32 timeout = 0;
12941292

12951293
do {
@@ -1299,8 +1297,9 @@ static void hns_roce_wait_csq_done(struct hns_roce_dev *hr_dev, u16 opcode)
12991297
} while (++timeout < tx_timeout);
13001298
}
13011299

1302-
static int __hns_roce_cmq_send(struct hns_roce_dev *hr_dev,
1303-
struct hns_roce_cmq_desc *desc, int num)
1300+
static int __hns_roce_cmq_send_one(struct hns_roce_dev *hr_dev,
1301+
struct hns_roce_cmq_desc *desc,
1302+
int num, u32 tx_timeout)
13041303
{
13051304
struct hns_roce_v2_priv *priv = hr_dev->priv;
13061305
struct hns_roce_v2_cmq_ring *csq = &priv->cmq.csq;
@@ -1309,8 +1308,6 @@ static int __hns_roce_cmq_send(struct hns_roce_dev *hr_dev,
13091308
int ret;
13101309
int i;
13111310

1312-
spin_lock_bh(&csq->lock);
1313-
13141311
tail = csq->head;
13151312

13161313
for (i = 0; i < num; i++) {
@@ -1324,22 +1321,17 @@ static int __hns_roce_cmq_send(struct hns_roce_dev *hr_dev,
13241321

13251322
atomic64_inc(&hr_dev->dfx_cnt[HNS_ROCE_DFX_CMDS_CNT]);
13261323

1327-
hns_roce_wait_csq_done(hr_dev, le16_to_cpu(desc->opcode));
1324+
hns_roce_wait_csq_done(hr_dev, tx_timeout);
13281325
if (hns_roce_cmq_csq_done(hr_dev)) {
13291326
ret = 0;
13301327
for (i = 0; i < num; i++) {
13311328
/* check the result of hardware write back */
1332-
desc[i] = csq->desc[tail++];
1329+
desc_ret = le16_to_cpu(csq->desc[tail++].retval);
13331330
if (tail == csq->desc_num)
13341331
tail = 0;
1335-
1336-
desc_ret = le16_to_cpu(desc[i].retval);
13371332
if (likely(desc_ret == CMD_EXEC_SUCCESS))
13381333
continue;
13391334

1340-
dev_err_ratelimited(hr_dev->dev,
1341-
"Cmdq IO error, opcode = 0x%x, return = 0x%x.\n",
1342-
desc->opcode, desc_ret);
13431335
ret = hns_roce_cmd_err_convert_errno(desc_ret);
13441336
}
13451337
} else {
@@ -1354,14 +1346,54 @@ static int __hns_roce_cmq_send(struct hns_roce_dev *hr_dev,
13541346
ret = -EAGAIN;
13551347
}
13561348

1357-
spin_unlock_bh(&csq->lock);
1358-
13591349
if (ret)
13601350
atomic64_inc(&hr_dev->dfx_cnt[HNS_ROCE_DFX_CMDS_ERR_CNT]);
13611351

13621352
return ret;
13631353
}
13641354

1355+
static int __hns_roce_cmq_send(struct hns_roce_dev *hr_dev,
1356+
struct hns_roce_cmq_desc *desc, int num)
1357+
{
1358+
struct hns_roce_v2_priv *priv = hr_dev->priv;
1359+
struct hns_roce_v2_cmq_ring *csq = &priv->cmq.csq;
1360+
u16 opcode = le16_to_cpu(desc->opcode);
1361+
u32 tx_timeout = hns_roce_cmdq_tx_timeout(opcode, priv->cmq.tx_timeout);
1362+
u8 try_cnt = HNS_ROCE_OPC_POST_MB_TRY_CNT;
1363+
u32 rsv_tail;
1364+
int ret;
1365+
int i;
1366+
1367+
while (try_cnt) {
1368+
try_cnt--;
1369+
1370+
spin_lock_bh(&csq->lock);
1371+
rsv_tail = csq->head;
1372+
ret = __hns_roce_cmq_send_one(hr_dev, desc, num, tx_timeout);
1373+
if (opcode == HNS_ROCE_OPC_POST_MB && ret == -ETIME &&
1374+
try_cnt) {
1375+
spin_unlock_bh(&csq->lock);
1376+
mdelay(HNS_ROCE_OPC_POST_MB_RETRY_GAP_MSEC);
1377+
continue;
1378+
}
1379+
1380+
for (i = 0; i < num; i++) {
1381+
desc[i] = csq->desc[rsv_tail++];
1382+
if (rsv_tail == csq->desc_num)
1383+
rsv_tail = 0;
1384+
}
1385+
spin_unlock_bh(&csq->lock);
1386+
break;
1387+
}
1388+
1389+
if (ret)
1390+
dev_err_ratelimited(hr_dev->dev,
1391+
"Cmdq IO error, opcode = 0x%x, return = %d.\n",
1392+
opcode, ret);
1393+
1394+
return ret;
1395+
}
1396+
13651397
static int hns_roce_cmq_send(struct hns_roce_dev *hr_dev,
13661398
struct hns_roce_cmq_desc *desc, int num)
13671399
{

drivers/infiniband/hw/hns/hns_roce_hw_v2.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,8 @@ enum hns_roce_opcode_type {
230230
};
231231

232232
#define HNS_ROCE_OPC_POST_MB_TIMEOUT 35000
233+
#define HNS_ROCE_OPC_POST_MB_TRY_CNT 8
234+
#define HNS_ROCE_OPC_POST_MB_RETRY_GAP_MSEC 5
233235
struct hns_roce_cmdq_tx_timeout_map {
234236
u16 opcode;
235237
u32 tx_timeout;

0 commit comments

Comments
 (0)