From: Xingang Wang wangxingang5@huawei.com
ascend inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I49RB2 CVE: NA
-------------------------------------------------
The user_mpam_en configuration is used to enable/disable whether SMMU mpam configuration will be used. If user_mpam_en is 1, the memory requests across SMMU will not carry the SMMU mpam configuration.
Signed-off-by: Xingang Wang wangxingang5@huawei.com Reviewed-by: Yingtai Xie xieyingtai@huawei.com Reviewed-by: Zhen Lei thunder.leizhen@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/iommu/arm-smmu-v3.c | 37 +++++++++++++++++++++++++++++++++++++ include/linux/ascend_smmu.h | 3 +++ 2 files changed, 40 insertions(+)
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 2cce9bccab5dc..c9ff437cb3283 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -194,6 +194,9 @@ #define MPAMIDR_PMG_MAX GENMASK(23, 16) #define MPAMIDR_PARTID_MAX GENMASK(15, 0)
+#define ARM_SMMU_USER_CFG0 0xe00 +#define ARM_SMMU_USER_MPAM_EN (1UL << 30) + /* Common MSI config fields */ #define MSI_CFG0_ADDR_MASK GENMASK_ULL(51, 2) #define MSI_CFG2_SH GENMASK(5, 4) @@ -4349,6 +4352,40 @@ int arm_smmu_get_dev_mpam(struct device *dev, int ssid, int *partid, int *pmg, } EXPORT_SYMBOL(arm_smmu_get_dev_mpam);
+/** + * arm_smmu_set_dev_user_mpam_en() - set user_mpam_en to smmu user cfg0 + */ +int arm_smmu_set_dev_user_mpam_en(struct device *dev, int user_mpam_en) +{ + struct arm_smmu_master_data *master = dev->iommu_fwspec->iommu_priv; + struct arm_smmu_device *smmu = master->domain->smmu; + u32 reg, __iomem *cfg = smmu->base + ARM_SMMU_USER_CFG0; + + reg = readl_relaxed(cfg); + reg &= ~ARM_SMMU_USER_MPAM_EN; + reg |= FIELD_PREP(ARM_SMMU_USER_MPAM_EN, user_mpam_en); + writel_relaxed(reg, cfg); + + return 0; +} +EXPORT_SYMBOL(arm_smmu_set_dev_user_mpam_en); + +/** + * arm_smmu_get_dev_user_mpam_en() - get user_mpam_en from smmu user cfg0 + */ +int arm_smmu_get_dev_user_mpam_en(struct device *dev, int *user_mpam_en) +{ + struct arm_smmu_master_data *master = dev->iommu_fwspec->iommu_priv; + struct arm_smmu_device *smmu = master->domain->smmu; + u32 reg, __iomem *cfg = smmu->base + ARM_SMMU_USER_CFG0; + + reg = readl_relaxed(cfg); + *user_mpam_en = FIELD_GET(ARM_SMMU_USER_MPAM_EN, reg); + + return 0; +} +EXPORT_SYMBOL(arm_smmu_get_dev_user_mpam_en); + static int arm_smmu_device_probe(struct platform_device *pdev) { int irq, ret; diff --git a/include/linux/ascend_smmu.h b/include/linux/ascend_smmu.h index a9f449a135781..c52968e98944c 100644 --- a/include/linux/ascend_smmu.h +++ b/include/linux/ascend_smmu.h @@ -9,4 +9,7 @@ extern int arm_smmu_set_dev_mpam(struct device *dev, int ssid, int partid, extern int arm_smmu_get_dev_mpam(struct device *dev, int ssid, int *partid, int *pmg, int *s1mpam);
+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); + #endif /* __LINUX_ASCEND_SMMU_H */