Re: [PATCH v9 0/7] KVM PCIe/MSI passthrough on ARM/ARM64: kernel part 3/3: vfio changes

2016-06-08 Thread Alex Williamson
On Wed, 8 Jun 2016 10:29:35 +0200
Auger Eric  wrote:

> Dear all,
> Le 20/05/2016 à 18:01, Eric Auger a écrit :
> > Alex, Robin,
> > 
> > While my 3 part series primarily addresses the problematic of mapping
> > MSI doorbells into arm-smmu, it fails in :
> > 
> > 1) determining whether the MSI controller is downstream or upstream to
> > the IOMMU,  
> > => indicates whether the MSI doorbell must be mapped
> > => participates in the decision about 2)  
> > 
> > 2) determining whether it is safe to assign a PCIe device.
> > 
> > I think we share this understanding with Robin. All above of course
> > stands for ARM.
> > 
> > I get stuck with those 2 issues and I have few questions about iommu
> > group setup, PCIe, iommu dt/ACPI description. I would be grateful to you
> > if you could answer part of those questions and advise about the
> > strategy to fix those.  
> 
> gentle reminder about the questions below; hope I did not miss any reply.
> If anybody has some time to spent on this topic...
> 
> > 
> > Best Regards
> > 
> > Eric
> > 
> > QUESTIONS:
> > 
> > 1) Robin, you pointed some host controllers which also are MSI
> > controllers
> > (http://thread.gmane.org/gmane.linux.kernel.pci/47174/focus=47268). In
> > that case MSIs never reach the IOMMU. I failed in finding anything about
> > MSIs in PCIe ACS spec. What should be the iommu groups in that
> > situation. Isn't the upstreamed code able to see some DMA transfers are
> > not properly isolated and alias devices in the same group? According to
> > your security warning, Alex, I would think the code does not recognize
> > it, can you confirm please?  
> my current understanding is end points would be in separate groups (assuming
> ACS support) although MSI controller frame is not properly protected.

We don't currently consider MSI differently from other DMA and we don't
currently have any sort of concept of a device within the intermediate
fabric as being a DMA target.  We expect fabric devices to only be
transaction routers.  We use ACS to determine whether there's any
possibility of DMA being redirected before it reaches the IOMMU, but it
seems that a DMA being consumed by an interrupt controller before it
reaches the IOMMU would be another cause for an isolation breach.
 
> > 2) can other PCIe components be MSI controllers?

I'm not even entirely sure what this means.  Would a DMA write from an
endpoint target the MMIO space of an intermediate, fabric device?
 
> > 3) Am I obliged to consider arbitrary topologies where an MSI controller
> > stands between the PCIe host and the iommu? in the PCIe space or
> > platform space? If this only relates to PCIe couldn' I check if an MSI
> > controller exists in the PCIe tree?  
> In my last series, I consider the assignment of platform device unsafe as
> soon as there is a GICv2m. This is a change in the user experience compared to
> what we have before.

If the MSI controller is downstream of our DMA translation, it doesn't
seem like we have much choice but to mark it unsafe.  The endpoint is
fully able to attempt to exploit it.
 
> > 4) Robin suggested in a private thread to enumerate through a list of
> > "registered" doorbells and if any belongs to an unsafe MSI controller,
> > consider the assignment is unsafe. This would be a first step before
> > doing something more complex. Alex, would that be acceptable to you for
> > issue #2?  
> I implemented this technique in my last series waiting for more discussion
> on 4, 5.

Seems sufficient.  I don't mind taking a broad swing versus all the
extra complexity of defining which devices are safe vs unsafe.
 
> > 5) About issue #1: don't we miss tools in dt/ACPI to describe the
> > location of the iommu on ARM? This is not needed on x86 because
> > irq_remapping and IOMMU are at the same place but my understanding is
> > that it is on ARM where
> > - there is no connection between the MSI controller - which implements
> > irq remapping - and the iommu
> > - MSI are conveyed on the same address space as standard memory
> > transactions.

It seems pretty dubious to me to have fixed address, unprotected MSI
controllers sitting in the DMA space of a device before IOMMU
translation.  Seems like you not only need to mark interrupts as
unsafe, but exclude the address space of the MSI controller from the
available IOVA space to the user.
 
> > 6)  can't we live with iommu/MSI controller respective location uncertainty?
> > 
> > - in my current series, with the above Xilinx MSI controller, I would
> > see there is an arm-smmu requiring mapping behind the PCI host, would
> > query the characteristics of the MSI doorbell (not implemented by that
> > controller), so no mapping would be done. So it would work I think.
> > - However in case we have this topology: PCIe host -> MSI controller
> > generally used behind an IOMMU (so registering a doorbell) -> IOMMU,
> > this wouldn't work since the doorbell would be mapped.  

I'm a little 

[RFC PATCH 15/15] iommu/exynos: update to use iommu big-endian

2016-06-08 Thread Matthew Leach
From: Ben Dooks 

Add initial support for big endian by always writing the pte
in le32. Note, revisit if hardware capable of doing big endian
fetches.

Signed-off-by: Ben Dooks 
---
Cc: Marek Szyprowski 
Cc: Joerg Roedel 
Cc: Kukjin Kim 
Cc: Krzysztof Kozlowski 
Cc: iommu@lists.linux-foundation.org
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-samsung-...@vger.kernel.org
Cc: linux-ker...@vger.kernel.org (open list)
---
 drivers/iommu/exynos-iommu.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 5ecc86c..dd8b3b3 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -54,6 +54,10 @@ typedef u32 sysmmu_pte_t;
 #define lv2ent_small(pent) ((*(pent) & 2) == 2)
 #define lv2ent_large(pent) ((*(pent) & 3) == 1)
 
+#ifdef CONFIG_BIG_ENDIAN
+#warning "revisit driver if we can enable big-endian ptes"
+#endif
+
 /*
  * v1.x - v3.x SYSMMU supports 32bit physical and 32bit virtual address spaces
  * v5.0 introduced support for 36bit physical address space by shifting
@@ -716,7 +720,7 @@ static inline void update_pte(sysmmu_pte_t *ent, 
sysmmu_pte_t val)
 {
dma_sync_single_for_cpu(dma_dev, virt_to_phys(ent), sizeof(*ent),
DMA_TO_DEVICE);
-   *ent = val;
+   *ent = cpu_to_le32(val);
dma_sync_single_for_device(dma_dev, virt_to_phys(ent), sizeof(*ent),
   DMA_TO_DEVICE);
 }
-- 
2.8.3

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


Re: [PATCH 1/3] PM / Runtime: Add notifiers for device runtime PM events

2016-06-08 Thread Rafael J. Wysocki
On Wed, Jun 8, 2016 at 12:25 PM, Marek Szyprowski
 wrote:
> From: Krzysztof Kozlowski 
>
> Allow drivers registering for certain runtime PM events of other
> devices. Some drivers in power domain are more or less coupled. When one
> driver is suspending (thus leading to power domain being also turned
> off) the other might have to perform some necessary steps. For example
> Exynos IOMMU has to save its context.
>
> Based on previous work of Sylwester Nawrocki .
>
> Signed-off-by: Krzysztof Kozlowski 
> Signed-off-by: Marek Szyprowski 

No, this is not the right way to address this and using notifiers for
that is just wrong (because of the potential ordering issues).

Also, the problem is not limited to runtime PM, but also to system
suspend/resume and initialization/shutdown.

I posted a series of device dependencies patches a few months ago that
might help to address this problem, but there was almost no interest
in it at that time.

Thanks,
Rafael


> ---
>  drivers/base/power/generic_ops.c |  9 +++
>  drivers/base/power/power.h   |  6 +
>  drivers/base/power/runtime.c | 34 +--
>  include/linux/pm.h   |  2 ++
>  include/linux/pm_runtime.h   | 51 
> 
>  5 files changed, 100 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/base/power/generic_ops.c 
> b/drivers/base/power/generic_ops.c
> index 07c3c4a9522d..f0838229b781 100644
> --- a/drivers/base/power/generic_ops.c
> +++ b/drivers/base/power/generic_ops.c
> @@ -10,6 +10,7 @@
>  #include 
>  #include 
>  #include 
> +#include "power.h"
>
>  #ifdef CONFIG_PM
>  /**
> @@ -25,8 +26,12 @@ int pm_generic_runtime_suspend(struct device *dev)
> const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
> int ret;
>
> +   pm_runtime_notifier_call(dev, RPM_EVENT_SUSPEND_PRE);
> +
> ret = pm && pm->runtime_suspend ? pm->runtime_suspend(dev) : 0;
>
> +   pm_runtime_notifier_call(dev, RPM_EVENT_SUSPEND_POST);
> +
> return ret;
>  }
>  EXPORT_SYMBOL_GPL(pm_generic_runtime_suspend);
> @@ -44,8 +49,12 @@ int pm_generic_runtime_resume(struct device *dev)
> const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
> int ret;
>
> +   pm_runtime_notifier_call(dev, RPM_EVENT_RESUME_PRE);
> +
> ret = pm && pm->runtime_resume ? pm->runtime_resume(dev) : 0;
>
> +   pm_runtime_notifier_call(dev, RPM_EVENT_RESUME_POST);
> +
> return ret;
>  }
>  EXPORT_SYMBOL_GPL(pm_generic_runtime_resume);
> diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
> index 50e30e7b059d..30b6319ce96c 100644
> --- a/drivers/base/power/power.h
> +++ b/drivers/base/power/power.h
> @@ -1,4 +1,5 @@
>  #include 
> +#include 
>
>  static inline void device_pm_init_common(struct device *dev)
>  {
> @@ -20,6 +21,7 @@ static inline void pm_runtime_early_init(struct device *dev)
>  extern void pm_runtime_init(struct device *dev);
>  extern void pm_runtime_reinit(struct device *dev);
>  extern void pm_runtime_remove(struct device *dev);
> +extern int pm_runtime_notifier_call(struct device *dev, enum rpm_event 
> event);
>
>  struct wake_irq {
> struct device *dev;
> @@ -87,6 +89,10 @@ static inline void pm_runtime_early_init(struct device 
> *dev)
>  static inline void pm_runtime_init(struct device *dev) {}
>  static inline void pm_runtime_reinit(struct device *dev) {}
>  static inline void pm_runtime_remove(struct device *dev) {}
> +static inline pm_runtime_notifier_call(struct device *dev, enum rpm_event 
> event)
> +{
> +   return 0;
> +}
>
>  static inline int dpm_sysfs_add(struct device *dev) { return 0; }
>  static inline void dpm_sysfs_remove(struct device *dev) {}
> diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
> index b74690418504..3a5637ca8400 100644
> --- a/drivers/base/power/runtime.c
> +++ b/drivers/base/power/runtime.c
> @@ -227,6 +227,27 @@ void pm_runtime_set_memalloc_noio(struct device *dev, 
> bool enable)
>  }
>  EXPORT_SYMBOL_GPL(pm_runtime_set_memalloc_noio);
>
> +int pm_runtime_notifier_call(struct device *dev, enum rpm_event event)
> +{
> +   return atomic_notifier_call_chain(>power.runtime_notifier,
> + event, dev);
> +}
> +
> +int pm_runtime_register_notifier(struct device *dev, struct notifier_block 
> *nb)
> +{
> +   return atomic_notifier_chain_register(>power.runtime_notifier,
> + nb);
> +}
> +EXPORT_SYMBOL_GPL(pm_runtime_register_notifier);
> +
> +int pm_runtime_unregister_notifier(struct device *dev,
> +   struct notifier_block *nb)
> +{
> +   return atomic_notifier_chain_unregister(>power.runtime_notifier,
> +   nb);
> +}
> 

Re: [RESEND PATCH] iommu/rockchip: fix zap cache during device attach

2016-06-08 Thread Heiko Stübner
Hi Joerg,

Am Mittwoch, 1. Juni 2016, 16:46:10 schrieb John Keeping:
> rk_iommu_command() takes a struct rk_iommu and iterates over the slave
> MMUs, so this is doubly wrong in that we're passing in the wrong pointer
> and talking to MMUs that we shouldn't be.
> 
> Fixes: cd6438c5f844 ("iommu/rockchip: Reconstruct to support multi slaves")
> Cc: sta...@vger.kernel.org
> Signed-off-by: John Keeping 
> Tested-by: Heiko Stuebner 
> Reviewed-by: Heiko Stuebner 

this definitly looks like material for 4.7-rc fixes to me. Could you take a 
look 
and maybe include it?


Thanks
Heiko

> ---
> The original was sent just before the merge window [0].  The only
> changes are to the commit message:
> 
> * add Cc: stable
> * add Heiko's {Tested,Reviewed}-by
> 
> [0] http://article.gmane.org/gmane.linux.kernel.iommu/13556
> 
>  drivers/iommu/rockchip-iommu.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
> index c7d6156ff536..25b4627cb57f 100644
> --- a/drivers/iommu/rockchip-iommu.c
> +++ b/drivers/iommu/rockchip-iommu.c
> @@ -815,7 +815,7 @@ static int rk_iommu_attach_device(struct iommu_domain
> *domain, dte_addr = virt_to_phys(rk_domain->dt);
>   for (i = 0; i < iommu->num_mmu; i++) {
>   rk_iommu_write(iommu->bases[i], RK_MMU_DTE_ADDR, dte_addr);
> - rk_iommu_command(iommu->bases[i], RK_MMU_CMD_ZAP_CACHE);
> + rk_iommu_base_command(iommu->bases[i], RK_MMU_CMD_ZAP_CACHE);
>   rk_iommu_write(iommu->bases[i], RK_MMU_INT_MASK, 
> RK_MMU_IRQ_MASK);
>   }

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


[PATCH v2 6/7] iommu/rockchip: use DMA API to map, to flush cache

2016-06-08 Thread Shunqian Zheng
Use DMA API instead of architecture internal functions like
__cpuc_flush_dcache_area() etc.

To support the virtual device like DRM the virtual slave iommu
added in the previous patch, attaching to which the DRM can use
it own domain->dev for dma_map_*(), dma_sync_*() even VOP is disabled.

With this patch, this driver is available for ARM64 like RK3399.

Signed-off-by: Shunqian Zheng 
---
 drivers/iommu/rockchip-iommu.c | 113 ++---
 1 file changed, 71 insertions(+), 42 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index d6c3051..aafea6e 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -4,8 +4,6 @@
  * published by the Free Software Foundation.
  */
 
-#include 
-#include 
 #include 
 #include 
 #include 
@@ -61,8 +59,7 @@
 #define RK_MMU_IRQ_BUS_ERROR 0x02  /* bus read error */
 #define RK_MMU_IRQ_MASK  (RK_MMU_IRQ_PAGE_FAULT | RK_MMU_IRQ_BUS_ERROR)
 
-#define NUM_DT_ENTRIES 1024
-#define NUM_PT_ENTRIES 1024
+#define NUM_TLB_ENTRIES 1024 /* for both DT and PT */
 
 #define SPAGE_ORDER 12
 #define SPAGE_SIZE (1 << SPAGE_ORDER)
@@ -82,7 +79,9 @@
 
 struct rk_iommu_domain {
struct list_head iommus;
+   struct device *dev;
u32 *dt; /* page directory table */
+   dma_addr_t dt_dma;
spinlock_t iommus_lock; /* lock for iommus list */
spinlock_t dt_lock; /* lock for modifying page directory table */
 
@@ -98,14 +97,12 @@ struct rk_iommu {
struct iommu_domain *domain; /* domain to which iommu is attached */
 };
 
-static inline void rk_table_flush(u32 *va, unsigned int count)
+static inline void rk_table_flush(struct device *dev, dma_addr_t dma,
+ unsigned int count)
 {
-   phys_addr_t pa_start = virt_to_phys(va);
-   phys_addr_t pa_end = virt_to_phys(va + count);
-   size_t size = pa_end - pa_start;
+   size_t size = count * 4;
 
-   __cpuc_flush_dcache_area(va, size);
-   outer_flush_range(pa_start, pa_end);
+   dma_sync_single_range_for_device(dev, dma, 0, size, DMA_TO_DEVICE);
 }
 
 static struct rk_iommu_domain *to_rk_domain(struct iommu_domain *dom)
@@ -188,10 +185,9 @@ static inline bool rk_dte_is_pt_valid(u32 dte)
return dte & RK_DTE_PT_VALID;
 }
 
-static u32 rk_mk_dte(u32 *pt)
+static inline u32 rk_mk_dte(dma_addr_t pt_dma)
 {
-   phys_addr_t pt_phys = virt_to_phys(pt);
-   return (pt_phys & RK_DTE_PT_ADDRESS_MASK) | RK_DTE_PT_VALID;
+   return (pt_dma & RK_DTE_PT_ADDRESS_MASK) | RK_DTE_PT_VALID;
 }
 
 /*
@@ -609,12 +605,14 @@ static u32 *rk_dte_get_page_table(struct rk_iommu_domain 
*rk_domain,
  dma_addr_t iova)
 {
u32 *page_table, *dte_addr;
+   u32 dte_index = rk_iova_dte_index(iova);
u32 dte;
phys_addr_t pt_phys;
+   dma_addr_t pt_dma;
 
assert_spin_locked(_domain->dt_lock);
 
-   dte_addr = _domain->dt[rk_iova_dte_index(iova)];
+   dte_addr = _domain->dt[dte_index];
dte = *dte_addr;
if (rk_dte_is_pt_valid(dte))
goto done;
@@ -623,19 +621,27 @@ static u32 *rk_dte_get_page_table(struct rk_iommu_domain 
*rk_domain,
if (!page_table)
return ERR_PTR(-ENOMEM);
 
-   dte = rk_mk_dte(page_table);
-   *dte_addr = dte;
+   pt_dma = dma_map_single(rk_domain->dev, page_table,
+   SPAGE_SIZE, DMA_TO_DEVICE);
+   if (dma_mapping_error(rk_domain->dev, pt_dma)) {
+   dev_err(rk_domain->dev, "dma mapping error\n");
+   free_page((unsigned long)page_table);
+   return ERR_PTR(-ENOMEM);
+   }
 
-   rk_table_flush(page_table, NUM_PT_ENTRIES);
-   rk_table_flush(dte_addr, 1);
+   dte = rk_mk_dte(pt_dma);
+   *dte_addr = dte;
 
+   rk_table_flush(rk_domain->dev, pt_dma, NUM_TLB_ENTRIES);
+   rk_table_flush(rk_domain->dev, rk_domain->dt_dma + dte_index * 4, 1);
 done:
pt_phys = rk_dte_pt_address(dte);
return (u32 *)phys_to_virt(pt_phys);
 }
 
 static size_t rk_iommu_unmap_iova(struct rk_iommu_domain *rk_domain,
- u32 *pte_addr, dma_addr_t iova, size_t size)
+ u32 *pte_addr, dma_addr_t pte_dma,
+ size_t size)
 {
unsigned int pte_count;
unsigned int pte_total = size / SPAGE_SIZE;
@@ -650,14 +656,14 @@ static size_t rk_iommu_unmap_iova(struct rk_iommu_domain 
*rk_domain,
pte_addr[pte_count] = rk_mk_pte_invalid(pte);
}
 
-   rk_table_flush(pte_addr, pte_count);
+   rk_table_flush(rk_domain->dev, pte_dma, pte_count);
 
return pte_count * SPAGE_SIZE;
 }
 
 static int rk_iommu_map_iova(struct rk_iommu_domain *rk_domain, u32 *pte_addr,
-dma_addr_t iova, phys_addr_t paddr, size_t size,
-int prot)

[PATCH v2 7/7] iommu/rockchip: enable rockchip iommu on ARM64 platform

2016-06-08 Thread Shunqian Zheng
From: Simon Xue 

Signed-off-by: Simon Xue 
Signed-off-by: Shunqian Zheng 
---
 drivers/iommu/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index ad08603..5572621 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -218,7 +218,7 @@ config OMAP_IOMMU_DEBUG
 
 config ROCKCHIP_IOMMU
bool "Rockchip IOMMU Support"
-   depends on ARM
+   depends on ARM || ARM64
depends on ARCH_ROCKCHIP || COMPILE_TEST
select IOMMU_API
select ARM_DMA_USE_IOMMU
-- 
1.9.1

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


[PATCH v2 5/7] drm: rockchip: use common iommu api to attach iommu

2016-06-08 Thread Shunqian Zheng
Rockchip DRM used the arm special API, arm_iommu_*(), to attach
iommu for ARM32 SoCs. This patch convert to common iommu API
so it would support ARM64 like RK3399.

The general idea is domain_alloc(), attach_device() and
arch_setup_dma_ops() to set dma_ops manually for DRM at the last.

Signed-off-by: Shunqian Zheng 
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 130 +++-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   1 +
 2 files changed, 89 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index f5a68fc..7965a66 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -14,8 +14,6 @@
  * GNU General Public License for more details.
  */
 
-#include 
-
 #include 
 #include 
 #include 
@@ -24,6 +22,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_fb.h"
@@ -46,7 +46,8 @@ static bool is_support_iommu = true;
 int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
   struct device *dev)
 {
-   struct dma_iommu_mapping *mapping = drm_dev->dev->archdata.mapping;
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+   struct iommu_domain *domain = private->domain;
int ret;
 
if (!is_support_iommu)
@@ -58,16 +59,25 @@ int rockchip_drm_dma_attach_device(struct drm_device 
*drm_dev,
 
dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
 
-   return arm_iommu_attach_device(dev, mapping);
+   ret = iommu_attach_device(domain, dev);
+
+   if (ret) {
+   dev_err(dev, "Failed to attach iommu device\n");
+   return ret;
+   }
+   arch_setup_dma_ops(dev, 0x, SZ_2G,
+  (struct iommu_ops *)dev->bus->iommu_ops, false);
+   return 0;
 }
 
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
struct device *dev)
 {
-   if (!is_support_iommu)
-   return;
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+   struct iommu_domain *domain = private->domain;
 
-   arm_iommu_detach_device(dev);
+   if (is_support_iommu)
+   iommu_detach_device(domain, dev);
 }
 
 int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
@@ -132,10 +142,70 @@ static void rockchip_drm_crtc_disable_vblank(struct 
drm_device *dev,
priv->crtc_funcs[pipe]->disable_vblank(crtc);
 }
 
+static int rockchip_drm_init_iommu(struct drm_device *drm_dev)
+{
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+   struct device *dev = drm_dev->dev;
+   int ret;
+
+   dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms),
+ GFP_KERNEL);
+   if (!dev->dma_parms) {
+   ret = -ENOMEM;
+   return ret;
+   }
+
+   ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
+   if (ret) {
+   dev_err(dev, "Failed to set coherent mask\n");
+   return ret;
+   }
+
+   dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
+
+   private->domain = iommu_domain_alloc(_bus_type);
+   if (!private->domain)
+   return -ENOMEM;
+
+   ret = iommu_get_dma_cookie(private->domain);
+   if (ret) {
+   dev_err(dev, "Failed to get dma cookie\n");
+   goto err_free_domain;
+   }
+
+   ret = iommu_dma_init_domain(private->domain, 0x, SZ_2G);
+   if (ret) {
+   dev_err(dev, "Failed to init domain\n");
+   goto err_put_cookie;
+   }
+
+   ret = rockchip_drm_dma_attach_device(drm_dev, dev);
+   if (ret) {
+   dev_err(dev, "Failed to attach device\n");
+   goto err_put_cookie;
+   }
+
+   return 0;
+
+err_put_cookie:
+   iommu_put_dma_cookie(private->domain);
+err_free_domain:
+   iommu_domain_free(private->domain);
+
+   return ret;
+}
+
+static void rockchip_iommu_cleanup(struct drm_device *drm_dev)
+{
+   struct rockchip_drm_private *private = drm_dev->dev_private;
+
+   iommu_put_dma_cookie(private->domain);
+   iommu_domain_free(private->domain);
+}
+
 static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags)
 {
struct rockchip_drm_private *private;
-   struct dma_iommu_mapping *mapping = NULL;
struct device *dev = drm_dev->dev;
struct drm_connector *connector;
int ret;
@@ -153,38 +223,18 @@ static int rockchip_drm_load(struct drm_device *drm_dev, 
unsigned long flags)
 
rockchip_drm_mode_config_init(drm_dev);
 
-   dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms),
- GFP_KERNEL);
-   if (!dev->dma_parms) {
-   ret = -ENOMEM;
-   goto 

[PATCH v2 4/7] ARM: dts: rockchip: add virtual iommu for display

2016-06-08 Thread Shunqian Zheng
An virtual iommu without reg or interrupts for display.
Adding this according to iommu driver changes.

Signed-off-by: Shunqian Zheng 
---
 arch/arm/boot/dts/rk3288.dtsi | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 7fa932f..4cd535f 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -219,9 +219,15 @@
clock-names = "timer", "pclk";
};
 
+   display_mmu: virtual-iommu {
+   compatible = "rockchip,iommu";
+   #iommu-cells = <0>;
+   };
+
display-subsystem {
compatible = "rockchip,display-subsystem";
ports = <_out>, <_out>;
+   iommus = <_mmu>;
};
 
