diff options
| -rw-r--r-- | arch/arm/include/asm/dma-mapping.h | 13 | ||||
| -rw-r--r-- | arch/arm/kernel/setup.c | 2 | ||||
| -rw-r--r-- | arch/arm/mm/dma-mapping.c | 84 | ||||
| -rw-r--r-- | drivers/iommu/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/iommu/iommu.c | 2 | ||||
| -rw-r--r-- | drivers/iommu/of_iommu.c | 89 | ||||
| -rw-r--r-- | drivers/of/platform.c | 50 | ||||
| -rw-r--r-- | include/asm-generic/vmlinux.lds.h | 2 | ||||
| -rw-r--r-- | include/linux/dma-mapping.h | 13 | ||||
| -rw-r--r-- | include/linux/iommu.h | 8 | ||||
| -rw-r--r-- | include/linux/of_iommu.h | 23 |
11 files changed, 243 insertions, 45 deletions
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index e6e3446abdf6..b52101d37ec7 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h | |||
| @@ -121,13 +121,12 @@ static inline unsigned long dma_max_pfn(struct device *dev) | |||
| 121 | } | 121 | } |
| 122 | #define dma_max_pfn(dev) dma_max_pfn(dev) | 122 | #define dma_max_pfn(dev) dma_max_pfn(dev) |
| 123 | 123 | ||
| 124 | static inline int set_arch_dma_coherent_ops(struct device *dev) | 124 | #define arch_setup_dma_ops arch_setup_dma_ops |
| 125 | { | 125 | extern void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, |
| 126 | dev->archdata.dma_coherent = true; | 126 | struct iommu_ops *iommu, bool coherent); |
| 127 | set_dma_ops(dev, &arm_coherent_dma_ops); | 127 | |
| 128 | return 0; | 128 | #define arch_teardown_dma_ops arch_teardown_dma_ops |
| 129 | } | 129 | extern void arch_teardown_dma_ops(struct device *dev); |
| 130 | #define set_arch_dma_coherent_ops(dev) set_arch_dma_coherent_ops(dev) | ||
| 131 | 130 | ||
| 132 | /* do not use this function in a driver */ | 131 | /* do not use this function in a driver */ |
| 133 | static inline bool is_device_dma_coherent(struct device *dev) | 132 | static inline bool is_device_dma_coherent(struct device *dev) |
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 8361652b6dab..f9c863911038 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/bootmem.h> | 18 | #include <linux/bootmem.h> |
| 19 | #include <linux/seq_file.h> | 19 | #include <linux/seq_file.h> |
| 20 | #include <linux/screen_info.h> | 20 | #include <linux/screen_info.h> |
| 21 | #include <linux/of_iommu.h> | ||
| 21 | #include <linux/of_platform.h> | 22 | #include <linux/of_platform.h> |
| 22 | #include <linux/init.h> | 23 | #include <linux/init.h> |
| 23 | #include <linux/kexec.h> | 24 | #include <linux/kexec.h> |
| @@ -806,6 +807,7 @@ static int __init customize_machine(void) | |||
| 806 | * machine from the device tree, if no callback is provided, | 807 | * machine from the device tree, if no callback is provided, |
| 807 | * otherwise we would always need an init_machine callback. | 808 | * otherwise we would always need an init_machine callback. |
| 808 | */ | 809 | */ |
| 810 | of_iommu_init(); | ||
| 809 | if (machine_desc->init_machine) | 811 | if (machine_desc->init_machine) |
| 810 | machine_desc->init_machine(); | 812 | machine_desc->init_machine(); |
| 811 | #ifdef CONFIG_OF | 813 | #ifdef CONFIG_OF |
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index e8907117861e..7864797609b3 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c | |||
| @@ -1947,9 +1947,8 @@ EXPORT_SYMBOL_GPL(arm_iommu_release_mapping); | |||
| 1947 | * arm_iommu_create_mapping) | 1947 | * arm_iommu_create_mapping) |
| 1948 | * | 1948 | * |
| 1949 | * Attaches specified io address space mapping to the provided device, | 1949 | * Attaches specified io address space mapping to the provided device, |
| 1950 | * this replaces the dma operations (dma_map_ops pointer) with the | 1950 | * More than one client might be attached to the same io address space |
| 1951 | * IOMMU aware version. More than one client might be attached to | 1951 | * mapping. |
| 1952 | * the same io address space mapping. | ||
| 1953 | */ | 1952 | */ |
| 1954 | int arm_iommu_attach_device(struct device *dev, | 1953 | int arm_iommu_attach_device(struct device *dev, |
| 1955 | struct dma_iommu_mapping *mapping) | 1954 | struct dma_iommu_mapping *mapping) |
| @@ -1962,7 +1961,6 @@ int arm_iommu_attach_device(struct device *dev, | |||
| 1962 | 1961 | ||
| 1963 | kref_get(&mapping->kref); | 1962 | kref_get(&mapping->kref); |
| 1964 | dev->archdata.mapping = mapping; | 1963 | dev->archdata.mapping = mapping; |
| 1965 | set_dma_ops(dev, &iommu_ops); | ||
| 1966 | 1964 | ||
| 1967 | pr_debug("Attached IOMMU controller to %s device.\n", dev_name(dev)); | 1965 | pr_debug("Attached IOMMU controller to %s device.\n", dev_name(dev)); |
| 1968 | return 0; | 1966 | return 0; |
| @@ -1974,7 +1972,6 @@ EXPORT_SYMBOL_GPL(arm_iommu_attach_device); | |||
| 1974 | * @dev: valid struct device pointer | 1972 | * @dev: valid struct device pointer |
| 1975 | * | 1973 | * |
| 1976 | * Detaches the provided device from a previously attached map. | 1974 | * Detaches the provided device from a previously attached map. |
| 1977 | * This voids the dma operations (dma_map_ops pointer) | ||
| 1978 | */ | 1975 | */ |
| 1979 | void arm_iommu_detach_device(struct device *dev) | 1976 | void arm_iommu_detach_device(struct device *dev) |
| 1980 | { | 1977 | { |
| @@ -1989,10 +1986,83 @@ void arm_iommu_detach_device(struct device *dev) | |||
| 1989 | iommu_detach_device(mapping->domain, dev); | 1986 | iommu_detach_device(mapping->domain, dev); |
| 1990 | kref_put(&mapping->kref, release_iommu_mapping); | 1987 | kref_put(&mapping->kref, release_iommu_mapping); |
| 1991 | dev->archdata.mapping = NULL; | 1988 | dev->archdata.mapping = NULL; |
| 1992 | set_dma_ops(dev, NULL); | ||
| 1993 | 1989 | ||
| 1994 | pr_debug("Detached IOMMU controller from %s device.\n", dev_name(dev)); | 1990 | pr_debug("Detached IOMMU controller from %s device.\n", dev_name(dev)); |
| 1995 | } | 1991 | } |
| 1996 | EXPORT_SYMBOL_GPL(arm_iommu_detach_device); | 1992 | EXPORT_SYMBOL_GPL(arm_iommu_detach_device); |
| 1997 | 1993 | ||
| 1998 | #endif | 1994 | static struct dma_map_ops *arm_get_iommu_dma_map_ops(bool coherent) |
| 1995 | { | ||
| 1996 | return coherent ? &iommu_coherent_ops : &iommu_ops; | ||
| 1997 | } | ||
| 1998 | |||
| 1999 | static bool arm_setup_iommu_dma_ops(struct device *dev, u64 dma_base, u64 size, | ||
| 2000 | struct iommu_ops *iommu) | ||
| 2001 | { | ||
| 2002 | struct dma_iommu_mapping *mapping; | ||
| 2003 | |||
| 2004 | if (!iommu) | ||
| 2005 | return false; | ||
| 2006 | |||
| 2007 | mapping = arm_iommu_create_mapping(dev->bus, dma_base, size); | ||
| 2008 | if (IS_ERR(mapping)) { | ||
| 2009 | pr_warn("Failed to create %llu-byte IOMMU mapping for device %s\n", | ||
| 2010 | size, dev_name(dev)); | ||
| 2011 | return false; | ||
| 2012 | } | ||
| 2013 | |||
| 2014 | if (arm_iommu_attach_device(dev, mapping)) { | ||
| 2015 | pr_warn("Failed to attached device %s to IOMMU_mapping\n", | ||
| 2016 | dev_name(dev)); | ||
| 2017 | arm_iommu_release_mapping(mapping); | ||
| 2018 | return false; | ||
| 2019 | } | ||
| 2020 | |||
| 2021 | return true; | ||
| 2022 | } | ||
| 2023 | |||
| 2024 | static void arm_teardown_iommu_dma_ops(struct device *dev) | ||
| 2025 | { | ||
| 2026 | struct dma_iommu_mapping *mapping = dev->archdata.mapping; | ||
| 2027 | |||
| 2028 | arm_iommu_detach_device(dev); | ||
| 2029 | arm_iommu_release_mapping(mapping); | ||
| 2030 | } | ||
| 2031 | |||
| 2032 | #else | ||
| 2033 | |||
| 2034 | static bool arm_setup_iommu_dma_ops(struct device *dev, u64 dma_base, u64 size, | ||
| 2035 | struct iommu_ops *iommu) | ||
| 2036 | { | ||
| 2037 | return false; | ||
| 2038 | } | ||
| 2039 | |||
| 2040 | static void arm_teardown_iommu_dma_ops(struct device *dev) { } | ||
| 2041 | |||
| 2042 | #define arm_get_iommu_dma_map_ops arm_get_dma_map_ops | ||
| 2043 | |||
| 2044 | #endif /* CONFIG_ARM_DMA_USE_IOMMU */ | ||
| 2045 | |||
| 2046 | static struct dma_map_ops *arm_get_dma_map_ops(bool coherent) | ||
| 2047 | { | ||
| 2048 | return coherent ? &arm_coherent_dma_ops : &arm_dma_ops; | ||
| 2049 | } | ||
| 2050 | |||
| 2051 | void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, | ||
| 2052 | struct iommu_ops *iommu, bool coherent) | ||
| 2053 | { | ||
| 2054 | struct dma_map_ops *dma_ops; | ||
| 2055 | |||
| 2056 | dev->archdata.dma_coherent = coherent; | ||
| 2057 | if (arm_setup_iommu_dma_ops(dev, dma_base, size, iommu)) | ||
| 2058 | dma_ops = arm_get_iommu_dma_map_ops(coherent); | ||
| 2059 | else | ||
| 2060 | dma_ops = arm_get_dma_map_ops(coherent); | ||
| 2061 | |||
| 2062 | set_dma_ops(dev, dma_ops); | ||
| 2063 | } | ||
| 2064 | |||
| 2065 | void arch_teardown_dma_ops(struct device *dev) | ||
| 2066 | { | ||
| 2067 | arm_teardown_iommu_dma_ops(dev); | ||
| 2068 | } | ||
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 2fbe3b1dc92d..325188eef1c1 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig | |||
| @@ -15,7 +15,7 @@ if IOMMU_SUPPORT | |||
| 15 | 15 | ||
| 16 | config OF_IOMMU | 16 | config OF_IOMMU |
| 17 | def_bool y | 17 | def_bool y |
| 18 | depends on OF | 18 | depends on OF && IOMMU_API |
| 19 | 19 | ||
| 20 | config FSL_PAMU | 20 | config FSL_PAMU |
| 21 | bool "Freescale IOMMU support" | 21 | bool "Freescale IOMM |
