Commit cd1b7ae3 authored by Shukun Tan's avatar Shukun Tan Committed by Herbert Xu
Browse files

crypto: hisilicon - unify SR-IOV related codes into QM



Clean the duplicate SR-IOV related codes, put all into qm.c.

Signed-off-by: default avatarShukun Tan <tanshukun1@huawei.com>
Reviewed-by: default avatarZhou Wang <wangzhou1@hisilicon.com>
Reviewed-by: default avatarZaibo Xu <xuzaibo@huawei.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 619e464a
Loading
Loading
Loading
Loading
+2 −103
Original line number Diff line number Diff line
@@ -792,107 +792,6 @@ err_with_qm_init:
	return ret;
}

static int hpre_vf_q_assign(struct hpre *hpre, int num_vfs)
{
	struct hisi_qm *qm = &hpre->qm;
	u32 qp_num = qm->qp_num;
	int q_num, remain_q_num, i;
	u32 q_base = qp_num;
	int ret;

	if (!num_vfs)
		return -EINVAL;

	remain_q_num = qm->ctrl_qp_num - qp_num;

	/* If remaining queues are not enough, return error. */
	if (remain_q_num < num_vfs)
		return -EINVAL;

	q_num = remain_q_num / num_vfs;
	for (i = 1; i <= num_vfs; i++) {
		if (i == num_vfs)
			q_num += remain_q_num % num_vfs;
		ret = hisi_qm_set_vft(qm, i, q_base, (u32)q_num);
		if (ret)
			return ret;
		q_base += q_num;
	}

	return 0;
}

static int hpre_clear_vft_config(struct hpre *hpre)
{
	struct hisi_qm *qm = &hpre->qm;
	u32 num_vfs = qm->vfs_num;
	int ret;
	u32 i;

	for (i = 1; i <= num_vfs; i++) {
		ret = hisi_qm_set_vft(qm, i, 0, 0);
		if (ret)
			return ret;
	}
	qm->vfs_num = 0;

	return 0;
}

static int hpre_sriov_enable(struct pci_dev *pdev, int max_vfs)
{
	struct hpre *hpre = pci_get_drvdata(pdev);
	int pre_existing_vfs, num_vfs, ret;

	pre_existing_vfs = pci_num_vf(pdev);
	if (pre_existing_vfs) {
		pci_err(pdev,
			"Can't enable VF. Please disable pre-enabled VFs!\n");
		return 0;
	}

	num_vfs = min_t(int, max_vfs, HPRE_VF_NUM);
	ret = hpre_vf_q_assign(hpre, num_vfs);
	if (ret) {
		pci_err(pdev, "Can't assign queues for VF!\n");
		return ret;
	}

	hpre->qm.vfs_num = num_vfs;

	ret = pci_enable_sriov(pdev, num_vfs);
	if (ret) {
		pci_err(pdev, "Can't enable VF!\n");
		hpre_clear_vft_config(hpre);
		return ret;
	}

	return num_vfs;
}

static int hpre_sriov_disable(struct pci_dev *pdev)
{
	struct hpre *hpre = pci_get_drvdata(pdev);

	if (pci_vfs_assigned(pdev)) {
		pci_err(pdev, "Failed to disable VFs while VFs are assigned!\n");
		return -EPERM;
	}

	/* remove in hpre_pci_driver will be called to free VF resources */
	pci_disable_sriov(pdev);

	return hpre_clear_vft_config(hpre);
}

static int hpre_sriov_configure(struct pci_dev *pdev, int num_vfs)
{
	if (num_vfs)
		return hpre_sriov_enable(pdev, num_vfs);
	else
		return hpre_sriov_disable(pdev);
}

