Re: [PATCH 1/2] iommu: call detach also for default_domain before attaching to new one

2016-02-16 Thread Marek Szyprowski

Hello,

On 2016-02-16 16:59, Joerg Roedel wrote:

On Tue, Feb 16, 2016 at 03:40:31PM +0100, Marek Szyprowski wrote:

This patch ensures that devices attached to the default_domain will be
first detached from it before attaching to new domain. To avoid forward
declaration, __iommu_attach_group() function has been moved to new place
in the source code.

Actually it was intentional to not invoke the detach_device call-back in
the attach_device path.

The reason is that detaching first and than attaching again leaves the
device without a domain for a short period of time, until it is attached
to the new domain.

The attach_device call-back is supposed to handle this situation and
just silently overwrite any other domain->device binding it finds for
the device.

This allows to do re-attachment with less iommu flushes and to get rid
of the detach_device call-back at some point.


Huh, I wasn't aware of this change in the iommu drivers api. For some
drivers attach/detach callbacks does something more than just programming
page table base register, like for example in case of exynos iommu it is
enabling runtime power management and clocks. The code is really much 
simpler
if those calls are balanced, but if the goal is to allow multiple 
unballanced

attach calls, I will try to fix this in our driver.

Maybe it should be documented somewhere, that attach calls can be 
unbalanced?


Best regards
--
Marek Szyprowski, PhD
Samsung R Institute Poland

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 11/11] iommu: exynos: add Maintainers entry for Exynos SYSMMU driver

2016-02-16 Thread Krzysztof Kozlowski
On 16.02.2016 23:57, Marek Szyprowski wrote:
> Add Marek Szyprowski as maintainer for Exynos IOMMU driver.
> 
> Signed-off-by: Marek Szyprowski 
> ---
>  MAINTAINERS | 6 ++
>  1 file changed, 6 insertions(+)
> 

Acked-by: Krzysztof Kozlowski 

Best regards,
Krzysztof


> diff --git a/MAINTAINERS b/MAINTAINERS
> index 7bd927e..1e9c4df 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -4336,6 +4336,12 @@ L: dri-de...@lists.freedesktop.org
>  S:   Maintained
>  F:   drivers/gpu/drm/exynos/exynos_dp*
>  
> +EXYNOS SYSMMU (IOMMU) driver
> +M:   Marek Szyprowski 
> +L:   iommu@lists.linux-foundation.org
> +S:   Maintained
> +F:   drivers/iommu/exynos-iommu.c
> +
>  EXYNOS MIPI DISPLAY DRIVERS
>  M:   Inki Dae 
>  M:   Donghwa Lee 
> 

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [RFC PATCH 1/2] PCI: Add PCI device flag PCI_DEV_FLAGS_BRIDGE_SKIP_ALIAS

2016-02-16 Thread Alex Williamson
On Wed, 17 Feb 2016 02:38:24 +0530
Jayachandran Chandrashekaran Nair
 wrote:

> On Tue, Feb 16, 2016 at 1:09 AM, Alex Williamson
>  wrote:
> > On Mon, 15 Feb 2016 12:20:23 -0600
> > Bjorn Helgaas  wrote:
> >  
> >> [+cc Alex, iommu list]
> >>
> >> On Mon, Feb 15, 2016 at 03:35:00AM +0530, Jayachandran C wrote:  
> >> > Add a new flag PCI_DEV_FLAGS_BRIDGE_SKIP_ALIAS to indicate bridges
> >> > that should not be considered during DMA alias search. This is
> >> > to support hardware (in this case Broadcom Vulcan PCIe subsystem)
> >> > that has internal bridges which have either missing or wrong PCIe
> >> > capabilities.  
> >
> > I figured this would come at some point, the right answer is of course
> > to follow the PCIe spec and implement the required PCIe capability in
> > the hardware.  
> 
> There are  PCIe controllers on the chip that follows the spec, the issue is
> how it is integrated to the northbridge (equivalent) on the chip, I have
> tried to explain it below.
> 
> >> This needs more explanation, like what exactly is wrong with this
> >> device?  A missing PCIe capability might cause other problems.
> >>
> >> What problem does this fix?  Without these patches, do we merely add
> >> aliases that are unnecessary?  Do we crash because something goes
> >> wrong in the pci_pcie_type() switch because of the incorrect
> >> capability?  
> 
> Here's how (for example) how the PCI enumeration of a 2 node Vulcan
> processor will look like:
> 
> 
> [0] +-0.0.0--[1]---+--1.a.0[2]-2.0.0---[3]3.0.0
> |  +--1.a.1[4]-4.0.0---[5]5.0.0
> |  .
> |  ... etc...
> |
> +-0.0.1--[10]--+-10.a.0[11]---11.0.0---[12]---12.0.0
>+-10.a.1[13]---13.0.0---[14]---14.0.0
>.
>... etc...

So we have:

"Glue Bridge"---"Glue Bridges"---Root Ports---Endpoints
  (no pcie)  (pci/x-pcie)

> 
> The devices 0.0.x and x.a.x are glue bridges that are there to
> bring the real PCIe controllers (pcie cap type 4) 2.0.0, 4.0.0,
> 11.0.0, 13.0.0 under a single PCI hierarchy. The x.a.x bridges
> have a PCIe capability (type 8) and 0.0.x does not have any pcie
> capability.
> 
> In case of Vulcan, both the GICv3 ITS driver code and the SMMUv3
> driver code does dma alias walk to find the device id to use
> in ITS and SMMU. In both cases it will ignore the x.0.0 bridges
> since they are type root port, but will continue on up and end
> up with incorrect device id.
> 
> The flag I have added is to make the pci_for_each_dma_alias()
> ignore the last 2 levels of glue/internal bridges.

Per the PCIe spec, I'm not even sure what you have is a valid
hierarchy, root ports sit on root complexes, not behind a PCI-to-PCIe
bridge.  So really you're pretending that the downstream "glue bridge"
is your host bridge and therefore root complex, but the PCI topology
would clearly dictate that the top-most bus is conventional PCI and
therefore everything is an alias of everything else and the DMA alias
code is doing exactly what it should.

Also note that the caller of pci_for_each_dma_alias() owns the callback
function triggered for each alias, that function could choose to prune
out these "glue bridges" itself if that's the appropriate thing to do.
Where do the SMMU and ITS actually reside in the above diagram?  You
can use the callout function to stop the traversal anywhere you wish,
it's free to return a -errno to stop or positive number, which the
caller can interpret as error or non-failure stop condition.

You could even think about changing what Linux considers to be the host
bridge.  Maybe these glue bridges shouldn't even be visible to Linux,
would that also solve the issue with the broken BAR?

> > The change takes the same code path as it would for a real PCIe bridge
> > port (downstream/upstream/root), which means they want to skip adding
> > this bridge as an alias of the device.  So we're adding in aliases that
> > don't exist, the bridge itself.
> >
> > If anything I'd suggest a flag that actually tries to address the
> > problem rather than a symptom of the problem.  For example, maybe the
> > flag should be PCI_DEV_FLAGS_IS_PCIE.  Maybe pci_is_pcie() should even
> > take that into account.  That has some trickle through for
> > pci_pcie_type() and all the accessor functions, but maybe it's a
> > cleaner solution overall (or maybe it explodes further).  Thanks,  
> 
> I didn't really want to mark the glue bridges as PCIe or have fake
> PCIe capability there, the obvious simple solution was to add
> the flag PCI_DEV_FLAGS_BRIDGE_SKIP_ALIAS
> 
> Any suggestions/comments on how to do this better would be welcome.

I definitely don't think either flag idea is the right solution, I
think you've actually already got the tools you need to solve it by
putting the intelligence in the callback function or by going 

Re: [RFC PATCH 1/2] PCI: Add PCI device flag PCI_DEV_FLAGS_BRIDGE_SKIP_ALIAS

2016-02-16 Thread Jayachandran Chandrashekaran Nair
On Tue, Feb 16, 2016 at 1:09 AM, Alex Williamson
 wrote:
> On Mon, 15 Feb 2016 12:20:23 -0600
> Bjorn Helgaas  wrote:
>
>> [+cc Alex, iommu list]
>>
>> On Mon, Feb 15, 2016 at 03:35:00AM +0530, Jayachandran C wrote:
>> > Add a new flag PCI_DEV_FLAGS_BRIDGE_SKIP_ALIAS to indicate bridges
>> > that should not be considered during DMA alias search. This is
>> > to support hardware (in this case Broadcom Vulcan PCIe subsystem)
>> > that has internal bridges which have either missing or wrong PCIe
>> > capabilities.
>
> I figured this would come at some point, the right answer is of course
> to follow the PCIe spec and implement the required PCIe capability in
> the hardware.

There are  PCIe controllers on the chip that follows the spec, the issue is
how it is integrated to the northbridge (equivalent) on the chip, I have
tried to explain it below.

>> This needs more explanation, like what exactly is wrong with this
>> device?  A missing PCIe capability might cause other problems.
>>
>> What problem does this fix?  Without these patches, do we merely add
>> aliases that are unnecessary?  Do we crash because something goes
>> wrong in the pci_pcie_type() switch because of the incorrect
>> capability?

Here's how (for example) how the PCI enumeration of a 2 node Vulcan
processor will look like:


[0] +-0.0.0--[1]---+--1.a.0[2]-2.0.0---[3]3.0.0
|  +--1.a.1[4]-4.0.0---[5]5.0.0
|  .
|  ... etc...
|
+-0.0.1--[10]--+-10.a.0[11]---11.0.0---[12]---12.0.0
   +-10.a.1[13]---13.0.0---[14]---14.0.0
   .
   ... etc...

The devices 0.0.x and x.a.x are glue bridges that are there to
bring the real PCIe controllers (pcie cap type 4) 2.0.0, 4.0.0,
11.0.0, 13.0.0 under a single PCI hierarchy. The x.a.x bridges
have a PCIe capability (type 8) and 0.0.x does not have any pcie
capability.

In case of Vulcan, both the GICv3 ITS driver code and the SMMUv3
driver code does dma alias walk to find the device id to use
in ITS and SMMU. In both cases it will ignore the x.0.0 bridges
since they are type root port, but will continue on up and end
up with incorrect device id.

The flag I have added is to make the pci_for_each_dma_alias()
ignore the last 2 levels of glue/internal bridges.

> The change takes the same code path as it would for a real PCIe bridge
> port (downstream/upstream/root), which means they want to skip adding
> this bridge as an alias of the device.  So we're adding in aliases that
> don't exist, the bridge itself.
>
> If anything I'd suggest a flag that actually tries to address the
> problem rather than a symptom of the problem.  For example, maybe the
> flag should be PCI_DEV_FLAGS_IS_PCIE.  Maybe pci_is_pcie() should even
> take that into account.  That has some trickle through for
> pci_pcie_type() and all the accessor functions, but maybe it's a
> cleaner solution overall (or maybe it explodes further).  Thanks,

I didn't really want to mark the glue bridges as PCIe or have fake
PCIe capability there, the obvious simple solution was to add
the flag PCI_DEV_FLAGS_BRIDGE_SKIP_ALIAS

Any suggestions/comments on how to do this better would be welcome.

Thanks,
JC.
[Using gmail due to IT transition, hope the ascii art makes it thru]
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v4 3/8] dma-mapping: add dma_{map,unmap}_resource

2016-02-16 Thread Niklas Söderlund
Map/Unmap a device resource from a physical address. If no dma_map_ops
method is available the operation is a no-op.

Signed-off-by: Niklas Söderlund 
---
 include/linux/dma-mapping.h | 32 
 1 file changed, 32 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index e3aba4e..cc305d1 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -216,6 +216,38 @@ static inline void dma_unmap_page(struct device *dev, 
dma_addr_t addr,
debug_dma_unmap_page(dev, addr, size, dir, false);
 }
 
