Re: [PATCH v3 0/5] enhance DMA CMA on x86

2014-10-02 Thread Akinobu Mita
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

2014-10-02 Thread 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:
>>> 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

2014-10-02 Thread Sean Paul
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

2014-10-02 Thread Daniel Kurtz
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

2014-10-02 Thread Daniel Kurtz
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

2014-10-02 Thread Sean Paul
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

2014-10-02 Thread Daniel Kurtz
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

2014-10-02 Thread Daniel Kurtz
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

2014-10-02 Thread Konrad Rzeszutek Wilk
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

2014-10-02 Thread Joerg Roedel
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

2014-10-02 Thread Joerg Roedel
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

2014-10-02 Thread Joerg Roedel
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

2014-10-02 Thread Joerg Roedel
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

2014-10-02 Thread Thierry Reding
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);
> >> @@