Re: [PATCH v3 0/5] enhance DMA CMA on x86
2014-10-03 7:03 GMT+09:00 Peter Hurley : > On 10/02/2014 12:41 PM, Konrad Rzeszutek Wilk wrote: >> On Tue, Sep 30, 2014 at 09:49:54PM -0400, Peter Hurley wrote: >>> On 09/30/2014 07:45 PM, Thomas Gleixner wrote: >>> Which is different than if the plan is to ship production units for x86; >>> then a general purpose solution will be required. >>> >>> As to the good design of a general purpose solution for allocating and >>> mapping huge order pages, you are certainly more qualified to help Akinobu >>> than I am. > > What Akinobu's patches intend to support is: > > phys_addr = dma_alloc_coherent(dev, 64 * 1024 * 1024, &bus_addr, > GFP_KERNEL); > > which raises three issues: > > 1. Where do coherent blocks of this size come from? > 2. How to prevent fragmentation of these reserved blocks over time by >existing DMA users? > 3. Is this support generically required across all iommu implementations on > x86? > > Questions 1 and 2 are non-trivial, in the general case, otherwise the page > allocator would already do this. Simply dropping in the contiguous memory > allocator doesn't work because CMA does not have the same policy and > performance > as the page allocator, and is already causing performance regressions even > in the absence of huge page allocations. Could you take a look at the patches I sent? Can they fix these issues? https://lkml.org/lkml/2014/9/28/110 With these patches, normal alloc_pages() is used for allocation first and dma_alloc_from_contiguous() is used as a fallback. > So that's why I raised question 3; is making the necessary compromises to > support > 64MB coherent DMA allocations across all x86 iommu implementations actually > required? > > Prior to Akinobu's patches, the use of CMA by x86 iommu configurations was > designed to be limited to testing configurations, as the introductory > commit states: > > commit 0a2b9a6ea93650b8a00f9fd5ee8fdd25671e2df6 > Author: Marek Szyprowski > Date: Thu Dec 29 13:09:51 2011 +0100 > > X86: integrate CMA with DMA-mapping subsystem > > This patch adds support for CMA to dma-mapping subsystem for x86 > architecture that uses common pci-dma/pci-nommu implementation. This > allows to test CMA on KVM/QEMU and a lot of common x86 boxes. > > Signed-off-by: Marek Szyprowski > Signed-off-by: Kyungmin Park > CC: Michal Nazarewicz > Acked-by: Arnd Bergmann > > > Which brings me to my suggestion: if support for huge coherent DMA is > required only for a special test platform, then could not this support > be specific to a new iommu configuration, namely iommu=cma, which would > get initialized much the same way that iommu=calgary is now. > > The code for such a iommu configuration would mostly duplicate > arch/x86/kernel/pci-swiotlb.c and the CMA support would get removed from > the other x86 iommu implementations. I'm not sure I read correctly, though. Can boot option 'cma=0' also help avoiding CMA from IOMMU implementation? ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v3 0/5] enhance DMA CMA on x86
On 10/02/2014 12:41 PM, Konrad Rzeszutek Wilk wrote: > On Tue, Sep 30, 2014 at 09:49:54PM -0400, Peter Hurley wrote: >> On 09/30/2014 07:45 PM, Thomas Gleixner wrote: >>> Whether the proposed patchset is the correct solution to support it is >>> a completely different question. >> >> This patchset has been in mainline since 3.16 and has already caused >> regressions, so the question of whether this is the correct solution has >> already been answered. >> >>> So either you stop this right now and help Akinobu to find the proper >>> solution >> >> If this is only a test platform for ARM parts then I don't think it >> unreasonable to suggest forking x86 swiotlb support into a iommu=cma > > Not sure what you mean by 'forking x86 swiotlb' ? As in have SWIOTLB > work under ARM? No, that's not what I meant. >> selector that gets DMA mapping working for this test platform and doesn't >> cause a bunch of breakage. > > I think you might want to take a look at the IOMMU_DETECT macros > and enable CMA there only if the certain devices are available. > > That way the normal flow of detecting which IOMMU to use is still present > and will turn of CMA if there is no device that would use it. > >> >> Which is different than if the plan is to ship production units for x86; >> then a general purpose solution will be required. >> >> As to the good design of a general purpose solution for allocating and >> mapping huge order pages, you are certainly more qualified to help Akinobu >> than I am. What Akinobu's patches intend to support is: phys_addr = dma_alloc_coherent(dev, 64 * 1024 * 1024, &bus_addr, GFP_KERNEL); which raises three issues: 1. Where do coherent blocks of this size come from? 2. How to prevent fragmentation of these reserved blocks over time by existing DMA users? 3. Is this support generically required across all iommu implementations on x86? Questions 1 and 2 are non-trivial, in the general case, otherwise the page allocator would already do this. Simply dropping in the contiguous memory allocator doesn't work because CMA does not have the same policy and performance as the page allocator, and is already causing performance regressions even in the absence of huge page allocations. So that's why I raised question 3; is making the necessary compromises to support 64MB coherent DMA allocations across all x86 iommu implementations actually required? Prior to Akinobu's patches, the use of CMA by x86 iommu configurations was designed to be limited to testing configurations, as the introductory commit states: commit 0a2b9a6ea93650b8a00f9fd5ee8fdd25671e2df6 Author: Marek Szyprowski Date: Thu Dec 29 13:09:51 2011 +0100 X86: integrate CMA with DMA-mapping subsystem This patch adds support for CMA to dma-mapping subsystem for x86 architecture that uses common pci-dma/pci-nommu implementation. This allows to test CMA on KVM/QEMU and a lot of common x86 boxes. Signed-off-by: Marek Szyprowski Signed-off-by: Kyungmin Park CC: Michal Nazarewicz Acked-by: Arnd Bergmann Which brings me to my suggestion: if support for huge coherent DMA is required only for a special test platform, then could not this support be specific to a new iommu configuration, namely iommu=cma, which would get initialized much the same way that iommu=calgary is now. The code for such a iommu configuration would mostly duplicate arch/x86/kernel/pci-swiotlb.c and the CMA support would get removed from the other x86 iommu implementations. Regards, Peter Hurley ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [RFC 09/10] drm/tegra: Add IOMMU support
On Tue, Sep 30, 2014 at 2:48 PM, Sean Paul wrote: > On Thu, Jun 26, 2014 at 4:49 PM, Thierry Reding > wrote: >> From: Thierry Reding >> >> When an IOMMU device is available on the platform bus, allocate an IOMMU >> domain and attach the display controllers to it. The display controllers >> can then scan out non-contiguous buffers by mapping them through the >> IOMMU. >> > > Hi Thierry, > A few comments from Stéphane and myself that came up while we were > reviewing this for our tree. > >> Signed-off-by: Thierry Reding >> --- >> drivers/gpu/drm/tegra/dc.c | 21 >> drivers/gpu/drm/tegra/drm.c | 17 >> drivers/gpu/drm/tegra/drm.h | 3 + >> drivers/gpu/drm/tegra/fb.c | 16 ++- >> drivers/gpu/drm/tegra/gem.c | 236 >> +++- >> drivers/gpu/drm/tegra/gem.h | 4 + >> 6 files changed, 273 insertions(+), 24 deletions(-) >> >> diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c >> index afcca04f5367..0f7452d04811 100644 >> --- a/drivers/gpu/drm/tegra/dc.c >> +++ b/drivers/gpu/drm/tegra/dc.c >> @@ -9,6 +9,7 @@ >> >> #include >> #include >> +#include >> #include >> >> #include "dc.h" >> @@ -1283,8 +1284,18 @@ static int tegra_dc_init(struct host1x_client *client) >> { >> struct drm_device *drm = dev_get_drvdata(client->parent); >> struct tegra_dc *dc = host1x_client_to_dc(client); >> + struct tegra_drm *tegra = drm->dev_private; >> int err; >> >> + if (tegra->domain) { >> + err = iommu_attach_device(tegra->domain, dc->dev); >> + if (err < 0) { >> + dev_err(dc->dev, "failed to attach to IOMMU: %d\n", >> + err); >> + return err; >> + } > > [from Stéphane] > > shouldn't we call detach in the error paths below? > > >> + } >> + >> drm_crtc_init(drm, &dc->base, &tegra_crtc_funcs); >> drm_mode_crtc_set_gamma_size(&dc->base, 256); >> drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs); >> @@ -1318,7 +1329,9 @@ static int tegra_dc_init(struct host1x_client *client) >> >> static int tegra_dc_exit(struct host1x_client *client) >> { >> + struct drm_device *drm = dev_get_drvdata(client->parent); >> struct tegra_dc *dc = host1x_client_to_dc(client); >> + struct tegra_drm *tegra = drm->dev_private; >> int err; >> >> devm_free_irq(dc->dev, dc->irq, dc); >> @@ -1335,6 +1348,8 @@ static int tegra_dc_exit(struct host1x_client *client) >> return err; >> } >> >> + iommu_detach_device(tegra->domain, dc->dev); >> + >> return 0; >> } >> >> @@ -1462,6 +1477,12 @@ static int tegra_dc_probe(struct platform_device >> *pdev) >> return -ENXIO; >> } >> >> + err = iommu_attach(&pdev->dev); >> + if (err < 0) { >> + dev_err(&pdev->dev, "failed to attach to IOMMU: %d\n", err); >> + return err; >> + } >> + >> INIT_LIST_HEAD(&dc->client.list); >> dc->client.ops = &dc_client_ops; >> dc->client.dev = &pdev->dev; >> diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c >> index 59736bb810cd..1d2bbafad982 100644 >> --- a/drivers/gpu/drm/tegra/drm.c >> +++ b/drivers/gpu/drm/tegra/drm.c >> @@ -8,6 +8,7 @@ >> */ >> >> #include >> +#include >> >> #include "drm.h" >> #include "gem.h" >> @@ -33,6 +34,16 @@ static int tegra_drm_load(struct drm_device *drm, >> unsigned long flags) >> if (!tegra) >> return -ENOMEM; >> >> + if (iommu_present(&platform_bus_type)) { >> + tegra->domain = iommu_domain_alloc(&platform_bus_type); >> + if (IS_ERR(tegra->domain)) { >> + kfree(tegra); >> + return PTR_ERR(tegra->domain); >> + } >> + >> + drm_mm_init(&tegra->mm, 0, SZ_2G); > > > [from Stéphane]: > > none of these are freed in the error path below (iommu_domain_free and > drm_mm_takedown) > > also |tegra| isn't freed either? > > > >> + } >> + >> mutex_init(&tegra->clients_lock); >> INIT_LIST_HEAD(&tegra->clients); >> drm->dev_private = tegra; >> @@ -71,6 +82,7 @@ static int tegra_drm_load(struct drm_device *drm, unsigned >> long flags) >> static int tegra_drm_unload(struct drm_device *drm) >> { >> struct host1x_device *device = to_host1x_device(drm->dev); >> + struct tegra_drm *tegra = drm->dev_private; >> int err; >> >> drm_kms_helper_poll_fini(drm); >> @@ -82,6 +94,11 @@ static int tegra_drm_unload(struct drm_device *drm) >> if (err < 0) >> return err; >> >> + if (tegra->domain) { >> + iommu_domain_free(tegra->domain); >> + drm_mm_takedown(&tegra->mm); >> + } >> + >> return 0; >> } >> >> diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/d
[PATCH 1/3] iommu/rockchip: rk3288 iommu driver
The rk3288 has several iommus. Each iommu belongs to a single master device. There is one device (ISP) that has two slave iommus, but that case is not yet supported by this driver. At subsys init, the iommu driver registers itself as the iommu driver for the platform bus. The master devices find their slave iommus using the "iommus" field in their devicetree description. Since each slave iommu belongs to exactly one master, their is no additional data needed at probe to associate a slave with its master. An iommu device's power domain, clock and irq are all shared with its master device, and the master device must be careful to attach from the iommu only after powering and clocking it (and leave it powered and clocked before detaching). Because their is no guarantee what the status of the iommu is at probe, and since the driver does not even know if the device is powered, we delay requesting its irq until the master device attaches, at which point we have a guarantee that the device is powered and clocked and we can reset it and disable its interrupt mask. An iommu_domain describes a virtual iova address space. Each iommu_domain has a corresponding page table that lists the mappings from iova to physical address. For the rk3288 iommu, the page table has two levels: The Level 1 "directory_table" has 1024 4-byte dte entries. Each dte points to a level 2 "page_table". Each level 2 page_table has 1024 4-byte pte entries. Each pte points to a 4 KiB page of memory. An iommu_domain is created when a dma_iommu_mapping is created via arm_iommu_create_mapping. Master devices can then attach themselves to this mapping (or attach the mapping to themselves?) by calling arm_iommu_attach_device(). This in turn instructs the iommu driver to write the page table's physical address into the slave iommu's "Directory Table Entry" (DTE) register. In fact multiple master devices, each with their own slave iommu device, can all attach to the same mapping. The iommus for these devices will share the same iommu_domain and therefore point to the same page table. Thus, the iommu domain maintains a list of iommu devices which are attached. This driver relies on the iommu core to ensure that all devices have detached before destroying a domain. Signed-off-by: Daniel Kurtz Signed-off-by: Simon Xue --- drivers/iommu/Kconfig | 11 + drivers/iommu/Makefile | 1 + drivers/iommu/rockchip-iommu.c | 924 + 3 files changed, 936 insertions(+) create mode 100644 drivers/iommu/rockchip-iommu.c diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index dd51122..b80454c 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -152,6 +152,17 @@ config OMAP_IOMMU_DEBUG Say N unless you know you need this. +config ROCKCHIP_IOMMU + bool "Rockchip IOMMU Support" + depends on ARCH_ROCKCHIP + select IOMMU_API + help + Support for IOMMUs found on Rockchip rk32xx SOCs. + These IOMMUs allow virtualization of the address space used by most + cores within the multimedia subsystem. + Say Y here if you are using a Rockchip SoC that includes an IOMMU + device. + config TEGRA_IOMMU_GART bool "Tegra GART IOMMU Support" depends on ARCH_TEGRA_2x_SOC diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 16edef7..3e47ef3 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o obj-$(CONFIG_OMAP_IOMMU) += omap-iommu2.o obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o +obj-$(CONFIG_ROCKCHIP_IOMMU) += rockchip-iommu.o obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iommu.o diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c new file mode 100644 index 000..4116df1 --- /dev/null +++ b/drivers/iommu/rockchip-iommu.c @@ -0,0 +1,924 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** MMU register offsets */ +#define RK_MMU_DTE_ADDR0x00/* Directory table address */ +#define RK_MMU_STATUS 0x04 +#define RK_MMU_COMMAND 0x08 +#define RK_MMU_PAGE_FAULT_ADDR 0x0C/* IOVA of last page fault */ +#define RK_MMU_ZAP_ONE_LINE0x10/* Shootdown one IOTLB entry */ +#define RK_MMU_INT_RAWSTAT 0x14/* IRQ status ignoring mask */ +#define RK_MMU_INT_CLEAR 0x18/* Acknowledge and re-arm irq */ +#define RK_MMU_INT_MASK0x1C
[PATCH 2/3] dt-bindings: iommu: Add documentation for rockchip iommu
Add binding documentation for Rockchip IOMMU. Signed-off-by: Daniel Kurtz Signed-off-by: Simon Xue --- .../devicetree/bindings/iommu/rockchip,iommu.txt | 26 ++ 1 file changed, 26 insertions(+) create mode 100644 Documentation/devicetree/bindings/iommu/rockchip,iommu.txt diff --git a/Documentation/devicetree/bindings/iommu/rockchip,iommu.txt b/Documentation/devicetree/bindings/iommu/rockchip,iommu.txt new file mode 100644 index 000..810e058 --- /dev/null +++ b/Documentation/devicetree/bindings/iommu/rockchip,iommu.txt @@ -0,0 +1,26 @@ +Rockchip IOMMU +== + +A Rockchip DRM iommu translates io virtual addresses to physical addresses for +its master device. Each slave device is bound to a single master device, and +shares its clocks, power domain and irq. + +Required properties: +- compatible : Should be "rockchip,iommu" +- reg : Address space for the configuration registers +- interrupts : Interrupt specifier for the IOMMU instance +- interrupt-names : Interrupt name for the IOMMU instance +- #iommu-cells: Should be <0>. This indicates the iommu is a +"single-master" device, and needs no additional information +to associate with its master device. See: +Documentation/devicetree/bindings/iommu/iommu.txt + +Example: + + vopl_mmu: iommu@0xff940300 { + compatible = "rockchip,iommu"; + reg = <0xff940300 0x100>; + interrupts = ; + interrupt-names = "vopl_mmu"; + #iommu-cells = <0>; + }; -- 2.1.0.rc2.206.gedb03e5 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [RFC 09/10] drm/tegra: Add IOMMU support
On Thu, Jun 26, 2014 at 4:49 PM, Thierry Reding wrote: > From: Thierry Reding > > When an IOMMU device is available on the platform bus, allocate an IOMMU > domain and attach the display controllers to it. The display controllers > can then scan out non-contiguous buffers by mapping them through the > IOMMU. > Hi Thierry, A few comments from Stéphane and myself that came up while we were reviewing this for our tree. > Signed-off-by: Thierry Reding > --- > drivers/gpu/drm/tegra/dc.c | 21 > drivers/gpu/drm/tegra/drm.c | 17 > drivers/gpu/drm/tegra/drm.h | 3 + > drivers/gpu/drm/tegra/fb.c | 16 ++- > drivers/gpu/drm/tegra/gem.c | 236 > +++- > drivers/gpu/drm/tegra/gem.h | 4 + > 6 files changed, 273 insertions(+), 24 deletions(-) > > diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c > index afcca04f5367..0f7452d04811 100644 > --- a/drivers/gpu/drm/tegra/dc.c > +++ b/drivers/gpu/drm/tegra/dc.c > @@ -9,6 +9,7 @@ > > #include > #include > +#include > #include > > #include "dc.h" > @@ -1283,8 +1284,18 @@ static int tegra_dc_init(struct host1x_client *client) > { > struct drm_device *drm = dev_get_drvdata(client->parent); > struct tegra_dc *dc = host1x_client_to_dc(client); > + struct tegra_drm *tegra = drm->dev_private; > int err; > > + if (tegra->domain) { > + err = iommu_attach_device(tegra->domain, dc->dev); > + if (err < 0) { > + dev_err(dc->dev, "failed to attach to IOMMU: %d\n", > + err); > + return err; > + } [from Stéphane] shouldn't we call detach in the error paths below? > + } > + > drm_crtc_init(drm, &dc->base, &tegra_crtc_funcs); > drm_mode_crtc_set_gamma_size(&dc->base, 256); > drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs); > @@ -1318,7 +1329,9 @@ static int tegra_dc_init(struct host1x_client *client) > > static int tegra_dc_exit(struct host1x_client *client) > { > + struct drm_device *drm = dev_get_drvdata(client->parent); > struct tegra_dc *dc = host1x_client_to_dc(client); > + struct tegra_drm *tegra = drm->dev_private; > int err; > > devm_free_irq(dc->dev, dc->irq, dc); > @@ -1335,6 +1348,8 @@ static int tegra_dc_exit(struct host1x_client *client) > return err; > } > > + iommu_detach_device(tegra->domain, dc->dev); > + > return 0; > } > > @@ -1462,6 +1477,12 @@ static int tegra_dc_probe(struct platform_device *pdev) > return -ENXIO; > } > > + err = iommu_attach(&pdev->dev); > + if (err < 0) { > + dev_err(&pdev->dev, "failed to attach to IOMMU: %d\n", err); > + return err; > + } > + > INIT_LIST_HEAD(&dc->client.list); > dc->client.ops = &dc_client_ops; > dc->client.dev = &pdev->dev; > diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c > index 59736bb810cd..1d2bbafad982 100644 > --- a/drivers/gpu/drm/tegra/drm.c > +++ b/drivers/gpu/drm/tegra/drm.c > @@ -8,6 +8,7 @@ > */ > > #include > +#include > > #include "drm.h" > #include "gem.h" > @@ -33,6 +34,16 @@ static int tegra_drm_load(struct drm_device *drm, unsigned > long flags) > if (!tegra) > return -ENOMEM; > > + if (iommu_present(&platform_bus_type)) { > + tegra->domain = iommu_domain_alloc(&platform_bus_type); > + if (IS_ERR(tegra->domain)) { > + kfree(tegra); > + return PTR_ERR(tegra->domain); > + } > + > + drm_mm_init(&tegra->mm, 0, SZ_2G); [from Stéphane]: none of these are freed in the error path below (iommu_domain_free and drm_mm_takedown) also |tegra| isn't freed either? > + } > + > mutex_init(&tegra->clients_lock); > INIT_LIST_HEAD(&tegra->clients); > drm->dev_private = tegra; > @@ -71,6 +82,7 @@ static int tegra_drm_load(struct drm_device *drm, unsigned > long flags) > static int tegra_drm_unload(struct drm_device *drm) > { > struct host1x_device *device = to_host1x_device(drm->dev); > + struct tegra_drm *tegra = drm->dev_private; > int err; > > drm_kms_helper_poll_fini(drm); > @@ -82,6 +94,11 @@ static int tegra_drm_unload(struct drm_device *drm) > if (err < 0) > return err; > > + if (tegra->domain) { > + iommu_domain_free(tegra->domain); > + drm_mm_takedown(&tegra->mm); > + } > + > return 0; > } > > diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h > index 96d754e7b3eb..a07c796b7edc 100644 > --- a/drivers/gpu/drm/tegra/drm.h > +++ b/drivers/gpu/drm/tegra/drm.h > @@ -39,6 +39,9 @@ struct tegra_fbdev { > struct tegra_drm { > struct drm_device *drm; > > +
[PATCH 3/3] ARM: dts: rk3288: add VOP iommu nodes
Add device nodes for the VOP iommus. Device nodes for other iommus will be added in later patches. The iommu nodes use the #iommu-cells property as described in: Documentation/devicetree/bindings/iommu/iommu.txt Signed-off-by: Daniel Kurtz Signed-off-by: Simon Xue --- arch/arm/boot/dts/rk3288.dtsi | 18 ++ 1 file changed, 18 insertions(+) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 5950b0a..cbc92fa 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -271,6 +271,24 @@ status = "disabled"; }; + vopb_mmu: iommu@0xff930300 { + compatible = "rockchip,iommu"; + reg = <0xff930300 0x100>; + interrupts = ; + interrupt-names = "vopb_mmu"; + #iommu-cells = <0>; + status = "disabled"; + }; + + vopl_mmu: iommu@0xff940300 { + compatible = "rockchip,iommu"; + reg = <0xff940300 0x100>; + interrupts = ; + interrupt-names = "vopl_mmu"; + #iommu-cells = <0>; + status = "disabled"; + }; + gic: interrupt-controller@ffc01000 { compatible = "arm,gic-400"; interrupt-controller; -- 2.1.0.rc2.206.gedb03e5 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 0/3] Rockchip IOMMU driver and devicetree bindings
Add a driver and devicetree bindings for the IOMMU found in Rockchip RK3288 SoCs. Daniel Kurtz (3): iommu/rockchip: rk3288 iommu driver dt-bindings: iommu: Add documentation for rockchip iommu ARM: dts: rk3288: add VOP iommu nodes .../devicetree/bindings/iommu/rockchip,iommu.txt | 26 + arch/arm/boot/dts/rk3288.dtsi | 18 + drivers/iommu/Kconfig | 11 + drivers/iommu/Makefile | 1 + drivers/iommu/rockchip-iommu.c | 924 + 5 files changed, 980 insertions(+) create mode 100644 Documentation/devicetree/bindings/iommu/rockchip,iommu.txt create mode 100644 drivers/iommu/rockchip-iommu.c -- 2.1.0.rc2.206.gedb03e5 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v3 0/5] enhance DMA CMA on x86
On Tue, Sep 30, 2014 at 09:49:54PM -0400, Peter Hurley wrote: > On 09/30/2014 07:45 PM, Thomas Gleixner wrote: > > Whether the proposed patchset is the correct solution to support it is > > a completely different question. > > This patchset has been in mainline since 3.16 and has already caused > regressions, so the question of whether this is the correct solution has > already been answered. > > > So either you stop this right now and help Akinobu to find the proper > > solution > > If this is only a test platform for ARM parts then I don't think it > unreasonable to suggest forking x86 swiotlb support into a iommu=cma Not sure what you mean by 'forking x86 swiotlb' ? As in have SWIOTLB work under ARM? > selector that gets DMA mapping working for this test platform and doesn't > cause a bunch of breakage. I think you might want to take a look at the IOMMU_DETECT macros and enable CMA there only if the certain devices are available. That way the normal flow of detecting which IOMMU to use is still present and will turn of CMA if there is no device that would use it. > > Which is different than if the plan is to ship production units for x86; > then a general purpose solution will be required. > > As to the good design of a general purpose solution for allocating and > mapping huge order pages, you are certainly more qualified to help Akinobu > than I am. > > Regards, > Peter Hurley > ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 0/2] iommu/vt-d: Make RMRR matching compatible with older kernels
Hi, here is a patch-set to make RMRR matching in the Intel IOMMU driver compatible with older kernels. This is needed because some BIOS vendors build RMRR entries to work with older kernels, but that will break on newer ones that implement the correct PCI device scope matching scheme defined in the VT-d specification. Make the current Intel IOMMU driver work with the old RMRR entries too. These patches have been tested in an affected system and fix the issue seen there (newer kernel did not setup RMRR entries for a plugged in device). Regards, Joerg Joerg Roedel (2): iommu/vt-d: Store bus information in RMRR PCI device path iommu/vt-d: Work around broken RMRR firmware entries drivers/iommu/dmar.c | 23 --- include/linux/dmar.h | 8 +++- 2 files changed, 27 insertions(+), 4 deletions(-) -- 1.9.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 2/2] iommu/vt-d: Work around broken RMRR firmware entries
From: Joerg Roedel The VT-d specification states that an RMRR entry in the DMAR table needs to specify the full path to the device. This is also how newer Linux kernels implement it. Unfortunatly older drivers just match for the target device and not the full path to the device, so that BIOS vendors implement that behavior into their BIOSes to make them work with older Linux kernels. But those RMRR entries break on newer Linux kernels. Work around this issue by adding a fall-back into the RMRR matching code to match those old RMRR entries too. Signed-off-by: Joerg Roedel --- drivers/iommu/dmar.c | 22 +++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 6ba28b0..371ff33 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -178,17 +178,33 @@ static bool dmar_match_pci_path(struct dmar_pci_notify_info *info, int bus, int i; if (info->bus != bus) - return false; + goto fallback; if (info->level != count) - return false; + goto fallback; for (i = 0; i < count; i++) { if (path[i].device != info->path[i].device || path[i].function != info->path[i].function) - return false; + goto fallback; } return true; + +fallback: + + if (count != 1) + return false; + + i = info->level - 1; + if (bus == info->path[i].bus && + path[0].device == info->path[i].device && + path[0].function == info->path[i].function) { + pr_info(FW_BUG "RMRR entry for device %02x:%02x.%x is broken - applying workaround\n", + bus, path[0].device, path[0].function); + return true; + } + + return false; } /* Return: > 0 if match found, 0 if no match found, < 0 if error happens */ -- 1.9.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 1/2] iommu/vt-d: Store bus information in RMRR PCI device path
From: Joerg Roedel This will be used later to match broken RMRR entries. Signed-off-by: Joerg Roedel --- drivers/iommu/dmar.c | 1 + include/linux/dmar.h | 8 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 06d268a..6ba28b0 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -155,6 +155,7 @@ dmar_alloc_pci_notify_info(struct pci_dev *dev, unsigned long event) if (event == BUS_NOTIFY_ADD_DEVICE) { for (tmp = dev; tmp; tmp = tmp->bus->self) { level--; + info->path[level].bus = tmp->bus->number; info->path[level].device = PCI_SLOT(tmp->devfn); info->path[level].function = PCI_FUNC(tmp->devfn); if (pci_is_root_bus(tmp->bus)) diff --git a/include/linux/dmar.h b/include/linux/dmar.h index 1deece4..593fff9 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h @@ -56,13 +56,19 @@ struct dmar_drhd_unit { struct intel_iommu *iommu; }; +struct dmar_pci_path { + u8 bus; + u8 device; + u8 function; +}; + struct dmar_pci_notify_info { struct pci_dev *dev; unsigned long event; int bus; u16 seg; u16 level; - struct acpi_dmar_pci_path path[]; + struct dmar_pci_pathpath[]; } __attribute__((packed)); extern struct rw_semaphore dmar_global_lock; -- 1.9.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 0/2] iommu/vt-d: Keep RMRR mappings around on driver unbind
On Wed, Oct 01, 2014 at 03:35:10PM -0700, Greg Kroah-Hartman wrote: > I have no objection to these, do you want me to take them through my > tree? Or if they are going through some other one feel free to add: > > Acked-by: Greg Kroah-Hartman > > To the first patch. Thanks Greg! I added the patches to the IOMMU tree. Joerg ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [RFC 09/10] drm/tegra: Add IOMMU support
On Wed, Oct 01, 2014 at 11:54:11AM -0400, Sean Paul wrote: > On Tue, Sep 30, 2014 at 2:48 PM, Sean Paul wrote: > > On Thu, Jun 26, 2014 at 4:49 PM, Thierry Reding > > wrote: > >> From: Thierry Reding > >> > >> When an IOMMU device is available on the platform bus, allocate an IOMMU > >> domain and attach the display controllers to it. The display controllers > >> can then scan out non-contiguous buffers by mapping them through the > >> IOMMU. > >> > > > > Hi Thierry, > > A few comments from Stéphane and myself that came up while we were > > reviewing this for our tree. > > > >> Signed-off-by: Thierry Reding > >> --- > >> drivers/gpu/drm/tegra/dc.c | 21 > >> drivers/gpu/drm/tegra/drm.c | 17 > >> drivers/gpu/drm/tegra/drm.h | 3 + > >> drivers/gpu/drm/tegra/fb.c | 16 ++- > >> drivers/gpu/drm/tegra/gem.c | 236 > >> +++- > >> drivers/gpu/drm/tegra/gem.h | 4 + > >> 6 files changed, 273 insertions(+), 24 deletions(-) > >> > >> diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c > >> index afcca04f5367..0f7452d04811 100644 > >> --- a/drivers/gpu/drm/tegra/dc.c > >> +++ b/drivers/gpu/drm/tegra/dc.c > >> @@ -9,6 +9,7 @@ > >> > >> #include > >> #include > >> +#include > >> #include > >> > >> #include "dc.h" > >> @@ -1283,8 +1284,18 @@ static int tegra_dc_init(struct host1x_client > >> *client) > >> { > >> struct drm_device *drm = dev_get_drvdata(client->parent); > >> struct tegra_dc *dc = host1x_client_to_dc(client); > >> + struct tegra_drm *tegra = drm->dev_private; > >> int err; > >> > >> + if (tegra->domain) { > >> + err = iommu_attach_device(tegra->domain, dc->dev); > >> + if (err < 0) { > >> + dev_err(dc->dev, "failed to attach to IOMMU: %d\n", > >> + err); > >> + return err; > >> + } > > > > [from Stéphane] > > > > shouldn't we call detach in the error paths below? > > > > > >> + } > >> + > >> drm_crtc_init(drm, &dc->base, &tegra_crtc_funcs); > >> drm_mode_crtc_set_gamma_size(&dc->base, 256); > >> drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs); > >> @@ -1318,7 +1329,9 @@ static int tegra_dc_init(struct host1x_client > >> *client) > >> > >> static int tegra_dc_exit(struct host1x_client *client) > >> { > >> + struct drm_device *drm = dev_get_drvdata(client->parent); > >> struct tegra_dc *dc = host1x_client_to_dc(client); > >> + struct tegra_drm *tegra = drm->dev_private; > >> int err; > >> > >> devm_free_irq(dc->dev, dc->irq, dc); > >> @@ -1335,6 +1348,8 @@ static int tegra_dc_exit(struct host1x_client > >> *client) > >> return err; > >> } > >> > >> + iommu_detach_device(tegra->domain, dc->dev); > >> + > >> return 0; > >> } > >> > >> @@ -1462,6 +1477,12 @@ static int tegra_dc_probe(struct platform_device > >> *pdev) > >> return -ENXIO; > >> } > >> > >> + err = iommu_attach(&pdev->dev); > >> + if (err < 0) { > >> + dev_err(&pdev->dev, "failed to attach to IOMMU: %d\n", > >> err); > >> + return err; > >> + } > >> + > >> INIT_LIST_HEAD(&dc->client.list); > >> dc->client.ops = &dc_client_ops; > >> dc->client.dev = &pdev->dev; > >> diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c > >> index 59736bb810cd..1d2bbafad982 100644 > >> --- a/drivers/gpu/drm/tegra/drm.c > >> +++ b/drivers/gpu/drm/tegra/drm.c > >> @@ -8,6 +8,7 @@ > >> */ > >> > >> #include > >> +#include > >> > >> #include "drm.h" > >> #include "gem.h" > >> @@ -33,6 +34,16 @@ static int tegra_drm_load(struct drm_device *drm, > >> unsigned long flags) > >> if (!tegra) > >> return -ENOMEM; > >> > >> + if (iommu_present(&platform_bus_type)) { > >> + tegra->domain = iommu_domain_alloc(&platform_bus_type); > >> + if (IS_ERR(tegra->domain)) { > >> + kfree(tegra); > >> + return PTR_ERR(tegra->domain); > >> + } > >> + > >> + drm_mm_init(&tegra->mm, 0, SZ_2G); > > > > > > [from Stéphane]: > > > > none of these are freed in the error path below (iommu_domain_free and > > drm_mm_takedown) > > > > also |tegra| isn't freed either? > > > > > > > >> + } > >> + > >> mutex_init(&tegra->clients_lock); > >> INIT_LIST_HEAD(&tegra->clients); > >> drm->dev_private = tegra; > >> @@ -71,6 +82,7 @@ static int tegra_drm_load(struct drm_device *drm, > >> unsigned long flags) > >> static int tegra_drm_unload(struct drm_device *drm) > >> { > >> struct host1x_device *device = to_host1x_device(drm->dev); > >> + struct tegra_drm *tegra = drm->dev_private; > >> int err; > >> > >> drm_kms_helper_poll_fini(drm); > >> @@