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 Reviewed-by: Yingtai Xie xieyingtai@huawei.com Reviewed-by: Ding Tianhong dingtianhong@huawei.com Signed-off-by: Yang Yingliang yangyingliang@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 1222e4fc45243..1b1b86d0bfed3 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 a6d2058599be5..e570acfc8f6ac 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 */