Re: centralize SWIOTLB config symbol and misc other cleanups V3
On Wed, May 02, 2018 at 05:46:17AM -0700, Christoph Hellwig wrote: > Any more comments? Especially from the x86, mips and powerpc arch > maintainers? I'd like to merge this in a few days as various other > patches depend on it. I've pulled it in to make forward progress. Any additional comments will have to be sent in the form of incremental patches. ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v5 1/2] iommu - Enable debugfs exposure of IOMMU driver internals
On Tue, 2018-05-08 at 15:07 -0500, Gary R Hook wrote: > On 05/08/2018 01:48 PM, Joe Perches wrote: > > On Tue, 2018-05-08 at 12:08 -0500, Hook, Gary wrote: > > > On 5/7/2018 6:47 PM, kbuild test robot wrote: > > > > > > > > All error/warnings (new ones prefixed by >>): > > > > > > > > In file included from include/linux/intel-iommu.h:32:0, > > > > from drivers/gpu/drm/i915/i915_drv.h:41, > > > > from drivers/gpu/drm/i915/i915_oa_bxt.c:31: > > > > include/linux/iommu.h: In function 'iommu_debugfs_new_driver_dir': > > > > > > include/linux/iommu.h:706:8: error: parameter name omitted > > > > > > > > struct dentry *iommu_debugfs_new_driver_dir(char *) {}; > > > > ^~ > > > > In file included from include/linux/intel-iommu.h:32:0, > > > > from drivers/gpu/drm/i915/i915_drv.h:41, > > > > from drivers/gpu/drm/i915/i915_oa_bxt.c:31: > > > > > > include/linux/iommu.h:706:8: warning: control reaches end of > > > > > > non-void function [-Wreturn-type] > > > > > > > > struct dentry *iommu_debugfs_new_driver_dir(char *) {}; > > > > ^~ > > > > > > > > vim +706 include/linux/iommu.h > > > > > > > > 700 > > > > 701#ifdef CONFIG_IOMMU_DEBUGFS > > > > 702void iommu_debugfs_setup(void); > > > > 703struct dentry *iommu_debugfs_new_driver_dir(char *); > > > > 704#else > > > > 705static inline void iommu_debugfs_setup(void) {} > > > >> 706struct dentry *iommu_debugfs_new_driver_dir(char *) {}; > > > > 707#endif > > > > 708 > > > > > > I have no problems with adding parameter names. But > > > scripts/checkpatch.pl doesn't seem to check for this, nor require it. > > > Should checkpatch be updated? > > > > I'm pretty sure that's not feasible. > > Ugh. This is a definition, not a declaration. My bad. Which is likely > why I decided to apologize up front. > > > And when the compiler tells you you've stuffed up some > > syntactical bit, why should checkpatch duplicate the > > output error message too? > > Well, that's the point: neither the 4.8 nor 5.4 compiler complained > about this. Perhaps because CONFIG_IOMMU_DEBUGFS was set in the .config for all the compilation previously performed? > Not as an error, despite the fact that (now that I read what > is actually here, as opposed to what I think is there) this is wrong. > Had an error message been emitted, and the make stopped, I would have > figure this out before embarrassing myself in front of the entire interwebs. There's no reason for that figuring out to be necessary. Linux compilation complexity is pretty high and almost no one understands it completely. cheers, Joe ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v5 1/2] iommu - Enable debugfs exposure of IOMMU driver internals
On 05/08/2018 03:42 PM, Joe Perches wrote: On Tue, 2018-05-08 at 15:07 -0500, Gary R Hook wrote: On 05/08/2018 01:48 PM, Joe Perches wrote: On Tue, 2018-05-08 at 12:08 -0500, Hook, Gary wrote: On 5/7/2018 6:47 PM, kbuild test robot wrote: All error/warnings (new ones prefixed by >>): In file included from include/linux/intel-iommu.h:32:0, from drivers/gpu/drm/i915/i915_drv.h:41, from drivers/gpu/drm/i915/i915_oa_bxt.c:31: include/linux/iommu.h: In function 'iommu_debugfs_new_driver_dir': include/linux/iommu.h:706:8: error: parameter name omitted struct dentry *iommu_debugfs_new_driver_dir(char *) {}; ^~ In file included from include/linux/intel-iommu.h:32:0, from drivers/gpu/drm/i915/i915_drv.h:41, from drivers/gpu/drm/i915/i915_oa_bxt.c:31: include/linux/iommu.h:706:8: warning: control reaches end of non-void function [-Wreturn-type] struct dentry *iommu_debugfs_new_driver_dir(char *) {}; ^~ vim +706 include/linux/iommu.h 700 701 #ifdef CONFIG_IOMMU_DEBUGFS 702 void iommu_debugfs_setup(void); 703 struct dentry *iommu_debugfs_new_driver_dir(char *); 704 #else 705 static inline void iommu_debugfs_setup(void) {} > 706struct dentry *iommu_debugfs_new_driver_dir(char *) {}; 707 #endif 708 I have no problems with adding parameter names. But scripts/checkpatch.pl doesn't seem to check for this, nor require it. Should checkpatch be updated? I'm pretty sure that's not feasible. Ugh. This is a definition, not a declaration. My bad. Which is likely why I decided to apologize up front. And when the compiler tells you you've stuffed up some syntactical bit, why should checkpatch duplicate the output error message too? Well, that's the point: neither the 4.8 nor 5.4 compiler complained about this. Perhaps because CONFIG_IOMMU_DEBUGFS was set in the .config for all the compilation previously performed? Well, you'd think maybe so, but I forced a recompilation of that one file (i915_oa_bxt.c) and no complaint with 5.4. Weird. Ah, well. Onward to patch version 6. Thanks again. ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v5 1/2] iommu - Enable debugfs exposure of IOMMU driver internals
On 05/08/2018 01:48 PM, Joe Perches wrote: On Tue, 2018-05-08 at 12:08 -0500, Hook, Gary wrote: On 5/7/2018 6:47 PM, kbuild test robot wrote: All error/warnings (new ones prefixed by >>): In file included from include/linux/intel-iommu.h:32:0, from drivers/gpu/drm/i915/i915_drv.h:41, from drivers/gpu/drm/i915/i915_oa_bxt.c:31: include/linux/iommu.h: In function 'iommu_debugfs_new_driver_dir': include/linux/iommu.h:706:8: error: parameter name omitted struct dentry *iommu_debugfs_new_driver_dir(char *) {}; ^~ In file included from include/linux/intel-iommu.h:32:0, from drivers/gpu/drm/i915/i915_drv.h:41, from drivers/gpu/drm/i915/i915_oa_bxt.c:31: include/linux/iommu.h:706:8: warning: control reaches end of non-void function [-Wreturn-type] struct dentry *iommu_debugfs_new_driver_dir(char *) {}; ^~ vim +706 include/linux/iommu.h 700 701#ifdef CONFIG_IOMMU_DEBUGFS 702void iommu_debugfs_setup(void); 703struct dentry *iommu_debugfs_new_driver_dir(char *); 704#else 705static inline void iommu_debugfs_setup(void) {} > 706 struct dentry *iommu_debugfs_new_driver_dir(char *) {}; 707#endif 708 I have no problems with adding parameter names. But scripts/checkpatch.pl doesn't seem to check for this, nor require it. Should checkpatch be updated? I'm pretty sure that's not feasible. Ugh. This is a definition, not a declaration. My bad. Which is likely why I decided to apologize up front. And when the compiler tells you you've stuffed up some syntactical bit, why should checkpatch duplicate the output error message too? Well, that's the point: neither the 4.8 nor 5.4 compiler complained about this. Not as an error, despite the fact that (now that I read what is actually here, as opposed to what I think is there) this is wrong. Had an error message been emitted, and the make stopped, I would have figure this out before embarrassing myself in front of the entire interwebs. btw: That's an unnecessary ; at the end of that non-void function and it should probably be something like: You are correct, sir. I've made a change on this. static inline struct dentry *iommu_debugfs_new_driver_dir(char *dir) { return NULL; } Thanks for taking a few moments to comment. Much appreciated. ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v5 1/2] iommu - Enable debugfs exposure of IOMMU driver internals
On Tue, 2018-05-08 at 12:08 -0500, Hook, Gary wrote: > On 5/7/2018 6:47 PM, kbuild test robot wrote: > > Hi Gary, > > > > I imagine these questions have been asked before, so I'll ask for > forgiveness up front. > > > > Thank you for the patch! Yet something to improve: > > > > [auto build test ERROR on iommu/next] > > [also build test ERROR on v4.17-rc4 next-20180507] > > [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/Gary-R-Hook/iommu-Enable-debugfs-exposure-of-IOMMU-driver-internals/20180508-062918 > > base: https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git next > > config: x86_64-randconfig-x016-201818 (attached as .config) > > compiler: gcc-7 (Debian 7.3.0-16) 7.3.0 > > reproduce: > > # save the attached .config to linux build tree > > make ARCH=x86_64 > > Is the gcc 7 compiler now a requirement to build the kernel? Or only to > run krobot tests? > > Is this the earliest version of the compiler that can be used? I'm still > using 4.8 and 5.4, which seems to suffice for the kernel. > > Googling about this has been fruitless. > > > > > All error/warnings (new ones prefixed by >>): > > > > In file included from include/linux/intel-iommu.h:32:0, > > from drivers/gpu/drm/i915/i915_drv.h:41, > > from drivers/gpu/drm/i915/i915_oa_bxt.c:31: > > include/linux/iommu.h: In function 'iommu_debugfs_new_driver_dir': > > > > include/linux/iommu.h:706:8: error: parameter name omitted > > > > struct dentry *iommu_debugfs_new_driver_dir(char *) {}; > > ^~ > > In file included from include/linux/intel-iommu.h:32:0, > > from drivers/gpu/drm/i915/i915_drv.h:41, > > from drivers/gpu/drm/i915/i915_oa_bxt.c:31: > > > > include/linux/iommu.h:706:8: warning: control reaches end of non-void > > > > function [-Wreturn-type] > > > > struct dentry *iommu_debugfs_new_driver_dir(char *) {}; > > ^~ > > > > vim +706 include/linux/iommu.h > > > > 700 > > 701 #ifdef CONFIG_IOMMU_DEBUGFS > > 702 void iommu_debugfs_setup(void); > > 703 struct dentry *iommu_debugfs_new_driver_dir(char *); > > 704 #else > > 705 static inline void iommu_debugfs_setup(void) {} > > > 706 struct dentry *iommu_debugfs_new_driver_dir(char *) {}; > > 707 #endif > > 708 > > I have no problems with adding parameter names. But > scripts/checkpatch.pl doesn't seem to check for this, nor require it. > Should checkpatch be updated? I'm pretty sure that's not feasible. And when the compiler tells you you've stuffed up some syntactical bit, why should checkpatch duplicate the output error message too? btw: That's an unnecessary ; at the end of that non-void function and it should probably be something like: static inline struct dentry *iommu_debugfs_new_driver_dir(char *dir) { return NULL; } ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 9/9] iommu/tegra: gart: Optimize mapping / unmapping performance
Currently GART writes one page entry at a time. More optimal would be to aggregate the writes and flush BUS buffer in the end, this gives map/unmap 10-40% (depending on size of mapping) performance boost compared to a flushing after each entry update. Signed-off-by: Dmitry Osipenko--- drivers/iommu/tegra-gart.c | 12 ++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c index ebc105c201bd..26d8735d26e8 100644 --- a/drivers/iommu/tegra-gart.c +++ b/drivers/iommu/tegra-gart.c @@ -226,7 +226,6 @@ static int gart_iommu_map(struct iommu_domain *domain, unsigned long iova, } } gart_set_pte(gart, iova, GART_PTE(pfn)); - FLUSH_GART_REGS(gart); spin_unlock_irqrestore(>pte_lock, flags); return 0; } @@ -243,7 +242,6 @@ static size_t gart_iommu_unmap(struct iommu_domain *domain, unsigned long iova, spin_lock_irqsave(>pte_lock, flags); gart_set_pte(gart, iova, 0); - FLUSH_GART_REGS(gart); spin_unlock_irqrestore(>pte_lock, flags); return bytes; } @@ -319,6 +317,14 @@ static int gart_iommu_of_xlate(struct device *dev, return 0; } +static void gart_iommu_sync(struct iommu_domain *domain) +{ + struct gart_domain *gart_domain = to_gart_domain(domain); + struct gart_device *gart = gart_domain->gart; + + FLUSH_GART_REGS(gart); +} + static const struct iommu_ops gart_iommu_ops = { .capable= gart_iommu_capable, .domain_alloc = gart_iommu_domain_alloc, @@ -334,6 +340,8 @@ static const struct iommu_ops gart_iommu_ops = { .iova_to_phys = gart_iommu_iova_to_phys, .pgsize_bitmap = GART_IOMMU_PGSIZES, .of_xlate = gart_iommu_of_xlate, + .iotlb_sync_map = gart_iommu_sync, + .iotlb_sync = gart_iommu_sync, }; static int gart_iommu_check_device(struct gart_device *gart, -- 2.17.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 8/9] iommu: Introduce iotlb_sync_map callback
Introduce iotlb_sync_map() callback that is invoked in the end of iommu_map(). This new callback allows IOMMU drivers to avoid syncing on mapping of each contiguous chunk and sync only when whole mapping is completed, optimizing performance of the mapping operation. Signed-off-by: Dmitry Osipenko--- drivers/iommu/iommu.c | 8 ++-- include/linux/iommu.h | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index d2aa23202bb9..39b2ee66aa96 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -1508,13 +1508,14 @@ static size_t iommu_pgsize(struct iommu_domain *domain, int iommu_map(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t size, int prot) { + const struct iommu_ops *ops = domain->ops; unsigned long orig_iova = iova; unsigned int min_pagesz; size_t orig_size = size; phys_addr_t orig_paddr = paddr; int ret = 0; - if (unlikely(domain->ops->map == NULL || + if (unlikely(ops->map == NULL || domain->pgsize_bitmap == 0UL)) return -ENODEV; @@ -1543,7 +1544,7 @@ int iommu_map(struct iommu_domain *domain, unsigned long iova, pr_debug("mapping: iova 0x%lx pa %pa pgsize 0x%zx\n", iova, , pgsize); - ret = domain->ops->map(domain, iova, paddr, pgsize, prot); + ret = ops->map(domain, iova, paddr, pgsize, prot); if (ret) break; @@ -1552,6 +1553,9 @@ int iommu_map(struct iommu_domain *domain, unsigned long iova, size -= pgsize; } + if (ops->iotlb_sync_map) + ops->iotlb_sync_map(domain); + /* unroll mapping in case something went wrong */ if (ret) iommu_unmap(domain, orig_iova, orig_size - size); diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 19938ee6eb31..5224aa376377 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -206,6 +206,7 @@ struct iommu_ops { void (*flush_iotlb_all)(struct iommu_domain *domain); void (*iotlb_range_add)(struct iommu_domain *domain, unsigned long iova, size_t size); + void (*iotlb_sync_map)(struct iommu_domain *domain); void (*iotlb_sync)(struct iommu_domain *domain); phys_addr_t (*iova_to_phys)(struct iommu_domain *domain, dma_addr_t iova); int (*add_device)(struct device *dev); -- 2.17.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 7/9] iommu/tegra: gart: Provide single domain and group for all devices
GART aperture is shared by all devices, hence there is a single IOMMU domain and group shared by these devices. Allocation of a group per device only wastes resources and allowance of having more than one domain is simply wrong because IOMMU mappings made by the users of "different" domains will stomp on each other. Signed-off-by: Dmitry Osipenko--- drivers/iommu/tegra-gart.c | 107 + 1 file changed, 24 insertions(+), 83 deletions(-) diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c index 5b2d27620350..ebc105c201bd 100644 --- a/drivers/iommu/tegra-gart.c +++ b/drivers/iommu/tegra-gart.c @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -44,22 +43,17 @@ #define GART_PAGE_MASK \ (~(GART_PAGE_SIZE - 1) & ~GART_ENTRY_PHYS_ADDR_VALID) -struct gart_client { - struct device *dev; - struct list_headlist; -}; - struct gart_device { void __iomem*regs; u32 *savedata; u32 page_count; /* total remappable size */ dma_addr_t iovmm_base; /* offset to vmm_area */ spinlock_t pte_lock; /* for pagetable */ - struct list_headclient; - spinlock_t client_lock;/* for client list */ struct device *dev; struct iommu_device iommu; /* IOMMU Core handle */ + struct iommu_group *group; /* Common IOMMU group */ + struct gart_domain *domain;/* Unique IOMMU domain */ struct tegra_mc_gart_handle mc_gart_handle; }; @@ -169,81 +163,31 @@ static inline bool gart_iova_range_valid(struct gart_device *gart, static int gart_iommu_attach_dev(struct iommu_domain *domain, struct device *dev) { - struct gart_domain *gart_domain = to_gart_domain(domain); - struct gart_device *gart = gart_domain->gart; - struct gart_client *client, *c; - int err = 0; - - client = devm_kzalloc(gart->dev, sizeof(*c), GFP_KERNEL); - if (!client) - return -ENOMEM; - client->dev = dev; - - spin_lock(>client_lock); - list_for_each_entry(c, >client, list) { - if (c->dev == dev) { - dev_err(gart->dev, - "%s is already attached\n", dev_name(dev)); - err = -EINVAL; - goto fail; - } - } - list_add(>list, >client); - spin_unlock(>client_lock); - dev_dbg(gart->dev, "Attached %s\n", dev_name(dev)); return 0; - -fail: - devm_kfree(gart->dev, client); - spin_unlock(>client_lock); - return err; } static void gart_iommu_detach_dev(struct iommu_domain *domain, struct device *dev) { - struct gart_domain *gart_domain = to_gart_domain(domain); - struct gart_device *gart = gart_domain->gart; - struct gart_client *c; - - spin_lock(>client_lock); - - list_for_each_entry(c, >client, list) { - if (c->dev == dev) { - list_del(>list); - devm_kfree(gart->dev, c); - dev_dbg(gart->dev, "Detached %s\n", dev_name(dev)); - goto out; - } - } - dev_err(gart->dev, "Couldn't find\n"); -out: - spin_unlock(>client_lock); } static struct iommu_domain *gart_iommu_domain_alloc(unsigned type) { - struct gart_domain *gart_domain; - struct gart_device *gart; - - if (type != IOMMU_DOMAIN_UNMANAGED) - return NULL; + struct gart_device *gart = gart_handle; - gart = gart_handle; - if (!gart) + if (type != IOMMU_DOMAIN_UNMANAGED || gart->domain) return NULL; - gart_domain = kzalloc(sizeof(*gart_domain), GFP_KERNEL); - if (!gart_domain) - return NULL; - - gart_domain->gart = gart; - gart_domain->domain.geometry.aperture_start = gart->iovmm_base; - gart_domain->domain.geometry.aperture_end = gart->iovmm_base + + gart->domain = kzalloc(sizeof(*gart->domain), GFP_KERNEL); + if (gart->domain) { + gart->domain->domain.geometry.aperture_start = gart->iovmm_base; + gart->domain->domain.geometry.aperture_end = gart->iovmm_base + gart->page_count * GART_PAGE_SIZE - 1; - gart_domain->domain.geometry.force_aperture = true; + gart->domain->domain.geometry.force_aperture = true; + gart->domain->gart = gart; + } - return _domain->domain; + return >domain->domain; } static void gart_iommu_domain_free(struct iommu_domain *domain) @@ -251,18 +195,7 @@ static
[PATCH v1 6/9] iommu/tegra: gart: Ignore devices without IOMMU phandle in DT
GART can't handle all devices, ignore devices that aren't related to GART. Device tree must explicitly assign GART IOMMU to the devices. Signed-off-by: Dmitry Osipenko--- drivers/iommu/tegra-gart.c | 33 - 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c index 39305224c48d..5b2d27620350 100644 --- a/drivers/iommu/tegra-gart.c +++ b/drivers/iommu/tegra-gart.c @@ -366,6 +366,26 @@ static void gart_iommu_remove_device(struct device *dev) iommu_device_unlink(_handle->iommu, dev); } +static int gart_iommu_check_device(struct gart_device *gart, + struct device *dev); + +struct iommu_group *gart_iommu_device_group(struct device *dev) +{ + int err; + + err = gart_iommu_check_device(gart_handle, dev); + if (err) + return ERR_PTR(err); + + return generic_device_group(dev); +} + +static int gart_iommu_of_xlate(struct device *dev, + struct of_phandle_args *args) +{ + return 0; +} + static const struct iommu_ops gart_iommu_ops = { .capable= gart_iommu_capable, .domain_alloc = gart_iommu_domain_alloc, @@ -374,14 +394,24 @@ static const struct iommu_ops gart_iommu_ops = { .detach_dev = gart_iommu_detach_dev, .add_device = gart_iommu_add_device, .remove_device = gart_iommu_remove_device, - .device_group = generic_device_group, + .device_group = gart_iommu_device_group, .map= gart_iommu_map, .map_sg = default_iommu_map_sg, .unmap = gart_iommu_unmap, .iova_to_phys = gart_iommu_iova_to_phys, .pgsize_bitmap = GART_IOMMU_PGSIZES, + .of_xlate = gart_iommu_of_xlate, }; +static int gart_iommu_check_device(struct gart_device *gart, + struct device *dev) +{ + if (!dev->iommu_fwspec || dev->iommu_fwspec->ops != _iommu_ops) + return -ENODEV; + + return 0; +} + static int tegra_gart_suspend(struct device *dev) { struct gart_device *gart = dev_get_drvdata(dev); @@ -462,6 +492,7 @@ static int tegra_gart_probe(struct platform_device *pdev) } iommu_device_set_ops(>iommu, _iommu_ops); + iommu_device_set_fwnode(>iommu, dev->fwnode); ret = iommu_device_register(>iommu); if (ret) { -- 2.17.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 5/9] iommu/tegra: gart: Clean up driver probe failure unwinding
Properly clean up allocated resources on driver probe failure. Signed-off-by: Dmitry Osipenko--- drivers/iommu/tegra-gart.c | 13 ++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c index 08e0de4087d1..39305224c48d 100644 --- a/drivers/iommu/tegra-gart.c +++ b/drivers/iommu/tegra-gart.c @@ -466,8 +466,7 @@ static int tegra_gart_probe(struct platform_device *pdev) ret = iommu_device_register(>iommu); if (ret) { dev_err(dev, "Failed to register IOMMU\n"); - iommu_device_sysfs_remove(>iommu); - return ret; + goto remove_sysfs; } gart->dev = >dev; @@ -483,7 +482,8 @@ static int tegra_gart_probe(struct platform_device *pdev) gart->savedata = vmalloc(sizeof(u32) * gart->page_count); if (!gart->savedata) { dev_err(dev, "failed to allocate context save area\n"); - return -ENOMEM; + ret = -ENOMEM; + goto iommu_unregister; } platform_set_drvdata(pdev, gart); @@ -493,6 +493,13 @@ static int tegra_gart_probe(struct platform_device *pdev) tegra_mc_register_gart(>mc_gart_handle); return 0; + +iommu_unregister: + iommu_device_unregister(>iommu); +remove_sysfs: + iommu_device_sysfs_remove(>iommu); + + return ret; } static const struct dev_pm_ops tegra_gart_pm_ops = { -- 2.17.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 3/9] iommu/tegra: gart: Remove code related to module unloading
GART driver is built-in, hence it can't be unloaded. This patch merely removes the dead code. Signed-off-by: Dmitry Osipenko--- drivers/iommu/tegra-gart.c | 25 +++-- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c index de48943bf843..268d29fb9097 100644 --- a/drivers/iommu/tegra-gart.c +++ b/drivers/iommu/tegra-gart.c @@ -502,20 +502,6 @@ static int tegra_gart_probe(struct platform_device *pdev) return 0; } -static int tegra_gart_remove(struct platform_device *pdev) -{ - struct gart_device *gart = platform_get_drvdata(pdev); - - iommu_device_unregister(>iommu); - iommu_device_sysfs_remove(>iommu); - - writel(0, gart->regs + GART_CONFIG); - if (gart->savedata) - vfree(gart->savedata); - gart_handle = NULL; - return 0; -} - static const struct dev_pm_ops tegra_gart_pm_ops = { .suspend= tegra_gart_suspend, .resume = tegra_gart_resume, @@ -529,26 +515,21 @@ MODULE_DEVICE_TABLE(of, tegra_gart_of_match); static struct platform_driver tegra_gart_driver = { .probe = tegra_gart_probe, - .remove = tegra_gart_remove, .driver = { .name = "tegra-gart", .pm = _gart_pm_ops, .of_match_table = tegra_gart_of_match, + .suppress_bind_attrs = true, }, + .prevent_deferred_probe = true, }; static int tegra_gart_init(void) { return platform_driver_register(_gart_driver); } - -static void __exit tegra_gart_exit(void) -{ - platform_driver_unregister(_gart_driver); -} - subsys_initcall(tegra_gart_init); -module_exit(tegra_gart_exit); + module_param(gart_debug, bool, 0644); MODULE_PARM_DESC(gart_debug, "Enable GART debugging"); -- 2.17.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 1/9] memory: tegra: Provide facility for integration with the GART driver
In order to report clients name and access direction on GART page fault, MC driver needs to access GART registers. Add facility that provides access to the GART. Signed-off-by: Dmitry Osipenko--- drivers/memory/tegra/mc.c | 26 +++--- include/soc/tegra/mc.h| 13 + 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index c81d01caf1a8..49dd7ad1459f 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -72,6 +72,8 @@ static const struct of_device_id tegra_mc_of_match[] = { }; MODULE_DEVICE_TABLE(of, tegra_mc_of_match); +static struct tegra_mc_gart_handle *gart_handle; + static int terga_mc_block_dma_common(struct tegra_mc *mc, const struct tegra_mc_reset *rst) { @@ -543,6 +545,11 @@ static irqreturn_t tegra_mc_irq(int irq, void *data) return IRQ_HANDLED; } +void tegra_mc_register_gart(struct tegra_mc_gart_handle *handle) +{ + WRITE_ONCE(gart_handle, handle); +} + static __maybe_unused irqreturn_t tegra20_mc_irq(int irq, void *data) { struct tegra_mc *mc = data; @@ -565,6 +572,7 @@ static __maybe_unused irqreturn_t tegra20_mc_irq(int irq, void *data) switch (BIT(bit)) { case MC_INT_DECERR_EMEM: reg = MC_DECERR_EMEM_OTHERS_STATUS; + addr = mc_readl(mc, reg + sizeof(u32)); value = mc_readl(mc, reg); id = value & mc->soc->client_id_mask; @@ -575,11 +583,24 @@ static __maybe_unused irqreturn_t tegra20_mc_irq(int irq, void *data) break; case MC_INT_INVALID_GART_PAGE: - dev_err_ratelimited(mc->dev, "%s\n", error); - continue; + if (READ_ONCE(gart_handle) == NULL) { + dev_err_ratelimited(mc->dev, "%s\n", error); + continue; + } + + addr = gart_handle->error_addr(gart_handle); + value = gart_handle->error_req(gart_handle); + + id = (value >> 1) & mc->soc->client_id_mask; + desc = error_names[2]; + + if (value & BIT(0)) + direction = "write"; + break; case MC_INT_SECURITY_VIOLATION: reg = MC_SECURITY_VIOLATION_STATUS; + addr = mc_readl(mc, reg + sizeof(u32)); value = mc_readl(mc, reg); id = value & mc->soc->client_id_mask; @@ -596,7 +617,6 @@ static __maybe_unused irqreturn_t tegra20_mc_irq(int irq, void *data) } client = mc->soc->clients[id].name; - addr = mc_readl(mc, reg + sizeof(u32)); dev_err_ratelimited(mc->dev, "%s: %s%s @%pa: %s (%s)\n", client, secure, direction, , error, diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h index b43f37fea096..5bf72eb4dd51 100644 --- a/include/soc/tegra/mc.h +++ b/include/soc/tegra/mc.h @@ -162,4 +162,17 @@ struct tegra_mc { void tegra_mc_write_emem_configuration(struct tegra_mc *mc, unsigned long rate); unsigned int tegra_mc_get_emem_device_count(struct tegra_mc *mc); +struct tegra_mc_gart_handle { + u32 (*error_addr)(struct tegra_mc_gart_handle *handle); + u32 (*error_req)(struct tegra_mc_gart_handle *handle); +}; + +#ifdef CONFIG_TEGRA_MC +void tegra_mc_register_gart(struct tegra_mc_gart_handle *handle); +#else +static inline void tegra_mc_register_gart(struct tegra_mc_gart_handle *handle) +{ +} +#endif + #endif /* __SOC_TEGRA_MC_H__ */ -- 2.17.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 0/9] Tegra GART driver clean up and optimization
Hello, This series addresses multiple shortcomings of the GART driver: 1. Thierry noticed that Memory Controller driver uses registers that belong to GART in [0] and for now MC driver only reports the fact of GART's page fault. The first two patches of the series are addressing this shortcoming. [0] https://www.spinics.net/lists/linux-tegra/msg33072.html 2. Currently GART is kept disabled by the commit c7e3ca515e784 ("iommu/tegra: gart: Do not register with bus"). If GART is re-enabled than all devices in the system are getting assigned to the GART as it is a global systems IOMMU provider. This is wrong simply because GART doesn't handle all those devices. This series makes GART to accept only devices that are explicitly assigned to GART in device tree using 'iommu' phandle. 3. This series makes a generic clean up of the driver by removing dead code, allowing to have one IOMMU domain at max, etc. 4. This series introduces and utilizes iotlb_sync_map() callback that was previously suggested by Joerg Roedel in [1]. [1] https://www.spinics.net/lists/linux-tegra/msg32914.html Dmitry Osipenko (9): memory: tegra: Provide facility for integration with the GART driver iommu/tegra: gart: Provide access to Memory Controller driver iommu/tegra: gart: Remove code related to module unloading iommu/tegra: gart: Remove pr_fmt and clean up includes iommu/tegra: gart: Clean up driver probe failure unwinding iommu/tegra: gart: Ignore devices without IOMMU phandle in DT iommu/tegra: gart: Provide single domain and group for all devices iommu: Introduce iotlb_sync_map callback iommu/tegra: gart: Optimize mapping / unmapping performance drivers/iommu/iommu.c | 8 +- drivers/iommu/tegra-gart.c | 216 + drivers/memory/tegra/mc.c | 26 - include/linux/iommu.h | 1 + include/soc/tegra/mc.h | 13 +++ 5 files changed, 143 insertions(+), 121 deletions(-) -- 2.17.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 4/9] iommu/tegra: gart: Remove pr_fmt and clean up includes
Remove unneeded 'includes' and sort them in alphabet order. Also remove pr_fmt since there is no pr_xxx() and it doesn't affect dev_xxx(). Signed-off-by: Dmitry Osipenko--- drivers/iommu/tegra-gart.c | 17 + 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c index 268d29fb9097..08e0de4087d1 100644 --- a/drivers/iommu/tegra-gart.c +++ b/drivers/iommu/tegra-gart.c @@ -17,24 +17,17 @@ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ -#define pr_fmt(fmt)"%s(): " fmt, __func__ - +#include +#include +#include #include -#include -#include +#include #include +#include #include -#include -#include -#include -#include -#include -#include #include -#include - /* bitmap of the page sizes currently supported */ #define GART_IOMMU_PGSIZES (SZ_4K) -- 2.17.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 2/9] iommu/tegra: gart: Provide access to Memory Controller driver
GART contains registers needed by the Memory Controller driver. Provide access to the MC driver by utilizing its GART-integration facility. Signed-off-by: Dmitry Osipenko--- drivers/iommu/tegra-gart.c | 23 +++ 1 file changed, 23 insertions(+) diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c index 89ec24c6952c..de48943bf843 100644 --- a/drivers/iommu/tegra-gart.c +++ b/drivers/iommu/tegra-gart.c @@ -31,6 +31,8 @@ #include #include +#include + #include /* bitmap of the page sizes currently supported */ @@ -41,6 +43,8 @@ #define GART_ENTRY_ADDR(0x28 - GART_REG_BASE) #define GART_ENTRY_DATA(0x2c - GART_REG_BASE) #define GART_ENTRY_PHYS_ADDR_VALID (1 << 31) +#define GART_ERROR_REQ (0x30 - GART_REG_BASE) +#define GART_ERROR_ADDR(0x34 - GART_REG_BASE) #define GART_PAGE_SHIFT12 #define GART_PAGE_SIZE (1 << GART_PAGE_SHIFT) @@ -63,6 +67,8 @@ struct gart_device { struct device *dev; struct iommu_device iommu; /* IOMMU Core handle */ + + struct tegra_mc_gart_handle mc_gart_handle; }; struct gart_domain { @@ -408,6 +414,20 @@ static int tegra_gart_resume(struct device *dev) return 0; } +static u32 tegra_gart_error_addr(struct tegra_mc_gart_handle *handle) +{ + struct gart_device *gart = container_of(handle, struct gart_device, + mc_gart_handle); + return readl(gart->regs + GART_ERROR_ADDR); +} + +static u32 tegra_gart_error_req(struct tegra_mc_gart_handle *handle) +{ + struct gart_device *gart = container_of(handle, struct gart_device, + mc_gart_handle); + return readl(gart->regs + GART_ERROR_REQ); +} + static int tegra_gart_probe(struct platform_device *pdev) { struct gart_device *gart; @@ -464,6 +484,8 @@ static int tegra_gart_probe(struct platform_device *pdev) gart->regs = gart_regs; gart->iovmm_base = (dma_addr_t)res_remap->start; gart->page_count = (resource_size(res_remap) >> GART_PAGE_SHIFT); + gart->mc_gart_handle.error_addr = tegra_gart_error_addr; + gart->mc_gart_handle.error_req = tegra_gart_error_req; gart->savedata = vmalloc(sizeof(u32) * gart->page_count); if (!gart->savedata) { @@ -475,6 +497,7 @@ static int tegra_gart_probe(struct platform_device *pdev) do_gart_setup(gart, NULL); gart_handle = gart; + tegra_mc_register_gart(>mc_gart_handle); return 0; } -- 2.17.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v5 1/2] iommu - Enable debugfs exposure of IOMMU driver internals
On 5/7/2018 6:47 PM, kbuild test robot wrote: Hi Gary, I imagine these questions have been asked before, so I'll ask for forgiveness up front. Thank you for the patch! Yet something to improve: [auto build test ERROR on iommu/next] [also build test ERROR on v4.17-rc4 next-20180507] [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/Gary-R-Hook/iommu-Enable-debugfs-exposure-of-IOMMU-driver-internals/20180508-062918 base: https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git next config: x86_64-randconfig-x016-201818 (attached as .config) compiler: gcc-7 (Debian 7.3.0-16) 7.3.0 reproduce: # save the attached .config to linux build tree make ARCH=x86_64 Is the gcc 7 compiler now a requirement to build the kernel? Or only to run krobot tests? Is this the earliest version of the compiler that can be used? I'm still using 4.8 and 5.4, which seems to suffice for the kernel. Googling about this has been fruitless. All error/warnings (new ones prefixed by >>): In file included from include/linux/intel-iommu.h:32:0, from drivers/gpu/drm/i915/i915_drv.h:41, from drivers/gpu/drm/i915/i915_oa_bxt.c:31: include/linux/iommu.h: In function 'iommu_debugfs_new_driver_dir': include/linux/iommu.h:706:8: error: parameter name omitted struct dentry *iommu_debugfs_new_driver_dir(char *) {}; ^~ In file included from include/linux/intel-iommu.h:32:0, from drivers/gpu/drm/i915/i915_drv.h:41, from drivers/gpu/drm/i915/i915_oa_bxt.c:31: include/linux/iommu.h:706:8: warning: control reaches end of non-void function [-Wreturn-type] struct dentry *iommu_debugfs_new_driver_dir(char *) {}; ^~ vim +706 include/linux/iommu.h 700 701 #ifdef CONFIG_IOMMU_DEBUGFS 702 void iommu_debugfs_setup(void); 703 struct dentry *iommu_debugfs_new_driver_dir(char *); 704 #else 705 static inline void iommu_debugfs_setup(void) {} > 706 struct dentry *iommu_debugfs_new_driver_dir(char *) {}; 707 #endif 708 I have no problems with adding parameter names. But scripts/checkpatch.pl doesn't seem to check for this, nor require it. Should checkpatch be updated? ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 3/3] dma-debug: unexport dma_debug_resize_entries and debug_dma_dump_mappings
On Tue, May 08, 2018 at 11:05:20AM +0100, Robin Murphy wrote: > On 24/04/18 15:02, Christoph Hellwig wrote: >> Only used by the AMD GART driver, which must be built in. > > FWIW debug_dma_dump_mappings() is also called by the Intel VT-d driver, but > the same reasoning still applies. I'll update the changelog. > This does rather beg the question of > whether it's right to have bits of low-level dma-debug internals *only* > called by a couple of IOMMU drivers, but that can wait for another day. My gut feeling is that it is wrong, but I didn't have time to look into the details and history of how this happened. ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v4 05/22] iommu: introduce iommu invalidate API function
Hi Jacob, Looks mostly good to me, I just have a couple more comments On 04/05/18 19:07, Jacob Pan wrote: > Now the passdown invalidation granularities look like: > (sorted by coarseness), will send out in v5 patchset soon if no issues. > > /** > * enum iommu_inv_granularity - Generic invalidation granularity > * > * @IOMMU_INV_GRANU_DOMAIN: Device context cache associated with a > *domain ID. > * @IOMMU_INV_GRANU_DEVICE: Device context cache associated with a > *device ID > * @IOMMU_INV_GRANU_DOMAIN_ALL_PASID: TLB entries or PASID caches of all > *PASIDs associated with a domain ID > * @IOMMU_INV_GRANU_PASID_SEL:TLB entries or PASID cache > associated > *with a PASID and a domain > * @IOMMU_INV_GRANU_PAGE_PASID: TLB entries of selected page > range > *within a PASID > * > * When an invalidation request is passed down to IOMMU to flush translation > * caches, it may carry different granularity levels, which can be specific > * to certain types of translation caches. For an example, PASID selective > * granularity is only applicable PASID cache and IOTLB invalidation but for > * device context caches. Should it be "PASID selective granularity is only applicable to PASID cache and IOTLB but not device context caches"? > * This enum is a collection of granularities for all types of translation > * caches. The idea is to make it easy for IOMMU model specific driver to > * convert from generic to model specific value. Not all combinations between > * translation caches and granularity levels are valid. Each IOMMU driver > * can enforce check based on its own conversion table. The conversion is > * based on 2D look-up with inputs as follows: > * - translation cache types > * - granularity > * No global granularity is allowed in that passdown invalidation for an > * assigned device should only impact the device or domain itself. That last sentence is a bit confusing, because "global granularity" might also refer to the "global" TLB flag which is allowed. In my opinion you can leave this rationale out, I doubt userspace will ever demand a mechanism for global invalidation. > * > * type | DTLB|TLB| PASID | CONTEXT > * granule | | | | > * -+---+---+---+--- > * DOMAIN | | | | Y > * DEVICE | | | | Y I can't really see a use-case for DOMAIN and DEVICE. It might make more sense to keep only DN_ALL_PASID, which would then also invalidate the device context cache. But since they will be very rare events, factoring them doesn't seem important. > * DN_ALL_PASID| Y | Y | Y | > * PASID_SEL | Y | Y | Y | > * PAGE_PASID | | Y | | Why not allow PAGE_PASID+DTLB? We need a way to invalidate individual DTLB entries Thanks, Jean ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 1/3] dma-debug: move initialization to common code
Hi Christoph, On 2018-04-24 16:02, Christoph Hellwig wrote: > Most mainstream architectures are using 65536 entries, so lets stick to > that. If someone is really desperate to override it that can still be > done through , but I'd rather see a really good > rationale for that. > > dma_debug_init is now called as a core_initcall, which for many > architectures means much earlier, and provides dma-debug functionality > earlier in the boot process. This should be safe as it only relies > on the memory allocator already being available. > > Signed-off-by: Christoph HellwigNice! Unification of this is definitely needed and solves the issues reported some time ago: https://patchwork.kernel.org/patch/9429637/ (arm) https://patchwork.kernel.org/patch/9431161/ (arm64, rejected) Acked-by: Marek Szyprowski > --- > arch/arm/mm/dma-mapping-nommu.c | 9 - > arch/arm/mm/dma-mapping.c | 9 - > arch/arm64/mm/dma-mapping.c | 10 -- > arch/c6x/kernel/dma.c | 11 --- > arch/ia64/kernel/dma-mapping.c | 10 -- > arch/microblaze/kernel/dma.c| 11 --- > arch/mips/mm/dma-default.c | 10 -- > arch/openrisc/kernel/dma.c | 11 --- > arch/powerpc/kernel/dma.c | 3 --- > arch/s390/pci/pci_dma.c | 9 - > arch/sh/mm/consistent.c | 9 - > arch/sparc/kernel/Makefile | 2 -- > arch/sparc/kernel/dma.c | 13 - > arch/x86/kernel/pci-dma.c | 4 > arch/xtensa/kernel/pci-dma.c| 9 - > include/linux/dma-debug.h | 6 -- > lib/dma-debug.c | 21 ++--- > 17 files changed, 14 insertions(+), 143 deletions(-) > delete mode 100644 arch/sparc/kernel/dma.c > > diff --git a/arch/arm/mm/dma-mapping-nommu.c b/arch/arm/mm/dma-mapping-nommu.c > index 619f24a42d09..f448a0663b10 100644 > --- a/arch/arm/mm/dma-mapping-nommu.c > +++ b/arch/arm/mm/dma-mapping-nommu.c > @@ -241,12 +241,3 @@ void arch_setup_dma_ops(struct device *dev, u64 > dma_base, u64 size, > void arch_teardown_dma_ops(struct device *dev) > { > } > - > -#define PREALLOC_DMA_DEBUG_ENTRIES 4096 > - > -static int __init dma_debug_do_init(void) > -{ > - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); > - return 0; > -} > -core_initcall(dma_debug_do_init); > diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c > index 8c398fedbbb6..c26bf83f44ca 100644 > --- a/arch/arm/mm/dma-mapping.c > +++ b/arch/arm/mm/dma-mapping.c > @@ -1165,15 +1165,6 @@ int arm_dma_supported(struct device *dev, u64 mask) > return __dma_supported(dev, mask, false); > } > > -#define PREALLOC_DMA_DEBUG_ENTRIES 4096 > - > -static int __init dma_debug_do_init(void) > -{ > - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); > - return 0; > -} > -core_initcall(dma_debug_do_init); > - > #ifdef CONFIG_ARM_DMA_USE_IOMMU > > static int __dma_info_to_prot(enum dma_data_direction dir, unsigned long > attrs) > diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c > index a96ec0181818..db01f2709842 100644 > --- a/arch/arm64/mm/dma-mapping.c > +++ b/arch/arm64/mm/dma-mapping.c > @@ -508,16 +508,6 @@ static int __init arm64_dma_init(void) > } > arch_initcall(arm64_dma_init); > > -#define PREALLOC_DMA_DEBUG_ENTRIES 4096 > - > -static int __init dma_debug_do_init(void) > -{ > - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); > - return 0; > -} > -fs_initcall(dma_debug_do_init); > - > - > #ifdef CONFIG_IOMMU_DMA > #include > #include > diff --git a/arch/c6x/kernel/dma.c b/arch/c6x/kernel/dma.c > index 9fff8be75f58..31e1a9ec3a9c 100644 > --- a/arch/c6x/kernel/dma.c > +++ b/arch/c6x/kernel/dma.c > @@ -136,14 +136,3 @@ const struct dma_map_ops c6x_dma_ops = { > .sync_sg_for_cpu= c6x_dma_sync_sg_for_cpu, > }; > EXPORT_SYMBOL(c6x_dma_ops); > - > -/* Number of entries preallocated for DMA-API debugging */ > -#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16) > - > -static int __init dma_init(void) > -{ > - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); > - > - return 0; > -} > -fs_initcall(dma_init); > diff --git a/arch/ia64/kernel/dma-mapping.c b/arch/ia64/kernel/dma-mapping.c > index f2d57e66fd86..7a471d8d67d4 100644 > --- a/arch/ia64/kernel/dma-mapping.c > +++ b/arch/ia64/kernel/dma-mapping.c > @@ -9,16 +9,6 @@ int iommu_detected __read_mostly; > const struct dma_map_ops *dma_ops; > EXPORT_SYMBOL(dma_ops); > > -#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16) > - > -static int __init dma_init(void) > -{ > - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); > - > - return 0; > -} > -fs_initcall(dma_init); > - > const struct dma_map_ops *dma_get_ops(struct device *dev) > { > return dma_ops; > diff --git a/arch/microblaze/kernel/dma.c b/arch/microblaze/kernel/dma.c > index c91e8cef98dd..3145e7dc8ab1 100644 > ---
Re: [PATCH] dma-debug: Check scatterlist segments
On 25/04/18 06:58, Christoph Hellwig wrote: This looks interesting. I suspect it is going to blow up in quite a few places, so maybe at least for now it might make sense to have a separate config option? True, it's nice to verify this for 'traditional' dma_map_sg() usage, but places where it's just used as an intermediate shorthand for "prepare all these pages for arbitrary future DMA" are liable to be noisy with false-positives for not respecting the default values when they arguably don't matter. I'll respin this as an additional config under DMA_API_DEBUG, and then we can debate "default y" or not. Robin. On Tue, Apr 24, 2018 at 05:12:19PM +0100, Robin Murphy wrote: Drivers/subsystems creating scatterlists for DMA should be taking care to respect the scatter-gather limitations of the appropriate device, as described by dma_parms. A DMA API implementation cannot feasibly split a scatterlist into *more* entries than originally passed, so it is not well defined what they should do when given a segment larger than the limit they are also required to respect. Conversely, devices which are less limited than the rather conservative defaults, or indeed have no limitations at all (e.g. GPUs with their own internal MMU), should be encouraged to set appropriate dma_parms, as they may get more efficient DMA mapping performance out of it. Signed-off-by: Robin Murphy--- lib/dma-debug.c | 26 ++ 1 file changed, 26 insertions(+) diff --git a/lib/dma-debug.c b/lib/dma-debug.c index 7f5cdc1e6b29..9f158941004d 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c @@ -1293,6 +1293,30 @@ static void check_sync(struct device *dev, put_hash_bucket(bucket, ); } +static void check_sg_segment(struct device *dev, struct scatterlist *sg) +{ + unsigned int max_seg = dma_get_max_seg_size(dev); + dma_addr_t start, end, boundary = dma_get_seg_boundary(dev); + + /* +* Either the driver forgot to set dma_parms appropriately, or +* whoever generated the list forgot to check them. +*/ + if (sg->length > max_seg) + err_printk(dev, NULL, "DMA-API: mapping sg segment longer than device claims to support [len=%u] [max=%u]\n", + sg->length, max_seg); + /* +* In some cases this could potentially be the DMA API +* implementation's fault, but it would usually imply that +* the scatterlist was built inappropriately to begin with. +*/ + start = sg_dma_address(sg); + end = start + sg_dma_len(sg) - 1; + if ((start ^ end) & ~boundary) + err_printk(dev, NULL, "DMA-API: mapping sg segment across boundary [start=0x%016llx] [end=0x%016llx] [boundary=0x%016llx]\n", + start, end, boundary); +} + void debug_dma_map_page(struct device *dev, struct page *page, size_t offset, size_t size, int direction, dma_addr_t dma_addr, bool map_single) @@ -1423,6 +1447,8 @@ void debug_dma_map_sg(struct device *dev, struct scatterlist *sg, check_for_illegal_area(dev, sg_virt(s), sg_dma_len(s)); } + check_sg_segment(dev, s); + add_dma_entry(entry); } } -- 2.17.0.dirty ---end quoted text--- ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 3/3] dma-debug: unexport dma_debug_resize_entries and debug_dma_dump_mappings
On 24/04/18 15:02, Christoph Hellwig wrote: Only used by the AMD GART driver, which must be built in. FWIW debug_dma_dump_mappings() is also called by the Intel VT-d driver, but the same reasoning still applies. This does rather beg the question of whether it's right to have bits of low-level dma-debug internals *only* called by a couple of IOMMU drivers, but that can wait for another day. Reviewed-by: Robin MurphySigned-off-by: Christoph Hellwig --- lib/dma-debug.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/dma-debug.c b/lib/dma-debug.c index 075253cb613b..6a1ebaa83623 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c @@ -444,7 +444,6 @@ void debug_dma_dump_mappings(struct device *dev) spin_unlock_irqrestore(>lock, flags); } } -EXPORT_SYMBOL(debug_dma_dump_mappings); /* * For each mapping (initial cacheline in the case of @@ -753,7 +752,6 @@ int dma_debug_resize_entries(u32 num_entries) return ret; } -EXPORT_SYMBOL(dma_debug_resize_entries); /* * DMA-API debugging init code ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 4/3] dma-debug: remove CONFIG_HAVE_DMA_API_DEBUG
On 27/04/18 16:53, Christoph Hellwig wrote: There is no arch specific code required for dma-debug, so there is no need to opt into the support either. Makes sense, and a purely negative diffstat is always pleasing :) Reviewed-by: Robin MurphySigned-off-by: Christoph Hellwig --- .../io/dma-api-debug/arch-support.txt | 31 --- arch/Kconfig | 3 -- arch/arm/Kconfig | 1 - arch/arm64/Kconfig| 1 - arch/c6x/Kconfig | 1 - arch/ia64/Kconfig | 1 - arch/microblaze/Kconfig | 1 - arch/mips/Kconfig | 1 - arch/powerpc/Kconfig | 1 - arch/riscv/Kconfig| 1 - arch/s390/Kconfig | 1 - arch/sh/Kconfig | 1 - arch/sparc/Kconfig| 1 - arch/x86/Kconfig | 1 - arch/xtensa/Kconfig | 1 - lib/Kconfig.debug | 1 - 16 files changed, 48 deletions(-) delete mode 100644 Documentation/features/io/dma-api-debug/arch-support.txt diff --git a/Documentation/features/io/dma-api-debug/arch-support.txt b/Documentation/features/io/dma-api-debug/arch-support.txt deleted file mode 100644 index e438ed675623.. --- a/Documentation/features/io/dma-api-debug/arch-support.txt +++ /dev/null @@ -1,31 +0,0 @@ -# -# Feature name: dma-api-debug -# Kconfig: HAVE_DMA_API_DEBUG -# description: arch supports DMA debug facilities -# ---- -| arch |status| ---- -| alpha: | TODO | -| arc: | TODO | -| arm: | ok | -| arm64: | ok | -| c6x: | ok | -| h8300: | TODO | -| hexagon: | TODO | -|ia64: | ok | -|m68k: | TODO | -| microblaze: | ok | -|mips: | ok | -| nios2: | TODO | -|openrisc: | TODO | -| parisc: | TODO | -| powerpc: | ok | -|s390: | ok | -| sh: | ok | -| sparc: | ok | -| um: | TODO | -| unicore32: | TODO | -| x86: | ok | -| xtensa: | ok | ---- diff --git a/arch/Kconfig b/arch/Kconfig index 8e0d665c8d53..f07a1a99e5db 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -278,9 +278,6 @@ config HAVE_CLK The calls support software clock gating and thus are a key power management tool on many systems. -config HAVE_DMA_API_DEBUG - bool - config HAVE_HW_BREAKPOINT bool depends on PERF_EVENTS diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 676977bdfe33..c43f5bb55ac8 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -60,7 +60,6 @@ config ARM select HAVE_CONTEXT_TRACKING select HAVE_C_RECORDMCOUNT select HAVE_DEBUG_KMEMLEAK - select HAVE_DMA_API_DEBUG select HAVE_DMA_CONTIGUOUS if MMU select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL) && !CPU_ENDIAN_BE32 && MMU select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index db51b6445744..b25ed7834f6c 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -105,7 +105,6 @@ config ARM64 select HAVE_CONTEXT_TRACKING select HAVE_DEBUG_BUGVERBOSE select HAVE_DEBUG_KMEMLEAK - select HAVE_DMA_API_DEBUG select HAVE_DMA_CONTIGUOUS select HAVE_DYNAMIC_FTRACE select HAVE_EFFICIENT_UNALIGNED_ACCESS diff --git a/arch/c6x/Kconfig b/arch/c6x/Kconfig index c6b4dd1418b4..8c088b96e372 100644 --- a/arch/c6x/Kconfig +++ b/arch/c6x/Kconfig @@ -10,7 +10,6 @@ config C6X select GENERIC_ATOMIC64 select GENERIC_IRQ_SHOW select HAVE_ARCH_TRACEHOOK - select HAVE_DMA_API_DEBUG select HAVE_MEMBLOCK select SPARSE_IRQ select IRQ_DOMAIN diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 9485b5490eca..2067289fad4a 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -29,7 +29,6 @@ config IA64 select HAVE_FUNCTION_TRACER select TTY select HAVE_ARCH_TRACEHOOK - select HAVE_DMA_API_DEBUG select HAVE_MEMBLOCK select HAVE_MEMBLOCK_NODE_MAP select HAVE_VIRT_CPU_ACCOUNTING diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index 3817a3e2146c..d14782100088 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig @@ -19,7 +19,6 @@ config MICROBLAZE select HAVE_ARCH_HASH select HAVE_ARCH_KGDB select HAVE_DEBUG_KMEMLEAK - select HAVE_DMA_API_DEBUG select HAVE_DYNAMIC_FTRACE
Re: [PATCH 2/3] dma-debug: simplify counting of preallocated requests
On 24/04/18 15:02, Christoph Hellwig wrote: Just keep a single variable with a descriptive name instead of two with confusing names. Reviewed-by: Robin MurphySigned-off-by: Christoph Hellwig --- lib/dma-debug.c | 20 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/lib/dma-debug.c b/lib/dma-debug.c index 712a897174e4..075253cb613b 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c @@ -132,7 +132,7 @@ static u32 min_free_entries; static u32 nr_total_entries; /* number of preallocated entries requested by kernel cmdline */ -static u32 req_entries; +static u32 nr_prealloc_entries = PREALLOC_DMA_DEBUG_ENTRIES; /* debugfs dentry's for the stuff above */ static struct dentry *dma_debug_dent__read_mostly; @@ -1011,7 +1011,6 @@ void dma_debug_add_bus(struct bus_type *bus) static int dma_debug_init(void) { - u32 num_entries; int i; /* Do not use dma_debug_initialized here, since we really want to be @@ -1032,12 +1031,7 @@ static int dma_debug_init(void) return 0; } - if (req_entries) - num_entries = req_entries; - else - num_entries = PREALLOC_DMA_DEBUG_ENTRIES; - - if (prealloc_memory(num_entries) != 0) { + if (prealloc_memory(nr_prealloc_entries) != 0) { pr_err("DMA-API: debugging out of memory error - disabled\n"); global_disable = true; @@ -1068,16 +1062,10 @@ static __init int dma_debug_cmdline(char *str) static __init int dma_debug_entries_cmdline(char *str) { - int res; - if (!str) return -EINVAL; - - res = get_option(, _entries); - - if (!res) - req_entries = 0; - + if (!get_option(, _prealloc_entries)) + nr_prealloc_entries = PREALLOC_DMA_DEBUG_ENTRIES; return 0; } ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 1/3] dma-debug: move initialization to common code
On 24/04/18 15:02, Christoph Hellwig wrote: Most mainstream architectures are using 65536 entries, so lets stick to that. If someone is really desperate to override it that can still be done through , but I'd rather see a really good rationale for that. dma_debug_init is now called as a core_initcall, which for many architectures means much earlier, and provides dma-debug functionality earlier in the boot process. This should be safe as it only relies on the memory allocator already being available. Reviewed-by: Robin MurphySigned-off-by: Christoph Hellwig --- arch/arm/mm/dma-mapping-nommu.c | 9 - arch/arm/mm/dma-mapping.c | 9 - arch/arm64/mm/dma-mapping.c | 10 -- arch/c6x/kernel/dma.c | 11 --- arch/ia64/kernel/dma-mapping.c | 10 -- arch/microblaze/kernel/dma.c| 11 --- arch/mips/mm/dma-default.c | 10 -- arch/openrisc/kernel/dma.c | 11 --- arch/powerpc/kernel/dma.c | 3 --- arch/s390/pci/pci_dma.c | 9 - arch/sh/mm/consistent.c | 9 - arch/sparc/kernel/Makefile | 2 -- arch/sparc/kernel/dma.c | 13 - arch/x86/kernel/pci-dma.c | 4 arch/xtensa/kernel/pci-dma.c| 9 - include/linux/dma-debug.h | 6 -- lib/dma-debug.c | 21 ++--- 17 files changed, 14 insertions(+), 143 deletions(-) delete mode 100644 arch/sparc/kernel/dma.c diff --git a/arch/arm/mm/dma-mapping-nommu.c b/arch/arm/mm/dma-mapping-nommu.c index 619f24a42d09..f448a0663b10 100644 --- a/arch/arm/mm/dma-mapping-nommu.c +++ b/arch/arm/mm/dma-mapping-nommu.c @@ -241,12 +241,3 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, void arch_teardown_dma_ops(struct device *dev) { } - -#define PREALLOC_DMA_DEBUG_ENTRIES 4096 - -static int __init dma_debug_do_init(void) -{ - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); - return 0; -} -core_initcall(dma_debug_do_init); diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 8c398fedbbb6..c26bf83f44ca 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -1165,15 +1165,6 @@ int arm_dma_supported(struct device *dev, u64 mask) return __dma_supported(dev, mask, false); } -#define PREALLOC_DMA_DEBUG_ENTRIES 4096 - -static int __init dma_debug_do_init(void) -{ - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); - return 0; -} -core_initcall(dma_debug_do_init); - #ifdef CONFIG_ARM_DMA_USE_IOMMU static int __dma_info_to_prot(enum dma_data_direction dir, unsigned long attrs) diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c index a96ec0181818..db01f2709842 100644 --- a/arch/arm64/mm/dma-mapping.c +++ b/arch/arm64/mm/dma-mapping.c @@ -508,16 +508,6 @@ static int __init arm64_dma_init(void) } arch_initcall(arm64_dma_init); -#define PREALLOC_DMA_DEBUG_ENTRIES 4096 - -static int __init dma_debug_do_init(void) -{ - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); - return 0; -} -fs_initcall(dma_debug_do_init); - - #ifdef CONFIG_IOMMU_DMA #include #include diff --git a/arch/c6x/kernel/dma.c b/arch/c6x/kernel/dma.c index 9fff8be75f58..31e1a9ec3a9c 100644 --- a/arch/c6x/kernel/dma.c +++ b/arch/c6x/kernel/dma.c @@ -136,14 +136,3 @@ const struct dma_map_ops c6x_dma_ops = { .sync_sg_for_cpu= c6x_dma_sync_sg_for_cpu, }; EXPORT_SYMBOL(c6x_dma_ops); - -/* Number of entries preallocated for DMA-API debugging */ -#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16) - -static int __init dma_init(void) -{ - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); - - return 0; -} -fs_initcall(dma_init); diff --git a/arch/ia64/kernel/dma-mapping.c b/arch/ia64/kernel/dma-mapping.c index f2d57e66fd86..7a471d8d67d4 100644 --- a/arch/ia64/kernel/dma-mapping.c +++ b/arch/ia64/kernel/dma-mapping.c @@ -9,16 +9,6 @@ int iommu_detected __read_mostly; const struct dma_map_ops *dma_ops; EXPORT_SYMBOL(dma_ops); -#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16) - -static int __init dma_init(void) -{ - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); - - return 0; -} -fs_initcall(dma_init); - const struct dma_map_ops *dma_get_ops(struct device *dev) { return dma_ops; diff --git a/arch/microblaze/kernel/dma.c b/arch/microblaze/kernel/dma.c index c91e8cef98dd..3145e7dc8ab1 100644 --- a/arch/microblaze/kernel/dma.c +++ b/arch/microblaze/kernel/dma.c @@ -184,14 +184,3 @@ const struct dma_map_ops dma_nommu_ops = { .sync_sg_for_device = dma_nommu_sync_sg_for_device, }; EXPORT_SYMBOL(dma_nommu_ops); - -/* Number of entries preallocated for DMA-API debugging */ -#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16) - -static int __init dma_init(void) -{ - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); - - return 0; -} -fs_initcall(dma_init); diff --git