driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I9CB6L CVE: NA
----------------------------------------------------------------------
When funcitons communicate with each other, if the mailbox operation fails, funciton cannot obtain the message from the communication source. If the vf does not receive the message from pf to stop function when reset, it will cause the vf to be unavailable.
For the global reset scenario: 1. Increase the QM_DEVICE_DOWN state. Before IO operation, check the state to avoid mailbox busy during communication. 2. When vf obtains pf message, if the mailbox fails, it is considered to be a global reset, and stop function directly. When pf sends reset message to vf, if the mailbox fails, it still send interrupt event to vf. 3. Increase the response time of PF waiting for vf.
Signed-off-by: Weili Qian qianweili@huawei.com Signed-off-by: JiangShui Yang yangjiangshui@h-partners.com --- drivers/crypto/hisilicon/qm.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index 6257d62cdb65..396978072b08 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -187,9 +187,9 @@ #define QM_IFC_INT_DISABLE BIT(0) #define QM_IFC_INT_STATUS_MASK BIT(0) #define QM_IFC_INT_SET_MASK BIT(0) -#define QM_WAIT_DST_ACK 10 -#define QM_MAX_PF_WAIT_COUNT 10 -#define QM_MAX_VF_WAIT_COUNT 40 +#define QM_WAIT_DST_ACK 100 +#define QM_MAX_PF_WAIT_COUNT 50 +#define QM_MAX_VF_WAIT_COUNT 100 #define QM_VF_RESET_WAIT_US 20000 #define QM_VF_RESET_WAIT_CNT 3000 #define QM_VF_RESET_WAIT_TIMEOUT_US \ @@ -1707,8 +1707,8 @@ static int qm_ping_all_vfs(struct hisi_qm *qm, u64 cmd) mutex_lock(&qm->mailbox_lock); /* PF sends command to all VFs by mailbox */ ret = qm_mb_nolock(qm, &mailbox); - if (ret) { - dev_err(dev, "failed to send command to VFs!\n"); + if (ret && cmd != QM_PF_FLR_PREPARE && cmd != QM_PF_SRST_PREPARE) { + dev_err(dev, "failed to send command to all vfs, cmd = %llu!\n", cmd); mutex_unlock(&qm->mailbox_lock); return ret; } @@ -1748,8 +1748,8 @@ static int qm_ping_pf(struct hisi_qm *qm, u64 cmd) qm_mb_pre_init(&mailbox, QM_MB_CMD_SRC, cmd, 0, 0); mutex_lock(&qm->mailbox_lock); ret = qm_mb_nolock(qm, &mailbox); - if (ret) { - dev_err(&qm->pdev->dev, "failed to send command to PF!\n"); + if (ret && (cmd > QM_VF_START_FAIL || cmd < QM_VF_PREPARE_DONE)) { + dev_err(&qm->pdev->dev, "failed to send command to PF, cmd = %llu!\n", cmd); goto unlock; }
@@ -1758,8 +1758,10 @@ static int qm_ping_pf(struct hisi_qm *qm, u64 cmd) while (true) { msleep(QM_WAIT_DST_ACK); val = readl(qm->io_base + QM_IFC_INT_SET_V); - if (!(val & QM_IFC_INT_STATUS_MASK)) + if (!(val & QM_IFC_INT_STATUS_MASK)) { + ret = 0; break; + }
if (++cnt > QM_MAX_VF_WAIT_COUNT) { ret = -ETIMEDOUT; @@ -4902,8 +4904,13 @@ static void qm_handle_cmd_msg(struct hisi_qm *qm, u32 fun_num) ret = hisi_qm_mb_read(qm, &msg, QM_MB_CMD_DST, fun_num); qm_clear_cmd_interrupt(qm, BIT(fun_num)); if (ret) { - dev_err(dev, "failed to get msg from source!\n"); - return; + if (!fun_num) { + msg = QM_PF_SRST_PREPARE; + dev_err(dev, "failed to get response from PF, suppos it is soft reset!\n"); + } else { + dev_err(dev, "failed to get msg from source!\n"); + return; + } }
cmd = msg & QM_MB_CMD_DATA_MASK;