driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I7BJW9 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 device 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 device 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 | 40 ++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 10 deletions(-)
diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index c5eaa8877e74..5867c69a8ff8 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -176,9 +176,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 \ @@ -535,6 +535,9 @@ static bool qm_check_dev_error(struct hisi_qm *qm) { u32 val, dev_val;
+ if (test_bit(QM_DEVICE_DOWN, &qm->misc_ctl)) + return true; + if (qm->fun_type == QM_HW_VF) return false;
@@ -706,12 +709,19 @@ static int qm_mb_nolock(struct hisi_qm *qm, struct qm_mailbox *mailbox)
int hisi_qm_mb_write(struct hisi_qm *qm, u8 cmd, dma_addr_t dma_addr, u16 queue, bool op) { + struct hisi_qm *pf_qm = pci_get_drvdata(pci_physfn(qm->pdev)); struct qm_mailbox mailbox; int ret;
dev_dbg(&qm->pdev->dev, "QM mailbox request to q%u: %u-0x%llx\n", queue, cmd, (unsigned long long)dma_addr);
+ /* No need to judge if master OOO is blocked. */ + if (qm_check_dev_error(pf_qm)) { + dev_err(&qm->pdev->dev, "QM mailbox operation failed since qm is stop!\n"); + return -EIO; + } + qm_mb_pre_init(&mailbox, cmd, dma_addr, queue, op); mutex_lock(&qm->mailbox_lock); ret = qm_mb_nolock(qm, &mailbox); @@ -1712,8 +1722,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; } @@ -1753,8 +1763,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; }
@@ -1763,8 +1773,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; @@ -4969,6 +4981,7 @@ static void qm_pf_reset_vf_process(struct hisi_qm *qm, if (ret) goto err_get_status;
+ clear_bit(QM_DEVICE_DOWN, &qm->misc_ctl); qm_pf_reset_vf_done(qm);
dev_info(dev, "device reset done.\n"); @@ -4976,6 +4989,7 @@ static void qm_pf_reset_vf_process(struct hisi_qm *qm, return;
err_get_status: + clear_bit(QM_DEVICE_DOWN, &qm->misc_ctl); qm_cmd_init(qm); qm_reset_bit_clear(qm); } @@ -4994,8 +5008,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_info(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; @@ -5004,6 +5023,7 @@ static void qm_handle_cmd_msg(struct hisi_qm *qm, u32 fun_num) qm_pf_reset_vf_process(qm, QM_DOWN); break; case QM_PF_SRST_PREPARE: + set_bit(QM_DEVICE_DOWN, &qm->misc_ctl); qm_pf_reset_vf_process(qm, QM_SOFT_RESET); break; case QM_VF_GET_QOS: