[PATCH] iommu/ipmmu-vmsa: Document R-Car V3H and E3 IPMMU DT bindings

2018-05-21 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Update the IPMMU DT binding documentation to include the compat strings
for the IPMMU devices included in the R-Car V3H and E3 SoCs.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Developed on top of renesas-drivers-2018-05-15-v4.17-rc5

 Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt |2 ++
 1 file changed, 2 insertions(+)

--- 0001/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt
+++ work/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt 
2018-05-21 23:37:16.370607110 +0900
@@ -20,6 +20,8 @@ Required Properties:
 - "renesas,ipmmu-r8a7795" for the R8A7795 (R-Car H3) IPMMU.
 - "renesas,ipmmu-r8a7796" for the R8A7796 (R-Car M3-W) IPMMU.
 - "renesas,ipmmu-r8a77970" for the R8A77970 (R-Car V3M) IPMMU.
+- "renesas,ipmmu-r8a77980" for the R8A77980 (R-Car V3H) IPMMU.
+- "renesas,ipmmu-r8a77990" for the R8A77990 (R-Car E3) IPMMU.
 - "renesas,ipmmu-r8a77995" for the R8A77995 (R-Car D3) IPMMU.
 - "renesas,ipmmu-vmsa" for generic R-Car Gen2 or RZ/G1 VMSA-compatible
   IPMMU.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH] iommu/ipmmu-vmsa: Document R-Car M3-N IPMMU DT bindings

2018-03-20 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Update the IPMMU DT binding documentation to include the r8a77965 compat
string for the IPMMU devices included in the R-Car M3-N SoC.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt |1 +
 1 file changed, 1 insertion(+)

--- 0001/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt
+++ work/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt 
2018-03-20 15:30:50.640607110 +0900
@@ -17,6 +17,7 @@ Required Properties:
 - "renesas,ipmmu-r8a7794" for the R8A7794 (R-Car E2) IPMMU.
 - "renesas,ipmmu-r8a7795" for the R8A7795 (R-Car H3) IPMMU.
 - "renesas,ipmmu-r8a7796" for the R8A7796 (R-Car M3-W) IPMMU.
+- "renesas,ipmmu-r8a77965" for the R8A77965 (R-Car M3-N) IPMMU.
 - "renesas,ipmmu-r8a77970" for the R8A77970 (R-Car V3M) IPMMU.
 - "renesas,ipmmu-r8a77995" for the R8A77995 (R-Car D3) IPMMU.
 - "renesas,ipmmu-vmsa" for generic R-Car Gen2 VMSA-compatible IPMMU.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v4 02/09] iommu/ipmmu-vmsa: Add optional root device feature

2017-10-16 Thread Magnus Damm
Hi Robin,

On Tue, Jun 20, 2017 at 2:19 AM, Robin Murphy <robin.mur...@arm.com> wrote:
> On 19/06/17 10:14, Magnus Damm wrote:
>> From: Magnus Damm <damm+rene...@opensource.se>
>>
>> Add root device handling to the IPMMU driver by allowing certain
>> DT compat strings to enable has_cache_leaf_nodes that in turn will
>> support both root devices with interrupts and leaf devices that
>> face the actual IPMMU consumer devices.
>>
>> Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
>> ---
>>
>>  Changes since V3:
>>  - Reworked root finding code to make it easier to follow, thanks Geert!
>>
>>  Changes since V2:
>>  - Fixed a bug in ipmmu_find_root() when only leaf devices are present
>>  - Broke out __ipmmu_find_root() to allow ->xlate() check for root devices
>>
>>  Changes since V1:
>>  - Moved patch to earlier in the series
>>  - Updated code to work with recent changes in:
>>[PATCH v3 00/06] iommu/ipmmu-vmsa: IPMMU multi-arch update V3
>>
>>  drivers/iommu/ipmmu-vmsa.c |   95 
>> 
>>  1 file changed, 78 insertions(+), 17 deletions(-)
>>
>> --- 0015/drivers/iommu/ipmmu-vmsa.c
>> +++ work/drivers/iommu/ipmmu-vmsa.c   2017-06-19 13:59:41.050607110 +0900
>> @@ -36,6 +36,7 @@
>>
>>  struct ipmmu_features {
>>   bool use_ns_alias_offset;
>> + bool has_cache_leaf_nodes;
>>  };
>>
>>  struct ipmmu_vmsa_device {
>> @@ -44,6 +45,7 @@ struct ipmmu_vmsa_device {
>>   struct iommu_device iommu;
>>   struct list_head list;
>>   const struct ipmmu_features *features;
>> + bool is_leaf;
>>   unsigned int num_utlbs;
>>   spinlock_t lock;/* Protects ctx and domains[] 
>> */
>>   DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
>> @@ -54,6 +56,7 @@ struct ipmmu_vmsa_device {
>>
>>  struct ipmmu_vmsa_domain {
>>   struct ipmmu_vmsa_device *mmu;
>> + struct ipmmu_vmsa_device *root;
>
> Would it not make more sense for this to be a property of the
> ipmmu_device itself, rather than per ipmmu_domain? I may of course have
> got the wrong idea of the topology here, but it seems as if mmu->is_leaf
> could be expressed as mmu->root == mmu vs. mmu->root == some_other_mmu,
> at which point there's one less thing to worry about in the domain.

Yes, you are right! Please have a look at patch 2 in V5 that is doing that.

>>   struct iommu_domain io_domain;
>>
>>   struct io_pgtable_cfg cfg;
>> @@ -203,6 +206,44 @@ static struct ipmmu_vmsa_iommu_priv *to_
>>  #define IMUASID_ASID0_SHIFT  0
>>
>>  /* 
>> -
>> + * Root device handling
>> + */
>> +
>> +static bool ipmmu_is_root(struct ipmmu_vmsa_device *mmu)
>> +{
>> + if (mmu->features->has_cache_leaf_nodes)
>> + return mmu->is_leaf ? false : true> +   else
>> + return true; /* older IPMMU hardware treated as single root */
>> +}
>> +
>> +static struct ipmmu_vmsa_device *__ipmmu_find_root(void)
>> +{
>> + struct ipmmu_vmsa_device *mmu;
>> + struct ipmmu_vmsa_device *root = NULL;
>> +
>> + spin_lock(_devices_lock);
>> +
>> + list_for_each_entry(mmu, _devices, list) {
>> + if (ipmmu_is_root(mmu)) {
>> + root = mmu;
>> + break;
>> + }
>> + }
>> +
>> + spin_unlock(_devices_lock);
>> + return root;
>> +}
>
> I wonder if it might be tidier to use driver_for_each_device() for this,
> and remove the local list at the same time as its previous user.

Yep, also included in V5.

> Either way, what happens if things end up hapening in this order:
>
> 1: probe leaf IPMMU B
> 2: probe device X behind IPMMU B
> 3: create and attach default domain for device X
> 4: probe root IPMMU A
>
> We know X will defer if B isn't ready, but it doesn't seem (at a glance,
> admittedly) that there's anything to enforce the expected probe ordering
> between A and B. This seems like another argument for moving the
> root/leaf association up to the device level, such that B can look up A
> once in its own probe routine, and defer itself if necessary.

There used to be code to check for presence of root device inside
xlate() in "[PATCH v4 09/09] iommu/ipmmu-vmsa: Hook up r8a7795 DT
matching code" however in V5 I'm deferring probe of non-root devices
to handle this.

>> +
>> +s

[PATCH v5 07/09] iommu/ipmmu-vmsa: Make IMBUSCTR setup optional

2017-10-16 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Introduce a feature to allow opt-out of setting up
IMBUSCR. The default case is unchanged.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V4:
 - Use leaf node mmu instead of root

 Changes since V3:
 - None

 Changes since V2:
 - None

 Changes since V1:
 - Updated the commit message
 - Reworked patch to coexist with the multi context feature


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

--- 0018/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-10-16 20:20:30.860607110 +0900
@@ -39,6 +39,7 @@ struct ipmmu_features {
bool use_ns_alias_offset;
bool has_cache_leaf_nodes;
unsigned int number_of_contexts;
+   bool setup_imbuscr;
 };
 
 struct ipmmu_vmsa_device {
@@ -457,9 +458,10 @@ static int ipmmu_domain_init_context(str
 domain->cfg.arm_lpae_s1_cfg.mair[0]);
 
/* IMBUSCR */
-   ipmmu_ctx_write_root(domain, IMBUSCR,
-ipmmu_ctx_read_root(domain, IMBUSCR) &
-~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
+   if (domain->mmu->features->setup_imbuscr)
+   ipmmu_ctx_write_root(domain, IMBUSCR,
+ipmmu_ctx_read_root(domain, IMBUSCR) &
+~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
 
/*
 * IMSTR
@@ -979,6 +981,7 @@ static const struct ipmmu_features ipmmu
.use_ns_alias_offset = true,
.has_cache_leaf_nodes = false,
.number_of_contexts = 1, /* software only tested with one context */
+   .setup_imbuscr = true,
 };
 
 static const struct of_device_id ipmmu_of_ids[] = {
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v5 09/09] iommu/ipmmu-vmsa: Hook up r8a7795 DT matching code

2017-10-16 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Tie in r8a7795 features and update the IOMMU_OF_DECLARE
compat string to include the updated compat string.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V4:
 - Got rid of root device availability check in ->xlate()
   -> deferred probing is used to make sure the root is always present

 Changes since V3:
 - Rebased code on top of
   [PATCH 00/04] iommu/ipmmu-vmsa: 32-bit ARM update
   This includes support for iommu_fwspec_add_ids()
 - Use dev_err() instead of dev_info() - Thanks Geert!
 - Moved single-invokation check into of_xlate() - Thanks Geert!
 - Dropped TODO list
 
 Changes since V2:
 - Check for lack of root device in ->xlate()
   This fixed a bug when IPMMU-MM is disabled in DT the system hangs on boot
 - Added code to ipmmu_init_platform_device() to handle multiple ->xlate() calls
 - Include empty white list by default
 - Updated TODO list

 Changes since V1:
 - Enable multi context feature
 - Update TODO list

 drivers/iommu/ipmmu-vmsa.c |   29 +
 1 file changed, 29 insertions(+)

--- 0019/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-10-16 19:53:14.710607110 +0900
@@ -25,6 +25,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
 #include 
@@ -735,9 +736,24 @@ static int ipmmu_init_platform_device(st
return 0;
 }
 
+static bool ipmmu_slave_whitelist(struct device *dev)
+{
+   /* By default, do not allow use of IPMMU */
+   return false;
+}
+
+static const struct soc_device_attribute soc_r8a7795[] = {
+   { .soc_id = "r8a7795", },
+   { /* sentinel */ }
+};
+
 static int ipmmu_of_xlate(struct device *dev,
  struct of_phandle_args *spec)
 {
+   /* For R-Car Gen3 use a white list to opt-in slave devices */
+   if (soc_device_match(soc_r8a7795) && !ipmmu_slave_whitelist(dev))
+   return -ENODEV;
+
iommu_fwspec_add_ids(dev, spec->args, 1);
 
/* Initialize once - xlate() will call multiple times */
@@ -996,11 +1012,22 @@ static const struct ipmmu_features ipmmu
.twobit_imttbcr_sl0 = false,
 };
 
+static const struct ipmmu_features ipmmu_features_r8a7795 = {
+   .use_ns_alias_offset = false,
+   .has_cache_leaf_nodes = true,
+   .number_of_contexts = 8,
+   .setup_imbuscr = false,
+   .twobit_imttbcr_sl0 = true,
+};
+
 static const struct of_device_id ipmmu_of_ids[] = {
{
.compatible = "renesas,ipmmu-vmsa",
.data = _features_default,
}, {
+   .compatible = "renesas,ipmmu-r8a7795",
+   .data = _features_r8a7795,
+   }, {
/* Terminator */
},
 };
@@ -1185,6 +1212,8 @@ static int __init ipmmu_vmsa_iommu_of_se
 
 IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa",
 ipmmu_vmsa_iommu_of_setup);
+IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795",
+ipmmu_vmsa_iommu_of_setup);
 #endif
 
 MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU");
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v5 08/09] iommu/ipmmu-vmsa: Allow two bit SL0

2017-10-16 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Introduce support for two bit SL0 bitfield in IMTTBCR
by using a separate feature flag.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V4:
 - Use leaf node mmu instead of root

 Changes since V3:
 - None

 Changes since V2:
 - None

 Changes since V1:
 - None

 drivers/iommu/ipmmu-vmsa.c |   14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

--- 0019/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-10-16 20:24:22.990607110 +0900
@@ -40,6 +40,7 @@ struct ipmmu_features {
bool has_cache_leaf_nodes;
unsigned int number_of_contexts;
bool setup_imbuscr;
+   bool twobit_imttbcr_sl0;
 };
 
 struct ipmmu_vmsa_device {
@@ -144,6 +145,10 @@ static struct ipmmu_vmsa_iommu_priv *to_
 #define IMTTBCR_TSZ0_MASK  (7 << 0)
 #define IMTTBCR_TSZ0_SHIFT O
 
+#define IMTTBCR_SL0_TWOBIT_LVL_3   (0 << 6)
+#define IMTTBCR_SL0_TWOBIT_LVL_2   (1 << 6)
+#define IMTTBCR_SL0_TWOBIT_LVL_1   (2 << 6)
+
 #define IMBUSCR0x000c
 #define IMBUSCR_DVM(1 << 2)
 #define IMBUSCR_BUSSEL_SYS (0 << 0)
@@ -396,6 +401,7 @@ static void ipmmu_domain_free_context(st
 static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain)
 {
u64 ttbr;
+   u32 tmp;
int ret;
 
/*
@@ -449,9 +455,14 @@ static int ipmmu_domain_init_context(str
 * We use long descriptors with inner-shareable WBWA tables and allocate
 * the whole 32-bit VA space to TTBR0.
 */
+   if (domain->mmu->features->twobit_imttbcr_sl0)
+   tmp = IMTTBCR_SL0_TWOBIT_LVL_1;
+   else
+   tmp = IMTTBCR_SL0_LVL_1;
+
ipmmu_ctx_write_root(domain, IMTTBCR, IMTTBCR_EAE |
 IMTTBCR_SH0_INNER_SHAREABLE | IMTTBCR_ORGN0_WB_WA |
-IMTTBCR_IRGN0_WB_WA | IMTTBCR_SL0_LVL_1);
+IMTTBCR_IRGN0_WB_WA | tmp);
 
/* MAIR0 */
ipmmu_ctx_write_root(domain, IMMAIR0,
@@ -982,6 +993,7 @@ static const struct ipmmu_features ipmmu
.has_cache_leaf_nodes = false,
.number_of_contexts = 1, /* software only tested with one context */
.setup_imbuscr = true,
+   .twobit_imttbcr_sl0 = false,
 };
 
 static const struct of_device_id ipmmu_of_ids[] = {
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v5 06/09] iommu/ipmmu-vmsa: Write IMCTR twice

2017-10-16 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Write IMCTR both in the root device and the leaf node.

To allow access of IMCTR introduce the following function:
 - ipmmu_ctx_write_all()

While at it also rename context functions:
 - ipmmu_ctx_read() -> ipmmu_ctx_read_root()
 - ipmmu_ctx_write() -> ipmmu_ctx_write_root()

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V4:
 - Updated to make use of new root pointer location

 Changes since V3:
 - Changed function names to improve code readability - Thanks Robin!

 Changes since V2:
 - None

 Changes since V1:
 - None

 drivers/iommu/ipmmu-vmsa.c |   56 +++-
 1 file changed, 35 insertions(+), 21 deletions(-)

--- 0015/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-10-16 19:50:19.240607110 +0900
@@ -248,19 +248,31 @@ static void ipmmu_write(struct ipmmu_vms
iowrite32(data, mmu->base + offset);
 }
 
-static u32 ipmmu_ctx_read(struct ipmmu_vmsa_domain *domain, unsigned int reg)
+static u32 ipmmu_ctx_read_root(struct ipmmu_vmsa_domain *domain,
+  unsigned int reg)
 {
return ipmmu_read(domain->mmu->root,
  domain->context_id * IM_CTX_SIZE + reg);
 }
 
-static void ipmmu_ctx_write(struct ipmmu_vmsa_domain *domain, unsigned int reg,
-   u32 data)
+static void ipmmu_ctx_write_root(struct ipmmu_vmsa_domain *domain,
+unsigned int reg, u32 data)
 {
ipmmu_write(domain->mmu->root,
domain->context_id * IM_CTX_SIZE + reg, data);
 }
 
+static void ipmmu_ctx_write_all(struct ipmmu_vmsa_domain *domain,
+   unsigned int reg, u32 data)
+{
+   if (domain->mmu != domain->mmu->root)
+   ipmmu_write(domain->mmu,
+   domain->context_id * IM_CTX_SIZE + reg, data);
+
+   ipmmu_write(domain->mmu->root,
+   domain->context_id * IM_CTX_SIZE + reg, data);
+}
+
 /* 
-
  * TLB and microTLB Management
  */
@@ -270,7 +282,7 @@ static void ipmmu_tlb_sync(struct ipmmu_
 {
unsigned int count = 0;
 
-   while (ipmmu_ctx_read(domain, IMCTR) & IMCTR_FLUSH) {
+   while (ipmmu_ctx_read_root(domain, IMCTR) & IMCTR_FLUSH) {
cpu_relax();
if (++count == TLB_LOOP_TIMEOUT) {
dev_err_ratelimited(domain->mmu->dev,
@@ -285,9 +297,9 @@ static void ipmmu_tlb_invalidate(struct
 {
u32 reg;
 
-   reg = ipmmu_ctx_read(domain, IMCTR);
+   reg = ipmmu_ctx_read_root(domain, IMCTR);
reg |= IMCTR_FLUSH;
-   ipmmu_ctx_write(domain, IMCTR, reg);
+   ipmmu_ctx_write_all(domain, IMCTR, reg);
 
ipmmu_tlb_sync(domain);
 }
@@ -428,31 +440,32 @@ static int ipmmu_domain_init_context(str
 
/* TTBR0 */
ttbr = domain->cfg.arm_lpae_s1_cfg.ttbr[0];
-   ipmmu_ctx_write(domain, IMTTLBR0, ttbr);
-   ipmmu_ctx_write(domain, IMTTUBR0, ttbr >> 32);
+   ipmmu_ctx_write_root(domain, IMTTLBR0, ttbr);
+   ipmmu_ctx_write_root(domain, IMTTUBR0, ttbr >> 32);
 
/*
 * TTBCR
 * We use long descriptors with inner-shareable WBWA tables and allocate
 * the whole 32-bit VA space to TTBR0.
 */
-   ipmmu_ctx_write(domain, IMTTBCR, IMTTBCR_EAE |
-   IMTTBCR_SH0_INNER_SHAREABLE | IMTTBCR_ORGN0_WB_WA |
-   IMTTBCR_IRGN0_WB_WA | IMTTBCR_SL0_LVL_1);
+   ipmmu_ctx_write_root(domain, IMTTBCR, IMTTBCR_EAE |
+IMTTBCR_SH0_INNER_SHAREABLE | IMTTBCR_ORGN0_WB_WA |
+IMTTBCR_IRGN0_WB_WA | IMTTBCR_SL0_LVL_1);
 
/* MAIR0 */
-   ipmmu_ctx_write(domain, IMMAIR0, domain->cfg.arm_lpae_s1_cfg.mair[0]);
+   ipmmu_ctx_write_root(domain, IMMAIR0,
+domain->cfg.arm_lpae_s1_cfg.mair[0]);
 
/* IMBUSCR */
-   ipmmu_ctx_write(domain, IMBUSCR,
-   ipmmu_ctx_read(domain, IMBUSCR) &
-   ~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
+   ipmmu_ctx_write_root(domain, IMBUSCR,
+ipmmu_ctx_read_root(domain, IMBUSCR) &
+~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
 
/*
 * IMSTR
 * Clear all interrupt flags.
 */
-   ipmmu_ctx_write(domain, IMSTR, ipmmu_ctx_read(domain, IMSTR));
+   ipmmu_ctx_write_root(domain, IMSTR, ipmmu_ctx_read_root(domain, IMSTR));
 
/*
 * IMCTR
@@ -461,7 +474,8 @@ static int ipmmu_domain_init_context(str
 * software management as we have no use for it. Flush the TLB as
 * required when modifying the context registers.
 */
-   ipmmu_ct

[PATCH v5 05/09] iommu/ipmmu-vmsa: IPMMU device is 40-bit bus master

2017-10-16 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

The r8a7795 IPMMU supports 40-bit bus mastering. Both
the coherent DMA mask and the streaming DMA mask are
set to unlock the 40-bit address space for coherent
allocations and streaming operations.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V4:
 - None

 Changes since V3:
 - None

 Changes since V2:
 - Updated the code and commit message to use 40 bits instead of 64 bits

 Changes since V1:
 - Updated the commit message

 drivers/iommu/ipmmu-vmsa.c |1 +
 1 file changed, 1 insertion(+)

--- 0012/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-10-16 20:37:31.480607110 +0900
@@ -996,6 +996,7 @@ static int ipmmu_probe(struct platform_d
spin_lock_init(>lock);
bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
mmu->features = of_device_get_match_data(>dev);
+   dma_set_mask_and_coherent(>dev, DMA_BIT_MASK(40));
 
/* Map I/O memory and request IRQ. */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v5 04/09] iommu/ipmmu-vmsa: Make use of IOMMU_OF_DECLARE()

2017-10-16 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Hook up IOMMU_OF_DECLARE() support in case CONFIG_IOMMU_DMA
is enabled. The only current supported case for 32-bit ARM
is disabled, however for 64-bit ARM usage of OF is required.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V4:
 - Use ipmmu_is_root() instead of now removed is_leaf flag

 Changes since V3:
 - Reworked to fit on top of
   [PATCH 00/04] iommu/ipmmu-vmsa: 32-bit ARM update

 Changes since V2:
 - Reworked registration code to make use of recently introduced:
 iommu_device_register()
 iommu_device_set_ops()
 iommu_device_set_fwnode()

 Changes since V1:
 - Reworked slightly to fit updated patch order and
   [PATCH v3 00/06] iommu/ipmmu-vmsa: IPMMU multi-arch update V3


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

--- 0014/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-10-16 19:59:42.700607110 +0900
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1055,17 +1056,30 @@ static int ipmmu_probe(struct platform_d
ipmmu_device_reset(mmu);
}
 
-   ret = iommu_device_sysfs_add(>iommu, >dev, NULL,
-dev_name(>dev));
-   if (ret)
-   return ret;
+   /*
+* Register the IPMMU to the IOMMU subsystem in the following cases:
+* - R-Car Gen2 IPMMU (all devices registered)
+* - R-Car Gen3 IPMMU (leaf devices only - skip root IPMMU-MM device)
+*/
+   if (!mmu->features->has_cache_leaf_nodes || !ipmmu_is_root(mmu)) {
+   ret = iommu_device_sysfs_add(>iommu, >dev, NULL,
+dev_name(>dev));
+   if (ret)
+   return ret;
 
-   iommu_device_set_ops(>iommu, _ops);
-   iommu_device_set_fwnode(>iommu, >dev.of_node->fwnode);
+   iommu_device_set_ops(>iommu, _ops);
+   iommu_device_set_fwnode(>iommu,
+   >dev.of_node->fwnode);
 
-   ret = iommu_device_register(>iommu);
-   if (ret)
-   return ret;
+   ret = iommu_device_register(>iommu);
+   if (ret)
+   return ret;
+
+#if defined(CONFIG_IOMMU_DMA)
+   if (!iommu_present(_bus_type))
+   bus_set_iommu(_bus_type, _ops);
+#endif
+   }
 
/*
 * We can't create the ARM mapping here as it requires the bus to have
@@ -1105,15 +1119,22 @@ static struct platform_driver ipmmu_driv
 
 static int __init ipmmu_init(void)
 {
+   static bool setup_done;
int ret;
 
+   if (setup_done)
+   return 0;
+
ret = platform_driver_register(_driver);
if (ret < 0)
return ret;
 
+#if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
if (!iommu_present(_bus_type))
bus_set_iommu(_bus_type, _ops);
+#endif
 
+   setup_done = true;
return 0;
 }
 
@@ -1125,6 +1146,17 @@ static void __exit ipmmu_exit(void)
 subsys_initcall(ipmmu_init);
 module_exit(ipmmu_exit);
 
+#ifdef CONFIG_IOMMU_DMA
+static int __init ipmmu_vmsa_iommu_of_setup(struct device_node *np)
+{
+   ipmmu_init();
+   return 0;
+}
+
+IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa",
+ipmmu_vmsa_iommu_of_setup);
+#endif
+
 MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU");
 MODULE_AUTHOR("Laurent Pinchart <laurent.pinch...@ideasonboard.com>");
 MODULE_LICENSE("GPL v2");
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v5 02/09] iommu/ipmmu-vmsa: Add optional root device feature

2017-10-16 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Add root device handling to the IPMMU driver by allowing certain
DT compat strings to enable has_cache_leaf_nodes that in turn will
support both root devices with interrupts and leaf devices that
face the actual IPMMU consumer devices.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V4: (Many thanks to Robin for feedback)
 - Put the root pointer under struct ipmmu_vmsa_device
 - Drop is_leaf flag
 - Use driver_for_each_device instead of local list of devices
 - Return -EPROBE_DEFER to hook up root device first

 Changes since V3:
 - Reworked root finding code to make it easier to follow, thanks Geert!
 
 Changes since V2:
 - Fixed a bug in ipmmu_find_root() when only leaf devices are present
 - Broke out __ipmmu_find_root() to allow ->xlate() check for root devices

 Changes since V1:
 - Moved patch to earlier in the series
 - Updated code to work with recent changes in:
   [PATCH v3 00/06] iommu/ipmmu-vmsa: IPMMU multi-arch update V3

 drivers/iommu/ipmmu-vmsa.c |   90 +++-
 1 file changed, 73 insertions(+), 17 deletions(-)

--- 0009/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-10-16 19:43:27.020607110 +0900
@@ -36,12 +36,14 @@
 
 struct ipmmu_features {
bool use_ns_alias_offset;
+   bool has_cache_leaf_nodes;
 };
 
 struct ipmmu_vmsa_device {
struct device *dev;
void __iomem *base;
struct iommu_device iommu;
+   struct ipmmu_vmsa_device *root;
const struct ipmmu_features *features;
unsigned int num_utlbs;
spinlock_t lock;/* Protects ctx and domains[] */
@@ -199,6 +201,36 @@ static struct ipmmu_vmsa_iommu_priv *to_
 #define IMUASID_ASID0_SHIFT0
 
 /* 
-
+ * Root device handling
+ */
+
+static struct platform_driver ipmmu_driver;
+
+static bool ipmmu_is_root(struct ipmmu_vmsa_device *mmu)
+{
+   return mmu->root == mmu;
+}
+
+static int __ipmmu_check_device(struct device *dev, void *data)
+{
+   struct ipmmu_vmsa_device *mmu = dev_get_drvdata(dev);
+   struct ipmmu_vmsa_device **rootp = data;
+
+   if (ipmmu_is_root(mmu))
+   *rootp = mmu;
+
+   return 0;
+}
+
+static struct ipmmu_vmsa_device *ipmmu_find_root(void)
+{
+   struct ipmmu_vmsa_device *root = NULL;
+
+   return driver_for_each_device(_driver.driver, NULL, ,
+ __ipmmu_check_device) == 0 ? root : NULL;
+}
+
+/* 
-
  * Read/Write Access
  */
 
@@ -215,13 +247,15 @@ static void ipmmu_write(struct ipmmu_vms
 
 static u32 ipmmu_ctx_read(struct ipmmu_vmsa_domain *domain, unsigned int reg)
 {
-   return ipmmu_read(domain->mmu, domain->context_id * IM_CTX_SIZE + reg);
+   return ipmmu_read(domain->mmu->root,
+ domain->context_id * IM_CTX_SIZE + reg);
 }
 
 static void ipmmu_ctx_write(struct ipmmu_vmsa_domain *domain, unsigned int reg,
u32 data)
 {
-   ipmmu_write(domain->mmu, domain->context_id * IM_CTX_SIZE + reg, data);
+   ipmmu_write(domain->mmu->root,
+   domain->context_id * IM_CTX_SIZE + reg, data);
 }
 
 /* 
-
@@ -369,12 +403,12 @@ static int ipmmu_domain_init_context(str
 * TODO: Add support for coherent walk through CCI with DVM and remove
 * cache handling. For now, delegate it to the io-pgtable code.
 */
-   domain->cfg.iommu_dev = domain->mmu->dev;
+   domain->cfg.iommu_dev = domain->mmu->root->dev;
 
/*
 * Find an unused context.
 */
-   ret = ipmmu_domain_allocate_context(domain->mmu, domain);
+   ret = ipmmu_domain_allocate_context(domain->mmu->root, domain);
if (ret == IPMMU_CTX_MAX)
return -EBUSY;
 
@@ -383,7 +417,8 @@ static int ipmmu_domain_init_context(str
domain->iop = alloc_io_pgtable_ops(ARM_32_LPAE_S1, >cfg,
   domain);
if (!domain->iop) {
-   ipmmu_domain_free_context(domain->mmu, domain->context_id);
+   ipmmu_domain_free_context(domain->mmu->root,
+ domain->context_id);
return -EINVAL;
}
 
@@ -437,7 +472,7 @@ static void ipmmu_domain_destroy_context
 */
ipmmu_ctx_write(domain, IMCTR, IMCTR_FLUSH);
ipmmu_tlb_sync(domain);
-   ipmmu_domain_free_context(domain->mmu, domain->context_id);
+   ipmmu_domain_free_context(domain->mmu->root, domain->context_id);
 }
 
 /* 
---

[PATCH v5 03/09] iommu/ipmmu-vmsa: Enable multi context support

2017-10-16 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Add support for up to 8 contexts. Each context is mapped to one
domain. One domain is assigned one or more slave devices. Contexts
are allocated dynamically and slave devices are grouped together
based on which IPMMU device they are connected to. This makes slave
devices tied to the same IPMMU device share the same IOVA space.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V4:
 - None

 Changes since V3:
 - Use number_of_contexts unsigned int, drop WARN_ON() - Thanks Robin!

 Changes since V2:
 - Updated patch description to reflect code included in:
   [PATCH v7 00/07] iommu/ipmmu-vmsa: IPMMU multi-arch update V7

 Changes since V1:
 - Support up to 8 contexts instead of 4
 - Use feature flag and runtime handling
 - Default to single context

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

--- 0011/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-10-16 19:46:09.900607110 +0900
@@ -32,11 +32,12 @@
 
 #include "io-pgtable.h"
 
-#define IPMMU_CTX_MAX 1
+#define IPMMU_CTX_MAX 8
 
 struct ipmmu_features {
bool use_ns_alias_offset;
bool has_cache_leaf_nodes;
+   unsigned int number_of_contexts;
 };
 
 struct ipmmu_vmsa_device {
@@ -46,6 +47,7 @@ struct ipmmu_vmsa_device {
struct ipmmu_vmsa_device *root;
const struct ipmmu_features *features;
unsigned int num_utlbs;
+   unsigned int num_ctx;
spinlock_t lock;/* Protects ctx and domains[] */
DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
struct ipmmu_vmsa_domain *domains[IPMMU_CTX_MAX];
@@ -352,11 +354,12 @@ static int ipmmu_domain_allocate_context
 
spin_lock_irqsave(>lock, flags);
 
-   ret = find_first_zero_bit(mmu->ctx, IPMMU_CTX_MAX);
-   if (ret != IPMMU_CTX_MAX) {
+   ret = find_first_zero_bit(mmu->ctx, mmu->num_ctx);
+   if (ret != mmu->num_ctx) {
mmu->domains[ret] = domain;
set_bit(ret, mmu->ctx);
-   }
+   } else
+   ret = -EBUSY;
 
spin_unlock_irqrestore(>lock, flags);
 
@@ -409,8 +412,8 @@ static int ipmmu_domain_init_context(str
 * Find an unused context.
 */
ret = ipmmu_domain_allocate_context(domain->mmu->root, domain);
-   if (ret == IPMMU_CTX_MAX)
-   return -EBUSY;
+   if (ret < 0)
+   return ret;
 
domain->context_id = ret;
 
@@ -539,7 +542,7 @@ static irqreturn_t ipmmu_irq(int irq, vo
/*
 * Check interrupts for all active contexts.
 */
-   for (i = 0; i < IPMMU_CTX_MAX; i++) {
+   for (i = 0; i < mmu->num_ctx; i++) {
if (!mmu->domains[i])
continue;
if (ipmmu_domain_irq(mmu->domains[i]) == IRQ_HANDLED)
@@ -603,6 +606,13 @@ static int ipmmu_attach_device(struct io
/* The domain hasn't been used yet, initialize it. */
domain->mmu = mmu;
ret = ipmmu_domain_init_context(domain);
+   if (ret < 0) {
+   dev_err(dev, "Unable to initialize IPMMU context\n");
+   domain->mmu = NULL;
+   } else {
+   dev_info(dev, "Using IPMMU context %u\n",
+domain->context_id);
+   }
} else if (domain->mmu != mmu) {
/*
 * Something is wrong, we can't attach two devices using
@@ -946,13 +956,14 @@ static void ipmmu_device_reset(struct ip
unsigned int i;
 
/* Disable all contexts. */
-   for (i = 0; i < 4; ++i)
+   for (i = 0; i < mmu->num_ctx; ++i)
ipmmu_write(mmu, i * IM_CTX_SIZE + IMCTR, 0);
 }
 
 static const struct ipmmu_features ipmmu_features_default = {
.use_ns_alias_offset = true,
.has_cache_leaf_nodes = false,
+   .number_of_contexts = 1, /* software only tested with one context */
 };
 
 static const struct of_device_id ipmmu_of_ids[] = {
@@ -1006,6 +1017,9 @@ static int ipmmu_probe(struct platform_d
if (mmu->features->use_ns_alias_offset)
mmu->base += IM_NS_ALIAS_OFFSET;
 
+   mmu->num_ctx = min_t(unsigned int, IPMMU_CTX_MAX,
+mmu->features->number_of_contexts);
+
irq = platform_get_irq(pdev, 0);
 
/*
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v5 01/09] iommu/ipmmu-vmsa: Introduce features, break out alias

2017-10-16 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Introduce struct ipmmu_features to track various hardware
and software implementation changes inside the driver for
different kinds of IPMMU hardware. Add use_ns_alias_offset
as a first example of a feature to control if the secure
register bank offset should be used or not.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V4:
 - None

 Changes since V3:
 - Use of_device_get_match_data(), thanks Robin!

 Changes since V2:
 - None

 Changes since V1:
 - Moved patch to front of the series


 drivers/iommu/ipmmu-vmsa.c |   31 ---
 1 file changed, 24 insertions(+), 7 deletions(-)

--- 0001/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-10-12 15:16:43.510607110 +0900
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -33,11 +34,15 @@
 
 #define IPMMU_CTX_MAX 1
 
+struct ipmmu_features {
+   bool use_ns_alias_offset;
+};
+
 struct ipmmu_vmsa_device {
struct device *dev;
void __iomem *base;
struct iommu_device iommu;
-
+   const struct ipmmu_features *features;
unsigned int num_utlbs;
spinlock_t lock;/* Protects ctx and domains[] */
DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
@@ -910,6 +915,21 @@ static void ipmmu_device_reset(struct ip
ipmmu_write(mmu, i * IM_CTX_SIZE + IMCTR, 0);
 }
 
+static const struct ipmmu_features ipmmu_features_default = {
+   .use_ns_alias_offset = true,
+};
+
+static const struct of_device_id ipmmu_of_ids[] = {
+   {
+   .compatible = "renesas,ipmmu-vmsa",
+   .data = _features_default,
+   }, {
+   /* Terminator */
+   },
+};
+
+MODULE_DEVICE_TABLE(of, ipmmu_of_ids);
+
 static int ipmmu_probe(struct platform_device *pdev)
 {
struct ipmmu_vmsa_device *mmu;
@@ -927,6 +947,7 @@ static int ipmmu_probe(struct platform_d
mmu->num_utlbs = 32;
spin_lock_init(>lock);
bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
+   mmu->features = of_device_get_match_data(>dev);
 
/* Map I/O memory and request IRQ. */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -946,7 +967,8 @@ static int ipmmu_probe(struct platform_d
 * Offset the registers base unconditionally to point to the non-secure
 * alias space for now.
 */
-   mmu->base += IM_NS_ALIAS_OFFSET;
+   if (mmu->features->use_ns_alias_offset)
+   mmu->base += IM_NS_ALIAS_OFFSET;
 
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
@@ -1002,11 +1024,6 @@ static int ipmmu_remove(struct platform_
return 0;
 }
 
-static const struct of_device_id ipmmu_of_ids[] = {
-   { .compatible = "renesas,ipmmu-vmsa", },
-   { }
-};
-
 static struct platform_driver ipmmu_driver = {
.driver = {
.name = "ipmmu-vmsa",
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v5 00/09] iommu/ipmmu-vmsa: r8a7795 support V5

2017-10-16 Thread Magnus Damm
iommu/ipmmu-vmsa: r8a7795 support V5

[PATCH v5 01/09] iommu/ipmmu-vmsa: Introduce features, break out alias
[PATCH v5 02/09] iommu/ipmmu-vmsa: Add optional root device feature
[PATCH v5 03/09] iommu/ipmmu-vmsa: Enable multi context support
[PATCH v5 04/09] iommu/ipmmu-vmsa: Make use of IOMMU_OF_DECLARE()
[PATCH v5 05/09] iommu/ipmmu-vmsa: IPMMU device is 40-bit bus master
[PATCH v5 06/09] iommu/ipmmu-vmsa: Write IMCTR twice
[PATCH v5 07/09] iommu/ipmmu-vmsa: Make IMBUSCTR setup optional
[PATCH v5 08/09] iommu/ipmmu-vmsa: Allow two bit SL0
[PATCH v5 09/09] iommu/ipmmu-vmsa: Hook up r8a7795 DT matching code

This is V5 of r8a7795 IPMMU driver where the series has been rebased
and reworked to fit on next-20171013 that includes:
[PATCH v2 00/05] iommu/ipmmu-vmsa: 32-bit ARM update V2
[PATCH] iommu/ipmmu-vmsa: Use iommu_device_sysfs_add()/remove()

The major feature change is in patch 2/9 that now gets by without
using a local list of registered IPMMU devices and instead relies
on driver_for_each_device(). Thanks to Robin Murphy for his support.

The DT binding for r8a7795 has been accepted for upstream merge
and this series implements support following such format:

d4e42e7 iommu/ipmmu-vmsa: Add r8a7795 DT binding

The r8a7795 IPMMU is almost register compatible with earlier devices
like r8a7790-r8a7794, however some bitfields have been shifted
slightly. On a grander scale topology has been added and interrupts
have been reworked. So now there are several "cache" IPMMU units
without interrupt that somehow communicate with IPMMU-MM that
is the only instance that supports interrupts. The code refers to
IPMMU-MM as a "root" device and the other ones as "leaf" nodes.

Changes since V4:
 - Rebased on top of [PATCH v2 00/05] iommu/ipmmu-vmsa: 32-bit ARM update V2
 - Reworked root device handling to make use of driver_for_each_device()
 - Added deferred probing to make sure root device always is present

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Developed on top of next-20171013
 Also applies to renesas-drivers-2017-10-03-v4.14-rc3
 Tested on top of renesas-drivers on r8a7796-m3ulcb using /dev/ttySC1
  - [PATCH v4 0/3] iommu/ipmmu-vmsa: r8a7796 support V4
  - local /dev/ttySC1 enablement for testing purpose
  - local DTS changes to hook up SYS-DMAC and IPMMU DS0, DS1 and MM
  - local whitelist code to enable "e731.dma-controller"
 
 drivers/iommu/ipmmu-vmsa.c |  310 ++--
 1 file changed, 244 insertions(+), 66 deletions(-)
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 1/3] iommu/ipmmu-vmsa: Document R-Car M3-W IPMMU DT bindings

2017-09-21 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Update the IPMMU DT binding documentation to include the r8a7796 compat
string for the IPMMU devices included in the R-Car M3-W SoC.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
Acked-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
Acked-by: Rob Herring <r...@kernel.org>
Acked-by: Simon Horman <horms+rene...@verge.net.au>
Acked-by: Geert Uytterhoeven <geert+rene...@glider.be>
---

 Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt |1 +
 1 file changed, 1 insertion(+)

--- 0001/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt
+++ work/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt 
2017-09-22 06:20:20.720607110 +0900
@@ -16,6 +16,7 @@ Required Properties:
 - "renesas,ipmmu-r8a7793" for the R8A7793 (R-Car M2-N) IPMMU.
 - "renesas,ipmmu-r8a7794" for the R8A7794 (R-Car E2) IPMMU.
 - "renesas,ipmmu-r8a7795" for the R8A7795 (R-Car H3) IPMMU.
+- "renesas,ipmmu-r8a7796" for the R8A7796 (R-Car M3-W) IPMMU.
 - "renesas,ipmmu-vmsa" for generic R-Car Gen2 VMSA-compatible IPMMU.
 
   - reg: Base address and size of the IPMMU registers.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 2/3] iommu/ipmmu-vmsa: Document R-Car V3M IPMMU DT bindings

2017-09-21 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Update the IPMMU DT binding documentation to include the r8a77970 compat
string for the IPMMU devices included in the R-Car V3M SoC.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt |1 +
 1 file changed, 1 insertion(+)

--- 0002/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt
+++ work/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt 
2017-09-22 06:16:39.180607110 +0900
@@ -17,6 +17,7 @@ Required Properties:
 - "renesas,ipmmu-r8a7794" for the R8A7794 (R-Car E2) IPMMU.
 - "renesas,ipmmu-r8a7795" for the R8A7795 (R-Car H3) IPMMU.
 - "renesas,ipmmu-r8a7796" for the R8A7796 (R-Car M3-W) IPMMU.
+- "renesas,ipmmu-r8a77970" for the R8A77970 (R-Car V3M) IPMMU.
 - "renesas,ipmmu-vmsa" for generic R-Car Gen2 VMSA-compatible IPMMU.
 
   - reg: Base address and size of the IPMMU registers.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 3/3] iommu/ipmmu-vmsa: Document R-Car D3 IPMMU DT bindings

2017-09-21 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Update the IPMMU DT binding documentation to include the r8a77995 compat
string for the IPMMU devices included in the R-Car D3 SoC.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt |1 +
 1 file changed, 1 insertion(+)

--- 0003/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt
+++ work/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt 
2017-09-22 06:21:25.640607110 +0900
@@ -18,6 +18,7 @@ Required Properties:
 - "renesas,ipmmu-r8a7795" for the R8A7795 (R-Car H3) IPMMU.
 - "renesas,ipmmu-r8a7796" for the R8A7796 (R-Car M3-W) IPMMU.
 - "renesas,ipmmu-r8a77970" for the R8A77970 (R-Car V3M) IPMMU.
+- "renesas,ipmmu-r8a77995" for the R8A77995 (R-Car D3) IPMMU.
 - "renesas,ipmmu-vmsa" for generic R-Car Gen2 VMSA-compatible IPMMU.
 
   - reg: Base address and size of the IPMMU registers.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 0/3] iommu/ipmmu-vmsa: R-Car Gen3 IPMMU DT binding update

2017-09-21 Thread Magnus Damm
iommu/ipmmu-vmsa: R-Car Gen3 IPMMU DT binding update

[PATCH 1/3] iommu/ipmmu-vmsa: Document R-Car M3-W IPMMU DT bindings
[PATCH 2/3] iommu/ipmmu-vmsa: Document R-Car V3M IPMMU DT bindings
[PATCH 3/3] iommu/ipmmu-vmsa: Document R-Car D3 IPMMU DT bindings

This series documents IPMMU DT bindings for the following SoCs:
 - R-Car M3-W - R8A7796
 - R-Car V3M - R8A77970
 - R-Car D3 - R8A77995

Patch 1/3 is ready for upstream merge and includes the following tags:
Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
Acked-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
Acked-by: Rob Herring <r...@kernel.org>
Acked-by: Simon Horman <horms+rene...@verge.net.au>
Acked-by: Geert Uytterhoeven <geert+rene...@glider.be>

Patch 2/3 and 3/3 are quite trivial but have no acked-by so far.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Developed on top of v4.14-rc1

 Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt |3 +++
 1 file changed, 3 insertions(+)

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


[PATCH] iommu/ipmmu-vmsa: Use iommu_device_sysfs_add()/remove()

2017-08-20 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Extend the driver to make use of iommu_device_sysfs_add()/remove()
functions to hook up initial sysfs support.

Suggested-by: Joerg Roedel <jroe...@suse.de>
Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Applies on top of next-20170817

 drivers/iommu/ipmmu-vmsa.c |6 ++
 1 file changed, 6 insertions(+)

--- 0001/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-08-21 14:40:13.940607110 +0900
@@ -953,6 +953,11 @@ static int ipmmu_probe(struct platform_d
 
ipmmu_device_reset(mmu);
 
+   ret = iommu_device_sysfs_add(>iommu, >dev, NULL,
+dev_name(>dev));
+   if (ret)
+   return ret;
+
iommu_device_set_ops(>iommu, _ops);
iommu_device_set_fwnode(>iommu, >dev.of_node->fwnode);
 
@@ -975,6 +980,7 @@ static int ipmmu_remove(struct platform_
 {
struct ipmmu_vmsa_device *mmu = platform_get_drvdata(pdev);
 
+   iommu_device_sysfs_remove(>iommu);
iommu_device_unregister(>iommu);
 
 #if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v2 05/05] iommu/ipmmu-vmsa: Clean up device tracking

2017-07-17 Thread Magnus Damm
From: Robin Murphy <robin.mur...@arm.com>

Get rid of now unused device tracking code. Future code should instead
be able to use driver_for_each_device() for this purpose.

This is a simplified version of the following patch from Robin
[PATCH] iommu/ipmmu-vmsa: Clean up group allocation

Signed-off-by: Robin Murphy <robin.mur...@arm.com>
Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Change since V1:
 - New patch

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

--- 0008/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-07-17 21:35:26.690607110 +0900
@@ -37,7 +37,6 @@ struct ipmmu_vmsa_device {
struct device *dev;
void __iomem *base;
struct iommu_device iommu;
-   struct list_head list;
 
unsigned int num_utlbs;
spinlock_t lock;/* Protects ctx and domains[] */
@@ -64,9 +63,6 @@ struct ipmmu_vmsa_iommu_priv {
struct list_head list;
 };
 
-static DEFINE_SPINLOCK(ipmmu_devices_lock);
-static LIST_HEAD(ipmmu_devices);
-
 static struct ipmmu_vmsa_domain *to_vmsa_domain(struct iommu_domain *dom)
 {
return container_of(dom, struct ipmmu_vmsa_domain, io_domain);
@@ -970,10 +966,6 @@ static int ipmmu_probe(struct platform_d
 * ipmmu_init() after the probe function returns.
 */
 
-   spin_lock(_devices_lock);
-   list_add(>list, _devices);
-   spin_unlock(_devices_lock);
-
platform_set_drvdata(pdev, mmu);
 
return 0;
@@ -983,10 +975,6 @@ static int ipmmu_remove(struct platform_
 {
struct ipmmu_vmsa_device *mmu = platform_get_drvdata(pdev);
 
-   spin_lock(_devices_lock);
-   list_del(>list);
-   spin_unlock(_devices_lock);
-
iommu_device_unregister(>iommu);
 
 #if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v2 04/05] iommu/ipmmu-vmsa: Replace local utlb code with fwspec ids

2017-07-17 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Now when both 32-bit and 64-bit code inside the driver is using
fwspec it is possible to replace the utlb handling with fwspec ids
that get populated from ->of_xlate().

Suggested-by: Robin Murphy <robin.mur...@arm.com>
Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V1:
 - Rebased to apply on top of earlier changes in series

 drivers/iommu/ipmmu-vmsa.c |  104 
 1 file changed, 19 insertions(+), 85 deletions(-)

--- 0006/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-07-17 21:12:11.650607110 +0900
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -59,8 +60,6 @@ struct ipmmu_vmsa_domain {
 
 struct ipmmu_vmsa_iommu_priv {
struct ipmmu_vmsa_device *mmu;
-   unsigned int *utlbs;
-   unsigned int num_utlbs;
struct device *dev;
struct list_head list;
 };
@@ -550,13 +549,14 @@ static int ipmmu_attach_device(struct io
   struct device *dev)
 {
struct ipmmu_vmsa_iommu_priv *priv = to_priv(dev);
+   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
struct ipmmu_vmsa_device *mmu = priv->mmu;
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
unsigned long flags;
unsigned int i;
int ret = 0;
 
-   if (!mmu) {
+   if (!priv || !priv->mmu) {
dev_err(dev, "Cannot attach to IPMMU\n");
return -ENXIO;
}
@@ -583,8 +583,8 @@ static int ipmmu_attach_device(struct io
if (ret < 0)
return ret;
 
-   for (i = 0; i < priv->num_utlbs; ++i)
-   ipmmu_utlb_enable(domain, priv->utlbs[i]);
+   for (i = 0; i < fwspec->num_ids; ++i)
+   ipmmu_utlb_enable(domain, fwspec->ids[i]);
 
return 0;
 }
@@ -592,12 +592,12 @@ static int ipmmu_attach_device(struct io
 static void ipmmu_detach_device(struct iommu_domain *io_domain,
struct device *dev)
 {
-   struct ipmmu_vmsa_iommu_priv *priv = to_priv(dev);
+   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
unsigned int i;
 
-   for (i = 0; i < priv->num_utlbs; ++i)
-   ipmmu_utlb_disable(domain, priv->utlbs[i]);
+   for (i = 0; i < fwspec->num_ids; ++i)
+   ipmmu_utlb_disable(domain, fwspec->ids[i]);
 
/*
 * TODO: Optimize by disabling the context when no device is attached.
@@ -633,102 +633,36 @@ static phys_addr_t ipmmu_iova_to_phys(st
return domain->iop->iova_to_phys(domain->iop, iova);
 }
 
-static int ipmmu_find_utlbs(struct ipmmu_vmsa_device *mmu, struct device *dev,
-   unsigned int *utlbs, unsigned int num_utlbs)
-{
-   unsigned int i;
-
-   for (i = 0; i < num_utlbs; ++i) {
-   struct of_phandle_args args;
-   int ret;
-
-   ret = of_parse_phandle_with_args(dev->of_node, "iommus",
-"#iommu-cells", i, );
-   if (ret < 0)
-   return ret;
-
-   of_node_put(args.np);
-
-   if (args.np != mmu->dev->of_node || args.args_count != 1)
-   return -EINVAL;
-
-   utlbs[i] = args.args[0];
-   }
-
-   return 0;
-}
-
-static int ipmmu_init_platform_device(struct device *dev)
+static int ipmmu_init_platform_device(struct device *dev,
+ struct of_phandle_args *args)
 {
+   struct platform_device *ipmmu_pdev;
struct ipmmu_vmsa_iommu_priv *priv;
-   struct ipmmu_vmsa_device *mmu;
-   unsigned int *utlbs;
-   unsigned int i;
-   int num_utlbs;
-   int ret = -ENODEV;
-
-   /* Find the master corresponding to the device. */
 
-   num_utlbs = of_count_phandle_with_args(dev->of_node, "iommus",
-  "#iommu-cells");
-   if (num_utlbs < 0)
+   ipmmu_pdev = of_find_device_by_node(args->np);
+   if (!ipmmu_pdev)
return -ENODEV;
 
-   utlbs = kcalloc(num_utlbs, sizeof(*utlbs), GFP_KERNEL);
-   if (!utlbs)
-   return -ENOMEM;
-
-   spin_lock(_devices_lock);
-
-   list_for_each_entry(mmu, _devices, list) {
-   ret = ipmmu_find_utlbs(mmu, dev, utlbs, num_utlbs);
-   if (!ret) {
-   /*
-* TODO Take a reference to the MMU to protect
-* against device removal.
-*/
-   break;
-   }
-   }
-
-   spin_unlock(_devices_lock);
-
-   if (ret < 0)
-

[PATCH v2 03/05] iommu/ipmmu-vmsa: Use fwspec on both 32 and 64-bit ARM

2017-07-17 Thread Magnus Damm
From: Robin Murphy <robin.mur...@arm.com>

Consolidate the 32-bit and 64-bit code to make use of fwspec instead
of archdata for the 32-bit ARM case.

This is a simplified version of the fwspec handling code from Robin
posted as [PATCH] iommu/ipmmu-vmsa: Convert to iommu_fwspec

Signed-off-by: Robin Murphy <robin.mur...@arm.com>
Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V1:
 - Rebased to apply on top of earlier changes in series

 drivers/iommu/ipmmu-vmsa.c |   21 +++--
 1 file changed, 3 insertions(+), 18 deletions(-)

--- 0004/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-07-17 21:04:54.850607110 +0900
@@ -73,22 +73,9 @@ static struct ipmmu_vmsa_domain *to_vmsa
return container_of(dom, struct ipmmu_vmsa_domain, io_domain);
 }
 
-
 static struct ipmmu_vmsa_iommu_priv *to_priv(struct device *dev)
 {
-#if defined(CONFIG_ARM)
-   return dev->archdata.iommu;
-#else
-   return dev->iommu_fwspec->iommu_priv;
-#endif
-}
-static void set_priv(struct device *dev, struct ipmmu_vmsa_iommu_priv *p)
-{
-#if defined(CONFIG_ARM)
-   dev->archdata.iommu = p;
-#else
-   dev->iommu_fwspec->iommu_priv = p;
-#endif
+   return dev->iommu_fwspec ? dev->iommu_fwspec->iommu_priv : NULL;
 }
 
 #define TLB_LOOP_TIMEOUT   100 /* 100us */
@@ -726,7 +713,7 @@ static int ipmmu_init_platform_device(st
priv->utlbs = utlbs;
priv->num_utlbs = num_utlbs;
priv->dev = dev;
-   set_priv(dev, priv);
+   dev->iommu_fwspec->iommu_priv = priv;
return 0;
 
 error:
@@ -887,14 +874,12 @@ static void ipmmu_domain_free_dma(struct
 
 static int ipmmu_add_device_dma(struct device *dev)
 {
-   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
struct iommu_group *group;
 
/*
 * Only let through devices that have been verified in xlate()
-* We may get called with dev->iommu_fwspec set to NULL.
 */
-   if (!fwspec || !fwspec->iommu_priv)
+   if (!to_priv(dev))
return -ENODEV;
 
group = iommu_group_get_for_dev(dev);
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v2 02/05] iommu/ipmmu-vmsa: Consistent ->of_xlate() handling

2017-07-17 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

The 32-bit ARM code gets updated to make use of ->of_xlate() and the
code is shared between 64-bit and 32-bit ARM. The of_device_is_available()
check gets dropped since it is included in of_iommu_xlate().

Suggested-by: Robin Murphy <robin.mur...@arm.com>
Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V1:
 - Moved "Initialize once" check to ipmmu_of_xlate() - thanks Geert!

 drivers/iommu/ipmmu-vmsa.c |   51 ++--
 1 file changed, 17 insertions(+), 34 deletions(-)

--- 0002/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-07-17 21:03:38.340607110 +0900
@@ -734,6 +734,16 @@ error:
return ret;
 }
 
+static int ipmmu_of_xlate(struct device *dev,
+ struct of_phandle_args *spec)
+{
+   /* Initialize once - xlate() will call multiple times */
+   if (to_priv(dev))
+   return 0;
+
+   return ipmmu_init_platform_device(dev);
+}
+
 #if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
 
 static struct iommu_domain *ipmmu_domain_alloc(unsigned type)
@@ -750,11 +760,11 @@ static int ipmmu_add_device(struct devic
struct iommu_group *group;
int ret;
 
-   if (to_priv(dev)) {
-   dev_warn(dev, "IOMMU driver already assigned to device %s\n",
-dev_name(dev));
-   return -EINVAL;
-   }
+   /*
+* Only let through devices that have been verified in xlate()
+*/
+   if (!to_priv(dev))
+   return -ENODEV;
 
/* Create a device group and add the device to it. */
group = iommu_group_alloc();
@@ -773,10 +783,6 @@ static int ipmmu_add_device(struct devic
goto error;
}
 
-   ret = ipmmu_init_platform_device(dev);
-   if (ret < 0)
-   goto error;
-
/*
 * Create the ARM mapping, used by the ARM DMA mapping core to allocate
 * VAs. This will allocate a corresponding IOMMU domain.
@@ -817,24 +823,13 @@ error:
if (!IS_ERR_OR_NULL(group))
iommu_group_remove_device(dev);
 
-   kfree(to_priv(dev)->utlbs);
-   kfree(to_priv(dev));
-   set_priv(dev, NULL);
-
return ret;
 }
 
 static void ipmmu_remove_device(struct device *dev)
 {
-   struct ipmmu_vmsa_iommu_priv *priv = to_priv(dev);
-
arm_iommu_detach_device(dev);
iommu_group_remove_device(dev);
-
-   kfree(priv->utlbs);
-   kfree(priv);
-
-   set_priv(dev, NULL);
 }
 
 static const struct iommu_ops ipmmu_ops = {
@@ -849,6 +844,7 @@ static const struct iommu_ops ipmmu_ops
.add_device = ipmmu_add_device,
.remove_device = ipmmu_remove_device,
.pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K,
+   .of_xlate = ipmmu_of_xlate,
 };
 
 #endif /* !CONFIG_ARM && CONFIG_IOMMU_DMA */
@@ -958,19 +954,6 @@ static struct iommu_group *ipmmu_find_gr
return group;
 }
 
-static int ipmmu_of_xlate_dma(struct device *dev,
- struct of_phandle_args *spec)
-{
-   /* If the IPMMU device is disabled in DT then return error
-* to make sure the of_iommu code does not install ops
-* even though the iommu device is disabled
-*/
-   if (!of_device_is_available(spec->np))
-   return -ENODEV;
-
-   return ipmmu_init_platform_device(dev);
-}
-
 static const struct iommu_ops ipmmu_ops = {
.domain_alloc = ipmmu_domain_alloc_dma,
.domain_free = ipmmu_domain_free_dma,
@@ -984,7 +967,7 @@ static const struct iommu_ops ipmmu_ops
.remove_device = ipmmu_remove_device_dma,
.device_group = ipmmu_find_group_dma,
.pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K,
-   .of_xlate = ipmmu_of_xlate_dma,
+   .of_xlate = ipmmu_of_xlate,
 };
 
 #endif /* CONFIG_IOMMU_DMA */
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v2 01/05] iommu/ipmmu-vmsa: Use iommu_device_register()/unregister()

2017-07-17 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Extend the driver to make use of iommu_device_register()/unregister()
functions together with iommu_device_set_ops() and iommu_set_fwnode().

These used to be part of the earlier posted 64-bit ARM (r8a7795) series but
it turns out that these days they are required on 32-bit ARM as well.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V1:
 - Perform iommu_device_set_ops() and iommu_device_set_fwnode() before
   iommu_device_register() - thanks Robin!

 drivers/iommu/ipmmu-vmsa.c |   10 ++
 1 file changed, 10 insertions(+)

--- 0001/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-07-17 21:01:47.140607110 +0900
@@ -35,6 +35,7 @@
 struct ipmmu_vmsa_device {
struct device *dev;
void __iomem *base;
+   struct iommu_device iommu;
struct list_head list;
 
unsigned int num_utlbs;
@@ -1054,6 +1055,13 @@ static int ipmmu_probe(struct platform_d
 
ipmmu_device_reset(mmu);
 
+   iommu_device_set_ops(>iommu, _ops);
+   iommu_device_set_fwnode(>iommu, >dev.of_node->fwnode);
+
+   ret = iommu_device_register(>iommu);
+   if (ret)
+   return ret;
+
/*
 * We can't create the ARM mapping here as it requires the bus to have
 * an IOMMU, which only happens when bus_set_iommu() is called in
@@ -1077,6 +1085,8 @@ static int ipmmu_remove(struct platform_
list_del(>list);
spin_unlock(_devices_lock);
 
+   iommu_device_unregister(>iommu);
+
 #if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
arm_iommu_release_mapping(mmu->mapping);
 #endif
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v2 00/05] iommu/ipmmu-vmsa: 32-bit ARM update V2

2017-07-17 Thread Magnus Damm
iommu/ipmmu-vmsa: 32-bit ARM update V2

[PATCH v2 01/05] iommu/ipmmu-vmsa: Use iommu_device_register()/unregister()
[PATCH v2 02/05] iommu/ipmmu-vmsa: Consistent ->of_xlate() handling
[PATCH v2 03/05] iommu/ipmmu-vmsa: Use fwspec on both 32 and 64-bit ARM
[PATCH v2 04/05] iommu/ipmmu-vmsa: Replace local utlb code with fwspec ids
[PATCH v2 05/05] iommu/ipmmu-vmsa: Clean up device tracking

This series updates the IPMMU driver to make use of recent IOMMU framework
changes and also improves code sharing in the driver between the 32-bit and
64-bit dma-mapping architecture glue code.

Suggested-by: Robin Murphy <robin.mur...@arm.com> (Patch 2 and 4)
Signed-off-by: Robin Murphy <robin.mur...@arm.com> (Patch 3 and 5)
Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V1:
 - Minor changes to patch 1 and 2 - thanks Robin and Geert!
 - Added patch 5 to include further clean ups

 Developed on top of v4.13-rc1

 drivers/iommu/ipmmu-vmsa.c |  198 ++--
 1 file changed, 49 insertions(+), 149 deletions(-)
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


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

2017-06-19 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

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 <damm+rene...@opensource.se>
Reviewed-by: Geert Uytterhoeven <geert+rene...@glider.be>
---

 Changes since V3:
 - Added Reviewed-by from Geert - thanks!

 Changes since V2:
 - Updated to include white list suppport

 Changes since V1:
 - None

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

--- 0016/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-19 19:48:27.430607110 +0900
@@ -755,8 +755,9 @@ static bool ipmmu_slave_whitelist(struct
return false;
 }
 
-static const struct soc_device_attribute soc_r8a7795[] = {
+static const struct soc_device_attribute soc_rcar_gen3[] = {
{ .soc_id = "r8a7795", },
+   { .soc_id = "r8a7796", },
{ /* sentinel */ }
 };
 
@@ -772,7 +773,7 @@ static int ipmmu_of_xlate(struct device
}
 
/* For R-Car Gen3 use a white list to opt-in slave devices */
-   if (soc_device_match(soc_r8a7795) && !ipmmu_slave_whitelist(dev))
+   if (soc_device_match(soc_rcar_gen3) && !ipmmu_slave_whitelist(dev))
return -ENODEV;
 
iommu_fwspec_add_ids(dev, spec->args, 1);
@@ -1034,7 +1035,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,
.number_of_contexts = 8,
@@ -1048,7 +1049,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 */
},
@@ -1229,6 +1233,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);
 #endif
 
 MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU");
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v4 0/3] iommu/ipmmu-vmsa: r8a7796 support V4

2017-06-19 Thread Magnus Damm
iommu/ipmmu-vmsa: r8a7796 support V4

[PATCH v4 1/3] iommu/ipmmu-vmsa: Add r8a7796 DT binding
[PATCH v4 2/3] iommu/ipmmu-vmsa: Increase maximum micro-TLBS to 48
[PATCH v4 3/3] iommu/ipmmu-vmsa: Hook up r8a7796 DT matching code

This series adds r8a7796 support to the IPMMU driver. The DT binding
gets updated, maximum number of micro-TLBs are increased and the
driver is adjusted to match on the new DT binding.

Changes since V3:
 - Rebased on top of [PATCH v4 00/09] iommu/ipmmu-vmsa: r8a7795 support V4
 - Patch 3/3 updated with Reviewed-by - thanks Geert!

Changes since V2:
 - Patch 2/3 updated with an outer set of () - thanks Ramesh!
 - Patch 2/3 updated with Reviewed-by - thanks Geert!
 - Patch 3/3 updated to include white list support

Changes since V1:
 - Patch 1/3 updated with more Acked-by tags
 - Patch 2/3 updated with high I/O register range support

Patch 1/3 is ready for upstream merge and includes the following tags:
Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
Acked-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
Acked-by: Rob Herring <r...@kernel.org>
Acked-by: Simon Horman <horms+rene...@verge.net.au>
Acked-by: Geert Uytterhoeven <geert+rene...@glider.be>

Patch 2/3 and 3/3 are quite trivial but have no acked-by so far.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Developed on top of next-20170614 with the following series applied
 [PATCH 00/04] iommu/ipmmu-vmsa: 32-bit ARM update
 [PATCH v4 00/09] iommu/ipmmu-vmsa: r8a7795 support V4

 Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt |1 
 drivers/iommu/ipmmu-vmsa.c |   24 
+++---
 2 files changed, 18 insertions(+), 7 deletions(-)
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v4 1/3] iommu/ipmmu-vmsa: Add r8a7796 DT binding

2017-06-19 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Update the IPMMU DT binding documentation to include the r8a7796 compat
string for R-Car M3-W.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
Acked-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
Acked-by: Rob Herring <r...@kernel.org>
Acked-by: Simon Horman <horms+rene...@verge.net.au>
Acked-by: Geert Uytterhoeven <geert+rene...@glider.be>
---

 Changes since V3:
 - None

 Changes since V2:
 - None

 Changes since V1:
 - Included in series, added Acked-by from Geert - thanks!

 Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt |1 +
 1 file changed, 1 insertion(+)

--- 0001/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt
+++ work/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt 
2017-06-19 19:51:13.990607110 +0900
@@ -16,6 +16,7 @@ Required Properties:
 - "renesas,ipmmu-r8a7793" for the R8A7793 (R-Car M2-N) IPMMU.
 - "renesas,ipmmu-r8a7794" for the R8A7794 (R-Car E2) IPMMU.
 - "renesas,ipmmu-r8a7795" for the R8A7795 (R-Car H3) IPMMU.
+- "renesas,ipmmu-r8a7796" for the R8A7796 (R-Car M3-W) IPMMU.
 - "renesas,ipmmu-vmsa" for generic R-Car Gen2 VMSA-compatible IPMMU.
 
   - reg: Base address and size of the IPMMU registers.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v4 2/3] iommu/ipmmu-vmsa: Increase maximum micro-TLBS to 48

2017-06-19 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Bump up the maximum numbers of micro-TLBS to 48.

Each IPMMU device instance get micro-TLB assignment via
the "iommus" property in DT. Older SoCs tend to use a
maximum number of 32 micro-TLBs per IPMMU instance however
newer SoCs such as r8a7796 make use of up to 48 micro-TLBs.

At this point no SoC specific handling is done to validate
the maximum number of micro-TLBs, and because of that the
DT information is assumed to be within correct range for
each particular SoC.

If needed in the future SoC specific feature flags can be
added to handle the maximum number of micro-TLBs without
requiring DT changes, however at this point this does not
seem necessary.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
Reviewed-by: Geert Uytterhoeven <geert+rene...@glider.be>
---

 Changes since V3:
 - None

 Changes since V2:
 - Added outer set of () to IMUASID() and IMUCTR() - thanks Ramesh!
 - Added Reviewed-by from Geert - thanks!

 Changes since V1:
 - Added support for the second I/O range at 0x600.

 drivers/iommu/ipmmu-vmsa.c |   10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

--- 0015/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-19 19:47:28.950607110 +0900
@@ -199,7 +199,9 @@ static struct ipmmu_vmsa_iommu_priv *to_
 #define IMPMBA(n)  (0x0280 + ((n) * 4))
 #define IMPMBD(n)  (0x02c0 + ((n) * 4))
 
-#define IMUCTR(n)  (0x0300 + ((n) * 16))
+#define IMUCTR(n)  ((n) < 32 ? IMUCTR0(n) : IMUCTR32(n))
+#define IMUCTR0(n) (0x0300 + ((n) * 16))
+#define IMUCTR32(n)(0x0600 + (((n) - 32) * 16))
 #define IMUCTR_FIXADDEN(1 << 31)
 #define IMUCTR_FIXADD_MASK (0xff << 16)
 #define IMUCTR_FIXADD_SHIFT16
@@ -209,7 +211,9 @@ static struct ipmmu_vmsa_iommu_priv *to_
 #define IMUCTR_FLUSH   (1 << 1)
 #define IMUCTR_MMUEN   (1 << 0)
 
-#define IMUASID(n) (0x0308 + ((n) * 16))
+#define IMUASID(n) ((n) < 32 ? IMUASID0(n) : IMUASID32(n))
+#define IMUASID0(n)(0x0308 + ((n) * 16))
+#define IMUASID32(n)   (0x0608 + (((n) - 32) * 16))
 #define IMUASID_ASID8_MASK (0xff << 8)
 #define IMUASID_ASID8_SHIFT8
 #define IMUASID_ASID0_MASK (0xff << 0)
@@ -1066,7 +1070,7 @@ static int ipmmu_probe(struct platform_d
}
 
mmu->dev = >dev;
-   mmu->num_utlbs = 32;
+   mmu->num_utlbs = 48;
spin_lock_init(>lock);
bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
mmu->features = of_device_get_match_data(>dev);
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v4 09/09] iommu/ipmmu-vmsa: Hook up r8a7795 DT matching code

2017-06-19 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Tie in r8a7795 features and update the IOMMU_OF_DECLARE
compat string to include the updated compat string.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V3:
 - Rebased code on top of
   [PATCH 00/04] iommu/ipmmu-vmsa: 32-bit ARM update
   This includes support for iommu_fwspec_add_ids()
 - Use dev_err() instead of dev_info() - Thanks Geert!
 - Moved single-invokation check into of_xlate() - Thanks Geert!
 - Dropped TODO list
 
 Changes since V2:
 - Check for lack of root device in ->xlate()
   This fixed a bug when IPMMU-MM is disabled in DT the system hangs on boot
 - Added code to ipmmu_init_platform_device() to handle multiple ->xlate() calls
 - Include empty white list by default
 - Updated TODO list

 Changes since V1:
 - Enable multi context feature
 - Update TODO list

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

--- 0029/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-19 14:10:58.930607110 +0900
@@ -25,6 +25,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
 #include 
@@ -730,10 +731,6 @@ static int ipmmu_init_platform_device(st
struct platform_device *ipmmu_pdev;
struct ipmmu_vmsa_iommu_priv *priv;
 
-   /* Initialize once - xlate() will call multiple times */
-   if (to_priv(dev))
-   return 0;
-
ipmmu_pdev = of_find_device_by_node(args->np);
if (!ipmmu_pdev)
return -ENODEV;
@@ -748,11 +745,41 @@ static int ipmmu_init_platform_device(st
return 0;
 }
 
+static bool ipmmu_slave_whitelist(struct device *dev)
+{
+   /* By default, do not allow use of IPMMU */
+   return false;
+}
+
+static const struct soc_device_attribute soc_r8a7795[] = {
+   { .soc_id = "r8a7795", },
+   { /* sentinel */ }
+};
+
 static int ipmmu_of_xlate(struct device *dev,
  struct of_phandle_args *spec)
 {
+   /* Failing in ->attach_device() results in a hang, so make
+* sure the root device is installed before going there
+*/
+   if (!__ipmmu_find_root()) {
+   dev_err(dev, "Unable to locate IPMMU root device\n");
+   return -ENODEV;
+   }
+
+   /* For R-Car Gen3 use a white list to opt-in slave devices */
+   if (soc_device_match(soc_r8a7795) && !ipmmu_slave_whitelist(dev))
+   return -ENODEV;
+
iommu_fwspec_add_ids(dev, spec->args, 1);
 
+   /*
+* Execute ipmmu_init_platform_device() once per device.
+* This xlate() callback will be invoked multiple times.
+*/
+   if (to_priv(dev))
+   return 0;
+
return ipmmu_init_platform_device(dev, spec);
 }
 
@@ -1003,11 +1030,22 @@ static const struct ipmmu_features ipmmu
.twobit_imttbcr_sl0 = false,
 };
 
+static const struct ipmmu_features ipmmu_features_r8a7795 = {
+   .use_ns_alias_offset = false,
+   .has_cache_leaf_nodes = true,
+   .number_of_contexts = 8,
+   .setup_imbuscr = false,
+   .twobit_imttbcr_sl0 = true,
+};
+
 static const struct of_device_id ipmmu_of_ids[] = {
{
.compatible = "renesas,ipmmu-vmsa",
.data = _features_default,
}, {
+   .compatible = "renesas,ipmmu-r8a7795",
+   .data = _features_r8a7795,
+   }, {
/* Terminator */
},
 };
@@ -1185,6 +1223,8 @@ static int __init ipmmu_vmsa_iommu_of_se
 
 IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa",
 ipmmu_vmsa_iommu_of_setup);
+IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795",
+ipmmu_vmsa_iommu_of_setup);
 #endif
 
 MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU");
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v4 08/09] iommu/ipmmu-vmsa: Allow two bit SL0

2017-06-19 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Introduce support for two bit SL0 bitfield in IMTTBCR
by using a separate feature flag.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V3:
 - None

 Changes since V2:
 - None

 Changes since V1:
 - None

 drivers/iommu/ipmmu-vmsa.c |   14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

--- 0027/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-19 14:08:26.100607110 +0900
@@ -40,6 +40,7 @@ struct ipmmu_features {
bool has_cache_leaf_nodes;
unsigned int number_of_contexts;
bool setup_imbuscr;
+   bool twobit_imttbcr_sl0;
 };
 
 struct ipmmu_vmsa_device {
@@ -149,6 +150,10 @@ static struct ipmmu_vmsa_iommu_priv *to_
 #define IMTTBCR_TSZ0_MASK  (7 << 0)
 #define IMTTBCR_TSZ0_SHIFT O
 
+#define IMTTBCR_SL0_TWOBIT_LVL_3   (0 << 6)
+#define IMTTBCR_SL0_TWOBIT_LVL_2   (1 << 6)
+#define IMTTBCR_SL0_TWOBIT_LVL_1   (2 << 6)
+
 #define IMBUSCR0x000c
 #define IMBUSCR_DVM(1 << 2)
 #define IMBUSCR_BUSSEL_SYS (0 << 0)
@@ -393,6 +398,7 @@ static int ipmmu_domain_allocate_context
 static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain)
 {
u64 ttbr;
+   u32 tmp;
int ret;
 
/*
@@ -445,9 +451,14 @@ static int ipmmu_domain_init_context(str
 * We use long descriptors with inner-shareable WBWA tables and allocate
 * the whole 32-bit VA space to TTBR0.
 */
+   if (domain->root->features->twobit_imttbcr_sl0)
+   tmp = IMTTBCR_SL0_TWOBIT_LVL_1;
+   else
+   tmp = IMTTBCR_SL0_LVL_1;
+
ipmmu_ctx_write_root(domain, IMTTBCR, IMTTBCR_EAE |
 IMTTBCR_SH0_INNER_SHAREABLE | IMTTBCR_ORGN0_WB_WA |
-IMTTBCR_IRGN0_WB_WA | IMTTBCR_SL0_LVL_1);
+IMTTBCR_IRGN0_WB_WA | tmp);
 
/* MAIR0 */
ipmmu_ctx_write_root(domain, IMMAIR0,
@@ -989,6 +1000,7 @@ static const struct ipmmu_features ipmmu
.has_cache_leaf_nodes = false,
.number_of_contexts = 1, /* software only tested with one context */
.setup_imbuscr = true,
+   .twobit_imttbcr_sl0 = false,
 };
 
 static const struct of_device_id ipmmu_of_ids[] = {
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v4 06/09] iommu/ipmmu-vmsa: Write IMCTR twice

2017-06-19 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Write IMCTR both in the root device and the leaf node.

To allow access of IMCTR introduce the following function:
 - ipmmu_ctx_write_all()

While at it also rename context functions:
 - ipmmu_ctx_read() -> ipmmu_ctx_read_root()
 - ipmmu_ctx_write() -> ipmmu_ctx_write_root()

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V3:
 - Changed function names to improve code readability - Thanks Robin!

 Changes since V2:
 - None

 Changes since V1:
 - None

 drivers/iommu/ipmmu-vmsa.c |   55 +++-
 1 file changed, 34 insertions(+), 21 deletions(-)

--- 0023/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-19 14:06:16.770607110 +0900
@@ -261,17 +261,28 @@ static void ipmmu_write(struct ipmmu_vms
iowrite32(data, mmu->base + offset);
 }
 
-static u32 ipmmu_ctx_read(struct ipmmu_vmsa_domain *domain, unsigned int reg)
+static u32 ipmmu_ctx_read_root(struct ipmmu_vmsa_domain *domain,
+  unsigned int reg)
 {
return ipmmu_read(domain->root, domain->context_id * IM_CTX_SIZE + reg);
 }
 
-static void ipmmu_ctx_write(struct ipmmu_vmsa_domain *domain, unsigned int reg,
-   u32 data)
+static void ipmmu_ctx_write_root(struct ipmmu_vmsa_domain *domain,
+unsigned int reg, u32 data)
 {
ipmmu_write(domain->root, domain->context_id * IM_CTX_SIZE + reg, data);
 }
 
+static void ipmmu_ctx_write_all(struct ipmmu_vmsa_domain *domain,
+   unsigned int reg, u32 data)
+{
+   if (domain->mmu != domain->root)
+   ipmmu_write(domain->mmu,
+   domain->context_id * IM_CTX_SIZE + reg, data);
+
+   ipmmu_write(domain->root, domain->context_id * IM_CTX_SIZE + reg, data);
+}
+
 /* 
-
  * TLB and microTLB Management
  */
@@ -281,7 +292,7 @@ static void ipmmu_tlb_sync(struct ipmmu_
 {
unsigned int count = 0;
 
-   while (ipmmu_ctx_read(domain, IMCTR) & IMCTR_FLUSH) {
+   while (ipmmu_ctx_read_root(domain, IMCTR) & IMCTR_FLUSH) {
cpu_relax();
if (++count == TLB_LOOP_TIMEOUT) {
dev_err_ratelimited(domain->mmu->dev,
@@ -296,9 +307,9 @@ static void ipmmu_tlb_invalidate(struct
 {
u32 reg;
 
-   reg = ipmmu_ctx_read(domain, IMCTR);
+   reg = ipmmu_ctx_read_root(domain, IMCTR);
reg |= IMCTR_FLUSH;
-   ipmmu_ctx_write(domain, IMCTR, reg);
+   ipmmu_ctx_write_all(domain, IMCTR, reg);
 
ipmmu_tlb_sync(domain);
 }
@@ -425,31 +436,32 @@ static int ipmmu_domain_init_context(str
 
/* TTBR0 */
ttbr = domain->cfg.arm_lpae_s1_cfg.ttbr[0];
-   ipmmu_ctx_write(domain, IMTTLBR0, ttbr);
-   ipmmu_ctx_write(domain, IMTTUBR0, ttbr >> 32);
+   ipmmu_ctx_write_root(domain, IMTTLBR0, ttbr);
+   ipmmu_ctx_write_root(domain, IMTTUBR0, ttbr >> 32);
 
/*
 * TTBCR
 * We use long descriptors with inner-shareable WBWA tables and allocate
 * the whole 32-bit VA space to TTBR0.
 */
-   ipmmu_ctx_write(domain, IMTTBCR, IMTTBCR_EAE |
-   IMTTBCR_SH0_INNER_SHAREABLE | IMTTBCR_ORGN0_WB_WA |
-   IMTTBCR_IRGN0_WB_WA | IMTTBCR_SL0_LVL_1);
+   ipmmu_ctx_write_root(domain, IMTTBCR, IMTTBCR_EAE |
+IMTTBCR_SH0_INNER_SHAREABLE | IMTTBCR_ORGN0_WB_WA |
+IMTTBCR_IRGN0_WB_WA | IMTTBCR_SL0_LVL_1);
 
/* MAIR0 */
-   ipmmu_ctx_write(domain, IMMAIR0, domain->cfg.arm_lpae_s1_cfg.mair[0]);
+   ipmmu_ctx_write_root(domain, IMMAIR0,
+domain->cfg.arm_lpae_s1_cfg.mair[0]);
 
/* IMBUSCR */
-   ipmmu_ctx_write(domain, IMBUSCR,
-   ipmmu_ctx_read(domain, IMBUSCR) &
-   ~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
+   ipmmu_ctx_write_root(domain, IMBUSCR,
+ipmmu_ctx_read_root(domain, IMBUSCR) &
+~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
 
/*
 * IMSTR
 * Clear all interrupt flags.
 */
-   ipmmu_ctx_write(domain, IMSTR, ipmmu_ctx_read(domain, IMSTR));
+   ipmmu_ctx_write_root(domain, IMSTR, ipmmu_ctx_read_root(domain, IMSTR));
 
/*
 * IMCTR
@@ -458,7 +470,8 @@ static int ipmmu_domain_init_context(str
 * software management as we have no use for it. Flush the TLB as
 * required when modifying the context registers.
 */
-   ipmmu_ctx_write(domain, IMCTR, IMCTR_INTEN | IMCTR_FLUSH | IMCTR_MMUEN);
+   ipmmu_ctx_write_all(domain, IMCTR,
+   IMCTR_INTEN | IMCTR_FLUSH | IMCTR_MMUEN);
 
return

[PATCH v4 07/09] iommu/ipmmu-vmsa: Make IMBUSCTR setup optional

2017-06-19 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Introduce a feature to allow opt-out of setting up
IMBUSCR. The default case is unchanged.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V3:
 - None

 Changes since V2:
 - None

 Changes since V1:
 - Updated the commit message
 - Reworked patch to coexist with the multi context feature

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

--- 0025/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-19 14:07:06.850607110 +0900
@@ -39,6 +39,7 @@ struct ipmmu_features {
bool use_ns_alias_offset;
bool has_cache_leaf_nodes;
unsigned int number_of_contexts;
+   bool setup_imbuscr;
 };
 
 struct ipmmu_vmsa_device {
@@ -453,9 +454,10 @@ static int ipmmu_domain_init_context(str
 domain->cfg.arm_lpae_s1_cfg.mair[0]);
 
/* IMBUSCR */
-   ipmmu_ctx_write_root(domain, IMBUSCR,
-ipmmu_ctx_read_root(domain, IMBUSCR) &
-~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
+   if (domain->root->features->setup_imbuscr)
+   ipmmu_ctx_write_root(domain, IMBUSCR,
+ipmmu_ctx_read_root(domain, IMBUSCR) &
+~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
 
/*
 * IMSTR
@@ -986,6 +988,7 @@ static const struct ipmmu_features ipmmu
.use_ns_alias_offset = true,
.has_cache_leaf_nodes = false,
.number_of_contexts = 1, /* software only tested with one context */
+   .setup_imbuscr = true,
 };
 
 static const struct of_device_id ipmmu_of_ids[] = {
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v4 03/09] iommu/ipmmu-vmsa: Enable multi context support

2017-06-19 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Add support for up to 8 contexts. Each context is mapped to one
domain. One domain is assigned one or more slave devices. Contexts
are allocated dynamically and slave devices are grouped together
based on which IPMMU device they are connected to. This makes slave
devices tied to the same IPMMU device share the same IOVA space.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V3:
 - Use number_of_contexts unsigned int, drop WARN_ON() - Thanks Robin!

 Changes since V2:
 - Updated patch description to reflect code included in:
   [PATCH v7 00/07] iommu/ipmmu-vmsa: IPMMU multi-arch update V7

 Changes since V1:
 - Support up to 8 contexts instead of 4
 - Use feature flag and runtime handling
 - Default to single context

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

--- 0017/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-19 14:00:59.880607110 +0900
@@ -32,11 +32,12 @@
 
 #include "io-pgtable.h"
 
-#define IPMMU_CTX_MAX 1
+#define IPMMU_CTX_MAX 8
 
 struct ipmmu_features {
bool use_ns_alias_offset;
bool has_cache_leaf_nodes;
+   unsigned int number_of_contexts;
 };
 
 struct ipmmu_vmsa_device {
@@ -47,6 +48,7 @@ struct ipmmu_vmsa_device {
const struct ipmmu_features *features;
bool is_leaf;
unsigned int num_utlbs;
+   unsigned int num_ctx;
spinlock_t lock;/* Protects ctx and domains[] */
DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
struct ipmmu_vmsa_domain *domains[IPMMU_CTX_MAX];
@@ -363,11 +365,12 @@ static int ipmmu_domain_allocate_context
 
spin_lock_irqsave(>lock, flags);
 
-   ret = find_first_zero_bit(mmu->ctx, IPMMU_CTX_MAX);
-   if (ret != IPMMU_CTX_MAX) {
+   ret = find_first_zero_bit(mmu->ctx, mmu->num_ctx);
+   if (ret != mmu->num_ctx) {
mmu->domains[ret] = domain;
set_bit(ret, mmu->ctx);
-   }
+   } else
+   ret = -EBUSY;
 
spin_unlock_irqrestore(>lock, flags);
 
@@ -412,9 +415,9 @@ static int ipmmu_domain_init_context(str
 * Find an unused context.
 */
ret = ipmmu_domain_allocate_context(domain->root, domain);
-   if (ret == IPMMU_CTX_MAX) {
+   if (ret < 0) {
free_io_pgtable_ops(domain->iop);
-   return -EBUSY;
+   return ret;
}
 
domain->context_id = ret;
@@ -549,7 +552,7 @@ static irqreturn_t ipmmu_irq(int irq, vo
/*
 * Check interrupts for all active contexts.
 */
-   for (i = 0; i < IPMMU_CTX_MAX; i++) {
+   for (i = 0; i < mmu->num_ctx; i++) {
if (!mmu->domains[i])
continue;
if (ipmmu_domain_irq(mmu->domains[i]) == IRQ_HANDLED)
@@ -620,6 +623,14 @@ static int ipmmu_attach_device(struct io
domain->mmu = mmu;
domain->root = root;
ret = ipmmu_domain_init_context(domain);
+   if (ret < 0) {
+   dev_err(dev, "Unable to initialize IPMMU context\n");
+   domain->mmu = NULL;
+   domain->root = NULL;
+   } else {
+   dev_info(dev, "Using IPMMU context %u\n",
+domain->context_id);
+   }
} else if (domain->mmu != mmu) {
/*
 * Something is wrong, we can't attach two devices using
@@ -953,13 +964,14 @@ static void ipmmu_device_reset(struct ip
unsigned int i;
 
/* Disable all contexts. */
-   for (i = 0; i < 4; ++i)
+   for (i = 0; i < mmu->num_ctx; ++i)
ipmmu_write(mmu, i * IM_CTX_SIZE + IMCTR, 0);
 }
 
 static const struct ipmmu_features ipmmu_features_default = {
.use_ns_alias_offset = true,
.has_cache_leaf_nodes = false,
+   .number_of_contexts = 1, /* software only tested with one context */
 };
 
 static const struct of_device_id ipmmu_of_ids[] = {
@@ -1013,6 +1025,9 @@ static int ipmmu_probe(struct platform_d
if (mmu->features->use_ns_alias_offset)
mmu->base += IM_NS_ALIAS_OFFSET;
 
+   mmu->num_ctx = min_t(unsigned int, IPMMU_CTX_MAX,
+mmu->features->number_of_contexts);
+
irq = platform_get_irq(pdev, 0);
 
/*
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v4 04/09] iommu/ipmmu-vmsa: Make use of IOMMU_OF_DECLARE()

2017-06-19 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Hook up IOMMU_OF_DECLARE() support in case CONFIG_IOMMU_DMA
is enabled. The only current supported case for 32-bit ARM
is disabled, however for 64-bit ARM usage of OF is required.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V3:
 - Reworked to fit on top of
   [PATCH 00/04] iommu/ipmmu-vmsa: 32-bit ARM update

 Changes since V2:
 - Reworked registration code to make use of recently introduced:
 iommu_device_register()
 iommu_device_set_ops()
 iommu_device_set_fwnode()

 Changes since V1:
 - Reworked slightly to fit updated patch order and
   [PATCH v3 00/06] iommu/ipmmu-vmsa: IPMMU multi-arch update V3

 drivers/iommu/ipmmu-vmsa.c |   43 +--
 1 file changed, 37 insertions(+), 6 deletions(-)

--- 0019/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-19 14:03:53.140607110 +0900
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1055,13 +1056,25 @@ static int ipmmu_probe(struct platform_d
ipmmu_device_reset(mmu);
}
 
-   ret = iommu_device_register(>iommu);
-   if (ret)
-   return ret;
-
-   iommu_device_set_ops(>iommu, _ops);
-   iommu_device_set_fwnode(>iommu, >dev.of_node->fwnode);
+   /*
+* Register the IPMMU to the IOMMU subsystem in the following cases:
+* - R-Car Gen2 IPMMU (all devices registered)
+* - R-Car Gen3 IPMMU (leaf devices only - skip root IPMMU-MM device)
+*/
+   if (!mmu->features->has_cache_leaf_nodes || mmu->is_leaf) {
+   ret = iommu_device_register(>iommu);
+   if (ret)
+   return ret;
 
+   iommu_device_set_ops(>iommu, _ops);
+   iommu_device_set_fwnode(>iommu,
+   >dev.of_node->fwnode);
+
+#if defined(CONFIG_IOMMU_DMA)
+   if (!iommu_present(_bus_type))
+   bus_set_iommu(_bus_type, _ops);
+#endif
+   }
/*
 * We can't create the ARM mapping here as it requires the bus to have
 * an IOMMU, which only happens when bus_set_iommu() is called in
@@ -1107,15 +1120,22 @@ static struct platform_driver ipmmu_driv
 
 static int __init ipmmu_init(void)
 {
+   static bool setup_done;
int ret;
 
+   if (setup_done)
+   return 0;
+
ret = platform_driver_register(_driver);
if (ret < 0)
return ret;
 
+#if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
if (!iommu_present(_bus_type))
bus_set_iommu(_bus_type, _ops);
+#endif
 
+   setup_done = true;
return 0;
 }
 
@@ -1127,6 +1147,17 @@ static void __exit ipmmu_exit(void)
 subsys_initcall(ipmmu_init);
 module_exit(ipmmu_exit);
 
+#ifdef CONFIG_IOMMU_DMA
+static int __init ipmmu_vmsa_iommu_of_setup(struct device_node *np)
+{
+   ipmmu_init();
+   return 0;
+}
+
+IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa",
+ipmmu_vmsa_iommu_of_setup);
+#endif
+
 MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU");
 MODULE_AUTHOR("Laurent Pinchart <laurent.pinch...@ideasonboard.com>");
 MODULE_LICENSE("GPL v2");
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v4 00/09] iommu/ipmmu-vmsa: r8a7795 support V4

2017-06-19 Thread Magnus Damm
iommu/ipmmu-vmsa: r8a7795 support V4

[PATCH v4 01/09] iommu/ipmmu-vmsa: Introduce features, break out alias
[PATCH v4 02/09] iommu/ipmmu-vmsa: Add optional root device feature
[PATCH v4 03/09] iommu/ipmmu-vmsa: Enable multi context support
[PATCH v4 04/09] iommu/ipmmu-vmsa: Make use of IOMMU_OF_DECLARE()
[PATCH v4 05/09] iommu/ipmmu-vmsa: IPMMU device is 40-bit bus master
[PATCH v4 06/09] iommu/ipmmu-vmsa: Write IMCTR twice
[PATCH v4 07/09] iommu/ipmmu-vmsa: Make IMBUSCTR setup optional
[PATCH v4 08/09] iommu/ipmmu-vmsa: Allow two bit SL0
[PATCH v4 09/09] iommu/ipmmu-vmsa: Hook up r8a7795 DT matching code

Here's an updated series for r8a7795 IPMMU support. The patches adjust
the code based on feedback from Geert and Robin together with a rebase
to include changes from the recently posted series:

[PATCH 00/04] iommu/ipmmu-vmsa: 32-bit ARM update

The DT binding for r8a7795 has been accepted for upstream merge
and this series implements support following such format:

d4e42e7 iommu/ipmmu-vmsa: Add r8a7795 DT binding

The r8a7795 IPMMU is almost register compatible with earlier devices
like r8a7790-r8a7794, however some bitfields have been shifted
slightly. On a grander scale topology has been added and interrupts
have been reworked. So now there are several "cache" IPMMU units
without interrupt that somehow communicate with IPMMU-MM that
is the only instance that supports interrupts. The code refers to
IPMMU-MM as a "root" device and the other ones as "leaf" nodes.

Changes since V3:
 - Rebased on top of [PATCH 00/04] iommu/ipmmu-vmsa: 32-bit ARM update
 - Patch 1/9 has been updated to use of_device_get_match_data(), thanks Robin!
 - Patch 2/9 has been reworked to make it easier to follow, thanks Geert!
 - Patch 3/9 now uses unsigned int for context counts - thanks Robin!
 - Patch 6/9 now includes function name changes - thanks Robin! 
 - Patch 9/9 now uses dev_err() instead of dev_info() - thanks Geert!

Changes since V2:
 - Patch 2/9 has been updated with a bug fix and to supply __ipmmu_find_root()
 - Patch 4/9 now makes use of iommu_device_* functions
 - Patch 5/9 sets the mask to 40 bits instead of 64 bits
 - Patch 9/9 implements white list handling via ->xlate() and fixes a bug

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Developed on top of next-20170614 with the following series applied
 [PATCH 00/04] iommu/ipmmu-vmsa: 32-bit ARM update

 drivers/iommu/ipmmu-vmsa.c |  327 ++--
 1 file changed, 260 insertions(+), 67 deletions(-)
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v4 01/09] iommu/ipmmu-vmsa: Introduce features, break out alias

2017-06-19 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Introduce struct ipmmu_features to track various hardware
and software implementation changes inside the driver for
different kinds of IPMMU hardware. Add use_ns_alias_offset
as a first example of a feature to control if the secure
register bank offset should be used or not.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V3:
 - Use of_device_get_match_data(), thanks Robin!

 Changes since V2:
 - None

 Changes since V1:
 - Moved patch to front of the series

 drivers/iommu/ipmmu-vmsa.c |   31 ---
 1 file changed, 24 insertions(+), 7 deletions(-)

--- 0014/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-19 13:57:36.300607110 +0900
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -33,12 +34,16 @@
 
 #define IPMMU_CTX_MAX 1
 
+struct ipmmu_features {
+   bool use_ns_alias_offset;
+};
+
 struct ipmmu_vmsa_device {
struct device *dev;
void __iomem *base;
struct iommu_device iommu;
struct list_head list;
-
+   const struct ipmmu_features *features;
unsigned int num_utlbs;
spinlock_t lock;/* Protects ctx and domains[] */
DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
@@ -904,6 +909,21 @@ static void ipmmu_device_reset(struct ip
ipmmu_write(mmu, i * IM_CTX_SIZE + IMCTR, 0);
 }
 
+static const struct ipmmu_features ipmmu_features_default = {
+   .use_ns_alias_offset = true,
+};
+
+static const struct of_device_id ipmmu_of_ids[] = {
+   {
+   .compatible = "renesas,ipmmu-vmsa",
+   .data = _features_default,
+   }, {
+   /* Terminator */
+   },
+};
+
+MODULE_DEVICE_TABLE(of, ipmmu_of_ids);
+
 static int ipmmu_probe(struct platform_device *pdev)
 {
struct ipmmu_vmsa_device *mmu;
@@ -921,6 +941,7 @@ static int ipmmu_probe(struct platform_d
mmu->num_utlbs = 32;
spin_lock_init(>lock);
bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
+   mmu->features = of_device_get_match_data(>dev);
 
/* Map I/O memory and request IRQ. */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -940,7 +961,8 @@ static int ipmmu_probe(struct platform_d
 * Offset the registers base unconditionally to point to the non-secure
 * alias space for now.
 */
-   mmu->base += IM_NS_ALIAS_OFFSET;
+   if (mmu->features->use_ns_alias_offset)
+   mmu->base += IM_NS_ALIAS_OFFSET;
 
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
@@ -998,11 +1020,6 @@ static int ipmmu_remove(struct platform_
return 0;
 }
 
-static const struct of_device_id ipmmu_of_ids[] = {
-   { .compatible = "renesas,ipmmu-vmsa", },
-   { }
-};
-
 static struct platform_driver ipmmu_driver = {
.driver = {
.name = "ipmmu-vmsa",
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v4 02/09] iommu/ipmmu-vmsa: Add optional root device feature

2017-06-19 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Add root device handling to the IPMMU driver by allowing certain
DT compat strings to enable has_cache_leaf_nodes that in turn will
support both root devices with interrupts and leaf devices that
face the actual IPMMU consumer devices.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V3:
 - Reworked root finding code to make it easier to follow, thanks Geert!
 
 Changes since V2:
 - Fixed a bug in ipmmu_find_root() when only leaf devices are present
 - Broke out __ipmmu_find_root() to allow ->xlate() check for root devices

 Changes since V1:
 - Moved patch to earlier in the series
 - Updated code to work with recent changes in:
   [PATCH v3 00/06] iommu/ipmmu-vmsa: IPMMU multi-arch update V3

 drivers/iommu/ipmmu-vmsa.c |   95 
 1 file changed, 78 insertions(+), 17 deletions(-)

--- 0015/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-19 13:59:41.050607110 +0900
@@ -36,6 +36,7 @@
 
 struct ipmmu_features {
bool use_ns_alias_offset;
+   bool has_cache_leaf_nodes;
 };
 
 struct ipmmu_vmsa_device {
@@ -44,6 +45,7 @@ struct ipmmu_vmsa_device {
struct iommu_device iommu;
struct list_head list;
const struct ipmmu_features *features;
+   bool is_leaf;
unsigned int num_utlbs;
spinlock_t lock;/* Protects ctx and domains[] */
DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
@@ -54,6 +56,7 @@ struct ipmmu_vmsa_device {
 
 struct ipmmu_vmsa_domain {
struct ipmmu_vmsa_device *mmu;
+   struct ipmmu_vmsa_device *root;
struct iommu_domain io_domain;
 
struct io_pgtable_cfg cfg;
@@ -203,6 +206,44 @@ static struct ipmmu_vmsa_iommu_priv *to_
 #define IMUASID_ASID0_SHIFT0
 
 /* 
-
+ * Root device handling
+ */
+
+static bool ipmmu_is_root(struct ipmmu_vmsa_device *mmu)
+{
+   if (mmu->features->has_cache_leaf_nodes)
+   return mmu->is_leaf ? false : true;
+   else
+   return true; /* older IPMMU hardware treated as single root */
+}
+
+static struct ipmmu_vmsa_device *__ipmmu_find_root(void)
+{
+   struct ipmmu_vmsa_device *mmu;
+   struct ipmmu_vmsa_device *root = NULL;
+
+   spin_lock(_devices_lock);
+
+   list_for_each_entry(mmu, _devices, list) {
+   if (ipmmu_is_root(mmu)) {
+   root = mmu;
+   break;
+   }
+   }
+
+   spin_unlock(_devices_lock);
+   return root;
+}
+
+static struct ipmmu_vmsa_device *ipmmu_find_root(struct ipmmu_vmsa_device 
*leaf)
+{
+   if (ipmmu_is_root(leaf))
+   return leaf;
+   else
+   return __ipmmu_find_root();
+}
+
+/* 
-
  * Read/Write Access
  */
 
@@ -219,13 +260,13 @@ static void ipmmu_write(struct ipmmu_vms
 
 static u32 ipmmu_ctx_read(struct ipmmu_vmsa_domain *domain, unsigned int reg)
 {
-   return ipmmu_read(domain->mmu, domain->context_id * IM_CTX_SIZE + reg);
+   return ipmmu_read(domain->root, domain->context_id * IM_CTX_SIZE + reg);
 }
 
 static void ipmmu_ctx_write(struct ipmmu_vmsa_domain *domain, unsigned int reg,
u32 data)
 {
-   ipmmu_write(domain->mmu, domain->context_id * IM_CTX_SIZE + reg, data);
+   ipmmu_write(domain->root, domain->context_id * IM_CTX_SIZE + reg, data);
 }
 
 /* 
-
@@ -360,7 +401,7 @@ static int ipmmu_domain_init_context(str
 * TODO: Add support for coherent walk through CCI with DVM and remove
 * cache handling. For now, delegate it to the io-pgtable code.
 */
-   domain->cfg.iommu_dev = domain->mmu->dev;
+   domain->cfg.iommu_dev = domain->root->dev;
 
domain->iop = alloc_io_pgtable_ops(ARM_32_LPAE_S1, >cfg,
   domain);
@@ -370,7 +411,7 @@ static int ipmmu_domain_init_context(str
/*
 * Find an unused context.
 */
-   ret = ipmmu_domain_allocate_context(domain->mmu, domain);
+   ret = ipmmu_domain_allocate_context(domain->root, domain);
if (ret == IPMMU_CTX_MAX) {
free_io_pgtable_ops(domain->iop);
return -EBUSY;
@@ -441,7 +482,7 @@ static void ipmmu_domain_destroy_context
 */
ipmmu_ctx_write(domain, IMCTR, IMCTR_FLUSH);
ipmmu_tlb_sync(domain);
-   ipmmu_domain_free_context(domain->mmu, domain->context_id);
+   ipmmu_domain_free_context(domain->root, domain->context_id);
 }
 
 /* 
-
@@ -555,7 +596,7 @@ static int ipmmu_attach_

Re: [PATCH 04/04] iommu/ipmmu-vmsa: Replace local utlb code with fwspec ids

2017-06-16 Thread Magnus Damm
Hi Geert,

On Fri, Jun 16, 2017 at 4:18 PM, Geert Uytterhoeven
<ge...@linux-m68k.org> wrote:
> Hi Magnus,
>
> On Thu, Jun 15, 2017 at 12:29 PM, Magnus Damm <magnus.d...@gmail.com> wrote:
>> Now when both 32-bit and 64-bit code inside the driver is using
>> fwspec it is possible to replace the utlb handling with fwspec ids
>> that get populated from ->of_xlate().
>
> Thanks for your patch!

Thanks for the feedback!

>> --- 0013/drivers/iommu/ipmmu-vmsa.c
>> +++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-15 18:32:27.580607110 +0900
>
>>  static int ipmmu_of_xlate(struct device *dev,
>>   struct of_phandle_args *spec)
>>  {
>> -   return ipmmu_init_platform_device(dev);
>> +   iommu_fwspec_add_ids(dev, spec->args, 1);
>
> Does it hurt if iommu_fwspec_add_ids() is called multiple times, as this is
> done before the "Initialize once - xlate() will call multiple times" check?

The function needs to be called several times to populate the ids, so
that the "initialize once" check happens later is intentional and
correct. Perhaps a bit unclear though...

>> +
>> +   return ipmmu_init_platform_device(dev, spec);
>>  }

Cheers,

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


[PATCH 04/04] iommu/ipmmu-vmsa: Replace local utlb code with fwspec ids

2017-06-15 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Now when both 32-bit and 64-bit code inside the driver is using
fwspec it is possible to replace the utlb handling with fwspec ids
that get populated from ->of_xlate().

Suggested-by: Robin Murphy <robin.mur...@arm.com>
Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 drivers/iommu/ipmmu-vmsa.c |  104 
 1 file changed, 19 insertions(+), 85 deletions(-)

--- 0013/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-15 18:32:27.580607110 +0900
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -59,8 +60,6 @@ struct ipmmu_vmsa_domain {
 
 struct ipmmu_vmsa_iommu_priv {
struct ipmmu_vmsa_device *mmu;
-   unsigned int *utlbs;
-   unsigned int num_utlbs;
struct device *dev;
struct list_head list;
 };
@@ -550,13 +549,14 @@ static int ipmmu_attach_device(struct io
   struct device *dev)
 {
struct ipmmu_vmsa_iommu_priv *priv = to_priv(dev);
+   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
struct ipmmu_vmsa_device *mmu = priv->mmu;
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
unsigned long flags;
unsigned int i;
int ret = 0;
 
-   if (!mmu) {
+   if (!priv || !priv->mmu) {
dev_err(dev, "Cannot attach to IPMMU\n");
return -ENXIO;
}
@@ -583,8 +583,8 @@ static int ipmmu_attach_device(struct io
if (ret < 0)
return ret;
 
-   for (i = 0; i < priv->num_utlbs; ++i)
-   ipmmu_utlb_enable(domain, priv->utlbs[i]);
+   for (i = 0; i < fwspec->num_ids; ++i)
+   ipmmu_utlb_enable(domain, fwspec->ids[i]);
 
return 0;
 }
@@ -592,12 +592,12 @@ static int ipmmu_attach_device(struct io
 static void ipmmu_detach_device(struct iommu_domain *io_domain,
struct device *dev)
 {
-   struct ipmmu_vmsa_iommu_priv *priv = to_priv(dev);
+   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
unsigned int i;
 
-   for (i = 0; i < priv->num_utlbs; ++i)
-   ipmmu_utlb_disable(domain, priv->utlbs[i]);
+   for (i = 0; i < fwspec->num_ids; ++i)
+   ipmmu_utlb_disable(domain, fwspec->ids[i]);
 
/*
 * TODO: Optimize by disabling the context when no device is attached.
@@ -633,102 +633,36 @@ static phys_addr_t ipmmu_iova_to_phys(st
return domain->iop->iova_to_phys(domain->iop, iova);
 }
 
-static int ipmmu_find_utlbs(struct ipmmu_vmsa_device *mmu, struct device *dev,
-   unsigned int *utlbs, unsigned int num_utlbs)
-{
-   unsigned int i;
-
-   for (i = 0; i < num_utlbs; ++i) {
-   struct of_phandle_args args;
-   int ret;
-
-   ret = of_parse_phandle_with_args(dev->of_node, "iommus",
-"#iommu-cells", i, );
-   if (ret < 0)
-   return ret;
-
-   of_node_put(args.np);
-
-   if (args.np != mmu->dev->of_node || args.args_count != 1)
-   return -EINVAL;
-
-   utlbs[i] = args.args[0];
-   }
-
-   return 0;
-}
-
-static int ipmmu_init_platform_device(struct device *dev)
+static int ipmmu_init_platform_device(struct device *dev,
+ struct of_phandle_args *args)
 {
+   struct platform_device *ipmmu_pdev;
struct ipmmu_vmsa_iommu_priv *priv;
-   struct ipmmu_vmsa_device *mmu;
-   unsigned int *utlbs;
-   unsigned int i;
-   int num_utlbs;
-   int ret = -ENODEV;
 
/* Initialize once - xlate() will call multiple times */
if (to_priv(dev))
return 0;
 
-   /* Find the master corresponding to the device. */
-
-   num_utlbs = of_count_phandle_with_args(dev->of_node, "iommus",
-  "#iommu-cells");
-   if (num_utlbs < 0)
+   ipmmu_pdev = of_find_device_by_node(args->np);
+   if (!ipmmu_pdev)
return -ENODEV;
 
-   utlbs = kcalloc(num_utlbs, sizeof(*utlbs), GFP_KERNEL);
-   if (!utlbs)
-   return -ENOMEM;
-
-   spin_lock(_devices_lock);
-
-   list_for_each_entry(mmu, _devices, list) {
-   ret = ipmmu_find_utlbs(mmu, dev, utlbs, num_utlbs);
-   if (!ret) {
-   /*
-* TODO Take a reference to the MMU to protect
-* against device removal.
-*/
-   break;
-   }
-   }
-
-   spi

[PATCH 02/04] iommu/ipmmu-vmsa: Consistent ->of_xlate() handling

2017-06-15 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

The 32-bit ARM code gets updated to make use of ->of_xlate() and the
code is shared between 64-bit and 32-bit ARM. The of_device_is_available()
check gets dropped since it is included in of_iommu_xlate().

Suggested-by: Robin Murphy <robin.mur...@arm.com>
Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 drivers/iommu/ipmmu-vmsa.c |   51 ++--
 1 file changed, 17 insertions(+), 34 deletions(-)

--- 0009/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-15 17:22:27.460607110 +0900
@@ -680,6 +680,10 @@ static int ipmmu_init_platform_device(st
int num_utlbs;
int ret = -ENODEV;
 
+   /* Initialize once - xlate() will call multiple times */
+   if (to_priv(dev))
+   return 0;
+
/* Find the master corresponding to the device. */
 
num_utlbs = of_count_phandle_with_args(dev->of_node, "iommus",
@@ -734,6 +738,12 @@ error:
return ret;
 }
 
+static int ipmmu_of_xlate(struct device *dev,
+ struct of_phandle_args *spec)
+{
+   return ipmmu_init_platform_device(dev);
+}
+
 #if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
 
 static struct iommu_domain *ipmmu_domain_alloc(unsigned type)
@@ -750,11 +760,11 @@ static int ipmmu_add_device(struct devic
struct iommu_group *group;
int ret;
 
-   if (to_priv(dev)) {
-   dev_warn(dev, "IOMMU driver already assigned to device %s\n",
-dev_name(dev));
-   return -EINVAL;
-   }
+   /*
+* Only let through devices that have been verified in xlate()
+*/
+   if (!to_priv(dev))
+   return -ENODEV;
 
/* Create a device group and add the device to it. */
group = iommu_group_alloc();
@@ -773,10 +783,6 @@ static int ipmmu_add_device(struct devic
goto error;
}
 
-   ret = ipmmu_init_platform_device(dev);
-   if (ret < 0)
-   goto error;
-
/*
 * Create the ARM mapping, used by the ARM DMA mapping core to allocate
 * VAs. This will allocate a corresponding IOMMU domain.
@@ -817,24 +823,13 @@ error:
if (!IS_ERR_OR_NULL(group))
iommu_group_remove_device(dev);
 
-   kfree(to_priv(dev)->utlbs);
-   kfree(to_priv(dev));
-   set_priv(dev, NULL);
-
return ret;
 }
 
 static void ipmmu_remove_device(struct device *dev)
 {
-   struct ipmmu_vmsa_iommu_priv *priv = to_priv(dev);
-
arm_iommu_detach_device(dev);
iommu_group_remove_device(dev);
-
-   kfree(priv->utlbs);
-   kfree(priv);
-
-   set_priv(dev, NULL);
 }
 
 static const struct iommu_ops ipmmu_ops = {
@@ -849,6 +844,7 @@ static const struct iommu_ops ipmmu_ops
.add_device = ipmmu_add_device,
.remove_device = ipmmu_remove_device,
.pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K,
+   .of_xlate = ipmmu_of_xlate,
 };
 
 #endif /* !CONFIG_ARM && CONFIG_IOMMU_DMA */
@@ -958,19 +954,6 @@ static struct iommu_group *ipmmu_find_gr
return group;
 }
 
-static int ipmmu_of_xlate_dma(struct device *dev,
- struct of_phandle_args *spec)
-{
-   /* If the IPMMU device is disabled in DT then return error
-* to make sure the of_iommu code does not install ops
-* even though the iommu device is disabled
-*/
-   if (!of_device_is_available(spec->np))
-   return -ENODEV;
-
-   return ipmmu_init_platform_device(dev);
-}
-
 static const struct iommu_ops ipmmu_ops = {
.domain_alloc = ipmmu_domain_alloc_dma,
.domain_free = ipmmu_domain_free_dma,
@@ -984,7 +967,7 @@ static const struct iommu_ops ipmmu_ops
.remove_device = ipmmu_remove_device_dma,
.device_group = ipmmu_find_group_dma,
.pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K,
-   .of_xlate = ipmmu_of_xlate_dma,
+   .of_xlate = ipmmu_of_xlate,
 };
 
 #endif /* CONFIG_IOMMU_DMA */
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 03/04] iommu/ipmmu-vmsa: Use fwspec on both 32 and 64-bit ARM

2017-06-15 Thread Magnus Damm
From: Robin Murphy <robin.mur...@arm.com>

Consolidate the 32-bit and 64-bit code to make use of fwspec instead
of archdata for the 32-bit ARM case.

This is a simplified version of the fwspec handling code from Robin
posted as [PATCH] iommu/ipmmu-vmsa: Convert to iommu_fwspec

Signed-off-by: Robin Murphy <robin.mur...@arm.com>
Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 drivers/iommu/ipmmu-vmsa.c |   21 +++--
 1 file changed, 3 insertions(+), 18 deletions(-)

--- 0010/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-15 17:29:00.290607110 +0900
@@ -73,22 +73,9 @@ static struct ipmmu_vmsa_domain *to_vmsa
return container_of(dom, struct ipmmu_vmsa_domain, io_domain);
 }
 
-
 static struct ipmmu_vmsa_iommu_priv *to_priv(struct device *dev)
 {
-#if defined(CONFIG_ARM)
-   return dev->archdata.iommu;
-#else
-   return dev->iommu_fwspec->iommu_priv;
-#endif
-}
-static void set_priv(struct device *dev, struct ipmmu_vmsa_iommu_priv *p)
-{
-#if defined(CONFIG_ARM)
-   dev->archdata.iommu = p;
-#else
-   dev->iommu_fwspec->iommu_priv = p;
-#endif
+   return dev->iommu_fwspec ? dev->iommu_fwspec->iommu_priv : NULL;
 }
 
 #define TLB_LOOP_TIMEOUT   100 /* 100us */
@@ -730,7 +717,7 @@ static int ipmmu_init_platform_device(st
priv->utlbs = utlbs;
priv->num_utlbs = num_utlbs;
priv->dev = dev;
-   set_priv(dev, priv);
+   dev->iommu_fwspec->iommu_priv = priv;
return 0;
 
 error:
@@ -887,14 +874,12 @@ static void ipmmu_domain_free_dma(struct
 
 static int ipmmu_add_device_dma(struct device *dev)
 {
-   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
struct iommu_group *group;
 
/*
 * Only let through devices that have been verified in xlate()
-* We may get called with dev->iommu_fwspec set to NULL.
 */
-   if (!fwspec || !fwspec->iommu_priv)
+   if (!to_priv(dev))
return -ENODEV;
 
group = iommu_group_get_for_dev(dev);
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 01/04] iommu/ipmmu-vmsa: Use iommu_device_register()/unregister()

2017-06-15 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Extend the driver to make use of iommu_device_register()/unregister()
functions together with iommu_device_set_ops() and iommu_set_fwnode().

These used to be part of the earlier posted 64-bit ARM (r8a7795) series but
it turns out that these days they are required on 32-bit ARM as well.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 drivers/iommu/ipmmu-vmsa.c |   10 ++
 1 file changed, 10 insertions(+)

--- 0001/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-15 16:57:21.890607110 +0900
@@ -35,6 +35,7 @@
 struct ipmmu_vmsa_device {
struct device *dev;
void __iomem *base;
+   struct iommu_device iommu;
struct list_head list;
 
unsigned int num_utlbs;
@@ -1054,6 +1055,13 @@ static int ipmmu_probe(struct platform_d
 
ipmmu_device_reset(mmu);
 
+   ret = iommu_device_register(>iommu);
+   if (ret)
+   return ret;
+
+   iommu_device_set_ops(>iommu, _ops);
+   iommu_device_set_fwnode(>iommu, >dev.of_node->fwnode);
+
/*
 * We can't create the ARM mapping here as it requires the bus to have
 * an IOMMU, which only happens when bus_set_iommu() is called in
@@ -1077,6 +1085,8 @@ static int ipmmu_remove(struct platform_
list_del(>list);
spin_unlock(_devices_lock);
 
+   iommu_device_unregister(>iommu);
+
 #if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
arm_iommu_release_mapping(mmu->mapping);
 #endif
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 00/04] iommu/ipmmu-vmsa: 32-bit ARM update

2017-06-15 Thread Magnus Damm
iommu/ipmmu-vmsa: 32-bit ARM update

[PATCH 01/04] iommu/ipmmu-vmsa: Use iommu_device_register()/unregister()
[PATCH 02/04] iommu/ipmmu-vmsa: Consistent ->of_xlate() handling
[PATCH 03/04] iommu/ipmmu-vmsa: Use fwspec on both 32 and 64-bit ARM
[PATCH 04/04] iommu/ipmmu-vmsa: Replace local utlb code with fwspec ids

This series updates the IPMMU driver to make use of recent IOMMU framework
changes and also improves code sharing in the driver between the 32-bit and
64-bit dma-mapping architecture glue code.

Suggested-by: Robin Murphy <robin.mur...@arm.com> (Patch 2 and 4)
Signed-off-by: Robin Murphy <robin.mur...@arm.com> (Patch 3)
Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Developed on renesas-drivers-2017-06-13-v4.12-rc5 and rebased to next-20170614

 drivers/iommu/ipmmu-vmsa.c |  186 +++-
 1 file changed, 49 insertions(+), 137 deletions(-)
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH/RFC] iommu: Move over to unsigned int domain type

2017-05-17 Thread Magnus Damm
Hi Joerg,

On Wed, May 17, 2017 at 10:18 PM, Joerg Roedel <j...@8bytes.org> wrote:
> On Wed, May 17, 2017 at 07:29:12PM +0900, Magnus Damm wrote:
>> From: Magnus Damm <damm+rene...@opensource.se>
>>
>> Checkpatch dislikes the type unsigned, so update the iommu
>> domain type and consumers to use unsigned int to reduce noise.
>
> And I hate stupid checkpatch warnings and refuse to fix them. This
> clearly is one.

Gotcha, fine by me! Let me know if there is anything more non-cosmetic
in the IOMMU subsystem that you think would be more useful to spend
cycles on.

Cheers,

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


Re: [PATCH v8 06/08] iommu/ipmmu-vmsa: Use fwspec iommu_priv on ARM64

2017-05-17 Thread Magnus Damm
Hi Robin,

On Wed, May 17, 2017 at 11:29 PM, Robin Murphy <robin.mur...@arm.com> wrote:
> Hi Magnus,
>
> On 17/05/17 11:07, Magnus Damm wrote:
>> From: Magnus Damm <damm+rene...@opensource.se>
>>
>> Convert from archdata to iommu_priv via iommu_fwspec on ARM64 but
>> let 32-bit ARM keep on using archdata for now.
>>
>> Once the 32-bit ARM code and the IPMMU driver is able to move over
>> to CONFIG_IOMMU_DMA=y then coverting to fwspec via ->of_xlate() will
>> be easy.
>>
>> For now fwspec ids and num_ids are not used to allow code sharing between
>> 32-bit and 64-bit ARM code inside the driver.
>
> That's not what I meant at all - this just looks like a crazy
> unmaintainable mess that's making things that much harder to unpick in
> future.
>
> Leaving the existing code fossilised and building up half of a second
> separate driver around it wrapped in ifdefs is not only hideous, it's
> more work in the end than simply pulling things into the right shape to
> begin with. What I meant was to start with the below (compile-tested
> only), and add the of_xlate support on top. AFAICS the arm/arm64
> differences overall should only come down to a bit of special-casing in
> add_device(), and (optionally) whether you outright reject
> IOMMU_DOMAIN_DMA or not.
>
> Sorry, but I just can't agree with the two-drivers-in-one approach.

Thanks for checking the code and sorry to disappoint you by not using
->ids[] and ->num_ids right away. The two-drivers-on-one approach
comes from wanting to use the same IOMMU driver on both 32-bit and
64-bit ARM architectures but the former is lacking IOMMU_DMA support
upstream.

Obviously using ->ids[] and ->num_ids is the right forward, and in my
mind it is only a question of time and merge order. I'm more than
happy to make use of your patch but I'm wondering if it will work on
32-bit ARM and R-Car Gen2 that currently does not use ->of_xlate(). I
can see that you're using iommu_fwspec_init() so it might work right
out of the box. Thanks for your help cooking up the patch by the way.

>From my side I was hoping on doing one larger feature jump for 32-bit
ARM by moving over to IOMMU_DMA=y together with ->of_xlate()and fwspec
at the same time. Doing minor increments of the legacy code that is
still using special mapping code instead of OMMU_DMA=y in case of
32-bit ARM just feels like a lot of potential breakage and little gain
to me.

What's the plan for supporting IOMMU_DMA=y on 32-bit ARM? Anything I
can do to help? Or do you prefer minor increments on 32-bit ARM over
larger feature jumps?

Let me know what you think. My plan is to revisit this topic early next week.

Cheers,

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


[PATCH/RFC] iommu: Move over to unsigned int domain type

2017-05-17 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Checkpatch dislikes the type unsigned, so update the iommu
domain type and consumers to use unsigned int to reduce noise.

$ ./scripts/checkpatch.pl 
../linux-v4.13-pre-drivers-iommu-ipmmu-dma-ops-20170517b.patch
WARNING: Prefer 'unsigned int' to bare use of 'unsigned'
#89: FILE: drivers/iommu/ipmmu-vmsa.c:720:
+static struct iommu_domain *ipmmu_domain_alloc(unsigned type)

WARNING: Prefer 'unsigned int' to bare use of 'unsigned'
#111: FILE: drivers/iommu/ipmmu-vmsa.c:844:
+static struct iommu_domain *ipmmu_domain_alloc_dma(unsigned type)

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Untested for now.

 drivers/iommu/amd_iommu.c   |2 +-
 drivers/iommu/arm-smmu-v3.c |2 +-
 drivers/iommu/arm-smmu.c|2 +-
 drivers/iommu/exynos-iommu.c|2 +-
 drivers/iommu/fsl_pamu_domain.c |2 +-
 drivers/iommu/intel-iommu.c |2 +-
 drivers/iommu/iommu.c   |4 ++--
 drivers/iommu/ipmmu-vmsa.c  |2 +-
 drivers/iommu/msm_iommu.c   |2 +-
 drivers/iommu/mtk_iommu.c   |2 +-
 drivers/iommu/mtk_iommu_v1.c|2 +-
 drivers/iommu/omap-iommu.c  |2 +-
 drivers/iommu/rockchip-iommu.c  |2 +-
 drivers/iommu/s390-iommu.c  |2 +-
 drivers/iommu/tegra-gart.c  |2 +-
 drivers/iommu/tegra-smmu.c  |2 +-
 include/linux/iommu.h   |4 ++--
 17 files changed, 19 insertions(+), 19 deletions(-)

--- 0001/drivers/iommu/amd_iommu.c
+++ work/drivers/iommu/amd_iommu.c  2017-05-17 19:19:00.810607110 +0900
@@ -2940,7 +2940,7 @@ out_err:
return NULL;
 }
 
-static struct iommu_domain *amd_iommu_domain_alloc(unsigned type)
+static struct iommu_domain *amd_iommu_domain_alloc(unsigned int type)
 {
struct protection_domain *pdomain;
struct dma_ops_domain *dma_domain;
--- 0001/drivers/iommu/arm-smmu-v3.c
+++ work/drivers/iommu/arm-smmu-v3.c2017-05-17 19:17:18.300607110 +0900
@@ -1381,7 +1381,7 @@ static bool arm_smmu_capable(enum iommu_
}
 }
 
-static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
+static struct iommu_domain *arm_smmu_domain_alloc(unsigned int type)
 {
struct arm_smmu_domain *smmu_domain;
 
--- 0001/drivers/iommu/arm-smmu.c
+++ work/drivers/iommu/arm-smmu.c   2017-05-17 19:17:35.410607110 +0900
@@ -1078,7 +1078,7 @@ static void arm_smmu_destroy_domain_cont
__arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx);
 }
 
-static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
+static struct iommu_domain *arm_smmu_domain_alloc(unsigned int type)
 {
struct arm_smmu_domain *smmu_domain;
 
--- 0001/drivers/iommu/exynos-iommu.c
+++ work/drivers/iommu/exynos-iommu.c   2017-05-17 19:15:55.760607110 +0900
@@ -730,7 +730,7 @@ static inline void update_pte(sysmmu_pte
   DMA_TO_DEVICE);
 }
 
-static struct iommu_domain *exynos_iommu_domain_alloc(unsigned type)
+static struct iommu_domain *exynos_iommu_domain_alloc(unsigned int type)
 {
struct exynos_iommu_domain *domain;
dma_addr_t handle;
--- 0001/drivers/iommu/fsl_pamu_domain.c
+++ work/drivers/iommu/fsl_pamu_domain.c2017-05-17 19:15:19.190607110 
+0900
@@ -416,7 +416,7 @@ static void fsl_pamu_domain_free(struct
kmem_cache_free(fsl_pamu_domain_cache, dma_domain);
 }
 
-static struct iommu_domain *fsl_pamu_domain_alloc(unsigned type)
+static struct iommu_domain *fsl_pamu_domain_alloc(unsigned int type)
 {
struct fsl_dma_domain *dma_domain;
 
--- 0001/drivers/iommu/intel-iommu.c
+++ work/drivers/iommu/intel-iommu.c2017-05-17 19:14:56.520607110 +0900
@@ -5021,7 +5021,7 @@ static int md_domain_init(struct dmar_do
return 0;
 }
 
-static struct iommu_domain *intel_iommu_domain_alloc(unsigned type)
+static struct iommu_domain *intel_iommu_domain_alloc(unsigned int type)
 {
struct dmar_domain *dmar_domain;
struct iommu_domain *domain;
--- 0001/drivers/iommu/iommu.c
+++ work/drivers/iommu/iommu.c  2017-05-17 19:20:48.720607110 +0900
@@ -105,7 +105,7 @@ void iommu_device_unregister(struct iomm
 }
 
 static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus,
-unsigned type);
+unsigned int type);
 static int __iommu_attach_device(struct iommu_domain *domain,
 struct device *dev);
 static int __iommu_attach_group(struct iommu_domain *domain,
@@ -1255,7 +1255,7 @@ void iommu_set_fault_handler(struct iomm
 EXPORT_SYMBOL_GPL(iommu_set_fault_handler);
 
 static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus,
-unsigned type)
+unsigned int type)
 {
struct iommu_domain *domain;
 
--- 0001/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-05-17 19:13:42.3106071

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

2017-05-17 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

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 <damm+rene...@opensource.se>
Acked-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
Reviewed-by: Joerg Roedel <jroe...@suse.de>
---

 Changes since V7:
 - None

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

--- 0010/drivers/iommu/Kconfig
+++ work/drivers/iommu/Kconfig  2017-05-17 16:45:15.530607110 +0900
@@ -275,7 +275,6 @@ config EXYNOS_IOMMU_DEBUG
 config IPMMU_VMSA
bool "Renesas VMSA-compatible IPMMU"
depends on ARM || IOMMU_DMA
-   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 v8 08/08] iommu/ipmmu-vmsa: Fix pgsize_bitmap semicolon typo

2017-05-17 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Fix comma-instead-of-semicolon typo error present
in the latest version of the IPMMU driver.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Earlier posted as:
 [PATCH] iommu/ipmmu-vmsa: Fix pgsize_bitmap semicolon typo

 drivers/iommu/ipmmu-vmsa.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- 0014/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-05-17 16:50:02.850607110 +0900
@@ -358,7 +358,7 @@ static int ipmmu_domain_init_context(str
 * non-secure mode.
 */
domain->cfg.quirks = IO_PGTABLE_QUIRK_ARM_NS;
-   domain->cfg.pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K,
+   domain->cfg.pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K;
domain->cfg.ias = 32;
domain->cfg.oas = 40;
domain->cfg.tlb = _gather_ops;
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v8 06/08] iommu/ipmmu-vmsa: Use fwspec iommu_priv on ARM64

2017-05-17 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Convert from archdata to iommu_priv via iommu_fwspec on ARM64 but
let 32-bit ARM keep on using archdata for now.

Once the 32-bit ARM code and the IPMMU driver is able to move over
to CONFIG_IOMMU_DMA=y then coverting to fwspec via ->of_xlate() will
be easy.

For now fwspec ids and num_ids are not used to allow code sharing between
32-bit and 64-bit ARM code inside the driver.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V7:
 - Rewrote code to use iommu_fwspec, thanks Robin!
 - Dropped reviewed-by from Joerg, also skipped tag from Geert

 drivers/iommu/ipmmu-vmsa.c |   97 ++--
 1 file changed, 58 insertions(+), 39 deletions(-)

--- 0011/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-05-17 16:45:07.510607110 +0900
@@ -56,7 +56,7 @@ struct ipmmu_vmsa_domain {
spinlock_t lock;/* Protects mappings */
 };
 
-struct ipmmu_vmsa_archdata {
+struct ipmmu_vmsa_iommu_priv {
struct ipmmu_vmsa_device *mmu;
unsigned int *utlbs;
unsigned int num_utlbs;
@@ -72,6 +72,24 @@ static struct ipmmu_vmsa_domain *to_vmsa
return container_of(dom, struct ipmmu_vmsa_domain, io_domain);
 }
 
+
+static struct ipmmu_vmsa_iommu_priv *to_priv(struct device *dev)
+{
+#if defined(CONFIG_ARM)
+   return dev->archdata.iommu;
+#else
+   return dev->iommu_fwspec->iommu_priv;
+#endif
+}
+static void set_priv(struct device *dev, struct ipmmu_vmsa_iommu_priv *p)
+{
+#if defined(CONFIG_ARM)
+   dev->archdata.iommu = p;
+#else
+   dev->iommu_fwspec->iommu_priv = p;
+#endif
+}
+
 #define TLB_LOOP_TIMEOUT   100 /* 100us */
 
 /* 
-
@@ -543,8 +561,8 @@ static void ipmmu_domain_free(struct iom
 static int ipmmu_attach_device(struct iommu_domain *io_domain,
   struct device *dev)
 {
-   struct ipmmu_vmsa_archdata *archdata = dev->archdata.iommu;
-   struct ipmmu_vmsa_device *mmu = archdata->mmu;
+   struct ipmmu_vmsa_iommu_priv *priv = to_priv(dev);
+   struct ipmmu_vmsa_device *mmu = priv->mmu;
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
unsigned long flags;
unsigned int i;
@@ -577,8 +595,8 @@ static int ipmmu_attach_device(struct io
if (ret < 0)
return ret;
 
-   for (i = 0; i < archdata->num_utlbs; ++i)
-   ipmmu_utlb_enable(domain, archdata->utlbs[i]);
+   for (i = 0; i < priv->num_utlbs; ++i)
+   ipmmu_utlb_enable(domain, priv->utlbs[i]);
 
return 0;
 }
@@ -586,12 +604,12 @@ static int ipmmu_attach_device(struct io
 static void ipmmu_detach_device(struct iommu_domain *io_domain,
struct device *dev)
 {
-   struct ipmmu_vmsa_archdata *archdata = dev->archdata.iommu;
+   struct ipmmu_vmsa_iommu_priv *priv = to_priv(dev);
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
unsigned int i;
 
-   for (i = 0; i < archdata->num_utlbs; ++i)
-   ipmmu_utlb_disable(domain, archdata->utlbs[i]);
+   for (i = 0; i < priv->num_utlbs; ++i)
+   ipmmu_utlb_disable(domain, priv->utlbs[i]);
 
/*
 * TODO: Optimize by disabling the context when no device is attached.
@@ -654,7 +672,7 @@ static int ipmmu_find_utlbs(struct ipmmu
 
 static int ipmmu_init_platform_device(struct device *dev)
 {
-   struct ipmmu_vmsa_archdata *archdata;
+   struct ipmmu_vmsa_iommu_priv *priv;
struct ipmmu_vmsa_device *mmu;
unsigned int *utlbs;
unsigned int i;
@@ -697,17 +715,17 @@ static int ipmmu_init_platform_device(st
}
}
 
-   archdata = kzalloc(sizeof(*archdata), GFP_KERNEL);
-   if (!archdata) {
+   priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+   if (!priv) {
ret = -ENOMEM;
goto error;
}
 
-   archdata->mmu = mmu;
-   archdata->utlbs = utlbs;
-   archdata->num_utlbs = num_utlbs;
-   archdata->dev = dev;
-   dev->archdata.iommu = archdata;
+   priv->mmu = mmu;
+   priv->utlbs = utlbs;
+   priv->num_utlbs = num_utlbs;
+   priv->dev = dev;
+   set_priv(dev, priv);
return 0;
 
 error:
@@ -727,12 +745,11 @@ static struct iommu_domain *ipmmu_domain
 
 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) {
+   if (to_priv(dev)) {
dev_warn(dev, "IOMMU driver already assigned to device %s\n",
 dev_name(dev));
retur

[PATCH v8 04/08] iommu/ipmmu-vmsa: Break out domain allocation code

2017-05-17 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Break out the domain allocation code into a separate function.

This is preparation for future code sharing.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
Reviewed-by: Joerg Roedel <jroe...@suse.de>
Reviewed-by: Geert Uytterhoeven <geert+rene...@glider.be>
---

 Changes since V7:
 - Added Reviewed-by from Geert - Thanks!

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

--- 0006/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-05-17 16:39:05.380607110 +0900
@@ -509,13 +509,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;
@@ -525,6 +522,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


[PATCH v8 01/08] iommu/ipmmu-vmsa: Remove platform data handling

2017-05-17 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

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 <damm+rene...@opensource.se>
Reviewed-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
Reviewed-by: Joerg Roedel <jroe...@suse.de>
Reviewed-by: Geert Uytterhoeven <geert+rene...@glider.be>
---

 Changes since V7:
 - Added Reviewed-by from Geert - Thanks!

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

--- 0001/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-05-17 16:30:57.620607110 +0900
@@ -768,11 +768,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 v8 00/08] iommu/ipmmu-vmsa: IPMMU multi-arch update V8

2017-05-17 Thread Magnus Damm
iommu/ipmmu-vmsa: IPMMU multi-arch update V8

[PATCH v8 01/08] iommu/ipmmu-vmsa: Remove platform data handling
[PATCH v8 02/08] iommu/ipmmu-vmsa: Rework interrupt code and use bitmap for 
context
[PATCH v8 03/08] iommu/ipmmu-vmsa: Break out utlb parsing code
[PATCH v8 04/08] iommu/ipmmu-vmsa: Break out domain allocation code
[PATCH v8 05/08] iommu/ipmmu-vmsa: Add new IOMMU_DOMAIN_DMA ops
[PATCH v8 06/08] iommu/ipmmu-vmsa: Use fwspec iommu_priv on ARM64
[PATCH v8 07/08] iommu/ipmmu-vmsa: Drop LPAE Kconfig dependency
[PATCH v8 08/08] iommu/ipmmu-vmsa: Fix pgsize_bitmap semicolon typo

These patches update the IPMMU driver with a modifications to support
build on multiple architectures. In the process of doing so the interrupt
code gets reworked, the foundation for supporting multiple contexts are
added and in case of CONFIG_IOMMU_DMA=y (on 64-bit or 32-bit ARM) devices
are grouped together and handled via ->xlate(). In this verison fwspec is
used on 64-bit ARM instead of archdata. Support for existing 32-bit ARM
SoCs from R-Car Gen2 is kept as-is.

Changes since V7:
 - Rebased on top of v4.12-rc1
 - Added Reviewed-by from Geert to patch 1/8 and 4/8, thanks!
 - Reworked patch 6/8 to use fwspec, thanks Robin!
 - Added patch 8/8

Changes since V6:
 - Rebased on top of v4.11-rc1 and the following fast-tracked change:
   3b6bb5b iommu/ipmmu-vmsa: Restrict IOMMU Domain Geometry to 32-bit address 
spac
 - Updated patch 5/7 to roll in a few patches from other series
   See individual patch for more details
 - Build tested on 32-bit and 64-bit ARM
 - Run time tested on 64-bit ARM (with additional SoC-specific patches)

Changes since V5:
 - Rebased series on top of next-20161019
 - Updated patch 5/7 to simplify domain allocation/free code - thanks Joerg!
 - Added reviewed-by tag from Joerg for patch 1-4 and 6-7.
 
Changes since V4:
 - Updated patch 3/7 to work on top on the following commit in next-20160920:
   b1e2afc iommu/ipmmu-vmsa: Fix wrong error handle of ipmmu_add_device
 - Add Kconfig hunk to patch 5/7 to avoid undeclared ipmmu_ops if COMPILE_TEST
 - Rebased patch 7/7 to fit on top of new Kconfig bits in 5/7

Changes since V3:
 - Updated patch 3/7 to fix hang-on-boot issue on 32-bit ARM - thanks Geert!
 - Reworked group parameter handling in patch 3/7 and 5/7.
 - Added patch 6/7 to fix build of the driver on s390/tile/um architectures

Changes since V2:
 - Got rid of patch 3 from the V2 however patch 1, 2 and 4 are kept.
 - V3 patch 3, 4 and 5 come from
   [PATCH 00/04] iommu/ipmmu-vmsa: IPMMU CONFIG_IOMMU_DMA update
 - Patch 5 has been reworked to include patch 3 of the V1 of this series 

Changes since V1:
 - Got rid of patch 2 and 3 from initial series
 - Updated bitmap code locking and also used lighter bitop functions
 - Updated the Kconfig bits to apply on top of ARCH_RENESAS

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Developed on top of a95cfad (v4.12-rc1 + fixes):

 Compile tested on 32-bit and 64-bit ARM

 Run time tested on 64-bit ARM r8a7796 Salvator-X

 drivers/iommu/Kconfig  |2 
 drivers/iommu/ipmmu-vmsa.c |  421 ++--
 2 files changed, 331 insertions(+), 92 deletions(-)
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v8 02/08] iommu/ipmmu-vmsa: Rework interrupt code and use bitmap for context

2017-05-17 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Introduce a bitmap for context handing and convert the
interrupt routine to handle all registered contexts.

At this point the number of contexts are still limited.

Also remove the use of the ARM specific mapping variable
from ipmmu_irq() to allow compile on ARM64.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
Reviewed-by: Joerg Roedel <jroe...@suse.de>
---

 Changes since V7:
 - None

 drivers/iommu/ipmmu-vmsa.c |   76 ++--
 1 file changed, 66 insertions(+), 10 deletions(-)

--- 0002/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-05-17 16:33:02.380607110 +0900
@@ -8,6 +8,7 @@
  * the Free Software Foundation; version 2 of the License.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -26,12 +27,17 @@
 
 #include "io-pgtable.h"
 
+#define IPMMU_CTX_MAX 1
+
 struct ipmmu_vmsa_device {
struct device *dev;
void __iomem *base;
struct list_head list;
 
unsigned int num_utlbs;
+   spinlock_t lock;/* Protects ctx and domains[] */
+   DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
+   struct ipmmu_vmsa_domain *domains[IPMMU_CTX_MAX];
 
struct dma_iommu_mapping *mapping;
 };
@@ -293,9 +299,29 @@ static struct iommu_gather_ops ipmmu_gat
  * Domain/Context Management
  */
 
+static int ipmmu_domain_allocate_context(struct ipmmu_vmsa_device *mmu,
+struct ipmmu_vmsa_domain *domain)
+{
+   unsigned long flags;
+   int ret;
+
+   spin_lock_irqsave(>lock, flags);
+
+   ret = find_first_zero_bit(mmu->ctx, IPMMU_CTX_MAX);
+   if (ret != IPMMU_CTX_MAX) {
+   mmu->domains[ret] = domain;
+   set_bit(ret, mmu->ctx);
+   }
+
+   spin_unlock_irqrestore(>lock, flags);
+
+   return ret;
+}
+
 static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain)
 {
u64 ttbr;
+   int ret;
 
/*
 * Allocate the page table operations.
@@ -327,10 +353,15 @@ static int ipmmu_domain_init_context(str
return -EINVAL;
 
/*
-* TODO: When adding support for multiple contexts, find an unused
-* context.
+* Find an unused context.
 */
-   domain->context_id = 0;
+   ret = ipmmu_domain_allocate_context(domain->mmu, domain);
+   if (ret == IPMMU_CTX_MAX) {
+   free_io_pgtable_ops(domain->iop);
+   return -EBUSY;
+   }
+
+   domain->context_id = ret;
 
/* TTBR0 */
ttbr = domain->cfg.arm_lpae_s1_cfg.ttbr[0];
@@ -372,6 +403,19 @@ static int ipmmu_domain_init_context(str
return 0;
 }
 
+static void ipmmu_domain_free_context(struct ipmmu_vmsa_device *mmu,
+ unsigned int context_id)
+{
+   unsigned long flags;
+
+   spin_lock_irqsave(>lock, flags);
+
+   clear_bit(context_id, mmu->ctx);
+   mmu->domains[context_id] = NULL;
+
+   spin_unlock_irqrestore(>lock, flags);
+}
+
 static void ipmmu_domain_destroy_context(struct ipmmu_vmsa_domain *domain)
 {
/*
@@ -382,6 +426,7 @@ static void ipmmu_domain_destroy_context
 */
ipmmu_ctx_write(domain, IMCTR, IMCTR_FLUSH);
ipmmu_tlb_sync(domain);
+   ipmmu_domain_free_context(domain->mmu, domain->context_id);
 }
 
 /* 
-
@@ -439,16 +484,25 @@ static irqreturn_t ipmmu_domain_irq(stru
 static irqreturn_t ipmmu_irq(int irq, void *dev)
 {
struct ipmmu_vmsa_device *mmu = dev;
-   struct iommu_domain *io_domain;
-   struct ipmmu_vmsa_domain *domain;
+   irqreturn_t status = IRQ_NONE;
+   unsigned int i;
+   unsigned long flags;
 
-   if (!mmu->mapping)
-   return IRQ_NONE;
+   spin_lock_irqsave(>lock, flags);
+
+   /*
+* Check interrupts for all active contexts.
+*/
+   for (i = 0; i < IPMMU_CTX_MAX; i++) {
+   if (!mmu->domains[i])
+   continue;
+   if (ipmmu_domain_irq(mmu->domains[i]) == IRQ_HANDLED)
+   status = IRQ_HANDLED;
+   }
 
-   io_domain = mmu->mapping->domain;
-   domain = to_vmsa_domain(io_domain);
+   spin_unlock_irqrestore(>lock, flags);
 
-   return ipmmu_domain_irq(domain);
+   return status;
 }
 
 /* 
-
@@ -776,6 +830,8 @@ static int ipmmu_probe(struct platform_d
 
mmu->dev = >dev;
mmu->num_utlbs = 32;
+   spin_lock_init(>lock);
+   bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
 
/* Map I/O memory and request IRQ. */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v8 05/08] iommu/ipmmu-vmsa: Add new IOMMU_DOMAIN_DMA ops

2017-05-17 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Introduce an alternative set of iommu_ops suitable for 64-bit ARM
as well as 32-bit ARM when CONFIG_IOMMU_DMA=y. Also adjust the
Kconfig to depend on ARM or IOMMU_DMA. Initialize the device
from ->xlate() when CONFIG_IOMMU_DMA=y.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V7:
 - None

 drivers/iommu/Kconfig  |1 
 drivers/iommu/ipmmu-vmsa.c |  164 +---
 2 files changed, 156 insertions(+), 9 deletions(-)

--- 0001/drivers/iommu/Kconfig
+++ work/drivers/iommu/Kconfig  2017-05-17 16:41:43.030607110 +0900
@@ -274,6 +274,7 @@ config EXYNOS_IOMMU_DEBUG
 
 config IPMMU_VMSA
bool "Renesas VMSA-compatible IPMMU"
+   depends on ARM || IOMMU_DMA
depends on ARM_LPAE
depends on ARCH_RENESAS || COMPILE_TEST
select IOMMU_API
--- 0009/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-05-17 16:42:02.730607110 +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"
 
@@ -57,6 +60,8 @@ struct ipmmu_vmsa_archdata {
struct ipmmu_vmsa_device *mmu;
unsigned int *utlbs;
unsigned int num_utlbs;
+   struct device *dev;
+   struct list_head list;
 };
 
 static DEFINE_SPINLOCK(ipmmu_devices_lock);
@@ -522,14 +527,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);
@@ -572,7 +569,8 @@ static int ipmmu_attach_device(struct io
dev_err(dev, "Can't attach IPMMU %s to domain on IPMMU %s\n",
dev_name(mmu->dev), dev_name(domain->mmu->dev));
ret = -EINVAL;
-   }
+   } else
+   dev_info(dev, "Reusing IPMMU context %u\n", domain->context_id);
 
spin_unlock_irqrestore(>lock, flags);
 
@@ -708,6 +706,7 @@ static int ipmmu_init_platform_device(st
archdata->mmu = mmu;
archdata->utlbs = utlbs;
archdata->num_utlbs = num_utlbs;
+   archdata->dev = dev;
dev->archdata.iommu = archdata;
return 0;
 
@@ -716,6 +715,16 @@ error:
return ret;
 }
 
+#if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
+
+static struct iommu_domain *ipmmu_domain_alloc(unsigned type)
+{
+   if (type != IOMMU_DOMAIN_UNMANAGED)
+   return NULL;
+
+   return __ipmmu_domain_alloc(type);
+}
+
 static int ipmmu_add_device(struct device *dev)
 {
struct ipmmu_vmsa_archdata *archdata;
@@ -825,6 +834,141 @@ 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 DEFINE_SPINLOCK(ipmmu_slave_devices_lock);
+static LIST_HEAD(ipmmu_slave_devices);
+
+static struct iommu_domain *ipmmu_domain_alloc_dma(unsigned type)
+{
+   struct iommu_domain *io_domain = NULL;
+
+   switch (type) {
+   case IOMMU_DOMAIN_UNMANAGED:
+   io_domain = __ipmmu_domain_alloc(type);
+   break;
+
+   case IOMMU_DOMAIN_DMA:
+   io_domain = __ipmmu_domain_alloc(type);
+   if (io_domain)
+   iommu_get_dma_cookie(io_domain);
+   break;
+   }
+
+   return io_domain;
+}
+
+static void ipmmu_domain_free_dma(struct iommu_domain *io_domain)
+{
+   switch (io_domain->type) {
+   case IOMMU_DOMAIN_DMA:
+   iommu_put_dma_cookie(io_domain);
+   /* fall-through */
+   default:
+   ipmmu_domain_free(io_domain);
+   break;
+   }
+}
+
+static int ipmmu_add_device_dma(struct device *dev)
+{
+   struct ipmmu_vmsa_archdata *archdata = dev->archdata.iommu;
+   struct iommu_group *group;
+
+   /* The device has been verified in xlate() */
+   if (!archdata)
+   return -ENODEV;
+
+   group = iommu_group_get_for_dev(dev);
+   if (IS_ERR(group))
+   return PTR_ERR(group);
+
+   spin_lock(_slave_devices_lock);
+   list_add(>list, _slave_devices);
+   spin_unlock(_slave_devices_lock);
+   return 0;
+}
+
+static void ipmmu_remove_device_dma(struct device *dev)
+{
+   struct ipmmu_vmsa_archdata *archdata = dev->archdata.iommu;
+
+   spin_lock(_slave_devices_lock);
+   list_del(>list);
+   spin_unlock(_slave_devices_lock);
+
+   iommu_group_remo

[PATCH v8 03/08] iommu/ipmmu-vmsa: Break out utlb parsing code

2017-05-17 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

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 <damm+rene...@opensource.se>
Reviewed-by: Joerg Roedel <jroe...@suse.de>
---

 Changes since V7:
 - Free archdata and utlbs in case of error

 drivers/iommu/ipmmu-vmsa.c |   64 
 1 file changed, 41 insertions(+), 23 deletions(-)

--- 0004/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-05-17 16:37:29.080607110 +0900
@@ -649,22 +649,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",
@@ -701,6 +694,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)) {
@@ -718,16 +741,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
@@ -738,6 +754,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;
 
@@ -762,16 +780,16 @@ static int ipmmu_add_device(struct devic
return 0;
 
 error:
-   arm_iommu_release_mapping(mmu->mapping);
-
-   kfree(dev->archdata.iommu);
-   kfree(utlbs);
-
-   dev->archdata.iommu = NULL;
+   if (mmu)
+   arm_iommu_release_mapping(mmu->mapping);
 
if (!IS_ERR_OR_NULL(group))
iommu_group_remove_device(dev);
 
+   kfree(archdata->utlbs);
+   kfree(archdata);
+   dev->archdata.iommu = NULL;
+
return ret;
 }
 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH V8 07/11] iommu: of: Handle IOMMU lookup failure with deferred probing or error

2017-05-17 Thread Magnus Damm
Hi Geert, everyone,

On Fri, May 5, 2017 at 10:23 PM, Geert Uytterhoeven
 wrote:
> Hi Sricharan, Robin,
>
> On Wed, May 3, 2017 at 12:24 PM, Sricharan R  wrote:
>> On 5/3/2017 3:24 PM, Robin Murphy wrote:
>>> On 02/05/17 19:35, Geert Uytterhoeven wrote:
 On Fri, Feb 3, 2017 at 4:48 PM, Sricharan R  
 wrote:
> From: Laurent Pinchart 
>
> Failures to look up an IOMMU when parsing the DT iommus property need to
> be handled separately from the .of_xlate() failures to support deferred
> probing.
>
> The lack of a registered IOMMU can be caused by the lack of a driver for
> the IOMMU, the IOMMU device probe not having been performed yet, having
> been deferred, or having failed.
>
> The first case occurs when the device tree describes the bus master and
> IOMMU topology correctly but no device driver exists for the IOMMU yet
> or the device driver has not been compiled in. Return NULL, the caller
> will configure the device without an IOMMU.
>
> The second and third cases are handled by deferring the probe of the bus
> master device which will eventually get reprobed after the IOMMU.
>
> The last case is currently handled by deferring the probe of the bus
> master device as well. A mechanism to either configure the bus master
> device without an IOMMU or to fail the bus master device probe depending
> on whether the IOMMU is optional or mandatory would be a good
> enhancement.
>
> Tested-by: Marek Szyprowski 
> Signed-off-by: Laurent Pichart 
> Signed-off-by: Sricharan R 

 This patch broke Renesas R-Car Gen3 platforms in renesas-drivers.
 As the IOMMU nodes in DT are not yet enabled, all devices having iommus
 properties in DT now fail to probe.
>>>
>>> How exactly do they fail to probe? Per d7b0558230e4, if there are no ops
>>> registered then they should merely defer until we reach the point of
>>> giving up and ignoring the IOMMU. Is it just that you have no other
>>> late-probing drivers or post-init module loads to kick the deferred
>>> queue after that point? I did try to find a way to explicitly kick it
>>> from a suitably late initcall, but there didn't seem to be any obvious
>>> public interface - anyone have any suggestions?
>>>
>>> I think that's more of a general problem with the probe deferral
>>> mechanism itself (I've seen the same thing happen with some of the
>>> CoreSight stuff on Juno due to the number of inter-component
>>> dependencies) rather than any specific fault of this series.
>
> I had a deeper look into the issue.
>
> What changed, is that of_dma_configure() now returns an error code,
> and dma_configure() looks at it.
>
> Actually there are two failure modes:
>   1. Devices with an iommus property pointing to a disabled IOMMU node.
>  These return -EPROBE_DEFER, and are now retried forever.
>   2. Devices that are blacklisted in the IPMMU driver, as we don't want to
>  use them with an IOMMU yet.
>  These return -ENODEV, due to ipmmu_of_xlate_dma().
>
>> I was thinking of an additional check like below to avoid the
>> situation ?
>>
>> From 499b6e662f60f23740b8880882b0a16f16434501 Mon Sep 17 00:00:00 2001
>> From: Sricharan R 
>> Date: Wed, 3 May 2017 13:16:59 +0530
>> Subject: [PATCH] iommu: of: Fix check for returning EPROBE_DEFER
>>
>> While returning EPROBE_DEFER for iommu masters
>> take in to account of iommu nodes that could be
>> marked in DT as 'status=disabled', in which case
>> simply return NULL and let the master's probe
>> continue rather than deferring.
>>
>> Signed-off-by: Sricharan R 
>> ---
>>  drivers/iommu/of_iommu.c | 1 +
>>  1 file changed, 1 insertion(+)
>>
>> diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
>> index 9f44ee8..e6e9bec 100644
>> --- a/drivers/iommu/of_iommu.c
>> +++ b/drivers/iommu/of_iommu.c
>> @@ -118,6 +118,7 @@ static bool of_iommu_driver_present(struct device_node 
>> *np)
>>
>> ops = iommu_ops_from_fwnode(fwnode);
>> if ((ops && !ops->of_xlate) ||
>> +   !of_device_is_available(iommu_spec->np) ||
>> (!ops && !of_iommu_driver_present(iommu_spec->np)))
>> return NULL;
>
> Thanks, this fixes the first class of failures.
>
> The second class can be worked around using:
>
> --- a/drivers/iommu/of_iommu.c
> +++ b/drivers/iommu/of_iommu.c
> @@ -196,6 +196,11 @@ static const struct iommu_ops
> ops = of_iommu_xlate(dev, _spec);
> of_node_put(iommu_spec.np);
> idx++;
> +   if (PTR_ERR(ops) == -ENODEV) {
> +   dev_info(dev, "%s: Ignoring -ENODEV => NULL\n",
> +__func__);

[PATCH] iommu/ipmmu-vmsa: Fix pgsize_bitmap semicolon typo

2017-04-20 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Fix comman-instead-of-semicolon typo error present
in the latest version of the IPMMU driver.

Will in the future be rolled into next driver update.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Applies on top of renesas-drivers-2017-04-18-v4.11-rc7 or -next plus:
 [PATCH v7 00/07] iommu/ipmmu-vmsa: IPMMU multi-arch update V7
 [PATCH v3 00/09] iommu/ipmmu-vmsa: r8a7795 support V3
 [PATCH v3 0/3] iommu/ipmmu-vmsa: r8a7796 support V3

 drivers/iommu/ipmmu-vmsa.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- 0001/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-04-20 22:30:07.000607110 +0900
@@ -431,7 +431,7 @@ static int ipmmu_domain_init_context(str
 * non-secure mode.
 */
domain->cfg.quirks = IO_PGTABLE_QUIRK_ARM_NS;
-   domain->cfg.pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K,
+   domain->cfg.pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K;
domain->cfg.ias = 32;
domain->cfg.oas = 40;
domain->cfg.tlb = _gather_ops;
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 2/3] iommu/ipmmu-vmsa: Increase maximum micro-TLBS to 48

2017-03-11 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Bump up the maximum numbers of micro-TLBS to 48.

Each IPMMU device instance get micro-TLB assignment via
the "iommus" property in DT. Older SoCs tend to use a
maximum number of 32 micro-TLBs per IPMMU instance however
newer SoCs such as r8a7796 make use of up to 48 micro-TLBs.

At this point no SoC specific handling is done to validate
the maximum number of micro-TLBs, and because of that the
DT information is assumed to be within correct range for
each particular SoC.

If needed in the future SoC specific feature flags can be
added to handle the maximum number of micro-TLBs without
requiring DT changes, however at this point this does not
seem necessary.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
Reviewed-by: Geert Uytterhoeven <geert+rene...@glider.be>
---

 Changes since V2:
 - Added outer set of () to IMUASID() and IMUCTR() - thanks Ramesh!
 - Added Reviewed-by from Geert - thanks!

 Changes since V1:
 - Added support for the second I/O range at 0x600.

 drivers/iommu/ipmmu-vmsa.c |   10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

--- 0020/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-12 14:11:23.020607110 +0900
@@ -213,7 +213,9 @@ static void set_archdata(struct device *
 #define IMPMBA(n)  (0x0280 + ((n) * 4))
 #define IMPMBD(n)  (0x02c0 + ((n) * 4))
 
-#define IMUCTR(n)  (0x0300 + ((n) * 16))
+#define IMUCTR(n)  ((n) < 32 ? IMUCTR0(n) : IMUCTR32(n))
+#define IMUCTR0(n) (0x0300 + ((n) * 16))
+#define IMUCTR32(n)(0x0600 + (((n) - 32) * 16))
 #define IMUCTR_FIXADDEN(1 << 31)
 #define IMUCTR_FIXADD_MASK (0xff << 16)
 #define IMUCTR_FIXADD_SHIFT16
@@ -223,7 +225,9 @@ static void set_archdata(struct device *
 #define IMUCTR_FLUSH   (1 << 1)
 #define IMUCTR_MMUEN   (1 << 0)
 
-#define IMUASID(n) (0x0308 + ((n) * 16))
+#define IMUASID(n) ((n) < 32 ? IMUASID0(n) : IMUASID32(n))
+#define IMUASID0(n)(0x0308 + ((n) * 16))
+#define IMUASID32(n)   (0x0608 + (((n) - 32) * 16))
 #define IMUASID_ASID8_MASK (0xff << 8)
 #define IMUASID_ASID8_SHIFT8
 #define IMUASID_ASID0_MASK (0xff << 0)
@@ -1164,7 +1168,7 @@ static int ipmmu_probe(struct platform_d
}
 
mmu->dev = >dev;
-   mmu->num_utlbs = 32;
+   mmu->num_utlbs = 48;
spin_lock_init(>lock);
bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
mmu->features = match->data;
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


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

2017-03-11 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

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 <damm+rene...@opensource.se>
---

 Changes since V2:
 - Updated to include white list suppport

 Changes since V1:
 - None

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

--- 0024/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-12 14:14:32.550607110 +0900
@@ -1058,8 +1058,9 @@ static bool ipmmu_slave_whitelist(struct
return false;
 }
 
-static const struct soc_device_attribute soc_r8a7795[] = {
+static const struct soc_device_attribute soc_rcar_gen3[] = {
{ .soc_id = "r8a7795", },
+   { .soc_id = "r8a7796", },
{ /* sentinel */ }
 };
 
@@ -1082,7 +1083,7 @@ static int ipmmu_of_xlate_dma(struct dev
}
 
/* For R-Car Gen3 use a white list to opt-in slave devices */
-   if (soc_device_match(soc_r8a7795) && !ipmmu_slave_whitelist(dev))
+   if (soc_device_match(soc_rcar_gen3) && !ipmmu_slave_whitelist(dev))
return -ENODEV;
 
return ipmmu_init_platform_device(dev);
@@ -1127,7 +1128,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,
@@ -1141,7 +1142,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 */
},
@@ -1333,6 +1337,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);
 #endif
 
 MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU");
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 0/3] iommu/ipmmu-vmsa: r8a7796 support V3

2017-03-11 Thread Magnus Damm
iommu/ipmmu-vmsa: r8a7796 support V3

[PATCH v3 1/3] iommu/ipmmu-vmsa: Add r8a7796 DT binding
[PATCH v3 2/3] iommu/ipmmu-vmsa: Increase maximum micro-TLBS to 48
[PATCH v3 3/3] iommu/ipmmu-vmsa: Hook up r8a7796 DT matching code

This series adds r8a7796 support to the IPMMU driver. The DT binding
gets updated, maximum number of micro-TLBs are increased and the
driver is adjusted to match on the new DT binding.

Changes since V2:
 - Patch 2/3 updated with an outer set of () - thanks Ramesh!
 - Patch 2/3 updated with Reviewed-by - thanks Geert!
 - Patch 3/3 updated to include white list support

Changes since V1:
 - Patch 1/3 updated with more Acked-by tags
 - Patch 2/3 updated with high I/O register range support

Patch 1/3 is ready for upstream merge and includes the following tags:
Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
Acked-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
Acked-by: Rob Herring <r...@kernel.org>
Acked-by: Simon Horman <horms+rene...@verge.net.au>
Acked-by: Geert Uytterhoeven <geert+rene...@glider.be>

Patch 2/3 and 3/3 are quite trivial but have now acked-by so far.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Developed on top of v4.11-rc1 with the following series applied:
 [PATCH v7 00/07] iommu/ipmmu-vmsa: IPMMU multi-arch update V7
 [PATCH v3 00/09] iommu/ipmmu-vmsa: r8a7795 support V3

 Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt |1 
 drivers/iommu/ipmmu-vmsa.c |   24 
+++---
 2 files changed, 18 insertions(+), 7 deletions(-)
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 1/3] iommu/ipmmu-vmsa: Add r8a7796 DT binding

2017-03-11 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Update the IPMMU DT binding documentation to include the r8a7796 compat
string for R-Car M3-W.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
Acked-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
Acked-by: Rob Herring <r...@kernel.org>
Acked-by: Simon Horman <horms+rene...@verge.net.au>
Acked-by: Geert Uytterhoeven <geert+rene...@glider.be>
---

 Changes since V2:
 - None

 Changes since V1:
 - Included in series, added Acked-by from Geert - thanks!

 Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt |1 +
 1 file changed, 1 insertion(+)

--- 0001/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt
+++ work/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt 
2017-03-12 14:09:01.920607110 +0900
@@ -16,6 +16,7 @@ Required Properties:
 - "renesas,ipmmu-r8a7793" for the R8A7793 (R-Car M2-N) IPMMU.
 - "renesas,ipmmu-r8a7794" for the R8A7794 (R-Car E2) IPMMU.
 - "renesas,ipmmu-r8a7795" for the R8A7795 (R-Car H3) IPMMU.
+- "renesas,ipmmu-r8a7796" for the R8A7796 (R-Car M3-W) IPMMU.
 - "renesas,ipmmu-vmsa" for generic R-Car Gen2 VMSA-compatible IPMMU.
 
   - reg: Base address and size of the IPMMU registers.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v3 02/09] iommu/ipmmu-vmsa: Add optional root device feature

2017-03-08 Thread Magnus Damm
Hi Geert,

On Wed, Mar 8, 2017 at 10:47 PM, Geert Uytterhoeven
<ge...@linux-m68k.org> wrote:
> Hi Magnus,
>
> On Wed, Mar 8, 2017 at 12:01 PM, Magnus Damm <magnus.d...@gmail.com> wrote:
>> From: Magnus Damm <damm+rene...@opensource.se>
>>
>> Add root device handling to the IPMMU driver by allowing certain
>> DT compat strings to enable has_cache_leaf_nodes that in turn will
>> support both root devices with interrupts and leaf devices that
>> face the actual IPMMU consumer devices.
>>
>> Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
>
>> --- 0011/drivers/iommu/ipmmu-vmsa.c
>> +++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-08 17:56:51.770607110 +0900
>
>> @@ -216,6 +219,44 @@ static void set_archdata(struct device *
>>  #define IMUASID_ASID0_SHIFT0
>>
>>  /* 
>> -
>> + * Root device handling
>> + */
>> +
>> +static bool ipmmu_is_root(struct ipmmu_vmsa_device *mmu)
>> +{
>> +   if (mmu->features->has_cache_leaf_nodes)
>> +   return mmu->is_leaf ? false : true;
>
> Expressions using the ternary operator are sometimes hard to read.
> In this case, you want negation, so why not use that?
>
> return !mmu->is_leaf;
>
>> +   else
>
> I'd drop the else.

Yeah, your suggestion makes the code easier to read. Will fix.

>> +   return true; /* older IPMMU hardware treated as single root 
>> */
>> +}
>> +
>> +static struct ipmmu_vmsa_device *__ipmmu_find_root(void)
>> +{
>> +   struct ipmmu_vmsa_device *mmu;
>> +   bool found = false;
>
> struct ipmmu_vmsa_device *root = NULL;

I used to have it initialized to NULL and not use any found variable
and only return the variable. But then I ran into the error case when
devices exist on the ipmmu_devices list however none of them are root.
I returned the last one on the list regardless if they were root or
not. So I updated the code to use the found variable, and because of
that I thought I could simply drop the NULL assignment.

>> +
>> +   spin_lock(_devices_lock);
>> +
>> +   list_for_each_entry(mmu, _devices, list) {
>> +   if (ipmmu_is_root(mmu)) {
>> +   found = true;
>
> root = mmu;
>
>> +   break;
>> +   }
>> +   }
>> +
>> +   spin_unlock(_devices_lock);
>> +   return found ? mmu : NULL;
>
> return root;

I agree it makes sense to use root as variable name, will fix. Not
sure about the NULL assignment though, can you enlighten me?

Cheers,

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


Re: [PATCH v3 09/09] iommu/ipmmu-vmsa: Hook up r8a7795 DT matching code

2017-03-08 Thread Magnus Damm
Hi Geert,

On Wed, Mar 8, 2017 at 10:58 PM, Geert Uytterhoeven
<ge...@linux-m68k.org> wrote:
> Hi Magnus,
>
> On Wed, Mar 8, 2017 at 12:02 PM, Magnus Damm <magnus.d...@gmail.com> wrote:
>> From: Magnus Damm <damm+rene...@opensource.se>
>>
>> Tie in r8a7795 features and update the IOMMU_OF_DECLARE
>> compat string to include the updated compat string.
>>
>> TODO:
>>  - Consider making use of iommu_fwspec_add_ids() for uTLB handling
>>  Needed to coexist with non-OF R-Car Gen2 somehow...
>>  - Break out stuff useful for R-Car Gen2 from this series
>>  Fix up the Gen2 IPMMU support code
>>and/or
>>  Fold more stuff into the multi-arch series
>>  - Add support for sysfs and iommu_device_link()/unlink()
>>
>> Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
>
>> --- 0018/drivers/iommu/ipmmu-vmsa.c
>> +++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-08 19:11:53.600607110 +0900
>
>> @@ -1043,6 +1048,17 @@ static struct iommu_group *ipmmu_find_gr
>> return group;
>>  }
>>
>> +static bool ipmmu_slave_whitelist(struct device *dev)
>> +{
>> +   /* By default, do not allow use of IPMMU */
>> +   return false;
>> +}
>> +
>> +static const struct soc_device_attribute soc_r8a7795[] = {
>> +   { .soc_id = "r8a7795", },
>
> If/when the whitelist is/becomes device/revision specific, you probably want
> to store a  pointer to the *_slave_whitelist() function in the .data member?

Yeah, for sure. It is a bit early to tell exactly how the code will
look like at this point, but I think it will become more clear in the
future. Just want to send out a new version of r8a7796 IPMMU support
and some r8a7795 DT integration to get a coherent working set of patch
series out of the door first.

>> +   { /* sentinel */ }
>> +};
>> +
>>  static int ipmmu_of_xlate_dma(struct device *dev,
>>   struct of_phandle_args *spec)
>>  {
>> @@ -1053,6 +1069,18 @@ static int ipmmu_of_xlate_dma(struct dev
>> if (!of_device_is_available(spec->np))
>> return -ENODEV;
>>
>> +   /* Failing in ->attach_device() results in a hang, so make
>> +* sure the root device is installed before going there
>> +*/
>> +   if (!__ipmmu_find_root()) {
>> +   dev_info(dev, "Unable to locate IPMMU root device\n");
>
> dev_err?

Good idea. Will fix.

>> +   return -ENODEV;
>> +   }
>> +
>> +   /* For R-Car Gen3 use a white list to opt-in slave devices */
>> +   if (soc_device_match(soc_r8a7795) && !ipmmu_slave_whitelist(dev))
>> +   return -ENODEV;

This will have to be updated for r8a7796 somehow as well.

Thanks for your help!

Cheers,

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


Re: [PATCH v3 03/09] iommu/ipmmu-vmsa: Enable multi context support

2017-03-08 Thread Magnus Damm
Hi Robin,

Thanks for your feedback!

On Wed, Mar 8, 2017 at 9:21 PM, Robin Murphy <robin.mur...@arm.com> wrote:
> On 08/03/17 11:01, Magnus Damm wrote:
>> From: Magnus Damm <damm+rene...@opensource.se>
>>
>> Add support for up to 8 contexts. Each context is mapped to one
>> domain. One domain is assigned one or more slave devices. Contexts
>> are allocated dynamically and slave devices are grouped together
>> based on which IPMMU device they are connected to. This makes slave
>> devices tied to the same IPMMU device share the same IOVA space.
>>
>> Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
>> ---
>>
>>  Changes since V2:
>>  - Updated patch description to reflect code included in:
>>[PATCH v7 00/07] iommu/ipmmu-vmsa: IPMMU multi-arch update V7
>>
>>  Changes since V1:
>>  - Support up to 8 contexts instead of 4
>>  - Use feature flag and runtime handling
>>  - Default to single context
>>
>>  drivers/iommu/ipmmu-vmsa.c |   38 ++
>>  1 file changed, 30 insertions(+), 8 deletions(-)
>>
>> --- 0012/drivers/iommu/ipmmu-vmsa.c
>> +++ work/drivers/iommu/ipmmu-vmsa.c   2017-03-08 17:59:19.900607110 +0900
>> @@ -30,11 +30,12 @@
>>
>>  #include "io-pgtable.h"
>>
>> -#define IPMMU_CTX_MAX 1
>> +#define IPMMU_CTX_MAX 8
>>
>>  struct ipmmu_features {
>>   bool use_ns_alias_offset;
>>   bool has_cache_leaf_nodes;
>> + bool has_eight_ctx;
>
> Wouldn't it be more sensible to just encode a number of contexts
> directly, if it isn't reported by the hardware itself? I'm just
> imagining future hardware generations... :P
>
> bool also_has_another_eight_ctx_on_top_of_that;
> bool wait_no_this_is_the_one_where_ctx_15_isnt_usable;

=)

Sure, I agree with you!

Please note that this is currently a mix of software and hardware
policy. On R-Car Gen2 (ARM32) the legacy code only uses a single
context for now but 4 contexts are supported by hardware according to
the data sheet. The remaining 3 contexts are untested at this point.
For R-Car Gen3 (ARM64) the hardware supports 8 contexts and this patch
enables all of them.

>>  };
>>
>>  struct ipmmu_vmsa_device {
>> @@ -44,6 +45,7 @@ struct ipmmu_vmsa_device {
>>   const struct ipmmu_features *features;
>>   bool is_leaf;
>>   unsigned int num_utlbs;
>> + unsigned int num_ctx;
>>   spinlock_t lock;/* Protects ctx and domains[] 
>> */
>>   DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
>>   struct ipmmu_vmsa_domain *domains[IPMMU_CTX_MAX];
>> @@ -376,11 +378,12 @@ static int ipmmu_domain_allocate_context
>>
>>   spin_lock_irqsave(>lock, flags);
>>
>> - ret = find_first_zero_bit(mmu->ctx, IPMMU_CTX_MAX);
>> - if (ret != IPMMU_CTX_MAX) {
>> + ret = find_first_zero_bit(mmu->ctx, mmu->num_ctx);
>> + if (ret != mmu->num_ctx) {
>>   mmu->domains[ret] = domain;
>>   set_bit(ret, mmu->ctx);
>
> Using test_and_set_bit() in a loop would avoid having to take a lock here.

So you mean that in case of test_and_set_bit() returns 1 then we try
find_first_zero_bit() again?

This is not really a performance sensitive part of the driver, so I'm
currently optimizing for code readability. I'm of course all for
dropping the lock, but I have a hard time figuring out how your
suggestion could result in semi-readable code. Any pointers? =)

>> @@ -1112,6 +1123,17 @@ static int ipmmu_probe(struct platform_d
>>   if (mmu->features->use_ns_alias_offset)
>>   mmu->base += IM_NS_ALIAS_OFFSET;
>>
>> + /*
>> +  * The number of contexts varies with generation and instance.
>> +  * Newer SoCs get a total of 8 contexts enabled, older ones just one.
>> +  */
>> + if (mmu->features->has_eight_ctx)
>> + mmu->num_ctx = 8;
>> + else
>> + mmu->num_ctx = 1;
>> +
>> + WARN_ON(mmu->num_ctx > IPMMU_CTX_MAX);
>
> The likelihood of that happening doesn't appear to warrant a runtime
> check. Especially one which probably isn't even generated because it's
> trivially resolvable to "if (false)..." at compile time.

Sure, I agree. Will drop.

Thanks,

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


Re: [PATCH v3 01/09] iommu/ipmmu-vmsa: Introduce features, break out alias

2017-03-08 Thread Magnus Damm
Hi Robin,

On Wed, Mar 8, 2017 at 8:53 PM, Robin Murphy <robin.mur...@arm.com> wrote:
> Hi Magnus,
>
> On 08/03/17 11:01, Magnus Damm wrote:
>> From: Magnus Damm <damm+rene...@opensource.se>
>>
>> Introduce struct ipmmu_features to track various hardware
>> and software implementation changes inside the driver for
>> different kinds of IPMMU hardware. Add use_ns_alias_offset
>> as a first example of a feature to control if the secure
>> register bank offset should be used or not.
>>
>> Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
>> ---
>>
>>  Changes since V2:
>>  - None
>>
>>  Changes since V1:
>>  - Moved patch to front of the series
>>
>>  drivers/iommu/ipmmu-vmsa.c |   35 ---
>>  1 file changed, 28 insertions(+), 7 deletions(-)
>>
>> --- 0007/drivers/iommu/ipmmu-vmsa.c
>> +++ work/drivers/iommu/ipmmu-vmsa.c   2017-03-07 12:25:47.0 +0900
>> @@ -32,11 +32,15 @@
>>
>>  #define IPMMU_CTX_MAX 1
>>
>> +struct ipmmu_features {
>> + bool use_ns_alias_offset;
>> +};
>> +
>>  struct ipmmu_vmsa_device {
>>   struct device *dev;
>>   void __iomem *base;
>>   struct list_head list;
>> -
>> + const struct ipmmu_features *features;
>>   unsigned int num_utlbs;
>>   spinlock_t lock;/* Protects ctx and domains[] 
>> */
>>   DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
>> @@ -999,13 +1003,33 @@ static void ipmmu_device_reset(struct ip
>>   ipmmu_write(mmu, i * IM_CTX_SIZE + IMCTR, 0);
>>  }
>>
>> +static const struct ipmmu_features ipmmu_features_default = {
>> + .use_ns_alias_offset = true,
>> +};
>> +
>> +static const struct of_device_id ipmmu_of_ids[] = {
>> + {
>> + .compatible = "renesas,ipmmu-vmsa",
>> + .data = _features_default,
>> + }, {
>> + /* Terminator */
>> + },
>> +};
>> +
>> +MODULE_DEVICE_TABLE(of, ipmmu_of_ids);
>> +
>>  static int ipmmu_probe(struct platform_device *pdev)
>>  {
>>   struct ipmmu_vmsa_device *mmu;
>> + const struct of_device_id *match;
>>   struct resource *res;
>>   int irq;
>>   int ret;
>>
>> + match = of_match_node(ipmmu_of_ids, pdev->dev.of_node);
>
> of_device_get_match_data() makes this a lot easier.
>
>> + if (!match)
>> + return -EINVAL;
>
> Also, if the driver is DT-only per the other series, note that this
> cannot happen anyway, since of_driver_match_device() would have to have
> found a match for your probe function to be called in the first place.

Yeah, you are right. As you know, in the IPMMU driver (with the
r8a7795 V3 series applied) the init handling is a bit special with
ARM32 and ARM64 being treated differently. I would like to clean it up
and share a common implementation.

Until that happens, how do you think we should handle the (!match)
case? BUG_ON()?

Cheers,

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


Re: [PATCH v3 06/09] iommu/ipmmu-vmsa: Write IMCTR twice

2017-03-08 Thread Magnus Damm
Hi Robin,

On Wed, Mar 8, 2017 at 9:34 PM, Robin Murphy <robin.mur...@arm.com> wrote:
> On 08/03/17 11:02, Magnus Damm wrote:
>> From: Magnus Damm <damm+rene...@opensource.se>
>>
>> Write IMCTR both in the root device and the leaf node.
>>
>> Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
>> ---
>>
>>  Changes since V2:
>>  - None
>>
>>  Changes since V1:
>>  - None
>>
>>  drivers/iommu/ipmmu-vmsa.c |   17 ++---
>>  1 file changed, 14 insertions(+), 3 deletions(-)
>>
>> --- 0018/drivers/iommu/ipmmu-vmsa.c
>> +++ work/drivers/iommu/ipmmu-vmsa.c   2017-03-08 18:30:36.870607110 +0900
>> @@ -286,6 +286,16 @@ static void ipmmu_ctx_write(struct ipmmu
>>   ipmmu_write(domain->root, domain->context_id * IM_CTX_SIZE + reg, 
>> data);
>>  }
>>
>> +static void ipmmu_ctx_write2(struct ipmmu_vmsa_domain *domain, unsigned int 
>> reg,
>> +  u32 data)
>
> That's pretty cryptic. Maybe both functions could do with less ambiguous
> names - something like ipmmu_ctx_write_root() vs. ipmmu_ctx_write_all(),
> perhaps? (and if there's a more specific hardware term than "all" that
> describes this kind of configuration, even better).

Yeah I agree. Will fix in next version!

Thanks,

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


Re: [PATCH v3 04/09] iommu/ipmmu-vmsa: Make use of IOMMU_OF_DECLARE()

2017-03-08 Thread Magnus Damm
Hi Geert,

On Wed, Mar 8, 2017 at 10:52 PM, Geert Uytterhoeven
<ge...@linux-m68k.org> wrote:
> Hi Magnus,
>
> On Wed, Mar 8, 2017 at 12:02 PM, Magnus Damm <magnus.d...@gmail.com> wrote:
>> From: Magnus Damm <damm+rene...@opensource.se>
>>
>> Hook up IOMMU_OF_DECLARE() support in case CONFIG_IOMMU_DMA
>> is enabled. The only current supported case for 32-bit ARM
>> is disabled, however for 64-bit ARM usage of OF is required.
>>
>> Signed-off-by: Magnus Damm <damm+rene...@opensource.se
>
> While I'm not such a big fan of *_OF_DECLARE() (it doesn't support deferred
> probing, which is needed for any device with dependencies, like clocks and
> power domains), what's the rationale for not using IOMMU_OF_DECLARE()
> on arm32, and thus the need for setup_done?

ARM32 could (and should) be converted over to IOMMU_OF_DECLARE(), but
it is just a matter of timing. If we try to do it before ARM32 is
converted over to CONFIG_IOMMU_DMA=y then we have to handle all the
hairy legacy implementation details of IOMMU support in case of
CONFIG_IOMMU_DMA=n _and_ deal with just moving over the init order
bits to OF. Testing and keeping all the combinations working is a lot
of work.

I prefer to kill two birds with one stone and do a larger feature jump
and move over ARM32 to same state of ARM64 (with OF init) once
CONFIG_IOMMU_DMA=y is ready for 32-bit ARM. Just changing the init
order bits to OF while keeping legacy CONFIG_IOMMU_DMA=n code is
introducing potential errors with not much upside. Unless there is
some other reason to do it that I can't see that is. =)

Cheers,

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


Re: [PATCH v7 06/07] iommu/ipmmu-vmsa: ARM and ARM64 archdata access

2017-03-08 Thread Magnus Damm
Hi Robin,

On Wed, Mar 8, 2017 at 9:48 PM, Robin Murphy <robin.mur...@arm.com> wrote:
> On 07/03/17 03:17, Magnus Damm wrote:
>> From: Magnus Damm <damm+rene...@opensource.se>
>>
>> Not all architectures have an iommu member in their archdata, so
>> use #ifdefs support build with COMPILE_TEST on any architecture.
>
> I have a feeling I might be repeating myself, but ipmmu_vmsa_archdata
> looks to be trivially convertible to iommu_fwspec, which I strongly
> encourage, not least because it would obviate bodges like this.

Yeah, I think it should be possible to use iommu_fwspec for this
purpose. The question is when to do it. =)

I actually looked into it recently, but then realised that for this to
work then due to code sharing I need to make use of iommu_fwspec on
both 32-bit and 64-bit ARM. So it requires rework of the existing
IPMMU for 32-bit ARM (including hairy legacy CONFIG_IOMMU_DMA=n code).
I was actually thinking of doing some rework of 32-bit ARM IPMMU code
anyway (I suspect iommu_device_* conversion caused breakage) and it
probably has to happen on top of current -next. I would also like to
start reducing burden of forward porting all these patches, and
stirring up the ground does not really help much there...

Cheers,

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


[PATCH v3 08/09] iommu/ipmmu-vmsa: Allow two bit SL0

2017-03-08 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Introduce support for two bit SL0 bitfield in IMTTBCR
by using a separate feature flag.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V2:
 - None

 Changes since V1:
 - None

 drivers/iommu/ipmmu-vmsa.c |   15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

--- 0022/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-08 18:33:07.630607110 +0900
@@ -38,6 +38,7 @@ struct ipmmu_features {
bool has_cache_leaf_nodes;
bool has_eight_ctx;
bool setup_imbuscr;
+   bool twobit_imttbcr_sl0;
 };
 
 struct ipmmu_vmsa_device {
@@ -163,6 +164,10 @@ static void set_archdata(struct device *
 #define IMTTBCR_TSZ0_MASK  (7 << 0)
 #define IMTTBCR_TSZ0_SHIFT O
 
+#define IMTTBCR_SL0_TWOBIT_LVL_3   (0 << 6)
+#define IMTTBCR_SL0_TWOBIT_LVL_2   (1 << 6)
+#define IMTTBCR_SL0_TWOBIT_LVL_1   (2 << 6)
+
 #define IMBUSCR0x000c
 #define IMBUSCR_DVM(1 << 2)
 #define IMBUSCR_BUSSEL_SYS (0 << 0)
@@ -406,6 +411,7 @@ static int ipmmu_domain_allocate_context
 static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain)
 {
u64 ttbr;
+   u32 tmp;
int ret;
 
/*
@@ -458,9 +464,15 @@ static int ipmmu_domain_init_context(str
 * We use long descriptors with inner-shareable WBWA tables and allocate
 * the whole 32-bit VA space to TTBR0.
 */
+
+   if (domain->root->features->twobit_imttbcr_sl0)
+   tmp = IMTTBCR_SL0_TWOBIT_LVL_1;
+   else
+   tmp = IMTTBCR_SL0_LVL_1;
+
ipmmu_ctx_write(domain, IMTTBCR, IMTTBCR_EAE |
IMTTBCR_SH0_INNER_SHAREABLE | IMTTBCR_ORGN0_WB_WA |
-   IMTTBCR_IRGN0_WB_WA | IMTTBCR_SL0_LVL_1);
+   IMTTBCR_IRGN0_WB_WA | tmp);
 
/* MAIR0 */
ipmmu_ctx_write(domain, IMMAIR0, domain->cfg.arm_lpae_s1_cfg.mair[0]);
@@ -1080,6 +1092,7 @@ static const struct ipmmu_features ipmmu
.has_cache_leaf_nodes = false,
.has_eight_ctx = false,
.setup_imbuscr = true,
+   .twobit_imttbcr_sl0 = false,
 };
 
 static const struct of_device_id ipmmu_of_ids[] = {
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 09/09] iommu/ipmmu-vmsa: Hook up r8a7795 DT matching code

2017-03-08 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Tie in r8a7795 features and update the IOMMU_OF_DECLARE
compat string to include the updated compat string.

TODO:
 - Consider making use of iommu_fwspec_add_ids() for uTLB handling
 Needed to coexist with non-OF R-Car Gen2 somehow...
 - Break out stuff useful for R-Car Gen2 from this series
 Fix up the Gen2 IPMMU support code
   and/or
 Fold more stuff into the multi-arch series
 - Add support for sysfs and iommu_device_link()/unlink()

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V2:
 - Check for lack of root device in ->xlate()
   This fixed a bug when IPMMU-MM is disabled in DT the system hangs on boot
 - Added code to ipmmu_init_platform_device() to handle multiple ->xlate() calls
 - Include empty white list by default
 - Updated TODO list

 Changes since V1:
 - Enable multi context feature
 - Update TODO list

 drivers/iommu/ipmmu-vmsa.c |   41 +
 1 file changed, 41 insertions(+)

--- 0018/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-08 19:11:53.600607110 +0900
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
 #include 
@@ -770,6 +771,10 @@ static int ipmmu_init_platform_device(st
int num_utlbs;
int ret = -ENODEV;
 
+   /* Initialize once - xlate() will call multiple times */
+   if (to_archdata(dev))
+   return 0;
+
/* Find the master corresponding to the device. */
 
num_utlbs = of_count_phandle_with_args(dev->of_node, "iommus",
@@ -1043,6 +1048,17 @@ static struct iommu_group *ipmmu_find_gr
return group;
 }
 
+static bool ipmmu_slave_whitelist(struct device *dev)
+{
+   /* By default, do not allow use of IPMMU */
+   return false;
+}
+
+static const struct soc_device_attribute soc_r8a7795[] = {
+   { .soc_id = "r8a7795", },
+   { /* sentinel */ }
+};
+
 static int ipmmu_of_xlate_dma(struct device *dev,
  struct of_phandle_args *spec)
 {
@@ -1053,6 +1069,18 @@ static int ipmmu_of_xlate_dma(struct dev
if (!of_device_is_available(spec->np))
return -ENODEV;
 
+   /* Failing in ->attach_device() results in a hang, so make
+* sure the root device is installed before going there
+*/
+   if (!__ipmmu_find_root()) {
+   dev_info(dev, "Unable to locate IPMMU root device\n");
+   return -ENODEV;
+   }
+
+   /* For R-Car Gen3 use a white list to opt-in slave devices */
+   if (soc_device_match(soc_r8a7795) && !ipmmu_slave_whitelist(dev))
+   return -ENODEV;
+
return ipmmu_init_platform_device(dev);
 }
 
@@ -1095,11 +1123,22 @@ static const struct ipmmu_features ipmmu
.twobit_imttbcr_sl0 = false,
 };
 
+static const struct ipmmu_features ipmmu_features_r8a7795 = {
+   .use_ns_alias_offset = false,
+   .has_cache_leaf_nodes = true,
+   .has_eight_ctx = true,
+   .setup_imbuscr = false,
+   .twobit_imttbcr_sl0 = true,
+};
+
 static const struct of_device_id ipmmu_of_ids[] = {
{
.compatible = "renesas,ipmmu-vmsa",
.data = _features_default,
}, {
+   .compatible = "renesas,ipmmu-r8a7795",
+   .data = _features_r8a7795,
+   }, {
/* Terminator */
},
 };
@@ -1288,6 +1327,8 @@ static int __init ipmmu_vmsa_iommu_of_se
 
 IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa",
 ipmmu_vmsa_iommu_of_setup);
+IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795",
+ipmmu_vmsa_iommu_of_setup);
 #endif
 
 MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU");
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 07/09] iommu/ipmmu-vmsa: Make IMBUSCTR setup optional

2017-03-08 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Introduce a feature to allow opt-out of setting up
IMBUSCR. The default case is unchanged.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V2:
 - None

 Changes since V1:
 - Updated the commit message
 - Reworked patch to coexist with the multi context feature

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

--- 0020/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-08 18:32:26.280607110 +0900
@@ -37,6 +37,7 @@ struct ipmmu_features {
bool use_ns_alias_offset;
bool has_cache_leaf_nodes;
bool has_eight_ctx;
+   bool setup_imbuscr;
 };
 
 struct ipmmu_vmsa_device {
@@ -465,10 +466,10 @@ static int ipmmu_domain_init_context(str
ipmmu_ctx_write(domain, IMMAIR0, domain->cfg.arm_lpae_s1_cfg.mair[0]);
 
/* IMBUSCR */
-   ipmmu_ctx_write(domain, IMBUSCR,
-   ipmmu_ctx_read(domain, IMBUSCR) &
-   ~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
-
+   if (domain->root->features->setup_imbuscr)
+   ipmmu_ctx_write(domain, IMBUSCR,
+   ipmmu_ctx_read(domain, IMBUSCR) &
+   ~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
/*
 * IMSTR
 * Clear all interrupt flags.
@@ -1078,6 +1079,7 @@ static const struct ipmmu_features ipmmu
.use_ns_alias_offset = true,
.has_cache_leaf_nodes = false,
.has_eight_ctx = false,
+   .setup_imbuscr = true,
 };
 
 static const struct of_device_id ipmmu_of_ids[] = {
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 06/09] iommu/ipmmu-vmsa: Write IMCTR twice

2017-03-08 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Write IMCTR both in the root device and the leaf node.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V2:
 - None

 Changes since V1:
 - None

 drivers/iommu/ipmmu-vmsa.c |   17 ++---
 1 file changed, 14 insertions(+), 3 deletions(-)

--- 0018/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-08 18:30:36.870607110 +0900
@@ -286,6 +286,16 @@ static void ipmmu_ctx_write(struct ipmmu
ipmmu_write(domain->root, domain->context_id * IM_CTX_SIZE + reg, data);
 }
 
+static void ipmmu_ctx_write2(struct ipmmu_vmsa_domain *domain, unsigned int 
reg,
+u32 data)
+{
+   if (domain->mmu != domain->root)
+   ipmmu_write(domain->mmu,
+   domain->context_id * IM_CTX_SIZE + reg, data);
+
+   ipmmu_write(domain->root, domain->context_id * IM_CTX_SIZE + reg, data);
+}
+
 /* 
-
  * TLB and microTLB Management
  */
@@ -312,7 +322,7 @@ static void ipmmu_tlb_invalidate(struct
 
reg = ipmmu_ctx_read(domain, IMCTR);
reg |= IMCTR_FLUSH;
-   ipmmu_ctx_write(domain, IMCTR, reg);
+   ipmmu_ctx_write2(domain, IMCTR, reg);
 
ipmmu_tlb_sync(domain);
 }
@@ -472,7 +482,8 @@ static int ipmmu_domain_init_context(str
 * software management as we have no use for it. Flush the TLB as
 * required when modifying the context registers.
 */
-   ipmmu_ctx_write(domain, IMCTR, IMCTR_INTEN | IMCTR_FLUSH | IMCTR_MMUEN);
+   ipmmu_ctx_write2(domain, IMCTR,
+IMCTR_INTEN | IMCTR_FLUSH | IMCTR_MMUEN);
 
return 0;
 }
@@ -498,7 +509,7 @@ static void ipmmu_domain_destroy_context
 *
 * TODO: Is TLB flush really needed ?
 */
-   ipmmu_ctx_write(domain, IMCTR, IMCTR_FLUSH);
+   ipmmu_ctx_write2(domain, IMCTR, IMCTR_FLUSH);
ipmmu_tlb_sync(domain);
ipmmu_domain_free_context(domain->root, domain->context_id);
 }
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 05/09] iommu/ipmmu-vmsa: IPMMU device is 40-bit bus master

2017-03-08 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

The r8a7795 IPMMU supports 40-bit bus mastering. Both
the coherent DMA mask and the streaming DMA mask are
set to unlock the 40-bit address space for coherent
allocations and streaming operations.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V2:
 - Updated the code and commit message to use 40 bits instead of 64 bits

 Changes since V1:
 - Updated the commit message

 drivers/iommu/ipmmu-vmsa.c |1 +
 1 file changed, 1 insertion(+)

--- 0016/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-08 18:29:56.390607110 +0900
@@ -1103,6 +1103,7 @@ static int ipmmu_probe(struct platform_d
spin_lock_init(>lock);
bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
mmu->features = match->data;
+   dma_set_mask_and_coherent(>dev, DMA_BIT_MASK(40));
 
/* Map I/O memory and request IRQ. */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 04/09] iommu/ipmmu-vmsa: Make use of IOMMU_OF_DECLARE()

2017-03-08 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Hook up IOMMU_OF_DECLARE() support in case CONFIG_IOMMU_DMA
is enabled. The only current supported case for 32-bit ARM
is disabled, however for 64-bit ARM usage of OF is required.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V2:
 - Reworked registration code to make use of recently introduced:
 iommu_device_register()
 iommu_device_set_ops()
 iommu_device_set_fwnode()

 Changes since V1:
 - Reworked slightly to fit updated patch order and
   [PATCH v3 00/06] iommu/ipmmu-vmsa: IPMMU multi-arch update V3

 drivers/iommu/ipmmu-vmsa.c |   39 +++
 1 file changed, 39 insertions(+)

--- 0012/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-08 19:08:31.610607110 +0900
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -41,6 +42,7 @@ struct ipmmu_features {
 struct ipmmu_vmsa_device {
struct device *dev;
void __iomem *base;
+   struct iommu_device iommu;
struct list_head list;
const struct ipmmu_features *features;
bool is_leaf;
@@ -1161,6 +1163,25 @@ static int ipmmu_probe(struct platform_d
ipmmu_device_reset(mmu);
}
 
+#if defined(CONFIG_IOMMU_DMA)
+   /*
+* Register the IPMMU to the IOMMU subsystem in the following cases:
+* - R-Car Gen2 IPMMU (all devices registered)
+* - R-Car Gen3 IPMMU (leaf devices only - skip root IPMMU-MM device)
+*/
+   if (!mmu->features->has_cache_leaf_nodes || mmu->is_leaf) {
+   ret = iommu_device_register(>iommu);
+   if (ret)
+   return ret;
+
+   iommu_device_set_ops(>iommu, _ops);
+   iommu_device_set_fwnode(>iommu,
+   >dev.of_node->fwnode);
+
+   if (!iommu_present(_bus_type))
+   bus_set_iommu(_bus_type, _ops);
+   }
+#endif
/*
 * We can't create the ARM mapping here as it requires the bus to have
 * an IOMMU, which only happens when bus_set_iommu() is called in
@@ -1204,15 +1225,22 @@ static struct platform_driver ipmmu_driv
 
 static int __init ipmmu_init(void)
 {
+   static bool setup_done;
int ret;
 
+   if (setup_done)
+   return 0;
+
ret = platform_driver_register(_driver);
if (ret < 0)
return ret;
 
+#if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
if (!iommu_present(_bus_type))
bus_set_iommu(_bus_type, _ops);
+#endif
 
+   setup_done = true;
return 0;
 }
 
@@ -1224,6 +1252,17 @@ static void __exit ipmmu_exit(void)
 subsys_initcall(ipmmu_init);
 module_exit(ipmmu_exit);
 
+#ifdef CONFIG_IOMMU_DMA
+static int __init ipmmu_vmsa_iommu_of_setup(struct device_node *np)
+{
+   ipmmu_init();
+   return 0;
+}
+
+IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa",
+ipmmu_vmsa_iommu_of_setup);
+#endif
+
 MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU");
 MODULE_AUTHOR("Laurent Pinchart <laurent.pinch...@ideasonboard.com>");
 MODULE_LICENSE("GPL v2");
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 03/09] iommu/ipmmu-vmsa: Enable multi context support

2017-03-08 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Add support for up to 8 contexts. Each context is mapped to one
domain. One domain is assigned one or more slave devices. Contexts
are allocated dynamically and slave devices are grouped together
based on which IPMMU device they are connected to. This makes slave
devices tied to the same IPMMU device share the same IOVA space.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V2:
 - Updated patch description to reflect code included in:
   [PATCH v7 00/07] iommu/ipmmu-vmsa: IPMMU multi-arch update V7

 Changes since V1:
 - Support up to 8 contexts instead of 4
 - Use feature flag and runtime handling
 - Default to single context

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

--- 0012/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-08 17:59:19.900607110 +0900
@@ -30,11 +30,12 @@
 
 #include "io-pgtable.h"
 
-#define IPMMU_CTX_MAX 1
+#define IPMMU_CTX_MAX 8
 
 struct ipmmu_features {
bool use_ns_alias_offset;
bool has_cache_leaf_nodes;
+   bool has_eight_ctx;
 };
 
 struct ipmmu_vmsa_device {
@@ -44,6 +45,7 @@ struct ipmmu_vmsa_device {
const struct ipmmu_features *features;
bool is_leaf;
unsigned int num_utlbs;
+   unsigned int num_ctx;
spinlock_t lock;/* Protects ctx and domains[] */
DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
struct ipmmu_vmsa_domain *domains[IPMMU_CTX_MAX];
@@ -376,11 +378,12 @@ static int ipmmu_domain_allocate_context
 
spin_lock_irqsave(>lock, flags);
 
-   ret = find_first_zero_bit(mmu->ctx, IPMMU_CTX_MAX);
-   if (ret != IPMMU_CTX_MAX) {
+   ret = find_first_zero_bit(mmu->ctx, mmu->num_ctx);
+   if (ret != mmu->num_ctx) {
mmu->domains[ret] = domain;
set_bit(ret, mmu->ctx);
-   }
+   } else
+   ret = -EBUSY;
 
spin_unlock_irqrestore(>lock, flags);
 
@@ -425,9 +428,9 @@ static int ipmmu_domain_init_context(str
 * Find an unused context.
 */
ret = ipmmu_domain_allocate_context(domain->root, domain);
-   if (ret == IPMMU_CTX_MAX) {
+   if (ret < 0) {
free_io_pgtable_ops(domain->iop);
-   return -EBUSY;
+   return ret;
}
 
domain->context_id = ret;
@@ -562,7 +565,7 @@ static irqreturn_t ipmmu_irq(int irq, vo
/*
 * Check interrupts for all active contexts.
 */
-   for (i = 0; i < IPMMU_CTX_MAX; i++) {
+   for (i = 0; i < mmu->num_ctx; i++) {
if (!mmu->domains[i])
continue;
if (ipmmu_domain_irq(mmu->domains[i]) == IRQ_HANDLED)
@@ -632,6 +635,13 @@ static int ipmmu_attach_device(struct io
domain->mmu = mmu;
domain->root = root;
ret = ipmmu_domain_init_context(domain);
+   if (ret < 0) {
+   dev_err(dev, "Unable to initialize IPMMU context\n");
+   domain->mmu = NULL;
+   } else {
+   dev_info(dev, "Using IPMMU context %u\n",
+domain->context_id);
+   }
} else if (domain->mmu != mmu) {
/*
 * Something is wrong, we can't attach two devices using
@@ -1047,13 +1057,14 @@ static void ipmmu_device_reset(struct ip
unsigned int i;
 
/* Disable all contexts. */
-   for (i = 0; i < 4; ++i)
+   for (i = 0; i < mmu->num_ctx; ++i)
ipmmu_write(mmu, i * IM_CTX_SIZE + IMCTR, 0);
 }
 
 static const struct ipmmu_features ipmmu_features_default = {
.use_ns_alias_offset = true,
.has_cache_leaf_nodes = false,
+   .has_eight_ctx = false,
 };
 
 static const struct of_device_id ipmmu_of_ids[] = {
@@ -1112,6 +1123,17 @@ static int ipmmu_probe(struct platform_d
if (mmu->features->use_ns_alias_offset)
mmu->base += IM_NS_ALIAS_OFFSET;
 
+   /*
+* The number of contexts varies with generation and instance.
+* Newer SoCs get a total of 8 contexts enabled, older ones just one.
+*/
+   if (mmu->features->has_eight_ctx)
+   mmu->num_ctx = 8;
+   else
+   mmu->num_ctx = 1;
+
+   WARN_ON(mmu->num_ctx > IPMMU_CTX_MAX);
+
irq = platform_get_irq(pdev, 0);
 
/*
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 02/09] iommu/ipmmu-vmsa: Add optional root device feature

2017-03-08 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Add root device handling to the IPMMU driver by allowing certain
DT compat strings to enable has_cache_leaf_nodes that in turn will
support both root devices with interrupts and leaf devices that
face the actual IPMMU consumer devices.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V2:
 - Fixed a bug in ipmmu_find_root() when only leaf devices are present
 - Broke out __ipmmu_find_root() to allow ->xlate() check for root devices

 Changes since V1:
 - Moved patch to earlier in the series
 - Updated code to work with recent changes in:
   [PATCH v3 00/06] iommu/ipmmu-vmsa: IPMMU multi-arch update V3

 drivers/iommu/ipmmu-vmsa.c |   95 
 1 file changed, 78 insertions(+), 17 deletions(-)

--- 0011/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-08 17:56:51.770607110 +0900
@@ -34,6 +34,7 @@
 
 struct ipmmu_features {
bool use_ns_alias_offset;
+   bool has_cache_leaf_nodes;
 };
 
 struct ipmmu_vmsa_device {
@@ -41,6 +42,7 @@ struct ipmmu_vmsa_device {
void __iomem *base;
struct list_head list;
const struct ipmmu_features *features;
+   bool is_leaf;
unsigned int num_utlbs;
spinlock_t lock;/* Protects ctx and domains[] */
DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
@@ -51,6 +53,7 @@ struct ipmmu_vmsa_device {
 
 struct ipmmu_vmsa_domain {
struct ipmmu_vmsa_device *mmu;
+   struct ipmmu_vmsa_device *root;
struct iommu_domain io_domain;
 
struct io_pgtable_cfg cfg;
@@ -216,6 +219,44 @@ static void set_archdata(struct device *
 #define IMUASID_ASID0_SHIFT0
 
 /* 
-
+ * Root device handling
+ */
+
+static bool ipmmu_is_root(struct ipmmu_vmsa_device *mmu)
+{
+   if (mmu->features->has_cache_leaf_nodes)
+   return mmu->is_leaf ? false : true;
+   else
+   return true; /* older IPMMU hardware treated as single root */
+}
+
+static struct ipmmu_vmsa_device *__ipmmu_find_root(void)
+{
+   struct ipmmu_vmsa_device *mmu;
+   bool found = false;
+
+   spin_lock(_devices_lock);
+
+   list_for_each_entry(mmu, _devices, list) {
+   if (ipmmu_is_root(mmu)) {
+   found = true;
+   break;
+   }
+   }
+
+   spin_unlock(_devices_lock);
+   return found ? mmu : NULL;
+}
+
+static struct ipmmu_vmsa_device *ipmmu_find_root(struct ipmmu_vmsa_device 
*leaf)
+{
+   if (ipmmu_is_root(leaf))
+   return leaf;
+   else
+   return __ipmmu_find_root();
+}
+
+/* 
-
  * Read/Write Access
  */
 
@@ -232,13 +273,13 @@ static void ipmmu_write(struct ipmmu_vms
 
 static u32 ipmmu_ctx_read(struct ipmmu_vmsa_domain *domain, unsigned int reg)
 {
-   return ipmmu_read(domain->mmu, domain->context_id * IM_CTX_SIZE + reg);
+   return ipmmu_read(domain->root, domain->context_id * IM_CTX_SIZE + reg);
 }
 
 static void ipmmu_ctx_write(struct ipmmu_vmsa_domain *domain, unsigned int reg,
u32 data)
 {
-   ipmmu_write(domain->mmu, domain->context_id * IM_CTX_SIZE + reg, data);
+   ipmmu_write(domain->root, domain->context_id * IM_CTX_SIZE + reg, data);
 }
 
 /* 
-
@@ -373,7 +414,7 @@ static int ipmmu_domain_init_context(str
 * TODO: Add support for coherent walk through CCI with DVM and remove
 * cache handling. For now, delegate it to the io-pgtable code.
 */
-   domain->cfg.iommu_dev = domain->mmu->dev;
+   domain->cfg.iommu_dev = domain->root->dev;
 
domain->iop = alloc_io_pgtable_ops(ARM_32_LPAE_S1, >cfg,
   domain);
@@ -383,7 +424,7 @@ static int ipmmu_domain_init_context(str
/*
 * Find an unused context.
 */
-   ret = ipmmu_domain_allocate_context(domain->mmu, domain);
+   ret = ipmmu_domain_allocate_context(domain->root, domain);
if (ret == IPMMU_CTX_MAX) {
free_io_pgtable_ops(domain->iop);
return -EBUSY;
@@ -454,7 +495,7 @@ static void ipmmu_domain_destroy_context
 */
ipmmu_ctx_write(domain, IMCTR, IMCTR_FLUSH);
ipmmu_tlb_sync(domain);
-   ipmmu_domain_free_context(domain->mmu, domain->context_id);
+   ipmmu_domain_free_context(domain->root, domain->context_id);
 }
 
 /* 
-
@@ -567,7 +608,7 @@ static int ipmmu_attach_device(struct io
   struct device *dev)
 {
struct ipmmu_vmsa

[PATCH v3 00/09] iommu/ipmmu-vmsa: r8a7795 support V3

2017-03-08 Thread Magnus Damm
iommu/ipmmu-vmsa: r8a7795 support V3

[PATCH v3 01/09] iommu/ipmmu-vmsa: Introduce features, break out alias
[PATCH v3 02/09] iommu/ipmmu-vmsa: Add optional root device feature
[PATCH v3 03/09] iommu/ipmmu-vmsa: Enable multi context support
[PATCH v3 04/09] iommu/ipmmu-vmsa: Make use of IOMMU_OF_DECLARE()
[PATCH v3 05/09] iommu/ipmmu-vmsa: IPMMU device is 40-bit bus master
[PATCH v3 06/09] iommu/ipmmu-vmsa: Write IMCTR twice
[PATCH v3 07/09] iommu/ipmmu-vmsa: Make IMBUSCTR setup optional
[PATCH v3 08/09] iommu/ipmmu-vmsa: Allow two bit SL0
[PATCH v3 09/09] iommu/ipmmu-vmsa: Hook up r8a7795 DT matching code

This series contains a much needed r8a7795 support update for the
IPMMU driver. Last series was earlier posted as:

[PATCH v2 00/11] iommu/ipmmu-vmsa: r8a7795 support V2

The DT binding for r8a7795 has been accepted for upstream merge
and this series implements support following such format:

d4e42e7 iommu/ipmmu-vmsa: Add r8a7795 DT binding

The r8a7795 IPMMU is almost register compatible with earlier devices
like r8a7790-r8a7794, however some bitfields have been shifted
slightly. On a grander scale topology has been added and interrupts
have been reworked. So now there are several "cache" IPMMU units
without interrupt that somehow communicate with IPMMU-MM that
is the only instance that supports interrupts. The code refers to
IPMMU-MM as a "root" device and the other ones as "leaf" nodes.

To make this more interesting the IPMMU driver needs to be shared
between 32-bit ARM for r8a7790-r8a7794 and 64-bit ARM for r8a7795.
In practice this means that two separate implementations are needed
inside the driver to attach to the rather different architecture
specific code.

CONFIG_IOMMU_DMA=y is needed on 64-bit ARM while on 32-bit ARM
the arch specific dma-mapping code is hooked up rather directly.
During init 64-bit ARM IPMMU support is relying on IOMMU_OF_DECLARE().

This version of the code is known to build on 32-bit and 64-bit ARM.

Some patches that existed in V1 have been folded into:
 [PATCH v7 00/07] iommu/ipmmu-vmsa: IPMMU multi-arch update V7

Changes since V2:
 - Patch 2/9 has been updated with a bug fix and to supply __ipmmu_find_root()
 - Patch 4/9 now makes use of iommu_device_* functions
 - Patch 5/9 sets the mask to 40 bits instead of 64 bits
 - Patch 9/9 implements white list handling via ->xlate() and fixes a bug

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Developed on top of v4.11-rc1 and:
 [PATCH v7 00/07] iommu/ipmmu-vmsa: IPMMU multi-arch update V7

 drivers/iommu/ipmmu-vmsa.c |  291 +---
 1 file changed, 251 insertions(+), 40 deletions(-)
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


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

2017-03-06 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

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 <damm+rene...@opensource.se>
Acked-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
Reviewed-by: Joerg Roedel <jroe...@suse.de>
---

 Changes since V6:
 - None

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

--- 0011/drivers/iommu/Kconfig
+++ work/drivers/iommu/Kconfig  2017-03-06 18:50:49.260607110 +0900
@@ -275,7 +275,6 @@ config EXYNOS_IOMMU_DEBUG
 config IPMMU_VMSA
bool "Renesas VMSA-compatible IPMMU"
depends on ARM || IOMMU_DMA
-   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 v7 05/07] iommu/ipmmu-vmsa: Add new IOMMU_DOMAIN_DMA ops

2017-03-06 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Introduce an alternative set of iommu_ops suitable for 64-bit ARM
as well as 32-bit ARM when CONFIG_IOMMU_DMA=y. Also adjust the
Kconfig to depend on ARM or IOMMU_DMA. Initialize the device
from ->xlate() when CONFIG_IOMMU_DMA=y.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V6:
 - Rolled in the following patches from "r8a7795 support V2":
   [PATCH v2 04/11] iommu/ipmmu-vmsa: Reuse iommu groups
   [PATCH v2 06/11] iommu/ipmmu-vmsa: Teach xlate() to skip disabled iommus
 - Moved find_group() implementation to prevent warning on 32-bit ARM
 - Rolled in the following patch from "IPMMU slave device whitelist V2":
   [PATCH/RFC v2 3/4] iommu/ipmmu-vmsa: Check devices in xlate()

 drivers/iommu/Kconfig  |1 
 drivers/iommu/ipmmu-vmsa.c |  164 +---
 2 files changed, 157 insertions(+), 8 deletions(-)

--- 0001/drivers/iommu/Kconfig
+++ work/drivers/iommu/Kconfig  2017-03-06 18:42:42.0 +0900
@@ -274,6 +274,7 @@ config EXYNOS_IOMMU_DEBUG
 
 config IPMMU_VMSA
bool "Renesas VMSA-compatible IPMMU"
+   depends on ARM || IOMMU_DMA
depends on ARM_LPAE
depends on ARCH_RENESAS || COMPILE_TEST
select IOMMU_API
--- 0009/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-06 19:22:27.700607110 +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"
 
@@ -57,6 +60,8 @@ struct ipmmu_vmsa_archdata {
struct ipmmu_vmsa_device *mmu;
unsigned int *utlbs;
unsigned int num_utlbs;
+   struct device *dev;
+   struct list_head list;
 };
 
 static DEFINE_SPINLOCK(ipmmu_devices_lock);
@@ -522,14 +527,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);
@@ -572,6 +569,9 @@ static int ipmmu_attach_device(struct io
dev_err(dev, "Can't attach IPMMU %s to domain on IPMMU %s\n",
dev_name(mmu->dev), dev_name(domain->mmu->dev));
ret = -EINVAL;
+   } else {
+   dev_info(dev, "Reusing IPMMU context %u\n",
+domain->context_id);
}
 
spin_unlock_irqrestore(>lock, flags);
@@ -708,6 +708,7 @@ static int ipmmu_init_platform_device(st
archdata->mmu = mmu;
archdata->utlbs = utlbs;
archdata->num_utlbs = num_utlbs;
+   archdata->dev = dev;
dev->archdata.iommu = archdata;
return 0;
 
@@ -716,6 +717,16 @@ error:
return ret;
 }
 
+#if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
+
+static struct iommu_domain *ipmmu_domain_alloc(unsigned type)
+{
+   if (type != IOMMU_DOMAIN_UNMANAGED)
+   return NULL;
+
+   return __ipmmu_domain_alloc(type);
+}
+
 static int ipmmu_add_device(struct device *dev)
 {
struct ipmmu_vmsa_archdata *archdata;
@@ -823,6 +834,141 @@ 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 DEFINE_SPINLOCK(ipmmu_slave_devices_lock);
+static LIST_HEAD(ipmmu_slave_devices);
+
+static struct iommu_domain *ipmmu_domain_alloc_dma(unsigned type)
+{
+   struct iommu_domain *io_domain = NULL;
+
+   switch (type) {
+   case IOMMU_DOMAIN_UNMANAGED:
+   io_domain = __ipmmu_domain_alloc(type);
+   break;
+
+   case IOMMU_DOMAIN_DMA:
+   io_domain = __ipmmu_domain_alloc(type);
+   if (io_domain)
+   iommu_get_dma_cookie(io_domain);
+   break;
+   }
+
+   return io_domain;
+}
+
+static void ipmmu_domain_free_dma(struct iommu_domain *io_domain)
+{
+   switch (io_domain->type) {
+   case IOMMU_DOMAIN_DMA:
+   iommu_put_dma_cookie(io_domain);
+   /* fall-through */
+   default:
+   ipmmu_domain_free(io_domain);
+   break;
+   }
+}
+
+static int ipmmu_add_device_dma(struct device *dev)
+{
+   struct ipmmu_vmsa_archdata *archdata = dev->archdata.iommu;
+   struct iommu_group *group;
+
+   /* The device has been verified in xlate() */
+   if (!archdata)
+   return -ENODEV;
+
+   group = iommu_group_get_for_dev(dev);
+   if (IS_ERR(group))
+  

[PATCH v7 06/07] iommu/ipmmu-vmsa: ARM and ARM64 archdata access

2017-03-06 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Not all architectures have an iommu member in their archdata, so
use #ifdefs support build with COMPILE_TEST on any architecture.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
Reviewed-by: Joerg Roedel <jroe...@suse.de>
---

Changes since V6:
 - Updated patch to handle newly introduced functions in:
   [PATCH v7 05/07] iommu/ipmmu-vmsa: Add new IOMMU_DOMAIN_DMA ops

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

--- 0010/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-06 19:26:26.070607110 +0900
@@ -72,6 +72,25 @@ static struct ipmmu_vmsa_domain *to_vmsa
return container_of(dom, struct ipmmu_vmsa_domain, io_domain);
 }
 
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+static struct ipmmu_vmsa_archdata *to_archdata(struct device *dev)
+{
+   return dev->archdata.iommu;
+}
+static void set_archdata(struct device *dev, struct ipmmu_vmsa_archdata *p)
+{
+   dev->archdata.iommu = p;
+}
+#else
+static struct ipmmu_vmsa_archdata *to_archdata(struct device *dev)
+{
+   return NULL;
+}
+static void set_archdata(struct device *dev, struct ipmmu_vmsa_archdata *p)
+{
+}
+#endif
+
 #define TLB_LOOP_TIMEOUT   100 /* 100us */
 
 /* 
-
@@ -543,7 +562,7 @@ static void ipmmu_domain_free(struct iom
 static int ipmmu_attach_device(struct iommu_domain *io_domain,
   struct device *dev)
 {
-   struct ipmmu_vmsa_archdata *archdata = dev->archdata.iommu;
+   struct ipmmu_vmsa_archdata *archdata = to_archdata(dev);
struct ipmmu_vmsa_device *mmu = archdata->mmu;
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
unsigned long flags;
@@ -588,7 +607,7 @@ static int ipmmu_attach_device(struct io
 static void ipmmu_detach_device(struct iommu_domain *io_domain,
struct device *dev)
 {
-   struct ipmmu_vmsa_archdata *archdata = dev->archdata.iommu;
+   struct ipmmu_vmsa_archdata *archdata = to_archdata(dev);
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
unsigned int i;
 
@@ -709,7 +728,7 @@ static int ipmmu_init_platform_device(st
archdata->utlbs = utlbs;
archdata->num_utlbs = num_utlbs;
archdata->dev = dev;
-   dev->archdata.iommu = archdata;
+   set_archdata(dev, archdata);
return 0;
 
 error:
@@ -729,12 +748,11 @@ static struct iommu_domain *ipmmu_domain
 
 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) {
+   if (to_archdata(dev)) {
dev_warn(dev, "IOMMU driver already assigned to device %s\n",
 dev_name(dev));
return -EINVAL;
@@ -770,8 +788,7 @@ 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;
+   mmu = to_archdata(dev)->mmu;
if (!mmu->mapping) {
struct dma_iommu_mapping *mapping;
 
@@ -799,7 +816,7 @@ error:
if (mmu)
arm_iommu_release_mapping(mmu->mapping);
 
-   dev->archdata.iommu = NULL;
+   set_archdata(dev, NULL);
 
if (!IS_ERR_OR_NULL(group))
iommu_group_remove_device(dev);
@@ -809,7 +826,7 @@ error:
 
 static void ipmmu_remove_device(struct device *dev)
 {
-   struct ipmmu_vmsa_archdata *archdata = dev->archdata.iommu;
+   struct ipmmu_vmsa_archdata *archdata = to_archdata(dev);
 
arm_iommu_detach_device(dev);
iommu_group_remove_device(dev);
@@ -817,7 +834,7 @@ static void ipmmu_remove_device(struct d
kfree(archdata->utlbs);
kfree(archdata);
 
-   dev->archdata.iommu = NULL;
+   set_archdata(dev, NULL);
 }
 
 static const struct iommu_ops ipmmu_ops = {
@@ -874,7 +891,7 @@ static void ipmmu_domain_free_dma(struct
 
 static int ipmmu_add_device_dma(struct device *dev)
 {
-   struct ipmmu_vmsa_archdata *archdata = dev->archdata.iommu;
+   struct ipmmu_vmsa_archdata *archdata = to_archdata(dev);
struct iommu_group *group;
 
/* The device has been verified in xlate() */
@@ -893,7 +910,7 @@ static int ipmmu_add_device_dma(struct d
 
 static void ipmmu_remove_device_dma(struct device *dev)
 {
-   struct ipmmu_vmsa_archdata *archdata = dev->archdata.iommu;
+   struct ipmmu_vmsa_archdata *archdata = to_archdata(dev);
 
spin_lock(_slave_devices_lock);
lis

[PATCH v7 02/07] iommu/ipmmu-vmsa: Rework interrupt code and use bitmap for context

2017-03-06 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Introduce a bitmap for context handing and convert the
interrupt routine to handle all registered contexts.

At this point the number of contexts are still limited.

Also remove the use of the ARM specific mapping variable
from ipmmu_irq() to allow compile on ARM64.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
Reviewed-by: Joerg Roedel <jroe...@suse.de>
---

 Changes since V6:
 - None

 drivers/iommu/ipmmu-vmsa.c |   76 ++--
 1 file changed, 66 insertions(+), 10 deletions(-)

--- 0003/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-06 18:32:38.350607110 +0900
@@ -8,6 +8,7 @@
  * the Free Software Foundation; version 2 of the License.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -26,12 +27,17 @@
 
 #include "io-pgtable.h"
 
+#define IPMMU_CTX_MAX 1
+
 struct ipmmu_vmsa_device {
struct device *dev;
void __iomem *base;
struct list_head list;
 
unsigned int num_utlbs;
+   spinlock_t lock;/* Protects ctx and domains[] */
+   DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
+   struct ipmmu_vmsa_domain *domains[IPMMU_CTX_MAX];
 
struct dma_iommu_mapping *mapping;
 };
@@ -293,9 +299,29 @@ static struct iommu_gather_ops ipmmu_gat
  * Domain/Context Management
  */
 
+static int ipmmu_domain_allocate_context(struct ipmmu_vmsa_device *mmu,
+struct ipmmu_vmsa_domain *domain)
+{
+   unsigned long flags;
+   int ret;
+
+   spin_lock_irqsave(>lock, flags);
+
+   ret = find_first_zero_bit(mmu->ctx, IPMMU_CTX_MAX);
+   if (ret != IPMMU_CTX_MAX) {
+   mmu->domains[ret] = domain;
+   set_bit(ret, mmu->ctx);
+   }
+
+   spin_unlock_irqrestore(>lock, flags);
+
+   return ret;
+}
+
 static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain)
 {
u64 ttbr;
+   int ret;
 
/*
 * Allocate the page table operations.
@@ -327,10 +353,15 @@ static int ipmmu_domain_init_context(str
return -EINVAL;
 
/*
-* TODO: When adding support for multiple contexts, find an unused
-* context.
+* Find an unused context.
 */
-   domain->context_id = 0;
+   ret = ipmmu_domain_allocate_context(domain->mmu, domain);
+   if (ret == IPMMU_CTX_MAX) {
+   free_io_pgtable_ops(domain->iop);
+   return -EBUSY;
+   }
+
+   domain->context_id = ret;
 
/* TTBR0 */
ttbr = domain->cfg.arm_lpae_s1_cfg.ttbr[0];
@@ -372,6 +403,19 @@ static int ipmmu_domain_init_context(str
return 0;
 }
 
+static void ipmmu_domain_free_context(struct ipmmu_vmsa_device *mmu,
+ unsigned int context_id)
+{
+   unsigned long flags;
+
+   spin_lock_irqsave(>lock, flags);
+
+   clear_bit(context_id, mmu->ctx);
+   mmu->domains[context_id] = NULL;
+
+   spin_unlock_irqrestore(>lock, flags);
+}
+
 static void ipmmu_domain_destroy_context(struct ipmmu_vmsa_domain *domain)
 {
/*
@@ -382,6 +426,7 @@ static void ipmmu_domain_destroy_context
 */
ipmmu_ctx_write(domain, IMCTR, IMCTR_FLUSH);
ipmmu_tlb_sync(domain);
+   ipmmu_domain_free_context(domain->mmu, domain->context_id);
 }
 
 /* 
-
@@ -439,16 +484,25 @@ static irqreturn_t ipmmu_domain_irq(stru
 static irqreturn_t ipmmu_irq(int irq, void *dev)
 {
struct ipmmu_vmsa_device *mmu = dev;
-   struct iommu_domain *io_domain;
-   struct ipmmu_vmsa_domain *domain;
+   irqreturn_t status = IRQ_NONE;
+   unsigned int i;
+   unsigned long flags;
 
-   if (!mmu->mapping)
-   return IRQ_NONE;
+   spin_lock_irqsave(>lock, flags);
+
+   /*
+* Check interrupts for all active contexts.
+*/
+   for (i = 0; i < IPMMU_CTX_MAX; i++) {
+   if (!mmu->domains[i])
+   continue;
+   if (ipmmu_domain_irq(mmu->domains[i]) == IRQ_HANDLED)
+   status = IRQ_HANDLED;
+   }
 
-   io_domain = mmu->mapping->domain;
-   domain = to_vmsa_domain(io_domain);
+   spin_unlock_irqrestore(>lock, flags);
 
-   return ipmmu_domain_irq(domain);
+   return status;
 }
 
 /* 
-
@@ -776,6 +830,8 @@ static int ipmmu_probe(struct platform_d
 
mmu->dev = >dev;
mmu->num_utlbs = 32;
+   spin_lock_init(>lock);
+   bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
 
/* Map I/O memory and request IRQ. */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


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

2017-03-06 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

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

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
Reviewed-by: Joerg Roedel <jroe...@suse.de>
---

 Changes since V6:
 - None

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

--- 0006/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-06 18:34:59.520607110 +0900
@@ -509,13 +509,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;
@@ -525,6 +522,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


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

2017-03-06 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

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 <damm+rene...@opensource.se>
Reviewed-by: Joerg Roedel <jroe...@suse.de>
---

Changes since V6:
 - None

 drivers/iommu/ipmmu-vmsa.c |   58 
 1 file changed, 37 insertions(+), 21 deletions(-)

--- 0004/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-06 18:33:38.600607110 +0900
@@ -649,22 +649,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",
@@ -701,6 +694,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)) {
@@ -718,16 +741,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
@@ -738,6 +754,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;
 
@@ -762,10 +780,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 v7 00/07] iommu/ipmmu-vmsa: IPMMU multi-arch update V7

2017-03-06 Thread Magnus Damm
iommu/ipmmu-vmsa: IPMMU multi-arch update V7

[PATCH v7 01/07] iommu/ipmmu-vmsa: Remove platform data handling
[PATCH v7 02/07] iommu/ipmmu-vmsa: Rework interrupt code and use bitmap for 
context
[PATCH v7 03/07] iommu/ipmmu-vmsa: Break out utlb parsing code
[PATCH v7 04/07] iommu/ipmmu-vmsa: Break out domain allocation code
[PATCH v7 05/07] iommu/ipmmu-vmsa: Add new IOMMU_DOMAIN_DMA ops
[PATCH v7 06/07] iommu/ipmmu-vmsa: ARM and ARM64 archdata access
[PATCH v7 07/07] iommu/ipmmu-vmsa: Drop LPAE Kconfig dependency

These patches update the IPMMU driver with a couple of changes to support
build on multiple architectures. In the process of doing so the interrupt
code gets reworked, the foundation for supporting multiple contexts are
added and in case of CONFIG_IOMMU_DMA=y (on 64-bit or 32-bit ARM) devices
are grouped together and handled via ->xlate() - thanks Robin! Support for
existing 32-bit ARM SoCs from R-Car Gen2 is kept as-is.

Changes since V6:
 - Rebased on top of v4.11-rc1 and the following fast-tracked change:
   3b6bb5b iommu/ipmmu-vmsa: Restrict IOMMU Domain Geometry to 32-bit address 
spac
 - Updated patch 5/7 to roll in a few patches from other series
   See individual patch for more details
 - Build tested on 32-bit and 64-bit ARM
 - Run time tested on 64-bit ARM (with additional SoC-specific patches)

Changes since V5:
 - Rebased series on top of next-20161019
 - Updated patch 5/7 to simplify domain allocation/free code - thanks Joerg!
 - Added reviewed-by tag from Joerg for patch 1-4 and 6-7.
 
Changes since V4:
 - Updated patch 3/7 to work on top on the following commit in next-20160920:
   b1e2afc iommu/ipmmu-vmsa: Fix wrong error handle of ipmmu_add_device
 - Add Kconfig hunk to patch 5/7 to avoid undeclared ipmmu_ops if COMPILE_TEST
 - Rebased patch 7/7 to fit on top of new Kconfig bits in 5/7

Changes since V3:
 - Updated patch 3/7 to fix hang-on-boot issue on 32-bit ARM - thanks Geert!
 - Reworked group parameter handling in patch 3/7 and 5/7.
 - Added patch 6/7 to fix build of the driver on s390/tile/um architectures

Changes since V2:
 - Got rid of patch 3 from the V2 however patch 1, 2 and 4 are kept.
 - V3 patch 3, 4 and 5 come from
   [PATCH 00/04] iommu/ipmmu-vmsa: IPMMU CONFIG_IOMMU_DMA update
 - Patch 5 has been reworked to include patch 3 of the V1 of this series 

Changes since V1:
 - Got rid of patch 2 and 3 from initial series
 - Updated bitmap code locking and also used lighter bitop functions
 - Updated the Kconfig bits to apply on top of ARCH_RENESAS

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Built on top v4.11-rc1:

 drivers/iommu/Kconfig  |2 
 drivers/iommu/ipmmu-vmsa.c |  359 
 2 files changed, 299 insertions(+), 62 deletions(-)
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


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

2017-03-06 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

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 <damm+rene...@opensource.se>
Reviewed-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
Reviewed-by: Joerg Roedel <jroe...@suse.de>
---

 Changes since V6:
 - None

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

--- 0001/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-06 17:25:49.0 +0900
@@ -768,11 +768,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


Re: [PATCH/RFC v2 0/4] iommu/ipmmu-vmsa: IPMMU slave device whitelist V2

2017-03-06 Thread Magnus Damm
On Fri, Jan 27, 2017 at 3:14 PM, Magnus Damm <magnus.d...@gmail.com> wrote:
> iommu/ipmmu-vmsa: IPMMU slave device whitelist V2
>
> [PATCH/RFC v2 1/4] iommu/of: Skip IOMMU devices disabled in DT
> [PATCH/RFC v2 2/4] iommu/ipmmu-vmsa: Get rid of disabled device check
> [PATCH/RFC v2 3/4] iommu/ipmmu-vmsa: Check devices in xlate()
> [PATCH/RFC v2 3/4] iommu/ipmmu-vmsa: Opt-in slave devices based on ES version
>
> Here's an updated prototype that shows how DT integration of IPMMU details
> may be integrated and merged upstream based on SoC data sheet ahead of
> time followed by enablement in the IPMMU driver code once the appropriate
> SoC ES version has been released and the hardware has been tested.
>
> Changes since V1:
>  - Broke out patch 1 from the IPMMU driver
>  - Moved slave device check from ->add_device() to ->xlate() (Thanks Robin!)
>  - Updated white list patch to hook into ->xlate()
>
> Patch 1 may be suitable for upstream merge, however other patches should
> in the future if agreed on be rolled into the IPMMU driver series.

Hi Geert, everyone,

Do you have any opinion about the code in this version of the series?

I recall that you agreed with the approach in "[PATCH/RFC 2/2]
iommu/ipmmu-vmsa: Opt-in slave devices based on ES version", however
it was suggested to me by Robin that my code in "[PATCH/RFC 1/2]
arm64: mm: Silently allow devices lacking IOMMU group" should be
reworked to use ->xlate().

Now this series makes use of ->xlate() to implement the white list, so
I hope that makes everyone happy.

Also, based on your suggestion I finally managed to break out the code
that skips over disabled devices in "[PATCH/RFC v2 1/4] iommu/of: Skip
IOMMU devices disabled in DT" but I'm not sure if this will cause
problem for other platforms.

Anyway, my current plan is to wait for feedback for "[PATCH/RFC v2
1/4] iommu/of: Skip IOMMU devices disabled in DT" and handle that
independently, and also roll in the other changes in this series into
my other IPMMU code.

Thanks,

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


Re: [PATCH v2 2/3] iommu/ipmmu-vmsa: Increase maximum micro-TLBS to 48

2017-01-30 Thread Magnus Damm
Hi Joerg,

On Fri, Jan 27, 2017 at 8:47 PM, Joerg Roedel <j...@8bytes.org> wrote:
> On Mon, Jan 23, 2017 at 08:40:29PM +0900, Magnus Damm wrote:
>> From: Magnus Damm <damm+rene...@opensource.se>
>>
>> Bump up the maximum numbers of micro-TLBS to 48.
>>
>> Each IPMMU device instance get micro-TLB assignment via
>> the "iommus" property in DT. Older SoCs tend to use a
>> maximum number of 32 micro-TLBs per IPMMU instance however
>> newer SoCs such as r8a7796 make use of up to 48 micro-TLBs.
>>
>> At this point no SoC specific handling is done to validate
>> the maximum number of micro-TLBs, and because of that the
>> DT information is assumed to be within correct range for
>> each particular SoC.
>>
>> If needed in the future SoC specific feature flags can be
>> added to handle the maximum number of micro-TLBs without
>> requiring DT changes, however at this point this does not
>> seem necessary.
>>
>> Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
>
> I get a conflict when applying this to v4.10-rc5. What is this based on,
> any patches I missed?

Thanks for giving it a go. The second patch in this series should apply as-is:
[PATCH v2 1/3] iommu/ipmmu-vmsa: Add r8a7796 DT binding

However for driver code there are two series in between:
 [PATCH v6 00/07] iommu/ipmmu-vmsa: IPMMU multi-arch update V6
 [PATCH v2 00/11] iommu/ipmmu-vmsa: r8a7795 support V2

For more detailed dependency information please see the cover letter!

Regarding the driver code please wait for "IPMMU multi-arch update V7"
that takes comments from Laurent into consideration. Hopefully I
should be able to send it out some time this week.

As for "[PATCH v2 1/3] iommu/ipmmu-vmsa: Add r8a7796 DT binding",
would it be possible to fast track mainline merge of that particular
DT binding patch? Can you take it in your tree?

To give some background, we already have the IPMMU DT binding for
older devices and the sister device r8a7795 in mainline, so the
r8a7796 DT binding is just a small incremental step. To make sure we
don't go too wild with DT changes we tend to require that the DT
binding change should be queued up before starting to merge changes to
DTS files. So currently some DT changes are blocking on that r8a7796
DT binding and it would be nice to unblock those if possible..

Thanks!

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


[PATCH/RFC] iommu/dma: Per-domain flag to control size-alignment

2017-01-26 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Introduce the flag "no_size_align" to allow disabling size-alignment
on a per-domain basis. This follows the suggestion by the comment
in the code, however a per-device control may be preferred?

Needed to make virtual space contiguous for certain devices.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 drivers/iommu/dma-iommu.c |6 +-
 include/linux/iommu.h |1 +
 2 files changed, 6 insertions(+), 1 deletion(-)

--- 0001/drivers/iommu/dma-iommu.c
+++ work/drivers/iommu/dma-iommu.c  2017-01-27 15:17:50.280607110 +0900
@@ -209,14 +209,18 @@ static struct iova *__alloc_iova(struct
struct iova_domain *iovad = cookie_iovad(domain);
unsigned long shift = iova_shift(iovad);
unsigned long length = iova_align(iovad, size) >> shift;
+   bool size_aligned = true;
 
if (domain->geometry.force_aperture)
dma_limit = min(dma_limit, domain->geometry.aperture_end);
+
+   if (domain->no_size_align)
+   size_aligned = false;
/*
 * Enforce size-alignment to be safe - there could perhaps be an
 * attribute to control this per-device, or at least per-domain...
 */
-   return alloc_iova(iovad, length, dma_limit >> shift, true);
+   return alloc_iova(iovad, length, dma_limit >> shift, size_aligned);
 }
 
 /* The IOVA allocator knows what we mapped, so just unmap whatever that was */
--- 0001/include/linux/iommu.h
+++ work/include/linux/iommu.h  2017-01-27 15:16:37.630607110 +0900
@@ -83,6 +83,7 @@ struct iommu_domain {
iommu_fault_handler_t handler;
void *handler_token;
struct iommu_domain_geometry geometry;
+   bool no_size_align;
void *iova_cookie;
 };
 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH/RFC v2 3/4] iommu/ipmmu-vmsa: Opt-in slave devices based on ES version

2017-01-26 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Match on r8a7795 ES2 and enable a certain DMA controller.
In other cases the IPMMU driver remains disabled.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Changes since V1:
 - Perform white list check in ->xlate() instead of ->add_device()

 drivers/iommu/ipmmu-vmsa.c |   25 +
 1 file changed, 25 insertions(+)

--- 0009/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-01-27 13:14:47.470607110 +0900
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
 #include 
@@ -1032,9 +1033,33 @@ static void ipmmu_remove_device_dma(stru
iommu_group_remove_device(dev);
 }
 
+static const struct soc_device_attribute r8a7795es2[] = {
+   { .soc_id = "r8a7795", .revision = "ES2.*" },
+   { /* sentinel */ }
+};
+
+static int ipmmu_slave_whitelist(struct device *dev)
+{
+   /* Opt-in slave devices based on SoC and ES version */
+   if (soc_device_match(r8a7795es2)) {
+   if (!strcmp(dev_name(dev), "e731.dma-controller"))
+   return 0;
+   }
+
+   /* By default, do not allow use of IPMMU */
+   return -ENODEV;
+}
+
 static int ipmmu_of_xlate_dma(struct device *dev,
  struct of_phandle_args *spec)
 {
+   int ret;
+
+   /* Opt-in devices based on SoC and ES version */
+   ret = ipmmu_slave_whitelist(dev);
+   if (ret)
+   return ret;
+
/* For now only tested on R-Car Gen3 with ARM64 arch init order
 * TODO: Test R-Car Gen2 with ARM32 arch init order
 */
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH/RFC v2 1/4] iommu/of: Skip IOMMU devices disabled in DT

2017-01-26 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Extend the shared IOMMU code to skip over ->xlate() in case the
IOMMU device pointed to by a slave device has been disabled in DT.

Difficult to trigger in case a single IOMMU device is used, however
when multiple IOMMUs are used and some of them are disabled in DT
then this patch makes sure that ->xlate() only gets invoked for the
enabled ones.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 I used to keep this as a local check in the xlate() callback
 for the not-yet-merged-upstream R-Car Gen3 IPMMU driver stack.

 Since honoring DT disabled devices probably makes sense for most users
 it seems like a good plan to try to push it into the common subsystem level.

 Thanks to Geert for suggesting this ages ago.

 Developed on top of renesas-drivers-2017-01-24-v4.10-rc5 which
 includes a recent version of iommu/next.

 drivers/iommu/of_iommu.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- 0001/drivers/iommu/of_iommu.c
+++ work/drivers/iommu/of_iommu.c   2017-01-27 13:19:22.540607110 +0900
@@ -159,7 +159,7 @@ const struct iommu_ops *of_iommu_configu
np = iommu_spec.np;
ops = of_iommu_get_ops(np);
 
-   if (!ops || !ops->of_xlate ||
+   if (!ops || !ops->of_xlate || !of_device_is_available(np) ||
iommu_fwspec_init(dev, >fwnode, ops) ||
ops->of_xlate(dev, _spec))
goto err_put_node;
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH/RFC v2 3/4] iommu/ipmmu-vmsa: Check devices in xlate()

2017-01-26 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Rework the IPMMU code to validate devices in ->xlate() instead of
accepting all devices in xlate() and instead validating devices
in ->add_device(). This makes it possible for the IPMMU device
driver to reject slave devices based on software policy.

Once a slave device is rejected by the ->xlate() callback the shared
function of_iommu_configure() will fail as well which in turn disables
per-device IOMMU handing in the arch-specific mapping code by not
passing any IOMMU callbacks to arch_setup_dma_ops().

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 TODO: Make sure this does not break R-Car Gen2 support

 drivers/iommu/ipmmu-vmsa.c |   27 +++
 1 file changed, 7 insertions(+), 20 deletions(-)

--- 0007/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-01-27 13:11:35.970607110 +0900
@@ -1007,16 +1007,14 @@ static int ipmmu_add_device_dma(struct d
struct ipmmu_vmsa_archdata *archdata = dev->archdata.iommu;
struct iommu_group *group;
 
-   /* only accept devices with iommus property */
-   if (of_count_phandle_with_args(dev->of_node, "iommus",
-  "#iommu-cells") < 0)
+   /* The device needs to be verified in xlate() */
+   if (!archdata)
return -ENODEV;
 
group = iommu_group_get_for_dev(dev);
if (IS_ERR(group))
return PTR_ERR(group);
 
-   archdata = dev->archdata.iommu;
spin_lock(_slave_devices_lock);
list_add(>list, _slave_devices);
spin_unlock(_slave_devices_lock);
@@ -1034,24 +1032,13 @@ static void ipmmu_remove_device_dma(stru
iommu_group_remove_device(dev);
 }
 
-static struct iommu_group *ipmmu_device_group_dma(struct device *dev)
-{
-   struct iommu_group *group;
-   int ret;
-
-   ret = ipmmu_init_platform_device(dev);
-   if (!ret)
-   group = ipmmu_find_group(dev);
-   else
-   group = ERR_PTR(ret);
-
-   return group;
-}
-
 static int ipmmu_of_xlate_dma(struct device *dev,
  struct of_phandle_args *spec)
 {
-   return 0;
+   /* For now only tested on R-Car Gen3 with ARM64 arch init order
+* TODO: Test R-Car Gen2 with ARM32 arch init order
+*/
+   return ipmmu_init_platform_device(dev);
 }
 
 static const struct iommu_ops ipmmu_ops = {
@@ -1065,7 +1052,7 @@ static const struct iommu_ops ipmmu_ops
.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,
+   .device_group = ipmmu_find_group,
.pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K,
.of_xlate = ipmmu_of_xlate_dma,
 };
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH/RFC v2 2/4] iommu/ipmmu-vmsa: Get rid of disabled device check

2017-01-26 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Since of_iommu_configure() now skips over disabled devices
we can simply drop this check in the IPMMU driver.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

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

--- 0001/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-01-27 13:09:36.840607110 +0900
@@ -1051,13 +1051,6 @@ static struct iommu_group *ipmmu_device_
 static int ipmmu_of_xlate_dma(struct device *dev,
  struct of_phandle_args *spec)
 {
-   /* If the IPMMU device is disabled in DT then return error
-* to make sure the of_iommu code does not install ops
-* even though the iommu device is disabled
-*/
-   if (!of_device_is_available(spec->np))
-   return -ENODEV;
-
return 0;
 }
 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH/RFC v2 0/4] iommu/ipmmu-vmsa: IPMMU slave device whitelist V2

2017-01-26 Thread Magnus Damm
iommu/ipmmu-vmsa: IPMMU slave device whitelist V2

[PATCH/RFC v2 1/4] iommu/of: Skip IOMMU devices disabled in DT
[PATCH/RFC v2 2/4] iommu/ipmmu-vmsa: Get rid of disabled device check
[PATCH/RFC v2 3/4] iommu/ipmmu-vmsa: Check devices in xlate()
[PATCH/RFC v2 3/4] iommu/ipmmu-vmsa: Opt-in slave devices based on ES version

Here's an updated prototype that shows how DT integration of IPMMU details
may be integrated and merged upstream based on SoC data sheet ahead of
time followed by enablement in the IPMMU driver code once the appropriate
SoC ES version has been released and the hardware has been tested.

Changes since V1:
 - Broke out patch 1 from the IPMMU driver
 - Moved slave device check from ->add_device() to ->xlate() (Thanks Robin!)
 - Updated white list patch to hook into ->xlate()

Patch 1 may be suitable for upstream merge, however other patches should
in the future if agreed on be rolled into the IPMMU driver series.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 Developed on top of renesas-drivers-2017-01-24-v4.10-rc5

 drivers/iommu/ipmmu-vmsa.c |   59 +++-
 drivers/iommu/of_iommu.c   |2 -
 2 files changed, 33 insertions(+), 28 deletions(-)
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH/RFC] iommu/ipmmu-vmsa: Restrict IOMMU Domain Geometry to 32-bit address space

2017-01-26 Thread Magnus Damm
Hi Geert,

On Thu, Jan 26, 2017 at 6:53 PM, Geert Uytterhoeven
 wrote:
> Currently, the IPMMU/VMSA driver supports 32-bit I/O Virtual Addresses
> only, and thus sets io_pgtable_cfg.ias = 32.  However, it doesn't force
> a 32-bit IOVA space through the IOMMU Domain Geometry.
>
> Hence if a device (e.g. SYS-DMAC) rightfully configures a 40-bit DMA
> mask, it will still be handed out a 40-bit IOVA, outside the 32-bit IOVA
> space, leading to out-of-bounds accesses of the PGD when mapping the
> IOVA.
>
> Force a 32-bit IOMMU Domain Geometry to fix this.

Nice, thanks!

> Signed-off-by: Geert Uytterhoeven 
> ---
> Should the generic code restrict the geometry based on IAS instead?

Might make sense. Since this is a software policy limited by hardware
it might be good to use as small IOVA space as possible to improve
performance. So selecting IOVA space based on slave device or domain
policy or something similar might be a good thing to do. Not sure how
to tie that into the IOMMU subsystem though...

Thanks!

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


Re: [PATCH/RFC 3/4] iommu: dma: iommu iova domain reset

2017-01-25 Thread Magnus Damm
Hi Robin, Shimoda-san, everyone,

Thanks for your feedback!

On Thu, Jan 26, 2017 at 1:38 AM, Robin Murphy <robin.mur...@arm.com> wrote:
> On 25/01/17 12:54, Yoshihiro Shimoda wrote:
>> From: Magnus Damm <damm+rene...@opensource.se>
>>
>> To add a workaround code for ipmmu-vmsa driver, this patch adds
>> a new geometry "force_reset_when_empty" not to reuse iova space.
>
> The domain geometry is absolutely not the appropriate place for that. If
> anything, it could possibly be a domain attribute, but it has nothing to
> do with describing the range of input addresses the hardware is able to
> translate.

I agree, this flag was added without too much consideration about
correct location.

>> When all pfns happen to get unmapped then ask the IOMMU driver to
>> flush the state followed by starting from an empty iova space.
>
> And what happens if all the PFNs are never unmapped? Many devices (USB
> being among them) use a coherent allocation for some kind of descriptor
> buffer which exists for the lifetime of the device, then use streaming
> mappings for data transfers - the net result of that is that the number
> of PFNs mapped will always be >=1, and eventually streaming mapping will
> fail because you've exhausted the address space. And if the device *is*
> a USB controller, at that point the thread will hang because the USB
> core's response to a DMA mapping failure happens to be "keep trying
> indefinitely".

You are absolutely right. My apologies for not providing more
information in the first place.

Like you mention, the workaround can not be made into something
general purpose, however for some restricted use case it might be
helpful. For instance, we have some MMC controllers that are able to
perform on-chip bus mastering but they lack scatter gather support.
>From the hardware design point of view the scatter gather feature was
decided to be put into the IPMMU hardware. Because of that we would
like to use the IPMMU hardware for this purpose, however with some ES
specific errata we need to handle unmapping in a special way.
Fortunately the MMC controllers are grouped together using the same
IPMMU and we are able to make sure that all the buffers are unmapped
now and then from a workaround in the MMC device driver. Not pretty
but not super intrusive.

> Essentially, however long this allocation workaround postpones it, one
> or other failure mode is unavoidable with certain devices unless you can
> do something drastic like periodically suspend and resume the entire
> system to reset everything.

Yeah, suspend/resume or unbind/bind might work.

>> Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
>> Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda...@renesas.com>
>> ---
>>  drivers/iommu/dma-iommu.c | 42 +-
>>  drivers/iommu/iova.c  |  9 +
>>  include/linux/iommu.h |  2 ++
>>  include/linux/iova.h  |  1 +
>>  4 files changed, 49 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
>> index a0b8c0f..d0fa0b1 100644
>> --- a/drivers/iommu/dma-iommu.c
>> +++ b/drivers/iommu/dma-iommu.c
>> @@ -42,6 +42,7 @@ struct iommu_dma_cookie {
>>   struct iova_domain  iovad;
>>   struct list_headmsi_page_list;
>>   spinlock_t  msi_lock;
>> + spinlock_t  reset_lock;
>
> So now we do get something in the cookie, but it's protecting a bunch of
> machinery that's accessible from a wider scope? That doesn't seem like a
> good design.

It's not. =)

There is room for improvement in the implementation for sure! We also
had other ideas of tracking mapped pages per device instead of per
domain. We have other requirements from the hardware to serialize some
MMC data handling, so grouping the MMC devices together into a single
IOMMU domain seemed light weight and simple for a first shot!

>>  };
>>
>>  static inline struct iova_domain *cookie_iovad(struct iommu_domain *domain)
>> @@ -74,6 +75,7 @@ int iommu_get_dma_cookie(struct iommu_domain *domain)
>>
>>   spin_lock_init(>msi_lock);
>>   INIT_LIST_HEAD(>msi_page_list);
>> + spin_lock_init(>reset_lock);
>>   domain->iova_cookie = cookie;
>>   return 0;
>>  }
>> @@ -208,9 +210,11 @@ int dma_direction_to_prot(enum dma_data_direction dir, 
>> bool coherent)
>>  static struct iova *__alloc_iova(struct iommu_domain *domain, size_t size,
>>   dma_addr_t dma_limit)
>>  {
>> + struct iommu_dma_cookie *cookie = domain->iova_cookie;
>>   struct iova_domain *iovad = cookie_iovad(domain);
>

Re: [PATCH/RFC 1/4] iommu: dma: track mapped iova

2017-01-25 Thread Magnus Damm
Hi Robin, Shimoda-san, everyone,

On Thu, Jan 26, 2017 at 1:27 AM, Robin Murphy <robin.mur...@arm.com> wrote:
> On 25/01/17 12:53, Yoshihiro Shimoda wrote:
>> From: Magnus Damm <damm+rene...@opensource.se>
>>
>> To track mapped iova for a workaround code in the future.
>>
>> Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
>> Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda...@renesas.com>
>> ---
>>  drivers/iommu/dma-iommu.c | 29 +++--
>>  include/linux/iommu.h |  2 ++
>
> So what's being added here is a counter of allocations within the
> iova_domain held by an iommu_dma_cookie? Then why is it all the way down
> in the iommu_domain and not in the cookie? That's needlessly invasive -
> it would be almost understandable (but still horrible) if you needed to
> refer to it directly from the IOMMU driver, but as far as I can see you
> don't.

You are very correct about all points. =)

As you noticed, the counter is kept per-domain. History is a bit
blurry but I think the reason for my abstraction-breaking is that i
decided to implement the simplest possible code to get the reset
callback to near the iova code and the domain level seemed suitable as
a first step. Moving it to a different level is of course no problem.

My main concern for this series is however if a subsystem-level
intrusive workaround like this ever could be beaten into acceptable
form for upstream merge.The code is pretty simple - the main portion
of the workaround is this counter that used to detect when the number
of mapped pages drops back to zero together with the callback. But
unless the code can be made pluggable it introduces overhead for all
users.

In your other email you asked what happens if the counter never drops
to zero. You are right that this workaround is not a general-purpose
fix suitable for all kinds of devices. Because of that the workaround
is designed to be enabled on only some of the IPMMU instances on the
system. It is also most likely an errata workaround for a particular
ES version, so we would most likely have to enable it with
soc_device_match().

I'll reply to patch 3/4 with some more details.

Thanks!

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


Re: [PATCH/RFC 1/2] arm64: mm: Silently allow devices lacking IOMMU group

2017-01-25 Thread Magnus Damm
Hi Robin,

On Mon, Jan 23, 2017 at 9:34 PM, Robin Murphy <robin.mur...@arm.com> wrote:
> Hi Magnus,
>
> On 23/01/17 12:12, Magnus Damm wrote:
>> From: Magnus Damm <damm+rene...@opensource.se>
>>
>> Consider failure of iommu_get_domain_for_dev() as non-critical and
>> get rid of the warning printout. This allows IOMMU properties to be
>> included in the DTB even though the kernel is configured with
>> CONFIG_IOMMU_API=n or in case a particular IOMMU driver refuses to
>> enable IOMMU support for a certain slave device and returns error
>> from the ->add_device() callback.
>>
>> This is only a cosmetic change that removes console warning printouts.
>
> The warning is there for a reason - at this point, we *expected* the
> device to be using an IOMMU for DMA, so a failure is significant. Rather
> than masking genuine failures in other cases because your case
> deliberately breaks that expectation, simply change the expectation -
> i.e. rather than letting of_xlate() succeed then failing add_device()
> later, reject the of_xlate() call up-front such that the DMA layer never
> gets told about the IOMMU in the first place.

Thanks for pointing me in the right direction! I will try to handle
this in xlate() instead.

Cheers,

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


Re: [PATCH/RFC 2/2] iommu/ipmmu-vmsa: Opt-in slave devices based on ES version

2017-01-24 Thread Magnus Damm
Hi Geert,

On Mon, Jan 23, 2017 at 9:50 PM, Geert Uytterhoeven
<ge...@linux-m68k.org> wrote:
> Hi Magnus,
>
> On Mon, Jan 23, 2017 at 1:12 PM, Magnus Damm <magnus.d...@gmail.com> wrote:
>> From: Magnus Damm <damm+rene...@opensource.se>
>>
>> Match on r8a7795 ES2 and enable a certain DMA controller.
>> In other cases the IPMMU driver remains disabled.
>>
>> Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
>> ---
>>
>>  drivers/iommu/ipmmu-vmsa.c |   24 
>>  1 file changed, 24 insertions(+)
>>
>> --- 0001/drivers/iommu/ipmmu-vmsa.c
>> +++ work/drivers/iommu/ipmmu-vmsa.c 2017-01-23 20:57:02.620607110 +0900
>> @@ -23,6 +23,7 @@
>>  #include 
>>  #include 
>>  #include 
>> +#include 
>>
>>  #if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
>>  #include 
>> @@ -1002,16 +1003,39 @@ static void ipmmu_domain_free_dma(struct
>> }
>>  }
>>
>> +static const struct soc_device_attribute r8a7795es2[] = {
>> +   { .soc_id = "r8a7795", .revision = "ES2.*" },
>> +   { /* sentinel */ }
>> +};
>> +
>> +static int ipmmu_slave_whitelist(struct device *dev)
>> +{
>> +   /* Opt-in slave devices based on SoC and ES version */
>> +   if (soc_device_match(r8a7795es2)) {
>> +   if (!strcmp(dev_name(dev), "e731.dma-controller"))
>> +   return 0;
>> +   }
>
> I have two comments about the construct above:
>   1. IPMMU will be disabled on all non-r8a7795 SoCs.
>  Is that what you want?

Sort of. This patch is just an example to stir up some discussion
about this topic. I realize this code as-is changes R-Car Gen2
behavior (that is merged upstream) so perhaps we should keep devices
enabled for those SoCs.

>   2. Usually we match on the old broken versions instead (e.g. against
>  "ES1.*"), as (1) it marks more clearly support for old SoCs, and
> (2) it makes it easier to remove the check later when these
> old SoCs are deemed extinct later.

Right, if I understand correctly then you're saying opt-out might be
better instead of opt-in. In case of IPMMU and R-Car Gen3 I believe it
might be less work to use opt-in rather than excluding not-yet-working
stuff. =)

With this series I would like to propose to disconnect the DT
integration timing from the enablement of IPMMU support for slave
devices. If we can enable the IPMMU in DT early on we can reduce
potential out-of-tree IPMMU enablement DT patches. So with the DT
bindings fixed and accurate data sheet we can merge DT bits ahead of
enablement time. And then use run time logic to determine what to
enable based on test results.

As you are aware, currently we have used the presence of "iommus" in
DT to determine if a device is going to be enabled or not. So if the
IPMMU Kconfig bits enable the IPMMU driver and the "iommus" DT
property tie a certain slave device to the IPMMU then we will make use
of IPMMU for a certain device. Currently we assume it will work on all
ES versions that use that particular DTB.

However ES specific hardware errata together with a wide range of ES
versions for r8a7795 and r8a7796 (and whatever SoCs and ES versions
that comes next) makes it difficult to use DT like above to enable
stuff seemingly on one ES version without potentially breaking other
ES versions. I would like to share DT files between the ES versions as
much as possible but still only enable IPMMU support for devices that
are known to work.

Let me know if you think it makes sense to enable DT in a different
way than my proposal.

I'll have a look at putting the white list code in ->xlate() instead
of ->add_device().

Thanks for your comments!

Cheers,

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


[PATCH/RFC 2/2] iommu/ipmmu-vmsa: Opt-in slave devices based on ES version

2017-01-23 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Match on r8a7795 ES2 and enable a certain DMA controller.
In other cases the IPMMU driver remains disabled.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 drivers/iommu/ipmmu-vmsa.c |   24 
 1 file changed, 24 insertions(+)

--- 0001/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-01-23 20:57:02.620607110 +0900
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
 #include 
@@ -1002,16 +1003,39 @@ static void ipmmu_domain_free_dma(struct
}
 }
 
+static const struct soc_device_attribute r8a7795es2[] = {
+   { .soc_id = "r8a7795", .revision = "ES2.*" },
+   { /* sentinel */ }
+};
+
+static int ipmmu_slave_whitelist(struct device *dev)
+{
+   /* Opt-in slave devices based on SoC and ES version */
+   if (soc_device_match(r8a7795es2)) {
+   if (!strcmp(dev_name(dev), "e731.dma-controller"))
+   return 0;
+   }
+
+   /* By default, do not allow use of IPMMU */
+   return -ENODEV;
+}
+
 static int ipmmu_add_device_dma(struct device *dev)
 {
struct ipmmu_vmsa_archdata *archdata = dev->archdata.iommu;
struct iommu_group *group;
+   int ret;
 
/* only accept devices with iommus property */
if (of_count_phandle_with_args(dev->of_node, "iommus",
   "#iommu-cells") < 0)
return -ENODEV;
 
+   /* opt-in devices based on SoC and ES version */
+   ret = ipmmu_slave_whitelist(dev);
+   if (ret)
+   return ret;
+
group = iommu_group_get_for_dev(dev);
if (IS_ERR(group))
return PTR_ERR(group);
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH/RFC 1/2] arm64: mm: Silently allow devices lacking IOMMU group

2017-01-23 Thread Magnus Damm
From: Magnus Damm <damm+rene...@opensource.se>

Consider failure of iommu_get_domain_for_dev() as non-critical and
get rid of the warning printout. This allows IOMMU properties to be
included in the DTB even though the kernel is configured with
CONFIG_IOMMU_API=n or in case a particular IOMMU driver refuses to
enable IOMMU support for a certain slave device and returns error
from the ->add_device() callback.

This is only a cosmetic change that removes console warning printouts.

Signed-off-by: Magnus Damm <damm+rene...@opensource.se>
---

 arch/arm64/mm/dma-mapping.c |   10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

--- 0001/arch/arm64/mm/dma-mapping.c
+++ work/arch/arm64/mm/dma-mapping.c2017-01-23 20:54:40.060607110 +0900
@@ -827,11 +827,19 @@ static bool do_iommu_attach(struct devic
struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
 
/*
+* In case IOMMU support is excluded from the kernel or if the device
+* is not hooked up to any IOMMU group then be silent and keep the
+* old dma_ops.
+*/
+   if (!domain)
+   return false;
+
+   /*
 * If the IOMMU driver has the DMA domain support that we require,
 * then the IOMMU core will have already configured a group for this
 * device, and allocated the default domain for that group.
 */
-   if (!domain || iommu_dma_init_domain(domain, dma_base, size, dev)) {
+   if (iommu_dma_init_domain(domain, dma_base, size, dev)) {
pr_warn("Failed to set up IOMMU for device %s; retaining 
platform DMA ops\n",
dev_name(dev));
return false;
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


  1   2   3   >