dma-direct: make uncached_kernel_address more general

Rename the symbol to arch_dma_set_uncached, and pass a size to it as
well as allow an error return.  That will allow reusing this hook for
in-place pagetable remapping.

As the in-place remap doesn't always require an explicit cache flush,
also detangle ARCH_HAS_DMA_PREP_COHERENT from ARCH_HAS_DMA_SET_UNCACHED.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
This commit is contained in:
Christoph Hellwig 2020-02-21 15:55:43 -08:00
parent 3d0fc341c4
commit fa7e2247c5
11 changed files with 21 additions and 17 deletions

View File

@ -248,11 +248,11 @@ config ARCH_HAS_SET_DIRECT_MAP
bool
#
# Select if arch has an uncached kernel segment and provides the
# uncached_kernel_address symbol to use it
# Select if the architecture provides the arch_dma_set_uncached symbol to
# either provide an uncached segement alias for a DMA allocation, or
# to remap the page tables in place.
#
config ARCH_HAS_UNCACHED_SEGMENT
select ARCH_HAS_DMA_PREP_COHERENT
config ARCH_HAS_DMA_SET_UNCACHED
bool
# Select if arch init_task must go in the __init_task_data section

View File

@ -8,7 +8,7 @@ config MICROBLAZE
select ARCH_HAS_GCOV_PROFILE_ALL
select ARCH_HAS_SYNC_DMA_FOR_CPU
select ARCH_HAS_SYNC_DMA_FOR_DEVICE
select ARCH_HAS_UNCACHED_SEGMENT if !MMU
select ARCH_HAS_DMA_SET_UNCACHED if !MMU
select ARCH_MIGHT_HAVE_PC_PARPORT
select ARCH_WANT_IPC_PARSE_VERSION
select BUILDTIME_TABLE_SORT

View File

@ -40,7 +40,7 @@ void arch_dma_prep_coherent(struct page *page, size_t size)
#define UNCACHED_SHADOW_MASK 0
#endif /* CONFIG_XILINX_UNCACHED_SHADOW */
void *uncached_kernel_address(void *ptr)
void *arch_dma_set_uncached(void *ptr, size_t size)
{
unsigned long addr = (unsigned long)ptr;

View File

@ -1187,8 +1187,9 @@ config DMA_NONCOHERENT
# significant advantages.
#
select ARCH_HAS_DMA_WRITE_COMBINE
select ARCH_HAS_DMA_PREP_COHERENT
select ARCH_HAS_SYNC_DMA_FOR_DEVICE
select ARCH_HAS_UNCACHED_SEGMENT
select ARCH_HAS_DMA_SET_UNCACHED
select DMA_NONCOHERENT_MMAP
select DMA_NONCOHERENT_CACHE_SYNC
select NEED_DMA_MAP_STATE

View File

@ -49,7 +49,7 @@ void arch_dma_prep_coherent(struct page *page, size_t size)
dma_cache_wback_inv((unsigned long)page_address(page), size);
}
void *uncached_kernel_address(void *addr)
void *arch_dma_set_uncached(void *addr, size_t size)
{
return (void *)(__pa(addr) + UNCAC_BASE);
}

View File

@ -2,9 +2,10 @@
config NIOS2
def_bool y
select ARCH_32BIT_OFF_T
select ARCH_HAS_DMA_PREP_COHERENT
select ARCH_HAS_SYNC_DMA_FOR_CPU
select ARCH_HAS_SYNC_DMA_FOR_DEVICE
select ARCH_HAS_UNCACHED_SEGMENT
select ARCH_HAS_DMA_SET_UNCACHED
select ARCH_NO_SWAP
select TIMER_OF
select GENERIC_ATOMIC64

View File

@ -67,7 +67,7 @@ void arch_dma_prep_coherent(struct page *page, size_t size)
flush_dcache_range(start, start + size);
}
void *uncached_kernel_address(void *ptr)
void *arch_dma_set_uncached(void *ptr, size_t size)
{
unsigned long addr = (unsigned long)ptr;

View File

@ -6,7 +6,7 @@ config XTENSA
select ARCH_HAS_DMA_PREP_COHERENT if MMU
select ARCH_HAS_SYNC_DMA_FOR_CPU if MMU
select ARCH_HAS_SYNC_DMA_FOR_DEVICE if MMU
select ARCH_HAS_UNCACHED_SEGMENT if MMU
select ARCH_HAS_DMA_SET_UNCACHED if MMU
select ARCH_USE_QUEUED_RWLOCKS
select ARCH_USE_QUEUED_SPINLOCKS
select ARCH_WANT_FRAME_POINTERS

View File

@ -92,7 +92,7 @@ void arch_dma_prep_coherent(struct page *page, size_t size)
* coherent DMA memory operations when CONFIG_MMU is not enabled.
*/
#ifdef CONFIG_MMU
void *uncached_kernel_address(void *p)
void *arch_dma_set_uncached(void *p, size_t size)
{
return p + XCHAL_KSEG_BYPASS_VADDR - XCHAL_KSEG_CACHED_VADDR;
}

View File

@ -108,6 +108,6 @@ static inline void arch_dma_prep_coherent(struct page *page, size_t size)
}
#endif /* CONFIG_ARCH_HAS_DMA_PREP_COHERENT */
void *uncached_kernel_address(void *addr);
void *arch_dma_set_uncached(void *addr, size_t size);
#endif /* _LINUX_DMA_NONCOHERENT_H */

View File

@ -192,10 +192,12 @@ void *dma_direct_alloc_pages(struct device *dev, size_t size,
memset(ret, 0, size);
if (IS_ENABLED(CONFIG_ARCH_HAS_UNCACHED_SEGMENT) &&
if (IS_ENABLED(CONFIG_ARCH_HAS_DMA_SET_UNCACHED) &&
dma_alloc_need_uncached(dev, attrs)) {
arch_dma_prep_coherent(page, size);
ret = uncached_kernel_address(ret);
ret = arch_dma_set_uncached(ret, size);
if (IS_ERR(ret))
goto out_free_pages;
}
done:
if (force_dma_unencrypted(dev))
@ -236,7 +238,7 @@ void dma_direct_free_pages(struct device *dev, size_t size, void *cpu_addr,
void *dma_direct_alloc(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
{
if (!IS_ENABLED(CONFIG_ARCH_HAS_UNCACHED_SEGMENT) &&
if (!IS_ENABLED(CONFIG_ARCH_HAS_DMA_SET_UNCACHED) &&
!IS_ENABLED(CONFIG_DMA_DIRECT_REMAP) &&
dma_alloc_need_uncached(dev, attrs))
return arch_dma_alloc(dev, size, dma_handle, gfp, attrs);
@ -246,7 +248,7 @@ void *dma_direct_alloc(struct device *dev, size_t size,
void dma_direct_free(struct device *dev, size_t size,
void *cpu_addr, dma_addr_t dma_addr, unsigned long attrs)
{
if (!IS_ENABLED(CONFIG_ARCH_HAS_UNCACHED_SEGMENT) &&
if (!IS_ENABLED(CONFIG_ARCH_HAS_DMA_SET_UNCACHED) &&
!IS_ENABLED(CONFIG_DMA_DIRECT_REMAP) &&
dma_alloc_need_uncached(dev, attrs))
arch_dma_free(dev, size, cpu_addr, dma_addr, attrs);