From: Xingang Wang wangxingang5@huawei.com
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: Xingang Wang wangxingang5@huawei.com --- drivers/char/svm.c | 79 +++++++++++++++++++++++++++++++++++++ include/linux/ascend_smmu.h | 1 + 2 files changed, 80 insertions(+)
diff --git a/drivers/char/svm.c b/drivers/char/svm.c index 7d82c19c5..cee3b113e 100644 --- a/drivers/char/svm.c +++ b/drivers/char/svm.c @@ -152,6 +152,7 @@ struct spalloc {
struct svm_mpam { #define SVM_GET_DEV_MPAM (1 << 0) +#define SVM_SET_DEV_MPAM (1 << 1) int flags; int pasid; int partid; @@ -1511,6 +1512,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 diff --git a/include/linux/ascend_smmu.h b/include/linux/ascend_smmu.h index a6d205859..e570acfc8 100644 --- a/include/linux/ascend_smmu.h +++ b/include/linux/ascend_smmu.h @@ -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 */