+static inline dma_addr_t dma_map_resource(struct device *dev,
+ phys_addr_t phys_addr,
+ size_t size,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+   struct dma_map_ops *ops = get_dma_ops(dev);
+   unsigned long pfn = __phys_to_pfn(phys_addr);
+
+   BUG_ON(!valid_dma_direction(dir));
+
+   /* Don't allow RAM to be mapped */
+   BUG_ON(pfn_valid(pfn));
+
+   if (ops->map_resource)
+   return ops->map_resource(dev, phys_addr, size, dir, attrs);
+
+   return phys_addr;
+}
+
+static inline void dma_unmap_resource(struct device *dev, dma_addr_t addr,
+ size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+   struct dma_map_ops *ops = get_dma_ops(dev);
+
+   BUG_ON(!valid_dma_direction(dir));
+   if (ops->unmap_resource)
+   ops->unmap_resource(dev, addr, size, dir, attrs);
+
+}
+
 static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
   size_t size,
   enum dma_data_direction dir)
-- 
2.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v4 2/8] dma-mapping: add {map,unmap}_resource to dma_map_ops

2016-02-16 Thread Niklas Söderlund
Add methods to handle mapping of device resources from a physical
address. This is needed for example to be able to map MMIO FIFO
registers to a IOMMU.

Signed-off-by: Niklas Söderlund 
Reviewed-by: Laurent Pinchart 
---
 include/linux/dma-mapping.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 75857cd..e3aba4e 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -49,6 +49,12 @@ struct dma_map_ops {
 struct scatterlist *sg, int nents,
 enum dma_data_direction dir,
 struct dma_attrs *attrs);
+   dma_addr_t (*map_resource)(struct device *dev, phys_addr_t phys_addr,
+  size_t size, enum dma_data_direction dir,
+  struct dma_attrs *attrs);
+   void (*unmap_resource)(struct device *dev, dma_addr_t dma_handle,
+  size_t size, enum dma_data_direction dir,
+  struct dma_attrs *attrs);
void (*sync_single_for_cpu)(struct device *dev,
dma_addr_t dma_handle, size_t size,
enum dma_data_direction dir);
-- 
2.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v4 0/8] dmaengine: rcar-dmac: add iommu support for slave transfers

2016-02-16 Thread Niklas Söderlund
Hi,

This series add iommu support to rcar-dmac. It's tested on Koelsch with
CONFIG_IPMMU_VMSA and by enabling the ipmmu_ds node in r8a7791.dtsi. I verified
operation by interacting with /dev/mmcblk1  which is a device behind the iommu.

The series depends on out of tree patch '[PATCH] dmaengine: use phys_addr_t for
slave configuration' which Vinod now have moved forward whit, thanks!

* Changes since v3
- Folded in a fix from Robin to his patch.
- Added a check to make sure dma_map_resource can not be used to map RAM as
  pointed out by Robin. I use BUG_ON to enforce this. It might not be the best
  method but I saw no other good way since DMA_ERROR_CODE might not be defined
  on all platforms.
- Added comment about that DTS changes will disable 2 DMA channels due to a HW
  (?) but in the DMAC.
- Dropped the use of dma_attrs, no longer needed.
- Collected Acked-by and Reviewed-by from Laurent.
- Various indentation fix ups.

* Changes since v2
- Drop patch to add dma_{map,unmap}_page_attrs.
- Add dma_{map,unmap}_resource to handle the mapping without involving a
  'struct page'. Thanks Laurent and Robin for pointing this out.
- Use size instead of address to keep track of if a mapping exist or not
  since addr == 0 is valid. Thanks Laurent.
- Pick up patch from Robin with Laurents ack (hope it's OK for me to
  attach the ack?) to add IOMMU_MMIO.
- Fix bug in rcar_dmac_device_config where the error check where
  inverted.
- Use DMA_BIDIRECTIONAL in rcar_dmac_device_config since we at that
  point can't be sure what direction the mapping is going to be used.

* Changes since v1
- Add and use a dma_{map,unmap}_page_attrs to be able to map the page
  using attributes DMA_ATTR_NO_KERNEL_MAPPING and
  DMA_ATTR_SKIP_CPU_SYNC. Thanks Laurent.
- Drop check if dmac is part of a iommu group or not, let the DMA
  mapping api handle it.
- Move slave configuration data around in rcar-dmac to avoid code
  duplication.
- Fix build issue reported by 'kbuild test robot' regarding phys_to_page
  not availability on some configurations.
- Add DT information for r8a7791.

* Changes since RFC
- Switch to use the dma-mapping api instead of using the iommu_map()
  directly. Turns out the dma-mapper is much smarter then me...
- Dropped the patch to expose domain->ops->pgsize_bitmap from within the
  iommu api.
- Dropped the patch showing how I tested the RFC.


Niklas Söderlund (7):
  dma-mapping: add {map,unmap}_resource to dma_map_ops
  dma-mapping: add dma_{map,unmap}_resource
  arm: dma-mapping: add {map,unmap}_resource for iommu ops
  dmaengine: rcar-dmac: group slave configuration
  dmaengine: rcar-dmac: add iommu support for slave transfers
  ARM: dts: r8a7790: add iommus to dmac0 and dmac1
  ARM: dts: r8a7791: add iommus to dmac0 and dmac1

Robin Murphy (1):
  iommu: Add MMIO mapping type

 arch/arm/boot/dts/r8a7790.dtsi | 30 
 arch/arm/boot/dts/r8a7791.dtsi | 30 
 arch/arm/mm/dma-mapping.c  | 63 
 drivers/dma/sh/rcar-dmac.c | 81 +-
 drivers/iommu/io-pgtable-arm.c |  9 +++--
 include/linux/dma-mapping.h| 38 
 include/linux/iommu.h  |  1 +
 7 files changed, 233 insertions(+), 19 deletions(-)

--
2.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v4 4/8] arm: dma-mapping: add {map, unmap}_resource for iommu ops

2016-02-16 Thread Niklas Söderlund
Add methods to map/unmap device resources addresses for dma_map_ops that
are IOMMU aware. This is needed to map a device MMIO register from a
physical address.

Signed-off-by: Niklas Söderlund 
Reviewed-by: Laurent Pinchart 
---
 arch/arm/mm/dma-mapping.c | 63 +++
 1 file changed, 63 insertions(+)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 0eca381..ae2b175 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1814,6 +1814,63 @@ static void arm_iommu_unmap_page(struct device *dev, 
dma_addr_t handle,
__free_iova(mapping, iova, len);
 }
 
+/**
+ * arm_iommu_map_resource - map a device resource for DMA
+ * @dev: valid struct device pointer
+ * @phys_addr: physical address of resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static dma_addr_t arm_iommu_map_resource(struct device *dev,
+   phys_addr_t phys_addr, size_t size,
+   enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+   struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+   dma_addr_t dma_addr;
+   int ret, prot;
+   phys_addr_t addr = phys_addr & PAGE_MASK;
+   int offset = phys_addr & ~PAGE_MASK;
+   int len = PAGE_ALIGN(size + offset);
+
+   dma_addr = __alloc_iova(mapping, size);
+   if (dma_addr == DMA_ERROR_CODE)
+   return dma_addr;
+
+   prot = __dma_direction_to_prot(dir) | IOMMU_MMIO;
+
+   ret = iommu_map(mapping->domain, dma_addr, addr, len, prot);
+   if (ret < 0)
+   goto fail;
+
+   return dma_addr + offset;
+fail:
+   __free_iova(mapping, dma_addr, size);
+   return DMA_ERROR_CODE;
+}
+
+/**
+ * arm_iommu_unmap_resource - unmap a device DMA resource
+ * @dev: valid struct device pointer
+ * @dma_handle: DMA address to resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static void arm_iommu_unmap_resource(struct device *dev, dma_addr_t dma_handle,
+   size_t size, enum dma_data_direction dir,
+   struct dma_attrs *attrs)
+{
+   struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+   dma_addr_t iova = dma_handle & PAGE_MASK;
+   int offset = dma_handle & ~PAGE_MASK;
+   int len = PAGE_ALIGN(size + offset);
+
+   if (!iova)
+   return;
+
+   iommu_unmap(mapping->domain, iova, len);
+   __free_iova(mapping, iova, len);
+}
+
 static void arm_iommu_sync_single_for_cpu(struct device *dev,
dma_addr_t handle, size_t size, enum dma_data_direction dir)
 {
@@ -1858,6 +1915,9 @@ struct dma_map_ops iommu_ops = {
.sync_sg_for_cpu= arm_iommu_sync_sg_for_cpu,
.sync_sg_for_device = arm_iommu_sync_sg_for_device,
 
+   .map_resource   = arm_iommu_map_resource,
+   .unmap_resource = arm_iommu_unmap_resource,
+
.set_dma_mask   = arm_dma_set_mask,
 };
 
@@ -1873,6 +1933,9 @@ struct dma_map_ops iommu_coherent_ops = {
.map_sg = arm_coherent_iommu_map_sg,
.unmap_sg   = arm_coherent_iommu_unmap_sg,
 
+   .map_resource   = arm_iommu_map_resource,
+   .unmap_resource = arm_iommu_unmap_resource,
+
.set_dma_mask   = arm_dma_set_mask,
 };
 
-- 
2.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v4 7/8] ARM: dts: r8a7790: add iommus to dmac0 and dmac1

2016-02-16 Thread Niklas Söderlund
A unconfirmed hardware bug prevents channel 0 and 15 to be used by the
DMAC together with the IPMMU. The DMAC driver will disable the channels
reducing the effective number of channels to 14 per DMAC.

Signed-off-by: Niklas Söderlund 
Acked-by: Laurent Pinchart 
---
 arch/arm/boot/dts/r8a7790.dtsi | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index 7dfd393..048bbf8 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -294,6 +294,21 @@
power-domains = <_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+   iommus = <_ds 0>,
+<_ds 1>,
+<_ds 2>,
+<_ds 3>,
+<_ds 4>,
+<_ds 5>,
+<_ds 6>,
+<_ds 7>,
+<_ds 8>,
+<_ds 9>,
+<_ds 10>,
+<_ds 11>,
+<_ds 12>,
+<_ds 13>,
+<_ds 14>;
};
 
dmac1: dma-controller@e672 {
@@ -325,6 +340,21 @@
power-domains = <_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+   iommus = <_ds 15>,
+<_ds 16>,
+<_ds 17>,
+<_ds 18>,
+<_ds 19>,
+<_ds 20>,
+<_ds 21>,
+<_ds 22>,
+<_ds 23>,
+<_ds 24>,
+<_ds 25>,
+<_ds 26>,
+<_ds 27>,
+<_ds 28>,
+<_ds 29>;
};
 
audma0: dma-controller@ec70 {
-- 
2.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v4 6/8] dmaengine: rcar-dmac: add iommu support for slave transfers

2016-02-16 Thread Niklas Söderlund
Enable slave transfers to devices behind IPMMU:s by mapping the slave
addresses using the dma-mapping API.

Signed-off-by: Niklas Söderlund 
Reviewed-by: Laurent Pinchart 
---
 drivers/dma/sh/rcar-dmac.c | 52 +-
 1 file changed, 47 insertions(+), 5 deletions(-)

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 743873c..6a24847 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -1106,21 +1106,63 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
return desc;
 }
 
+static int rcar_dmac_set_slave_addr(struct dma_chan *chan,
+struct rcar_dmac_chan_slave *slave,
+phys_addr_t addr, size_t size)
+{
+   enum dma_data_direction dir;
+
+   /*
+* We can't know the direction at this time, see documentation for
+* 'direction' in struct dma_slave_config.
+*/
+   dir = DMA_BIDIRECTIONAL;
+
+   if (slave->xfer_size) {
+   dma_unmap_resource(chan->device->dev, slave->slave_addr,
+  slave->xfer_size, dir, NULL);
+   slave->slave_addr = 0;
+   slave->xfer_size = 0;
+   }
+
+   if (size) {
+   slave->slave_addr = dma_map_resource(chan->device->dev, addr,
+   size, dir, NULL);
+
+   if (dma_mapping_error(chan->device->dev, slave->slave_addr)) {
+   struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
+
+   dev_err(chan->device->dev,
+   "chan%u: failed to map %zx@%pap", rchan->index,
+   size, );
+   return -EIO;
+   }
+
+   slave->xfer_size = size;
+   }
+
+   return 0;
+}
+
 static int rcar_dmac_device_config(struct dma_chan *chan,
   struct dma_slave_config *cfg)
 {
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
+   int ret;
 
/*
 * We could lock this, but you shouldn't be configuring the
 * channel, while using it...
 */
-   rchan->src.slave_addr = cfg->src_addr;
-   rchan->dst.slave_addr = cfg->dst_addr;
-   rchan->src.xfer_size = cfg->src_addr_width;
-   rchan->dst.xfer_size = cfg->dst_addr_width;
 
-   return 0;
+   ret = rcar_dmac_set_slave_addr(chan, >src, cfg->src_addr,
+  cfg->src_addr_width);
+   if (ret)
+   return ret;
+
+   ret = rcar_dmac_set_slave_addr(chan, >dst, cfg->dst_addr,
+  cfg->dst_addr_width);
+   return ret;
 }
 
 static int rcar_dmac_chan_terminate_all(struct dma_chan *chan)
