diff options
| -rw-r--r-- | arch/arm/include/asm/dma-mapping.h | 12 | ||||
| -rw-r--r-- | arch/arm/mm/dma-mapping.c | 83 |
2 files changed, 81 insertions, 14 deletions
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index f3c0d953f6a2..9410b7e548fc 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h | |||
| @@ -121,14 +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 void arch_setup_dma_ops(struct device *dev, u64 dma_base, | ||
| 125 | u64 size, struct iommu_ops *iommu, | ||
| 126 | bool coherent) | ||
| 127 | { | ||
| 128 | if (coherent) | ||
| 129 | set_dma_ops(dev, &arm_coherent_dma_ops); | ||
| 130 | } | ||
| 131 | #define arch_setup_dma_ops arch_setup_dma_ops | 124 | #define arch_setup_dma_ops arch_setup_dma_ops |
| 125 | extern void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, | ||
| 126 | struct iommu_ops *iommu, bool coherent); | ||
| 127 | |||
| 128 | #define arch_teardown_dma_ops arch_teardown_dma_ops | ||
| 129 | extern void arch_teardown_dma_ops(struct device *dev); | ||
| 132 | 130 | ||
| 133 | static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) | 131 | static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) |
| 134 | { | 132 | { |
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index e8907117861e..09645f00bd17 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,82 @@ 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 | if (arm_setup_iommu_dma_ops(dev, dma_base, size, iommu)) | ||
| 2057 | dma_ops = arm_get_iommu_dma_map_ops(coherent); | ||
| 2058 | else | ||
| 2059 | dma_ops = arm_get_dma_map_ops(coherent); | ||
| 2060 | |||
| 2061 | set_dma_ops(dev, dma_ops); | ||
| 2062 | } | ||
| 2063 | |||
| 2064 | void arch_teardown_dma_ops(struct device *dev) | ||
| 2065 | { | ||
| 2066 | arm_teardown_iommu_dma_ops(dev); | ||
| 2067 | } | ||
