Re: [PATCH 04/10] iommu: Add sysfs bindings for struct iommu_device

2017-02-03 Thread kbuild test robot
Hi Joerg,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.10-rc6]
[cannot apply to iommu/next next-20170203]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Joerg-Roedel/Let-IOMMU-core-know-about-individual-IOMMUs/20170203-232949
config: x86_64-randconfig-h0-02040037 (attached as .config)
compiler: gcc-4.9 (Debian 4.9.4-2) 4.9.4
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64 

All errors (new ones prefixed by >>):

   In file included from drivers/iommu/dmar.c:34:0:
   include/linux/intel-iommu.h:443:22: error: field 'iommu' has incomplete type
 struct iommu_device iommu;  /* IOMMU core code handle */
 ^
   drivers/iommu/dmar.c: In function 'alloc_iommu':
>> drivers/iommu/dmar.c:1083:3: error: implicit declaration of function 
>> 'iommu_device_sysfs_add' [-Werror=implicit-function-declaration]
  err = iommu_device_sysfs_add(&iommu->iommu, NULL,
  ^
   drivers/iommu/dmar.c:1091:3: error: implicit declaration of function 
'iommu_device_register' [-Werror=implicit-function-declaration]
  err = iommu_device_register(&iommu->iommu);
  ^
   drivers/iommu/dmar.c: In function 'free_iommu':
>> drivers/iommu/dmar.c::2: error: implicit declaration of function 
>> 'iommu_device_sysfs_remove' [-Werror=implicit-function-declaration]
 iommu_device_sysfs_remove(&iommu->iommu);
 ^
   drivers/iommu/dmar.c:1112:2: error: implicit declaration of function 
'iommu_device_unregister' [-Werror=implicit-function-declaration]
 iommu_device_unregister(&iommu->iommu);
 ^
   cc1: some warnings being treated as errors

vim +/iommu_device_sysfs_add +1083 drivers/iommu/dmar.c

  1077  if (sts & DMA_GSTS_QIES)
  1078  iommu->gcmd |= DMA_GCMD_QIE;
  1079  
  1080  raw_spin_lock_init(&iommu->register_lock);
  1081  
  1082  if (intel_iommu_enabled) {
> 1083  err = iommu_device_sysfs_add(&iommu->iommu, NULL,
  1084   intel_iommu_groups,
  1085   "%s", iommu->name);
  1086  if (err)
  1087  goto err_unmap;
  1088  
  1089  iommu->iommu.ops = &intel_iommu_ops;
  1090  
  1091  err = iommu_device_register(&iommu->iommu);
  1092  if (err)
  1093  goto err_unmap;
  1094  }
  1095  
  1096  drhd->iommu = iommu;
  1097  
  1098  return 0;
  1099  
  1100  err_unmap:
  1101  unmap_iommu(iommu);
  1102  error_free_seq_id:
  1103  dmar_free_seq_id(iommu);
  1104  error:
  1105  kfree(iommu);
  1106  return err;
  1107  }
  1108  
  1109  static void free_iommu(struct intel_iommu *iommu)
  1110  {
>   iommu_device_sysfs_remove(&iommu->iommu);
  1112  iommu_device_unregister(&iommu->iommu);
  1113  
  1114  if (iommu->irq) {

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [PATCH 03/10] iommu: Introduce new 'struct iommu_device'

2017-02-03 Thread kbuild test robot
Hi Joerg,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.10-rc6]
[cannot apply to iommu/next next-20170203]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Joerg-Roedel/Let-IOMMU-core-know-about-individual-IOMMUs/20170203-232949
config: x86_64-randconfig-h0-02040037 (attached as .config)
compiler: gcc-4.9 (Debian 4.9.4-2) 4.9.4
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64 

All errors (new ones prefixed by >>):

   In file included from drivers/iommu/dmar.c:34:0:
   include/linux/intel-iommu.h:444:22: error: field 'iommu' has incomplete type
 struct iommu_device iommu;  /* IOMMU core code handle */
 ^
   drivers/iommu/dmar.c: In function 'alloc_iommu':
>> drivers/iommu/dmar.c:1094:3: error: implicit declaration of function 
>> 'iommu_device_register' [-Werror=implicit-function-declaration]
  err = iommu_device_register(&iommu->iommu);
  ^
   drivers/iommu/dmar.c: In function 'free_iommu':
>> drivers/iommu/dmar.c:1115:2: error: implicit declaration of function 
>> 'iommu_device_unregister' [-Werror=implicit-function-declaration]
 iommu_device_unregister(&iommu->iommu);
 ^
   cc1: some warnings being treated as errors

vim +/iommu_device_register +1094 drivers/iommu/dmar.c

  1088  err = PTR_ERR(iommu->iommu_dev);
  1089  goto err_unmap;
  1090  }
  1091  
  1092  iommu->iommu.ops = &intel_iommu_ops;
  1093  
> 1094  err = iommu_device_register(&iommu->iommu);
  1095  if (err)
  1096  goto err_unmap;
  1097  }
  1098  
  1099  drhd->iommu = iommu;
  1100  
  1101  return 0;
  1102  
  1103  err_unmap:
  1104  unmap_iommu(iommu);
  1105  error_free_seq_id:
  1106  dmar_free_seq_id(iommu);
  1107  error:
  1108  kfree(iommu);
  1109  return err;
  1110  }
    
  1112  static void free_iommu(struct intel_iommu *iommu)
  1113  {
  1114  iommu_device_destroy(iommu->iommu_dev);
> 1115  iommu_device_unregister(&iommu->iommu);
  1116  
  1117  if (iommu->irq) {
  1118  if (iommu->pr_irq) {

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [PATCH V8 08/11] drivers: acpi: Handle IOMMU lookup failure with deferred probing or error

2017-02-03 Thread Robin Murphy
On 03/02/17 16:15, Sricharan wrote:
> Hi Lorenzo, Robin,
> 
>> -Original Message-
>> From: linux-arm-kernel [mailto:linux-arm-kernel-boun...@lists.infradead.org] 
>> On Behalf Of Sricharan R
>> Sent: Friday, February 03, 2017 9:19 PM
>> To: robin.mur...@arm.com; will.dea...@arm.com; j...@8bytes.org; 
>> lorenzo.pieral...@arm.com; iommu@lists.linux-foundation.org;
>> linux-arm-ker...@lists.infradead.org; linux-arm-...@vger.kernel.org; 
>> m.szyprow...@samsung.com; bhelg...@google.com; linux-
>> p...@vger.kernel.org; linux-a...@vger.kernel.org; t...@semihalf.com; 
>> hanjun@linaro.org; ok...@codeaurora.org
>> Cc: sricha...@codeaurora.org
>> Subject: [PATCH V8 08/11] drivers: acpi: Handle IOMMU lookup failure with 
>> deferred probing or error
>>
>> This is an equivalent to the DT's handling of the iommu master's probe
>> with deferred probing when the corrsponding iommu is not probed yet.
>> 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 firmware 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: Hanjun Guo 
>> Acked-by: Lorenzo Pieralisi 
>> Signed-off-by: Sricharan R 
>> ---
>> drivers/acpi/arm64/iort.c  | 25 -
>> drivers/acpi/scan.c|  7 +--
>> drivers/base/dma-mapping.c |  2 +-
>> include/acpi/acpi_bus.h|  2 +-
>> include/linux/acpi.h   |  7 +--
>> 5 files changed, 36 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
>> index bf0ed09..d01bae8 100644
>> --- a/drivers/acpi/arm64/iort.c
>> +++ b/drivers/acpi/arm64/iort.c
>> @@ -550,8 +550,17 @@ static const struct iommu_ops *iort_iommu_xlate(struct 
>> device *dev,
>>  return NULL;
>>
>>  ops = iommu_get_instance(iort_fwnode);
>> +/*
>> + * If the ops look-up fails, this means that either
>> + * the SMMU drivers have not been probed yet or that
>> + * the SMMU drivers are not built in the kernel;
>> + * Depending on whether the SMMU drivers are built-in
>> + * in the kernel or not, defer the IOMMU configuration
>> + * or just abort it.
>> + */
>>  if (!ops)
>> -return NULL;
>> +return iort_iommu_driver_enabled(node->type) ?
>> +   ERR_PTR(-EPROBE_DEFER) : NULL;
>>
>>  ret = arm_smmu_iort_xlate(dev, streamid, iort_fwnode, ops);
>>  }
>> @@ -625,12 +634,26 @@ const struct iommu_ops *iort_iommu_configure(struct 
>> device *dev)
>>
>>  while (parent) {
>>  ops = iort_iommu_xlate(dev, parent, streamid);
>> +if (IS_ERR_OR_NULL(ops))
>> +return ops;
>>
>>  parent = iort_node_get_id(node, &streamid,
>>IORT_IOMMU_TYPE, i++);
>>  }
>>  }
>>
>> +/*
>> + * If we have reason to believe the IOMMU driver missed the initial
>> + * add_device callback for dev, replay it to get things in order.
>> + */
>> +if (!IS_ERR_OR_NULL(ops) && ops->add_device &&
>> +dev->bus && !dev->iommu_group) {
>> +int err = ops->add_device(dev);
>> +
>> +if (err)
>> +ops = ERR_PTR(err);
>> +}
>> +
> 
> On the last post we discussed that the above replay hunk can be made
> common. In trying to do that, i ended up with a patch like below. But not
> sure if that should be a part of this series though. I tested with OF devices
> and would have to be tested with ACPI devices once. Nothing changes
> functionally because of this ideally. Should be split in two patches though.
> 
> Regards,
>  Sricharan
> 
> From aafbf2c97375a086327504f2367eaf9197c719b1 Mon Sep 17 00:00:00 2001
> From: Sricharan R 
> Date: Fri, 3 Feb 2017 15:24:47 +0530
> Subject: [PATCH] drivers: iommu: Add iommu_add_device api
> 
> The code to call IOMMU driver's add_device is same
> for both OF and ACPI cases. So add an api which can
> be shared across both the places.
> 
> Also, now with probe-deferral the iommu master devices gets
> added to the respective iommus during 

RE: [PATCH 0/5] Implement SMMU passthrough using the default domain

2017-02-03 Thread Sricharan
Hi Will, Rob,

>-Original Message-
>From: linux-arm-kernel [mailto:linux-arm-kernel-boun...@lists.infradead.org] 
>On Behalf Of Will Deacon
>Sent: Thursday, February 02, 2017 9:41 PM
>To: Sricharan 
>Cc: linux-arm-ker...@lists.infradead.org; 'Rob Clark' ; 
>'Joerg Roedel' ; iommu@lists.linux-
>foundation.org
>Subject: Re: [PATCH 0/5] Implement SMMU passthrough using the default domain
>
>On Thu, Feb 02, 2017 at 09:15:19PM +0530, Sricharan wrote:
>> Hi Rob,
>>
>> >-Original Message-
>> >From: linux-arm-kernel 
>> >[mailto:linux-arm-kernel-boun...@lists.infradead.org] On Behalf Of Rob Clark
>> >Sent: Thursday, February 02, 2017 8:33 PM
>> >To: Joerg Roedel 
>> >Cc: Will Deacon ; iommu@lists.linux-foundation.org; 
>> >Sricharan ; linux-arm-
>> >ker...@lists.infradead.org
>> >Subject: Re: [PATCH 0/5] Implement SMMU passthrough using the default domain
>> >
>> >On Thu, Jan 26, 2017 at 12:18 PM, Joerg Roedel  wrote:
>> >> On Tue, Jan 24, 2017 at 08:42:23PM +0530, Sricharan wrote:
>> >>> Thanks for this series. We had a case with the GPU.
>> >>> The GPU's iommu was setup by kernel and the GPU
>> >>> also does dynamic updates for on-the-fly switching between
>> >>> process pagetables.  GPU driver was not using DMA domain and
>> >>> the GPU's firmware was always expecting to run out  of contextbank
>> >>>  '0' (although not correct) , which was not the case after the DMA domain
>> >>> was made default  as '0' was getting allocated for DMA domain and
>> >>> there were concerns about reusing the DMA domain as well.
>> >>> Now with this series, looks there is an way out of that that can be 
>> >>> tried.
>> >>>
>> >>> So should the default domain not be per device specific selectable ?
>> >>
>> >> Note that iommu-drivers can request direct-mapping for any given device
>> >> on its initializtion. This is used on x86 for devices that need a 1-1
>> >> mapping for some reason.
>> >>
>> >> Also device drivers can use the iommu-api and assign their own domain to
>> >> a device, which allows them to manage the dma address space on their
>> >> own.
>> >
>> >Part of the problem is that dev->archdata.dma_ops gets wired up to
>> >iommu_dma_ops.  Which isn't so bad on it's own, except that cache ops
>> >are not exposed to drivers, forcing us to use dma-mapping API
>> >(dma_map_sg, etc) for cache operations.
>> >
>> >Possibly we should just expose cache op's to drivers bypass this abuse
>> >of dma-mapping.
>> >
>> [1], with this, when the default domain in not DOMAIN_DMA, then
>> dev->archdata.dma_ops is not set to iommu_dma_ops , instead remains
>> to be swiotlb_ops. Is that not correct for gpu's unmanaged domain case ?
>>
>> https://www.spinics.net/lists/arm-kernel/msg556209.html
>>
>> >btw, Will, we definitely want this to *not* rely on kcmdline for the
>> >gpu with it's own private iommu case..
>>
>> Ya, that changes behavior for all devices and some might want
>> DMA_DOMAIN and some UNMANAGED.
>
>My patch changes the *default* domain. When would this ever be UNMANAGED?
>
>If you're using an UNMANAGED domain, I think you need to take care of the
>DMA ops yourself. There are likely missing functions to do that, but they
>should be added in a separate series.

Sorry, i should have said DOMAIN_DMA or DOMAIN_IDENTITY is set as
*default* domains from your patchset. So i have not tested this series
yet. But the requirement that i thought for the gpu was
* a context bank (specially '0') should not be reserved for DOMAIN_DMA
   * dma_ops should not be set to iommu_dma_ops for the gpu device.

I was seeing that both of that are satisfied in this series, if we choose
IDENTITY_DOMAIN as default and later gpu attaches it own
*UNMANAGED* domain.

The only thing i was thinking was, since we are changing the default domain
for all device from command line, some device which require DOMAIN_DMA
and some which require DOMAIN_IDENTITY as default was not possible.

Regards,
 Sricharan


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


RE: [PATCH V8 08/11] drivers: acpi: Handle IOMMU lookup failure with deferred probing or error

2017-02-03 Thread Sricharan
Hi Lorenzo, Robin,

>-Original Message-
>From: linux-arm-kernel [mailto:linux-arm-kernel-boun...@lists.infradead.org] 
>On Behalf Of Sricharan R
>Sent: Friday, February 03, 2017 9:19 PM
>To: robin.mur...@arm.com; will.dea...@arm.com; j...@8bytes.org; 
>lorenzo.pieral...@arm.com; iommu@lists.linux-foundation.org;
>linux-arm-ker...@lists.infradead.org; linux-arm-...@vger.kernel.org; 
>m.szyprow...@samsung.com; bhelg...@google.com; linux-
>p...@vger.kernel.org; linux-a...@vger.kernel.org; t...@semihalf.com; 
>hanjun@linaro.org; ok...@codeaurora.org
>Cc: sricha...@codeaurora.org
>Subject: [PATCH V8 08/11] drivers: acpi: Handle IOMMU lookup failure with 
>deferred probing or error
>
>This is an equivalent to the DT's handling of the iommu master's probe
>with deferred probing when the corrsponding iommu is not probed yet.
>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 firmware 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: Hanjun Guo 
>Acked-by: Lorenzo Pieralisi 
>Signed-off-by: Sricharan R 
>---
> drivers/acpi/arm64/iort.c  | 25 -
> drivers/acpi/scan.c|  7 +--
> drivers/base/dma-mapping.c |  2 +-
> include/acpi/acpi_bus.h|  2 +-
> include/linux/acpi.h   |  7 +--
> 5 files changed, 36 insertions(+), 7 deletions(-)
>
>diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
>index bf0ed09..d01bae8 100644
>--- a/drivers/acpi/arm64/iort.c
>+++ b/drivers/acpi/arm64/iort.c
>@@ -550,8 +550,17 @@ static const struct iommu_ops *iort_iommu_xlate(struct 
>device *dev,
>   return NULL;
>
>   ops = iommu_get_instance(iort_fwnode);
>+  /*
>+   * If the ops look-up fails, this means that either
>+   * the SMMU drivers have not been probed yet or that
>+   * the SMMU drivers are not built in the kernel;
>+   * Depending on whether the SMMU drivers are built-in
>+   * in the kernel or not, defer the IOMMU configuration
>+   * or just abort it.
>+   */
>   if (!ops)
>-  return NULL;
>+  return iort_iommu_driver_enabled(node->type) ?
>+ ERR_PTR(-EPROBE_DEFER) : NULL;
>
>   ret = arm_smmu_iort_xlate(dev, streamid, iort_fwnode, ops);
>   }
>@@ -625,12 +634,26 @@ const struct iommu_ops *iort_iommu_configure(struct 
>device *dev)
>
>   while (parent) {
>   ops = iort_iommu_xlate(dev, parent, streamid);
>+  if (IS_ERR_OR_NULL(ops))
>+  return ops;
>
>   parent = iort_node_get_id(node, &streamid,
> IORT_IOMMU_TYPE, i++);
>   }
>   }
>
>+  /*
>+   * If we have reason to believe the IOMMU driver missed the initial
>+   * add_device callback for dev, replay it to get things in order.
>+   */
>+  if (!IS_ERR_OR_NULL(ops) && ops->add_device &&
>+  dev->bus && !dev->iommu_group) {
>+  int err = ops->add_device(dev);
>+
>+  if (err)
>+  ops = ERR_PTR(err);
>+  }
>+

On the last post we discussed that the above replay hunk can be made
common. In trying to do that, i ended up with a patch like below. But not
sure if that should be a part of this series though. I tested with OF devices
and would have to be tested with ACPI devices once. Nothing changes
functionally because of this ideally. Should be split in two patches though.

Regards,
 Sricharan

>From aafbf2c97375a086327504f2367eaf9197c719b1 Mon Sep 17 00:00:00 2001
From: Sricharan R 
Date: Fri, 3 Feb 2017 15:24:47 +0530
Subject: [PATCH] drivers: iommu: Add iommu_add_device api

The code to call IOMMU driver's add_device is same
for both OF and ACPI cases. So add an api which can
be shared across both the places.

Also, now with probe-deferral the iommu master devices gets
added to the respective iommus during probe time instead
of device creation time. The xlate callbacks of iommu
drivers are also called only at probe time. As a result
the add_iommu_group which gets called when the iommu is

Re: [PATCH 03/10] iommu: Introduce new 'struct iommu_device'

2017-02-03 Thread kbuild test robot
Hi Joerg,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.10-rc6]
[cannot apply to iommu/next next-20170203]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Joerg-Roedel/Let-IOMMU-core-know-about-individual-IOMMUs/20170203-232949
config: i386-defconfig (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=i386 

All errors (new ones prefixed by >>):

   In file included from drivers/gpu/drm/i915/i915_drv.h:41:0,
from drivers/gpu/drm/i915/i915_drv.c:48:
>> include/linux/intel-iommu.h:444:22: error: field 'iommu' has incomplete type
 struct iommu_device iommu;  /* IOMMU core code handle */
 ^

vim +/iommu +444 include/linux/intel-iommu.h

   438  #ifdef CONFIG_IRQ_REMAP
   439  struct ir_table *ir_table;  /* Interrupt remapping info */
   440  struct irq_domain *ir_domain;
   441  struct irq_domain *ir_msi_domain;
   442  #endif
   443  struct device   *iommu_dev; /* IOMMU-sysfs device */
 > 444  struct iommu_device iommu;  /* IOMMU core code handle */
   445  int node;
   446  u32 flags;  /* Software defined flags */
   447  };

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH V8 10/11] iommu/arm-smmu: Clean up early-probing workarounds

