Re: [PATCH V3 2/4] ARM: dts: rockchip: rk322x add iommu nodes
Am Montag, 24. Juli 2017, 10:32:08 CEST schrieb Simon Xue: > Add VPU/VDEC/VOP/IEP iommu nodes > > Signed-off-by: Simon Xueapplied for 4.14 Thanks Heiko ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH V3 4/4] ARM64: dts: rockchip: rk3399 add iommu nodes
Am Montag, 24. Juli 2017, 10:32:10 CEST schrieb Simon Xue: > Add VPU/VDEC/IEP/VOPL/VOPB/ISP0/ISP1 iommu nodes > > Signed-off-by: Simon Xueapplied for 4.14 (after adapting the subject a bit, dropping the vop-mmus added via another patch) Thanks Heiko ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v2 1/8] dt-bindings: mediatek: Add binding for mt2712 IOMMU and SMI
On Mon, Aug 21, 2017 at 07:00:14PM +0800, Yong Wu wrote: > This patch adds decriptions for mt2712 IOMMU and SMI. > > In order to balance the bandwidth, mt2712 has two M4Us, two > smi-commons, 10 smi-larbs. and mt2712 is also MTK IOMMU gen2 which > uses ARM Short-Descriptor translation table format. > > The mt2712 M4U-SMI HW diagram is as below: > > EMI > | > > | | > M4U0 M4U1 > | | > smi-common0smi-common1 > | | > - > | | | | | | || | | > | | | | | | || | | > larb0 larb1 larb2 larb3 larb6larb4larb5larb7 larb8 larb9 > disp0 vdec cam venc jpg mdp1/disp1 mdp2/disp2 mdp3 vdo/nr tvd > > All the connections are HW fixed, SW can NOT adjust it. > > Signed-off-by: Yong Wu> --- > Hi Rob, > Comparing with the v1, I add larb8 and larb9 in this version. > So I don't add your ACK here. Thanks for the explanation. That's minor enough you could have kept it. Acked-by: Rob Herring > --- > .../devicetree/bindings/iommu/mediatek,iommu.txt | 6 +- > .../memory-controllers/mediatek,smi-common.txt | 6 +- > .../memory-controllers/mediatek,smi-larb.txt | 5 +- > include/dt-bindings/memory/mt2712-larb-port.h | 102 > + > 4 files changed, 113 insertions(+), 6 deletions(-) > create mode 100644 include/dt-bindings/memory/mt2712-larb-port.h ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH V3 3/4] ARM64: dts: rockchip: rk3368 add iommu nodes
Am Montag, 24. Juli 2017, 10:32:09 CEST schrieb Simon Xue: > Add IEP/ISP/VOP/HEVC/VPU iommu nodes > > Signed-off-by: Simon Xueapplied for 4.14 (after adapting the subject a bit) Thanks Heiko ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH V3 1/4] ARM64: dts: rockchip: rk3328 add iommu nodes
Am Montag, 24. Juli 2017, 10:32:07 CEST schrieb Simon Xue: > Add H265e/VEPU/VPU/VDEC/VOP iommu nodes > > Signed-off-by: Simon Xueapplied for 4.14 (after adapting the subject a bit) Thanks Heiko ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 1/8] dt-bindings: mediatek: Add binding for mt2712 IOMMU and SMI
This patch adds decriptions for mt2712 IOMMU and SMI. In order to balance the bandwidth, mt2712 has two M4Us, two smi-commons, 10 smi-larbs. and mt2712 is also MTK IOMMU gen2 which uses ARM Short-Descriptor translation table format. The mt2712 M4U-SMI HW diagram is as below: EMI | | | M4U0 M4U1 | | smi-common0smi-common1 | | - | | | | | | || | | | | | | | | || | | larb0 larb1 larb2 larb3 larb6larb4larb5larb7 larb8 larb9 disp0 vdec cam venc jpg mdp1/disp1 mdp2/disp2 mdp3 vdo/nr tvd All the connections are HW fixed, SW can NOT adjust it. Signed-off-by: Yong Wu--- Hi Rob, Comparing with the v1, I add larb8 and larb9 in this version. So I don't add your ACK here. --- .../devicetree/bindings/iommu/mediatek,iommu.txt | 6 +- .../memory-controllers/mediatek,smi-common.txt | 6 +- .../memory-controllers/mediatek,smi-larb.txt | 5 +- include/dt-bindings/memory/mt2712-larb-port.h | 102 + 4 files changed, 113 insertions(+), 6 deletions(-) create mode 100644 include/dt-bindings/memory/mt2712-larb-port.h diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt b/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt index 53c20ca..df5db73 100644 --- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt +++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt @@ -40,6 +40,7 @@ video decode local arbiter, all these ports are according to the video HW. Required properties: - compatible : must be one of the following string: "mediatek,mt2701-m4u" for mt2701 which uses generation one m4u HW. + "mediatek,mt2712-m4u" for mt2712 which uses generation two m4u HW. "mediatek,mt8173-m4u" for mt8173 which uses generation two m4u HW. - reg : m4u register base and size. - interrupts : the interrupt of m4u. @@ -50,8 +51,9 @@ Required properties: according to the local arbiter index, like larb0, larb1, larb2... - iommu-cells : must be 1. This is the mtk_m4u_id according to the HW. Specifies the mtk_m4u_id as defined in - dt-binding/memory/mt2701-larb-port.h for mt2701 and - dt-binding/memory/mt8173-larb-port.h for mt8173 + dt-binding/memory/mt2701-larb-port.h for mt2701, + dt-binding/memory/mt2712-larb-port.h for mt2712, and + dt-binding/memory/mt8173-larb-port.h for mt8173. Example: iommu: iommu@10205000 { diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt index aa614b2..615abdd 100644 --- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt +++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt @@ -2,8 +2,9 @@ SMI (Smart Multimedia Interface) Common The hardware block diagram please check bindings/iommu/mediatek,iommu.txt -Mediatek SMI have two generations of HW architecture, mt8173 uses the second -generation of SMI HW while mt2701 uses the first generation HW of SMI. +Mediatek SMI have two generations of HW architecture, mt2712 and mt8173 use +the second generation of SMI HW while mt2701 uses the first generation HW of +SMI. There's slight differences between the two SMI, for generation 2, the register which control the iommu port is at each larb's register base. But @@ -15,6 +16,7 @@ not needed for SMI generation 2. Required properties: - compatible : must be one of : "mediatek,mt2701-smi-common" + "mediatek,mt2712-smi-common" "mediatek,mt8173-smi-common" - reg : the register and size of the SMI block. - power-domains : a phandle to the power domain of this local arbiter. diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt index ddf46b8..083155c 100644 --- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt +++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt @@ -4,8 +4,9 @@ The hardware block diagram please check bindings/iommu/mediatek,iommu.txt Required properties: - compatible : must be one of : - "mediatek,mt8173-smi-larb" "mediatek,mt2701-smi-larb" + "mediatek,mt2712-smi-larb" + "mediatek,mt8173-smi-larb" - reg : the register and size of this local arbiter. - mediatek,smi : a phandle to the
[PATCH v2 0/8] MT2712 IOMMU SUPPORT
This patchset mainly adds support for M4U of mt2712. The M4U in mt2712 is MTK's generation2 M4U which use the ARM Short-descriptor like mt8173. The main difference is that there are 2 M4Us and 2 smi-commons in mt2712, while there is only 1 M4U and 1 smi-common in mt8173. The purpose is for balance the bandwidth. The mt2712 M4U-SMI HW diagram is as below: EMI | | | M4U0 M4U1 | | smi-common0smi-common1 | | - | | | | | | || | | | | | | | | || | | larb0 larb1 larb2 larb3 larb6larb4larb5larb7 larb8 larb9 disp0 vdec cam venc jpg mdp1/disp1 mdp2/disp2 mdp3 vdo/nr tvd This patchset is based on v4.13-rc1, Also it base on Robin's[1], Honghui[2],Arvind[3], all have been applied. Currently it don't contain the dtsi part. The patch 1 adds the binding for MT2712 IOMMU, the patch 2 is a prepared patch for mt2712, the patch 3 adds the MT2712 IOMMU support. the patch 4/5 improve the m4u flow for mt2712, the last patch 6/7/8 mainly fix bug or improve code. [1]:https://patchwork.kernel.org/patch/9828671/ [2]:https://patchwork.kernel.org/patch/9880223/ [3]:https://patchwork.kernel.org/patch/9892759/ change log: v2: 1) Add larb8 and larb9 in the HW diagram. larb8 and larb9 are called by the bdpsys larb, they are a little special, their mmu_en register offset is different from the normal larb. Fortunately, their mmu_en register is enabled defaultly, we don't need set again. After adding larb8 and larb9, the larb number is over 8, therefore, MTK_LARB_NR_MAX also is increased. 2) Add a prepared patch that moving the MTK_M4U_TO_LARB/PORT into the c file. 3) Discard the original patch[7/8] which was only a cleanup for SMI, It's unnecessary for this patch-set. 4) Use subsys_initcall instead of IOMMU_OF_DECLARE according to Robin's suggestion. Also, Improve some coding format, like using for_each_set_bit and changing the definition of F_MMU_TF_PROTECT_SEL. v1: https://lists.linuxfoundation.org/pipermail/iommu/2017-August/023664.html Yong Wu (8): dt-bindings: mediatek: Add binding for mt2712 IOMMU and SMI iommu/mediatek: Move MTK_M4U_TO_LARB/PORT into mtk_iommu.c iommu/mediatek: Add mt2712 IOMMU support iommu/mediatek: Merge 2 M4U HWs into one iommu domain iommu/mediatek: Move pgtable allocation into domain_alloc iommu/mediatek: Disable iommu clock when system suspend iommu/mediatek: Enlarge the validate PA range for 4GB mode memory: mtk-smi: Degrade SMI init to module_init .../devicetree/bindings/iommu/mediatek,iommu.txt | 6 +- .../memory-controllers/mediatek,smi-common.txt | 6 +- .../memory-controllers/mediatek,smi-larb.txt | 5 +- drivers/iommu/mtk_iommu.c | 214 + drivers/iommu/mtk_iommu.h | 9 + drivers/memory/mtk-smi.c | 65 ++- include/dt-bindings/memory/mt2712-larb-port.h | 102 ++ include/dt-bindings/memory/mt8173-larb-port.h | 4 - include/soc/mediatek/smi.h | 2 +- 9 files changed, 314 insertions(+), 99 deletions(-) create mode 100644 include/dt-bindings/memory/mt2712-larb-port.h -- 1.9.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 3/8] iommu/mediatek: Add mt2712 IOMMU support
The M4U IP blocks in mt2712 is MTK's generation2 M4U which use the ARM Short-descriptor like mt8173, and most of the HW registers are the same. The difference is that there are 2 M4U HWs in mt2712 while there's only one in mt8173. The purpose of 2 M4U HWs is for balance the bandwidth. Normally if there are 2 M4U HWs, there should be 2 iommu domains, each M4U has a iommu domain. Signed-off-by: Yong Wu--- drivers/iommu/mtk_iommu.c | 71 ++ drivers/iommu/mtk_iommu.h | 7 + drivers/memory/mtk-smi.c | 54 +-- include/soc/mediatek/smi.h | 2 +- 4 files changed, 93 insertions(+), 41 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 4db6c8f..df23e02 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -53,7 +53,11 @@ #define REG_MMU_CTRL_REG 0x110 #define F_MMU_PREFETCH_RT_REPLACE_MOD BIT(4) -#define F_MMU_TF_PROTECT_SEL(prot) (((prot) & 0x3) << 5) +#define F_MMU_TF_PROTECT_SEL_SHIFT(data) \ + ((data)->m4u_plat == M4U_MT2712 ? 4 : 5) +/* It's named by F_MMU_TF_PROT_SEL in mt2712. */ +#define F_MMU_TF_PROTECT_SEL(prot, data) \ + (((prot) & 0x3) << F_MMU_TF_PROTECT_SEL_SHIFT(data)) #define REG_MMU_IVRP_PADDR 0x114 #define F_MMU_IVRP_PA_SET(pa, ext) (((pa) >> 1) | ((!!(ext)) << 31)) @@ -96,7 +100,7 @@ * Get the local arbiter ID and the portid within the larb arbiter * from mtk_m4u_id which is defined by MTK_M4U_ID. */ -#define MTK_M4U_TO_LARB(id)(((id) >> 5) & 0x7) +#define MTK_M4U_TO_LARB(id)(((id) >> 5) & 0xf) #define MTK_M4U_TO_PORT(id)((id) & 0x1f) struct mtk_iommu_domain { @@ -307,10 +311,6 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, data->m4u_dom = NULL; return ret; } - } else if (data->m4u_dom != dom) { - /* All the client devices should be in the same m4u domain */ - dev_err(dev, "try to attach into the error iommu domain\n"); - return -EPERM; } mtk_iommu_config(data, dev, true); @@ -470,8 +470,9 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data) return ret; } - regval = F_MMU_PREFETCH_RT_REPLACE_MOD | - F_MMU_TF_PROTECT_SEL(2); + regval = F_MMU_TF_PROTECT_SEL(2, data); + if (data->m4u_plat == M4U_MT8173) + regval |= F_MMU_PREFETCH_RT_REPLACE_MOD; writel_relaxed(regval, data->base + REG_MMU_CTRL_REG); regval = F_L2_MULIT_HIT_EN | @@ -493,9 +494,11 @@ 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); - writel_relaxed(0, data->base + REG_MMU_DCM_DIS); - writel_relaxed(0, data->base + REG_MMU_STANDARD_AXI_MODE); + + /* It's MISC control register whose default value is ok except mt8173.*/ + if (data->m4u_plat == M4U_MT8173) + writel_relaxed(0, data->base + REG_MMU_STANDARD_AXI_MODE); if (devm_request_irq(data->dev, data->irq, mtk_iommu_isr, 0, dev_name(data->dev), (void *)data)) { @@ -527,6 +530,7 @@ static int mtk_iommu_probe(struct platform_device *pdev) if (!data) return -ENOMEM; data->dev = dev; + data->m4u_plat = (enum mtk_iommu_plat)of_device_get_match_data(dev); /* Protect memory. HW will access here while translation fault.*/ protect = devm_kzalloc(dev, MTK_PROTECT_PA_ALIGN * 2, GFP_KERNEL); @@ -560,6 +564,7 @@ static int mtk_iommu_probe(struct platform_device *pdev) for (i = 0; i < larb_nr; i++) { struct device_node *larbnode; struct platform_device *plarbdev; + u32 id; larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i); if (!larbnode) @@ -568,17 +573,14 @@ static int mtk_iommu_probe(struct platform_device *pdev) if (!of_device_is_available(larbnode)) continue; + ret = of_property_read_u32(larbnode, "mediatek,larb-id", ); + if (ret)/* The id is consecutive if there is no this property */ + id = i; + plarbdev = of_find_device_by_node(larbnode); - if (!plarbdev) { - plarbdev = of_platform_device_create( - larbnode, NULL, - platform_bus_type.dev_root); - if (!plarbdev) { - of_node_put(larbnode); - return -EPROBE_DEFER; - } -
[PATCH v2 2/8] iommu/mediatek: Move MTK_M4U_TO_LARB/PORT into mtk_iommu.c
The definition of MTK_M4U_TO_LARB and MTK_M4U_TO_PORT are shared by all the gen2 M4U HWs. Thus, Move them out from mt8173-larb-port.h, and put them into the c file. Suggested-by: Honghui ZhangSigned-off-by: Yong Wu --- This patch only moves the position of the MACRO MTK_M4U_TO_LARB/PORT. --- drivers/iommu/mtk_iommu.c | 8 +++- include/dt-bindings/memory/mt8173-larb-port.h | 4 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 91c6d36..4db6c8f 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include "mtk_iommu.h" @@ -93,6 +92,13 @@ #define MTK_PROTECT_PA_ALIGN 128 +/* + * Get the local arbiter ID and the portid within the larb arbiter + * from mtk_m4u_id which is defined by MTK_M4U_ID. + */ +#define MTK_M4U_TO_LARB(id)(((id) >> 5) & 0x7) +#define MTK_M4U_TO_PORT(id)((id) & 0x1f) + struct mtk_iommu_domain { spinlock_t pgtlock; /* lock for page table */ diff --git a/include/dt-bindings/memory/mt8173-larb-port.h b/include/dt-bindings/memory/mt8173-larb-port.h index 5fef5d1..111b4b0 100644 --- a/include/dt-bindings/memory/mt8173-larb-port.h +++ b/include/dt-bindings/memory/mt8173-larb-port.h @@ -15,10 +15,6 @@ #define __DTS_IOMMU_PORT_MT8173_H #define MTK_M4U_ID(larb, port) (((larb) << 5) | (port)) -/* Local arbiter ID */ -#define MTK_M4U_TO_LARB(id)(((id) >> 5) & 0x7) -/* PortID within the local arbiter */ -#define MTK_M4U_TO_PORT(id)((id) & 0x1f) #define M4U_LARB0_ID 0 #define M4U_LARB1_ID 1 -- 1.9.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 4/8] iommu/mediatek: Merge 2 M4U HWs into one iommu domain
In theory, If there are 2 M4U HWs, there should be 2 IOMMU domains. But one IOMMU domain(4GB iova range) is enough for us currently, It's unnecessary to maintain 2 pagetables. Besides, This patch can simplify our consumer code largely. They don't need map a iova range from one domain into another, They can share the iova address easily. Signed-off-by: Yong Wu--- drivers/iommu/mtk_iommu.c | 92 ++- drivers/iommu/mtk_iommu.h | 2 ++ 2 files changed, 70 insertions(+), 24 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index df23e02..1503dfa 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -114,6 +114,27 @@ struct mtk_iommu_domain { static struct iommu_ops mtk_iommu_ops; +static LIST_HEAD(m4ulist); /* List all the M4U HWs */ + +#define for_each_m4u(data) list_for_each_entry(data, , list) + +/* + * There may be 1 or 2 M4U HWs, But we always expect they are in the same domain + * for the performance. + * + * Here always return the mtk_iommu_data of the first probed M4U where the + * iommu domain information is recorded. + */ +static struct mtk_iommu_data *mtk_iommu_get_m4u_data(void) +{ + struct mtk_iommu_data *data; + + for_each_m4u(data) + return data; + + return NULL; +} + static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom) { return container_of(dom, struct mtk_iommu_domain, domain); @@ -123,9 +144,12 @@ static void mtk_iommu_tlb_flush_all(void *cookie) { struct mtk_iommu_data *data = cookie; - writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0, data->base + REG_MMU_INV_SEL); - writel_relaxed(F_ALL_INVLD, data->base + REG_MMU_INVALIDATE); - wmb(); /* Make sure the tlb flush all done */ + for_each_m4u(data) { + writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0, + data->base + REG_MMU_INV_SEL); + writel_relaxed(F_ALL_INVLD, data->base + REG_MMU_INVALIDATE); + wmb(); /* Make sure the tlb flush all done */ + } } static void mtk_iommu_tlb_add_flush_nosync(unsigned long iova, size_t size, @@ -134,12 +158,17 @@ static void mtk_iommu_tlb_add_flush_nosync(unsigned long iova, size_t size, { struct mtk_iommu_data *data = cookie; - writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0, data->base + REG_MMU_INV_SEL); + for_each_m4u(data) { + writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0, + data->base + REG_MMU_INV_SEL); - writel_relaxed(iova, data->base + REG_MMU_INVLD_START_A); - writel_relaxed(iova + size - 1, data->base + REG_MMU_INVLD_END_A); - writel_relaxed(F_MMU_INV_RANGE, data->base + REG_MMU_INVALIDATE); - data->tlb_flush_active = true; + writel_relaxed(iova, data->base + REG_MMU_INVLD_START_A); + writel_relaxed(iova + size - 1, + data->base + REG_MMU_INVLD_END_A); + writel_relaxed(F_MMU_INV_RANGE, + data->base + REG_MMU_INVALIDATE); + data->tlb_flush_active = true; + } } static void mtk_iommu_tlb_sync(void *cookie) @@ -148,20 +177,22 @@ static void mtk_iommu_tlb_sync(void *cookie) int ret; u32 tmp; - /* Avoid timing out if there's nothing to wait for */ - if (!data->tlb_flush_active) - return; + for_each_m4u(data) { + /* Avoid timing out if there's nothing to wait for */ + if (!data->tlb_flush_active) + return; - ret = readl_poll_timeout_atomic(data->base + REG_MMU_CPE_DONE, tmp, - tmp != 0, 10, 10); - if (ret) { - dev_warn(data->dev, -"Partial TLB flush timed out, falling back to full flush\n"); - mtk_iommu_tlb_flush_all(cookie); + ret = readl_poll_timeout_atomic(data->base + REG_MMU_CPE_DONE, + tmp, tmp != 0, 10, 10); + if (ret) { + dev_warn(data->dev, +"Partial TLB flush timed out, falling back to full flush\n"); + mtk_iommu_tlb_flush_all(cookie); + } + /* Clear the CPE status */ + writel_relaxed(0, data->base + REG_MMU_CPE_DONE); + data->tlb_flush_active = false; } - /* Clear the CPE status */ - writel_relaxed(0, data->base + REG_MMU_CPE_DONE); - data->tlb_flush_active = false; } static const struct iommu_gather_ops mtk_iommu_gather_ops = { @@ -298,10 +329,11 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, struct device *dev) { struct mtk_iommu_domain *dom = to_mtk_domain(domain); - struct mtk_iommu_data
[PATCH v2 5/8] iommu/mediatek: Move pgtable allocation into domain_alloc
After adding the global list for M4U HW, We get a chance to move the pagetable allocation into the mtk_iommu_domain_alloc. Let the domain_alloc do the right thing. This patch is for fixing this problem[1]. [1]: https://patchwork.codeaurora.org/patch/53987/ Signed-off-by: Yong Wu--- drivers/iommu/mtk_iommu.c | 52 --- 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 1503dfa..a82196c 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -262,9 +262,9 @@ static void mtk_iommu_config(struct mtk_iommu_data *data, } } -static int mtk_iommu_domain_finalise(struct mtk_iommu_data *data) +static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom) { - struct mtk_iommu_domain *dom = data->m4u_dom; + struct mtk_iommu_data *data = mtk_iommu_get_m4u_data(); spin_lock_init(>pgtlock); @@ -290,9 +290,6 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_data *data) /* Update our support page sizes bitmap */ dom->domain.pgsize_bitmap = dom->cfg.pgsize_bitmap; - - writel(data->m4u_dom->cfg.arm_v7s_cfg.ttbr[0], - data->base + REG_MMU_PT_BASE_ADDR); return 0; } @@ -307,20 +304,30 @@ static struct iommu_domain *mtk_iommu_domain_alloc(unsigned type) if (!dom) return NULL; - if (iommu_get_dma_cookie(>domain)) { - kfree(dom); - return NULL; - } + if (iommu_get_dma_cookie(>domain)) + goto free_dom; + + if (mtk_iommu_domain_finalise(dom)) + goto put_dma_cookie; dom->domain.geometry.aperture_start = 0; dom->domain.geometry.aperture_end = DMA_BIT_MASK(32); dom->domain.geometry.force_aperture = true; return >domain; + +put_dma_cookie: + iommu_put_dma_cookie(>domain); +free_dom: + kfree(dom); + return NULL; } static void mtk_iommu_domain_free(struct iommu_domain *domain) { + struct mtk_iommu_domain *dom = to_mtk_domain(domain); + + free_io_pgtable_ops(dom->iop); iommu_put_dma_cookie(domain); kfree(to_mtk_domain(domain)); } @@ -329,33 +336,19 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, struct device *dev) { struct mtk_iommu_domain *dom = to_mtk_domain(domain); - struct mtk_iommu_data *curdata = dev->iommu_fwspec->iommu_priv; - struct mtk_iommu_data *data = mtk_iommu_get_m4u_data(); - int ret; + struct mtk_iommu_data *data = dev->iommu_fwspec->iommu_priv; - if (!data || !curdata) + if (!data) return -ENODEV; + /* Update the pgtable base address register of the M4U HW */ if (!data->m4u_dom) { data->m4u_dom = dom; - ret = mtk_iommu_domain_finalise(data); - if (ret) { - data->m4u_dom = NULL; - return ret; - } - } - - /* -* Update the pgtable base address register of another M4U HW with the -* existed pgtable if there are more than one M4U HW. -*/ - if (!curdata->m4u_dom) { - curdata->m4u_dom = data->m4u_dom; - writel(data->m4u_dom->cfg.arm_v7s_cfg.ttbr[0], - curdata->base + REG_MMU_PT_BASE_ADDR); + writel(dom->cfg.arm_v7s_cfg.ttbr[0], + data->base + REG_MMU_PT_BASE_ADDR); } - mtk_iommu_config(curdata, dev, true); + mtk_iommu_config(data, dev, true); return 0; } @@ -664,7 +657,6 @@ static int mtk_iommu_remove(struct platform_device *pdev) if (iommu_present(_bus_type)) bus_set_iommu(_bus_type, NULL); - free_io_pgtable_ops(data->m4u_dom->iop); clk_disable_unprepare(data->bclk); devm_free_irq(>dev, data->irq, data); component_master_del(>dev, _iommu_com_ops); -- 1.9.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 7/8] iommu/mediatek: Enlarge the validate PA range for 4GB mode
This patch is for 4GB mode, mainly for 4 issues: 1) Fix a 4GB bug: if the dram base is 0x4000_, the dram size is 0xc000_. then the code just meet a corner case because max_pfn is 0x10_. data->enable_4GB = !!(max_pfn > (0xUL >> 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__ to 0x1__ 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__ to 0x1__. Thus, the PA from iova_to_pa should also '|' BIT(32) Signed-off-by: Honghui ZhangSigned-off-by: Yong Wu --- drivers/iommu/mtk_iommu.c | 18 +++--- 1 file changed, 15 insertions(+), 3 deletions(-) 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 0xf000 #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(>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__ to 0x1__. 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 > (0xUL >> 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); -- 1.9.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 6/8] iommu/mediatek: Disable iommu clock when system suspend
When system suspend, infra power domain may be off, and the iommu's clock must be disabled when system off, or the iommu's bclk clock maybe disabled after system resume. Signed-off-by: Honghui ZhangSigned-off-by: Yong Wu --- drivers/iommu/mtk_iommu.c | 9 - 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index a82196c..e21de86 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -675,6 +675,7 @@ static int __maybe_unused mtk_iommu_suspend(struct device *dev) reg->ctrl_reg = readl_relaxed(base + REG_MMU_CTRL_REG); reg->int_control0 = readl_relaxed(base + REG_MMU_INT_CONTROL0); reg->int_main_control = readl_relaxed(base + REG_MMU_INT_MAIN_CONTROL); + clk_disable_unprepare(data->bclk); return 0; } @@ -683,7 +684,13 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev) struct mtk_iommu_data *data = dev_get_drvdata(dev); struct mtk_iommu_suspend_reg *reg = >reg; void __iomem *base = data->base; + int ret; + ret = clk_prepare_enable(data->bclk); + if (ret) { + dev_err(data->dev, "Failed to enable clk(%d) in resume\n", ret); + return ret; + } writel_relaxed(reg->standard_axi_mode, base + REG_MMU_STANDARD_AXI_MODE); writel_relaxed(reg->dcm_dis, base + REG_MMU_DCM_DIS); @@ -699,7 +706,7 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev) } static const struct dev_pm_ops mtk_iommu_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(mtk_iommu_suspend, mtk_iommu_resume) + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mtk_iommu_suspend, mtk_iommu_resume) }; static const struct of_device_id mtk_iommu_of_ids[] = { -- 1.9.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 8/8] memory: mtk-smi: Degrade SMI init to module_init
The initialization of MediaTek power manager(SCPSYS) is builtin_platform_driver, and SMI must depend on power-domain. Thus, currently subsys_initcall for SMI is unnecessary, SMI will be always probe defered by power-domain. Degrade it to module_init. In addition, there are two small changes about the probe sequence: 1) Delete this two lines. if (!dev->pm_domain) return -EPROBE_DEFER; This is not helpful. the platform driver framework guarantee this. The "dev_pm_domain_attach" in the "platform_drv_probe" will return EPROBE_DEFER if its powerdomain is not ready. 2) Add the probe-defer for the smi-larb device should waiting for smi-common. In mt2712, there are 2 smi-commons, 10 smi-larbs. All will be probe-defered by the power-domain, there is seldom case that smi-larb probe done before smi-common. then it will hang like this: Unable to handle kernel NULL pointer dereference at virtual address pgd = ff800a4e [] *pgd=beffe003[ 17.610026] , *pud=beffe003 ... [] mtk_smi_enable+0x1c/0xd0 [] mtk_smi_larb_get+0x30/0x98 [] mtk_mipicsi0_resume+0x38/0x1b8 [] pm_generic_runtime_resume+0x3c/0x58 [] __genpd_runtime_resume+0x38/0x98 [] genpd_runtime_resume+0x164/0x220 [] __rpm_callback+0x78/0xa0 [] rpm_callback+0x38/0xa0 [] rpm_resume+0x4a4/0x6f8 [] __pm_runtime_resume+0x64/0xa0 [] mtk_mipicsi0_probe+0x40c/0xb70 [] platform_drv_probe+0x58/0xc0 [] driver_probe_device+0x284/0x438 [] __device_attach_driver+0xb4/0x160 [] bus_for_each_drv+0x68/0xa8 [] __device_attach+0xd4/0x168 [] device_initial_probe+0x24/0x30 [] bus_probe_device+0xa0/0xa8 [] deferred_probe_work_func+0x94/0xf0 [] process_one_work+0x1d8/0x6e0 Signed-off-by: Yong Wu--- drivers/memory/mtk-smi.c | 11 --- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c index 8ffe321..8f2d152 100644 --- a/drivers/memory/mtk-smi.c +++ b/drivers/memory/mtk-smi.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -288,9 +289,6 @@ static int mtk_smi_larb_probe(struct platform_device *pdev) struct platform_device *smi_pdev; int err; - if (!dev->pm_domain) - return -EPROBE_DEFER; - larb = devm_kzalloc(dev, sizeof(*larb), GFP_KERNEL); if (!larb) return -ENOMEM; @@ -326,6 +324,8 @@ static int mtk_smi_larb_probe(struct platform_device *pdev) smi_pdev = of_find_device_by_node(smi_node); of_node_put(smi_node); if (smi_pdev) { + if (!platform_get_drvdata(smi_pdev)) + return -EPROBE_DEFER; larb->smi_common_dev = _pdev->dev; } else { dev_err(dev, "Failed to get the smi_common device\n"); @@ -377,9 +377,6 @@ static int mtk_smi_common_probe(struct platform_device *pdev) enum mtk_smi_gen smi_gen; int ret; - if (!dev->pm_domain) - return -EPROBE_DEFER; - common = devm_kzalloc(dev, sizeof(*common), GFP_KERNEL); if (!common) return -ENOMEM; @@ -456,4 +453,4 @@ static int __init mtk_smi_init(void) return ret; } -subsys_initcall(mtk_smi_init); +module_init(mtk_smi_init); -- 1.9.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [RFC 2/3] virtio-iommu: device probing and operations
On 21/08/17 08:59, Tian, Kevin wrote: >> From: Jean-Philippe Brucker [mailto:jean-philippe.bruc...@arm.com] >> Sent: Monday, April 24, 2017 11:06 PM >> 1. Attach device >> >> >> struct virtio_iommu_req_attach { >> le32address_space; >> le32device; >> le32flags/reserved; >> }; >> >> Attach a device to an address space. 'address_space' is an identifier >> unique to the guest. If the address space doesn't exist in the IOMMU > > Based on your description this address space ID is per operation right? > MAP/UNMAP and page-table sharing should have different ID spaces... I think it's simpler if we keep a single IOASID space per virtio-iommu device, because the maximum number of address spaces (described by ioasid_bits) might be a restriction of the pIOMMU. For page-table >> sharing you still need to define which devices will share a page directory using ATTACH requests, though that interface is not set in stone. >>> >>> got you. yes VM is supposed to consume less IOASIDs than physically >>> available. It doesn’t hurt to have one IOASID space for both IOVA >>> map/unmap usages (one IOASID per device) and SVM usages (multiple >>> IOASIDs per device). The former is digested by software and the latter >>> will be bound to hardware. >>> >> >> Hmm, I'm using address space indexed by IOASID for "classic" IOMMU, and >> then contexts indexed by PASID when talking about SVM. So in my mind an >> address space can have multiple sub-address-spaces (contexts). Number of >> IOASIDs is a limitation of the pIOMMU, and number of PASIDs is a >> limitation of the device. Therefore attaching devices to address spaces >> would update the number of available contexts in that address space. The >> terminology is not ideal, and I'd be happy to change it for something more >> clear. >> > > (sorry to pick up this old thread, as the .tex one is not good for review > and this thread provides necessary background for IOASID). > > Hi, Jean, > > I'd like to hear more clarification regarding the relationship between > IOASID and PASID. When reading back above explanation, it looks > confusing to me now (though I might get the meaning months ago :/). > At least Intel VT-d only understands PASID (or you can think IOASID > =PASID). There is no such layered address space concept. Then for > map/unmap type request, do you intend to steal some PASIDs for > that purpose on such architecture (since IOASID is a mandatory field > in map/unmap request)? IOASID is a logical ID, it isn't used by hardware. The address space concept in virtio-iommu allows to group endpoints together, so that they have the same address space. I thought it was pretty much the same as "domains" in VT-d? In any case, it is the same as domains in Linux. An IOASID provides a handle for communication between virtio-iommu device and driver, but unlike PASID, the IOASID number doesn't mean anything outside of virtio-iommu. I haven't introduced PASIDs in public virtio-iommu documents yet, but the way I intend it, PASID != IOASID. We will still have a logical address space identified by IOASID, that can contain multiple contexts identified by PASID. At the moment, after the ATTACH request, an address space contains a single anonymous context (NO PASID) that can be managed with MAP/UNMAP requests. With virtio-iommu v0.4, structures look like the following. The NO PASID context is implicit. address space context endpoint . .- mapping endpoint + IOASID NO PASID +- mapping endpoint ' '- mapping I'd like to add a flag to ATTACH that says "don't create a default anonymous context, I'll handle contexts myself". Then a new "ADD_TABLE" request to handle contexts. When creating a context, the guest decides if it wants to manage it via MAP/UNMAP requests (and a new "context" field), or instead manage mappings itself by allocating a page directory and use INVALIDATE requests. address space context endpoint . .- mapping endpoint + IOASID +--- NO PASID +- mapping endpoint '| '- mapping +--- PASID 0 pgd | ... '--- PASID N pgd In this example the guest chose to still have an anonymous context that uses MAP/UNMAP, along with a few PASID contexts with their own page tables. Thanks, Jean ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
RE: [RFC 2/3] virtio-iommu: device probing and operations
> From: Jean-Philippe Brucker [mailto:jean-philippe.bruc...@arm.com] > Sent: Monday, April 24, 2017 11:06 PM > 1. Attach device > > > struct virtio_iommu_req_attach { > le32address_space; > le32device; > le32flags/reserved; > }; > > Attach a device to an address space. 'address_space' is an identifier > unique to the guest. If the address space doesn't exist in the IOMMU > >>> > >>> Based on your description this address space ID is per operation right? > >>> MAP/UNMAP and page-table sharing should have different ID spaces... > >> > >> I think it's simpler if we keep a single IOASID space per virtio-iommu > >> device, because the maximum number of address spaces (described by > >> ioasid_bits) might be a restriction of the pIOMMU. For page-table > sharing > >> you still need to define which devices will share a page directory using > >> ATTACH requests, though that interface is not set in stone. > > > > got you. yes VM is supposed to consume less IOASIDs than physically > > available. It doesn’t hurt to have one IOASID space for both IOVA > > map/unmap usages (one IOASID per device) and SVM usages (multiple > > IOASIDs per device). The former is digested by software and the latter > > will be bound to hardware. > > > > Hmm, I'm using address space indexed by IOASID for "classic" IOMMU, and > then contexts indexed by PASID when talking about SVM. So in my mind an > address space can have multiple sub-address-spaces (contexts). Number of > IOASIDs is a limitation of the pIOMMU, and number of PASIDs is a > limitation of the device. Therefore attaching devices to address spaces > would update the number of available contexts in that address space. The > terminology is not ideal, and I'd be happy to change it for something more > clear. > (sorry to pick up this old thread, as the .tex one is not good for review and this thread provides necessary background for IOASID). Hi, Jean, I'd like to hear more clarification regarding the relationship between IOASID and PASID. When reading back above explanation, it looks confusing to me now (though I might get the meaning months ago :/). At least Intel VT-d only understands PASID (or you can think IOASID =PASID). There is no such layered address space concept. Then for map/unmap type request, do you intend to steal some PASIDs for that purpose on such architecture (since IOASID is a mandatory field in map/unmap request)? Thanks Kevin ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 0/4] Patches to support ring0 SVM and devtlb
Thanks Joerg On Fri, Aug 18, 2017 at 11:35:21AM +0200, Joerg Roedel wrote: > Hi Ashok, > > On Tue, Aug 15, 2017 at 07:59:29AM -0700, Raj, Ashok wrote: > > I haven't received any update to this patchset.. > > > > Could you help get this merged through your tree? we have tested this > > series internally. > > The mm-notifier patch needs acks or rb from mm-developers before I can > merge this patch-set. someone from the mm list.. could you help ack/rb this patch? Cheers, Ashok ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu