[PATCH OLK-6.6] crypto: hisilicon/qm - support querying the hardware fault status through VFs
From: Zhushuai Yin <yinzhushuai@huawei.com> driver inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/8816 CVE: NA ---------------------------------------------------------------------- The problem that the VF device cannot obtain the isolation status and isolation threshold of the device is resolved. Signed-off-by: Zhushuai Yin <yinzhushuai@huawei.com> Signed-off-by: JiangShui Yang <yangjiangshui@h-partners.com> --- drivers/crypto/hisilicon/hpre/hpre_main.c | 10 +- drivers/crypto/hisilicon/qm.c | 119 +++++++++++++++++++--- 2 files changed, 111 insertions(+), 18 deletions(-) diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c b/drivers/crypto/hisilicon/hpre/hpre_main.c index 074b3424becf..bcc5bc02bb30 100644 --- a/drivers/crypto/hisilicon/hpre/hpre_main.c +++ b/drivers/crypto/hisilicon/hpre/hpre_main.c @@ -1613,12 +1613,10 @@ static int hpre_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err_qm_del_list; } - if (qm->uacce) { - ret = uacce_register(qm->uacce); - if (ret) { - pci_err(pdev, "failed to register uacce (%d)!\n", ret); - goto err_with_alg_register; - } + ret = qm_register_uacce(qm); + if (ret) { + pci_err(pdev, "failed to register uacce (%d)!\n", ret); + goto err_with_alg_register; } if (qm->fun_type == QM_HW_PF && vfs_num) { diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index ae7132a84e4a..7e7d4d3a79f0 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -252,6 +252,10 @@ #define QM_QOS_MAX_CIR_U 6 #define QM_AUTOSUSPEND_DELAY 3000 +/* qm isolation state mask */ +#define QM_ISOLATED_STATE BIT(31) +#define QM_ISOLATED_THRESHOLD_MASK GENMASK(15, 0) + /* abnormal status value for stopping queue */ #define QM_STOP_QUEUE_FAIL 1 #define QM_DUMP_SQC_FAIL 3 @@ -292,6 +296,21 @@ enum qm_alg_type { ALG_TYPE_1, }; +/** + * @brief Message format for QM_VF_GET_ISOLATE and QM_PF_SET_ISOLATE commands + * + * These commands use a 32-bit command field (cmd) and 32-bit data field (data) + * + * @details + * Command behavior: + * - QM_VF_GET_ISOLATE: VF requests isolation status and threshold + * - QM_PF_SET_ISOLATE: PF sets isolation status and threshold + * + * Data field bit layout: + * - bit31 (MSB): Isolation status flag (1 = isolated, 0 = non-isolated) + * - bit15-0 (16 LSB): Isolation threshold value + * - bit30-16 (15 bits): Reserved + */ enum qm_ifc_cmd { QM_PF_FLR_PREPARE = 0x01, QM_PF_SRST_PREPARE, @@ -302,6 +321,8 @@ enum qm_ifc_cmd { QM_VF_START_FAIL, QM_PF_SET_QOS, QM_VF_GET_QOS, + QM_VF_GET_ISOLATE, + QM_PF_SET_ISOLATE }; enum qm_basic_type { @@ -1780,7 +1801,7 @@ static int qm_ping_single_vf(struct hisi_qm *qm, enum qm_ifc_cmd cmd, u32 data, return ret; } -static int qm_ping_all_vfs(struct hisi_qm *qm, enum qm_ifc_cmd cmd) +static int qm_ping_all_vfs(struct hisi_qm *qm, enum qm_ifc_cmd cmd, u32 data) { struct device *dev = &qm->pdev->dev; u32 vfs_num = qm->vfs_num; @@ -1789,7 +1810,7 @@ static int qm_ping_all_vfs(struct hisi_qm *qm, enum qm_ifc_cmd cmd) int ret; u32 i; - ret = qm->ops->set_ifc_begin(qm, cmd, 0, QM_MB_PING_ALL_VFS); + ret = qm->ops->set_ifc_begin(qm, cmd, data, QM_MB_PING_ALL_VFS); if (ret && cmd != QM_PF_FLR_PREPARE && cmd != QM_PF_SRST_PREPARE) { dev_err(dev, "failed to send command(0x%x) to all vfs!\n", cmd); qm->ops->set_ifc_end(qm); @@ -2808,7 +2829,10 @@ static void qm_uacce_base_init(struct hisi_qm *qm) else mmio_page_nr = QM_QP_DB_INTERVAL / PAGE_SIZE; - uacce->is_vf = pdev->is_virtfn; + if (qm->fun_type == QM_HW_PF) + uacce->is_vf = false; + else + uacce->is_vf = true; uacce->priv = qm; uacce->parent = &pdev->dev; qm_get_xqc_depth(qm, &sq_depth, &cq_depth, QM_QP_DEPTH_CAP); @@ -2898,6 +2922,7 @@ static enum uacce_dev_state hisi_qm_get_isolate_state(struct uacce_device *uacce static int hisi_qm_isolate_threshold_write(struct uacce_device *uacce, u32 num) { struct hisi_qm *qm = uacce->priv; + int ret; /* Must be set by PF */ if (uacce->is_vf) @@ -2911,6 +2936,18 @@ static int hisi_qm_isolate_threshold_write(struct uacce_device *uacce, u32 num) /* After the policy is updated, need to reset the hardware err list */ qm_hw_err_destroy(qm); + + if (!qm->vfs_num) { + mutex_unlock(&qm->isolate_data.isolate_lock); + return 0; + } + + /* Notifying all VFs to update after the PF sets a threshold. */ + if (test_bit(QM_SUPPORT_MB_COMMAND, &qm->caps)) { + ret = qm_ping_all_vfs(qm, QM_PF_SET_ISOLATE, qm->isolate_data.err_threshold); + if (ret) + dev_err(&qm->pdev->dev, "failed to send command to all VFs set isolate!\n"); + } mutex_unlock(&qm->isolate_data.isolate_lock); return 0; @@ -2921,7 +2958,7 @@ static u32 hisi_qm_isolate_threshold_read(struct uacce_device *uacce) struct hisi_qm *qm = uacce->priv; struct hisi_qm *pf_qm; - if (uacce->is_vf) { + if (uacce->is_vf && !test_bit(QM_SUPPORT_MB_COMMAND, &qm->caps)) { pf_qm = pci_get_drvdata(pci_physfn(qm->pdev)); return pf_qm->isolate_data.err_threshold; } @@ -3004,10 +3041,19 @@ static int qm_alloc_uacce(struct hisi_qm *qm) int qm_register_uacce(struct hisi_qm *qm) { + int ret; + if (!qm->uacce) return 0; dev_info(&qm->pdev->dev, "qm register to uacce\n"); + + if (qm->fun_type == QM_HW_VF && test_bit(QM_SUPPORT_MB_COMMAND, &qm->caps)) { + ret = qm_ping_pf(qm, QM_VF_GET_ISOLATE); + if (ret) + dev_err(&qm->pdev->dev, "failed to send cmd to PF to get isolate!\n"); + } + return uacce_register(qm->uacce); } EXPORT_SYMBOL_GPL(qm_register_uacce); @@ -4581,7 +4627,7 @@ static int qm_try_stop_vfs(struct hisi_qm *qm, enum qm_ifc_cmd cmd, /* Kunpeng930 supports to notify VFs to stop before PF reset */ if (test_bit(QM_SUPPORT_MB_COMMAND, &qm->caps)) { - ret = qm_ping_all_vfs(qm, cmd); + ret = qm_ping_all_vfs(qm, cmd, 0); if (ret) pci_err(pdev, "failed to send command to all VFs before PF reset!\n"); } else { @@ -4766,6 +4812,7 @@ static int qm_vf_reset_done(struct hisi_qm *qm) static int qm_try_start_vfs(struct hisi_qm *qm, enum qm_ifc_cmd cmd) { struct pci_dev *pdev = qm->pdev; + u32 data; int ret; if (!qm->vfs_num) @@ -4779,7 +4826,11 @@ static int qm_try_start_vfs(struct hisi_qm *qm, enum qm_ifc_cmd cmd) /* Kunpeng930 supports to notify VFs to start after PF reset. */ if (test_bit(QM_SUPPORT_MB_COMMAND, &qm->caps)) { - ret = qm_ping_all_vfs(qm, cmd); + data = qm->isolate_data.err_threshold; + if (qm->isolate_data.is_isolate) + data |= QM_ISOLATED_STATE; + /* Broadcasting isolate info via RAS to all VFs. */ + ret = qm_ping_all_vfs(qm, cmd, data); if (ret) pci_warn(pdev, "failed to send cmd to all VFs after PF reset!\n"); } else { @@ -5247,10 +5298,22 @@ static void qm_pf_reset_vf_done(struct hisi_qm *qm) qm_reset_bit_clear(qm); } -static int qm_wait_pf_reset_finish(struct hisi_qm *qm) +static void qm_vf_update_isolate_info(struct hisi_qm *qm, u32 data) +{ + /* Updating the local isolation status. */ + mutex_lock(&qm->isolate_data.isolate_lock); + if (data & QM_ISOLATED_STATE) + qm->isolate_data.is_isolate = true; + else + qm->isolate_data.is_isolate = false; + qm->isolate_data.err_threshold = data & QM_ISOLATED_THRESHOLD_MASK; + mutex_unlock(&qm->isolate_data.isolate_lock); +} + +static int qm_wait_pf_reset_finish(struct hisi_qm *qm, enum qm_stop_reason stop_reason) { struct device *dev = &qm->pdev->dev; - u32 val, cmd; + u32 val, cmd, data; int ret; /* Wait for reset to finish */ @@ -5267,7 +5330,7 @@ static int qm_wait_pf_reset_finish(struct hisi_qm *qm) * Whether message is got successfully, * VF needs to ack PF by clearing the interrupt. */ - ret = qm->ops->get_ifc(qm, &cmd, NULL, 0); + ret = qm->ops->get_ifc(qm, &cmd, &data, 0); qm_clear_cmd_interrupt(qm, 0); if (ret) { dev_err(dev, "failed to get command from PF in reset done!\n"); @@ -5276,10 +5339,14 @@ static int qm_wait_pf_reset_finish(struct hisi_qm *qm) if (cmd != QM_PF_RESET_DONE) { dev_err(dev, "the command(0x%x) is not reset done!\n", cmd); - ret = -EINVAL; + return -EINVAL; } - return ret; + /* The VF processes the device isolation information received from the RAS reset. */ + if (stop_reason == QM_SOFT_RESET) + qm_vf_update_isolate_info(qm, data); + + return 0; } static void qm_pf_reset_vf_process(struct hisi_qm *qm, @@ -5294,7 +5361,7 @@ static void qm_pf_reset_vf_process(struct hisi_qm *qm, qm_cmd_uninit(qm); qm_pf_reset_vf_prepare(qm, stop_reason); - ret = qm_wait_pf_reset_finish(qm); + ret = qm_wait_pf_reset_finish(qm, stop_reason); if (ret) goto err_get_status; @@ -5306,11 +5373,32 @@ static void qm_pf_reset_vf_process(struct hisi_qm *qm, return; err_get_status: + if (stop_reason == QM_SOFT_RESET) { + /* Update local isolation status on PF-VF reset failure. */ + mutex_lock(&qm->isolate_data.isolate_lock); + qm->isolate_data.is_isolate = true; + mutex_unlock(&qm->isolate_data.isolate_lock); + } clear_bit(QM_DEVICE_DOWN, &qm->misc_ctl); qm_cmd_init(qm); qm_reset_bit_clear(qm); } +static void qm_vf_get_isolate_data(struct hisi_qm *qm, u32 fun_num) +{ + u32 data = qm->isolate_data.err_threshold; + struct device *dev = &qm->pdev->dev; + int ret; + + if (qm->isolate_data.is_isolate) + data |= QM_ISOLATED_STATE; + + ret = qm_ping_single_vf(qm, QM_PF_SET_ISOLATE, data, fun_num); + if (ret) + dev_err(dev, "failed to send command(0x%x) to VF(%u)!\n", + (unsigned int)QM_PF_SET_ISOLATE, fun_num); +} + static void qm_handle_cmd_msg(struct hisi_qm *qm, u32 fun_num) { struct device *dev = &qm->pdev->dev; @@ -5348,6 +5436,13 @@ static void qm_handle_cmd_msg(struct hisi_qm *qm, u32 fun_num) case QM_PF_SET_QOS: qm->mb_qos = data; break; + case QM_VF_GET_ISOLATE: + /* Read the isolation policy of the PF during VF initialization. */ + qm_vf_get_isolate_data(qm, fun_num); + break; + case QM_PF_SET_ISOLATE: + qm_vf_update_isolate_info(qm, data); + break; default: dev_err(dev, "unsupported command(0x%x) sent by function(%u)!\n", cmd, fun_num); break; -- 2.43.0
participants (1)
-
ZongYu Wu