From 516747fdf71bcbb282398f8c09e108d2f5a2e177 Mon Sep 17 00:00:00 2001 From: "Isaac J. Manjarres" Date: Tue, 7 Apr 2020 10:02:12 -0700 Subject: [PATCH 1/2] iommu/arm-smmu: Fix DOMAIN_ATTR_PAGE_TABLE_FORCE_COHERENT enablement The functionality provided by DOMAIN_ATTR_PAGE_TABLE_FORCE_COHERENT can be guaranteed, independent of CONFIG_QCOM_IOMMU_IO_PGTABLE_QUIRKS, so do not guard its enablement with that config. Change-Id: Ifae4280f256b99529ae5a074dbc91b37b5d87e21 Signed-off-by: Isaac J. Manjarres --- drivers/iommu/arm-smmu.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 4dffea14e0e7..0bb354190e9a 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -3674,22 +3674,18 @@ static int __arm_smmu_domain_set_attr2(struct iommu_domain *domain, case DOMAIN_ATTR_PAGE_TABLE_FORCE_COHERENT: { int force_coherent = *((int *)data); - if (IS_ENABLED(CONFIG_QCOM_IOMMU_IO_PGTABLE_QUIRKS)) { - if (smmu_domain->smmu != NULL) { - dev_err(smmu_domain->smmu->dev, - "cannot change force coherent attribute while attached\n"); - ret = -EBUSY; - } else if (force_coherent) { - set_bit(DOMAIN_ATTR_PAGE_TABLE_FORCE_COHERENT, - smmu_domain->attributes); - ret = 0; - } else { - clear_bit(DOMAIN_ATTR_PAGE_TABLE_FORCE_COHERENT, - smmu_domain->attributes); - ret = 0; - } + if (smmu_domain->smmu != NULL) { + dev_err(smmu_domain->smmu->dev, + "cannot change force coherent attribute while attached\n"); + ret = -EBUSY; + } else if (force_coherent) { + set_bit(DOMAIN_ATTR_PAGE_TABLE_FORCE_COHERENT, + smmu_domain->attributes); + ret = 0; } else { - ret = -ENOTSUPP; + clear_bit(DOMAIN_ATTR_PAGE_TABLE_FORCE_COHERENT, + smmu_domain->attributes); + ret = 0; } break; } From f85843d3df7e95861284d79ccd40f885f041931e Mon Sep 17 00:00:00 2001 From: "Isaac J. Manjarres" Date: Tue, 7 Apr 2020 09:56:46 -0700 Subject: [PATCH 2/2] iommu/arm-smmu: Add support to disable page-table coherency There may be environments where page-table walker coherency is enabled by default, so add support to allow clients to disable it. Change-Id: I1681c680e82cabb5b132867af03f2e599bfc72e3 Signed-off-by: Isaac J. Manjarres --- drivers/iommu/arm-smmu.c | 30 ++++++++++++++++++++++++++++++ include/linux/iommu.h | 9 +++++---- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 0bb354190e9a..617eb9080a7e 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -214,6 +214,9 @@ static bool is_iommu_pt_coherent(struct arm_smmu_domain *smmu_domain) if (test_bit(DOMAIN_ATTR_PAGE_TABLE_FORCE_COHERENT, smmu_domain->attributes)) return true; + else if (test_bit(DOMAIN_ATTR_PAGE_TABLE_FORCE_NON_COHERENT, + smmu_domain->attributes)) + return false; else if (smmu_domain->smmu && smmu_domain->smmu->dev) return dev_is_dma_coherent(smmu_domain->smmu->dev); else @@ -2673,6 +2676,9 @@ static int arm_smmu_setup_default_domain(struct device *dev, if (!strcmp(str, "coherent")) __arm_smmu_domain_set_attr(domain, DOMAIN_ATTR_PAGE_TABLE_FORCE_COHERENT, &attr); + else if (!strcmp(str, "non-coherent")) + __arm_smmu_domain_set_attr(domain, + DOMAIN_ATTR_PAGE_TABLE_FORCE_NON_COHERENT, &attr); else if (!strcmp(str, "LLC")) __arm_smmu_domain_set_attr(domain, DOMAIN_ATTR_USE_UPSTREAM_HINT, &attr); @@ -3449,6 +3455,12 @@ static int arm_smmu_domain_get_attr(struct iommu_domain *domain, smmu_domain->attributes); ret = 0; break; + case DOMAIN_ATTR_PAGE_TABLE_FORCE_NON_COHERENT: + *((int *)data) = + test_bit(DOMAIN_ATTR_PAGE_TABLE_FORCE_NON_COHERENT, + smmu_domain->attributes); + ret = 0; + break; case DOMAIN_ATTR_CB_STALL_DISABLE: *((int *)data) = test_bit(DOMAIN_ATTR_CB_STALL_DISABLE, smmu_domain->attributes); @@ -3689,6 +3701,24 @@ static int __arm_smmu_domain_set_attr2(struct iommu_domain *domain, } break; } + case DOMAIN_ATTR_PAGE_TABLE_FORCE_NON_COHERENT: { + int force_non_coherent = *((int *)data); + + if (smmu_domain->smmu != NULL) { + dev_err(smmu_domain->smmu->dev, + "cannot change force non-coherent attribute while attached\n"); + ret = -EBUSY; + } else if (force_non_coherent) { + set_bit(DOMAIN_ATTR_PAGE_TABLE_FORCE_NON_COHERENT, + smmu_domain->attributes); + ret = 0; + } else { + clear_bit(DOMAIN_ATTR_PAGE_TABLE_FORCE_NON_COHERENT, + smmu_domain->attributes); + ret = 0; + } + break; + } default: ret = -ENODEV; } diff --git a/include/linux/iommu.h b/include/linux/iommu.h index d11f0c03d2a9..1a3216244cb9 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -185,10 +185,11 @@ enum iommu_attr { #define DOMAIN_ATTR_EARLY_MAP (EXTENDED_ATTR_BASE + 13) #define DOMAIN_ATTR_PAGE_TABLE_IS_COHERENT (EXTENDED_ATTR_BASE + 14) #define DOMAIN_ATTR_PAGE_TABLE_FORCE_COHERENT (EXTENDED_ATTR_BASE + 15) -#define DOMAIN_ATTR_CB_STALL_DISABLE (EXTENDED_ATTR_BASE + 16) -#define DOMAIN_ATTR_USE_LLC_NWA (EXTENDED_ATTR_BASE + 17) -#define DOMAIN_ATTR_NO_CFRE (EXTENDED_ATTR_BASE + 18) -#define DOMAIN_ATTR_EXTENDED_MAX (EXTENDED_ATTR_BASE + 19) +#define DOMAIN_ATTR_PAGE_TABLE_FORCE_NON_COHERENT (EXTENDED_ATTR_BASE + 16) +#define DOMAIN_ATTR_CB_STALL_DISABLE (EXTENDED_ATTR_BASE + 17) +#define DOMAIN_ATTR_USE_LLC_NWA (EXTENDED_ATTR_BASE + 18) +#define DOMAIN_ATTR_NO_CFRE (EXTENDED_ATTR_BASE + 19) +#define DOMAIN_ATTR_EXTENDED_MAX (EXTENDED_ATTR_BASE + 20) /* These are the possible reserved region types */ enum iommu_resv_type {