sdmmc: dwmmc@ff0c {
-- 
1.9.1

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


[PATCH v2 3/7] iommu/rockchip: support virtual iommu slave device

2016-06-08 Thread Shunqian Zheng
An virtual master device like DRM need to attach to iommu
domain to share the domain with VOP(the one with actual
iommu slave). We currently check the group is NULL to indicate
a virtual master, which is not true since we decide to use
the common iommu api to attach device in DRM.

With this patch, we can probe a virtual iommu device and
allow the DRM attaching to it. The virtual iommu is needed also
because we want convert to use DMA API for map/unmap, cache flush,
so that DRM buffer alloc still work even VOP is disabled.

Signed-off-by: Shunqian Zheng 
---
 drivers/iommu/rockchip-iommu.c | 37 +
 1 file changed, 25 insertions(+), 12 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 3c16ec3..d6c3051 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -75,6 +75,11 @@
 
 #define IOMMU_REG_POLL_COUNT_FAST 1000
 
+/* A virtual iommu in device-tree registered without reg or
+ * interrupts, so the num_mmu is zero.
+ */
+#define RK_IOMMU_IS_VIRTUAL(iommu) (iommu->num_mmu == 0)
+
 struct rk_iommu_domain {
struct list_head iommus;
u32 *dt; /* page directory table */
@@ -789,13 +794,13 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
int ret, i;
phys_addr_t dte_addr;
 
-   /*
-* Allow 'virtual devices' (e.g., drm) to attach to domain.
-* Such a device does not belong to an iommu group.
-*/
iommu = rk_iommu_from_dev(dev);
-   if (!iommu)
+
+   iommu->domain = domain;
+   if (RK_IOMMU_IS_VIRTUAL(iommu)) {
+   dev_dbg(dev, "Attach virtual device to iommu domain\n");
return 0;
+   }
 
ret = rk_iommu_enable_stall(iommu);
if (ret)
@@ -805,7 +810,6 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
if (ret)
return ret;
 
-   iommu->domain = domain;
 
ret = devm_request_irq(iommu->dev, iommu->irq, rk_iommu_irq,
   IRQF_SHARED, dev_name(dev), iommu);
@@ -842,10 +846,13 @@ static void rk_iommu_detach_device(struct iommu_domain 
*domain,
unsigned long flags;
int i;
 
-   /* Allow 'virtual devices' (eg drm) to detach from domain */
iommu = rk_iommu_from_dev(dev);
-   if (!iommu)
+
+   iommu->domain = NULL;
+   if (RK_IOMMU_IS_VIRTUAL(iommu)) {
+   dev_dbg(dev, "Master with virtual iommu detached from 
domain\n");
return;
+   }
 
spin_lock_irqsave(_domain->iommus_lock, flags);
list_del_init(>node);
@@ -862,8 +869,6 @@ static void rk_iommu_detach_device(struct iommu_domain 
*domain,
 
devm_free_irq(iommu->dev, iommu->irq, iommu);
 
-   iommu->domain = NULL;
-
dev_dbg(dev, "Detached from iommu domain\n");
 }
 
@@ -1034,6 +1039,7 @@ static int rk_iommu_probe(struct platform_device *pdev)
struct device *dev = >dev;
struct rk_iommu *iommu;
struct resource *res;
+   int num_res = pdev->num_resources;
int i;
 
iommu = devm_kzalloc(dev, sizeof(*iommu), GFP_KERNEL);
@@ -1043,12 +1049,19 @@ static int rk_iommu_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, iommu);
iommu->dev = dev;
iommu->num_mmu = 0;
-   iommu->bases = devm_kzalloc(dev, sizeof(*iommu->bases) * iommu->num_mmu,
+
+   if (!num_res) {
+   iommu->bases = NULL;
+   dev_info(dev, "this is a virtual iommu\n");
+   return 0;
+   }
+
+   iommu->bases = devm_kzalloc(dev, sizeof(*iommu->bases) * num_res,
GFP_KERNEL);
if (!iommu->bases)
return -ENOMEM;
 
-   for (i = 0; i < pdev->num_resources; i++) {
+   for (i = 0; i < num_res; i++) {
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
if (!res)
continue;
-- 
1.9.1

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


[PATCH v2 2/7] iommu/rockchip: add map_sg callback for rk_iommu_ops

2016-06-08 Thread Shunqian Zheng
From: Simon Xue 

The iommu_dma_alloc() in iommu/dma-iommu.c calls iommu_map_sg()
that requires the callback iommu_ops .map_sg(). Adding the
default_iommu_map_sg() to rockchip iommu accordingly.

Signed-off-by: Simon Xue 
Signed-off-by: Shunqian Zheng 
---
 drivers/iommu/rockchip-iommu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index ec0ce62..3c16ec3 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1022,6 +1022,7 @@ static const struct iommu_ops rk_iommu_ops = {
.detach_dev = rk_iommu_detach_device,
.map = rk_iommu_map,
.unmap = rk_iommu_unmap,
+   .map_sg = default_iommu_map_sg,
.add_device = rk_iommu_add_device,
.remove_device = rk_iommu_remove_device,
.iova_to_phys = rk_iommu_iova_to_phys,
-- 
1.9.1

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


[PATCH v2 0/7] fix bugs; enable iommu for ARM64

2016-06-08 Thread Shunqian Zheng
This series patches mainly for ARM64 supporting.
To do this, it first add virtual iommu slave device which DRM can attach to,
convert DRM driver to use common iommu API instead of the ARM32
functions, and then use DMA API in iommu driver to map, to flush cache.

The v2 patches make a lot changes vs v1, so please forget the v1.

Shunqian Zheng (4):
  iommu/rockchip: support virtual iommu slave device
  ARM: dts: rockchip: add virtual iommu for display
  drm: rockchip: use common iommu api to attach iommu
  iommu/rockchip: use DMA API to map, to flush cache

Simon Xue (3):
  iommu/rockchip: fix devm_{request,free}_irq parameter
  iommu/rockchip: add map_sg callback for rk_iommu_ops
  iommu/rockchip: enable rockchip iommu on ARM64 platform

 arch/arm/boot/dts/rk3288.dtsi   |   6 ++
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 130 
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |   1 +
 drivers/iommu/Kconfig   |   2 +-
 drivers/iommu/rockchip-iommu.c  | 151 ++--
 5 files changed, 193 insertions(+), 97 deletions(-)

-- 
1.9.1

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


Re: [RFC PATCH v1 10/18] x86/efi: Access EFI related tables in the clear

2016-06-08 Thread Matt Fleming
On Tue, 26 Apr, at 05:57:40PM, Tom Lendacky wrote:
> The EFI tables are not encrypted and need to be accessed as such. Be sure
> to memmap them without the encryption attribute set. For EFI support that
> lives outside of the arch/x86 tree, create a routine that uses the __weak
> attribute so that it can be overridden by an architecture specific routine.
> 
> When freeing boot services related memory, since it has been mapped as
> un-encrypted, be sure to change the mapping to encrypted for future use.
> 
> Signed-off-by: Tom Lendacky 
> ---
>  arch/x86/include/asm/cacheflush.h  |3 +
>  arch/x86/include/asm/mem_encrypt.h |   22 +++
>  arch/x86/kernel/setup.c|6 +--
>  arch/x86/mm/mem_encrypt.c  |   56 +++
>  arch/x86/mm/pageattr.c |   75 
> 
>  arch/x86/platform/efi/efi.c|   26 +++-
>  arch/x86/platform/efi/efi_64.c |9 +++-
>  arch/x86/platform/efi/quirks.c |   12 +-
>  drivers/firmware/efi/efi.c |   18 +++--
>  drivers/firmware/efi/esrt.c|   12 +++---
>  include/linux/efi.h|3 +
>  11 files changed, 212 insertions(+), 30 deletions(-)

[...]

> diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
> index 994a7df8..871b213 100644
> --- a/arch/x86/platform/efi/efi.c
> +++ b/arch/x86/platform/efi/efi.c
> @@ -53,6 +53,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  #define EFI_DEBUG
>  
> @@ -261,12 +262,12 @@ static int __init efi_systab_init(void *phys)
>   u64 tmp = 0;
>  
>   if (efi_setup) {
> - data = early_memremap(efi_setup, sizeof(*data));
> + data = sme_early_memremap(efi_setup, sizeof(*data));
>   if (!data)
>   return -ENOMEM;
>   }

Beware, this data comes from a previous kernel that kexec'd this
kernel. Unless you've updated bzImage64_load() to allocate an
unencrypted region 'efi_setup' will in fact be encrypted.

> @@ -690,6 +691,7 @@ static void *realloc_pages(void *old_memmap, int 
> old_shift)
>   ret = (void *)__get_free_pages(GFP_KERNEL, old_shift + 1);
>   if (!ret)
>   goto out;
> + sme_set_mem_dec(ret, PAGE_SIZE << (old_shift + 1));
>  
>   /*
>* A first-time allocation doesn't have anything to copy.

I'm not sure why it's necessary to mark this region as unencrypted,
because at this point the kernel controls the platform and when we
call into the firmware it should be using our page tables. I wouldn't
expect the firmware to mess with the SYSCFG MSR either.

Have you come across a situation where the above was required?

> diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
> index 49e4dd4..834a992 100644
> --- a/arch/x86/platform/efi/efi_64.c
> +++ b/arch/x86/platform/efi/efi_64.c
> @@ -223,7 +223,7 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, 
> unsigned num_pages)
>   if (efi_enabled(EFI_OLD_MEMMAP))
>   return 0;
>  
> - efi_scratch.efi_pgt = (pgd_t *)__pa(efi_pgd);
> + efi_scratch.efi_pgt = (pgd_t *)__sme_pa(efi_pgd);
>   pgd = efi_pgd;
>  
>   /*

Huh? Why does __pa() now OR in sme_mas_mask? I thought SME only
required the page table structures to be modified, not the end
address?

> @@ -262,7 +262,8 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, 
> unsigned num_pages)
>   pfn = md->phys_addr >> PAGE_SHIFT;
>   npages = md->num_pages;
>  
> - if (kernel_map_pages_in_pgd(pgd, pfn, md->phys_addr, npages, 
> _PAGE_RW)) {
> + if (kernel_map_pages_in_pgd(pgd, pfn, md->phys_addr, npages,
> + _PAGE_RW | _PAGE_ENC)) {
>   pr_err("Failed to map 1:1 memory\n");
>   return 1;
>   }

Could you push the _PAGE_ENC addition down into
kernel_map_pages_in_pgd()? Other flags are also handled that way, see
_PAGE_PRESENT.

> @@ -272,6 +273,7 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, 
> unsigned num_pages)
>   if (!page)
>   panic("Unable to allocate EFI runtime stack < 4GB\n");
>  
> + sme_set_mem_dec(page_address(page), PAGE_SIZE);
>   efi_scratch.phys_stack = virt_to_phys(page_address(page));
>   efi_scratch.phys_stack += PAGE_SIZE; /* stack grows down */
>  

We should not need to mark the stack as unencrypted, the firmware
should respect our SME settings, right?

> diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
> index ab50ada..dde4fb6b 100644
> --- a/arch/x86/platform/efi/quirks.c
> +++ b/arch/x86/platform/efi/quirks.c
> @@ -13,6 +13,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  #define EFI_MIN_RESERVE 5120
>  
> @@ -265,6 +266,13 @@ void __init efi_free_boot_services(void)
>   

[PATCH 1/3] PM / Runtime: Add notifiers for device runtime PM events

2016-06-08 Thread Marek Szyprowski
From: Krzysztof Kozlowski 

Allow drivers registering for certain runtime PM events of other
devices. Some drivers in power domain are more or less coupled. When one
driver is suspending (thus leading to power domain being also turned
off) the other might have to perform some necessary steps. For example
Exynos IOMMU has to save its context.

Based on previous work of Sylwester Nawrocki .

Signed-off-by: Krzysztof Kozlowski 
Signed-off-by: Marek Szyprowski 
---
 drivers/base/power/generic_ops.c |  9 +++
 drivers/base/power/power.h   |  6 +
 drivers/base/power/runtime.c | 34 +--
 include/linux/pm.h   |  2 ++
 include/linux/pm_runtime.h   | 51 
 5 files changed, 100 insertions(+), 2 deletions(-)

diff --git a/drivers/base/power/generic_ops.c b/drivers/base/power/generic_ops.c
index 07c3c4a9522d..f0838229b781 100644
--- a/drivers/base/power/generic_ops.c
+++ b/drivers/base/power/generic_ops.c
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include "power.h"
 
 #ifdef CONFIG_PM
 /**
@@ -25,8 +26,12 @@ int pm_generic_runtime_suspend(struct device *dev)
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
int ret;
 
+   pm_runtime_notifier_call(dev, RPM_EVENT_SUSPEND_PRE);
+
ret = pm && pm->runtime_suspend ? pm->runtime_suspend(dev) : 0;
 
+   pm_runtime_notifier_call(dev, RPM_EVENT_SUSPEND_POST);
+
return ret;
 }
 EXPORT_SYMBOL_GPL(pm_generic_runtime_suspend);
@@ -44,8 +49,12 @@ int pm_generic_runtime_resume(struct device *dev)
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
int ret;
 
+   pm_runtime_notifier_call(dev, RPM_EVENT_RESUME_PRE);
+
ret = pm && pm->runtime_resume ? pm->runtime_resume(dev) : 0;
 
+   pm_runtime_notifier_call(dev, RPM_EVENT_RESUME_POST);
+
return ret;
 }
 EXPORT_SYMBOL_GPL(pm_generic_runtime_resume);
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index 50e30e7b059d..30b6319ce96c 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -1,4 +1,5 @@
 #include 
+#include 
 
 static inline void device_pm_init_common(struct device *dev)
 {
@@ -20,6 +21,7 @@ static inline void pm_runtime_early_init(struct device *dev)
 extern void pm_runtime_init(struct device *dev);
 extern void pm_runtime_reinit(struct device *dev);
 extern void pm_runtime_remove(struct device *dev);
+extern int pm_runtime_notifier_call(struct device *dev, enum rpm_event event);
 
 struct wake_irq {
struct device *dev;
@@ -87,6 +89,10 @@ static inline void pm_runtime_early_init(struct device *dev)
 static inline void pm_runtime_init(struct device *dev) {}
 static inline void pm_runtime_reinit(struct device *dev) {}
 static inline void pm_runtime_remove(struct device *dev) {}
+static inline pm_runtime_notifier_call(struct device *dev, enum rpm_event 
event)
+{
+   return 0;
+}
 
 static inline int dpm_sysfs_add(struct device *dev) { return 0; }
 static inline void dpm_sysfs_remove(struct device *dev) {}
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index b74690418504..3a5637ca8400 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -227,6 +227,27 @@ void pm_runtime_set_memalloc_noio(struct device *dev, bool 
enable)
 }
 EXPORT_SYMBOL_GPL(pm_runtime_set_memalloc_noio);
 
+int pm_runtime_notifier_call(struct device *dev, enum rpm_event event)
+{
+   return atomic_notifier_call_chain(>power.runtime_notifier,
+ event, dev);
+}
+
+int pm_runtime_register_notifier(struct device *dev, struct notifier_block *nb)
+{
+   return atomic_notifier_chain_register(>power.runtime_notifier,
+ nb);
+}
+EXPORT_SYMBOL_GPL(pm_runtime_register_notifier);
+
+int pm_runtime_unregister_notifier(struct device *dev,
+   struct notifier_block *nb)
+{
+   return atomic_notifier_chain_unregister(>power.runtime_notifier,
+   nb);
+}
+EXPORT_SYMBOL_GPL(pm_runtime_unregister_notifier);
+
 /**
  * rpm_check_suspend_allowed - Test whether a device may be suspended.
  * @dev: Device to test.
@@ -1174,6 +1195,7 @@ void __pm_runtime_disable(struct device *dev, bool 
check_resume)
goto out;
}
 
+   pm_runtime_notifier_call(dev, RPM_EVENT_DISABLE_PRE);
/*
 * Wake up the device if there's a resume request pending, because that
 * means there probably is some I/O to process and disabling runtime PM
@@ -1195,6 +1217,7 @@ void __pm_runtime_disable(struct device *dev, bool 
check_resume)
if (!dev->power.disable_depth++)
__pm_runtime_barrier(dev);
 
+   pm_runtime_notifier_call(dev, 

[PATCH 3/3] iommu/exynos: Add proper runtime pm support

2016-06-08 Thread Marek Szyprowski
This patch uses recently introduced runtime pm notifiers to track the
runtime pm state of the master's device. This way each SYSMMU controller
knows when its master's device is active and can save/restore its state
instead of being enabled all the time. This way SYSMMU controllers no
longer prevents respective power domains to be turned off when master's
device is not used.

Signed-off-by: Marek Szyprowski 
---
 drivers/iommu/exynos-iommu.c | 211 +--
 1 file changed, 101 insertions(+), 110 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 9d1a14f88891..de4126787c41 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -25,6 +25,7 @@
 #include 
 #include 
 #include 
+#include 
 
 typedef u32 sysmmu_iova_t;
 typedef u32 sysmmu_pte_t;
@@ -233,13 +234,14 @@ struct sysmmu_drvdata {
struct clk *aclk;   /* SYSMMU's aclk clock */
struct clk *pclk;   /* SYSMMU's pclk clock */
struct clk *clk_master; /* master's device clock */
-   int activations;/* number of calls to sysmmu_enable */
spinlock_t lock;/* lock for modyfying state */
+   int active; /* current status */
struct exynos_iommu_domain *domain; /* domain we belong to */
struct list_head domain_node;   /* node for domain clients list */
struct list_head owner_node;/* node for owner controllers list */
phys_addr_t pgtable;/* assigned page table structure */
unsigned int version;   /* our version */
+   struct notifier_block pm_nb;/* for tracking master's runtime pm */
 };
 
 static struct exynos_iommu_domain *to_exynos_domain(struct iommu_domain *dom)
@@ -247,25 +249,6 @@ static struct exynos_iommu_domain *to_exynos_domain(struct 
iommu_domain *dom)
return container_of(dom, struct exynos_iommu_domain, domain);
 }
 
-static bool set_sysmmu_active(struct sysmmu_drvdata *data)
-{
-   /* return true if the System MMU was not active previously
-  and it needs to be initialized */
-   return ++data->activations == 1;
-}
-
-static bool set_sysmmu_inactive(struct sysmmu_drvdata *data)
-{
-   /* return true if the System MMU is needed to be disabled */
-   BUG_ON(data->activations < 1);
-   return --data->activations == 0;
-}
-
-static bool is_sysmmu_active(struct sysmmu_drvdata *data)
-{
-   return data->activations > 0;
-}
-
 static void sysmmu_unblock(struct sysmmu_drvdata *data)
 {
writel(CTRL_ENABLE, data->sfrbase + REG_MMU_CTRL);
@@ -384,7 +367,7 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id)
unsigned short reg_status, reg_clear;
int ret = -ENOSYS;
 
-   WARN_ON(!is_sysmmu_active(data));
+   WARN_ON(!data->active);
 
if (MMU_MAJ_VER(data->version) < 5) {
reg_status = REG_INT_STATUS;
@@ -440,32 +423,6 @@ static void __sysmmu_disable_nocount(struct sysmmu_drvdata 
*data)
__sysmmu_disable_clocks(data);
 }
 
-static bool __sysmmu_disable(struct sysmmu_drvdata *data)
-{
-   bool disabled;
-   unsigned long flags;
-
-   spin_lock_irqsave(>lock, flags);
-
-   disabled = set_sysmmu_inactive(data);
-
-   if (disabled) {
-   data->pgtable = 0;
-   data->domain = NULL;
-
-   __sysmmu_disable_nocount(data);
-
-   dev_dbg(data->sysmmu, "Disabled\n");
-   } else  {
-   dev_dbg(data->sysmmu, "%d times left to disable\n",
-   data->activations);
-   }
-
-   spin_unlock_irqrestore(>lock, flags);
-
-   return disabled;
-}
-
 static void __sysmmu_init_config(struct sysmmu_drvdata *data)
 {
unsigned int cfg;
@@ -501,34 +458,6 @@ static void __sysmmu_enable_nocount(struct sysmmu_drvdata 
*data)
clk_disable(data->clk_master);
 }
 
-static int __sysmmu_enable(struct sysmmu_drvdata *data, phys_addr_t pgtable,
-  struct exynos_iommu_domain *domain)
-{
-   int ret = 0;
-   unsigned long flags;
-
-   spin_lock_irqsave(>lock, flags);
-   if (set_sysmmu_active(data)) {
-   data->pgtable = pgtable;
-   data->domain = domain;
-
-   __sysmmu_enable_nocount(data);
-
-   dev_dbg(data->sysmmu, "Enabled\n");
-   } else {
-   ret = (pgtable == data->pgtable) ? 1 : -EBUSY;
-
-   dev_dbg(data->sysmmu, "already enabled\n");
-   }
-
-   if (WARN_ON(ret < 0))
-   set_sysmmu_inactive(data); /* decrement count */
-
-   spin_unlock_irqrestore(>lock, flags);
-
-   return ret;
-}
-
 static void sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data,
sysmmu_iova_t iova)
 {
@@ -536,7 +465,7 @@ static void 

[PATCH 2/3] iommu/exynos: Remove excessive, useless debug

2016-06-08 Thread Marek Szyprowski
Remove excessive, useless debug about skipping TLB invalidation, which
is a normal situation when more aggressive power management is enabled.

Signed-off-by: Marek Szyprowski 
---
 drivers/iommu/exynos-iommu.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 633e6d023c0d..9d1a14f88891 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -574,9 +574,6 @@ static void sysmmu_tlb_invalidate_entry(struct 
sysmmu_drvdata *data,
sysmmu_unblock(data);
}
clk_disable(data->clk_master);
-   } else {
-   dev_dbg(data->master,
-   "disabled. Skipping TLB invalidation @ %#x\n", iova);
}
spin_unlock_irqrestore(>lock, flags);
 }
-- 
1.9.2

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


[PATCH 0/3] Exynos IOMMU: proper runtime pm support

2016-06-08 Thread Marek Szyprowski
Hello,

This patch series finally implements proper runtime pm support in Exynos
IOMMU driver. This has been achieved by adding runtime pm notifiers,
which lets SYSMMU controller to follow it's master device (the device
which actually performs DMA transaction) runtime pm. The main idea
behind this solution is an observation that any DMA activity from master
device can be done only when master device is active, thus when master
device is suspended SYSMMU controller device can also be suspended.

This patchset finally solves the situation that power domains are always
enabled, because all SYSMMU controllers (which belongs to those domains)
are permanently active (because existing driver was simplified and kept
SYSMMU device active all the time after initialization).

This patchset requires my previous changes to Exynos IOMMU driver
submitted in the "Exynos IOMMU: improve clock management" thread:
http://www.spinics.net/lists/arm-kernel/msg505695.html  

Best regards
Marek Szyprowski
Samsung R Institute Poland

Krzysztof Kozlowski (1):
  PM / Runtime: Add notifiers for device runtime PM events

Marek Szyprowski (2):
  iommu/exynos: Remove excessive, useless debug
  iommu/exynos: Add proper runtime pm support

 drivers/base/power/generic_ops.c |   9 ++
 drivers/base/power/power.h   |   6 ++
 drivers/base/power/runtime.c |  34 ++-
 drivers/iommu/exynos-iommu.c | 214 ++-
 include/linux/pm.h   |   2 +
 include/linux/pm_runtime.h   |  51 ++
 6 files changed, 201 insertions(+), 115 deletions(-)

-- 
1.9.2

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


Re: [RFC PATCH v1 10/18] x86/efi: Access EFI related tables in the clear

2016-06-08 Thread Matt Fleming
(Sorry for the delay)

On Thu, 26 May, at 08:45:58AM, Tom Lendacky wrote:
> 
> The patch in question is patch 6/18 where PAGE_KERNEL is changed to
> include the _PAGE_ENC attribute (the encryption mask). This now
> makes FIXMAP_PAGE_NORMAL contain the encryption mask while
> FIXMAP_PAGE_IO does not. In this way, anything mapped using the
> early_ioremap call won't be mapped encrypted.

There are semantics attached to early_ioremap() that do not apply in
this case; that you're mapping an MMIO region but for EFI we just care
about noting where the firmware (not the kernel) populated the region
with data. Similar problems exist for other early boot code such as
the devicetree stuff.

early_ioremap() is not the answer.

What you really want is just some way to distinguish kernel-owned
regions from those owned by "somebody else".

I have no problem updating early_memremap() to take a @flags argument
to make that distinction, provided that the naming is generic and not
tied to AMD's SME technology via an "sme" prefix/suffix.

And making it generic should allow it to be easily sprinkled into the
shared architecture code in drivers/firmware/efi/ without issue.

I'm going to follow up with some additional comments/questions on
PATCH 10.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [RESEND PATCH v2 0/6] vfio-pci: Add support for mmapping MSI-X table

2016-06-08 Thread Yongji Xie

Hi, Eric

On 2016/6/8 15:41, Auger Eric wrote:


Hi Yongji,

Le 02/06/2016 à 08:09, Yongji Xie a écrit :

Current vfio-pci implementation disallows to mmap the page
containing MSI-X table in case that users can write directly
to MSI-X table and generate an incorrect MSIs.

However, this will cause some performance issue when there
are some critical device registers in the same page as the
MSI-X table. We have to handle the mmio access to these
registers in QEMU emulation rather than in guest.

To solve this issue, this series allows to expose MSI-X table
to userspace when hardware enables the capability of interrupt
remapping which can ensure that a given PCI device can only
shoot the MSIs assigned for it. And we introduce a new bus_flags
PCI_BUS_FLAGS_MSI_REMAP to test this capability on PCI side
for different archs.

The patch 3 are based on the proposed patchset[1].

You may have noticed I sent a respin of [1] yesterday:
http://www.gossamer-threads.com/lists/linux/kernel/2455187.

Unfortunately you will see I removed the patch defining the new
msi_domain_info MSI_FLAG_IRQ_REMAPPING flag you rely on in this series.
I did so because I was not using it anymore. At the beginning this was
used to detect whether the MSI assignment was safe but this
method was covering cases where the MSI controller was
upstream to the IOMMU. So now I rely on a mechanism where MSI controller
are supposed to register their MSI doorbells and tag whether it is safe.

I don't know yet how this change will be welcomed though. Depending
on reviews/discussions, might happen we revert to the previous flag.

If you need the feature you can embed the used patches in your series and
follow the review process separately. Sorry for the setback.


Thanks for your notification. I'd better wait until your patches get
settled. Then I could exactly know which way we should use to test the
capability of interrupt remapping on ARM in my series.

Thanks,
Yongji

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

[PATCH v4 2/5] iommu/mediatek: move the common struct into header file

2016-06-08 Thread honghui.zhang
From: Honghui Zhang 

Move the struct defines of mtk iommu into a new header files for
common use.

Signed-off-by: Honghui Zhang 
---
 drivers/iommu/mtk_iommu.c | 48 +
 drivers/iommu/mtk_iommu.h | 77 +++
 2 files changed, 78 insertions(+), 47 deletions(-)
 create mode 100644 drivers/iommu/mtk_iommu.h

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index c3043d8..4f18ff5 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -34,7 +34,7 @@
 #include 
 #include 
 
-#include "io-pgtable.h"
+#include "mtk_iommu.h"
 
 #define REG_MMU_PT_BASE_ADDR   0x000
 
@@ -93,20 +93,6 @@
 
 #define MTK_PROTECT_PA_ALIGN   128
 
-struct mtk_iommu_suspend_reg {
-   u32 standard_axi_mode;
-   u32 dcm_dis;
-   u32 ctrl_reg;
-   u32 int_control0;
-   u32 int_main_control;
-};
-
-struct mtk_iommu_client_priv {
-   struct list_headclient;
-   unsigned intmtk_m4u_id;
-   struct device   *m4udev;
-};
-
 struct mtk_iommu_domain {
spinlock_t  pgtlock; /* lock for page table */
 
@@ -116,19 +102,6 @@ struct mtk_iommu_domain {
struct iommu_domain domain;
 };
 
-struct mtk_iommu_data {
-   void __iomem*base;
-   int irq;
-   struct device   *dev;
-   struct clk  *bclk;
-   phys_addr_t protect_base; /* protect memory base */
-   struct mtk_iommu_suspend_regreg;
-   struct mtk_iommu_domain *m4u_dom;
-   struct iommu_group  *m4u_group;
-   struct mtk_smi_iommusmi_imu;  /* SMI larb iommu info */
-   boolenable_4GB;
-};
-
 static struct iommu_ops mtk_iommu_ops;
 
 static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom)
@@ -552,25 +525,6 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data 
*data)
return 0;
 }
 