static void hpre_remove(struct pci_dev *pdev)
{
	struct hpre *hpre = pci_get_drvdata(pdev);
@@ -902,7 +801,7 @@ static void hpre_remove(struct pci_dev *pdev)
	hpre_algs_unregister();
	hisi_qm_del_from_list(qm, &hpre_devices);
	if (qm->fun_type == QM_HW_PF && qm->vfs_num) {
		ret = hpre_sriov_disable(pdev);
		ret = hisi_qm_sriov_disable(pdev);
		if (ret) {
			pci_err(pdev, "Disable SRIOV fail!\n");
			return;
@@ -929,7 +828,7 @@ static struct pci_driver hpre_pci_driver = {
	.id_table		= hpre_dev_ids,
	.probe			= hpre_probe,
	.remove			= hpre_remove,
	.sriov_configure	= hpre_sriov_configure,
	.sriov_configure	= hisi_qm_sriov_configure,
	.err_handler		= &hpre_err_handler,
};

+128 −8
Original line number Diff line number Diff line
@@ -1781,12 +1781,6 @@ int hisi_qm_get_vft(struct hisi_qm *qm, u32 *base, u32 *number)
EXPORT_SYMBOL_GPL(hisi_qm_get_vft);

/**
 * hisi_qm_set_vft() - Set "virtual function table" for a qm.
 * @fun_num: Number of operated function.
 * @qm: The qm in which to set vft, alway in a PF.
 * @base: The base number of queue in vft.
 * @number: The number of queues in vft. 0 means invalid vft.
 *
 * This function is alway called in PF driver, it is used to assign queues
 * among PF and VFs.
 *
@@ -1794,7 +1788,7 @@ EXPORT_SYMBOL_GPL(hisi_qm_get_vft);
 * Assign queues A~B to VF: hisi_qm_set_vft(qm, 2, A, B - A + 1)
 * (VF function number 0x2)
 */
int hisi_qm_set_vft(struct hisi_qm *qm, u32 fun_num, u32 base,
static int hisi_qm_set_vft(struct hisi_qm *qm, u32 fun_num, u32 base,
		    u32 number)
{
	u32 max_q_num = qm->ctrl_qp_num;
@@ -1805,7 +1799,6 @@ int hisi_qm_set_vft(struct hisi_qm *qm, u32 fun_num, u32 base,

	return qm_set_sqc_cqc_vft(qm, fun_num, base, number);
}
EXPORT_SYMBOL_GPL(hisi_qm_set_vft);

static void qm_init_eq_aeq_status(struct hisi_qm *qm)
{
@@ -2299,6 +2292,133 @@ err:
}
EXPORT_SYMBOL_GPL(hisi_qm_alloc_qps_node);

static int qm_vf_q_assign(struct hisi_qm *qm, u32 num_vfs)
{
	u32 remain_q_num, q_num, i, j;
	u32 q_base = qm->qp_num;
	int ret;

	if (!num_vfs)
		return -EINVAL;

	remain_q_num = qm->ctrl_qp_num - qm->qp_num;

	/* If remain queues not enough, return error. */
	if (qm->ctrl_qp_num < qm->qp_num || remain_q_num < num_vfs)
		return -EINVAL;

	q_num = remain_q_num / num_vfs;
	for (i = 1; i <= num_vfs; i++) {
		if (i == num_vfs)
			q_num += remain_q_num % num_vfs;
		ret = hisi_qm_set_vft(qm, i, q_base, q_num);
		if (ret) {
			for (j = i; j > 0; j--)
				hisi_qm_set_vft(qm, j, 0, 0);
			return ret;
		}
		q_base += q_num;
	}

	return 0;
}

static int qm_clear_vft_config(struct hisi_qm *qm)
{
	int ret;
	u32 i;

	for (i = 1; i <= qm->vfs_num; i++) {
		ret = hisi_qm_set_vft(qm, i, 0, 0);
		if (ret)
			return ret;
	}
	qm->vfs_num = 0;

	return 0;
}

/**
 * hisi_qm_sriov_enable() - enable virtual functions
 * @pdev: the PCIe device
 * @max_vfs: the number of virtual functions to enable
 *
 * Returns the number of enabled VFs. If there are VFs enabled already or
 * max_vfs is more than the total number of device can be enabled, returns
 * failure.
 */
int hisi_qm_sriov_enable(struct pci_dev *pdev, int max_vfs)
{
	struct hisi_qm *qm = pci_get_drvdata(pdev);
	int pre_existing_vfs, num_vfs, total_vfs, ret;

	total_vfs = pci_sriov_get_totalvfs(pdev);
	pre_existing_vfs = pci_num_vf(pdev);
	if (pre_existing_vfs) {
		pci_err(pdev, "%d VFs already enabled. Please disable pre-enabled VFs!\n",
			pre_existing_vfs);
		return 0;
	}

	num_vfs = min_t(int, max_vfs, total_vfs);
	ret = qm_vf_q_assign(qm, num_vfs);
	if (ret) {
		pci_err(pdev, "Can't assign queues for VF!\n");
		return ret;
	}

	qm->vfs_num = num_vfs;

	ret = pci_enable_sriov(pdev, num_vfs);
	if (ret) {
		pci_err(pdev, "Can't enable VF!\n");
		qm_clear_vft_config(qm);
		return ret;
	}

	pci_info(pdev, "VF enabled, vfs_num(=%d)!\n", num_vfs);

	return num_vfs;
}
EXPORT_SYMBOL_GPL(hisi_qm_sriov_enable);

/**
 * hisi_qm_sriov_disable - disable virtual functions
 * @pdev: the PCI device
 *
 * Return failure if there are VFs assigned already.
 */
int hisi_qm_sriov_disable(struct pci_dev *pdev)
{
	struct hisi_qm *qm = pci_get_drvdata(pdev);

	if (pci_vfs_assigned(pdev)) {
		pci_err(pdev, "Failed to disable VFs as VFs are assigned!\n");
		return -EPERM;
	}

	/* remove in hpre_pci_driver will be called to free VF resources */
	pci_disable_sriov(pdev);
	return qm_clear_vft_config(qm);
}
EXPORT_SYMBOL_GPL(hisi_qm_sriov_disable);

/**
 * hisi_qm_sriov_configure - configure the number of VFs
 * @pdev: The PCI device
 * @num_vfs: The number of VFs need enabled
 *
 * Enable SR-IOV according to num_vfs, 0 means disable.
 */
int hisi_qm_sriov_configure(struct pci_dev *pdev, int num_vfs)
{
	if (num_vfs == 0)
		return hisi_qm_sriov_disable(pdev);
	else
		return hisi_qm_sriov_enable(pdev, num_vfs);
}
EXPORT_SYMBOL_GPL(hisi_qm_sriov_configure);

static pci_ers_result_t qm_dev_err_handle(struct hisi_qm *qm)
{
	u32 err_sts;
+3 −1
Original line number Diff line number Diff line
@@ -268,10 +268,12 @@ void hisi_qm_release_qp(struct hisi_qp *qp);
int hisi_qp_send(struct hisi_qp *qp, const void *msg);
int hisi_qm_get_free_qp_num(struct hisi_qm *qm);
int hisi_qm_get_vft(struct hisi_qm *qm, u32 *base, u32 *number);
int hisi_qm_set_vft(struct hisi_qm *qm, u32 fun_num, u32 base, u32 number);
int hisi_qm_debug_init(struct hisi_qm *qm);
enum qm_hw_ver hisi_qm_get_hw_version(struct pci_dev *pdev);
void hisi_qm_debug_regs_clear(struct hisi_qm *qm);
int hisi_qm_sriov_enable(struct pci_dev *pdev, int max_vfs);
int hisi_qm_sriov_disable(struct pci_dev *pdev);
int hisi_qm_sriov_configure(struct pci_dev *pdev, int num_vfs);
void hisi_qm_dev_err_init(struct hisi_qm *qm);
void hisi_qm_dev_err_uninit(struct hisi_qm *qm);
pci_ers_result_t hisi_qm_dev_err_detected(struct pci_dev *pdev,
+2 −106
Original line number Diff line number Diff line
@@ -892,110 +892,6 @@ err_qm_uninit:
	return ret;
}

/* now we only support equal assignment */
static int sec_vf_q_assign(struct sec_dev *sec, u32 num_vfs)
{
	struct hisi_qm *qm = &sec->qm;
	u32 qp_num = qm->qp_num;
	u32 q_base = qp_num;
	u32 q_num, remain_q_num;
	int i, j, ret;

	if (!num_vfs)
		return -EINVAL;

	remain_q_num = qm->ctrl_qp_num - qp_num;
	q_num = remain_q_num / num_vfs;

	for (i = 1; i <= num_vfs; i++) {
		if (i == num_vfs)
			q_num += remain_q_num % num_vfs;
		ret = hisi_qm_set_vft(qm, i, q_base, q_num);
		if (ret) {
			for (j = i; j > 0; j--)
				hisi_qm_set_vft(qm, j, 0, 0);
			return ret;
		}
		q_base += q_num;
	}

	return 0;
}

static int sec_clear_vft_config(struct sec_dev *sec)
{
	struct hisi_qm *qm = &sec->qm;
	u32 num_vfs = qm->vfs_num;
	int ret;
	u32 i;

	for (i = 1; i <= num_vfs; i++) {
		ret = hisi_qm_set_vft(qm, i, 0, 0);
		if (ret)
			return ret;
	}

	qm->vfs_num = 0;

	return 0;
}

static int sec_sriov_enable(struct pci_dev *pdev, int max_vfs)
{
	struct sec_dev *sec = pci_get_drvdata(pdev);
	int pre_existing_vfs, ret;
	u32 num_vfs;

	pre_existing_vfs = pci_num_vf(pdev);

	if (pre_existing_vfs) {
		pci_err(pdev, "Can't enable VF. Please disable at first!\n");
		return 0;
	}

	num_vfs = min_t(u32, max_vfs, SEC_VF_NUM);

	ret = sec_vf_q_assign(sec, num_vfs);
	if (ret) {
		pci_err(pdev, "Can't assign queues for VF!\n");
		return ret;
	}

	sec->qm.vfs_num = num_vfs;

	ret = pci_enable_sriov(pdev, num_vfs);
	if (ret) {
		pci_err(pdev, "Can't enable VF!\n");
		sec_clear_vft_config(sec);
		return ret;
	}

	return num_vfs;
}

static int sec_sriov_disable(struct pci_dev *pdev)
{
	struct sec_dev *sec = pci_get_drvdata(pdev);

	if (pci_vfs_assigned(pdev)) {
		pci_err(pdev, "Can't disable VFs while VFs are assigned!\n");
		return -EPERM;
	}

	/* remove in sec_pci_driver will be called to free VF resources */
	pci_disable_sriov(pdev);

	return sec_clear_vft_config(sec);
}

static int sec_sriov_configure(struct pci_dev *pdev, int num_vfs)
{
	if (num_vfs)
		return sec_sriov_enable(pdev, num_vfs);
	else
		return sec_sriov_disable(pdev);
}

static void sec_remove(struct pci_dev *pdev)
{
	struct sec_dev *sec = pci_get_drvdata(pdev);
@@ -1006,7 +902,7 @@ static void sec_remove(struct pci_dev *pdev)
	hisi_qm_del_from_list(qm, &sec_devices);

	if (qm->fun_type == QM_HW_PF && qm->vfs_num)
		(void)sec_sriov_disable(pdev);
		hisi_qm_sriov_disable(pdev);

	sec_debugfs_exit(sec);

@@ -1030,7 +926,7 @@ static struct pci_driver sec_pci_driver = {
	.probe = sec_probe,
	.remove = sec_remove,
	.err_handler = &sec_err_handler,
	.sriov_configure = sec_sriov_configure,
	.sriov_configure = hisi_qm_sriov_configure,
};

static void sec_register_debugfs(void)
+3 −106
Original line number Diff line number Diff line
@@ -653,101 +653,6 @@ static int hisi_zip_pf_probe_init(struct hisi_zip *hisi_zip)
	return 0;
}

/* Currently we only support equal assignment */
static int hisi_zip_vf_q_assign(struct hisi_zip *hisi_zip, int num_vfs)
{
	struct hisi_qm *qm = &hisi_zip->qm;
	u32 qp_num = qm->qp_num;
	u32 q_base = qp_num;
	u32 q_num, remain_q_num, i;
	int ret;

	if (!num_vfs)
		return -EINVAL;

	remain_q_num = qm->ctrl_qp_num - qp_num;
	if (remain_q_num < num_vfs)
		return -EINVAL;

	q_num = remain_q_num / num_vfs;
	for (i = 1; i <= num_vfs; i++) {
		if (i == num_vfs)
			q_num += remain_q_num % num_vfs;
		ret = hisi_qm_set_vft(qm, i, q_base, q_num);
		if (ret)
			return ret;
		q_base += q_num;
	}

	return 0;
}

static int hisi_zip_clear_vft_config(struct hisi_zip *hisi_zip)
{
	struct hisi_qm *qm = &hisi_zip->qm;
	u32 i, num_vfs = qm->vfs_num;
	int ret;

	for (i = 1; i <= num_vfs; i++) {
		ret = hisi_qm_set_vft(qm, i, 0, 0);
		if (ret)
			return ret;
	}

	qm->vfs_num = 0;

	return 0;
}

static int hisi_zip_sriov_enable(struct pci_dev *pdev, int max_vfs)
{
	struct hisi_zip *hisi_zip = pci_get_drvdata(pdev);
	int pre_existing_vfs, num_vfs, ret;

	pre_existing_vfs = pci_num_vf(pdev);

	if (pre_existing_vfs) {
		dev_err(&pdev->dev,
			"Can't enable VF. Please disable pre-enabled VFs!\n");
		return 0;
	}

	num_vfs = min_t(int, max_vfs, HZIP_VF_NUM);

	ret = hisi_zip_vf_q_assign(hisi_zip, num_vfs);
	if (ret) {
		dev_err(&pdev->dev, "Can't assign queues for VF!\n");
		return ret;
	}

	hisi_zip->qm.vfs_num = num_vfs;

	ret = pci_enable_sriov(pdev, num_vfs);
	if (ret) {
		dev_err(&pdev->dev, "Can't enable VF!\n");
		hisi_zip_clear_vft_config(hisi_zip);
		return ret;
	}

	return num_vfs;
}

static int hisi_zip_sriov_disable(struct pci_dev *pdev)
{
	struct hisi_zip *hisi_zip = pci_get_drvdata(pdev);

	if (pci_vfs_assigned(pdev)) {
		dev_err(&pdev->dev,
			"Can't disable VFs while VFs are assigned!\n");
		return -EPERM;
	}

	/* remove in hisi_zip_pci_driver will be called to free VF resources */
	pci_disable_sriov(pdev);

	return hisi_zip_clear_vft_config(hisi_zip);
}

static int hisi_zip_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
	struct hisi_zip *hisi_zip;
@@ -820,7 +725,7 @@ static int hisi_zip_probe(struct pci_dev *pdev, const struct pci_device_id *id)
	}

	if (qm->fun_type == QM_HW_PF && vfs_num > 0) {
		ret = hisi_zip_sriov_enable(pdev, vfs_num);
		ret = hisi_qm_sriov_enable(pdev, vfs_num);
		if (ret < 0)
			goto err_remove_from_list;
	}
@@ -836,21 +741,13 @@ err_qm_uninit:
	return ret;
}

static int hisi_zip_sriov_configure(struct pci_dev *pdev, int num_vfs)
{
	if (num_vfs == 0)
		return hisi_zip_sriov_disable(pdev);
	else
		return hisi_zip_sriov_enable(pdev, num_vfs);
}

static void hisi_zip_remove(struct pci_dev *pdev)
{
	struct hisi_zip *hisi_zip = pci_get_drvdata(pdev);
	struct hisi_qm *qm = &hisi_zip->qm;

	if (qm->fun_type == QM_HW_PF && qm->vfs_num)
		hisi_zip_sriov_disable(pdev);
		hisi_qm_sriov_disable(pdev);

	hisi_zip_debugfs_exit(hisi_zip);
	hisi_qm_stop(qm);
@@ -870,7 +767,7 @@ static struct pci_driver hisi_zip_pci_driver = {
	.probe			= hisi_zip_probe,
	.remove			= hisi_zip_remove,
	.sriov_configure	= IS_ENABLED(CONFIG_PCI_IOV) ?
					hisi_zip_sriov_configure : NULL,
					hisi_qm_sriov_configure : NULL,
	.err_handler		= &hisi_zip_err_handler,
};