Skip to contentSkip to conversation

IOMMU: Tegra SMMU fixes

PATCH Applied Dmitry Osipenko 3 participants 10 messages Mar 6, 2019 – Apr 11, 2019

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover IOMMU: Tegra SMMU fixes

Hello,

This small series primarily fixes a bug that affects Terga30 and Terga114 platforms, it also carries two patches that improve SMMU functionality and clean up code a tad.

Dmitry Osipenko (3):
iommu/tegra-smmu: Fix invalid ASID bits on Tegra30/114 iommu/tegra-smmu: Properly release domain resources iommu/tegra-smmu: Respect IOMMU API read-write protections

 drivers/iommu/tegra-smmu.c | 41 ++++++++++++++++++++++++++++----------
 1 file changed, 31 insertions(+), 10 deletions(-)
Signature · 1 line
2.20.1
#1 lore raw

PATCH 1/3 iommu/tegra-smmu: Fix invalid ASID bits on Tegra30/114

Both Tegra30 and Tegra114 have 4 ASID's and the corresponding bitfield of the TLB_FLUSH register differs from later Tegra generations that have 128 ASID's.

In a result the PTE's are now flushed correctly from TLB and this fixes problems with graphics (randomly failing tests) on Tegra30.

---
 drivers/iommu/tegra-smmu.c | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)
drivers/iommu/tegra-smmu.c +18 -7
index 5182c7d6171e..8d30653cd13a 100644
@@ -102,7 +102,6 @@ static inline u32 smmu_readl(struct tegra_smmu *smmu, unsigned long offset)
 #define  SMMU_TLB_FLUSH_VA_MATCH_ALL     (0 << 0)
 #define  SMMU_TLB_FLUSH_VA_MATCH_SECTION (2 << 0)
 #define  SMMU_TLB_FLUSH_VA_MATCH_GROUP   (3 << 0)
-#define  SMMU_TLB_FLUSH_ASID(x)          (((x) & 0x7f) << 24)
 #define  SMMU_TLB_FLUSH_VA_SECTION(addr) ((((addr) & 0xffc00000) >> 12) | \
 					  SMMU_TLB_FLUSH_VA_MATCH_SECTION)
 #define  SMMU_TLB_FLUSH_VA_GROUP(addr)   ((((addr) & 0xffffc000) >> 12) | \