-static int compare_of(struct device *dev, void *data)
-{
-   return dev->of_node == data;
-}
-
-static int mtk_iommu_bind(struct device *dev)
-{
-   struct mtk_iommu_data *data = dev_get_drvdata(dev);
-
-   return component_bind_all(dev, >smi_imu);
-}
-
-static void mtk_iommu_unbind(struct device *dev)
-{
-   struct mtk_iommu_data *data = dev_get_drvdata(dev);
-
-   component_unbind_all(dev, >smi_imu);
-}
-
 static const struct component_master_ops mtk_iommu_com_ops = {
.bind   = mtk_iommu_bind,
.unbind = mtk_iommu_unbind,
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
new file mode 100644
index 000..9ed0a84
--- /dev/null
+++ b/drivers/iommu/mtk_iommu.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2015-2016 MediaTek Inc.
+ * Author: Honghui Zhang 
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _MTK_IOMMU_H_
+#define _MTK_IOMMU_H_
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "io-pgtable.h"
+
+struct mtk_iommu_suspend_reg {
+   u32 standard_axi_mode;
+   u32 dcm_dis;
+   u32 ctrl_reg;
+   u32 int_control0;
+   u32 int_main_control;
+};
+
+struct mtk_iommu_client_priv {
+   struct list_headclient;
+   unsigned intmtk_m4u_id;
+   struct device   *m4udev;
+};
+
+struct mtk_iommu_domain;
+
+struct mtk_iommu_data {
+   void __iomem*base;
+   int irq;
+   struct device   *dev;
+   struct clk  *bclk;
+   phys_addr_t protect_base; /* protect memory base */
+   struct mtk_iommu_suspend_regreg;
+   struct mtk_iommu_domain *m4u_dom;
+   struct iommu_group  *m4u_group;
+   struct mtk_smi_iommusmi_imu;  /* SMI larb iommu info */
+   boolenable_4GB;
+};
+
+static int compare_of(struct device *dev, void *data)
+{
+   return dev->of_node == data;
+}
+
+static 

[PATCH v4 1/5] dt-bindings: mediatek: add descriptions for mediatek mt2701 iommu and smi

2016-06-08 Thread honghui.zhang
From: Honghui Zhang 

This patch defines the local arbitor port IDs for mediatek SoC MT2701 and
add descriptions of binding for mediatek generation one iommu and smi.

Signed-off-by: Honghui Zhang 
Acked-by: Rob Herring 
---
 .../devicetree/bindings/iommu/mediatek,iommu.txt   | 13 +++-
 .../memory-controllers/mediatek,smi-common.txt | 21 +-
 .../memory-controllers/mediatek,smi-larb.txt   |  4 +-
 include/dt-bindings/memory/mt2701-larb-port.h  | 85 ++
 4 files changed, 115 insertions(+), 8 deletions(-)
 create mode 100644 include/dt-bindings/memory/mt2701-larb-port.h

diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt 
b/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
index cd1b1cd..53c20ca 100644
--- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
+++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
@@ -1,7 +1,9 @@
 * Mediatek IOMMU Architecture Implementation
 
-  Some Mediatek SOCs contain a Multimedia Memory Management Unit (M4U) which
-uses the ARM Short-Descriptor translation table format for address translation.
+  Some Mediatek SOCs contain a Multimedia Memory Management Unit (M4U), and
+this M4U have two generations of HW architecture. Generation one uses flat
+pagetable, and only supports 4K size page mapping. Generation two uses the
+ARM Short-Descriptor translation table format for address translation.
 
   About the M4U Hardware Block Diagram, please check below:
 
@@ -36,7 +38,9 @@ in each larb. Take a example, There are many ports like MC, 
PP, VLD in the
 video decode local arbiter, all these ports are according to the video HW.
 
 Required properties:
-- compatible : must be "mediatek,mt8173-m4u".
+- compatible : must be one of the following string:
+   "mediatek,mt2701-m4u" for mt2701 which uses generation one m4u HW.
+   "mediatek,mt8173-m4u" for mt8173 which uses generation two m4u HW.
 - reg : m4u register base and size.
 - interrupts : the interrupt of m4u.
 - clocks : must contain one entry for each clock-names.
@@ -46,7 +50,8 @@ Required properties:
according to the local arbiter index, like larb0, larb1, larb2...
 - iommu-cells : must be 1. This is the mtk_m4u_id according to the HW.
Specifies the mtk_m4u_id as defined in
-   dt-binding/memory/mt8173-larb-port.h.
+   dt-binding/memory/mt2701-larb-port.h for mt2701 and
+   dt-binding/memory/mt8173-larb-port.h for mt8173
 
 Example:
iommu: iommu@10205000 {
diff --git 
a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt 
b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
index 06a83ce..aa614b2 100644
--- 
a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
+++ 
b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
@@ -2,16 +2,31 @@ SMI (Smart Multimedia Interface) Common
 
 The hardware block diagram please check bindings/iommu/mediatek,iommu.txt
 
+Mediatek SMI have two generations of HW architecture, mt8173 uses the second
+generation of SMI HW while mt2701 uses the first generation HW of SMI.
+
+There's slight differences between the two SMI, for generation 2, the
+register which control the iommu port is at each larb's register base. But
+for generation 1, the register is at smi ao base(smi always on register
+base). Besides that, the smi async clock should be prepared and enabled for
+SMI generation 1 to transform the smi clock into emi clock domain, but that is
+not needed for SMI generation 2.
+
 Required properties:
-- compatible : must be "mediatek,mt8173-smi-common"
+- compatible : must be one of :
+   "mediatek,mt2701-smi-common"
+   "mediatek,mt8173-smi-common"
 - reg : the register and size of the SMI block.
 - power-domains : a phandle to the power domain of this local arbiter.
 - clocks : Must contain an entry for each entry in clock-names.
-- clock-names : must contain 2 entries, as follows:
+- clock-names : must contain 3 entries for generation 1 smi HW and 2 entries
+  for generation 2 smi HW as follows:
   - "apb" : Advanced Peripheral Bus clock, It's the clock for setting
the register.
   - "smi" : It's the clock for transfer data and command.
-  They may be the same if both source clocks are the same.
+   They may be the same if both source clocks are the same.
+  - "async" : asynchronous clock, it help transform the smi clock into the emi
+ clock domain, this clock is only needed by generation 1 smi HW.
 
 Example:
smi_common: smi@14022000 {
diff --git 
a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt 
b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
index 55ff3b7..21277a5 100644
--- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
+++ 

[PATCH v4 0/5] MT2701 iommu support

2016-06-08 Thread honghui.zhang
From: Honghui Zhang 

  Mediatek's m4u(Multimedia Memory Management Unit) and SMI(Smart
Multimedia Interface)have two generations HW. They basically sharing the
same hardware block diagram, but have some difference as below:

  Generation one m4u only supports one layer, flat pagetable addressing,
and only supports 4K size page mapping. While generation two m4u supports 2
levels of pagetable which uses the ARM short-descriptor translation table
format for address translation.
They have slight different register base and register offset.
They have very different HW ports defines.

  Generaion one SMI has additional "async" clock which transform the smi
clock into emi clock domain, this clock should be prepared and enabled for
SMI generation one HW.
The register which control the iommu need to translation the address or not
for a particular port is located at smi ao base(smi always on register
base) for generation one SMI HW, but located at each larb's register base
for generation two HW.

This patch set add mt2701 iommu support, it's based on 4.7-rc1 and James
Liao's "Add clock support for Mediatek MT2701 v8[1]" and "Mediatek MT2701
SCPSYS power domain support v7[2]" patch.

v4:
-Rebase on 4.7-rc1.
-Do not call of_node_put call in mtk_iommu_create_mapping.

v3: https://lists.linuxfoundation.org/pipermail/iommu/2016-May/017179.html
-Rebase on "of: Implement iterator for phandles[3]" and take use of
 of_for_each_phandle.
-Forward-declare mtk_iommu_domain and implement the struct separately.
-Free the pagetable memory in mtk_iommu_domain_free
-Roll back the mapping in error case.
-Minor cleanups.

v2: https://lists.linuxfoundation.org/pipermail/iommu/2016-May/017068.html
-Fix syntax errors in dt-bindings.
-Use dma_alloc/free_coherent to allocate pagetable memory and reduce the
 streaming DMA stuff.
-Make the mtk_iommu_ops.pgsize_bitmap as ~0UL << MT2701_IOMMU_PAGE_SHIFT.
-Use macro instead of variable to indicate the pagetable size.
-Change some macro name from MTK_XXX to MT2701_XXX.

v1: http://lists.infradead.org/pipermail/linux-mediatek/2016-May/005301.html
-initial version

[1] http://lists.infradead.org/pipermail/linux-mediatek/2016-May/005439.html
[2] http://lists.infradead.org/pipermail/linux-mediatek/2016-May/005429.html
[3] https://lists.linuxfoundation.org/pipermail/iommu/2016-April/016300.html

Honghui Zhang (5):
  dt-bindings: mediatek: add descriptions for mediatek mt2701 iommu and
smi
  iommu/mediatek: move the common struct into header file
  memory/mediatek: add support for mt2701
  iommu/mediatek: add support for mtk iommu generation one HW
  ARM: dts: mt2701: add iommu/smi dtsi node for mt2701

 .../devicetree/bindings/iommu/mediatek,iommu.txt   |  13 +-
 .../memory-controllers/mediatek,smi-common.txt |  21 +-
 .../memory-controllers/mediatek,smi-larb.txt   |   4 +-
 arch/arm/boot/dts/mt2701.dtsi  |  51 ++
 drivers/iommu/Kconfig  |  18 +
 drivers/iommu/Makefile |   1 +
 drivers/iommu/mtk_iommu.c  |  48 +-
 drivers/iommu/mtk_iommu.h  |  77 +++
 drivers/iommu/mtk_iommu_v1.c   | 727 +
 drivers/memory/mtk-smi.c   | 167 -
 include/dt-bindings/memory/mt2701-larb-port.h  |  85 +++
 11 files changed, 1139 insertions(+), 73 deletions(-)
 create mode 100644 drivers/iommu/mtk_iommu.h
 create mode 100644 drivers/iommu/mtk_iommu_v1.c
 create mode 100644 include/dt-bindings/memory/mt2701-larb-port.h

-- 
1.8.1.1.dirty

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


[PATCH v4 4/5] iommu/mediatek: add support for mtk iommu generation one HW

2016-06-08 Thread honghui.zhang
From: Honghui Zhang 

Mediatek SoC's M4U has two generations of HW architcture. Generation one
uses flat, one layer pagetable, and was shipped with ARM architecture, it
only supports 4K size page mapping. MT2701 SoC uses this generation one
m4u HW. Generation two uses the ARM short-descriptor translation table
format for address translation, and was shipped with ARM64 architecture,
MT8173 uses this generation two m4u HW. All the two generation iommu HW
only have one iommu domain, and all its iommu clients share the same
iova address.

These two generation m4u HW have slit different register groups and
register offset, but most register names are the same. This patch add iommu
support for mediatek SoC mt2701.

Signed-off-by: Honghui Zhang 
---
 drivers/iommu/Kconfig|  18 ++
 drivers/iommu/Makefile   |   1 +
 drivers/iommu/mtk_iommu_v1.c | 727 +++
 3 files changed, 746 insertions(+)
 create mode 100644 drivers/iommu/mtk_iommu_v1.c

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index ad08603..32bb1e5 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -343,4 +343,22 @@ config MTK_IOMMU
 
  If unsure, say N here.
 
+config MTK_IOMMU_V1
+   bool "MTK IOMMU Version 1 (M4U gen1) Support"
+   depends on ARM
+   depends on ARCH_MEDIATEK || COMPILE_TEST
+   select ARM_DMA_USE_IOMMU
+   select IOMMU_API
+   select MEMORY
+   select MTK_SMI
+   select COMMON_CLK_MT2701_MMSYS
+   select COMMON_CLK_MT2701_IMGSYS
+   select COMMON_CLK_MT2701_VDECSYS
+   help
+ Support for the M4U on certain Mediatek SoCs. M4U generation 1 HW is
+ Multimedia Memory Managememt Unit. This option enables remapping of
+ DMA memory accesses for the multimedia subsystem.
+
+ if unsure, say N here.
+
 endif # IOMMU_SUPPORT
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index c6edb31..778baf5 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_INTEL_IOMMU_SVM) += intel-svm.o
 obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o
 obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o
 obj-$(CONFIG_MTK_IOMMU) += mtk_iommu.o
+obj-$(CONFIG_MTK_IOMMU_V1) += mtk_iommu_v1.o
 obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
 obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
 obj-$(CONFIG_ROCKCHIP_IOMMU) += rockchip-iommu.o
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
new file mode 100644
index 000..294485d
--- /dev/null
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -0,0 +1,727 @@
+/*
+ * Copyright (c) 2015-2016 MediaTek Inc.
+ * Author: Honghui Zhang 
+ *
+ * Based on driver/iommu/mtk_iommu.c
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "mtk_iommu.h"
+
+#define REG_MMU_PT_BASE_ADDR   0x000
+
+#define F_ALL_INVLD0x2
+#define F_MMU_INV_RANGE0x1
+#define F_INVLD_EN0BIT(0)
+#define F_INVLD_EN1BIT(1)
+
+#define F_MMU_FAULT_VA_MSK 0xf000
+#define MTK_PROTECT_PA_ALIGN   128
+
+#define REG_MMU_CTRL_REG   0x210
+#define F_MMU_CTRL_COHERENT_EN BIT(8)
+#define REG_MMU_IVRP_PADDR 0x214
+#define REG_MMU_INT_CONTROL0x220
+#define F_INT_TRANSLATION_FAULTBIT(0)
+#define F_INT_MAIN_MULTI_HIT_FAULT BIT(1)
+#define F_INT_INVALID_PA_FAULT BIT(2)
+#define F_INT_ENTRY_REPLACEMENT_FAULT  BIT(3)
+#define F_INT_TABLE_WALK_FAULT BIT(4)
+#define F_INT_TLB_MISS_FAULT   BIT(5)
+#define F_INT_PFH_DMA_FIFO_OVERFLOWBIT(6)
+#define F_INT_MISS_DMA_FIFO_OVERFLOW   BIT(7)
+
+#define F_MMU_TF_PROTECT_SEL(prot) (((prot) & 0x3) << 5)
+#define F_INT_CLR_BIT  BIT(12)
+
+#define REG_MMU_FAULT_ST   0x224
+#define REG_MMU_FAULT_VA   0x228
+#define REG_MMU_INVLD_PA   0x22C
+#define REG_MMU_INT_ID 0x388
+#define REG_MMU_INVALIDATE   

[PATCH v4 3/5] memory/mediatek: add support for mt2701

2016-06-08 Thread honghui.zhang
From: Honghui Zhang 

Mediatek SMI has two generations of HW architecture, mt8173 uses the
second generation of SMI HW while mt2701 uses the first generation
HW of SMI.

There's slight differences between the two generations, for generation 2,
the register which control the iommu port access PA or IOVA is at each
larb's register base. But for generation 1, the register is at smi ao
base(smi always on register base).
Besides that, the smi async clock should be prepared and enabled for SMI
generation 1 HW to transform the smi clock into emi clock domain, but is
not needed for SMI generation 2.

This patch add SMI driver for mt2701 which use generation 1 SMI HW.

Signed-off-by: Honghui Zhang 
---
 drivers/memory/mtk-smi.c | 167 ++-
 1 file changed, 149 insertions(+), 18 deletions(-)

diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index f6b5757..4afbc41 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -21,19 +21,50 @@
 #include 
 #include 
 #include 
+#include 
 
 #define SMI_LARB_MMU_EN0xf00
+#define REG_SMI_SECUR_CON_BASE 0x5c0
+
+/* every register control 8 port, register offset 0x4 */
+#define REG_SMI_SECUR_CON_OFFSET(id)   (((id) >> 3) << 2)
+#define REG_SMI_SECUR_CON_ADDR(id) \
+   (REG_SMI_SECUR_CON_BASE + REG_SMI_SECUR_CON_OFFSET(id))
+
+/*
+ * every port have 4 bit to control, bit[port + 3] control virtual or physical,
+ * bit[port + 2 : port + 1] control the domain, bit[port] control the security
+ * or non-security.
+ */
+#define SMI_SECUR_CON_VAL_MSK(id)  (~(0xf << (((id) & 0x7) << 2)))
+#define SMI_SECUR_CON_VAL_VIRT(id) BITid) & 0x7) << 2) + 3)
+/* mt2701 domain should be set to 3 */
+#define SMI_SECUR_CON_VAL_DOMAIN(id)   (0x3 << id) & 0x7) << 2) + 1))
+
+struct mtk_smi_larb_gen {
+   int port_in_larb[MTK_LARB_NR_MAX + 1];
+   void (*config_port)(struct device *);
+};
 
 struct mtk_smi {
-   struct device   *dev;
-   struct clk  *clk_apb, *clk_smi;
+   struct device   *dev;
+   struct clk  *clk_apb, *clk_smi;
+   struct clk  *clk_async; /*only needed by mt2701*/
+   void __iomem*smi_ao_base;
 };
 
 struct mtk_smi_larb { /* larb: local arbiter */
-   struct mtk_smi  smi;
-   void __iomem*base;
-   struct device   *smi_common_dev;
-   u32 *mmu;
+   struct mtk_smi  smi;
+   void __iomem*base;
+   struct device   *smi_common_dev;
+   const struct mtk_smi_larb_gen   *larb_gen;
+   int larbid;
+   u32 *mmu;
+};
+
+enum mtk_smi_gen {
+   MTK_SMI_GEN1,
+   MTK_SMI_GEN2
 };
 
 static int mtk_smi_enable(const struct mtk_smi *smi)
@@ -71,6 +102,7 @@ static void mtk_smi_disable(const struct mtk_smi *smi)
 int mtk_smi_larb_get(struct device *larbdev)
 {
struct mtk_smi_larb *larb = dev_get_drvdata(larbdev);
+   const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
int ret;
 
@@ -87,7 +119,7 @@ int mtk_smi_larb_get(struct device *larbdev)
}
 
/* Configure the iommu info for this larb */
-   writel(*larb->mmu, larb->base + SMI_LARB_MMU_EN);
+   larb_gen->config_port(larbdev);
 
return 0;
 }
