diff mbox

[v2,7/8] iommu/mediatek: Enlarge the validate PA range for 4GB mode

Message ID 1503313221-26453-8-git-send-email-yong.wu@mediatek.com (mailing list archive)
State New, archived
Headers show

Commit Message

Yong Wu (吴勇) Aug. 21, 2017, 11 a.m. UTC
This patch is for 4GB mode, mainly for 4 issues:
1) Fix a 4GB bug:
   if the dram base is 0x4000_0000, the dram size is 0xc000_0000.
   then the code just meet a corner case because max_pfn is
   0x10_0000.
   data->enable_4GB = !!(max_pfn > (0xffffffffUL >> PAGE_SHIFT));
   It's true at the case above. That is unexpected.
2) In mt2712, there is a new register for the 4GB PA range(0x118)
   we should enlarge the max PA range, or the HW will report
   error.
   The dram range is from 0x1_0000_0000 to 0x1_ffff_ffff in the 4GB
   mode, we cut out the bit[32:30] of the SA(Start address) and
   EA(End address) into this REG_MMU_VLD_PA_RNG(0x118).
3) In mt2712, the register(0x13c) is extended for 4GB mode.
   bit[7:6] indicate the valid PA[32:33]. Thus, we don't mask the
   value and print it directly for debug.
4) if 4GB is enabled, the dram PA range is from 0x1_0000_0000 to
   0x1_ffff_ffff. Thus, the PA from iova_to_pa should also '|' BIT(32)

Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
Signed-off-by: Yong Wu <yong.wu@mediatek.com>
---
 drivers/iommu/mtk_iommu.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

Comments

kernel test robot Aug. 23, 2017, 5:55 p.m. UTC | #1
Hi Yong,

[auto build test ERROR on iommu/next]
[also build test ERROR on next-20170823]
[cannot apply to v4.13-rc6]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Yong-Wu/MT2712-IOMMU-SUPPORT/20170824-074750
base:   https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git next
config: arm64-allmodconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm64 

All errors (new ones prefixed by >>):

   drivers/iommu/mtk_iommu.c: In function 'mtk_iommu_hw_init':
>> drivers/iommu/mtk_iommu.c:536:30: error: 'const struct mtk_iommu_data' has no member named 'm4u_type'; did you mean 'm4u_dom'?
     if (data->enable_4GB && data->m4u_type != M4U_MT8173) {
                                 ^~

vim +536 drivers/iommu/mtk_iommu.c

   500	
   501	static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
   502	{
   503		u32 regval;
   504		int ret;
   505	
   506		ret = clk_prepare_enable(data->bclk);
   507		if (ret) {
   508			dev_err(data->dev, "Failed to enable iommu bclk(%d)\n", ret);
   509			return ret;
   510		}
   511	
   512		regval = F_MMU_TF_PROTECT_SEL(2, data);
   513		if (data->m4u_plat == M4U_MT8173)
   514			regval |= F_MMU_PREFETCH_RT_REPLACE_MOD;
   515		writel_relaxed(regval, data->base + REG_MMU_CTRL_REG);
   516	
   517		regval = F_L2_MULIT_HIT_EN |
   518			F_TABLE_WALK_FAULT_INT_EN |
   519			F_PREETCH_FIFO_OVERFLOW_INT_EN |
   520			F_MISS_FIFO_OVERFLOW_INT_EN |
   521			F_PREFETCH_FIFO_ERR_INT_EN |
   522			F_MISS_FIFO_ERR_INT_EN;
   523		writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL0);
   524	
   525		regval = F_INT_TRANSLATION_FAULT |
   526			F_INT_MAIN_MULTI_HIT_FAULT |
   527			F_INT_INVALID_PA_FAULT |
   528			F_INT_ENTRY_REPLACEMENT_FAULT |
   529			F_INT_TLB_MISS_FAULT |
   530			F_INT_MISS_TRANSACTION_FIFO_FAULT |
   531			F_INT_PRETETCH_TRANSATION_FIFO_FAULT;
   532		writel_relaxed(regval, data->base + REG_MMU_INT_MAIN_CONTROL);
   533	
   534		writel_relaxed(F_MMU_IVRP_PA_SET(data->protect_base, data->enable_4GB),
   535			       data->base + REG_MMU_IVRP_PADDR);
 > 536		if (data->enable_4GB && data->m4u_type != M4U_MT8173) {
   537			/*
   538			 * If 4GB mode is enabled, the validate PA range is from
   539			 * 0x1_0000_0000 to 0x1_ffff_ffff. here record bit[32:30].
   540			 */
   541			regval = F_MMU_VLD_PA_RNG(7, 4);
   542			writel_relaxed(regval, data->base + REG_MMU_VLD_PA_RNG);
   543		}
   544		writel_relaxed(0, data->base + REG_MMU_DCM_DIS);
   545	
   546		/* It's MISC control register whose default value is ok except mt8173.*/
   547		if (data->m4u_plat == M4U_MT8173)
   548			writel_relaxed(0, data->base + REG_MMU_STANDARD_AXI_MODE);
   549	
   550		if (devm_request_irq(data->dev, data->irq, mtk_iommu_isr, 0,
   551				     dev_name(data->dev), (void *)data)) {
   552			writel_relaxed(0, data->base + REG_MMU_PT_BASE_ADDR);
   553			clk_disable_unprepare(data->bclk);
   554			dev_err(data->dev, "Failed @ IRQ-%d Request\n", data->irq);
   555			return -ENODEV;
   556		}
   557	
   558		return 0;
   559	}
   560	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
kernel test robot Aug. 24, 2017, 6:15 a.m. UTC | #2
Hi Yong,

[auto build test WARNING on iommu/next]
[also build test WARNING on next-20170823]
[cannot apply to v4.13-rc6]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Yong-Wu/MT2712-IOMMU-SUPPORT/20170824-074750
base:   https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git next
config: arm-allmodconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

All warnings (new ones prefixed by >>):

   In file included from include/linux/kernel.h:10:0,
                    from include/linux/list.h:8,
                    from include/linux/preempt.h:10,
                    from include/linux/spinlock.h:50,
                    from include/linux/mmzone.h:7,
                    from include/linux/bootmem.h:7,
                    from drivers/iommu/mtk_iommu.c:14:
   drivers/iommu/mtk_iommu.c: In function 'mtk_iommu_iova_to_phys':
   include/linux/bitops.h:6:24: warning: left shift count >= width of type [-Wshift-count-overflow]
    #define BIT(nr)   (1UL << (nr))
                           ^
>> drivers/iommu/mtk_iommu.c:407:9: note: in expansion of macro 'BIT'
      pa |= BIT(32);
            ^~~
   drivers/iommu/mtk_iommu.c: In function 'mtk_iommu_hw_init':
   drivers/iommu/mtk_iommu.c:536:30: error: 'const struct mtk_iommu_data' has no member named 'm4u_type'; did you mean 'm4u_dom'?
     if (data->enable_4GB && data->m4u_type != M4U_MT8173) {
                                 ^~
   In file included from include/linux/kernel.h:10:0,
                    from include/linux/list.h:8,
                    from include/linux/preempt.h:10,
                    from include/linux/spinlock.h:50,
                    from include/linux/mmzone.h:7,
                    from include/linux/bootmem.h:7,
                    from drivers/iommu/mtk_iommu.c:14:
   drivers/iommu/mtk_iommu.c: In function 'mtk_iommu_probe':
   include/linux/bitops.h:6:24: warning: left shift count >= width of type [-Wshift-count-overflow]
    #define BIT(nr)   (1UL << (nr))
                           ^
   drivers/iommu/mtk_iommu.c:589:35: note: in expansion of macro 'BIT'
     data->enable_4GB = !!(max_pfn > (BIT(32) >> PAGE_SHIFT));
                                      ^~~

vim +/BIT +407 drivers/iommu/mtk_iommu.c

   393	
   394	static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,
   395						  dma_addr_t iova)
   396	{
   397		struct mtk_iommu_domain *dom = to_mtk_domain(domain);
   398		struct mtk_iommu_data *data = mtk_iommu_get_m4u_data();
   399		unsigned long flags;
   400		phys_addr_t pa;
   401	
   402		spin_lock_irqsave(&dom->pgtlock, flags);
   403		pa = dom->iop->iova_to_phys(dom->iop, iova);
   404		spin_unlock_irqrestore(&dom->pgtlock, flags);
   405	
   406		if (data->enable_4GB)
 > 407			pa |= BIT(32);
   408	
   409		return pa;
   410	}
   411	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
diff mbox

Patch

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index e21de86..4f233e1 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -61,6 +61,8 @@ 
 
 #define REG_MMU_IVRP_PADDR			0x114
 #define F_MMU_IVRP_PA_SET(pa, ext)		(((pa) >> 1) | ((!!(ext)) << 31))
+#define REG_MMU_VLD_PA_RNG			0x118
+#define F_MMU_VLD_PA_RNG(EA, SA)		(((EA) << 8) | (SA))
 
 #define REG_MMU_INT_CONTROL0			0x120
 #define F_L2_MULIT_HIT_EN			BIT(0)
@@ -85,7 +87,6 @@ 
 #define REG_MMU_FAULT_ST1			0x134
 
 #define REG_MMU_FAULT_VA			0x13c
-#define F_MMU_FAULT_VA_MSK			0xfffff000
 #define F_MMU_FAULT_VA_WRITE_BIT		BIT(1)
 #define F_MMU_FAULT_VA_LAYER_BIT		BIT(0)
 
@@ -214,7 +215,6 @@  static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
 	fault_iova = readl_relaxed(data->base + REG_MMU_FAULT_VA);
 	layer = fault_iova & F_MMU_FAULT_VA_LAYER_BIT;
 	write = fault_iova & F_MMU_FAULT_VA_WRITE_BIT;
-	fault_iova &= F_MMU_FAULT_VA_MSK;
 	fault_pa = readl_relaxed(data->base + REG_MMU_INVLD_PA);
 	regval = readl_relaxed(data->base + REG_MMU_INT_ID);
 	fault_larb = F_MMU0_INT_ID_LARB_ID(regval);
@@ -395,6 +395,7 @@  static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,
 					  dma_addr_t iova)
 {
 	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
+	struct mtk_iommu_data *data = mtk_iommu_get_m4u_data();
 	unsigned long flags;
 	phys_addr_t pa;
 
@@ -402,6 +403,9 @@  static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,
 	pa = dom->iop->iova_to_phys(dom->iop, iova);
 	spin_unlock_irqrestore(&dom->pgtlock, flags);
 
+	if (data->enable_4GB)
+		pa |= BIT(32);
+
 	return pa;
 }
 
@@ -529,6 +533,14 @@  static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
 
 	writel_relaxed(F_MMU_IVRP_PA_SET(data->protect_base, data->enable_4GB),
 		       data->base + REG_MMU_IVRP_PADDR);
+	if (data->enable_4GB && data->m4u_type != M4U_MT8173) {
+		/*
+		 * If 4GB mode is enabled, the validate PA range is from
+		 * 0x1_0000_0000 to 0x1_ffff_ffff. here record bit[32:30].
+		 */
+		regval = F_MMU_VLD_PA_RNG(7, 4);
+		writel_relaxed(regval, data->base + REG_MMU_VLD_PA_RNG);
+	}
 	writel_relaxed(0, data->base + REG_MMU_DCM_DIS);
 
 	/* It's MISC control register whose default value is ok except mt8173.*/
@@ -574,7 +586,7 @@  static int mtk_iommu_probe(struct platform_device *pdev)
 	data->protect_base = ALIGN(virt_to_phys(protect), MTK_PROTECT_PA_ALIGN);
 
 	/* Whether the current dram is over 4GB */
-	data->enable_4GB = !!(max_pfn > (0xffffffffUL >> PAGE_SHIFT));
+	data->enable_4GB = !!(max_pfn > (BIT(32) >> PAGE_SHIFT));
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	data->base = devm_ioremap_resource(dev, res);