-- 
2.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v4 5/8] dmaengine: rcar-dmac: group slave configuration

2016-02-16 Thread Niklas Söderlund
Group slave address and transfer size in own structs for source and
destination. This is in preparation for hooking up the dma-mapping API
to the slave addresses.

Signed-off-by: Niklas Söderlund 
Reviewed-by: Laurent Pinchart 
---
 drivers/dma/sh/rcar-dmac.c | 37 +
 1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 7820d07..743873c 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -118,14 +118,21 @@ struct rcar_dmac_desc_page {
sizeof(struct rcar_dmac_xfer_chunk))
 
 /*
+ * @slave_addr: slave memory address
+ * @xfer_size: size (in bytes) of hardware transfers
+ */
+struct rcar_dmac_chan_slave {
+   dma_addr_t slave_addr;
+   unsigned int xfer_size;
+};
+
+/*
  * struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
  * @chan: base DMA channel object
  * @iomem: channel I/O memory base
  * @index: index of this channel in the controller
- * @src_xfer_size: size (in bytes) of hardware transfers on the source side
- * @dst_xfer_size: size (in bytes) of hardware transfers on the destination 
side
- * @src_slave_addr: slave source memory address
- * @dst_slave_addr: slave destination memory address
+ * @src: slave memory address and size on the source side
+ * @dst: slave memory address and size on the destination side
  * @mid_rid: hardware MID/RID for the DMA client using this channel
  * @lock: protects the channel CHCR register and the desc members
  * @desc.free: list of free descriptors
@@ -142,10 +149,8 @@ struct rcar_dmac_chan {
void __iomem *iomem;
unsigned int index;
 
-   unsigned int src_xfer_size;
-   unsigned int dst_xfer_size;
-   dma_addr_t src_slave_addr;
-   dma_addr_t dst_slave_addr;
+   struct rcar_dmac_chan_slave src;
+   struct rcar_dmac_chan_slave dst;
int mid_rid;
 
spinlock_t lock;
@@ -793,13 +798,13 @@ static void rcar_dmac_chan_configure_desc(struct 
rcar_dmac_chan *chan,
case DMA_DEV_TO_MEM:
chcr = RCAR_DMACHCR_DM_INC | RCAR_DMACHCR_SM_FIXED
 | RCAR_DMACHCR_RS_DMARS;
-   xfer_size = chan->src_xfer_size;
+   xfer_size = chan->src.xfer_size;
break;
 
case DMA_MEM_TO_DEV:
chcr = RCAR_DMACHCR_DM_FIXED | RCAR_DMACHCR_SM_INC
 | RCAR_DMACHCR_RS_DMARS;
-   xfer_size = chan->dst_xfer_size;
+   xfer_size = chan->dst.xfer_size;
break;
 
case DMA_MEM_TO_MEM:
@@ -1038,7 +1043,7 @@ rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct 
scatterlist *sgl,
}
 
dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src_slave_addr : rchan->dst_slave_addr;
+? rchan->src.slave_addr : rchan->dst.slave_addr;
return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
  dir, flags, false);
 }
@@ -1093,7 +1098,7 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
}
 
dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src_slave_addr : rchan->dst_slave_addr;
+? rchan->src.slave_addr : rchan->dst.slave_addr;
desc = rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
  dir, flags, true);
 
@@ -1110,10 +1115,10 @@ static int rcar_dmac_device_config(struct dma_chan 
*chan,
 * We could lock this, but you shouldn't be configuring the
 * channel, while using it...
 */
-   rchan->src_slave_addr = cfg->src_addr;
-   rchan->dst_slave_addr = cfg->dst_addr;
-   rchan->src_xfer_size = cfg->src_addr_width;
-   rchan->dst_xfer_size = cfg->dst_addr_width;
+   rchan->src.slave_addr = cfg->src_addr;
+   rchan->dst.slave_addr = cfg->dst_addr;
+   rchan->src.xfer_size = cfg->src_addr_width;
+   rchan->dst.xfer_size = cfg->dst_addr_width;
 
return 0;
 }
-- 
2.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: Can't boot new 4.4 kernel with IOMMU enabled

2016-02-16 Thread Mark Hounschell

On 02/16/2016 11:24 AM, Joerg Roedel wrote:

On Tue, Feb 02, 2016 at 10:49:11AM -0500, Mark Hounschell wrote:

Just wondering if this issue is still being considered?


Yes it is, I just went through a move and have a few other issues on the
plate. But I this is still on the list.





Thanks, I'll be standing by.

Mark

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: DMAR error messages after 'shutdown -r'.

2016-02-16 Thread Joerg Roedel
On Tue, Feb 09, 2016 at 02:59:00PM -0500, Valdis Kletnieks wrote:
> [0.027629] Freeing SMP alternatives memory: 28K (8e111000 - 
> 8e118000)
> [0.048199] ftrace: allocating 31090 entries in 122 pages
> [0.061837] DMAR: Host address width 36
> [0.061841] DMAR: DRHD base: 0x00fed9 flags: 0x1
> [0.061894] DMAR: dmar0: reg_base_addr fed9 ver 1:0 cap c9008020660262 
> ecap f0105a
> [0.061896] DMAR: RMRR base: 0x00cdb11000 end: 0x00cdb30fff
> [0.061899] DMAR-IR: IOAPIC id 2 under DRHD base  0xfed9 IOMMU 0
> [0.061901] DMAR-IR: HPET id 0 under DRHD base 0xfed9
> [0.061903] DMAR-IR: Queued invalidation will be enabled to support x2apic 
> and Intr-remapping.
>  Error here
> [0.062027] DMAR: DRHD: handling fault status reg 2
> [0.062034] DMAR: DMAR:[DMA Read] Request device [00:1f.2] fault addr 
> cdacd000
>DMAR:[fault reason 06] PTE Read access is not set
> 

This is probably from a missing RMRR entry for device 00:1f.2. Can you
please post full dmesg after boot?

Thanks,

Joerg
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v8 3/5] memory: mediatek: Add SMI driver

2016-02-16 Thread Will Deacon
On Tue, Feb 16, 2016 at 05:26:41PM +0100, Joerg Roedel wrote:
> On Tue, Feb 16, 2016 at 04:20:00PM +, Will Deacon wrote:
> > I'm more than happy to bake a branch containing all the page table stuff,
> > but Yong's stuff depends on it so I'll work with whatever is easiest for
> > you.
> 
> Okay, to the best is if you would collect all the page table patches and
> send me a pull-request. I pull that into my tree then and put Yong's
> stuff on-top.

Okey doke, I'll put something together this week.

Cheers,

Will
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v8 3/5] memory: mediatek: Add SMI driver

2016-02-16 Thread Joerg Roedel
On Tue, Feb 16, 2016 at 04:20:00PM +, Will Deacon wrote:
> I'm more than happy to bake a branch containing all the page table stuff,
> but Yong's stuff depends on it so I'll work with whatever is easiest for
> you.

Okay, to the best is if you would collect all the page table patches and
send me a pull-request. I pull that into my tree then and put Yong's
stuff on-top.



Joerg

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: Can't boot new 4.4 kernel with IOMMU enabled

2016-02-16 Thread Joerg Roedel
On Tue, Feb 02, 2016 at 10:49:11AM -0500, Mark Hounschell wrote:
> Just wondering if this issue is still being considered?

Yes it is, I just went through a move and have a few other issues on the
plate. But I this is still on the list.



Joerg

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v8 3/5] memory: mediatek: Add SMI driver

2016-02-16 Thread Will Deacon
On Tue, Feb 16, 2016 at 05:10:09PM +0100, Joerg Roedel wrote:
> On Tue, Feb 16, 2016 at 03:32:11PM +, Robin Murphy wrote:
> > On 16/02/16 14:11, Joerg Roedel wrote:
> > >On Sun, Jan 31, 2016 at 12:00:41PM +0100, Matthias Brugger wrote:
> > >>On 26/01/16 05:12, Yong Wu wrote:
> > >>>This patch add SMI(Smart Multimedia Interface) driver. This driver
> > >>>is responsible to enable/disable iommu and control the power domain
> > >>>and clocks of each local arbiter.
> > >>>
> > >>>Signed-off-by: Yong Wu 
> > >>>Tested-by: Philipp Zabel 
> > >>>---
> > >>
> > >>Signed-off-by: Matthias Brugger 
> > >>
> > >>Joerg would you mind to take this through your branch?
> > >
> > >Hmm, I somehow missed the patch-set, at least I can't find the v8
> > >patches in my inbox.
> > >
> > >Yong, can you please re-send with all Acks and other tags added?
> > 
> > Just to note patch 4 of this series also depends on the v3
> > io-pgtable short-descriptor series posted separately[1] - is that on
> > your radar already or would you like that resent as well?
> 
> No, that was not on my radar, I somehow expected Will to handle this
> series :)

I'm more than happy to bake a branch containing all the page table stuff,
but Yong's stuff depends on it so I'll work with whatever is easiest for
you.

Will
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v8 3/5] memory: mediatek: Add SMI driver

2016-02-16 Thread Joerg Roedel
On Tue, Feb 16, 2016 at 03:32:11PM +, Robin Murphy wrote:
> Hi Joerg,
> 
> On 16/02/16 14:11, Joerg Roedel wrote:
> >On Sun, Jan 31, 2016 at 12:00:41PM +0100, Matthias Brugger wrote:
> >>
> >>
> >>On 26/01/16 05:12, Yong Wu wrote:
> >>>This patch add SMI(Smart Multimedia Interface) driver. This driver
> >>>is responsible to enable/disable iommu and control the power domain
> >>>and clocks of each local arbiter.
> >>>
> >>>Signed-off-by: Yong Wu 
> >>>Tested-by: Philipp Zabel 
> >>>---
> >>
> >>Signed-off-by: Matthias Brugger 
> >>
> >>Joerg would you mind to take this through your branch?
> >
> >Hmm, I somehow missed the patch-set, at least I can't find the v8
> >patches in my inbox.
> >
> >Yong, can you please re-send with all Acks and other tags added?
> 
> Just to note patch 4 of this series also depends on the v3
> io-pgtable short-descriptor series posted separately[1] - is that on
> your radar already or would you like that resent as well?