@@ -126,6 +158,45 @@ mtk_smi_larb_bind(struct device *dev, struct device 
*master, void *data)
return -ENODEV;
 }
 
+static void mtk_smi_larb_config_port(struct device *dev)
+{
+   struct mtk_smi_larb *larb = dev_get_drvdata(dev);
+
+   writel(*larb->mmu, larb->base + SMI_LARB_MMU_EN);
+}
+
+
+static void mtk_smi_larb_config_port_gen1(struct device *dev)
+{
+   struct mtk_smi_larb *larb = dev_get_drvdata(dev);
+   const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
+   struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
+   int i, m4u_port_id, larb_port_num;
+   u32 sec_con_val, reg_val;
+
+   m4u_port_id = larb_gen->port_in_larb[larb->larbid];
+   larb_port_num = larb_gen->port_in_larb[larb->larbid + 1]
+   - larb_gen->port_in_larb[larb->larbid];
+
+   for (i = 0; i < larb_port_num; i++, m4u_port_id++) {
+   if (*larb->mmu & BIT(i)) {
+   /* bit[port + 3] controls the virtual or physical */
+   sec_con_val = SMI_SECUR_CON_VAL_VIRT(m4u_port_id);
+   } else {
+   /* do not need to enable m4u for this port */
+   continue;
+   }
+   reg_val = readl(common->smi_ao_base
+   + REG_SMI_SECUR_CON_ADDR(m4u_port_id));
+   reg_val &= SMI_SECUR_CON_VAL_MSK(m4u_port_id);
+   reg_val |= 

[PATCH] iommu/mediatek: Do not call of_node_put in mtk_iommu_of_xlate

2016-06-08 Thread honghui.zhang
From: Honghui Zhang 

The device_node will be released in of_iommu_configure, it may be double
released if call of_node_put in mtk_iommu_of_xlate.

Signed-off-by: Honghui Zhang 
---
 drivers/iommu/mtk_iommu.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index c3043d8..493bd3e 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -455,7 +455,6 @@ static int mtk_iommu_of_xlate(struct device *dev, struct 
of_phandle_args *args)
if (!dev->archdata.iommu) {
/* Get the m4u device */
m4updev = of_find_device_by_node(args->np);
-   of_node_put(args->np);
if (WARN_ON(!m4updev))
return -EINVAL;
 
-- 
1.8.1.1.dirty

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


Re: [PATCH 3/3] iommu/ipmmu-vmsa: Hook up r8a7796 DT matching code

2016-06-08 Thread Magnus Damm
Hi Laurent,

On Wed, Jun 8, 2016 at 5:48 PM, Laurent Pinchart
 wrote:
> Hi Geert,
>
> On Wednesday 08 Jun 2016 09:04:17 Geert Uytterhoeven wrote:
>> On Wed, Jun 8, 2016 at 2:18 AM, Laurent Pinchart wrote:
>> >> --- 0031/drivers/iommu/ipmmu-vmsa.c
>> >> +++ work/drivers/iommu/ipmmu-vmsa.c   2016-06-06 11:19:40.210607110 +0900
>> >> @@ -1074,7 +1074,7 @@ static const struct ipmmu_features ipmmu
>> >>   .twobit_imttbcr_sl0 = false,
>  >>  };
>> >>
>> >> -static const struct ipmmu_features ipmmu_features_r8a7795 = {
>> >> +static const struct ipmmu_features ipmmu_features_rcar_gen3 = {
>> >>   .use_ns_alias_offset = false,
>> >>   .has_cache_leaf_nodes = true,
>> >>   .has_eight_ctx = true,
>> >> @@ -1088,7 +1088,10 @@ static const struct of_device_id ipmmu_o
>> >>   .data = _features_default,
>> >>   }, {
>> >>   .compatible = "renesas,ipmmu-r8a7795",
>> >> - .data = _features_r8a7795,
>> >> + .data = _features_rcar_gen3,
>> >> + }, {
>> >> + .compatible = "renesas,ipmmu-r8a7796",
>> >> + .data = _features_rcar_gen3,
>> >>   }, {
>> >>   /* Terminator */
>> >>   },
>> >> @@ -1268,6 +1271,8 @@ IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "r
>> >>ipmmu_vmsa_iommu_of_setup);
>> >>  IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795",
>> >>ipmmu_vmsa_iommu_of_setup);
>> >> +IOMMU_OF_DECLARE(ipmmu_r8a7796_iommu_of, "renesas,ipmmu-r8a7796",
>> >> +  ipmmu_vmsa_iommu_of_setup);
>> >
>> > How about a Gen3 generic compatible string in addition to the SoC-specific
>> > ones ?
>>
>> Do we want to specify the number of utlbs here?
>> Does it differ between r8a7795, r8a7796, and future members?
>
> It differs between IPMMU instances on a given SoC, so if we want to specify it
> it should be a DT property.

Can you please point out which documentation that says it varies with
IPMMU instance?

Based on IMUCTRn register description "H3-ES1" has 0-31 range while
"Others" have 0-47.

Thanks,

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


Re: [PATCH 3/3] iommu/ipmmu-vmsa: Hook up r8a7796 DT matching code

2016-06-08 Thread Laurent Pinchart
Hi Geert,

On Wednesday 08 Jun 2016 09:04:17 Geert Uytterhoeven wrote:
> On Wed, Jun 8, 2016 at 2:18 AM, Laurent Pinchart wrote:
> >> --- 0031/drivers/iommu/ipmmu-vmsa.c
> >> +++ work/drivers/iommu/ipmmu-vmsa.c   2016-06-06 11:19:40.210607110 +0900
> >> @@ -1074,7 +1074,7 @@ static const struct ipmmu_features ipmmu
> >>   .twobit_imttbcr_sl0 = false,
 >>  };