@@ -205,8 +204,12 @@ static inline void smmu_flush_tlb_asid(struct tegra_smmu *smmu,
 {
 	u32 value;
 
-	value = SMMU_TLB_FLUSH_ASID_MATCH | SMMU_TLB_FLUSH_ASID(asid) |
-		SMMU_TLB_FLUSH_VA_MATCH_ALL;
+	if (smmu->soc->num_asids == 4)
+		value = (asid & 0x3) << 29;
+	else
+		value = (asid & 0x7f) << 24;
+
+	value |= SMMU_TLB_FLUSH_ASID_MATCH | SMMU_TLB_FLUSH_VA_MATCH_ALL;
 	smmu_writel(smmu, value, SMMU_TLB_FLUSH);
 }
 
@@ -216,8 +219,12 @@ static inline void smmu_flush_tlb_section(struct tegra_smmu *smmu,
 {
 	u32 value;
 
-	value = SMMU_TLB_FLUSH_ASID_MATCH | SMMU_TLB_FLUSH_ASID(asid) |
-		SMMU_TLB_FLUSH_VA_SECTION(iova);
+	if (smmu->soc->num_asids == 4)
+		value = (asid & 0x3) << 29;
+	else
+		value = (asid & 0x7f) << 24;
+
+	value |= SMMU_TLB_FLUSH_ASID_MATCH | SMMU_TLB_FLUSH_VA_SECTION(iova);
 	smmu_writel(smmu, value, SMMU_TLB_FLUSH);
 }
 
@@ -227,8 +234,12 @@ static inline void smmu_flush_tlb_group(struct tegra_smmu *smmu,
 {
 	u32 value;
 
-	value = SMMU_TLB_FLUSH_ASID_MATCH | SMMU_TLB_FLUSH_ASID(asid) |
-		SMMU_TLB_FLUSH_VA_GROUP(iova);
+	if (smmu->soc->num_asids == 4)
+		value = (asid & 0x3) << 29;
+	else
+		value = (asid & 0x7f) << 24;
+
+	value |= SMMU_TLB_FLUSH_ASID_MATCH | SMMU_TLB_FLUSH_VA_GROUP(iova);
 	smmu_writel(smmu, value, SMMU_TLB_FLUSH);
 }
 
Signature · 1 line
2.20.1
Acked-by on v1 1/3
#2 lore raw

Re: [PATCH v1 1/3] iommu/tegra-smmu: Fix invalid ASID bits on Tegra30/114

Quoted 18 lines · Dmitry Osipenko

Both Tegra30 and Tegra114 have 4 ASID's and the corresponding bitfield of the TLB_FLUSH register differs from later Tegra generations that have 128 ASID's.

In a result the PTE's are now flushed correctly from TLB and this fixes problems with graphics (randomly failing tests) on Tegra30.

---
 drivers/iommu/tegra-smmu.c | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)
drivers/iommu/tegra-smmu.c +0 -0
index 5182c7d6171e..8d30653cd13a 100644

drivers/iommu/tegra-smmu.c static inline u32 smmu_readl(struct tegra_smmu *smmu, unsigned long offset) · line 105

Quoted 4 lines
drivers/iommu/tegra-smmu.c +0 -1
@@ -102,7 +102,6 @@ static inline u32 smmu_readl(struct tegra_smmu *smmu, unsigned long offset)
 #define  SMMU_TLB_FLUSH_VA_MATCH_ALL     (0 << 0)
 #define  SMMU_TLB_FLUSH_VA_MATCH_SECTION (2 << 0)
 #define  SMMU_TLB_FLUSH_VA_MATCH_GROUP   (3 << 0)
-#define  SMMU_TLB_FLUSH_ASID(x)          (((x) & 0x7f) << 24)

Given that the same operation is repeated three times below, it might have been worth to fold the conditional into the macro. That'd require the macro to take an smmu parameter, but would otherwise leave the individual instances shorter.

But either way, the fix is good, so:

#3 lore raw

Re: [PATCH v1 1/3] iommu/tegra-smmu: Fix invalid ASID bits on Tegra30/114

03.04.2019 11:41, Thierry Reding пишет:

Quoted 14 lines · Dmitry Osipenko
Quoted 13 lines

Both Tegra30 and Tegra114 have 4 ASID's and the corresponding bitfield of the TLB_FLUSH register differs from later Tegra generations that have 128 ASID's.

In a result the PTE's are now flushed correctly from TLB and this fixes problems with graphics (randomly failing tests) on Tegra30.

---
 drivers/iommu/tegra-smmu.c | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)
Quoted 14 lines

drivers/iommu/tegra-smmu.c static inline u32 smmu_readl(struct tegra_smmu *smmu, unsigned long offset) · line 105

Quoted 9 lines
drivers/iommu/tegra-smmu.c +0 -1
index 5182c7d6171e..8d30653cd13a 100644
@@ -102,7 +102,6 @@ static inline u32 smmu_readl(struct tegra_smmu *smmu, unsigned long offset)
 #define  SMMU_TLB_FLUSH_VA_MATCH_ALL     (0 << 0)
 #define  SMMU_TLB_FLUSH_VA_MATCH_SECTION (2 << 0)
 #define  SMMU_TLB_FLUSH_VA_MATCH_GROUP   (3 << 0)
-#define  SMMU_TLB_FLUSH_ASID(x)          (((x) & 0x7f) << 24)

Given that the same operation is repeated three times below, it might have been worth to fold the conditional into the macro. That'd require the macro to take an smmu parameter, but would otherwise leave the individual instances shorter.

I had that variant initially and the result felt more clumsy to me.

Quoted 4 lines

But either way, the fix is good, so:

Thanks

#4 lore raw

PATCH 2/3 iommu/tegra-smmu: Properly release domain resources

In reply to Dmitry Osipenko

Release all memory allocations associated with a released domain and emit warning if domain is in-use at the time of destruction.

---
 drivers/iommu/tegra-smmu.c | 3 +++
 1 file changed, 3 insertions(+)
drivers/iommu/tegra-smmu.c +3 -0
index 8d30653cd13a..27b1249f0773 100644
@@ -327,6 +327,9 @@ static void tegra_smmu_domain_free(struct iommu_domain *domain)
 
 	/* TODO: free page directory and page tables */
 
+	WARN_ON_ONCE(as->use_count);
+	kfree(as->count);
+	kfree(as->pts);
 	kfree(as);
 }
 
