From 5f852147b35dd4f100bf5102ceb4650bcc7063b9 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 7 Feb 2019 12:59:15 +0100 Subject: [PATCH 2678/2944] dma: Introduce dma_max_mapping_size() to #39258954 commit 133d624b1cee16906134e92d5befb843b58bcf31 upstream The function returns the maximum size that can be mapped using DMA-API functions. The patch also adds the implementation for direct DMA and a new dma_map_ops pointer so that other implementations can expose their limit. [Zelin Deng: fix dma_is_direct() missing error and build error on arm] Cc: stable@vger.kernel.org Reviewed-by: Konrad Rzeszutek Wilk Reviewed-by: Christoph Hellwig Signed-off-by: Joerg Roedel Signed-off-by: Michael S. Tsirkin Signed-off-by: Zelin Deng Reviewed-by: Artie Ding Reviewed-by: Baolin Wang --- Documentation/DMA-API.txt | 8 ++++++++ include/linux/dma-mapping.h | 9 +++++++++ kernel/dma/direct.c | 11 +++++++++++ kernel/dma/mapping.c | 14 ++++++++++++++ 4 files changed, 42 insertions(+) diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt index ac66ae2..87fa256 100644 --- a/Documentation/DMA-API.txt +++ b/Documentation/DMA-API.txt @@ -204,6 +204,14 @@ Requesting the required mask does not alter the current mask. If you wish to take advantage of it, you should issue a dma_set_mask() call to set the mask to the value returned. +:: + + size_t + dma_direct_max_mapping_size(struct device *dev); + +Returns the maximum size of a mapping for the device. The size parameter +of the mapping functions like dma_map_single(), dma_map_page() and +others should not be larger than the returned value. Part Id - Streaming DMA mappings -------------------------------- diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index ebe5b37..4bb23fa 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -11,6 +11,7 @@ #include #include #include +#include /** * List of possible attributes associated with a DMA mapping. The semantics @@ -133,6 +134,7 @@ struct dma_map_ops { #ifdef ARCH_HAS_DMA_GET_REQUIRED_MASK u64 (*get_required_mask)(struct device *dev); #endif + size_t (*max_mapping_size)(struct device *dev); }; #define DMA_MAPPING_ERROR (~(dma_addr_t)0) @@ -198,6 +200,8 @@ static inline int dma_mmap_from_global_coherent(struct vm_area_struct *vma, } #endif /* CONFIG_HAVE_GENERIC_DMA_COHERENT */ +size_t dma_direct_max_mapping_size(struct device *dev); + #ifdef CONFIG_HAS_DMA #include static inline const struct dma_map_ops *get_dma_ops(struct device *dev) @@ -777,12 +781,17 @@ extern void *dmam_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp); extern void dmam_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle); +size_t dma_max_mapping_size(struct device *dev); #else /* !CONFIG_HAS_DMA */ static inline void *dmam_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp) { return NULL; } static inline void dmam_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle) { } +static inline size_t dma_max_mapping_size(struct device *dev) +{ + return 0; +} #endif /* !CONFIG_HAS_DMA */ extern void *dmam_alloc_attrs(struct device *dev, size_t size, diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c index 1d2f147..a608b37 100644 --- a/kernel/dma/direct.c +++ b/kernel/dma/direct.c @@ -198,6 +198,17 @@ int dma_direct_supported(struct device *dev, u64 mask) return 1; } +size_t dma_direct_max_mapping_size(struct device *dev) +{ + size_t size = SIZE_MAX; + + /* If SWIOTLB is active, use its maximum mapping size */ + if (is_swiotlb_active()) + size = swiotlb_max_mapping_size(dev); + + return size; +} + int dma_direct_mapping_error(struct device *dev, dma_addr_t dma_addr) { return dma_addr == DIRECT_MAPPING_ERROR; diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c index d2a92dd..a700c8c 100644 --- a/kernel/dma/mapping.c +++ b/kernel/dma/mapping.c @@ -328,6 +328,20 @@ void dma_common_free_remap(void *cpu_addr, size_t size, unsigned long vm_flags) } #endif +size_t dma_max_mapping_size(struct device *dev) +{ + const struct dma_map_ops *ops = get_dma_ops(dev); + size_t size = SIZE_MAX; + + if (!ops) + size = dma_direct_max_mapping_size(dev); + else if (ops && ops->max_mapping_size) + size = ops->max_mapping_size(dev); + + return size; +} +EXPORT_SYMBOL_GPL(dma_max_mapping_size); + /* * enables DMA API use for a device */ -- 1.8.3.1