> >> 
> >> -static const struct ipmmu_features ipmmu_features_r8a7795 = {
> >> +static const struct ipmmu_features ipmmu_features_rcar_gen3 = {
> >>   .use_ns_alias_offset = false,
> >>   .has_cache_leaf_nodes = true,
> >>   .has_eight_ctx = true,
> >> @@ -1088,7 +1088,10 @@ static const struct of_device_id ipmmu_o
> >>   .data = _features_default,
> >>   }, {
> >>   .compatible = "renesas,ipmmu-r8a7795",
> >> - .data = _features_r8a7795,
> >> + .data = _features_rcar_gen3,
> >> + }, {
> >> + .compatible = "renesas,ipmmu-r8a7796",
> >> + .data = _features_rcar_gen3,
> >>   }, {
> >>   /* Terminator */
> >>   },
> >> @@ -1268,6 +1271,8 @@ IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "r
> >>ipmmu_vmsa_iommu_of_setup);
> >>  IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795",
> >>ipmmu_vmsa_iommu_of_setup);
> >> +IOMMU_OF_DECLARE(ipmmu_r8a7796_iommu_of, "renesas,ipmmu-r8a7796",
> >> +  ipmmu_vmsa_iommu_of_setup);
> > 
> > How about a Gen3 generic compatible string in addition to the SoC-specific
> > ones ?
> 
> Do we want to specify the number of utlbs here?
> Does it differ between r8a7795, r8a7796, and future members?