No, that was not on my radar, I somehow expected Will to handle this
series :)

So please resend that as well.


Thanks,

Joerg

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 1/2] iommu: call detach also for default_domain before attaching to new one

2016-02-16 Thread Joerg Roedel
On Tue, Feb 16, 2016 at 03:40:31PM +0100, Marek Szyprowski wrote:
> This patch ensures that devices attached to the default_domain will be
> first detached from it before attaching to new domain. To avoid forward
> declaration, __iommu_attach_group() function has been moved to new place
> in the source code.

Actually it was intentional to not invoke the detach_device call-back in
the attach_device path.

The reason is that detaching first and than attaching again leaves the
device without a domain for a short period of time, until it is attached
to the new domain.

The attach_device call-back is supposed to handle this situation and
just silently overwrite any other domain->device binding it finds for
the device.

This allows to do re-attachment with less iommu flushes and to get rid
of the detach_device call-back at some point.



Joerg

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v8 3/5] memory: mediatek: Add SMI driver

2016-02-16 Thread Robin Murphy

Hi Joerg,

On 16/02/16 14:11, Joerg Roedel wrote:

On Sun, Jan 31, 2016 at 12:00:41PM +0100, Matthias Brugger wrote:



On 26/01/16 05:12, Yong Wu wrote:

This patch add SMI(Smart Multimedia Interface) driver. This driver
is responsible to enable/disable iommu and control the power domain
and clocks of each local arbiter.

Signed-off-by: Yong Wu 
Tested-by: Philipp Zabel 
---


Signed-off-by: Matthias Brugger 

Joerg would you mind to take this through your branch?


Hmm, I somehow missed the patch-set, at least I can't find the v8
patches in my inbox.

Yong, can you please re-send with all Acks and other tags added?


Just to note patch 4 of this series also depends on the v3 io-pgtable 
short-descriptor series posted separately[1] - is that on your radar 
already or would you like that resent as well?


Robin.

[1]:http://thread.gmane.org/gmane.linux.kernel.iommu/12007




Thanks,

Joerg

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu



___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 06/11] iommu: exynos: refactor fault handling code

2016-02-16 Thread Marek Szyprowski
This patch provides a new implementation for page fault handing code. The
new implementation is ready for future extensions. No functional changes
have been made.

Signed-off-by: Marek Szyprowski 
---
 drivers/iommu/exynos-iommu.c | 109 ---
 1 file changed, 41 insertions(+), 68 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 4275222..3a577a4 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -148,40 +148,25 @@ static sysmmu_pte_t *page_entry(sysmmu_pte_t *sent, 
sysmmu_iova_t iova)
lv2table_base(sent)) + lv2ent_offset(iova);
 }
 
