Message ID | 20220615161224.6923-4-yf.wang@mediatek.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | iommu/mediatek: TTBR up to 35bit support | expand |
On 2022-06-15 17:12, yf.wang--- via iommu wrote: > From: Yunfei Wang <yf.wang@mediatek.com> > > Single memory zone feature will remove ZONE_DMA32 and ZONE_DMA. So add > the quirk IO_PGTABLE_QUIRK_ARM_MTK_TTBR_EXT to let level 1 and level 2 > pgtable support at most 35bit PA. I'm not sure how this works in practice, given that you don't seem to be setting the IOMMU's own DMA masks to more than 32 bits, so the DMA mapping in io-pgtable is going to fail if you ever do actually allocate a pagetable page above 4GB :/ > Signed-off-by: Ning Li <ning.li@mediatek.com> > Signed-off-by: Yunfei Wang <yf.wang@mediatek.com> > --- > drivers/iommu/mtk_iommu.c | 14 +++++++++----- > 1 file changed, 9 insertions(+), 5 deletions(-) > > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c > index 3d62399e8865..4dbc33758711 100644 > --- a/drivers/iommu/mtk_iommu.c > +++ b/drivers/iommu/mtk_iommu.c > @@ -138,6 +138,7 @@ > /* PM and clock always on. e.g. infra iommu */ > #define PM_CLK_AO BIT(15) > #define IFA_IOMMU_PCIE_SUPPORT BIT(16) > +#define PGTABLE_PA_35_EN BIT(17) > > #define MTK_IOMMU_HAS_FLAG_MASK(pdata, _x, mask) \ > ((((pdata)->flags) & (mask)) == (_x)) > @@ -240,6 +241,7 @@ struct mtk_iommu_data { > struct mtk_iommu_domain { > struct io_pgtable_cfg cfg; > struct io_pgtable_ops *iop; > + u32 ttbr; > > struct mtk_iommu_bank_data *bank; > struct iommu_domain domain; > @@ -596,6 +598,9 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom, > .iommu_dev = data->dev, > }; > > + if (MTK_IOMMU_HAS_FLAG(data->plat_data, PGTABLE_PA_35_EN)) > + dom->cfg.quirks |= IO_PGTABLE_QUIRK_ARM_MTK_TTBR_EXT; > + > if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_4GB_MODE)) > dom->cfg.oas = data->enable_4GB ? 33 : 32; > else > @@ -684,8 +689,8 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, > goto err_unlock; > } > bank->m4u_dom = dom; > - writel(dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, > - bank->base + REG_MMU_PT_BASE_ADDR); > + bank->m4u_dom->ttbr = MTK_IOMMU_ADDR(dom->cfg.arm_v7s_cfg.ttbr); > + writel(bank->m4u_dom->ttbr, data->base + REG_MMU_PT_BASE_ADDR); To add to my comment on patch #1, having to make this change here further indicates that you're using it the wrong way. Thanks, Robin. > > pm_runtime_put(m4udev); > } > @@ -1366,8 +1371,7 @@ static int __maybe_unused mtk_iommu_runtime_resume(struct device *dev) > writel_relaxed(reg->int_control[i], base + REG_MMU_INT_CONTROL0); > writel_relaxed(reg->int_main_control[i], base + REG_MMU_INT_MAIN_CONTROL); > writel_relaxed(reg->ivrp_paddr[i], base + REG_MMU_IVRP_PADDR); > - writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, > - base + REG_MMU_PT_BASE_ADDR); > + writel(m4u_dom->ttbr, base + REG_MMU_PT_BASE_ADDR); > } while (++i < data->plat_data->banks_num); > > /* > @@ -1401,7 +1405,7 @@ static const struct mtk_iommu_plat_data mt2712_data = { > static const struct mtk_iommu_plat_data mt6779_data = { > .m4u_plat = M4U_MT6779, > .flags = HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | WR_THROT_EN | > - MTK_IOMMU_TYPE_MM, > + MTK_IOMMU_TYPE_MM | PGTABLE_PA_35_EN, > .inv_sel_reg = REG_MMU_INV_SEL_GEN2, > .banks_num = 1, > .banks_enable = {true},
Hi, Thank you for the patch! Yet something to improve: [auto build test ERROR on joro-iommu/next] [also build test ERROR on linus/master v5.19-rc2 next-20220615] [cannot apply to arm-perf/for-next/perf] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/intel-lab-lkp/linux/commits/yf-wang-mediatek-com/iommu-io-pgtable-arm-v7s-Add-a-quirk-to-allow-pgtable-PA-up-to-35bit/20220616-011227 base: https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git next config: arc-allyesconfig (https://download.01.org/0day-ci/archive/20220616/202206161233.WDjdWJGb-lkp@intel.com/config) compiler: arceb-elf-gcc (GCC) 11.3.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/intel-lab-lkp/linux/commit/0032fcce9c1ab50caec1ef5dd4089a8a61fcf15c git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review yf-wang-mediatek-com/iommu-io-pgtable-arm-v7s-Add-a-quirk-to-allow-pgtable-PA-up-to-35bit/20220616-011227 git checkout 0032fcce9c1ab50caec1ef5dd4089a8a61fcf15c # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.3.0 make.cross W=1 O=build_dir ARCH=arc SHELL=/bin/bash If you fix the issue, kindly add following tag where applicable Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): In file included from include/linux/scatterlist.h:9, from include/linux/dma-mapping.h:10, from include/linux/dma-direct.h:9, from drivers/iommu/mtk_iommu.c:11: drivers/iommu/mtk_iommu.c: In function 'mtk_iommu_attach_device': >> drivers/iommu/mtk_iommu.c:693:49: error: 'struct mtk_iommu_data' has no member named 'base' 693 | writel(bank->m4u_dom->ttbr, data->base + REG_MMU_PT_BASE_ADDR); | ^~ arch/arc/include/asm/io.h:231:75: note: in definition of macro 'writel_relaxed' 231 | #define writel_relaxed(v,c) __raw_writel((__force u32) cpu_to_le32(v),c) | ^ drivers/iommu/mtk_iommu.c:693:17: note: in expansion of macro 'writel' 693 | writel(bank->m4u_dom->ttbr, data->base + REG_MMU_PT_BASE_ADDR); | ^~~~~~ vim +693 drivers/iommu/mtk_iommu.c 646 647 static int mtk_iommu_attach_device(struct iommu_domain *domain, 648 struct device *dev) 649 { 650 struct mtk_iommu_data *data = dev_iommu_priv_get(dev), *frstdata; 651 struct mtk_iommu_domain *dom = to_mtk_domain(domain); 652 struct list_head *hw_list = data->hw_list; 653 struct device *m4udev = data->dev; 654 struct mtk_iommu_bank_data *bank; 655 unsigned int bankid; 656 int ret, region_id; 657 658 region_id = mtk_iommu_get_iova_region_id(dev, data->plat_data); 659 if (region_id < 0) 660 return region_id; 661 662 bankid = mtk_iommu_get_bank_id(dev, data->plat_data); 663 mutex_lock(&dom->mutex); 664 if (!dom->bank) { 665 /* Data is in the frstdata in sharing pgtable case. */ 666 frstdata = mtk_iommu_get_frst_data(hw_list); 667 668 ret = mtk_iommu_domain_finalise(dom, frstdata, region_id); 669 if (ret) { 670 mutex_unlock(&dom->mutex); 671 return -ENODEV; 672 } 673 dom->bank = &data->bank[bankid]; 674 } 675 mutex_unlock(&dom->mutex); 676 677 mutex_lock(&data->mutex); 678 bank = &data->bank[bankid]; 679 if (!bank->m4u_dom) { /* Initialize the M4U HW for each a BANK */ 680 ret = pm_runtime_resume_and_get(m4udev); 681 if (ret < 0) { 682 dev_err(m4udev, "pm get fail(%d) in attach.\n", ret); 683 goto err_unlock; 684 } 685 686 ret = mtk_iommu_hw_init(data, bankid); 687 if (ret) { 688 pm_runtime_put(m4udev); 689 goto err_unlock; 690 } 691 bank->m4u_dom = dom; 692 bank->m4u_dom->ttbr = MTK_IOMMU_ADDR(dom->cfg.arm_v7s_cfg.ttbr); > 693 writel(bank->m4u_dom->ttbr, data->base + REG_MMU_PT_BASE_ADDR); 694 695 pm_runtime_put(m4udev); 696 } 697 mutex_unlock(&data->mutex); 698 699 return mtk_iommu_config(data, dev, true, region_id); 700 701 err_unlock: 702 mutex_unlock(&data->mutex); 703 return ret; 704 } 705
On Wed, 2022-06-15 at 18:25 +0100, Robin Murphy wrote: > On 2022-06-15 17:12, yf.wang--- via iommu wrote: > > From: Yunfei Wang <yf.wang@mediatek.com> > > > > Single memory zone feature will remove ZONE_DMA32 and ZONE_DMA. So > > add > > the quirk IO_PGTABLE_QUIRK_ARM_MTK_TTBR_EXT to let level 1 and > > level 2 > > pgtable support at most 35bit PA. > > I'm not sure how this works in practice, given that you don't seem to > be > setting the IOMMU's own DMA masks to more than 32 bits, so the DMA > mapping in io-pgtable is going to fail if you ever do actually > allocate > a pagetable page above 4GB :/ > Hi Robin, About DMA masks, the master device has set dma mask, when iommu do dma map, it will check the dam_mask of the master dev to determine which range the address of the iova alloc is in. Add the quirk ARM_MTK_TTBR_EXT to let pgtable support larger phys memory. Do actually test work fine, example: pgtable phys address:0x12054006a, encoded to 32 bits ttbr:0x20540001 > > Signed-off-by: Ning Li <ning.li@mediatek.com> > > Signed-off-by: Yunfei Wang <yf.wang@mediatek.com> > > --- > > drivers/iommu/mtk_iommu.c | 14 +++++++++----- > > 1 file changed, 9 insertions(+), 5 deletions(-) > > > > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c > > index 3d62399e8865..4dbc33758711 100644 > > --- a/drivers/iommu/mtk_iommu.c > > +++ b/drivers/iommu/mtk_iommu.c > > @@ -138,6 +138,7 @@ > > /* PM and clock always on. e.g. infra iommu */ > > #define PM_CLK_AO BIT(15) > > #define IFA_IOMMU_PCIE_SUPPORT BIT(16) > > +#define PGTABLE_PA_35_EN BIT(17) > > > > #define MTK_IOMMU_HAS_FLAG_MASK(pdata, _x, mask) \ > > ((((pdata)->flags) & (mask)) == (_x)) > > @@ -240,6 +241,7 @@ struct mtk_iommu_data { > > struct mtk_iommu_domain { > > struct io_pgtable_cfg cfg; > > struct io_pgtable_ops *iop; > > + u32 ttbr; > > > > struct mtk_iommu_bank_data *bank; > > struct iommu_domain domain; > > @@ -596,6 +598,9 @@ static int mtk_iommu_domain_finalise(struct > > mtk_iommu_domain *dom, > > .iommu_dev = data->dev, > > }; > > > > + if (MTK_IOMMU_HAS_FLAG(data->plat_data, PGTABLE_PA_35_EN)) > > + dom->cfg.quirks |= IO_PGTABLE_QUIRK_ARM_MTK_TTBR_EXT; > > + > > if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_4GB_MODE)) > > dom->cfg.oas = data->enable_4GB ? 33 : 32; > > else > > @@ -684,8 +689,8 @@ static int mtk_iommu_attach_device(struct > > iommu_domain *domain, > > goto err_unlock; > > } > > bank->m4u_dom = dom; > > - writel(dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, > > - bank->base + REG_MMU_PT_BASE_ADDR); > > + bank->m4u_dom->ttbr = MTK_IOMMU_ADDR(dom- > > >cfg.arm_v7s_cfg.ttbr); > > + writel(bank->m4u_dom->ttbr, data->base + > > REG_MMU_PT_BASE_ADDR); > > To add to my comment on patch #1, having to make this change here > further indicates that you're using it the wrong way. > > Thanks, > Robin. > Hi Robin, According to your Path#1's suggestion, next version will keep ttbr to encoded 32 bits, then will don't need to modify it. Thanks, Yunfei.
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 3d62399e8865..4dbc33758711 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -138,6 +138,7 @@ /* PM and clock always on. e.g. infra iommu */ #define PM_CLK_AO BIT(15) #define IFA_IOMMU_PCIE_SUPPORT BIT(16) +#define PGTABLE_PA_35_EN BIT(17) #define MTK_IOMMU_HAS_FLAG_MASK(pdata, _x, mask) \ ((((pdata)->flags) & (mask)) == (_x)) @@ -240,6 +241,7 @@ struct mtk_iommu_data { struct mtk_iommu_domain { struct io_pgtable_cfg cfg; struct io_pgtable_ops *iop; + u32 ttbr; struct mtk_iommu_bank_data *bank; struct iommu_domain domain; @@ -596,6 +598,9 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom, .iommu_dev = data->dev, }; + if (MTK_IOMMU_HAS_FLAG(data->plat_data, PGTABLE_PA_35_EN)) + dom->cfg.quirks |= IO_PGTABLE_QUIRK_ARM_MTK_TTBR_EXT; + if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_4GB_MODE)) dom->cfg.oas = data->enable_4GB ? 33 : 32; else @@ -684,8 +689,8 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, goto err_unlock; } bank->m4u_dom = dom; - writel(dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, - bank->base + REG_MMU_PT_BASE_ADDR); + bank->m4u_dom->ttbr = MTK_IOMMU_ADDR(dom->cfg.arm_v7s_cfg.ttbr); + writel(bank->m4u_dom->ttbr, data->base + REG_MMU_PT_BASE_ADDR); pm_runtime_put(m4udev); } @@ -1366,8 +1371,7 @@ static int __maybe_unused mtk_iommu_runtime_resume(struct device *dev) writel_relaxed(reg->int_control[i], base + REG_MMU_INT_CONTROL0); writel_relaxed(reg->int_main_control[i], base + REG_MMU_INT_MAIN_CONTROL); writel_relaxed(reg->ivrp_paddr[i], base + REG_MMU_IVRP_PADDR); - writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, - base + REG_MMU_PT_BASE_ADDR); + writel(m4u_dom->ttbr, base + REG_MMU_PT_BASE_ADDR); } while (++i < data->plat_data->banks_num); /* @@ -1401,7 +1405,7 @@ static const struct mtk_iommu_plat_data mt2712_data = { static const struct mtk_iommu_plat_data mt6779_data = { .m4u_plat = M4U_MT6779, .flags = HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | WR_THROT_EN | - MTK_IOMMU_TYPE_MM, + MTK_IOMMU_TYPE_MM | PGTABLE_PA_35_EN, .inv_sel_reg = REG_MMU_INV_SEL_GEN2, .banks_num = 1, .banks_enable = {true},