It differs between IPMMU instances on a given SoC, so if we want to specify it 
it should be a DT property.

-- 
Regards,

Laurent Pinchart

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


Re: [PATCH 3/3] iommu/ipmmu-vmsa: Hook up r8a7796 DT matching code

2016-06-08 Thread Magnus Damm
Hi Laurent,

On Wed, Jun 8, 2016 at 9:18 AM, Laurent Pinchart
 wrote:
> Hi Magnus,
>
> Thank you for the patch.
>
> On Tuesday 07 Jun 2016 12:39:45 Magnus Damm wrote:
>> From: Magnus Damm 
>>
>> Support the r8a7796 IPMMU by sharing feature flags between
>> r8a7795 and r8a7796. Also update IOMMU_OF_DECLARE to hook
>> up the updated compat string.
>>
>> Signed-off-by: Magnus Damm 
>> ---
>>
>>  drivers/iommu/ipmmu-vmsa.c |9 +++--
>>  1 file changed, 7 insertions(+), 2 deletions(-)
>>
>> --- 0031/drivers/iommu/ipmmu-vmsa.c
>> +++ work/drivers/iommu/ipmmu-vmsa.c   2016-06-06 11:19:40.210607110 +0900
>> @@ -1074,7 +1074,7 @@ static const struct ipmmu_features ipmmu
>>   .twobit_imttbcr_sl0 = false,
>>  };
>>
>> -static const struct ipmmu_features ipmmu_features_r8a7795 = {
>> +static const struct ipmmu_features ipmmu_features_rcar_gen3 = {
>>   .use_ns_alias_offset = false,
>>   .has_cache_leaf_nodes = true,
>>   .has_eight_ctx = true,
>> @@ -1088,7 +1088,10 @@ static const struct of_device_id ipmmu_o
>>   .data = _features_default,
>>   }, {
>>   .compatible = "renesas,ipmmu-r8a7795",
>> - .data = _features_r8a7795,
>> + .data = _features_rcar_gen3,
>> + }, {
>> + .compatible = "renesas,ipmmu-r8a7796",
>> + .data = _features_rcar_gen3,
>>   }, {
>>   /* Terminator */
>>   },
>> @@ -1268,6 +1271,8 @@ IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "r
>>ipmmu_vmsa_iommu_of_setup);
>>  IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795",
>>ipmmu_vmsa_iommu_of_setup);
>> +IOMMU_OF_DECLARE(ipmmu_r8a7796_iommu_of, "renesas,ipmmu-r8a7796",
>> +  ipmmu_vmsa_iommu_of_setup);
>
> How about a Gen3 generic compatible string in addition to the SoC-specific
> ones ?

As you probably know, neither R-Car Gen2 nor R-Car Gen3 families are
finished evolving. Because of that I find speculating with DT compat
strings just potentially confusing with no apparent upside. Just going
with what we know (ie the part number) is more than good enough IMO.

Thanks,

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


Re: [PATCH 3/3] iommu/ipmmu-vmsa: Hook up r8a7796 DT matching code

2016-06-08 Thread Magnus Damm
Hi Geert,

On Wed, Jun 8, 2016 at 4:04 PM, Geert Uytterhoeven  wrote:
> Hi Laurent,
>
> On Wed, Jun 8, 2016 at 2:18 AM, Laurent Pinchart
>  wrote:
>>> --- 0031/drivers/iommu/ipmmu-vmsa.c
>>> +++ work/drivers/iommu/ipmmu-vmsa.c   2016-06-06 11:19:40.210607110 +0900
>>> @@ -1074,7 +1074,7 @@ static const struct ipmmu_features ipmmu
>>>   .twobit_imttbcr_sl0 = false,
>>>  };
>>>
>>> -static const struct ipmmu_features ipmmu_features_r8a7795 = {
>>> +static const struct ipmmu_features ipmmu_features_rcar_gen3 = {
>>>   .use_ns_alias_offset = false,
>>>   .has_cache_leaf_nodes = true,
>>>   .has_eight_ctx = true,
>>> @@ -1088,7 +1088,10 @@ static const struct of_device_id ipmmu_o
>>>   .data = _features_default,
>>>   }, {
>>>   .compatible = "renesas,ipmmu-r8a7795",
>>> - .data = _features_r8a7795,
>>> + .data = _features_rcar_gen3,
>>> + }, {
>>> + .compatible = "renesas,ipmmu-r8a7796",
>>> + .data = _features_rcar_gen3,
>>>   }, {
>>>   /* Terminator */
>>>   },
>>> @@ -1268,6 +1271,8 @@ IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "r
>>>ipmmu_vmsa_iommu_of_setup);
>>>  IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795",
>>>ipmmu_vmsa_iommu_of_setup);
>>> +IOMMU_OF_DECLARE(ipmmu_r8a7796_iommu_of, "renesas,ipmmu-r8a7796",
>>> +  ipmmu_vmsa_iommu_of_setup);
>>
>> How about a Gen3 generic compatible string in addition to the SoC-specific
>> ones ?
>
> Do we want to specify the number of utlbs here?
> Does it differ between r8a7795, r8a7796, and future members?

The utlb number is already a property of the SoC part number. So I
don't see why we want to encode this as a separate DT property instead
of going with an in-driver feature flag.

Thanks,

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


Re: [RESEND PATCH v2 0/6] vfio-pci: Add support for mmapping MSI-X table

2016-06-08 Thread Auger Eric
Hi Yongji,

Le 02/06/2016 à 08:09, Yongji Xie a écrit :
> Current vfio-pci implementation disallows to mmap the page
> containing MSI-X table in case that users can write directly
> to MSI-X table and generate an incorrect MSIs.
> 
> However, this will cause some performance issue when there
> are some critical device registers in the same page as the 
> MSI-X table. We have to handle the mmio access to these
> registers in QEMU emulation rather than in guest.
> 
> To solve this issue, this series allows to expose MSI-X table
> to userspace when hardware enables the capability of interrupt
> remapping which can ensure that a given PCI device can only
> shoot the MSIs assigned for it. And we introduce a new bus_flags
> PCI_BUS_FLAGS_MSI_REMAP to test this capability on PCI side
> for different archs.
> 
> The patch 3 are based on the proposed patchset[1].
You may have noticed I sent a respin of [1] yesterday:
http://www.gossamer-threads.com/lists/linux/kernel/2455187.

Unfortunately you will see I removed the patch defining the new
msi_domain_info MSI_FLAG_IRQ_REMAPPING flag you rely on in this series.
I did so because I was not using it anymore. At the beginning this was
used to detect whether the MSI assignment was safe but this
method was covering cases where the MSI controller was
upstream to the IOMMU. So now I rely on a mechanism where MSI controller
are supposed to register their MSI doorbells and tag whether it is safe.

I don't know yet how this change will be welcomed though. Depending
on reviews/discussions, might happen we revert to the previous flag.

If you need the feature you can embed the used patches in your series and
follow the review process separately. Sorry for the setback.

Best Regards

Eric
> 
> Changelog v2: 
> - Make the commit log more clear
> - Replace pci_bus_check_msi_remapping() with pci_bus_msi_isolated()
>   so that we could clearly know what the function does
> - Set PCI_BUS_FLAGS_MSI_REMAP in pci_create_root_bus() instead
>   of iommu_bus_notifier()
> - Reserve VFIO_REGION_INFO_FLAG_CAPS when we allow to mmap MSI-X
>   table so that we can know whether we allow to mmap MSI-X table
>   in QEMU
> 
> [1] 
> https://www.mail-archive.com/linux-kernel%40vger.kernel.org/msg1138820.html
> 
> Yongji Xie (6):
>   PCI: Add a new PCI_BUS_FLAGS_MSI_REMAP flag
>   PCI: Set PCI_BUS_FLAGS_MSI_REMAP if MSI controller enables IRQ remapping
>   PCI: Set PCI_BUS_FLAGS_MSI_REMAP if IOMMU have capability of IRQ remapping
>   iommu: Set PCI_BUS_FLAGS_MSI_REMAP on iommu driver initialization
>   pci-ioda: Set PCI_BUS_FLAGS_MSI_REMAP for IODA host bridge
>   vfio-pci: Allow to expose MSI-X table to userspace if interrupt remapping 
> is enabled
> 
>  arch/powerpc/platforms/powernv/pci-ioda.c |8 
>  drivers/iommu/iommu.c |8 
>  drivers/pci/msi.c |   15 +++
>  drivers/pci/probe.c   |7 +++
>  drivers/vfio/pci/vfio_pci.c   |   17 ++---
>  drivers/vfio/pci/vfio_pci_rdwr.c  |3 ++-
>  include/linux/msi.h   |5 -
>  include/linux/pci.h   |1 +
>  8 files changed, 59 insertions(+), 5 deletions(-)
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v4 07/07] iommu/ipmmu-vmsa: Drop LPAE Kconfig dependency

2016-06-08 Thread Magnus Damm
From: Magnus Damm 

Neither the ARM page table code enabled by IOMMU_IO_PGTABLE_LPAE
nor the IPMMU_VMSA driver actually depends on ARM_LPAE, so get
rid of the dependency.

Tested with ipmmu-vmsa on r8a7794 ALT and a kernel config using:
 # CONFIG_ARM_LPAE is not set

Signed-off-by: Magnus Damm 
Acked-by: Laurent Pinchart 
---

 Changes since V3:
 - None

 Changes since V2:
 - None

 Changes since V1:
 - Rebased on top of ARCH_RENESAS change
 - Added Acked-by from Laurent

 drivers/iommu/Kconfig |1 -
 1 file changed, 1 deletion(-)

--- 0001/drivers/iommu/Kconfig
+++ work/drivers/iommu/Kconfig  2016-06-02 22:17:14.950607110 +0900
@@ -273,7 +273,6 @@ config EXYNOS_IOMMU_DEBUG
 
 config IPMMU_VMSA
