提交 44503aec 编写于 作者: X xuzaibo 提交者: Xie XiuQi

ACC: Bugfixed while removing VFs with user space tasks on

driver inclusion
category: bugfix
bugzilla: NA
CVE: NA

[  686.684022] Call trace:
[  686.684025]  __vunmap+0x44/0xf8
[  686.684026]  vunmap+0x24/0x30
[  686.684030]  arch_dma_free+0x84/0xa8
[  686.684032]  dma_direct_free+0x30/0x38
[  686.684033]  dma_free_attrs+0xa0/0xe8
[  686.684037]  uacce_queue_drain+0x12c/0x180 [uacce]
[  686.684039]  uacce_fops_flush+0x70/0x80 [uacce]
[  686.684041]  filp_close+0x30/0x90
[  686.684045]  put_files_struct+0xf8/0x100
[  686.684048]  exit_files+0x40/0x58
[  686.684052]  do_exit+0x294/0xa18
[  686.684054]  do_group_exit+0x38/0xa0
[  686.684055]  __arm64_sys_exit_group+0x14/0x18
[  686.684059]  el0_svc_common+0x5c/0x100
[  686.684060]  el0_svc_handler+0x2c/0x80
[  686.684062]  el0_svc+0x8/0xc
[  686.684063] ---[ end trace 82054841c5907aec ]---
[  686.684070] Unable to handle kernel paging request at virtual
	       address ffff00001aee0204
As user tries to disable SRIOV on the PCI device, we try to check
whether there is any user including kernel crypto or user space. If
any, disabling returns failure. For devices who don't use UACCE, there
is no such check.
Signed-off-by: Nxuzaibo <xuzaibo@huawei.com>
Reviewed-by: Nwangzhou <wangzhou1@hisilicon.com>
Signed-off-by: Nlingmingqiang <lingmingqiang@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 34c8a762
......@@ -4,7 +4,6 @@
#include <linux/bitops.h>
#include <linux/debugfs.h>
#include <linux/io.h>
#include <linux/bitops.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
......@@ -858,9 +857,9 @@ static int hpre_clear_vft_config(struct hpre *hpre)
return 0;
}
#ifdef CONFIG_PCI_IOV
static int hpre_sriov_enable(struct pci_dev *pdev, int max_vfs)
{
#ifdef CONFIG_PCI_IOV
struct hpre *hpre = pci_get_drvdata(pdev);
int pre_existing_vfs, num_vfs, ret;
......@@ -884,9 +883,31 @@ static int hpre_sriov_enable(struct pci_dev *pdev, int max_vfs)
return ret;
}
return num_vfs;
#else
return 0;
#endif
}
static int hpre_try_frozen_vfs(struct pci_dev *pdev)
{
int ret = 0;
struct hpre *hpre, *vf_hpre;
struct pci_dev *dev;
/* Try to frozen all the VFs as disable SRIOV */
mutex_lock(&hpre_list_lock);
list_for_each_entry(hpre, &hpre_list, list) {
dev = hpre->qm.pdev;
if (dev == pdev)
continue;
if (pci_physfn(dev) == pdev) {
vf_hpre = pci_get_drvdata(dev);
ret = hisi_qm_frozen(&vf_hpre->qm);
if (ret)
goto frozen_fail;
}
}
frozen_fail:
mutex_unlock(&hpre_list_lock);
return ret;
}
static int hpre_sriov_disable(struct pci_dev *pdev)
......@@ -900,6 +921,16 @@ static int hpre_sriov_disable(struct pci_dev *pdev)
return -EPERM;
}
/* While VF is in used, SRIOV cannot be disabled.
* However, there is a risk that the behavior is uncertain if the
* device is in hardware resetting.
*/
if (hpre_try_frozen_vfs(pdev)) {
dev_err(&pdev->dev,
"Uacce user space task is using its VF!\n");
return -EBUSY;
}
/* remove in hpre_pci_driver will be called to free VF resources */
pci_disable_sriov(pdev);
return hpre_clear_vft_config(hpre);
......@@ -912,6 +943,7 @@ static int hpre_sriov_configure(struct pci_dev *pdev, int num_vfs)
else
return hpre_sriov_enable(pdev, num_vfs);
}
#endif
static void hpre_log_hw_error(struct hpre *hpre, u32 err_sts)
{
......@@ -1229,7 +1261,9 @@ static struct pci_driver hpre_pci_driver = {
.id_table = hpre_dev_ids,
.probe = hpre_probe,
.remove = hpre_remove,
#ifdef CONFIG_PCI_IOV
.sriov_configure = hpre_sriov_configure,
#endif
.err_handler = &hpre_err_handler,
};
......
......@@ -1825,6 +1825,34 @@ void hisi_qm_uninit(struct hisi_qm *qm)
}
EXPORT_SYMBOL_GPL(hisi_qm_uninit);
/**
* hisi_qm_frozen() - Try to froze QM to cut continuous queue request. If
* there is user on the QM, return failure without doing anything.
* @qm: The qm needed to be fronzen.
*
* This function frozes QM, then we can do SRIOV disabling.
*/
int hisi_qm_frozen(struct hisi_qm *qm)
{
int ret, i;
write_lock(&qm->qps_lock);
for (i = 0, ret = 0; i < qm->qp_num; i++)
if (!qm->qp_array[i])
ret++;
if (ret == qm->qp_num) {
bitmap_set(qm->qp_bitmap, 0, qm->qp_num);
} else {
write_unlock(&qm->qps_lock);
return -EBUSY;
}
write_unlock(&qm->qps_lock);
return 0;
}
EXPORT_SYMBOL_GPL(hisi_qm_frozen);
/**
* hisi_qm_get_vft() - Get vft from a qm.
* @qm: The qm we want to get its vft.
......
......@@ -305,6 +305,7 @@ struct hisi_qp {
int hisi_qm_init(struct hisi_qm *qm);
void hisi_qm_uninit(struct hisi_qm *qm);
int hisi_qm_frozen(struct hisi_qm *qm);
int hisi_qm_start(struct hisi_qm *qm);
int hisi_qm_stop(struct hisi_qm *qm);
struct hisi_qp *hisi_qm_create_qp(struct hisi_qm *qm, u8 alg_type);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册