2017-02-03 Thread Sricharan R
From: Robin Murphy 

Now that the appropriate ordering is enforced via probe-deferral of
masters in core code, rip it all out and bask in the simplicity.

Tested-by: Hanjun Guo 
Acked-by: Will Deacon 
Signed-off-by: Robin Murphy 
[Sricharan: Rebased on top of ACPI IORT SMMU series]
Signed-off-by: Sricharan R 
---
 drivers/iommu/arm-smmu-v3.c | 46 ++-
 drivers/iommu/arm-smmu.c| 58 +++--
 2 files changed, 10 insertions(+), 94 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 7bb157c..eba4ac8 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -2743,51 +2743,9 @@ static int arm_smmu_device_remove(struct platform_device 
*pdev)
.probe  = arm_smmu_device_probe,
.remove = arm_smmu_device_remove,
 };
+module_platform_driver(arm_smmu_driver);
 
-static int __init arm_smmu_init(void)
-{
-   static bool registered;
-   int ret = 0;
-
-   if (!registered) {
-   ret = platform_driver_register(&arm_smmu_driver);
-   registered = !ret;
-   }
-   return ret;
-}
-
-static void __exit arm_smmu_exit(void)
-{
-   return platform_driver_unregister(&arm_smmu_driver);
-}
-
-subsys_initcall(arm_smmu_init);
-module_exit(arm_smmu_exit);
-
-static int __init arm_smmu_of_init(struct device_node *np)
-{
-   int ret = arm_smmu_init();
-
-   if (ret)
-   return ret;
-
-   if (!of_platform_device_create(np, NULL, platform_bus_type.dev_root))
-   return -ENODEV;
-
-   return 0;
-}
-IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3", arm_smmu_of_init);
-
-#ifdef CONFIG_ACPI
-static int __init acpi_smmu_v3_init(struct acpi_table_header *table)
-{
-   if (iort_node_match(ACPI_IORT_NODE_SMMU_V3))
-   return arm_smmu_init();
-
-   return 0;
-}
-IORT_ACPI_DECLARE(arm_smmu_v3, ACPI_SIG_IORT, acpi_smmu_v3_init);
-#endif
+IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3", NULL);
 
 MODULE_DESCRIPTION("IOMMU API for ARM architected SMMUv3 implementations");
 MODULE_AUTHOR("Will Deacon ");
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 091d4a6..faea579 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -2190,56 +2190,14 @@ static int arm_smmu_device_remove(struct 
platform_device *pdev)
.probe  = arm_smmu_device_probe,
.remove = arm_smmu_device_remove,
 };
-
-static int __init arm_smmu_init(void)
-{
-   static bool registered;
-   int ret = 0;
-
-   if (!registered) {
-   ret = platform_driver_register(&arm_smmu_driver);
-   registered = !ret;
-   }
-   return ret;
-}
-
-static void __exit arm_smmu_exit(void)
-{
-   return platform_driver_unregister(&arm_smmu_driver);
-}
-
-subsys_initcall(arm_smmu_init);
-module_exit(arm_smmu_exit);
-
-static int __init arm_smmu_of_init(struct device_node *np)
-{
-   int ret = arm_smmu_init();
-
-   if (ret)
-   return ret;
-
-   if (!of_platform_device_create(np, NULL, platform_bus_type.dev_root))
-   return -ENODEV;
-
-   return 0;
-}
-IOMMU_OF_DECLARE(arm_smmuv1, "arm,smmu-v1", arm_smmu_of_init);
-IOMMU_OF_DECLARE(arm_smmuv2, "arm,smmu-v2", arm_smmu_of_init);
-IOMMU_OF_DECLARE(arm_mmu400, "arm,mmu-400", arm_smmu_of_init);
-IOMMU_OF_DECLARE(arm_mmu401, "arm,mmu-401", arm_smmu_of_init);
-IOMMU_OF_DECLARE(arm_mmu500, "arm,mmu-500", arm_smmu_of_init);
-IOMMU_OF_DECLARE(cavium_smmuv2, "cavium,smmu-v2", arm_smmu_of_init);
-
-#ifdef CONFIG_ACPI
-static int __init arm_smmu_acpi_init(struct acpi_table_header *table)
-{
-   if (iort_node_match(ACPI_IORT_NODE_SMMU))
-   return arm_smmu_init();
-
-   return 0;
-}
-IORT_ACPI_DECLARE(arm_smmu, ACPI_SIG_IORT, arm_smmu_acpi_init);
-#endif
+module_platform_driver(arm_smmu_driver);
+
+IOMMU_OF_DECLARE(arm_smmuv1, "arm,smmu-v1", NULL);
+IOMMU_OF_DECLARE(arm_smmuv2, "arm,smmu-v2", NULL);
+IOMMU_OF_DECLARE(arm_mmu400, "arm,mmu-400", NULL);
+IOMMU_OF_DECLARE(arm_mmu401, "arm,mmu-401", NULL);
+IOMMU_OF_DECLARE(arm_mmu500, "arm,mmu-500", NULL);
+IOMMU_OF_DECLARE(cavium_smmuv2, "cavium,smmu-v2", NULL);
 
 MODULE_DESCRIPTION("IOMMU API for ARM architected SMMU implementations");
 MODULE_AUTHOR("Will Deacon ");
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation

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


[PATCH V8 11/11] ACPI/IORT: Remove linker section for IORT entries probing

2017-02-03 Thread Sricharan R
From: Lorenzo Pieralisi 

The IORT linker section introduced by commit 34ceea275f62
("ACPI/IORT: Introduce linker section for IORT entries probing")
was needed to make sure SMMU drivers are registered (and therefore
probed) in the kernel before devices using the SMMU have a chance
to probe in turn.

Through the introduction of deferred IOMMU configuration the linker
section based IORT probing infrastructure is not needed any longer, in
that device/SMMU probe dependencies are managed through the probe
deferral mechanism, making the IORT linker section infrastructure
unused, so that it can be removed.

Remove the unused IORT linker section probing infrastructure
from the kernel to complete the ACPI IORT IOMMU configure probe
deferral mechanism implementation.

Tested-by: Hanjun Guo 
Signed-off-by: Lorenzo Pieralisi 
Cc: Robin Murphy 
Cc: Sricharan R 
---
 drivers/acpi/arm64/iort.c | 2 --
 include/asm-generic/vmlinux.lds.h | 1 -
 include/linux/acpi_iort.h | 3 ---
 3 files changed, 6 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index d01bae8..ac45623 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -992,6 +992,4 @@ void __init acpi_iort_init(void)
}
 
iort_init_platform_devices();
-
-   acpi_probe_device_table(iort);
 }
diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 4e09b28..93ea70a 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -567,7 +567,6 @@
IRQCHIP_OF_MATCH_TABLE()\
ACPI_PROBE_TABLE(irqchip)   \
ACPI_PROBE_TABLE(clksrc)\
-   ACPI_PROBE_TABLE(iort)  \
EARLYCON_TABLE()
 
 #define INIT_TEXT  \
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index 77e0809..f167e1d04 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -52,7 +52,4 @@ const struct iommu_ops *iort_iommu_configure(struct device 
*dev)
 { return NULL; }
 #endif
 
-#define IORT_ACPI_DECLARE(name, table_id, fn)  \
-   ACPI_DECLARE_PROBE_ENTRY(iort, name, table_id, 0, NULL, 0, fn)
-
 #endif /* __ACPI_IORT_H__ */
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation

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


[PATCH V8 09/11] arm64: dma-mapping: Remove the notifier trick to handle early setting of dma_ops

2017-02-03 Thread Sricharan R
With arch_setup_dma_ops now being called late during device's probe after
the device's IOMMU is probed, the notifier trick required to handle the
early setup of dma_ops before the IOMMU group gets created is not
required. So removing the notifiers here.

Tested-by: Marek Szyprowski 
Tested-by: Hanjun Guo 
Acked-by: Will Deacon 
Signed-off-by: Sricharan R 
[rm: clean up even more]
Signed-off-by: Robin Murphy 
---

[*] Rebased the series against linux-next. Please note that there is an
conflict while applying this patch against iommu-next because of the
patch [1] "arm64: dma-mapping: Only swizzle DMA ops for IOMMU_DOMAIN_DMA"
not there

[1] https://www.spinics.net/lists/arm-kernel/msg556209.html

 arch/arm64/mm/dma-mapping.c | 142 ++--
 1 file changed, 18 insertions(+), 124 deletions(-)

diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 6e295e8..3653c4c 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -814,34 +814,26 @@ static void __iommu_unmap_sg_attrs(struct device *dev,
.mapping_error = iommu_dma_mapping_error,
 };
 
-/*
- * TODO: Right now __iommu_setup_dma_ops() gets called too early to do
- * everything it needs to - the device is only partially created and the
- * IOMMU driver hasn't seen it yet, so it can't have a group. Thus we
- * need this delayed attachment dance. Once IOMMU probe ordering is sorted
- * to move the arch_setup_dma_ops() call later, all the notifier bits below
- * become unnecessary, and will go away.
- */
-struct iommu_dma_notifier_data {
-   struct list_head list;
-   struct device *dev;
-   const struct iommu_ops *ops;
-   u64 dma_base;
-   u64 size;
-};
-static LIST_HEAD(iommu_dma_masters);
-static DEFINE_MUTEX(iommu_dma_notifier_lock);
+static int __init __iommu_dma_init(void)
+{
+   return iommu_dma_init();
+}
+arch_initcall(__iommu_dma_init);
 