bool "Renesas VMSA-compatible IPMMU"
-   depends on ARM_LPAE
depends on ARCH_RENESAS || COMPILE_TEST
select IOMMU_API
select IOMMU_IO_PGTABLE_LPAE
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v4 01/07] iommu/ipmmu-vmsa: Remove platform data handling

2016-06-08 Thread Magnus Damm
From: Magnus Damm 

The IPMMU driver is using DT these days, and platform data is no longer
used by the driver. Remove unused code.

Signed-off-by: Magnus Damm 
Reviewed-by: Laurent Pinchart 
---

 Changes since V3:
 - None

 Changes since V2:
 - None

 Changes since V1:
 - Added Reviewed-by from Laurent

 drivers/iommu/ipmmu-vmsa.c |5 -
 1 file changed, 5 deletions(-)

--- 0001/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2016-06-02 20:43:14.090607110 +0900
@@ -766,11 +766,6 @@ static int ipmmu_probe(struct platform_d
int irq;
int ret;
 
-   if (!IS_ENABLED(CONFIG_OF) && !pdev->dev.platform_data) {
-   dev_err(>dev, "missing platform data\n");
-   return -EINVAL;
-   }
-
mmu = devm_kzalloc(>dev, sizeof(*mmu), GFP_KERNEL);
if (!mmu) {
dev_err(>dev, "cannot allocate device data\n");
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v4 03/07] iommu/ipmmu-vmsa: Break out utlb parsing code

2016-06-08 Thread Magnus Damm
From: Magnus Damm 

Break out the utlb parsing code and dev_data allocation into a
separate function. This is preparation for future code sharing.

Signed-off-by: Magnus Damm 
---

 Changes since V3:
 - Initialize "mmu" to NULL, check before accessing
 - Removed group parameter from ipmmu_init_platform_device()

 Changes since V2:
 - Included this new patch from the following series:
   [PATCH 00/04] iommu/ipmmu-vmsa: IPMMU CONFIG_IOMMU_DMA update
 - Reworked code to fit on top on previous two patches in current series.

 drivers/iommu/ipmmu-vmsa.c |   60 +++-
 1 file changed, 38 insertions(+), 22 deletions(-)

--- 0004/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2016-06-08 14:59:34.470607110 +0900
@@ -647,22 +647,15 @@ static int ipmmu_find_utlbs(struct ipmmu
return 0;
 }
 
-static int ipmmu_add_device(struct device *dev)
+static int ipmmu_init_platform_device(struct device *dev)
 {
struct ipmmu_vmsa_archdata *archdata;
struct ipmmu_vmsa_device *mmu;
-   struct iommu_group *group = NULL;
unsigned int *utlbs;
unsigned int i;
int num_utlbs;
int ret = -ENODEV;
 
-   if (dev->archdata.iommu) {
-   dev_warn(dev, "IOMMU driver already assigned to device %s\n",
-dev_name(dev));
-   return -EINVAL;
-   }
-
/* Find the master corresponding to the device. */
 
num_utlbs = of_count_phandle_with_args(dev->of_node, "iommus",
@@ -690,7 +683,7 @@ static int ipmmu_add_device(struct devic
spin_unlock(_devices_lock);
 
if (ret < 0)
-   return -ENODEV;
+   goto error;
 
for (i = 0; i < num_utlbs; ++i) {
if (utlbs[i] >= mmu->num_utlbs) {
@@ -699,6 +692,36 @@ static int ipmmu_add_device(struct devic
}
}
 
+   archdata = kzalloc(sizeof(*archdata), GFP_KERNEL);
+   if (!archdata) {
+   ret = -ENOMEM;
+   goto error;
+   }
+
+   archdata->mmu = mmu;
+   archdata->utlbs = utlbs;
+   archdata->num_utlbs = num_utlbs;
+   dev->archdata.iommu = archdata;
+   return 0;
+
+error:
+   kfree(utlbs);
+   return ret;
+}
+
+static int ipmmu_add_device(struct device *dev)
+{
+   struct ipmmu_vmsa_archdata *archdata;
+   struct ipmmu_vmsa_device *mmu = NULL;
+   struct iommu_group *group;
+   int ret;
+
+   if (dev->archdata.iommu) {
+   dev_warn(dev, "IOMMU driver already assigned to device %s\n",
+dev_name(dev));
+   return -EINVAL;
+   }
+
/* Create a device group and add the device to it. */
group = iommu_group_alloc();
if (IS_ERR(group)) {
@@ -716,16 +739,9 @@ static int ipmmu_add_device(struct devic
goto error;
}
 
-   archdata = kzalloc(sizeof(*archdata), GFP_KERNEL);
-   if (!archdata) {
-   ret = -ENOMEM;
+   ret = ipmmu_init_platform_device(dev);
+   if (ret < 0)
goto error;
-   }
-
-   archdata->mmu = mmu;
-   archdata->utlbs = utlbs;
-   archdata->num_utlbs = num_utlbs;
-   dev->archdata.iommu = archdata;
 
/*
 * Create the ARM mapping, used by the ARM DMA mapping core to allocate
@@ -736,6 +752,8 @@ static int ipmmu_add_device(struct devic
 * - Make the mapping size configurable ? We currently use a 2GB mapping
 *   at a 1GB offset to ensure that NULL VAs will fault.
 */
+   archdata = dev->archdata.iommu;
+   mmu = archdata->mmu;
if (!mmu->mapping) {
struct dma_iommu_mapping *mapping;
 
@@ -760,10 +778,8 @@ static int ipmmu_add_device(struct devic
return 0;
 
 error:
-   arm_iommu_release_mapping(mmu->mapping);
-
-   kfree(dev->archdata.iommu);
-   kfree(utlbs);
+   if (mmu)
+   arm_iommu_release_mapping(mmu->mapping);
 
dev->archdata.iommu = NULL;
 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v4 05/07] iommu/ipmmu-vmsa: Add new IOMMU_DOMAIN_DMA ops

2016-06-08 Thread Magnus Damm
From: Magnus Damm 

Introduce an alternative set of iommu_ops suitable for 64-bit ARM
as well as 32-bit ARM when CONFIG_IOMMU_DMA=y.

Signed-off-by: Magnus Damm 
---

 Changes since V3:
 - Removed group parameter from ipmmu_init_platform_device()

 Changes since V2:
 - Included this new patch from the following series:
   [PATCH 00/04] iommu/ipmmu-vmsa: IPMMU CONFIG_IOMMU_DMA update
 - Use only a single iommu_ops structure with #ifdef CONFIG_IOMMU_DMA
 - Folded in #ifdefs to handle CONFIG_ARM and CONFIG_IOMMU_DMA
 - of_xlate() is now used without #ifdefs
 - Made sure code compiles on both 32-bit and 64-bit ARM.

 drivers/iommu/ipmmu-vmsa.c |  111 
 1 file changed, 103 insertions(+), 8 deletions(-)

--- 0008/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2016-06-08 15:08:39.950607110 +0900
@@ -10,6 +10,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -22,8 +23,10 @@
 #include 
 #include 
 
+#if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
 #include 
 #include 
+#endif
 
 #include "io-pgtable.h"
 
@@ -520,14 +523,6 @@ static struct iommu_domain *__ipmmu_doma
return >io_domain;
 }
 
-static struct iommu_domain *ipmmu_domain_alloc(unsigned type)
-{
-   if (type != IOMMU_DOMAIN_UNMANAGED)
-   return NULL;
-
-   return __ipmmu_domain_alloc(type);
-}
-
 static void ipmmu_domain_free(struct iommu_domain *io_domain)
 {
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
@@ -714,6 +709,8 @@ error:
return ret;
 }
 
+#if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
+
 static int ipmmu_add_device(struct device *dev)
 {
struct ipmmu_vmsa_archdata *archdata;
@@ -807,6 +804,14 @@ static void ipmmu_remove_device(struct d
dev->archdata.iommu = NULL;
 }
 
+static struct iommu_domain *ipmmu_domain_alloc(unsigned type)
+{
+   if (type != IOMMU_DOMAIN_UNMANAGED)
+   return NULL;
+
+   return __ipmmu_domain_alloc(type);
+}
+
 static const struct iommu_ops ipmmu_ops = {
.domain_alloc = ipmmu_domain_alloc,
.domain_free = ipmmu_domain_free,
@@ -821,6 +826,94 @@ static const struct iommu_ops ipmmu_ops
.pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K,
 };
 
+#endif /* !CONFIG_ARM && CONFIG_IOMMU_DMA */
+
+#ifdef CONFIG_IOMMU_DMA
+
+static struct iommu_domain *ipmmu_domain_alloc_dma(unsigned type)
+{
+   struct iommu_domain *io_domain;
+
+   if (type != IOMMU_DOMAIN_DMA)
+   return NULL;
+
+   io_domain = __ipmmu_domain_alloc(type);
+   if (io_domain)
+   iommu_get_dma_cookie(io_domain);
+
+   return io_domain;
+}
+
+static void ipmmu_domain_free_dma(struct iommu_domain *io_domain)
+{
+   iommu_put_dma_cookie(io_domain);
+   ipmmu_domain_free(io_domain);
+}
+
+static int ipmmu_add_device_dma(struct device *dev)
+{
+   struct iommu_group *group;
+
+   /* only accept devices with iommus property */
+   if (of_count_phandle_with_args(dev->of_node, "iommus",
+  "#iommu-cells") < 0)
+   return -ENODEV;
+
+   group = iommu_group_get_for_dev(dev);
+   if (IS_ERR(group))
+   return PTR_ERR(group);
+
+   return 0;
+}
+
+static void ipmmu_remove_device_dma(struct device *dev)
+{
+   iommu_group_remove_device(dev);
+}
+
+static struct iommu_group *ipmmu_device_group_dma(struct device *dev)
+{
+   struct iommu_group *group;
+   int ret;
+
+   group = generic_device_group(dev);
+   if (IS_ERR(group))
+   return group;
+
+   ret = ipmmu_init_platform_device(dev);
+   if (ret) {
+   iommu_group_put(group);
+   group = ERR_PTR(ret);
+   }
+
+   return group;
+}
+
+static int ipmmu_of_xlate_dma(struct device *dev,
+ struct of_phandle_args *spec)
+{
+   /* dummy callback to satisfy of_iommu_configure() */
+   return 0;
+}
+
+static const struct iommu_ops ipmmu_ops = {
+   .domain_alloc = ipmmu_domain_alloc_dma,
+   .domain_free = ipmmu_domain_free_dma,
+   .attach_dev = ipmmu_attach_device,
+   .detach_dev = ipmmu_detach_device,
+   .map = ipmmu_map,
+   .unmap = ipmmu_unmap,
+   .map_sg = default_iommu_map_sg,
+   .iova_to_phys = ipmmu_iova_to_phys,
+   .add_device = ipmmu_add_device_dma,
+   .remove_device = ipmmu_remove_device_dma,
+   .device_group = ipmmu_device_group_dma,
+   .pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K,
+   .of_xlate = ipmmu_of_xlate_dma,
+};
+
+#endif /* CONFIG_IOMMU_DMA */
+
 /* 
-
  * Probe/remove and init
  */
@@ -910,7 +1003,9 @@ static int ipmmu_remove(struct platform_
list_del(>list);
spin_unlock(_devices_lock);
 
+#if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)

[PATCH v4 04/07] iommu/ipmmu-vmsa: Break out domain allocation code

2016-06-08 Thread Magnus Damm
From: Magnus Damm 

Break out the domain allocation code into a separate function.
This is preparation for future code sharing.

Signed-off-by: Magnus Damm 
---

 Changes since V3:
 - None

 Changes since V2:
 - Included this new patch as-is from the following series:
   [PATCH 00/04] iommu/ipmmu-vmsa: IPMMU CONFIG_IOMMU_DMA update

 drivers/iommu/ipmmu-vmsa.c |   13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

--- 0005/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2016-06-08 15:00:20.760607110 +0900
@@ -507,13 +507,10 @@ static irqreturn_t ipmmu_irq(int irq, vo
  * IOMMU Operations
  */
 
-static struct iommu_domain *ipmmu_domain_alloc(unsigned type)
+static struct iommu_domain *__ipmmu_domain_alloc(unsigned type)
 {
struct ipmmu_vmsa_domain *domain;
 
-   if (type != IOMMU_DOMAIN_UNMANAGED)
-   return NULL;
-
domain = kzalloc(sizeof(*domain), GFP_KERNEL);
if (!domain)
return NULL;
@@ -523,6 +520,14 @@ static struct iommu_domain *ipmmu_domain
return >io_domain;
 }
 
+static struct iommu_domain *ipmmu_domain_alloc(unsigned type)
+{
+   if (type != IOMMU_DOMAIN_UNMANAGED)
+   return NULL;
+
+   return __ipmmu_domain_alloc(type);
+}
+
 static void ipmmu_domain_free(struct iommu_domain *io_domain)
 {
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu