From: Linus Torvalds Date: Tue, 16 Dec 2014 22:53:01 +0000 (-0800) Subject: Merge tag 'iommu-config-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git... X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=6f51ee709e4c6b56f2c2a071da2d056a109b9d26;p=openwrt%2Fstaging%2Fblogic.git Merge tag 'iommu-config-for-linus' of git://git./linux/kernel/git/arm/arm-soc Pull ARM SoC/iommu configuration update from Arnd Bergmann: "The iomm-config branch contains work from Will Deacon, quoting his description: This series adds automatic IOMMU and DMA-mapping configuration for OF-based DMA masters described using the generic IOMMU devicetree bindings. Although there is plenty of future work around splitting up iommu_ops, adding default IOMMU domains and sorting out automatic IOMMU group creation for the platform_bus, this is already useful enough for people to port over their IOMMU drivers and start using the new probing infrastructure (indeed, Marek has patches queued for the Exynos IOMMU). The branch touches core ARM and IOMMU driver files, and the respective maintainers (Russell King and Joerg Roedel) agreed to have the contents merged through the arm-soc tree. The final version was ready just before the merge window, so we ended up delaying it a bit longer than the rest, but we don't expect to see regressions because this is just additional infrastructure that will get used in drivers starting in 3.20 but is unused so far" * tag 'iommu-config-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: iommu: store DT-probed IOMMU data privately arm: dma-mapping: plumb our iommu mapping ops into arch_setup_dma_ops arm: call iommu_init before of_platform_populate dma-mapping: detect and configure IOMMU in of_dma_configure iommu: fix initialization without 'add_device' callback iommu: provide helper function to configure an IOMMU for an of master iommu: add new iommu_ops callback for adding an OF device dma-mapping: replace set_arch_dma_coherent_ops with arch_setup_dma_ops iommu: provide early initialisation hook for IOMMU drivers --- 6f51ee709e4c6b56f2c2a071da2d056a109b9d26 diff --cc arch/arm/include/asm/dma-mapping.h index e6e3446abdf6,9410b7e548fc..b52101d37ec7 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h @@@ -121,20 -121,13 +121,19 @@@ static inline unsigned long dma_max_pfn } #define dma_max_pfn(dev) dma_max_pfn(dev) - static inline int set_arch_dma_coherent_ops(struct device *dev) - { - dev->archdata.dma_coherent = true; - set_dma_ops(dev, &arm_coherent_dma_ops); - return 0; - } - #define set_arch_dma_coherent_ops(dev) set_arch_dma_coherent_ops(dev) + #define arch_setup_dma_ops arch_setup_dma_ops + extern void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, + struct iommu_ops *iommu, bool coherent); + + #define arch_teardown_dma_ops arch_teardown_dma_ops + extern void arch_teardown_dma_ops(struct device *dev); +/* do not use this function in a driver */ +static inline bool is_device_dma_coherent(struct device *dev) +{ + return dev->archdata.dma_coherent; +} + static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) { unsigned int offset = paddr & ~PAGE_MASK; diff --cc arch/arm/mm/dma-mapping.c index e8907117861e,09645f00bd17..7864797609b3 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@@ -1995,4 -1991,77 +1991,78 @@@ void arm_iommu_detach_device(struct dev } EXPORT_SYMBOL_GPL(arm_iommu_detach_device); - #endif + static struct dma_map_ops *arm_get_iommu_dma_map_ops(bool coherent) + { + return coherent ? &iommu_coherent_ops : &iommu_ops; + } + + static bool arm_setup_iommu_dma_ops(struct device *dev, u64 dma_base, u64 size, + struct iommu_ops *iommu) + { + struct dma_iommu_mapping *mapping; + + if (!iommu) + return false; + + mapping = arm_iommu_create_mapping(dev->bus, dma_base, size); + if (IS_ERR(mapping)) { + pr_warn("Failed to create %llu-byte IOMMU mapping for device %s\n", + size, dev_name(dev)); + return false; + } + + if (arm_iommu_attach_device(dev, mapping)) { + pr_warn("Failed to attached device %s to IOMMU_mapping\n", + dev_name(dev)); + arm_iommu_release_mapping(mapping); + return false; + } + + return true; + } + + static void arm_teardown_iommu_dma_ops(struct device *dev) + { + struct dma_iommu_mapping *mapping = dev->archdata.mapping; + + arm_iommu_detach_device(dev); + arm_iommu_release_mapping(mapping); + } + + #else + + static bool arm_setup_iommu_dma_ops(struct device *dev, u64 dma_base, u64 size, + struct iommu_ops *iommu) + { + return false; + } + + static void arm_teardown_iommu_dma_ops(struct device *dev) { } + + #define arm_get_iommu_dma_map_ops arm_get_dma_map_ops + + #endif /* CONFIG_ARM_DMA_USE_IOMMU */ + + static struct dma_map_ops *arm_get_dma_map_ops(bool coherent) + { + return coherent ? &arm_coherent_dma_ops : &arm_dma_ops; + } + + void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, + struct iommu_ops *iommu, bool coherent) + { + struct dma_map_ops *dma_ops; + ++ dev->archdata.dma_coherent = coherent; + if (arm_setup_iommu_dma_ops(dev, dma_base, size, iommu)) + dma_ops = arm_get_iommu_dma_map_ops(coherent); + else + dma_ops = arm_get_dma_map_ops(coherent); + + set_dma_ops(dev, dma_ops); + } + + void arch_teardown_dma_ops(struct device *dev) + { + arm_teardown_iommu_dma_ops(dev); + } diff --cc include/linux/iommu.h index 7a7bd15e54f1,415c7613d02c..38daa453f2e5 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@@ -21,8 -21,8 +21,9 @@@ #include #include + #include #include +#include #include #define IOMMU_READ (1 << 0)