Commit 464f6990 authored by Xingang Wang's avatar Xingang Wang Committed by Yang Yingliang
Browse files

svm: Add support to set svm mpam configuration

ascend inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I49RB2


CVE: NA

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

This add svm_set_mpam interface in svm module, which traverse all
accelerators, and set the mpam configuration in SMMU. If error occurs
during the traverse process, mpam configuration of all accelerators
will rollback to previous.

Signed-off-by: default avatarXingang Wang <wangxingang5@huawei.com>
Reviewed-by: default avatarYingtai Xie <xieyingtai@huawei.com>
Reviewed-by: default avatarDing Tianhong <dingtianhong@huawei.com>
Signed-off-by: default avatarYang Yingliang <yangyingliang@huawei.com>
parent 0cc88dd8
Loading
Loading
Loading
Loading
+79 −0
Original line number Diff line number Diff line
@@ -130,6 +130,7 @@ struct meminfo {

struct svm_mpam {
#define SVM_GET_DEV_MPAM	(1 << 0)
#define SVM_SET_DEV_MPAM	(1 << 1)
	int flags;
	int pasid;
	int partid;
@@ -1237,6 +1238,84 @@ int __svm_get_mpam(struct svm_mpam *mpam)
	return 0;
}

static int svm_set_core_mpam(struct device *dev, void *data)
{
	int err = 0;
	struct svm_mpam *mpam = data;

	if (mpam->flags & SVM_SET_DEV_MPAM) {
		err = arm_smmu_set_dev_mpam(dev, mpam->pasid, mpam->partid,
				mpam->pmg, mpam->s1mpam);
		if (err) {
			dev_err(dev, "set mpam failed, %d\n", err);
			return err;
		}
	}

	return 0;
}

static int __svm_set_mpam(struct svm_mpam *mpam)
{
	int err = 0;
#ifdef CONFIG_ACPI
	struct core_device *cdev = NULL;
#else
	struct svm_device *sdev = NULL;
#endif

#ifdef CONFIG_ACPI
	list_for_each_entry(cdev, &child_list, entry) {
		err = svm_set_core_mpam(&cdev->dev, mpam);
		if (err)
			return err;
	}
#else
	list_for_each_entry(sdev, &sdev_list, entry) {
		err = device_for_each_child(sdev->dev, mpam, svm_set_core_mpam);
		if (err)
			return err;
	}
#endif

	return 0;
}

/**
 * svm_set_mpam() - set mpam configuration of all core device in smmu
 * @pasid: substream id
 * @partid: mpam partition id
 * @pmg: mpam pmg
 * @s1mpam: 0 for ste mpam, 1 for cd mpam
 */
int svm_set_mpam(int pasid, int partid, int pmg, int s1mpam)
{
	int err;
	struct svm_mpam mpam, old_mpam;

	old_mpam.flags = SVM_GET_DEV_MPAM;
	old_mpam.pasid = pasid;
	err = __svm_get_mpam(&old_mpam);
	if (err)
		return err;

	mpam.flags = SVM_SET_DEV_MPAM;
	mpam.pasid = pasid;
	mpam.partid = partid;
	mpam.pmg = pmg;
	mpam.s1mpam = s1mpam;
	err = __svm_set_mpam(&mpam);
	if (err)
		goto rollback;

	return 0;

rollback:
	__svm_set_mpam(&old_mpam);
	return err;
}
EXPORT_SYMBOL_GPL(svm_set_mpam);

/**
 * svm_get_mpam() - get smmu mpam configuration of core device
 * @pasid: substream id
+1 −0
Original line number Diff line number Diff line
@@ -13,5 +13,6 @@ extern int arm_smmu_set_dev_user_mpam_en(struct device *dev, int user_mpam_en);
extern int arm_smmu_get_dev_user_mpam_en(struct device *dev, int *user_mpam_en);

extern int svm_get_mpam(int pasid, int *partid, int *pmg, int *s1mpam);
extern int svm_set_mpam(int pasid, int partid, int pmg, int s1mpam);

#endif /* __LINUX_ASCEND_SMMU_H */