-enum exynos_sysmmu_inttype {
-   SYSMMU_PAGEFAULT,
-   SYSMMU_AR_MULTIHIT,
-   SYSMMU_AW_MULTIHIT,
-   SYSMMU_BUSERROR,
-   SYSMMU_AR_SECURITY,
-   SYSMMU_AR_ACCESS,
-   SYSMMU_AW_SECURITY,
-   SYSMMU_AW_PROTECTION, /* 7 */
-   SYSMMU_FAULT_UNKNOWN,
-   SYSMMU_FAULTS_NUM
-};
-
-static unsigned short fault_reg_offset[SYSMMU_FAULTS_NUM] = {
-   REG_PAGE_FAULT_ADDR,
-   REG_AR_FAULT_ADDR,
-   REG_AW_FAULT_ADDR,
-   REG_DEFAULT_SLAVE_ADDR,
-   REG_AR_FAULT_ADDR,
-   REG_AR_FAULT_ADDR,
-   REG_AW_FAULT_ADDR,
-   REG_AW_FAULT_ADDR
+/*
+ * IOMMU fault information register
+ */
+struct sysmmu_fault_info {
+   unsigned int bit;   /* bit number in STATUS register */
+   unsigned short addr_reg; /* register to read VA fault address */
+   const char *name;   /* human readable fault name */
+   unsigned int type;  /* fault type for report_iommu_fault */
 };
 
-static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = {
-   "PAGE FAULT",
-   "AR MULTI-HIT FAULT",
-   "AW MULTI-HIT FAULT",
-   "BUS ERROR",
-   "AR SECURITY PROTECTION FAULT",
-   "AR ACCESS PROTECTION FAULT",
-   "AW SECURITY PROTECTION FAULT",
-   "AW ACCESS PROTECTION FAULT",
-   "UNKNOWN FAULT"
+static const struct sysmmu_fault_info sysmmu_faults[] = {
+   { 0, REG_PAGE_FAULT_ADDR, "PAGE", IOMMU_FAULT_READ },
+   { 1, REG_AR_FAULT_ADDR, "AR MULTI-HIT", IOMMU_FAULT_READ },
+   { 2, REG_AW_FAULT_ADDR, "AW MULTI-HIT", IOMMU_FAULT_WRITE },
+   { 3, REG_DEFAULT_SLAVE_ADDR, "BUS ERROR", IOMMU_FAULT_READ },
+   { 4, REG_AR_FAULT_ADDR, "AR SECURITY PROTECTION", IOMMU_FAULT_READ },
+   { 5, REG_AR_FAULT_ADDR, "AR ACCESS PROTECTION", IOMMU_FAULT_READ },
+   { 6, REG_AW_FAULT_ADDR, "AW SECURITY PROTECTION", IOMMU_FAULT_WRITE },
+   { 7, REG_AW_FAULT_ADDR, "AW ACCESS PROTECTION", IOMMU_FAULT_WRITE },
 };
 
 /*
@@ -299,24 +284,19 @@ static void __sysmmu_set_ptbase(struct sysmmu_drvdata 
*data, phys_addr_t pgd)
__sysmmu_tlb_invalidate(data);
 }
 
-static void show_fault_information(const char *name,
-   enum exynos_sysmmu_inttype itype,
-   phys_addr_t pgtable_base, sysmmu_iova_t fault_addr)
+static void show_fault_information(struct sysmmu_drvdata *data,
+  const struct sysmmu_fault_info *finfo,
+  sysmmu_iova_t fault_addr)
 {
sysmmu_pte_t *ent;
 
-   if ((itype >= SYSMMU_FAULTS_NUM) || (itype < SYSMMU_PAGEFAULT))
-   itype = SYSMMU_FAULT_UNKNOWN;
-
-   pr_err("%s occurred at %#x by %s(Page table base: %pa)\n",
-   sysmmu_fault_name[itype], fault_addr, name, _base);
-
-   ent = section_entry(phys_to_virt(pgtable_base), fault_addr);
-   pr_err("\tLv1 entry: %#x\n", *ent);
-
+   dev_err(data->sysmmu, "%s FAULT occurred at %#x (page table base: 
%pa)\n",
+   finfo->name, fault_addr, >pgtable);
+   ent = section_entry(phys_to_virt(data->pgtable), fault_addr);
+   dev_err(data->sysmmu, "\tLv1 entry: %#x\n", *ent);
if (lv1ent_page(ent)) {
ent = page_entry(ent, fault_addr);
-   pr_err("\t Lv2 entry: %#x\n", *ent);
+   dev_err(data->sysmmu, "\t Lv2 entry: %#x\n", *ent);
}
 }
 
@@ -324,8 +304,10 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id)
 {
/* SYSMMU is in blocked state when interrupt occurred. */
struct sysmmu_drvdata *data = dev_id;
-   enum exynos_sysmmu_inttype itype;
-   sysmmu_iova_t addr = -1;
+   const struct sysmmu_fault_info *finfo = sysmmu_faults;
+   int i, n = ARRAY_SIZE(sysmmu_faults);
+   unsigned int itype;
+   sysmmu_iova_t fault_addr = -1;
int ret = -ENOSYS;
 
WARN_ON(!is_sysmmu_active(data));
@@ -334,29 +316,20 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void 
*dev_id)
 
clk_enable(data->clk_master);
 
-   itype = (enum exynos_sysmmu_inttype)
-   __ffs(__raw_readl(data->sfrbase + REG_INT_STATUS));
-   if (WARN_ON(!((itype >= 0) && (itype < SYSMMU_FAULT_UNKNOWN
-   itype = SYSMMU_FAULT_UNKNOWN;
-   else
-   addr = __raw_readl(data->sfrbase + 

[PATCH 10/11] iommu: exynos: add support for v5 SYSMMU

2016-02-16 Thread Marek Szyprowski
This patch adds support for v5 of SYSMMU controller, found in Samsung
Exynos 5433 SoCs. The main difference of v5 is support for 36-bit physical
address space and some changes in register layout and core clocks hanging.
This patch also adds support for ARM64 architecture, which is used by
Exynos 5433 SoCs.

Signed-off-by: Marek Szyprowski 
---
 .../devicetree/bindings/iommu/samsung,sysmmu.txt   |   5 +-
 drivers/iommu/Kconfig  |   2 +-
 drivers/iommu/exynos-iommu.c   | 195 +++--
 3 files changed, 150 insertions(+), 52 deletions(-)

diff --git a/Documentation/devicetree/bindings/iommu/samsung,sysmmu.txt 
b/Documentation/devicetree/bindings/iommu/samsung,sysmmu.txt
index f61ca25..85f0688 100644
--- a/Documentation/devicetree/bindings/iommu/samsung,sysmmu.txt
+++ b/Documentation/devicetree/bindings/iommu/samsung,sysmmu.txt
@@ -35,9 +35,10 @@ Required properties:
 - interrupts: An interrupt specifier for interrupt signal of System MMU,
  according to the format defined by a particular interrupt
  controller.
-- clock-names: Should be "sysmmu" if the System MMU is needed to gate its 
clock.
+- clock-names: Should be "sysmmu" or a pair of "aclk" and "pclk" to gate
+  SYSMMU core clocks.
   Optional "master" if the clock to the System MMU is gated by
-  another gate clock other than "sysmmu" (usually main gate clock
+  another gate clock other core  (usually main gate clock
   of peripheral device this SYSMMU belongs to).
 - clocks: Phandles for respective clocks described by clock-names.
 - power-domains: Required if the System MMU is needed to gate its power.
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index a1e75cb..1674de1 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -243,7 +243,7 @@ config TEGRA_IOMMU_SMMU
 
 config EXYNOS_IOMMU
bool "Exynos IOMMU Support"
-   depends on ARCH_EXYNOS && ARM && MMU
+   depends on ARCH_EXYNOS && MMU
select IOMMU_API
select ARM_DMA_USE_IOMMU
help
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index e42a76c..f00378a 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -1,6 +1,5 @@
-/* linux/drivers/iommu/exynos_iommu.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+/*
+ * Copyright (c) 2011,2016 Samsung Electronics Co., Ltd.
  * http://www.samsung.com
  *
  * This program is free software; you can redistribute it and/or modify
@@ -55,17 +54,25 @@ typedef u32 sysmmu_pte_t;
 #define lv2ent_small(pent) ((*(pent) & 2) == 2)
 #define lv2ent_large(pent) ((*(pent) & 3) == 1)
 
-static u32 sysmmu_page_offset(sysmmu_iova_t iova, u32 size)
-{
-   return iova & (size - 1);
-}
-
-#define section_phys(sent) (*(sent) & SECT_MASK)
-#define section_offs(iova) sysmmu_page_offset((iova), SECT_SIZE)
-#define lpage_phys(pent) (*(pent) & LPAGE_MASK)
-#define lpage_offs(iova) sysmmu_page_offset((iova), LPAGE_SIZE)
-#define spage_phys(pent) (*(pent) & SPAGE_MASK)
-#define spage_offs(iova) sysmmu_page_offset((iova), SPAGE_SIZE)
+/*
+ * v1.x - v3.x SYSMMU supports 32bit physical and 32bit virtual address spaces
+ * v5.0 introduced support for 36bit physical address space by shifting
+ * all page entry values by 4 bits.
+ * All SYSMMU controllers in the system support the address spaces of the same
+ * size, so PG_ENT_SHIFT can be initialized on first SYSMMU probe to proper
+ * value (0 or 4).
+ */
+static short PG_ENT_SHIFT = -1;
+#define SYSMMU_PG_ENT_SHIFT 0
+#define SYSMMU_V5_PG_ENT_SHIFT 4
+
+#define sect_to_phys(ent) (((phys_addr_t) ent) << PG_ENT_SHIFT)
+#define section_phys(sent) (sect_to_phys(*(sent)) & SECT_MASK)
+#define section_offs(iova) (iova & (SECT_SIZE - 1))
+#define lpage_phys(pent) (sect_to_phys(*(pent)) & LPAGE_MASK)
+#define lpage_offs(iova) (iova & (LPAGE_SIZE - 1))
+#define spage_phys(pent) (sect_to_phys(*(pent)) & SPAGE_MASK)
+#define spage_offs(iova) (iova & (SPAGE_SIZE - 1))
 
 #define NUM_LV1ENTRIES 4096
 #define NUM_LV2ENTRIES (SECT_SIZE / SPAGE_SIZE)
@@ -84,13 +91,12 @@ static u32 lv2ent_offset(sysmmu_iova_t iova)
 #define LV2TABLE_SIZE (NUM_LV2ENTRIES * sizeof(sysmmu_pte_t))
 
 #define SPAGES_PER_LPAGE (LPAGE_SIZE / SPAGE_SIZE)
+#define lv2table_base(sent) (sect_to_phys(*(sent) & 0xFFC0))
 
-#define lv2table_base(sent) (*(sent) & 0xFC00)
-
-#define mk_lv1ent_sect(pa) ((pa) | 2)
-#define mk_lv1ent_page(pa) ((pa) | 1)
-#define mk_lv2ent_lpage(pa) ((pa) | 1)
-#define mk_lv2ent_spage(pa) ((pa) | 2)
+#define mk_lv1ent_sect(pa) ((pa >> PG_ENT_SHIFT) | 2)
+#define mk_lv1ent_page(pa) ((pa >> PG_ENT_SHIFT) | 1)
+#define mk_lv2ent_lpage(pa) ((pa >> PG_ENT_SHIFT) | 1)
+#define mk_lv2ent_spage(pa) ((pa >> PG_ENT_SHIFT) | 2)
 
 #define CTRL_ENABLE0x5
 #define CTRL_BLOCK 0x7
@@ -98,14 +104,23 @@ static u32 lv2ent_offset(sysmmu_iova_t iova)
 
 

[PATCH 05/11] iommu: exynos: refactor code (no direct register access)

2016-02-16 Thread Marek Szyprowski
This patch changes some internal functions to have access to the state of
sysmmu device instead of having only it's registers. This will make the
code ready for future extensions.

Signed-off-by: Marek Szyprowski 
---
 drivers/iommu/exynos-iommu.c | 40 +++-
 1 file changed, 19 insertions(+), 21 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index bf6b826..4275222 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -254,50 +254,49 @@ static bool is_sysmmu_active(struct sysmmu_drvdata *data)
return data->activations > 0;
 }
 
-static void sysmmu_unblock(void __iomem *sfrbase)
+static void sysmmu_unblock(struct sysmmu_drvdata *data)
 {
-   __raw_writel(CTRL_ENABLE, sfrbase + REG_MMU_CTRL);
+   __raw_writel(CTRL_ENABLE, data->sfrbase + REG_MMU_CTRL);
 }
 
-static bool sysmmu_block(void __iomem *sfrbase)
+static bool sysmmu_block(struct sysmmu_drvdata *data)
 {
int i = 120;
 
-   __raw_writel(CTRL_BLOCK, sfrbase + REG_MMU_CTRL);
-   while ((i > 0) && !(__raw_readl(sfrbase + REG_MMU_STATUS) & 1))
+   __raw_writel(CTRL_BLOCK, data->sfrbase + REG_MMU_CTRL);
+   while ((i > 0) && !(__raw_readl(data->sfrbase + REG_MMU_STATUS) & 1))
--i;
 
-   if (!(__raw_readl(sfrbase + REG_MMU_STATUS) & 1)) {
-   sysmmu_unblock(sfrbase);
+   if (!(__raw_readl(data->sfrbase + REG_MMU_STATUS) & 1)) {
+   sysmmu_unblock(data);
return false;
}
 
return true;
 }
 
-static void __sysmmu_tlb_invalidate(void __iomem *sfrbase)
+static void __sysmmu_tlb_invalidate(struct sysmmu_drvdata *data)
 {
-   __raw_writel(0x1, sfrbase + REG_MMU_FLUSH);
+   __raw_writel(0x1, data->sfrbase + REG_MMU_FLUSH);
 }
 
-static void __sysmmu_tlb_invalidate_entry(void __iomem *sfrbase,
+static void __sysmmu_tlb_invalidate_entry(struct sysmmu_drvdata *data,
sysmmu_iova_t iova, unsigned int num_inv)
 {
unsigned int i;
 
for (i = 0; i < num_inv; i++) {
__raw_writel((iova & SPAGE_MASK) | 1,
-   sfrbase + REG_MMU_FLUSH_ENTRY);
+   data->sfrbase + REG_MMU_FLUSH_ENTRY);
iova += SPAGE_SIZE;
}
 }
 
-static void __sysmmu_set_ptbase(void __iomem *sfrbase,
-  phys_addr_t pgd)
+static void __sysmmu_set_ptbase(struct sysmmu_drvdata *data, phys_addr_t pgd)
 {
-   __raw_writel(pgd, sfrbase + REG_PT_BASE_ADDR);
+   __raw_writel(pgd, data->sfrbase + REG_PT_BASE_ADDR);
 
-   __sysmmu_tlb_invalidate(sfrbase);
+   __sysmmu_tlb_invalidate(data);
 }
 
 static void show_fault_information(const char *name,
@@ -363,7 +362,7 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id)
 
__raw_writel(1 << itype, data->sfrbase + REG_INT_CLEAR);
 
-   sysmmu_unblock(data->sfrbase);
+   sysmmu_unblock(data);
 
clk_disable(data->clk_master);
 
@@ -440,7 +439,7 @@ static void __sysmmu_enable_nocount(struct sysmmu_drvdata 
*data)
 
__sysmmu_init_config(data);
 
-   __sysmmu_set_ptbase(data->sfrbase, data->pgtable);
+   __sysmmu_set_ptbase(data, data->pgtable);
 
__raw_writel(CTRL_ENABLE, data->sfrbase + REG_MMU_CTRL);
 
@@ -521,10 +520,9 @@ static void sysmmu_tlb_invalidate_entry(struct 
sysmmu_drvdata *data,
if (MMU_MAJ_VER(data->version) == 2)
num_inv = min_t(unsigned int, size / PAGE_SIZE, 64);
 
-   if (sysmmu_block(data->sfrbase)) {
-   __sysmmu_tlb_invalidate_entry(
-   data->sfrbase, iova, num_inv);
-   sysmmu_unblock(data->sfrbase);
+   if (sysmmu_block(data)) {
+   __sysmmu_tlb_invalidate_entry(data, iova, num_inv);
+   sysmmu_unblock(data);
}
clk_disable(data->clk_master);
} else {
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 01/11] iommu: exynos: rework iommu group initialization

2016-02-16 Thread Marek Szyprowski
This patch replaces custom code in add_device implementation with
iommu_group_get_for_dev() call and provides the needed callback.

Signed-off-by: Marek Szyprowski 
---
 drivers/iommu/exynos-iommu.c | 27 ---
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 97c41b8..4fc0790 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -1114,28 +1114,32 @@ static phys_addr_t exynos_iommu_iova_to_phys(struct 
iommu_domain *iommu_domain,
return phys;
 }
 
+static struct iommu_group *get_device_iommu_group(struct device *dev)
+{
+   struct iommu_group *group;
+
+   group = iommu_group_get(dev);
+   if (!group)
+   group = iommu_group_alloc();
+
+   return group;
+}
+
 static int exynos_iommu_add_device(struct device *dev)
 {
struct iommu_group *group;
-   int ret;
 
if (!has_sysmmu(dev))
return -ENODEV;
 
-   group = iommu_group_get(dev);
+   group = iommu_group_get_for_dev(dev);
 
-   if (!group) {
-   group = iommu_group_alloc();
-   if (IS_ERR(group)) {
-   dev_err(dev, "Failed to allocate IOMMU group\n");
-   return PTR_ERR(group);
-   }
-   }
+   if (IS_ERR(group))
+   return PTR_ERR(group);
 
-   ret = iommu_group_add_device(group, dev);
iommu_group_put(group);
 
-   return ret;
+   return 0;
 }
 
 static void exynos_iommu_remove_device(struct device *dev)
@@ -1182,6 +1186,7 @@ static struct iommu_ops exynos_iommu_ops = {
.unmap = exynos_iommu_unmap,
.map_sg = default_iommu_map_sg,
.iova_to_phys = exynos_iommu_iova_to_phys,
+   .device_group = get_device_iommu_group,
.add_device = exynos_iommu_add_device,
.remove_device = exynos_iommu_remove_device,
.pgsize_bitmap = SECT_SIZE | LPAGE_SIZE | SPAGE_SIZE,
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 02/11] iommu: exynos: add support for IOMMU_DOMAIN_DMA domain type

2016-02-16 Thread Marek Szyprowski
This patch adds support for DMA domain type. Such domain have DMA cookie
prepared and can be used by generic DMA-IOMMU glue layer.

Signed-off-by: Marek Szyprowski 
---
 drivers/iommu/exynos-iommu.c | 19 +++
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 4fc0790..595e0da 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -25,9 +25,9 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
-#include 
 #include 
 
 typedef u32 sysmmu_iova_t;
@@ -662,16 +662,21 @@ static struct iommu_domain 
*exynos_iommu_domain_alloc(unsigned type)
struct exynos_iommu_domain *domain;
int i;
 
-   if (type != IOMMU_DOMAIN_UNMANAGED)
-   return NULL;
 
domain = kzalloc(sizeof(*domain), GFP_KERNEL);
if (!domain)
return NULL;
 
+   if (type == IOMMU_DOMAIN_DMA) {
+   if (iommu_get_dma_cookie(>domain) != 0)
+   goto err_pgtable;
+   } else if (type != IOMMU_DOMAIN_UNMANAGED) {
+   goto err_pgtable;
+   }
+
domain->pgtable = (sysmmu_pte_t *)__get_free_pages(GFP_KERNEL, 2);
if (!domain->pgtable)
-   goto err_pgtable;
+   goto err_dma_cookie;
 
domain->lv2entcnt = (short *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 
1);
if (!domain->lv2entcnt)
@@ -703,6 +708,9 @@ static struct iommu_domain 
*exynos_iommu_domain_alloc(unsigned type)
 
 err_counter:
free_pages((unsigned long)domain->pgtable, 2);
+err_dma_cookie:
+   if (type == IOMMU_DOMAIN_DMA)
+   iommu_put_dma_cookie(>domain);
 err_pgtable:
kfree(domain);
return NULL;
@@ -727,6 +735,9 @@ static void exynos_iommu_domain_free(struct iommu_domain 
*iommu_domain)
 
spin_unlock_irqrestore(>lock, flags);
 
+   if (iommu_domain->type == IOMMU_DOMAIN_DMA)
+   iommu_put_dma_cookie(iommu_domain);
+
for (i = 0; i < NUM_LV1ENTRIES; i++)
if (lv1ent_page(domain->pgtable + i))
kmem_cache_free(lv2table_kmem_cache,
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 11/11] iommu: exynos: add Maintainers entry for Exynos SYSMMU driver

2016-02-16 Thread Marek Szyprowski
Add Marek Szyprowski as maintainer for Exynos IOMMU driver.

Signed-off-by: Marek Szyprowski 
---
 MAINTAINERS | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 7bd927e..1e9c4df 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4336,6 +4336,12 @@ L:   dri-de...@lists.freedesktop.org
 S: Maintained
 F: drivers/gpu/drm/exynos/exynos_dp*
 
+EXYNOS SYSMMU (IOMMU) driver
+M: Marek Szyprowski 
+L: iommu@lists.linux-foundation.org
+S: Maintained
+F: drivers/iommu/exynos-iommu.c
+
 EXYNOS MIPI DISPLAY DRIVERS
 M: Inki Dae 
 M: Donghwa Lee 
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 07/11] iommu: exynos: refactor init config code

2016-02-16 Thread Marek Szyprowski
This patch rewrites sysmmu_init_config function to make it easier to read
and understand.

Signed-off-by: Marek Szyprowski 
---
 drivers/iommu/exynos-iommu.c | 25 +
 1 file changed, 9 insertions(+), 16 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 3a577a4..15787a1 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -383,24 +383,17 @@ static bool __sysmmu_disable(struct sysmmu_drvdata *data)
 
 static void __sysmmu_init_config(struct sysmmu_drvdata *data)
 {
-   unsigned int cfg = CFG_LRU | CFG_QOS(15);
-   unsigned int ver;
-
-   ver = MMU_RAW_VER(__raw_readl(data->sfrbase + REG_MMU_VERSION));
-   if (MMU_MAJ_VER(ver) == 3) {
-   if (MMU_MIN_VER(ver) >= 2) {
-   cfg |= CFG_FLPDCACHE;
-   if (MMU_MIN_VER(ver) == 3) {
-   cfg |= CFG_ACGEN;
-   cfg &= ~CFG_LRU;
-   } else {
-   cfg |= CFG_SYSSEL;
-   }
-   }
-   }
+   unsigned int cfg;
+
+   data->version = MMU_RAW_VER(__raw_readl(data->sfrbase + 
REG_MMU_VERSION));
+   if (data->version <= MAKE_MMU_VER(3, 1))
+   cfg = CFG_LRU | CFG_QOS(15);
+   else if (data->version <= MAKE_MMU_VER(3, 2))
+   cfg = CFG_LRU | CFG_QOS(15) | CFG_FLPDCACHE | CFG_SYSSEL;
+   else
+   cfg = CFG_QOS(15) | CFG_FLPDCACHE | CFG_ACGEN;
 
__raw_writel(cfg, data->sfrbase + REG_MMU_CFG);
-   data->version = ver;
 }
 
 static void __sysmmu_enable_nocount(struct sysmmu_drvdata *data)
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 03/11] iommu: exynos: remove ARM-specific cache flush interface

2016-02-16 Thread Marek Szyprowski
This patch replaces custom ARM-specific code for performing CPU cache flush
operations with generic code based on DMA-mapping. Domain managing code
is independent of particular SYSMMU device, so the first registered SYSMMU
device is used for DMA-mapping calls. This simplification works fine
because all SYSMMU controllers are in the same address space (where
DMA address equals physical address) and the DMA-mapping calls are done
mainly to flush CPU cache to make changes visible to SYSMMU controllers.

Signed-off-by: Marek Szyprowski 
---
 drivers/iommu/exynos-iommu.c | 74 +---
 1 file changed, 49 insertions(+), 25 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 595e0da..8c8a7f7 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -27,9 +27,6 @@
 #include 
 #include 
 
-#include 
-#include 
-
 typedef u32 sysmmu_iova_t;
 typedef u32 sysmmu_pte_t;
 
@@ -83,6 +80,7 @@ static u32 lv2ent_offset(sysmmu_iova_t iova)
return (iova >> SPAGE_ORDER) & (NUM_LV2ENTRIES - 1);
 }
 
+#define LV1TABLE_SIZE (NUM_LV1ENTRIES * sizeof(sysmmu_pte_t))
 #define LV2TABLE_SIZE (NUM_LV2ENTRIES * sizeof(sysmmu_pte_t))
 
 #define SPAGES_PER_LPAGE (LPAGE_SIZE / SPAGE_SIZE)
@@ -134,6 +132,7 @@ static u32 lv2ent_offset(sysmmu_iova_t iova)
 
 #define has_sysmmu(dev)(dev->archdata.iommu != NULL)
 
+static struct device *dma_dev;
 static struct kmem_cache *lv2table_kmem_cache;
 static sysmmu_pte_t *zero_lv2_table;
 #define ZERO_LV2LINK mk_lv1ent_page(virt_to_phys(zero_lv2_table))
@@ -650,16 +649,19 @@ static struct platform_driver exynos_sysmmu_driver 
__refdata = {
}
 };
 
-static inline void pgtable_flush(void *vastart, void *vaend)
+static inline void update_pte(sysmmu_pte_t *ent, sysmmu_pte_t val)
 {
-   dmac_flush_range(vastart, vaend);
-   outer_flush_range(virt_to_phys(vastart),
-   virt_to_phys(vaend));
+   dma_sync_single_for_cpu(dma_dev, virt_to_phys(ent), sizeof(*ent),
+   DMA_TO_DEVICE);
+   *ent = val;
+   dma_sync_single_for_device(dma_dev, virt_to_phys(ent), sizeof(*ent),
+  DMA_TO_DEVICE);
 }
 
 static struct iommu_domain *exynos_iommu_domain_alloc(unsigned type)
 {
struct exynos_iommu_domain *domain;
+   dma_addr_t handle;
int i;
 
 
@@ -694,7 +696,10 @@ static struct iommu_domain 
*exynos_iommu_domain_alloc(unsigned type)
domain->pgtable[i + 7] = ZERO_LV2LINK;
}
 
-   pgtable_flush(domain->pgtable, domain->pgtable + NUM_LV1ENTRIES);
+   handle = dma_map_single(dma_dev, domain->pgtable, LV1TABLE_SIZE,
+   DMA_TO_DEVICE);
+   /* For mapping page table entries we rely on dma == phys */
+   BUG_ON(handle != virt_to_phys(domain->pgtable));
 
spin_lock_init(>lock);
spin_lock_init(>pgtablelock);
@@ -738,10 +743,18 @@ static void exynos_iommu_domain_free(struct iommu_domain 
*iommu_domain)
if (iommu_domain->type == IOMMU_DOMAIN_DMA)
iommu_put_dma_cookie(iommu_domain);
 
+   dma_unmap_single(dma_dev, virt_to_phys(domain->pgtable), LV1TABLE_SIZE,
+DMA_TO_DEVICE);
+
for (i = 0; i < NUM_LV1ENTRIES; i++)
-   if (lv1ent_page(domain->pgtable + i))
+   if (lv1ent_page(domain->pgtable + i)) {
+   phys_addr_t base = lv2table_base(domain->pgtable + i);
+
+   dma_unmap_single(dma_dev, base, LV2TABLE_SIZE,
+DMA_TO_DEVICE);
kmem_cache_free(lv2table_kmem_cache,
-   phys_to_virt(lv2table_base(domain->pgtable + 
i)));
+   phys_to_virt(base));
+   }
 
free_pages((unsigned long)domain->pgtable, 2);
free_pages((unsigned long)domain->lv2entcnt, 1);
@@ -834,11 +847,10 @@ static sysmmu_pte_t *alloc_lv2entry(struct 
exynos_iommu_domain *domain,
if (!pent)
return ERR_PTR(-ENOMEM);
 
-   *sent = mk_lv1ent_page(virt_to_phys(pent));
+   update_pte(sent, mk_lv1ent_page(virt_to_phys(pent)));
kmemleak_ignore(pent);
*pgcounter = NUM_LV2ENTRIES;
-   pgtable_flush(pent, pent + NUM_LV2ENTRIES);
-   pgtable_flush(sent, sent + 1);
+   dma_map_single(dma_dev, pent, LV2TABLE_SIZE, DMA_TO_DEVICE);
 
/*
 * If pre-fetched SLPD is a faulty SLPD in zero_l2_table,
@@ -891,9 +903,7 @@ static int lv1set_section(struct exynos_iommu_domain 
*domain,
*pgcnt = 0;
}
 
-   *sent = mk_lv1ent_sect(paddr);
-
-   pgtable_flush(sent, sent + 1);
+   update_pte(sent, mk_lv1ent_sect(paddr));
 
spin_lock(>lock);
if 

[PATCH 08/11] iommu: exynos: unify code for fldp cache invalidation

2016-02-16 Thread Marek Szyprowski
This patch simplifies the code for handling of flpdcache invalidation.

Signed-off-by: Marek Szyprowski 
---
 drivers/iommu/exynos-iommu.c | 13 -
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 15787a1..e42a76c 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -440,13 +440,6 @@ static int __sysmmu_enable(struct sysmmu_drvdata *data, 
phys_addr_t pgtable,
return ret;
 }
 
-static void __sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data,
- sysmmu_iova_t iova)
-{
-   if (data->version == MAKE_MMU_VER(3, 3))
-   __raw_writel(iova | 0x1, data->sfrbase + REG_MMU_FLUSH_ENTRY);
-}
-
 static void sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data,
sysmmu_iova_t iova)
 {
@@ -455,8 +448,10 @@ static void sysmmu_tlb_invalidate_flpdcache(struct 
sysmmu_drvdata *data,
clk_enable(data->clk_master);
 
spin_lock_irqsave(>lock, flags);
-   if (is_sysmmu_active(data))
-   __sysmmu_tlb_invalidate_flpdcache(data, iova);
+   if (is_sysmmu_active(data)) {
+   if (data->version >= MAKE_MMU_VER(3, 3))
+   __sysmmu_tlb_invalidate_entry(data, iova, 1);
+   }
spin_unlock_irqrestore(>lock, flags);
 
clk_disable(data->clk_master);
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 04/11] iommu: exynos: simplify master clock operations

2016-02-16 Thread Marek Szyprowski
All clock API function can be called on NULL clock, so simplify code avoid
checking of master clock presence.

Signed-off-by: Marek Szyprowski 
---
 drivers/iommu/exynos-iommu.c | 32 
 1 file changed, 12 insertions(+), 20 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 8c8a7f7..bf6b826 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -333,8 +333,7 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id)
 
spin_lock(>lock);
 
-   if (!IS_ERR(data->clk_master))
-   clk_enable(data->clk_master);
+   clk_enable(data->clk_master);
 
itype = (enum exynos_sysmmu_inttype)
__ffs(__raw_readl(data->sfrbase + REG_INT_STATUS));
@@ -366,8 +365,7 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id)
 
sysmmu_unblock(data->sfrbase);
 
-   if (!IS_ERR(data->clk_master))
-   clk_disable(data->clk_master);
+   clk_disable(data->clk_master);
 
spin_unlock(>lock);
 
@@ -376,15 +374,13 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void 
*dev_id)
 
 static void __sysmmu_disable_nocount(struct sysmmu_drvdata *data)
 {
-   if (!IS_ERR(data->clk_master))
-   clk_enable(data->clk_master);
+   clk_enable(data->clk_master);
 
__raw_writel(CTRL_DISABLE, data->sfrbase + REG_MMU_CTRL);
__raw_writel(0, data->sfrbase + REG_MMU_CFG);
 
clk_disable(data->clk);
-   if (!IS_ERR(data->clk_master))
-   clk_disable(data->clk_master);
+   clk_disable(data->clk_master);
 }
 
 static bool __sysmmu_disable(struct sysmmu_drvdata *data)
@@ -437,8 +433,7 @@ static void __sysmmu_init_config(struct sysmmu_drvdata 
*data)
 
 static void __sysmmu_enable_nocount(struct sysmmu_drvdata *data)
 {
-   if (!IS_ERR(data->clk_master))
-   clk_enable(data->clk_master);
+   clk_enable(data->clk_master);
clk_enable(data->clk);
 
__raw_writel(CTRL_BLOCK, data->sfrbase + REG_MMU_CTRL);
@@ -449,8 +444,7 @@ static void __sysmmu_enable_nocount(struct sysmmu_drvdata 
*data)
 
__raw_writel(CTRL_ENABLE, data->sfrbase + REG_MMU_CTRL);
 
-   if (!IS_ERR(data->clk_master))
-   clk_disable(data->clk_master);
+   clk_disable(data->clk_master);
 }
 
 static int __sysmmu_enable(struct sysmmu_drvdata *data, phys_addr_t pgtable,
@@ -493,16 +487,14 @@ static void sysmmu_tlb_invalidate_flpdcache(struct 
sysmmu_drvdata *data,
 {
unsigned long flags;
 
-   if (!IS_ERR(data->clk_master))
-   clk_enable(data->clk_master);
+   clk_enable(data->clk_master);
 
spin_lock_irqsave(>lock, flags);
if (is_sysmmu_active(data))
__sysmmu_tlb_invalidate_flpdcache(data, iova);
spin_unlock_irqrestore(>lock, flags);
 
-   if (!IS_ERR(data->clk_master))
-   clk_disable(data->clk_master);
+   clk_disable(data->clk_master);
 }
 
 static void sysmmu_tlb_invalidate_entry(struct sysmmu_drvdata *data,
@@ -514,8 +506,7 @@ static void sysmmu_tlb_invalidate_entry(struct 
sysmmu_drvdata *data,
if (is_sysmmu_active(data)) {
unsigned int num_inv = 1;
 
-   if (!IS_ERR(data->clk_master))
-   clk_enable(data->clk_master);
+   clk_enable(data->clk_master);
 
/*
 * L2TLB invalidation required
@@ -535,8 +526,7 @@ static void sysmmu_tlb_invalidate_entry(struct 
sysmmu_drvdata *data,
data->sfrbase, iova, num_inv);
sysmmu_unblock(data->sfrbase);
}
-   if (!IS_ERR(data->clk_master))
-   clk_disable(data->clk_master);
+   clk_disable(data->clk_master);
} else {
dev_dbg(data->master,
"disabled. Skipping TLB invalidation @ %#x\n", iova);
@@ -593,6 +583,8 @@ static int __init exynos_sysmmu_probe(struct 
platform_device *pdev)
dev_err(dev, "Failed to prepare master's clk\n");
return ret;
}
+   } else {
+   data->clk_master = NULL;
}
 
data->sysmmu = dev;
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 09/11] iommu: exynos: update device tree documentation

2016-02-16 Thread Marek Szyprowski
Exynos SYSMMU bindings documentation was merged before generic IOMMU
binding have been introduced. This patch updates documentation to match
current state.

Signed-off-by: Marek Szyprowski 
---
 .../devicetree/bindings/iommu/samsung,sysmmu.txt  | 19 ---
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/Documentation/devicetree/bindings/iommu/samsung,sysmmu.txt 
b/Documentation/devicetree/bindings/iommu/samsung,sysmmu.txt
index bc620fe..f61ca25 100644
--- a/Documentation/devicetree/bindings/iommu/samsung,sysmmu.txt
+++ b/Documentation/devicetree/bindings/iommu/samsung,sysmmu.txt
@@ -23,28 +23,23 @@ MMUs.
   for window 1, 2 and 3.
 * M2M Scalers and G2D in Exynos5420 has one System MMU on the read channel and
   the other System MMU on the write channel.
-The drivers must consider how to handle those System MMUs. One of the idea is
-to implement child devices or sub-devices which are the client devices of the
-System MMU.
 
-Note:
-The current DT binding for the Exynos System MMU is incomplete.
-The following properties can be removed or changed, if found incompatible with
-the "Generic IOMMU Binding" support for attaching devices to the IOMMU.
+For information on assigning System MMU controller to its peripheral devices,
+see generic IOMMU bindings.
 
 Required properties:
 - compatible: Should be "samsung,exynos-sysmmu"
 - reg: A tuple of base address and size of System MMU registers.
+- #iommu-cells: Should be <0>.
 - interrupt-parent: The phandle of the interrupt controller of System MMU
 - interrupts: An interrupt specifier for interrupt signal of System MMU,
  according to the format defined by a particular interrupt
  controller.
 - clock-names: Should be "sysmmu" if the System MMU is needed to gate its 
clock.
   Optional "master" if the clock to the System MMU is gated by
-  another gate clock other than "sysmmu".
-  Exynos4 SoCs, there needs no "master" clock.
-  Exynos5 SoCs, some System MMUs must have "master" clocks.
-- clocks: Required if the System MMU is needed to gate its clock.
+  another gate clock other than "sysmmu" (usually main gate clock
+  of peripheral device this SYSMMU belongs to).
+- clocks: Phandles for respective clocks described by clock-names.
 - power-domains: Required if the System MMU is needed to gate its power.
  Please refer to the following document:
  Documentation/devicetree/bindings/power/pd-samsung.txt
@@ -57,6 +52,7 @@ Examples:
power-domains = <_gsc>;
clocks = < CLK_GSCL0>;
clock-names = "gscl";
+   iommus = <_gsc0>;
};
 
sysmmu_gsc0: sysmmu@13E8 {
@@ -67,4 +63,5 @@ Examples:
clock-names = "sysmmu", "master";
clocks = < CLK_SMMU_GSCL0>, < CLK_GSCL0>;
power-domains = <_gsc>;
+   #iommu-cells = <0>;
};
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 00/11] SYSMMU driver update and support for Exynos 5433

2016-02-16 Thread Marek Szyprowski
Hello,

This patchset updates Exynos SYSMMU (IOMMU) driver to make use of the
new features in the IOMMU core (support for IOMMU_DOMAIN_DMA) and adds
support for SYSMMU v5 controllers, which are available in Samsung Exynos
5433 SoCs. The driver has been also updated to compile and work on ARM64
architecture.

Best regards
Marek Szyprowski
Samsung R Institute Poland


Patch summary:

Marek Szyprowski (11):
  iommu: exynos: rework iommu group initialization
  iommu: exynos: add support for IOMMU_DOMAIN_DMA domain type
  iommu: exynos: remove ARM-specific cache flush interface
  iommu: exynos: simplify master clock operations
  iommu: exynos: refactor code (no direct register access)
  iommu: exynos: refactor fault handling code
  iommu: exynos: refactor init config code
  iommu: exynos: unify code for fldp cache invalidation
  iommu: exynos: update device tree documentation
  iommu: exynos: add support for v5 SYSMMU
  iommu: exynos: add Maintainers entry for Exynos SYSMMU driver

 .../devicetree/bindings/iommu/samsung,sysmmu.txt   |  22 +-
 MAINTAINERS|   6 +
 drivers/iommu/Kconfig  |   2 +-
 drivers/iommu/exynos-iommu.c   | 514 -
 4 files changed, 318 insertions(+), 226 deletions(-)

-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 0/2] iommu: fix handling of attach/detach for default domains

2016-02-16 Thread Marek Szyprowski
Hello,

This patchset fixes attaching and detaching devices to a group, which
has default domain configured. With both patches applied all calls to
iommu's attach/detach functions will be balanced, whenever caller
attaches device to the default domain or the custom one.

Best regards
Marek Szyprowski
Samsung R Institute Poland


Patch summary:

Marek Szyprowski (2):
  iommu: call detach also for default_domain before attaching to new one
  iommu: fix default domain handling in __iommu_detach_group()

 drivers/iommu/iommu.c | 48 +++-
 1 file changed, 27 insertions(+), 21 deletions(-)

-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 1/2] iommu: call detach also for default_domain before attaching to new one

2016-02-16 Thread Marek Szyprowski
This patch ensures that devices attached to the default_domain will be
first detached from it before attaching to new domain. To avoid forward
declaration, __iommu_attach_group() function has been moved to new place
in the source code.

Signed-off-by: Marek Szyprowski 
---
 drivers/iommu/iommu.c | 38 ++
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 0e3b009..db231ad 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1198,22 +1198,6 @@ static int iommu_group_do_attach_device(struct device 
*dev, void *data)
return __iommu_attach_device(domain, dev);
 }
 
-static int __iommu_attach_group(struct iommu_domain *domain,
-   struct iommu_group *group)
-{
-   int ret;
-
-   if (group->default_domain && group->domain != group->default_domain)
-   return -EBUSY;
-
-   ret = __iommu_group_for_each_dev(group, domain,
-iommu_group_do_attach_device);
-   if (ret == 0)
-   group->domain = domain;
-
-   return ret;
-}
-
 int iommu_attach_group(struct iommu_domain *domain, struct iommu_group *group)
 {
int ret;
@@ -1235,6 +1219,28 @@ static int iommu_group_do_detach_device(struct device 
*dev, void *data)
return 0;
 }
 
+static int __iommu_attach_group(struct iommu_domain *domain,
+   struct iommu_group *group)
+{
+   int ret;
+
+   if (group->default_domain && group->domain != group->default_domain)
+   return -EBUSY;
+
+   if (group->default_domain && group->default_domain == group->domain) {
+   __iommu_group_for_each_dev(group, group->domain,
+  iommu_group_do_detach_device);
+   group->domain = NULL;
+   }
+
+   ret = __iommu_group_for_each_dev(group, domain,
+iommu_group_do_attach_device);
+   if (ret == 0)
+   group->domain = domain;
+
+   return ret;
+}
+
 static void __iommu_detach_group(struct iommu_domain *domain,
 struct iommu_group *group)
 {
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 2/2] iommu: fix default domain handling in __iommu_detach_group()

2016-02-16 Thread Marek Szyprowski
This patch ensures that all devices will be first detached from the
provided domain and then attached to the default_domain if such has been
provided.

Signed-off-by: Marek Szyprowski 
---
 drivers/iommu/iommu.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index db231ad..045efb0 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1246,14 +1246,14 @@ static void __iommu_detach_group(struct iommu_domain 
*domain,
 {
int ret;
 
-   if (!group->default_domain) {
-   __iommu_group_for_each_dev(group, domain,
-  iommu_group_do_detach_device);
-   group->domain = NULL;
+   if (group->domain == group->default_domain)
return;
-   }
 
-   if (group->domain == group->default_domain)
+   __iommu_group_for_each_dev(group, domain,
+  iommu_group_do_detach_device);
+   group->domain = NULL;
+
+   if (!group->default_domain)
return;
 
/* Detach by re-attaching to the default domain */
-- 
1.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v3 1/8] iommu: Add MMIO mapping type

2016-02-16 Thread Niklas Söderlund
* Robin Murphy  [2016-02-16 12:43:40 +]:

> On 16/02/16 12:06, Niklas Söderlund wrote:
> >Hi Robin,
> >
> >Thanks for your update patch I will include it in my next version. But
> >I'm sorry I do not understand, is your modification an addition or a
> >substitution to your original patch?
>
> Apologies for being confusing - that was a diff on top of the existing
> patch, to be folded in. My original patch was only handling IOMMU_MMIO for
> stage 2 PTEs, so we also need the extra code to handle the different way of
> setting the appropriate memory type in stage 1 PTEs.

That's what I though but wanted to be clear, thanks for clarifying. I
will fold the diff into your patch and keep your SoB line and send it
out with my series, hope that's a OK way for me to handle it.

Once more thanks for your patch and feedback.

>
> Robin.
>
> >* Robin Murphy  [2016-02-11 15:57:26 +]:
> >
> >>On 11/02/16 00:02, Laurent Pinchart wrote:
> >>>Hi Niklas,
> >>>
> >>>Thank you for the patch.
> >>>
> >>>On Wednesday 10 February 2016 01:57:51 Niklas Söderlund wrote:
> From: Robin Murphy 
> 
> On some platforms, MMIO regions might need slightly different treatment
> compared to mapping regular memory; add the notion of MMIO mappings to
> the IOMMU API's memory type flags, so that callers can let the IOMMU
> drivers know to do the right thing.
> 
> Signed-off-by: Robin Murphy 
> Acked-by: Laurent Pinchart 
> >>>
> >>>Answering the question from the cover letter, yes, it's totally fine to 
> >>>pick
> >>>the ack, that's actually expected.
> >>>
> ---
>   drivers/iommu/io-pgtable-arm.c | 4 +++-
>   include/linux/iommu.h  | 1 +
> >>>
> >>>You might be asked to split this patch in two.
> >>
> >>Worse than that, you might also be asked to fix it up when the silly author
> >>remembers that he did this on a stage-2-only ARM SMMU, and the attributes
> >>for the stage 1 tables that the IPMMU uses are in a different code path:
> >>
> >>--->8---
> >>diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
> >>index 5b5c299..7622c6e 100644
> >>--- a/drivers/iommu/io-pgtable-arm.c
> >>+++ b/drivers/iommu/io-pgtable-arm.c
> >>@@ -354,7 +354,10 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct
> >>arm_lpae_io_pgtable *data,
> >> if (!(prot & IOMMU_WRITE) && (prot & IOMMU_READ))
> >> pte |= ARM_LPAE_PTE_AP_RDONLY;
> >>
> >>-   if (prot & IOMMU_CACHE)
> >>+   if (prot & IOMMU_MMIO)
> >>+   pte |= (ARM_LPAE_MAIR_ATTR_IDX_DEV
> >>+   << ARM_LPAE_PTE_ATTRINDX_SHIFT);
> >>+   else if (prot & IOMMU_CACHE)
> >> pte |= (ARM_LPAE_MAIR_ATTR_IDX_CACHE
> >> << ARM_LPAE_PTE_ATTRINDX_SHIFT);
> >> } else {
> >>--->8---
> >>
> >>Sorry for the bother,
> >>Robin.
> >>
>   2 files changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/iommu/io-pgtable-arm.c 
> b/drivers/iommu/io-pgtable-arm.c
> index 381ca5a..3ff4f87 100644
> --- a/drivers/iommu/io-pgtable-arm.c
> +++ b/drivers/iommu/io-pgtable-arm.c
> @@ -364,7 +364,9 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct
> arm_lpae_io_pgtable *data, pte |= ARM_LPAE_PTE_HAP_READ;
>   if (prot & IOMMU_WRITE)
>   pte |= ARM_LPAE_PTE_HAP_WRITE;
> - if (prot & IOMMU_CACHE)
> + if (prot & IOMMU_MMIO)
> + pte |= ARM_LPAE_PTE_MEMATTR_DEV;
> + else if (prot & IOMMU_CACHE)
>   pte |= ARM_LPAE_PTE_MEMATTR_OIWB;
>   else
>   pte |= ARM_LPAE_PTE_MEMATTR_NC;
> diff --git a/include/linux/iommu.h b/include/linux/iommu.h
> index a5c539f..34b6432 100644
> --- a/include/linux/iommu.h
> +++ b/include/linux/iommu.h
> @@ -30,6 +30,7 @@
>   #define IOMMU_WRITE (1 << 1)
>   #define IOMMU_CACHE (1 << 2) /* DMA cache coherency */
>   #define IOMMU_NOEXEC(1 << 3)
> +#define IOMMU_MMIO   (1 << 4) /* e.g. things like MSI doorbells */
> 
>   struct iommu_ops;
>   struct iommu_group;
> >>>
> >>
> >
>
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v3 1/8] iommu: Add MMIO mapping type

2016-02-16 Thread Robin Murphy

On 16/02/16 12:06, Niklas Söderlund wrote:

Hi Robin,

Thanks for your update patch I will include it in my next version. But
I'm sorry I do not understand, is your modification an addition or a
substitution to your original patch?


Apologies for being confusing - that was a diff on top of the existing 
patch, to be folded in. My original patch was only handling IOMMU_MMIO 
for stage 2 PTEs, so we also need the extra code to handle the different 
way of setting the appropriate memory type in stage 1 PTEs.


Robin.


* Robin Murphy  [2016-02-11 15:57:26 +]:


On 11/02/16 00:02, Laurent Pinchart wrote:

Hi Niklas,

Thank you for the patch.

On Wednesday 10 February 2016 01:57:51 Niklas Söderlund wrote:

From: Robin Murphy 

On some platforms, MMIO regions might need slightly different treatment
compared to mapping regular memory; add the notion of MMIO mappings to
the IOMMU API's memory type flags, so that callers can let the IOMMU
drivers know to do the right thing.

Signed-off-by: Robin Murphy 
Acked-by: Laurent Pinchart 


Answering the question from the cover letter, yes, it's totally fine to pick
the ack, that's actually expected.


---
  drivers/iommu/io-pgtable-arm.c | 4 +++-
  include/linux/iommu.h  | 1 +


You might be asked to split this patch in two.


Worse than that, you might also be asked to fix it up when the silly author
remembers that he did this on a stage-2-only ARM SMMU, and the attributes
for the stage 1 tables that the IPMMU uses are in a different code path:

--->8---
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 5b5c299..7622c6e 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -354,7 +354,10 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct
arm_lpae_io_pgtable *data,
 if (!(prot & IOMMU_WRITE) && (prot & IOMMU_READ))
 pte |= ARM_LPAE_PTE_AP_RDONLY;

-   if (prot & IOMMU_CACHE)
+   if (prot & IOMMU_MMIO)
+   pte |= (ARM_LPAE_MAIR_ATTR_IDX_DEV
+   << ARM_LPAE_PTE_ATTRINDX_SHIFT);
+   else if (prot & IOMMU_CACHE)
 pte |= (ARM_LPAE_MAIR_ATTR_IDX_CACHE
 << ARM_LPAE_PTE_ATTRINDX_SHIFT);
 } else {
--->8---

Sorry for the bother,
Robin.


  2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 381ca5a..3ff4f87 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -364,7 +364,9 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct
arm_lpae_io_pgtable *data, pte |= ARM_LPAE_PTE_HAP_READ;
if (prot & IOMMU_WRITE)
pte |= ARM_LPAE_PTE_HAP_WRITE;
-   if (prot & IOMMU_CACHE)
+   if (prot & IOMMU_MMIO)
+   pte |= ARM_LPAE_PTE_MEMATTR_DEV;
+   else if (prot & IOMMU_CACHE)
pte |= ARM_LPAE_PTE_MEMATTR_OIWB;
else
pte |= ARM_LPAE_PTE_MEMATTR_NC;
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index a5c539f..34b6432 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -30,6 +30,7 @@
  #define IOMMU_WRITE   (1 << 1)
  #define IOMMU_CACHE   (1 << 2) /* DMA cache coherency */
  #define IOMMU_NOEXEC  (1 << 3)
+#define IOMMU_MMIO (1 << 4) /* e.g. things like MSI doorbells */

  struct iommu_ops;
  struct iommu_group;








___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v3 1/8] iommu: Add MMIO mapping type

2016-02-16 Thread Niklas Söderlund
Hi Robin,

Thanks for your update patch I will include it in my next version. But
I'm sorry I do not understand, is your modification an addition or a
substitution to your original patch?

* Robin Murphy  [2016-02-11 15:57:26 +]:

> On 11/02/16 00:02, Laurent Pinchart wrote:
> >Hi Niklas,
> >
> >Thank you for the patch.
> >
> >On Wednesday 10 February 2016 01:57:51 Niklas Söderlund wrote:
> >>From: Robin Murphy 
> >>
> >>On some platforms, MMIO regions might need slightly different treatment
> >>compared to mapping regular memory; add the notion of MMIO mappings to
> >>the IOMMU API's memory type flags, so that callers can let the IOMMU
> >>drivers know to do the right thing.
> >>
> >>Signed-off-by: Robin Murphy 
> >>Acked-by: Laurent Pinchart 
> >
> >Answering the question from the cover letter, yes, it's totally fine to pick
> >the ack, that's actually expected.
> >
> >>---
> >>  drivers/iommu/io-pgtable-arm.c | 4 +++-
> >>  include/linux/iommu.h  | 1 +
> >
> >You might be asked to split this patch in two.
>
> Worse than that, you might also be asked to fix it up when the silly author
> remembers that he did this on a stage-2-only ARM SMMU, and the attributes
> for the stage 1 tables that the IPMMU uses are in a different code path:
>
> --->8---
> diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
> index 5b5c299..7622c6e 100644
> --- a/drivers/iommu/io-pgtable-arm.c
> +++ b/drivers/iommu/io-pgtable-arm.c
> @@ -354,7 +354,10 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct
> arm_lpae_io_pgtable *data,
> if (!(prot & IOMMU_WRITE) && (prot & IOMMU_READ))
> pte |= ARM_LPAE_PTE_AP_RDONLY;
>
> -   if (prot & IOMMU_CACHE)
> +   if (prot & IOMMU_MMIO)
> +   pte |= (ARM_LPAE_MAIR_ATTR_IDX_DEV
> +   << ARM_LPAE_PTE_ATTRINDX_SHIFT);
> +   else if (prot & IOMMU_CACHE)
> pte |= (ARM_LPAE_MAIR_ATTR_IDX_CACHE
> << ARM_LPAE_PTE_ATTRINDX_SHIFT);
> } else {
> --->8---
>
> Sorry for the bother,
> Robin.
>
> >>  2 files changed, 4 insertions(+), 1 deletion(-)
> >>
> >>diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
> >>index 381ca5a..3ff4f87 100644
> >>--- a/drivers/iommu/io-pgtable-arm.c
> >>+++ b/drivers/iommu/io-pgtable-arm.c
> >>@@ -364,7 +364,9 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct
> >>arm_lpae_io_pgtable *data, pte |= ARM_LPAE_PTE_HAP_READ;
> >>if (prot & IOMMU_WRITE)
> >>pte |= ARM_LPAE_PTE_HAP_WRITE;
> >>-   if (prot & IOMMU_CACHE)
> >>+   if (prot & IOMMU_MMIO)
> >>+   pte |= ARM_LPAE_PTE_MEMATTR_DEV;
> >>+   else if (prot & IOMMU_CACHE)
> >>pte |= ARM_LPAE_PTE_MEMATTR_OIWB;
> >>else
> >>pte |= ARM_LPAE_PTE_MEMATTR_NC;
> >>diff --git a/include/linux/iommu.h b/include/linux/iommu.h
> >>index a5c539f..34b6432 100644
> >>--- a/include/linux/iommu.h
> >>+++ b/include/linux/iommu.h
> >>@@ -30,6 +30,7 @@
> >>  #define IOMMU_WRITE   (1 << 1)
> >>  #define IOMMU_CACHE   (1 << 2) /* DMA cache coherency */
> >>  #define IOMMU_NOEXEC  (1 << 3)
> >>+#define IOMMU_MMIO (1 << 4) /* e.g. things like MSI doorbells */
> >>
> >>  struct iommu_ops;
> >>  struct iommu_group;
> >
>
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu