Re: [PATCH 04/10] iommu: Add sysfs bindings for struct iommu_device
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'
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
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
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
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'
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
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
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
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
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
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
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
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
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()
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
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
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
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
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
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
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
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
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
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
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
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()
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
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'
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
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
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
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
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
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
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