Signature · 1 line
2.20.1
#6 lore raw

PATCH 3/3 iommu/tegra-smmu: Respect IOMMU API read-write protections

In reply to Dmitry Osipenko

Set PTE read/write attributes accordingly to the the protections requested by IOMMU API.

---
 drivers/iommu/tegra-smmu.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)
drivers/iommu/tegra-smmu.c +10 -3
index 27b1249f0773..463ee08f7d3a 100644
@@ -145,8 +145,6 @@ static inline u32 smmu_readl(struct tegra_smmu *smmu, unsigned long offset)
 
 #define SMMU_PDE_ATTR		(SMMU_PDE_READABLE | SMMU_PDE_WRITABLE | \
 				 SMMU_PDE_NONSECURE)
-#define SMMU_PTE_ATTR		(SMMU_PTE_READABLE | SMMU_PTE_WRITABLE | \
-				 SMMU_PTE_NONSECURE)
 
 static unsigned int iova_pd_index(unsigned long iova)
 {
@@ -659,6 +657,7 @@ static int tegra_smmu_map(struct iommu_domain *domain, unsigned long iova,
 {
 	struct tegra_smmu_as *as = to_smmu_as(domain);
 	dma_addr_t pte_dma;
+	u32 pte_attrs;
 	u32 *pte;
 
 	pte = as_get_pte(as, iova, &pte_dma);
@@ -669,8 +668,16 @@ static int tegra_smmu_map(struct iommu_domain *domain, unsigned long iova,
 	if (*pte == 0)
 		tegra_smmu_pte_get_use(as, iova);
 
+	pte_attrs = SMMU_PTE_NONSECURE;
+
+	if (prot & IOMMU_READ)
+		pte_attrs |= SMMU_PTE_READABLE;
+
+	if (prot & IOMMU_WRITE)
+		pte_attrs |= SMMU_PTE_WRITABLE;
+
 	tegra_smmu_set_pte(as, iova, pte, pte_dma,
-			   __phys_to_pfn(paddr) | SMMU_PTE_ATTR);
+			   __phys_to_pfn(paddr) | pte_attrs);
 
 	return 0;
 }
Signature · 1 line
2.20.1
#8 lore raw
In reply to Dmitry Osipenko

07.03.2019 1:50, Dmitry Osipenko пишет:

Quoted 6 lines

Hello,

This small series primarily fixes a bug that affects Terga30 and Terga114 platforms, it also carries two patches that improve SMMU functionality and clean up code a tad.

Quoted 8 lines

Dmitry Osipenko (3):
iommu/tegra-smmu: Fix invalid ASID bits on Tegra30/114 iommu/tegra-smmu: Properly release domain resources iommu/tegra-smmu: Respect IOMMU API read-write protections

 drivers/iommu/tegra-smmu.c | 41 ++++++++++++++++++++++++++++----------
 1 file changed, 31 insertions(+), 10 deletions(-)

Joerg, could you please apply this series?

maintainer Applied
#9 lore raw
Quoted 1 line · Dmitry Osipenko

Joerg, could you please apply this series?

Applied, thanks.