aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2015-08-06 08:20:31 -0400
committerThierry Reding <treding@nvidia.com>2015-08-13 11:05:28 -0400
commit11cec15bf3fb498206ef63b1fa26c27689e02d0e (patch)
tree330bd3eff26a1915e86b5e896cdee4db2c909896
parent4080e99b8341f81c4ed1e17d8ef44d171c473a1b (diff)
iommu/tegra-smmu: Parameterize number of TLB lines
The number of TLB lines was increased from 16 on Tegra30 to 32 on Tegra114 and later. Parameterize the value so that the initial default can be set accordingly. On Tegra30, initializing the value to 32 would effectively disable the TLB and hence cause massive latencies for memory accesses translated through the SMMU. This is especially noticeable for isochronuous clients such as display, whose FIFOs would continuously underrun. Fixes: 891846516317 ("memory: Add NVIDIA Tegra memory controller support") Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r--drivers/iommu/tegra-smmu.c9
-rw-r--r--drivers/memory/tegra/tegra114.c1
-rw-r--r--drivers/memory/tegra/tegra124.c1
-rw-r--r--drivers/memory/tegra/tegra30.c1
-rw-r--r--include/soc/tegra/mc.h1
5 files changed, 11 insertions, 2 deletions
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 2f1481ad4aa5..9305964250ac 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -27,6 +27,7 @@ struct tegra_smmu {
27 const struct tegra_smmu_soc *soc; 27 const struct tegra_smmu_soc *soc;
28 28
29 unsigned long pfn_mask; 29 unsigned long pfn_mask;
30 unsigned long tlb_mask;
30 31
31 unsigned long *asids; 32 unsigned long *asids;
32 struct mutex lock; 33 struct mutex lock;
@@ -70,7 +71,8 @@ static inline u32 smmu_readl(struct tegra_smmu *smmu, unsigned long offset)
70#define SMMU_TLB_CONFIG 0x14 71#define SMMU_TLB_CONFIG 0x14
71#define SMMU_TLB_CONFIG_HIT_UNDER_MISS (1 << 29) 72#define SMMU_TLB_CONFIG_HIT_UNDER_MISS (1 << 29)
72#define SMMU_TLB_CONFIG_ROUND_ROBIN_ARBITRATION (1 << 28) 73#define SMMU_TLB_CONFIG_ROUND_ROBIN_ARBITRATION (1 << 28)
73#define SMMU_TLB_CONFIG_ACTIVE_LINES(x) ((x) & 0x3f) 74#define SMMU_TLB_CONFIG_ACTIVE_LINES(smmu) \
75 ((smmu)->soc->num_tlb_lines & (smmu)->tlb_mask)
74 76
75#define SMMU_PTC_CONFIG 0x18 77#define SMMU_PTC_CONFIG 0x18
76#define SMMU_PTC_CONFIG_ENABLE (1 << 29) 78#define SMMU_PTC_CONFIG_ENABLE (1 << 29)
@@ -901,6 +903,9 @@ struct tegra_smmu *tegra_smmu_probe(struct device *dev,
901 smmu->pfn_mask = BIT_MASK(mc->soc->num_address_bits - PAGE_SHIFT) - 1; 903 smmu->pfn_mask = BIT_MASK(mc->soc->num_address_bits - PAGE_SHIFT) - 1;
902 dev_dbg(dev, "address bits: %u, PFN mask: %#lx\n", 904 dev_dbg(dev, "address bits: %u, PFN mask: %#lx\n",
903 mc->soc->num_address_bits, smmu->pfn_mask); 905 mc->soc->num_address_bits, smmu->pfn_mask);
906 smmu->tlb_mask = (smmu->soc->num_tlb_lines << 1) - 1;
907 dev_dbg(dev, "TLB lines: %u, mask: %#lx\n", smmu->soc->num_tlb_lines,
908 smmu->tlb_mask);
904 909
905 value = SMMU_PTC_CONFIG_ENABLE | SMMU_PTC_CONFIG_INDEX_MAP(0x3f); 910 value = SMMU_PTC_CONFIG_ENABLE | SMMU_PTC_CONFIG_INDEX_MAP(0x3f);
906 911
@@ -910,7 +915,7 @@ struct tegra_smmu *tegra_smmu_probe(struct device *dev,
910 smmu_writel(smmu, value, SMMU_PTC_CONFIG); 915 smmu_writel(smmu, value, SMMU_PTC_CONFIG);
911 916
912 value = SMMU_TLB_CONFIG_HIT_UNDER_MISS | 917 value = SMMU_TLB_CONFIG_HIT_UNDER_MISS |
913 SMMU_TLB_CONFIG_ACTIVE_LINES(0x20); 918 SMMU_TLB_CONFIG_ACTIVE_LINES(smmu);
914 919
915 if (soc->supports_round_robin_arbitration) 920 if (soc->supports_round_robin_arbitration)
916 value |= SMMU_TLB_CONFIG_ROUND_ROBIN_ARBITRATION; 921 value |= SMMU_TLB_CONFIG_ROUND_ROBIN_ARBITRATION;
diff --git a/drivers/memory/tegra/tegra114.c b/drivers/memory/tegra/tegra114.c
index 7122f39be9cc..8053f70dbfd1 100644
--- a/drivers/memory/tegra/tegra114.c
+++ b/drivers/memory/tegra/tegra114.c
@@ -919,6 +919,7 @@ static const struct tegra_smmu_soc tegra114_smmu_soc = {
919 .num_swgroups = ARRAY_SIZE(tegra114_swgroups), 919 .num_swgroups = ARRAY_SIZE(tegra114_swgroups),
920 .supports_round_robin_arbitration = false, 920 .supports_round_robin_arbitration = false,
921 .supports_request_limit = false, 921 .supports_request_limit = false,
922 .num_tlb_lines = 32,
922 .num_asids = 4, 923 .num_asids = 4,
923}; 924};
924 925
diff --git a/drivers/memory/tegra/tegra124.c b/drivers/memory/tegra/tegra124.c
index ebda63283853..7d734befe0ed 100644
--- a/drivers/memory/tegra/tegra124.c
+++ b/drivers/memory/tegra/tegra124.c
@@ -1029,6 +1029,7 @@ static const struct tegra_smmu_soc tegra132_smmu_soc = {
1029 .num_swgroups = ARRAY_SIZE(tegra124_swgroups), 1029 .num_swgroups = ARRAY_SIZE(tegra124_swgroups),
1030 .supports_round_robin_arbitration = true, 1030 .supports_round_robin_arbitration = true,
1031 .supports_request_limit = true, 1031 .supports_request_limit = true,
1032 .num_tlb_lines = 32,
1032 .num_asids = 128, 1033 .num_asids = 128,
1033}; 1034};
1034 1035
diff --git a/drivers/memory/tegra/tegra30.c b/drivers/memory/tegra/tegra30.c
index 3cb30b69d95b..7e0694d80edb 100644
--- a/drivers/memory/tegra/tegra30.c
+++ b/drivers/memory/tegra/tegra30.c
@@ -941,6 +941,7 @@ static const struct tegra_smmu_soc tegra30_smmu_soc = {
941 .num_swgroups = ARRAY_SIZE(tegra30_swgroups), 941 .num_swgroups = ARRAY_SIZE(tegra30_swgroups),
942 .supports_round_robin_arbitration = false, 942 .supports_round_robin_arbitration = false,
943 .supports_request_limit = false, 943 .supports_request_limit = false,
944 .num_tlb_lines = 16,
944 .num_asids = 4, 945 .num_asids = 4,
945}; 946};
946 947
diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h
index d6c3190ec852..8cb3a7ecd6f8 100644
--- a/include/soc/tegra/mc.h
+++ b/include/soc/tegra/mc.h
@@ -61,6 +61,7 @@ struct tegra_smmu_soc {
61 bool supports_round_robin_arbitration; 61 bool supports_round_robin_arbitration;
62 bool supports_request_limit; 62 bool supports_request_limit;
63 63
64 unsigned int num_tlb_lines;
64 unsigned int num_asids; 65 unsigned int num_asids;
65}; 66};
66 67