-static bool do_iommu_attach(struct device *dev, const struct iommu_ops *ops,
-  u64 dma_base, u64 size)
+static void __iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
+ const struct iommu_ops *ops)
 {
-   struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
+   struct iommu_domain *domain;
+
+   if (!ops)
+   return;
 
/*
-* 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.
+* The IOMMU core code allocates the default DMA domain, which the
+* underlying IOMMU driver needs to support via the dma-iommu layer.
 */
+   domain = iommu_get_domain_for_dev(dev);
+
if (!domain)
goto out_err;
 
@@ -852,109 +844,11 @@ static bool do_iommu_attach(struct device *dev, const 
struct iommu_ops *ops,
dev->archdata.dma_ops = &iommu_dma_ops;
}
 
-   return true;
+   return;
+
 out_err:
pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA 
ops\n",
-dev_name(dev));
-   return false;
-}
-
-static void queue_iommu_attach(struct device *dev, const struct iommu_ops *ops,
- u64 dma_base, u64 size)
-{
-   struct iommu_dma_notifier_data *iommudata;
-
-   iommudata = kzalloc(sizeof(*iommudata), GFP_KERNEL);
-   if (!iommudata)
-   return;
-
-   iommudata->dev = dev;
-   iommudata->ops = ops;
-   iommudata->dma_base = dma_base;
-   iommudata->size = size;
-
-   mutex_lock(&iommu_dma_notifier_lock);
-   list_add(&iommudata->list, &iommu_dma_masters);
-   mutex_unlock(&iommu_dma_notifier_lock);
-}
-
-static int __iommu_attach_notifier(struct notifier_block *nb,
-  unsigned long action, void *data)
-{
-   struct iommu_dma_notifier_data *master, *tmp;
-
-   if (action != BUS_NOTIFY_BIND_DRIVER)
-   return 0;
-
-   mutex_lock(&iommu_dma_notifier_lock);
-   list_for_each_entry_safe(master, tmp, &iommu_dma_masters, list) {
-   if (data == master->dev && do_iommu_attach(master->dev,
-   master->ops, master->dma_base, master->size)) {
-   list_del(&master->list);
-   kfree(master);
-   break;
-   }
-   }
-   mutex_unlock(&iommu_dma_notifier_lock);
-   return 0;
-}
-
-static int __init register_iommu_dma_ops_notifier(struct bus_type *bus)
-{
-   struct notifier_block *nb = kzalloc(sizeof(*nb), GFP_KERNEL);
-   int ret;
-
-   if (!nb)
-   return -ENOMEM;
-
-   nb->notifier_call = __iommu_attach_notifier;
-
-   ret = bus_register_notifier(bus, nb);
-   if (ret) {
-   pr_warn("Failed to register DMA domain notifier; IOMMU DMA o

[PATCH V8 08/11] drivers: acpi: Handle IOMMU lookup failure with deferred probing or error

2017-02-03 Thread Sricharan R
This is an equivalent to the DT's handling of the iommu master's probe
with deferred probing when the corrsponding iommu is not probed yet.
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 firmware 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: Hanjun Guo 
Acked-by: Lorenzo Pieralisi 
Signed-off-by: Sricharan R 
---
 drivers/acpi/arm64/iort.c  | 25 -
 drivers/acpi/scan.c|  7 +--
 drivers/base/dma-mapping.c |  2 +-
 include/acpi/acpi_bus.h|  2 +-
 include/linux/acpi.h   |  7 +--
 5 files changed, 36 insertions(+), 7 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index bf0ed09..d01bae8 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -550,8 +550,17 @@ static const struct iommu_ops *iort_iommu_xlate(struct 
device *dev,
return NULL;
 
ops = iommu_get_instance(iort_fwnode);
+   /*
+* If the ops look-up fails, this means that either
+* the SMMU drivers have not been probed yet or that
+* the SMMU drivers are not built in the kernel;
+* Depending on whether the SMMU drivers are built-in
+* in the kernel or not, defer the IOMMU configuration
+* or just abort it.
+*/
if (!ops)
-   return NULL;
+   return iort_iommu_driver_enabled(node->type) ?
+  ERR_PTR(-EPROBE_DEFER) : NULL;
 
ret = arm_smmu_iort_xlate(dev, streamid, iort_fwnode, ops);
}
@@ -625,12 +634,26 @@ const struct iommu_ops *iort_iommu_configure(struct 
device *dev)
 
while (parent) {
ops = iort_iommu_xlate(dev, parent, streamid);
+   if (IS_ERR_OR_NULL(ops))
+   return ops;
 
parent = iort_node_get_id(node, &streamid,
  IORT_IOMMU_TYPE, i++);
}
}
 
+   /*
+* If we have reason to believe the IOMMU driver missed the initial
+* add_device callback for dev, replay it to get things in order.
+*/
+   if (!IS_ERR_OR_NULL(ops) && ops->add_device &&
+   dev->bus && !dev->iommu_group) {
+   int err = ops->add_device(dev);
+
+   if (err)
+   ops = ERR_PTR(err);
+   }
+
return ops;
 }
 
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 1926918..823b005 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1373,20 +1373,23 @@ enum dev_dma_attr acpi_get_dma_attr(struct acpi_device 
*adev)
  * @dev: The pointer to the device
  * @attr: device dma attributes
  */
-void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
+int acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
 {
const struct iommu_ops *iommu;
 
iort_set_dma_mask(dev);
 
iommu = iort_iommu_configure(dev);
-
+   if (IS_ERR(iommu))
+   return PTR_ERR(iommu);
/*
 * Assume dma valid range starts at 0 and covers the whole
 * coherent_dma_mask.
 */
arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, iommu,
   attr == DEV_DMA_COHERENT);
+
+   return 0;
 }
 EXPORT_SYMBOL_GPL(acpi_dma_configure);
 
diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
index 82bd45c..755a2b5 100644
--- a/drivers/base/dma-mapping.c
+++ b/drivers/base/dma-mapping.c
@@ -368,7 +368,7 @@ int dma_configure(struct device *dev)
} else if (has_acpi_companion(dma_dev)) {
attr = acpi_get_dma_attr(to_acpi_device_node(dma_dev->fwnode));
if (attr != DEV_DMA_NOT_SUPPORTED)
-   acpi_dma_configure(dev, attr);
+   ret = acpi_dma_configure(dev, attr);
}
 
if (bridge)
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 4242c31..9aa762fe 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -573,7 +573,7 @@ struct acpi_pci_root {
 
 bool acpi_dma_supported(st

[PATCH V8 06/11] of/acpi: Configure dma operations at probe time for platform/amba/pci bus devices

2017-02-03 Thread Sricharan R
Configuring DMA ops at probe time will allow deferring device probe when
the IOMMU isn't available yet. The dma_configure for the device is
now called from the generic device_attach callback just before the
bus/driver probe is called. This way, configuring the DMA ops for the
device would be called at the same place for all bus_types, hence the
deferred probing mechanism should work for all buses as well.

pci_bus_add_devices(platform/amba)(_device_create/driver_register)
   | |
pci_bus_add_device (device_add/driver_register)
   | |
device_attach   device_initial_probe
   | |
__device_attach_driver__device_attach_driver
   |
driver_probe_device
   |
really_probe
   |
dma_configure

Similarly on the device/driver_unregister path __device_release_driver is
called which inturn calls dma_deconfigure.

This patch changes the dma ops configuration to probe time for
both OF and ACPI based platform/amba/pci bus devices.

Tested-by: Marek Szyprowski 
Tested-by: Hanjun Guo 
Acked-by: Bjorn Helgaas  (drivers/pci part)
Acked-by: Rafael J. Wysocki 
Signed-off-by: Sricharan R 
---
 drivers/acpi/glue.c |  5 -
 drivers/base/dd.c   |  9 +
 drivers/base/dma-mapping.c  | 40 
 drivers/of/platform.c   |  5 +
 drivers/pci/probe.c | 28 
 include/linux/dma-mapping.h |  3 +++
 6 files changed, 53 insertions(+), 37 deletions(-)

diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index fb19e1c..c05f241 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -176,7 +176,6 @@ int acpi_bind_one(struct device *dev, struct acpi_device 
*acpi_dev)
struct list_head *physnode_list;
unsigned int node_id;
int retval = -EINVAL;
-   enum dev_dma_attr attr;
 
if (has_acpi_companion(dev)) {
if (acpi_dev) {
@@ -233,10 +232,6 @@ int acpi_bind_one(struct device *dev, struct acpi_device 
*acpi_dev)
if (!has_acpi_companion(dev))
ACPI_COMPANION_SET(dev, acpi_dev);
 
-   attr = acpi_get_dma_attr(acpi_dev);
-   if (attr != DEV_DMA_NOT_SUPPORTED)
-   acpi_dma_configure(dev, attr);
-
acpi_physnode_link_name(physical_node_name, node_id);
retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
   physical_node_name);
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index a1fbf55..4882f06 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -19,6 +19,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -356,6 +357,10 @@ static int really_probe(struct device *dev, struct 
device_driver *drv)
if (ret)
goto pinctrl_bind_failed;
 
+   ret = dma_configure(dev);
+   if (ret)
+   goto dma_failed;
+
if (driver_sysfs_add(dev)) {
printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
__func__, dev_name(dev));
@@ -417,6 +422,8 @@ static int really_probe(struct device *dev, struct 
device_driver *drv)
goto done;
 
 probe_failed:
+   dma_deconfigure(dev);
+dma_failed:
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
 BUS_NOTIFY_DRIVER_NOT_BOUND, dev);
@@ -826,6 +833,8 @@ static void __device_release_driver(struct device *dev, 
struct device *parent)
drv->remove(dev);
 
device_links_driver_cleanup(dev);
+   dma_deconfigure(dev);
+
devres_release_all(dev);
dev->driver = NULL;
dev_set_drvdata(dev, NULL);
diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
index efd71cf..449b948 100644
--- a/drivers/base/dma-mapping.c
+++ b/drivers/base/dma-mapping.c
@@ -7,9 +7,11 @@
  * This file is released under the GPLv2.
  */
 
+#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -341,3 +343,41 @@ void dma_common_free_remap(void *cpu_addr, size_t size, 
unsigned long vm_flags)
vunmap(cpu_addr);
 }
 #endif
+
+/*
+ * Common configuration to enable DMA API use for a device
+ */
+#include 
+
+int dma_configure(struct device *dev)
+{
+   struct device *bridge = NULL, *dma_dev = dev;
+   enum dev_dma_attr attr;
+
+   if (dev_is_pci(dev)) {
+   bridge = pci_get_host_bridge_device(to_pci_dev(dev));
+   dma_dev = bridge;
+   if (IS_ENABLED(CONFIG_OF) && dma_dev->parent &&
+   dma_dev->parent->of_node)
+   dma_dev = dma_dev->parent;
+   }
+
+   if (dma_dev->of_node) {
+   of_dma_configure(dev, dma_dev->of_node);
+   } else if (has_acpi_companion(dma_dev)) {
+   attr = acpi_get_dma_attr(to_acpi_device_node(dma_dev->fwnode));
+   

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

2017-02-03 Thread Sricharan R
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 
---
 [*] Fixed minor comment from Bjorn for removing the pci.h header inclusion
 in of_iommu.c

 drivers/base/dma-mapping.c | 5 +++--
 drivers/iommu/of_iommu.c   | 4 ++--
 drivers/of/device.c| 7 ++-
 include/linux/of_device.h  | 9 ++---
 4 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
index 449b948..82bd45c 100644
--- a/drivers/base/dma-mapping.c
+++ b/drivers/base/dma-mapping.c
@@ -353,6 +353,7 @@ int dma_configure(struct device *dev)
 {
struct device *bridge = NULL, *dma_dev = dev;
enum dev_dma_attr attr;
+   int ret = 0;
 
if (dev_is_pci(dev)) {
bridge = pci_get_host_bridge_device(to_pci_dev(dev));
@@ -363,7 +364,7 @@ int dma_configure(struct device *dev)
}
 
if (dma_dev->of_node) {
-   of_dma_configure(dev, dma_dev->of_node);
+   ret = of_dma_configure(dev, dma_dev->of_node);
} else if (has_acpi_companion(dma_dev)) {
attr = acpi_get_dma_attr(to_acpi_device_node(dma_dev->fwnode));
if (attr != DEV_DMA_NOT_SUPPORTED)
@@ -373,7 +374,7 @@ int dma_configure(struct device *dev)
if (bridge)
pci_put_host_bridge_device(bridge);
 
-   return 0;
+   return ret;
 }
 
 void dma_deconfigure(struct device *dev)
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 1f92d98..2d04663 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -236,7 +236,7 @@ const struct iommu_ops *of_iommu_configure(struct device 
*dev,
ops = ERR_PTR(err);
}
 
-   return IS_ERR(ops) ? NULL : ops;
+   return ops;
 }
 
 static int __init of_iommu_init(void)
@@ -247,7 +247,7 @@ static int __init of_iommu_init(void)
for_each_matching_node_and_match(np, matches, &match) {
const of_iommu_init_fn init_fn = match->data;
 
-   if (init_fn(np))
+   if (init_fn && init_fn(np))
pr_err("Failed to initialise IOMMU %s\n",
of_node_full_name(np));
}
diff --git a/drivers/of/device.c b/drivers/of/device.c
index c17c19d..ba51ca6 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -82,7 +82,7 @@ int of_device_add(struct platform_device *ofdev)
  * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events
  * to fix up DMA configuration.
  */
-void of_dma_configure(struct device *dev, struct device_node *np)
+int of_dma_configure(struct device *dev, struct device_node *np)
 {
u64 dma_addr, paddr, size;
int ret;
@@ -129,10 +129,15 @@ void of_dma_configure(struct device *dev, struct 
device_node *np)
coherent ? " " : " not ");
 
iommu = of_iommu_configure(dev, np);
+   if (IS_ERR(iommu))
+   return PTR_ERR(iommu);
+
dev_dbg(dev, "device is%sbehind an iommu\n",
iommu ? " " : " not ");
 
arch_setup_dma_ops(dev, dma_addr, size, iommu, coherent);
+
+   return 0;
 }
 EXPORT_SYMBOL_GPL(of_dma_configure);
 
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index 3cb2288..9499861 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -56,7 +56,7 @@ static inline struct device_node *of_cpu_device_node_get(int 
cpu)
return of_node_get(cpu_dev->of_node);
 }
 
-void of_dma_configure(struct device *dev, struct device_node *np);
+int of_dma_configure(struct device *dev, struct device_node *np);
 void of_dma_deconfigure(struct device *dev);
 #else /* CONFIG_OF */
 
@@ -105,8 +105,11 @@ static inline struct device_node 
*of_cpu_device_node_get(int cpu)
 {
return NULL;
 }
-static inline void of_dma_configure(struct device *dev, struct device_node *np)
-{}
+
+static inline int o

[PATCH V8 05/11] ACPI/IORT: Add function to check SMMUs drivers presence

2017-02-03 Thread Sricharan R
From: Lorenzo Pieralisi 

The IOMMU probe deferral implementation requires a mechanism to detect
if drivers for SMMU components are built-in in the kernel to detect
whether IOMMU configuration for a given device should be deferred (ie
SMMU drivers present but still not probed) or not (drivers not present).

Add a simple function to IORT to detect if SMMU drivers for SMMU
components managed by IORT are built-in in the kernel.

Tested-by: Hanjun Guo 
Signed-off-by: Lorenzo Pieralisi 
Cc: Robin Murphy 
Cc: Sricharan R 
---
 drivers/acpi/arm64/iort.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index e0d2e6e..bf0ed09 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -523,6 +523,19 @@ static int arm_smmu_iort_xlate(struct device *dev, u32 
streamid,
return ret;
 }
 
+static inline bool iort_iommu_driver_enabled(u8 type)
+{
+   switch (type) {
+   case ACPI_IORT_NODE_SMMU_V3:
+   return IS_BUILTIN(CONFIG_ARM_SMMU_V3);
+   case ACPI_IORT_NODE_SMMU:
+   return IS_BUILTIN(CONFIG_ARM_SMMU);
+   default:
+   pr_warn("IORT node type %u does not describe an SMMU\n", type);
+   return false;
+   }
+}
+
 static const struct iommu_ops *iort_iommu_xlate(struct device *dev,
struct acpi_iort_node *node,
u32 streamid)
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation

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


[PATCH V8 04/11] of: dma: Make of_dma_deconfigure() public

2017-02-03 Thread Sricharan R
From: Laurent Pinchart 

As part of moving DMA initializing to probe time the
of_dma_deconfigure() function will need to be called from different
source files. Make it public and move it to drivers/of/device.c where
the of_dma_configure() function is.

Tested-by: Marek Szyprowski 
Signed-off-by: Laurent Pinchart 
---
 drivers/of/device.c   | 12 
 drivers/of/platform.c |  5 -
 include/linux/of_device.h |  3 +++
 3 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/of/device.c b/drivers/of/device.c
index 09dedd0..c17c19d 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -136,6 +136,18 @@ void of_dma_configure(struct device *dev, struct 
device_node *np)
 }
 EXPORT_SYMBOL_GPL(of_dma_configure);
 
+/**
+ * of_dma_deconfigure - Clean up DMA configuration
+ * @dev:   Device for which to clean up DMA configuration
+ *
+ * Clean up all configuration performed by of_dma_configure_ops() and free all
+ * resources that have been allocated.
+ */
+void of_dma_deconfigure(struct device *dev)
+{
+   arch_teardown_dma_ops(dev);
+}
+
 int of_device_register(struct platform_device *pdev)
 {
device_initialize(&pdev->dev);
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index b8064bc..57418f7 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -158,11 +158,6 @@ struct platform_device *of_device_alloc(struct device_node 
*np,
 }
 EXPORT_SYMBOL(of_device_alloc);
 
-static void of_dma_deconfigure(struct device *dev)
-{
-   arch_teardown_dma_ops(dev);
-}
-
 /**
  * of_platform_device_create_pdata - Alloc, initialize and register an 
of_device
  * @np: pointer to node to create device for
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index e9afbcc..3cb2288 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -57,6 +57,7 @@ static inline struct device_node *of_cpu_device_node_get(int 
cpu)
 }
 
 void of_dma_configure(struct device *dev, struct device_node *np);
+void of_dma_deconfigure(struct device *dev);
 #else /* CONFIG_OF */
 
 static inline int of_driver_match_device(struct device *dev,
@@ -106,6 +107,8 @@ static inline struct device_node 
*of_cpu_device_node_get(int cpu)
 }
 static inline void of_dma_configure(struct device *dev, struct device_node *np)
 {}
+static inline void of_dma_deconfigure(struct device *dev)
+{}
 #endif /* CONFIG_OF */
 
 #endif /* _LINUX_OF_DEVICE_H */
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation

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


[PATCH V8 03/11] of: dma: Move range size workaround to of_dma_get_range()

2017-02-03 Thread Sricharan R
From: Laurent Pinchart 

Invalid dma-ranges values should be worked around when retrieving the
DMA range in of_dma_get_range(), not by all callers of the function.
This isn't much of a problem now that we have a single caller, but that
situation will change when moving DMA configuration to device probe
time.

Tested-by: Marek Szyprowski 
Signed-off-by: Laurent Pinchart 
---
 drivers/of/address.c | 20 ++--
 drivers/of/device.c  | 15 ---
 2 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/drivers/of/address.c b/drivers/of/address.c
index 02b2903..6aeb816 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -819,8 +819,8 @@ void __iomem *of_io_request_and_map(struct device_node *np, 
int index,
  * CPU addr (phys_addr_t)  : pna cells
  * size: nsize cells
  *
- * It returns -ENODEV if "dma-ranges" property was not found
- * for this device in DT.
+ * Return 0 on success, -ENODEV if the "dma-ranges" property was not found for
+ * this device in DT, or -EINVAL if the CPU address or size is invalid.
  */
 int of_dma_get_range(struct device_node *np, u64 *dma_addr, u64 *paddr, u64 
*size)
 {
@@ -880,6 +880,22 @@ int of_dma_get_range(struct device_node *np, u64 
*dma_addr, u64 *paddr, u64 *siz
*dma_addr = dmaaddr;
 
*size = of_read_number(ranges + naddr + pna, nsize);
+   /*
+* DT nodes sometimes incorrectly set the size as a mask. Work around
+* those incorrect DT by computing the size as mask + 1.
+*/
+   if (*size & 1) {
+   pr_warn("%s: size 0x%llx for dma-range in node(%s) set as 
mask\n",
+   __func__, *size, np->full_name);
+   *size = *size + 1;
+   }
+
+   if (!*size) {
+   pr_err("%s: invalid size zero for dma-range in node(%s)\n",
+  __func__, np->full_name);
+   ret = -EINVAL;
+   goto out;
+   }
 
pr_debug("dma_addr(%llx) cpu_addr(%llx) size(%llx)\n",
 *dma_addr, *paddr, *size);
diff --git a/drivers/of/device.c b/drivers/of/device.c
index b1e6beb..09dedd0 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -110,21 +110,6 @@ void of_dma_configure(struct device *dev, struct 
device_node *np)
size = dev->coherent_dma_mask + 1;
} else {
offset = PFN_DOWN(paddr - dma_addr);
-
-   /*
-* Add a work around to treat the size as mask + 1 in case
-* it is defined in DT as a mask.
-*/
-   if (size & 1) {
-   dev_warn(dev, "Invalid size 0x%llx for dma-range\n",
-size);
-   size = size + 1;
-   }
-
-   if (!size) {
-   dev_err(dev, "Adjusted size 0x%llx invalid\n", size);
-   return;
-   }
dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", offset);
}
 
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation

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


[PATCH V8 00/11] IOMMU probe deferral support

2017-02-03 Thread Sricharan R
This series calls the dma ops configuration for the devices
at a generic place so that it works for all busses.
The dma_configure_ops for a device is now called during
the device_attach callback just before the probe of the
bus/driver is called. Similarly dma_deconfigure is called during
device/driver_detach path.

pci_bus_add_devices(platform/amba)(_device_create/driver_register)
   | |
pci_bus_add_device (device_add/driver_register)
   | |
device_attach   device_initial_probe
   | |
__device_attach_driver__device_attach_driver
   |
driver_probe_device
   |
really_probe
   |
dma_configure

Similarly on the device/driver_unregister path __device_release_driver is
called which inturn calls dma_deconfigure.

Rebased the series against linux-next. Please note that there is an
conflict in patch#9 while applying against iommu-next because of the
below patch not being there on iommu-next

"arm64: dma-mapping: Only swizzle DMA ops for IOMMU_DOMAIN_DMA"
https://www.spinics.net/lists/arm-kernel/msg556209.html
  
Similarly there was conflict in patch#1 and patch#9 while applying
against master because of the above patch not there and additionally
the below one not being there.

"iommu: Drop the of_iommu_{set/get}_ops() interface"
https://lkml.org/lkml/2017/1/3/489

* Tested with platform and pci devices for probe deferral
  and reprobe on arm64 based platform.

   Build tested on linux-next, iommu-next, master.

Previous post of this series [6]. 

 [V8]
 * Picked up all the acks and tested tags from Marek and
   Hanjun for DT and ACPI patches respectively, since
   no functional changes was done.

 * Addressed Minor comments Sinan and Bjorn.

 * Added Robin's fix for fixing the deferencing NULL for
   of_iommu_table after init in patch #2.

 * Rebased it on top of linux-next

 [V7]
 * Updated the subject and commit log for patch #6 as per
   comments from Lorenzo. No functional changes.

 [V6]
 * Fixed a bug in dma_configure function pointed out by
   Robin.
 * Reordered the patches as per comments from Robin and
   Lorenzo.
 * Added Tags.

 [V5]
 * Reworked the pci configuration code hanging outside and
   pushed it to dma_configure as in PATCH#5,6,7.
   Also added a couple of patches that Lorenzo provided for
   correcting the Probe deferring mechanism in case of
   ACPI devices from here [5].

 [V4]
 * Took the reworked patches [2] from Robin's branch and
   rebased on top of Lorenzo's ACPI IORT ARM support series [3].

 * Added the patches for moving the dma ops configuration of
   acpi based devices to probe time as well.
 [V3]
 * Removed the patch to split dma_masks/dma_ops configuration
   separately based on review comments that both masks and ops are
   required only during the device probe time.

 * Reworked the series based on Generic DT bindings series.

 * Added call to iommu's remove_device in the cleanup path for arm and
   arm64.

 * Removed the notifier trick in arm64 to handle early device
   registration.

 * Added reset of dma_ops in cleanup path for arm based on comments.

 * Fixed the pci_iommu_configure path and tested with PCI device as
   well.
 
 * Fixed a bug to return the correct iommu_ops from patch 7 [4] in
   last post.

 * Fixed few other cosmetic comments.
  
 [V2]
 * Updated the Initial post to call dma_configure/deconfigure from
   generic code
 
 * Added iommu add_device callback from of_iommu_configure path

 [V1]
 * Initial post from Laurent Pinchart [1]

[1] http://lists.linuxfoundation.org/pipermail/iommu/2015-May/013016.html
[2] 
http://www.linux-arm.org/git?p=linux-rm.git;a=shortlog;h=refs/heads/iommu/defer
[3] https://lkml.org/lkml/2016/11/21/141
[4] https://www.mail-archive.com/iommu@lists.linux-foundation.org/msg13940.html
[5] git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/linux.git 
iommu/probe-deferral
[6] https://www.spinics.net/lists/arm-kernel/msg557110.html
[7] https://www.spinics.net/lists/arm-kernel/msg556209.html

Laurent Pinchart (3):
  of: dma: Move range size workaround to of_dma_get_range()
  of: dma: Make of_dma_deconfigure() public
  iommu: of: Handle IOMMU lookup failure with deferred probing or error

Lorenzo Pieralisi (2):
  ACPI/IORT: Add function to check SMMUs drivers presence
  ACPI/IORT: Remove linker section for IORT entries probing

Robin Murphy (3):
  iommu/of: Refactor of_iommu_configure() for error handling
  iommu/of: Prepare for deferred IOMMU configuration
  iommu/arm-smmu: Clean up early-probing workarounds

Sricharan R (3):
  of/acpi: Configure dma operations at probe time for platform/amba/pci
bus devices
  drivers: acpi: Handle IOMMU lookup failure with deferred probing or
error
  arm64: dma-mapping: Remove the no

[PATCH V8 02/11] iommu/of: Prepare for deferred IOMMU configuration

2017-02-03 Thread Sricharan R
From: Robin Murphy 

IOMMU configuration represents unchanging properties of the hardware,
and as such should only need happen once in a device's lifetime, but
the necessary interaction with the IOMMU device and driver complicates
exactly when that point should be.

Since the only reasonable tool available for handling the inter-device
dependency is probe deferral, we need to prepare of_iommu_configure()
to run later than it is currently called (i.e. at driver probe rather
than device creation), to handle being retried, and to tell whether a
not-yet present IOMMU should be waited for or skipped (by virtue of
having declared a built-in driver or not).

Tested-by: Marek Szyprowski 
Signed-off-by: Robin Murphy 
---
 drivers/iommu/of_iommu.c | 43 ++-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index ee49081..1f92d98 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -96,6 +96,19 @@ int of_get_dma_window(struct device_node *dn, const char 
*prefix, int index,
 }
 EXPORT_SYMBOL_GPL(of_get_dma_window);
 
+static bool of_iommu_driver_present(struct device_node *np)
+{
+   /*
+* If the IOMMU still isn't ready by the time we reach init, assume
+* it never will be. We don't want to defer indefinitely, nor attempt
+* to dereference __iommu_of_table after it's been freed.
+*/
+   if (system_state > SYSTEM_BOOTING)
+   return false;
+
+   return of_match_node(&__iommu_of_table, np);
+}
+
 static const struct iommu_ops
 *of_iommu_xlate(struct device *dev, struct of_phandle_args *iommu_spec)
 {
@@ -104,12 +117,20 @@ int of_get_dma_window(struct device_node *dn, const char 
*prefix, int index,
int err;
 
ops = iommu_get_instance(fwnode);
-   if (!ops || !ops->of_xlate)
+   if ((ops && !ops->of_xlate) ||
+   (!ops && !of_iommu_driver_present(iommu_spec->np)))
return NULL;
 
err = iommu_fwspec_init(dev, &iommu_spec->np->fwnode, ops);
if (err)
return ERR_PTR(err);
+   /*
+* The otherwise-empty fwspec handily serves to indicate the specific
+* IOMMU device we're waiting for, which will be useful if we ever get
+* a proper probe-ordering dependency mechanism in future.
+*/
+   if (!ops)
+   return ERR_PTR(-EPROBE_DEFER);
 
err = ops->of_xlate(dev, iommu_spec);
if (err)
@@ -186,14 +207,34 @@ const struct iommu_ops *of_iommu_configure(struct device 
*dev,
   struct device_node *master_np)
 {
const struct iommu_ops *ops;
+   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
 
if (!master_np)
return NULL;
 
+   if (fwspec) {
+   if (fwspec->ops)
+   return fwspec->ops;
+
+   /* In the deferred case, start again from scratch */
+   iommu_fwspec_free(dev);
+   }
+
if (dev_is_pci(dev))
ops = of_pci_iommu_init(to_pci_dev(dev), master_np);
else
ops = of_platform_iommu_init(dev, master_np);
+   /*
+* If we have reason to believe the IOMMU driver missed the initial
+* add_device callback for dev, replay it to get things in order.
+*/
+   if (!IS_ERR_OR_NULL(ops) && ops->add_device &&
+   dev->bus && !dev->iommu_group) {
+   int err = ops->add_device(dev);
+
+   if (err)
+   ops = ERR_PTR(err);
+   }
 
return IS_ERR(ops) ? NULL : ops;
 }
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation

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


[PATCH V8 01/11] iommu/of: Refactor of_iommu_configure() for error handling

2017-02-03 Thread Sricharan R
From: Robin Murphy 

In preparation for some upcoming cleverness, rework the control flow in
of_iommu_configure() to minimise duplication and improve the propogation
of errors. It's also as good a time as any to switch over from the
now-just-a-compatibility-wrapper of_iommu_get_ops() to using the generic
IOMMU instance interface directly.

Tested-by: Marek Szyprowski 
Signed-off-by: Robin Murphy 
---
 [*] Resolved a conflict while rebasing on top linux-next as the patch
 is not there in mainline master.

"iommu: Drop the of_iommu_{set/get}_ops() interface"
https://lkml.org/lkml/2017/1/3/489

 drivers/iommu/of_iommu.c | 83 +++-
 1 file changed, 53 insertions(+), 30 deletions(-)

diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index d7f480a..ee49081 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -96,6 +96,28 @@ int of_get_dma_window(struct device_node *dn, const char 
*prefix, int index,
 }
 EXPORT_SYMBOL_GPL(of_get_dma_window);
 
+static const struct iommu_ops
+*of_iommu_xlate(struct device *dev, struct of_phandle_args *iommu_spec)
+{
+   const struct iommu_ops *ops;
+   struct fwnode_handle *fwnode = &iommu_spec->np->fwnode;
+   int err;
+
+   ops = iommu_get_instance(fwnode);
+   if (!ops || !ops->of_xlate)
+   return NULL;
+
+   err = iommu_fwspec_init(dev, &iommu_spec->np->fwnode, ops);
+   if (err)
+   return ERR_PTR(err);
+
+   err = ops->of_xlate(dev, iommu_spec);
+   if (err)
+   return ERR_PTR(err);
+
+   return ops;
+}
+
 static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data)
 {
struct of_phandle_args *iommu_spec = data;
@@ -105,10 +127,11 @@ static int __get_pci_rid(struct pci_dev *pdev, u16 alias, 
void *data)
 }
 
 static const struct iommu_ops
-*of_pci_iommu_configure(struct pci_dev *pdev, struct device_node *bridge_np)
+*of_pci_iommu_init(struct pci_dev *pdev, struct device_node *bridge_np)
 {
const struct iommu_ops *ops;
struct of_phandle_args iommu_spec;
+   int err;
 
/*
 * Start by tracing the RID alias down the PCI topology as
@@ -123,56 +146,56 @@ static int __get_pci_rid(struct pci_dev *pdev, u16 alias, 
void *data)
 * bus into the system beyond, and which IOMMU it ends up at.
 */
iommu_spec.np = NULL;
-   if (of_pci_map_rid(bridge_np, iommu_spec.args[0], "iommu-map",
-  "iommu-map-mask", &iommu_spec.np, iommu_spec.args))
-   return NULL;
+   err = of_pci_map_rid(bridge_np, iommu_spec.args[0], "iommu-map",
+"iommu-map-mask", &iommu_spec.np,
+iommu_spec.args);
+   if (err)
+   return ERR_PTR(err);
 
-   ops = iommu_get_instance(&iommu_spec.np->fwnode);
-   if (!ops || !ops->of_xlate ||
-   iommu_fwspec_init(&pdev->dev, &iommu_spec.np->fwnode, ops) ||
-   ops->of_xlate(&pdev->dev, &iommu_spec))
-   ops = NULL;
+   ops = of_iommu_xlate(&pdev->dev, &iommu_spec);
 
of_node_put(iommu_spec.np);
return ops;
 }
 
-const struct iommu_ops *of_iommu_configure(struct device *dev,
-  struct device_node *master_np)
+static const struct iommu_ops
+*of_platform_iommu_init(struct device *dev, struct device_node *np)
 {
struct of_phandle_args iommu_spec;
-   struct device_node *np;
const struct iommu_ops *ops = NULL;
int idx = 0;
 
-   if (dev_is_pci(dev))
-   return of_pci_iommu_configure(to_pci_dev(dev), master_np);
-
/*
 * We don't currently walk up the tree looking for a parent IOMMU.
 * See the `Notes:' section of
 * Documentation/devicetree/bindings/iommu/iommu.txt
 */
-   while (!of_parse_phandle_with_args(master_np, "iommus",
-  "#iommu-cells", idx,
-  &iommu_spec)) {
-   np = iommu_spec.np;
-   ops = iommu_get_instance(&np->fwnode);
-
-   if (!ops || !ops->of_xlate ||
-   iommu_fwspec_init(dev, &np->fwnode, ops) ||
-   ops->of_xlate(dev, &iommu_spec))
-   goto err_put_node;
-
-   of_node_put(np);
+   while (!of_parse_phandle_with_args(np, "iommus", "#iommu-cells",
+  idx, &iommu_spec)) {
+   ops = of_iommu_xlate(dev, &iommu_spec);
+   of_node_put(iommu_spec.np);
idx++;
+   if (IS_ERR_OR_NULL(ops))
+   break;
}
 
return ops;
+}
+
+const struct iommu_ops *of_iommu_configure(struct device *dev,
+  struct device_node *master_np)
+{
+   const struct iommu_ops *ops;
+
+   if (!master_np)
+ 

[PATCH 10/10] iommu: Remove iommu_register_instance interface

2017-02-03 Thread Joerg Roedel
From: Joerg Roedel 

And also move its remaining functionality to
iommu_device_register() and 'struct iommu_device'.

Cc: Rob Herring 
Cc: Frank Rowand 
Cc: Matthias Brugger 
Cc: Marek Szyprowski 
Cc: devicet...@vger.kernel.org
Cc: linux-arm-ker...@lists.infradead.org
Signed-off-by: Joerg Roedel 
---
 drivers/iommu/arm-smmu-v3.c  |  3 +--
 drivers/iommu/arm-smmu.c |  4 ++--
 drivers/iommu/exynos-iommu.c |  2 --
 drivers/iommu/iommu.c| 37 ++---
 drivers/iommu/msm_iommu.c|  2 --
 drivers/iommu/mtk_iommu.c|  1 -
 include/linux/iommu.h|  8 +---
 include/linux/of_iommu.h |  6 --
 8 files changed, 10 insertions(+), 53 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 37094b5..3b00a2e 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -2698,10 +2698,9 @@ static int arm_smmu_device_probe(struct platform_device 
*pdev)
return ret;
 
smmu->iommu.ops = &arm_smmu_ops;
+   smmu->iommu.fwnode = dev->fwnode;
ret = iommu_device_register(&smmu->iommu);
 
-   iommu_register_instance(dev->fwnode, &arm_smmu_ops);
-
 #ifdef CONFIG_PCI
if (pci_bus_type.iommu_ops != &arm_smmu_ops) {
pci_request_acs();
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 827e778..dbbd2f2 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -2112,7 +2112,8 @@ static int arm_smmu_device_probe(struct platform_device 
*pdev)
return err;
}
 
-   smmu->iommu.ops = &arm_smmu_ops;
+   smmu->iommu.ops= &arm_smmu_ops;
+   smmu->iommu.fwnode = dev->fwnode;
 
err = iommu_device_register(&smmu->iommu);
if (err) {
@@ -2120,7 +2121,6 @@ static int arm_smmu_device_probe(struct platform_device 
*pdev)
return err;
}
 
-   iommu_register_instance(dev->fwnode, &arm_smmu_ops);
platform_set_drvdata(pdev, smmu);
arm_smmu_device_reset(smmu);
 
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 90f0f52..839f6c1 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -644,8 +644,6 @@ static int __init exynos_sysmmu_probe(struct 
platform_device *pdev)
 
pm_runtime_enable(dev);
 
-   of_iommu_set_ops(dev->of_node, &exynos_iommu_ops);
-
return 0;
 }
 
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 21061da..a7e14b4 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1647,43 +1647,18 @@ int iommu_request_dm_for_dev(struct device *dev)
return ret;
 }
 
-struct iommu_instance {
-   struct list_head list;
-   struct fwnode_handle *fwnode;
-   const struct iommu_ops *ops;
-};
-static LIST_HEAD(iommu_instance_list);
-static DEFINE_SPINLOCK(iommu_instance_lock);
-
-void iommu_register_instance(struct fwnode_handle *fwnode,
-const struct iommu_ops *ops)
-{
-   struct iommu_instance *iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
-
-   if (WARN_ON(!iommu))
-   return;
-
-   of_node_get(to_of_node(fwnode));
-   INIT_LIST_HEAD(&iommu->list);
-   iommu->fwnode = fwnode;
-   iommu->ops = ops;
-   spin_lock(&iommu_instance_lock);
-   list_add_tail(&iommu->list, &iommu_instance_list);
-   spin_unlock(&iommu_instance_lock);
-}
-
 const struct iommu_ops *iommu_ops_from_fwnode(struct fwnode_handle *fwnode)
 {
-   struct iommu_instance *instance;
const struct iommu_ops *ops = NULL;
+   struct iommu_device *iommu;
 
-   spin_lock(&iommu_instance_lock);
-   list_for_each_entry(instance, &iommu_instance_list, list)
-   if (instance->fwnode == fwnode) {
-   ops = instance->ops;
+   spin_lock(&iommu_device_lock);
+   list_for_each_entry(iommu, &iommu_device_list, list)
+   if (iommu->fwnode == fwnode) {
+   ops = iommu->ops;
break;
}
-   spin_unlock(&iommu_instance_lock);
+   spin_unlock(&iommu_device_lock);
return ops;
 }
 
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index 38d19f9..b89b47e 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -810,8 +810,6 @@ static int msm_iommu_probe(struct platform_device *pdev)
goto fail;
}
 
-   of_iommu_set_ops(pdev->dev.of_node, &msm_iommu_ops);
-
pr_info("device mapped at %p, irq %d with %d ctx banks\n",
iommu->base, iommu->irq, iommu->ncb);
 
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 9fb7258..f0612aa 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -681,7 +681,6 @@ static int mtk_iommu_init_fn(struct device_node *np)
return ret;
}
 
-   of_iommu_set_ops(np, &mtk_iommu_ops);
return 0;
 }
 
diff

[PATCH 05/10] iommu: Make iommu_device_link/unlink take a struct iommu_device

2017-02-03 Thread Joerg Roedel
From: Joerg Roedel 

This makes the interface more consistent with
iommu_device_sysfs_add/remove.

Signed-off-by: Joerg Roedel 
---
 drivers/iommu/amd_iommu.c   |  4 ++--
 drivers/iommu/intel-iommu.c |  4 ++--
 drivers/iommu/iommu-sysfs.c | 16 
 include/linux/iommu.h   |  4 ++--
 4 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index a584ac2..b8adfcc 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -472,7 +472,7 @@ static int iommu_init_device(struct device *dev)
 
dev->archdata.iommu = dev_data;
 
-   iommu_device_link(&iommu->iommu.dev, dev);
+   iommu_device_link(&iommu->iommu, dev);
 
return 0;
 }
@@ -514,7 +514,7 @@ static void iommu_uninit_device(struct device *dev)
if (dev_data->domain)
detach_device(dev);
 
-   iommu_device_unlink(&iommu->iommu.dev, dev);
+   iommu_device_unlink(&iommu->iommu, dev);
 
iommu_group_remove_device(dev);
 
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 3084837..364c54e 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -5181,7 +5181,7 @@ static int intel_iommu_add_device(struct device *dev)
if (!iommu)
return -ENODEV;
 
-   iommu_device_link(&iommu->iommu.dev, dev);
+   iommu_device_link(&iommu->iommu, dev);
 
group = iommu_group_get_for_dev(dev);
 
@@ -5203,7 +5203,7 @@ static void intel_iommu_remove_device(struct device *dev)
 
iommu_group_remove_device(dev);
 
-   iommu_device_unlink(&iommu->iommu.dev, dev);
+   iommu_device_unlink(&iommu->iommu, dev);
 }
 
 #ifdef CONFIG_INTEL_IOMMU_SVM
