Commit c9781f87 authored by Weili Qian's avatar Weili Qian
Browse files

crypto: hisilicon/qm - disable error report before flr

driver inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IBATCK


CVE: NA

----------------------------------------------------------------------

Before function level reset, driver first disable device error report
and then waits for the device reset to complete. However, when the
error is recovered, the error bits will be enabled again, resulting in
invalid disable. It is modified to detect that there is no error
before disable error report, and then do FLR. In addition, the device
cache is triggered to write back to memory to prevent residual data in
the device.

Fixes: 7ce396fa ("crypto: hisilicon - add FLR support")
Signed-off-by: default avatarWeili Qian <qianweili@huawei.com>
Signed-off-by: default avatarJiangShui Yang <yangjiangshui@h-partners.com>
parent 32b5a32c
Loading
Loading
Loading
Loading
+32 −17
Original line number Diff line number Diff line
@@ -4670,22 +4670,30 @@ void hisi_qm_reset_prepare(struct pci_dev *pdev)
	u32 delay = 0;
	int ret;

	hisi_qm_dev_err_uninit(pf_qm);
	while (true) {
		ret = qm_reset_prepare_ready(qm);
		if (ret) {
			pci_err(pdev, "FLR not ready!\n");
			return;
		}

		hisi_qm_dev_err_uninit(pf_qm);
		/*
	 * Check whether there is an ECC mbit error, If it occurs, need to
	 * wait for soft reset to fix it.
		 * Check whether there is an ECC mbit error,
		 * If it occurs, need to wait for soft reset
		 * to fix it.
		 */
	while (qm_check_dev_error(pf_qm)) {
		msleep(++delay);
		if (delay > QM_RESET_WAIT_TIMEOUT)
		if (qm_check_dev_error(qm)) {
			qm_reset_bit_clear(qm);
			if (delay > QM_RESET_WAIT_TIMEOUT) {
				pci_err(pdev, "the hardware error was not recovered!\n");
				return;
			}

	ret = qm_reset_prepare_ready(qm);
	if (ret) {
		pci_err(pdev, "FLR not ready!\n");
		return;
			msleep(++delay);
		} else {
			break;
		}
	}

	/* PF obtains the information of VF by querying the register. */
@@ -4699,16 +4707,23 @@ void hisi_qm_reset_prepare(struct pci_dev *pdev)
	ret = hisi_qm_stop(qm, QM_DOWN);
	if (ret) {
		pci_err(pdev, "Failed to stop QM, ret = %d.\n", ret);
		hisi_qm_set_hw_reset(qm, QM_RESET_STOP_TX_OFFSET);
		hisi_qm_set_hw_reset(qm, QM_RESET_STOP_RX_OFFSET);
		return;
		goto err_prepare;
	}

	ret = qm_wait_vf_prepare_finish(qm);
	if (ret)
		pci_err(pdev, "failed to stop by vfs in FLR!\n");

	hisi_qm_cache_wb(qm);
	pci_info(pdev, "FLR resetting...\n");
	return;

err_prepare:
	pci_info(pdev, "FLR resetting prepare failed!\n");
	hisi_qm_set_hw_reset(qm, QM_RESET_STOP_TX_OFFSET);
	hisi_qm_set_hw_reset(qm, QM_RESET_STOP_RX_OFFSET);
	atomic_set(&qm->status.flags, QM_STOP);
	hisi_qm_cache_wb(qm);
}
EXPORT_SYMBOL_GPL(hisi_qm_reset_prepare);