diff --git a/drivers/iommu/iommu-sysfs.c b/drivers/iommu/iommu-sysfs.c
index bb87d35..c58351e 100644
--- a/drivers/iommu/iommu-sysfs.c
+++ b/drivers/iommu/iommu-sysfs.c
@@ -95,31 +95,31 @@ void iommu_device_sysfs_remove(struct iommu_device *iommu)
  * directory of the IOMMU device in sysfs and an "iommu" link will be
  * created under the linked device, pointing back at the IOMMU device.
  */
-int iommu_device_link(struct device *dev, struct device *link)
+int iommu_device_link(struct iommu_device *iommu, struct device *link)
 {
int ret;
 
-   if (!dev || IS_ERR(dev))
+   if (!iommu || IS_ERR(iommu))
return -ENODEV;
 
-   ret = sysfs_add_link_to_group(&dev->kobj, "devices",
+   ret = sysfs_add_link_to_group(&iommu->dev.kobj, "devices",
  &link->kobj, dev_name(link));
if (ret)
return ret;
 
-   ret = sysfs_create_link_nowarn(&link->kobj, &dev->kobj, "iommu");
+   ret = sysfs_create_link_nowarn(&link->kobj, &iommu->dev.kobj, "iommu");
if (ret)
-   sysfs_remove_link_from_group(&dev->kobj, "devices",
+   sysfs_remove_link_from_group(&iommu->dev.kobj, "devices",
 dev_name(link));
 
return ret;
 }
 
-void iommu_device_unlink(struct device *dev, struct device *link)
+void iommu_device_unlink(struct iommu_device *iommu, struct device *link)
 {
-   if (!dev || IS_ERR(dev))
+   if (!iommu || IS_ERR(iommu))
return;
 
sysfs_remove_link(&link->kobj, "iommu");
-   sysfs_remove_link_from_group(&dev->kobj, "devices", dev_name(link));
+   sysfs_remove_link_from_group(&iommu->dev.kobj, "devices", 
dev_name(link));
 }
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 1b5fbbc..e53452f 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -224,6 +224,8 @@ int  iommu_device_sysfs_add(struct iommu_device *iommu,
const struct attribute_group **groups,
const char *fmt, ...) __printf(4, 5);
 void iommu_device_sysfs_remove(struct iommu_device *iommu);
+int  iommu_device_link(struct iommu_device   *iommu, struct device *link);
+void iommu_device_unlink(struct iommu_device *iommu, struct device *link);
 
 #define IOMMU_GROUP_NOTIFY_ADD_DEVICE  1 /* Device added */
 #define IOMMU_GROUP_NOTIFY_DEL_DEVICE  2 /* Pre Device removed */
@@ -288,8 +290,6 @@ extern int iommu_domain_get_attr(struct iommu_domain 
*domain, enum iommu_attr,
 void *data);
 extern int iommu_domain_set_attr(struct iommu_domain *domain, enum iommu_attr,
 void *data);
-int iommu_device_link(struct device *dev, struct device *link);
-void iommu_device_unlink(struct device *dev, struct device *link);
 
 /* Window handling function prototypes */
 extern int iommu_domain_window_enable(struct iommu_domain *domain, u32 wnd_nr,
-- 
1.9.1

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


[PATCH 09/10] iommu/exynos: Make use of iommu_device_register interface

2017-02-03 Thread Joerg Roedel
From: Joerg Roedel 

Register Exynos IOMMUs to the IOMMU core and make them
visible in sysfs. This patch does not add the links between
IOMMUs and translated devices yet.

Cc: Marek Szyprowski 
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-samsung-...@vger.kernel.org
Signed-off-by: Joerg Roedel 
---
 drivers/iommu/exynos-iommu.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 57ba0d3..90f0f52 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -276,6 +276,8 @@ struct sysmmu_drvdata {
struct list_head owner_node;/* node for owner controllers list */
phys_addr_t pgtable;/* assigned page table structure */
unsigned int version;   /* our version */
+
+   struct iommu_device iommu;  /* IOMMU core handle */
 };
 
 static struct exynos_iommu_domain *to_exynos_domain(struct iommu_domain *dom)
@@ -556,6 +558,7 @@ static int __init exynos_sysmmu_probe(struct 
platform_device *pdev)
struct device *dev = &pdev->dev;
struct sysmmu_drvdata *data;
struct resource *res;
+   resource_size_t ioaddr;
 
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
@@ -565,6 +568,7 @@ static int __init exynos_sysmmu_probe(struct 
platform_device *pdev)
data->sfrbase = devm_ioremap_resource(dev, res);
if (IS_ERR(data->sfrbase))
return PTR_ERR(data->sfrbase);
+   ioaddr = res->start;
 
irq = platform_get_irq(pdev, 0);
if (irq <= 0) {
@@ -611,6 +615,18 @@ static int __init exynos_sysmmu_probe(struct 
platform_device *pdev)
data->sysmmu = dev;
spin_lock_init(&data->lock);
 
+   ret = iommu_device_sysfs_add(&data->iommu, &pdev->dev, NULL,
+"sysmmu.%pa", &ioaddr);
+   if (ret)
+   return ret;
+
+   data->iommu.ops= &exynos_iommu_ops;
+   data->iommu.fwnode = &dev->of_node->fwnode;
+
+   ret = iommu_device_register(&data->iommu);
+   if (ret)
+   return ret;
+
platform_set_drvdata(pdev, data);
 
__sysmmu_get_version(data);
-- 
1.9.1

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


[PATCH 07/10] iommu/msm: Make use of iommu_device_register interface

2017-02-03 Thread Joerg Roedel
From: Joerg Roedel 

Register the MSM IOMMUs to the iommu core and add sysfs
entries for that driver.

Signed-off-by: Joerg Roedel 
---
 drivers/iommu/msm_iommu.c | 73 +++
 drivers/iommu/msm_iommu.h |  3 ++
 2 files changed, 76 insertions(+)

diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index b09692b..38d19f9 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -371,6 +371,58 @@ static int msm_iommu_domain_config(struct msm_priv *priv)
return 0;
 }
 
+/* Must be called under msm_iommu_lock */
+static struct msm_iommu_dev *find_iommu_for_dev(struct device *dev)
+{
+   struct msm_iommu_dev *iommu, *ret = NULL;
+   struct msm_iommu_ctx_dev *master;
+
+   list_for_each_entry(iommu, &qcom_iommu_devices, dev_node) {
+   master = list_first_entry(&iommu->ctx_list,
+ struct msm_iommu_ctx_dev,
+ list);
+   if (master->of_node == dev->of_node) {
+   ret = iommu;
+   break;
+   }
+   }
+
+   return ret;
+}
+
+static int msm_iommu_add_device(struct device *dev)
+{
+   struct msm_iommu_dev *iommu;
+   unsigned long flags;
+   int ret = 0;
+
+   spin_lock_irqsave(&msm_iommu_lock, flags);
+
+   iommu = find_iommu_for_dev(dev);
+   if (iommu)
+   iommu_device_link(&iommu->iommu, dev);
+   else
+   ret = -ENODEV;
+
+   spin_unlock_irqrestore(&msm_iommu_lock, flags);
+
+   return ret;
+}
+
+static void msm_iommu_remove_device(struct device *dev)
+{
+   struct msm_iommu_dev *iommu;
+   unsigned long flags;
+
+   spin_lock_irqsave(&msm_iommu_lock, flags);
+
+   iommu = find_iommu_for_dev(dev);
+   if (iommu)
+   iommu_device_unlink(&iommu->iommu, dev);
+
+   spin_unlock_irqrestore(&msm_iommu_lock, flags);
+}
+
 static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device 
*dev)
 {
int ret = 0;
@@ -646,6 +698,8 @@ irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
.unmap = msm_iommu_unmap,
.map_sg = default_iommu_map_sg,
.iova_to_phys = msm_iommu_iova_to_phys,
+   .add_device = msm_iommu_add_device,
+   .remove_device = msm_iommu_remove_device,
.pgsize_bitmap = MSM_IOMMU_PGSIZES,
.of_xlate = qcom_iommu_of_xlate,
 };
@@ -653,6 +707,7 @@ irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
 static int msm_iommu_probe(struct platform_device *pdev)
 {
struct resource *r;
+   resource_size_t ioaddr;
struct msm_iommu_dev *iommu;
int ret, par, val;
 
@@ -696,6 +751,7 @@ static int msm_iommu_probe(struct platform_device *pdev)
ret = PTR_ERR(iommu->base);
goto fail;
}
+   ioaddr = r->start;
 
iommu->irq = platform_get_irq(pdev, 0);
if (iommu->irq < 0) {
@@ -737,6 +793,23 @@ static int msm_iommu_probe(struct platform_device *pdev)
}
 
list_add(&iommu->dev_node, &qcom_iommu_devices);
+
+   ret = iommu_device_sysfs_add(&iommu->iommu, iommu->dev, NULL,
+"msm-smmu.%pa", &ioaddr);
+   if (ret) {
+   pr_err("Could not add msm-smmu at %pa to sysfs\n", &ioaddr);
+   goto fail;
+   }
+
+   iommu->iommu.ops= &msm_iommu_ops;
+   iommu->iommu.fwnode = &pdev->dev.of_node->fwnode;
+
+   ret = iommu_device_register(&iommu->iommu);
+   if (ret) {
+   pr_err("Could not register msm-smmu at %pa\n", &ioaddr);
+   goto fail;
+   }
+
of_iommu_set_ops(pdev->dev.of_node, &msm_iommu_ops);
 
pr_info("device mapped at %p, irq %d with %d ctx banks\n",
diff --git a/drivers/iommu/msm_iommu.h b/drivers/iommu/msm_iommu.h
index 4ca25d5..ae92d27 100644
--- a/drivers/iommu/msm_iommu.h
+++ b/drivers/iommu/msm_iommu.h
@@ -19,6 +19,7 @@
 #define MSM_IOMMU_H
 
 #include 
+#include 
 #include 
 
 /* Sharability attributes of MSM IOMMU mappings */
@@ -68,6 +69,8 @@ struct msm_iommu_dev {
struct list_head dom_node;
struct list_head ctx_list;
DECLARE_BITMAP(context_map, IOMMU_MAX_CBS);
+
+   struct iommu_device iommu;
 };
 
 /**
-- 
1.9.1

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


[PATCH 04/10] iommu: Add sysfs bindings for struct iommu_device

2017-02-03 Thread Joerg Roedel
From: Joerg Roedel 

There is currently support for iommu sysfs bindings, but
those need to be implemented in the IOMMU drivers. Add a
more generic version of this by adding a struct device to
struct iommu_device and use that for the sysfs bindings.

Also convert the AMD and Intel IOMMU driver to make use of
it.

Signed-off-by: Joerg Roedel 
---
 drivers/iommu/amd_iommu.c   | 14 -
 drivers/iommu/amd_iommu_init.c  |  6 ++
 drivers/iommu/amd_iommu_types.h |  3 ---
 drivers/iommu/dmar.c| 13 +---
 drivers/iommu/intel-iommu.c | 15 --
 drivers/iommu/iommu-sysfs.c | 45 +
 include/linux/intel-iommu.h |  1 -
 include/linux/iommu.h   | 11 ++
 8 files changed, 50 insertions(+), 58 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 7c11c36..a584ac2 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -445,6 +445,7 @@ static void init_iommu_group(struct device *dev)
 static int iommu_init_device(struct device *dev)
 {
struct iommu_dev_data *dev_data;
+   struct amd_iommu *iommu;
int devid;
 
if (dev->archdata.iommu)
@@ -454,6 +455,8 @@ static int iommu_init_device(struct device *dev)
if (devid < 0)
return devid;
 
+   iommu = amd_iommu_rlookup_table[devid];
+
dev_data = find_dev_data(devid);
if (!dev_data)
return -ENOMEM;
@@ -469,8 +472,7 @@ static int iommu_init_device(struct device *dev)
 
dev->archdata.iommu = dev_data;
 
-   iommu_device_link(amd_iommu_rlookup_table[dev_data->devid]->iommu_dev,
- dev);
+   iommu_device_link(&iommu->iommu.dev, dev);
 
return 0;
 }
@@ -495,13 +497,16 @@ static void iommu_ignore_device(struct device *dev)
 
 static void iommu_uninit_device(struct device *dev)
 {
-   int devid;
struct iommu_dev_data *dev_data;
+   struct amd_iommu *iommu;
+   int devid;
 
devid = get_device_id(dev);
if (devid < 0)
return;
 
+   iommu = amd_iommu_rlookup_table[devid];
+
dev_data = search_dev_data(devid);
if (!dev_data)
return;
@@ -509,8 +514,7 @@ static void iommu_uninit_device(struct device *dev)
if (dev_data->domain)
detach_device(dev);
 
-   iommu_device_unlink(amd_iommu_rlookup_table[dev_data->devid]->iommu_dev,
-   dev);
+   iommu_device_unlink(&iommu->iommu.dev, dev);
 
iommu_group_remove_device(dev);
 
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 02a577b..88b0070 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -1637,10 +1637,8 @@ static int iommu_init_pci(struct amd_iommu *iommu)
amd_iommu_erratum_746_workaround(iommu);
amd_iommu_ats_write_check_workaround(iommu);
 
-   iommu->iommu_dev = iommu_device_create(&iommu->dev->dev, iommu,
-  amd_iommu_groups, "ivhd%d",
-  iommu->index);
-
+   iommu_device_sysfs_add(&iommu->iommu, &iommu->dev->dev,
+  amd_iommu_groups, "ivhd%d", iommu->index);
iommu->iommu.ops = &amd_iommu_ops;
iommu_device_register(&iommu->iommu);
 
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index 0683505..af00f38 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -535,9 +535,6 @@ struct amd_iommu {
/* if one, we need to send a completion wait command */
bool need_sync;
 
-   /* IOMMU sysfs device */
-   struct device *iommu_dev;
-
/* Handle for IOMMU core code */
struct iommu_device iommu;
 
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index c55411e..48264a0 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -1080,14 +1080,11 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
raw_spin_lock_init(&iommu->register_lock);
 
if (intel_iommu_enabled) {
-   iommu->iommu_dev = iommu_device_create(NULL, iommu,
-  intel_iommu_groups,
-  "%s", iommu->name);
-
-   if (IS_ERR(iommu->iommu_dev)) {
-   err = PTR_ERR(iommu->iommu_dev);
+   err = iommu_device_sysfs_add(&iommu->iommu, NULL,
+intel_iommu_groups,
+"%s", iommu->name);
+   if (err)
goto err_unmap;
-   }
 
iommu->iommu.ops = &intel_iommu_ops;
 
@@ -,7 +1108,7 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
 
 static void free_iommu(struct intel_iommu *iommu)
 {
-   iommu_device_destroy

[PATCH 06/10] iommu/arm-smmu: Make use of the iommu_register interface

2017-02-03 Thread Joerg Roedel
From: Joerg Roedel 

Also add the smmu devices to sysfs.

Signed-off-by: Joerg Roedel 
---
 drivers/iommu/arm-smmu-v3.c | 20 +++-
 drivers/iommu/arm-smmu.c| 29 +
 2 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 4d6ec44..37094b5 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -616,6 +616,9 @@ struct arm_smmu_device {
unsigned intsid_bits;
 
struct arm_smmu_strtab_cfg  strtab_cfg;
+
+   /* IOMMU core code handle */
+   struct iommu_device iommu;
 };
 
 /* SMMU private data for each master */
@@ -1795,8 +1798,10 @@ static int arm_smmu_add_device(struct device *dev)
}
 
group = iommu_group_get_for_dev(dev);
-   if (!IS_ERR(group))
+   if (!IS_ERR(group)) {
iommu_group_put(group);
+   iommu_device_link(&smmu->iommu, dev);
+   }
 
return PTR_ERR_OR_ZERO(group);
 }
@@ -1805,14 +1810,17 @@ static void arm_smmu_remove_device(struct device *dev)
 {
struct iommu_fwspec *fwspec = dev->iommu_fwspec;
struct arm_smmu_master_data *master;
+   struct arm_smmu_device *smmu;
 
if (!fwspec || fwspec->ops != &arm_smmu_ops)
return;
 
master = fwspec->iommu_priv;
+   smmu = master->smmu;
if (master && master->ste.valid)
arm_smmu_detach_dev(dev);
iommu_group_remove_device(dev);
+   iommu_device_unlink(&smmu->iommu, dev);
kfree(master);
iommu_fwspec_free(dev);
 }
@@ -2613,6 +2621,7 @@ static int arm_smmu_device_probe(struct platform_device 
*pdev)
 {
int irq, ret;
struct resource *res;
+   resource_size_t ioaddr;
struct arm_smmu_device *smmu;
struct device *dev = &pdev->dev;
bool bypass;
@@ -2630,6 +2639,7 @@ static int arm_smmu_device_probe(struct platform_device 
*pdev)
dev_err(dev, "MMIO region too small (%pr)\n", res);
return -EINVAL;
}
+   ioaddr = res->start;
 
smmu->base = devm_ioremap_resource(dev, res);
if (IS_ERR(smmu->base))
@@ -2682,6 +2692,14 @@ static int arm_smmu_device_probe(struct platform_device 
*pdev)
return ret;
 
/* And we're up. Go go go! */
+   ret = iommu_device_sysfs_add(&smmu->iommu, dev, NULL,
+"smmu3.%pa", &ioaddr);
+   if (ret)
+   return ret;
+
+   smmu->iommu.ops = &arm_smmu_ops;
+   ret = iommu_device_register(&smmu->iommu);
+
iommu_register_instance(dev->fwnode, &arm_smmu_ops);
 
 #ifdef CONFIG_PCI
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index a60cded..827e778 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -380,6 +380,9 @@ struct arm_smmu_device {
unsigned int*irqs;
 
u32 cavium_id_base; /* Specific to Cavium */
+
+   /* IOMMU core code handle */
+   struct iommu_device iommu;
 };
 
 enum arm_smmu_context_fmt {
@@ -1444,6 +1447,8 @@ static int arm_smmu_add_device(struct device *dev)
if (ret)
goto out_free;
 
+   iommu_device_link(&smmu->iommu, dev);
+
return 0;
 
 out_free:
@@ -1456,10 +1461,17 @@ static int arm_smmu_add_device(struct device *dev)
 static void arm_smmu_remove_device(struct device *dev)
 {
struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+   struct arm_smmu_master_cfg *cfg;
+   struct arm_smmu_device *smmu;
+
 
if (!fwspec || fwspec->ops != &arm_smmu_ops)
return;
 
+   cfg  = fwspec->iommu_priv;
+   smmu = cfg->smmu;
+
+   iommu_device_unlink(&smmu->iommu, dev);
arm_smmu_master_free_smes(fwspec);
iommu_group_remove_device(dev);
kfree(fwspec->iommu_priv);
@@ -2011,6 +2023,7 @@ static int arm_smmu_device_dt_probe(struct 
platform_device *pdev,
 static int arm_smmu_device_probe(struct platform_device *pdev)
 {
struct resource *res;
+   resource_size_t ioaddr;
struct arm_smmu_device *smmu;
struct device *dev = &pdev->dev;
int num_irqs, i, err;
@@ -2031,6 +2044,7 @@ static int arm_smmu_device_probe(struct platform_device 
*pdev)
return err;
 
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   ioaddr = res->start;
smmu->base = devm_ioremap_resource(dev, res);
if (IS_ERR(smmu->base))
return PTR_ERR(smmu->base);
@@ -2091,6 +2105,21 @@ static int arm_smmu_device_probe(struct platform_device 
*pdev)
}
}
 
+   err = iommu_device_sysfs_add(&smmu->iommu, smmu->dev, NULL,
+"smmu.%pa", &ioaddr);
+   if (err) {
+   dev_err(dev, "Failed to register iommu in sysfs\n");
+   return err;
+   

[PATCH 08/10] iommu/mediatek: Make use of iommu_device_register interface

2017-02-03 Thread Joerg Roedel
From: Joerg Roedel 

Register individual Mediatek IOMMUs to the iommu core and
add sysfs entries.

Cc: Matthias Brugger 
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-media...@lists.infradead.org
Signed-off-by: Joerg Roedel 
---
 drivers/iommu/mtk_iommu.c | 26 ++
 drivers/iommu/mtk_iommu.h |  2 ++
 2 files changed, 28 insertions(+)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 1479c76..9fb7258 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -360,11 +360,15 @@ static phys_addr_t mtk_iommu_iova_to_phys(struct 
iommu_domain *domain,
 
 static int mtk_iommu_add_device(struct device *dev)
 {
+   struct mtk_iommu_data *data;
struct iommu_group *group;
 
if (!dev->iommu_fwspec || dev->iommu_fwspec->ops != &mtk_iommu_ops)
return -ENODEV; /* Not a iommu client device */
 
+   data = dev->iommu_fwspec->iommu_priv;
+   iommu_device_link(&data->iommu, dev);
+
group = iommu_group_get_for_dev(dev);
if (IS_ERR(group))
return PTR_ERR(group);
@@ -375,9 +379,14 @@ static int mtk_iommu_add_device(struct device *dev)
 
 static void mtk_iommu_remove_device(struct device *dev)
 {
+   struct mtk_iommu_data *data;
+
if (!dev->iommu_fwspec || dev->iommu_fwspec->ops != &mtk_iommu_ops)
return;
 
+   data = dev->iommu_fwspec->iommu_priv;
+   iommu_device_unlink(&data->iommu, dev);
+
iommu_group_remove_device(dev);
iommu_fwspec_free(dev);
 }
@@ -497,6 +506,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
struct mtk_iommu_data   *data;
struct device   *dev = &pdev->dev;
struct resource *res;
+   resource_size_t ioaddr;
struct component_match  *match = NULL;
void*protect;
int i, larb_nr, ret;
@@ -519,6 +529,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
data->base = devm_ioremap_resource(dev, res);
if (IS_ERR(data->base))
return PTR_ERR(data->base);
+   ioaddr = res->start;
 
data->irq = platform_get_irq(pdev, 0);
if (data->irq < 0)
@@ -567,6 +578,18 @@ static int mtk_iommu_probe(struct platform_device *pdev)
if (ret)
return ret;
 
+   ret = iommu_device_sysfs_add(&data->iommu, dev, NULL,
+"mtk-iommu.%pa", &ioaddr);
+   if (ret)
+   return ret;
+
+   data->iommu.ops= &mtk_iommu_ops;
+   data->iommu.fwnode = &pdev->dev.of_node->fwnode;
+
+   ret = iommu_device_register(&data->iommu);
+   if (ret)
+   return ret;
+
if (!iommu_present(&platform_bus_type))
bus_set_iommu(&platform_bus_type, &mtk_iommu_ops);
 
@@ -577,6 +600,9 @@ static int mtk_iommu_remove(struct platform_device *pdev)
 {
struct mtk_iommu_data *data = platform_get_drvdata(pdev);
 
+   iommu_device_sysfs_remove(&data->iommu);
+   iommu_device_unregister(&data->iommu);
+
if (iommu_present(&platform_bus_type))
bus_set_iommu(&platform_bus_type, NULL);
 
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index 50177f7..2a28ead 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -47,6 +47,8 @@ struct mtk_iommu_data {
struct iommu_group  *m4u_group;
struct mtk_smi_iommusmi_imu;  /* SMI larb iommu info */
boolenable_4GB;
+
+   struct iommu_device iommu;
 };
 
 static inline int compare_of(struct device *dev, void *data)
-- 
1.9.1

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


[PATCH 02/10] iommu: Rename struct iommu_device

2017-02-03 Thread Joerg Roedel
From: Joerg Roedel 

The struct is used to link devices to iommu-groups, so
'struct group_device' is a better name. Further this makes
the name iommu_device available for a struct representing
hardware iommus.

Signed-off-by: Joerg Roedel 
---
 drivers/iommu/iommu.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 0ee05bb..e4e8a93 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -55,7 +55,7 @@ struct iommu_group {
struct iommu_domain *domain;
 };
 
-struct iommu_device {
+struct group_device {
struct list_head list;
struct device *dev;
char *name;
@@ -374,7 +374,7 @@ static int iommu_group_create_direct_mappings(struct 
iommu_group *group,
 int iommu_group_add_device(struct iommu_group *group, struct device *dev)
 {
int ret, i = 0;
-   struct iommu_device *device;
+   struct group_device *device;
 
device = kzalloc(sizeof(*device), GFP_KERNEL);
if (!device)
@@ -449,7 +449,7 @@ int iommu_group_add_device(struct iommu_group *group, 
struct device *dev)
 void iommu_group_remove_device(struct device *dev)
 {
struct iommu_group *group = dev->iommu_group;
-   struct iommu_device *tmp_device, *device = NULL;
+   struct group_device *tmp_device, *device = NULL;
 
pr_info("Removing device %s from group %d\n", dev_name(dev), group->id);
 
@@ -484,7 +484,7 @@ void iommu_group_remove_device(struct device *dev)
 
 static int iommu_group_device_count(struct iommu_group *group)
 {
-   struct iommu_device *entry;
+   struct group_device *entry;
int ret = 0;
 
list_for_each_entry(entry, &group->devices, list)
@@ -507,7 +507,7 @@ static int iommu_group_device_count(struct iommu_group 
*group)
 static int __iommu_group_for_each_dev(struct iommu_group *group, void *data,
  int (*fn)(struct device *, void *))
 {
-   struct iommu_device *device;
+   struct group_device *device;
int ret = 0;
 
list_for_each_entry(device, &group->devices, list) {
-- 
1.9.1

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


[PATCH 01/10] iommu: Rename iommu_get_instance()

2017-02-03 Thread Joerg Roedel
From: Joerg Roedel 

Rename the function to iommu_ops_from_fwnode(), because that
is what the function actually does. The new name is much
more descriptive about what the function does.

Signed-off-by: Joerg Roedel 
---
 drivers/acpi/arm64/iort.c | 2 +-
 drivers/iommu/iommu.c | 2 +-
 include/linux/iommu.h | 4 ++--
 include/linux/of_iommu.h  | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index e0d2e6e..3752521 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -536,7 +536,7 @@ static const struct iommu_ops *iort_iommu_xlate(struct 
device *dev,
if (!iort_fwnode)
return NULL;
 
-   ops = iommu_get_instance(iort_fwnode);
+   ops = iommu_ops_from_fwnode(iort_fwnode);
if (!ops)
return NULL;
 
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index dbe7f65..0ee05bb 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1653,7 +1653,7 @@ void iommu_register_instance(struct fwnode_handle *fwnode,
spin_unlock(&iommu_instance_lock);
 }
 
-const struct iommu_ops *iommu_get_instance(struct fwnode_handle *fwnode)
+const struct iommu_ops *iommu_ops_from_fwnode(struct fwnode_handle *fwnode)
 {
struct iommu_instance *instance;
const struct iommu_ops *ops = NULL;
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 0ff5111..085e1f0 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -354,7 +354,7 @@ int iommu_fwspec_init(struct device *dev, struct 
fwnode_handle *iommu_fwnode,
 int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
 void iommu_register_instance(struct fwnode_handle *fwnode,
 const struct iommu_ops *ops);
-const struct iommu_ops *iommu_get_instance(struct fwnode_handle *fwnode);
+const struct iommu_ops *iommu_ops_from_fwnode(struct fwnode_handle *fwnode);
 
 #else /* CONFIG_IOMMU_API */
 
@@ -590,7 +590,7 @@ static inline void iommu_register_instance(struct 
fwnode_handle *fwnode,
 }
 
 static inline
-const struct iommu_ops *iommu_get_instance(struct fwnode_handle *fwnode)
+const struct iommu_ops *iommu_ops_from_fwnode(struct fwnode_handle *fwnode)
 {
return NULL;
 }
diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
index 6a7fc50..66fcbc9 100644
--- a/include/linux/of_iommu.h
+++ b/include/linux/of_iommu.h
@@ -39,7 +39,7 @@ static inline void of_iommu_set_ops(struct device_node *np,
 
 static inline const struct iommu_ops *of_iommu_get_ops(struct device_node *np)
 {
-   return iommu_get_instance(&np->fwnode);
+   return iommu_ops_from_fwnode(&np->fwnode);
 }
 
 extern struct of_device_id __iommu_of_table;
-- 
1.9.1

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


[PATCH 00/10] Let IOMMU core know about individual IOMMUs

2017-02-03 Thread Joerg Roedel
Hi,

the IOMMU core code already has two ways of representing
individual hardware IOMMUs. One is the sysfs code and the
other is the newer iommu_register_instance interface. These
two interfaces are special purpose and can be unified.

This unification is attempted in this patch-set. It
introduces an extensible 'struct iommu_device' which
represents a hardware IOMMU in the IOMMU core code.

For now the struct contains a pointer to the iommu_ops, which
is a step to get rid of the per-bus iommu_ops, and a pointer
to a firmware-node structure.

The patches have been tested on x86 hardware and an AMD Seattle
ARM64 system.

Please review, test and provide feedback!

Thanks a lot,

   Joerg

Joerg Roedel (10):
  iommu: Rename iommu_get_instance()
  iommu: Rename struct iommu_device
  iommu: Introduce new 'struct iommu_device'
  iommu: Add sysfs bindings for struct iommu_device
  iommu: Make iommu_device_link/unlink take a struct iommu_device
  iommu/arm-smmu: Make use of the iommu_register interface
  iommu/msm: Make use of iommu_device_register interface
  iommu/mediatek: Make use of iommu_device_register interface
  iommu/exynos: Make use of iommu_device_register interface
  iommu: Remove iommu_register_instance interface

 drivers/acpi/arm64/iort.c   |  2 +-
 drivers/iommu/amd_iommu.c   | 18 ++
 drivers/iommu/amd_iommu_init.c  |  9 +++--
 drivers/iommu/amd_iommu_types.h |  4 +--
 drivers/iommu/arm-smmu-v3.c | 21 ++--
 drivers/iommu/arm-smmu.c| 31 -
 drivers/iommu/dmar.c| 20 +++
 drivers/iommu/exynos-iommu.c| 18 --
 drivers/iommu/intel-iommu.c | 19 ++-
 drivers/iommu/iommu-sysfs.c | 61 +++---
 drivers/iommu/iommu.c   | 68 +-
 drivers/iommu/msm_iommu.c   | 73 -
 drivers/iommu/msm_iommu.h   |  3 ++
 drivers/iommu/mtk_iommu.c   | 27 ++-
 drivers/iommu/mtk_iommu.h   |  2 ++
 include/linux/intel-iommu.h |  3 +-
 include/linux/iommu.h   | 41 ++-
 include/linux/of_iommu.h|  8 +
 18 files changed, 298 insertions(+), 130 deletions(-)

-- 
1.9.1

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


[PATCH 03/10] iommu: Introduce new 'struct iommu_device'

2017-02-03 Thread Joerg Roedel
From: Joerg Roedel 

This struct represents one hardware iommu in the iommu core
code. For now it only has the iommu-ops associated with it,
but that will be extended soon.

The register/unregister interface is also added, as well as
making use of it in the Intel and AMD IOMMU drivers.

Signed-off-by: Joerg Roedel 
---
 drivers/iommu/amd_iommu.c   |  4 ++--
 drivers/iommu/amd_iommu_init.c  |  5 +
 drivers/iommu/amd_iommu_types.h |  3 +++
 drivers/iommu/dmar.c|  9 +
 drivers/iommu/intel-iommu.c |  4 ++--
 drivers/iommu/iommu.c   | 19 +++
 include/linux/intel-iommu.h |  2 ++
 include/linux/iommu.h   | 14 ++
 8 files changed, 56 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 3ef0f42..7c11c36 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -112,7 +112,7 @@ struct flush_queue {
  * Domain for untranslated devices - only allocated
  * if iommu=pt passed on kernel cmd line.
  */
-static const struct iommu_ops amd_iommu_ops;
+const struct iommu_ops amd_iommu_ops;
 
 static ATOMIC_NOTIFIER_HEAD(ppr_notifier);
 int amd_iommu_max_glx_val = -1;
@@ -3217,7 +3217,7 @@ static void amd_iommu_apply_dm_region(struct device *dev,
WARN_ON_ONCE(reserve_iova(&dma_dom->iovad, start, end) == NULL);
 }
 
-static const struct iommu_ops amd_iommu_ops = {
+const struct iommu_ops amd_iommu_ops = {
.capable = amd_iommu_capable,
.domain_alloc = amd_iommu_domain_alloc,
.domain_free  = amd_iommu_domain_free,
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 6799cf9..02a577b 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -94,6 +94,8 @@
  * out of it.
  */
 
+extern const struct iommu_ops amd_iommu_ops;
+
 /*
  * structure describing one IOMMU in the ACPI table. Typically followed by one
  * or more ivhd_entrys.
@@ -1639,6 +1641,9 @@ static int iommu_init_pci(struct amd_iommu *iommu)
   amd_iommu_groups, "ivhd%d",
   iommu->index);
 
+   iommu->iommu.ops = &amd_iommu_ops;
+   iommu_device_register(&iommu->iommu);
+
return pci_enable_device(iommu->dev);
 }
 
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index 0d91785..0683505 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -538,6 +538,9 @@ struct amd_iommu {
/* IOMMU sysfs device */
struct device *iommu_dev;
 
+   /* Handle for IOMMU core code */
+   struct iommu_device iommu;
+
/*
 * We can't rely on the BIOS to restore all values on reinit, so we
 * need to stash them
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 8ccbd70..c55411e 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -74,6 +74,8 @@ struct dmar_res_callback {
 static int alloc_iommu(struct dmar_drhd_unit *drhd);
 static void free_iommu(struct intel_iommu *iommu);
 
+extern const struct iommu_ops intel_iommu_ops;
+
 static void dmar_register_drhd_unit(struct dmar_drhd_unit *drhd)
 {
/*
@@ -1086,6 +1088,12 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
err = PTR_ERR(iommu->iommu_dev);
goto err_unmap;
}
+
+   iommu->iommu.ops = &intel_iommu_ops;
+
+   err = iommu_device_register(&iommu->iommu);
+   if (err)
+   goto err_unmap;
}
 
drhd->iommu = iommu;
@@ -1104,6 +1112,7 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
 static void free_iommu(struct intel_iommu *iommu)
 {
iommu_device_destroy(iommu->iommu_dev);
+   iommu_device_unregister(&iommu->iommu);
 
if (iommu->irq) {
if (iommu->pr_irq) {
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 8a18525..ca22872 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -547,7 +547,7 @@ static int domain_detach_iommu(struct dmar_domain *domain,
 static DEFINE_SPINLOCK(device_domain_lock);
 static LIST_HEAD(device_domain_list);
 
-static const struct iommu_ops intel_iommu_ops;
+const struct iommu_ops intel_iommu_ops;
 
 static bool translation_pre_enabled(struct intel_iommu *iommu)
 {
@@ -5332,7 +5332,7 @@ struct intel_iommu *intel_svm_device_to_iommu(struct 
device *dev)
 }
 #endif /* CONFIG_INTEL_IOMMU_SVM */
 
-static const struct iommu_ops intel_iommu_ops = {
+const struct iommu_ops intel_iommu_ops = {
.capable= intel_iommu_capable,
.domain_alloc   = intel_iommu_domain_alloc,
.domain_free= intel_iommu_domain_free,
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index e4e8a93..21061da 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -77,6 +77,25 @@ struct iommu_group_attribut

Re: [PATCH] iommu/ipmmu-vmsa: Add r8a7795 DT binding

2017-02-03 Thread Laurent Pinchart
Hi Rob,

On Monday 29 Feb 2016 23:33:09 Magnus Damm wrote:
> From: Magnus Damm 
> 
> Update the IPMMU DT binding documentation to include the r8a7795 compat
> string as well as the "renesas,ipmmu-main" property that on r8a7795 will
> be used to describe the topology and the relationship between the various
> cache IPMMU instances and the main IPMMU.
> 
> Signed-off-by: Magnus Damm 

This DT binding has been merged already, but isn't used upstream (nor in the 
dts nor in the drivers). We plan to start using it, and I'd like to seize this 
last opportunity to change it if needed and ask you for a review.

> ---
> 
>  Written against linux-next tag next-20160229
> 
>  Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt |   15 -
>  1 file changed, 13 insertions(+), 2 deletions(-)
> 
> --- 0001/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt
> +++
> work/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt   
2016-02
> -29 23:25:15.540513000 +0900 @@ -7,23 +7,34 @@ connected to the IPMMU
> through a port ca
> 
>  Required Properties:
> 
> -  - compatible: Must contain SoC-specific and generic entries from below.
> +  - compatible: Must contain SoC-specific and generic entry below in case
> +the device is compatible with the R-Car Gen2 VMSA-compatible IPMMU.
> 
>  - "renesas,ipmmu-r8a73a4" for the R8A73A4 (R-Mobile APE6) IPMMU.
>  - "renesas,ipmmu-r8a7790" for the R8A7790 (R-Car H2) IPMMU.
>  - "renesas,ipmmu-r8a7791" for the R8A7791 (R-Car M2-W) IPMMU.
>  - "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-vmsa" for generic R-Car Gen2 VMSA-compatible IPMMU.
> 
>- reg: Base address and size of the IPMMU registers.
>- interrupts: Specifiers for the MMU fault interrupts. For instances that
> support secure mode two interrupts must be specified, for non-secure and
> secure mode, in that order. For instances that don't support secure mode a
> -single interrupt must be specified.
> +single interrupt must be specified. Not required for cache IPMMUs.
> 
>- #iommu-cells: Must be 1.
> 
> +Optional properties:
> +
> +  - renesas,ipmmu-main: reference to the main IPMMU instance in two cells.
> +The first cell is a phandle to the main IPMMU and the second cell is
> +the interrupt bit number associated with the particular cache IPMMU
> device.
> +The interrupt bit number needs to match the main IPMMU IMSSTR register.
> +Only used by cache IPMMU instances.
> +
> +
>  Each bus master connected to an IPMMU must reference the IPMMU in its
> device node with the following property:

-- 
Regards,

Laurent Pinchart

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


Re: [PATCH 0/5] Implement SMMU passthrough using the default domain

2017-02-03 Thread Rob Clark
On Thu, Feb 2, 2017 at 10:12 AM, Will Deacon  wrote:
> On Thu, Feb 02, 2017 at 10:02:50AM -0500, Rob Clark wrote:
>> On Thu, Jan 26, 2017 at 12:18 PM, Joerg Roedel  wrote:
>> > On Tue, Jan 24, 2017 at 08:42:23PM +0530, Sricharan wrote:
>> >> Thanks for this series. We had a case with the GPU.
>> >> The GPU's iommu was setup by kernel and the GPU
>> >> also does dynamic updates for on-the-fly switching between
>> >> process pagetables.  GPU driver was not using DMA domain and
>> >> the GPU's firmware was always expecting to run out  of contextbank
>> >>  '0' (although not correct) , which was not the case after the DMA domain
>> >> was made default  as '0' was getting allocated for DMA domain and
>> >> there were concerns about reusing the DMA domain as well.
>> >> Now with this series, looks there is an way out of that that can be tried.
>> >>
>> >> So should the default domain not be per device specific selectable ?
>> >
>> > Note that iommu-drivers can request direct-mapping for any given device
>> > on its initializtion. This is used on x86 for devices that need a 1-1
>> > mapping for some reason.
>> >
>> > Also device drivers can use the iommu-api and assign their own domain to
>> > a device, which allows them to manage the dma address space on their
>> > own.
>>
>> Part of the problem is that dev->archdata.dma_ops gets wired up to
>> iommu_dma_ops.  Which isn't so bad on it's own, except that cache ops
>> are not exposed to drivers, forcing us to use dma-mapping API
>> (dma_map_sg, etc) for cache operations.
>>
>> Possibly we should just expose cache op's to drivers bypass this abuse
>> of dma-mapping.
>>
>> btw, Will, we definitely want this to *not* rely on kcmdline for the
>> gpu with it's own private iommu case..
>
> I still need to understand the unmanaged domain case, but I don't really
> see why that's related to this series to be honest.
>

Only relation is if we were trying to solve the case of a driver that
needs to manage it's own domain with this patchset..  but that seems a
bit like "when all you have is a hammer, everything looks like a
nail"..

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


Re: [PATCH 1/1] iommu: to avoid an unnecessary assignment

2017-02-03 Thread Robin Murphy
On 03/02/17 09:35, Zhen Lei wrote:
> Move the assignment statement into if branch above, where it only
> needs to be.
> 
> Signed-off-by: Zhen Lei 
> ---
>  drivers/iommu/iommu.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
> index dbe7f65..b231400 100644
> --- a/drivers/iommu/iommu.c
> +++ b/drivers/iommu/iommu.c
> @@ -1714,13 +1714,14 @@ int iommu_fwspec_add_ids(struct device *dev, u32 
> *ids, int num_ids)
>   fwspec = krealloc(dev->iommu_fwspec, size, GFP_KERNEL);
>   if (!fwspec)
>   return -ENOMEM;
> +
> + dev->iommu_fwspec = fwspec;
>   }
> 
>   for (i = 0; i < num_ids; i++)
>   fwspec->ids[fwspec->num_ids + i] = ids[i];
> 
>   fwspec->num_ids += num_ids;
> - dev->iommu_fwspec = fwspec;

Strictly, it was done here because I like following transactional
idioms, i.e. at any point dev->fwspec is either the old one or the
fully-initialised new one. However, since the state of the new one
immediately after realloc isn't uninitialised, but still directly
equivalent to the old one, I don't see an issue with moving the
assignemnt there, plus it does avoid a redundant reassignment the first
time through.

Reviewed-by: Robin Murphy 

>   return 0;
>  }
>  EXPORT_SYMBOL_GPL(iommu_fwspec_add_ids);
> --
> 2.5.0
> 
> 
> ___
> iommu mailing list
> iommu@lists.linux-foundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/iommu
> 

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


Re: [bug report] iommu: iommu_get_group_resv_regions

2017-02-03 Thread Auger Eric
Hi Dan,

On 03/02/2017 10:14, Dan Carpenter wrote:
> Hello Eric Auger,
> 
> The patch 6c65fb318e8b: "iommu: iommu_get_group_resv_regions" from
> Jan 19, 2017, leads to the following static checker warning:
> 
>   drivers/iommu/iommu.c:215 iommu_insert_device_resv_regions()
>   error: uninitialized symbol 'ret'.
> 
> drivers/iommu/iommu.c
>203  static int
>204  iommu_insert_device_resv_regions(struct list_head *dev_resv_regions,
>205   struct list_head *group_resv_regions)
>206  {
>207  struct iommu_resv_region *entry;
>208  int ret;
>209  
>210  list_for_each_entry(entry, dev_resv_regions, list) {
>211  ret = iommu_insert_resv_region(entry, 
> group_resv_regions);
>212  if (ret)
>213  break;
>214  }
>215  return ret;
> 
> On the one hand, it probably doesn't make sense that the dev_resv_regions
> would ever be empty, but on the other hand, there some code that assumes
> it is possible.  What I mean is that iommu_get_resv_regions() can
> basically do nothing if ->get_resv_regions() isn't implemented.
> 
> I guess we should probably set ret = -EINVAL here?

we should rather initialize ret to 0. The dev_resv_regions can be void
if a device has no reserved region or if the IOMMU does not implement
the ops. We only return -ENOMEM error if we failed allocating.

Do you want to send the fix or shall I do?

Thanks for reporting

Eric
-
> 
>216  }
>217  
>218  int iommu_get_group_resv_regions(struct iommu_group *group,
>219   struct list_head *head)
>220  {
>221  struct iommu_device *device;
>222  int ret = 0;
>223  
>224  mutex_lock(&group->mutex);
>225  list_for_each_entry(device, &group->devices, list) {
>226  struct list_head dev_resv_regions;
>227  
>228  INIT_LIST_HEAD(&dev_resv_regions);
>229  iommu_get_resv_regions(device->dev, 
> &dev_resv_regions);
>230  ret = 
> iommu_insert_device_resv_regions(&dev_resv_regions, head);
>231  iommu_put_resv_regions(device->dev, 
> &dev_resv_regions);
>232  if (ret)
>233  break;
>234  }
>235  mutex_unlock(&group->mutex);
>236  return ret;
>237  }
>238  EXPORT_SYMBOL_GPL(iommu_get_group_resv_regions);
> 
> 
> regards,
> dan carpenter
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 1/1] iommu: to avoid an unnecessary assignment

2017-02-03 Thread Zhen Lei
Move the assignment statement into if branch above, where it only
needs to be.

Signed-off-by: Zhen Lei 
---
 drivers/iommu/iommu.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index dbe7f65..b231400 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1714,13 +1714,14 @@ int iommu_fwspec_add_ids(struct device *dev, u32 *ids, 
int num_ids)
fwspec = krealloc(dev->iommu_fwspec, size, GFP_KERNEL);
if (!fwspec)
return -ENOMEM;
+
+   dev->iommu_fwspec = fwspec;
}

for (i = 0; i < num_ids; i++)
fwspec->ids[fwspec->num_ids + i] = ids[i];

fwspec->num_ids += num_ids;
-   dev->iommu_fwspec = fwspec;
return 0;
 }
 EXPORT_SYMBOL_GPL(iommu_fwspec_add_ids);
--
2.5.0


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


[bug report] iommu: iommu_get_group_resv_regions

2017-02-03 Thread Dan Carpenter
Hello Eric Auger,

The patch 6c65fb318e8b: "iommu: iommu_get_group_resv_regions" from
Jan 19, 2017, leads to the following static checker warning:

drivers/iommu/iommu.c:215 iommu_insert_device_resv_regions()
error: uninitialized symbol 'ret'.

drivers/iommu/iommu.c
   203  static int
   204  iommu_insert_device_resv_regions(struct list_head *dev_resv_regions,
   205   struct list_head *group_resv_regions)
   206  {
   207  struct iommu_resv_region *entry;
   208  int ret;
   209  
   210  list_for_each_entry(entry, dev_resv_regions, list) {
   211  ret = iommu_insert_resv_region(entry, 
group_resv_regions);
   212  if (ret)
   213  break;
   214  }
   215  return ret;

On the one hand, it probably doesn't make sense that the dev_resv_regions
would ever be empty, but on the other hand, there some code that assumes
it is possible.  What I mean is that iommu_get_resv_regions() can
basically do nothing if ->get_resv_regions() isn't implemented.

I guess we should probably set ret = -EINVAL here?

   216  }
   217  
   218  int iommu_get_group_resv_regions(struct iommu_group *group,
   219   struct list_head *head)
   220  {
   221  struct iommu_device *device;
   222  int ret = 0;
   223  
   224  mutex_lock(&group->mutex);
   225  list_for_each_entry(device, &group->devices, list) {
   226  struct list_head dev_resv_regions;
   227  
   228  INIT_LIST_HEAD(&dev_resv_regions);
   229  iommu_get_resv_regions(device->dev, &dev_resv_regions);
   230  ret = 
iommu_insert_device_resv_regions(&dev_resv_regions, head);
   231  iommu_put_resv_regions(device->dev, &dev_resv_regions);
   232  if (ret)
   233  break;
   234  }
   235  mutex_unlock(&group->mutex);
   236  return ret;
   237  }
   238  EXPORT_SYMBOL_GPL(iommu_get_group_resv_regions);


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