Commit 9d3bfbb4 authored by Catalin Marinas's avatar Catalin Marinas

arm64: Combine coherent and non-coherent swiotlb dma_ops

Since dev_archdata now has a dma_coherent state, combine the two
coherent and non-coherent operations and remove their declaration,
together with set_dma_ops, from the arch dma-mapping.h file.
Acked-by: default avatarWill Deacon <will.deacon@arm.com>
Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
parent 9f71ac96
...@@ -28,8 +28,6 @@ ...@@ -28,8 +28,6 @@
#define DMA_ERROR_CODE (~(dma_addr_t)0) #define DMA_ERROR_CODE (~(dma_addr_t)0)
extern struct dma_map_ops *dma_ops; extern struct dma_map_ops *dma_ops;
extern struct dma_map_ops coherent_swiotlb_dma_ops;
extern struct dma_map_ops noncoherent_swiotlb_dma_ops;
static inline struct dma_map_ops *__generic_dma_ops(struct device *dev) static inline struct dma_map_ops *__generic_dma_ops(struct device *dev)
{ {
...@@ -47,23 +45,18 @@ static inline struct dma_map_ops *get_dma_ops(struct device *dev) ...@@ -47,23 +45,18 @@ static inline struct dma_map_ops *get_dma_ops(struct device *dev)
return __generic_dma_ops(dev); return __generic_dma_ops(dev);
} }
static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops)
{
dev->archdata.dma_ops = ops;
}
static inline void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, static inline void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
struct iommu_ops *iommu, bool coherent) struct iommu_ops *iommu, bool coherent)
{ {
dev->archdata.dma_coherent = coherent; dev->archdata.dma_coherent = coherent;
if (coherent)
set_dma_ops(dev, &coherent_swiotlb_dma_ops);
} }
#define arch_setup_dma_ops arch_setup_dma_ops #define arch_setup_dma_ops arch_setup_dma_ops
/* do not use this function in a driver */ /* do not use this function in a driver */
static inline bool is_device_dma_coherent(struct device *dev) static inline bool is_device_dma_coherent(struct device *dev)
{ {
if (!dev)
return false;
return dev->archdata.dma_coherent; return dev->archdata.dma_coherent;
} }
......
...@@ -134,16 +134,17 @@ static void __dma_free_coherent(struct device *dev, size_t size, ...@@ -134,16 +134,17 @@ static void __dma_free_coherent(struct device *dev, size_t size,
swiotlb_free_coherent(dev, size, vaddr, dma_handle); swiotlb_free_coherent(dev, size, vaddr, dma_handle);
} }
static void *__dma_alloc_noncoherent(struct device *dev, size_t size, static void *__dma_alloc(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flags, dma_addr_t *dma_handle, gfp_t flags,
struct dma_attrs *attrs) struct dma_attrs *attrs)
{ {
struct page *page; struct page *page;
void *ptr, *coherent_ptr; void *ptr, *coherent_ptr;
bool coherent = is_device_dma_coherent(dev);
size = PAGE_ALIGN(size); size = PAGE_ALIGN(size);
if (!(flags & __GFP_WAIT)) { if (!coherent && !(flags & __GFP_WAIT)) {
struct page *page = NULL; struct page *page = NULL;
void *addr = __alloc_from_pool(size, &page); void *addr = __alloc_from_pool(size, &page);
...@@ -151,13 +152,16 @@ static void *__dma_alloc_noncoherent(struct device *dev, size_t size, ...@@ -151,13 +152,16 @@ static void *__dma_alloc_noncoherent(struct device *dev, size_t size,
*dma_handle = phys_to_dma(dev, page_to_phys(page)); *dma_handle = phys_to_dma(dev, page_to_phys(page));
return addr; return addr;
} }
ptr = __dma_alloc_coherent(dev, size, dma_handle, flags, attrs); ptr = __dma_alloc_coherent(dev, size, dma_handle, flags, attrs);
if (!ptr) if (!ptr)
goto no_mem; goto no_mem;
/* no need for non-cacheable mapping if coherent */
if (coherent)
return ptr;
/* remove any dirty cache lines on the kernel alias */ /* remove any dirty cache lines on the kernel alias */
__dma_flush_range(ptr, ptr + size); __dma_flush_range(ptr, ptr + size);
...@@ -179,15 +183,17 @@ static void *__dma_alloc_noncoherent(struct device *dev, size_t size, ...@@ -179,15 +183,17 @@ static void *__dma_alloc_noncoherent(struct device *dev, size_t size,
return NULL; return NULL;
} }
static void __dma_free_noncoherent(struct device *dev, size_t size, static void __dma_free(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle, void *vaddr, dma_addr_t dma_handle,
struct dma_attrs *attrs) struct dma_attrs *attrs)
{ {
void *swiotlb_addr = phys_to_virt(dma_to_phys(dev, dma_handle)); void *swiotlb_addr = phys_to_virt(dma_to_phys(dev, dma_handle));
if (__free_from_pool(vaddr, size)) if (!is_device_dma_coherent(dev)) {
return; if (__free_from_pool(vaddr, size))
vunmap(vaddr); return;
vunmap(vaddr);
}
__dma_free_coherent(dev, size, swiotlb_addr, dma_handle, attrs); __dma_free_coherent(dev, size, swiotlb_addr, dma_handle, attrs);
} }
...@@ -199,7 +205,8 @@ static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page, ...@@ -199,7 +205,8 @@ static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,
dma_addr_t dev_addr; dma_addr_t dev_addr;
dev_addr = swiotlb_map_page(dev, page, offset, size, dir, attrs); dev_addr = swiotlb_map_page(dev, page, offset, size, dir, attrs);
__dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir); if (!is_device_dma_coherent(dev))
__dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
return dev_addr; return dev_addr;
} }
...@@ -209,7 +216,8 @@ static void __swiotlb_unmap_page(struct device *dev, dma_addr_t dev_addr, ...@@ -209,7 +216,8 @@ static void __swiotlb_unmap_page(struct device *dev, dma_addr_t dev_addr,
size_t size, enum dma_data_direction dir, size_t size, enum dma_data_direction dir,
struct dma_attrs *attrs) struct dma_attrs *attrs)
{ {
__dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir); if (!is_device_dma_coherent(dev))
__dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
swiotlb_unmap_page(dev, dev_addr, size, dir, attrs); swiotlb_unmap_page(dev, dev_addr, size, dir, attrs);
} }
...@@ -221,9 +229,10 @@ static int __swiotlb_map_sg_attrs(struct device *dev, struct scatterlist *sgl, ...@@ -221,9 +229,10 @@ static int __swiotlb_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
int i, ret; int i, ret;
ret = swiotlb_map_sg_attrs(dev, sgl, nelems, dir, attrs); ret = swiotlb_map_sg_attrs(dev, sgl, nelems, dir, attrs);
for_each_sg(sgl, sg, ret, i) if (!is_device_dma_coherent(dev))
__dma_map_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)), for_each_sg(sgl, sg, ret, i)
sg->length, dir); __dma_map_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)),
sg->length, dir);
return ret; return ret;
} }
...@@ -236,9 +245,10 @@ static void __swiotlb_unmap_sg_attrs(struct device *dev, ...@@ -236,9 +245,10 @@ static void __swiotlb_unmap_sg_attrs(struct device *dev,
struct scatterlist *sg; struct scatterlist *sg;
int i; int i;
for_each_sg(sgl, sg, nelems, i) if (!is_device_dma_coherent(dev))
__dma_unmap_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)), for_each_sg(sgl, sg, nelems, i)
sg->length, dir); __dma_unmap_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)),
sg->length, dir);
swiotlb_unmap_sg_attrs(dev, sgl, nelems, dir, attrs); swiotlb_unmap_sg_attrs(dev, sgl, nelems, dir, attrs);
} }
...@@ -246,7 +256,8 @@ static void __swiotlb_sync_single_for_cpu(struct device *dev, ...@@ -246,7 +256,8 @@ static void __swiotlb_sync_single_for_cpu(struct device *dev,
dma_addr_t dev_addr, size_t size, dma_addr_t dev_addr, size_t size,
enum dma_data_direction dir) enum dma_data_direction dir)
{ {
__dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir); if (!is_device_dma_coherent(dev))
__dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
swiotlb_sync_single_for_cpu(dev, dev_addr, size, dir); swiotlb_sync_single_for_cpu(dev, dev_addr, size, dir);
} }
...@@ -255,7 +266,8 @@ static void __swiotlb_sync_single_for_device(struct device *dev, ...@@ -255,7 +266,8 @@ static void __swiotlb_sync_single_for_device(struct device *dev,
enum dma_data_direction dir) enum dma_data_direction dir)
{ {
swiotlb_sync_single_for_device(dev, dev_addr, size, dir); swiotlb_sync_single_for_device(dev, dev_addr, size, dir);
__dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir); if (!is_device_dma_coherent(dev))
__dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
} }
static void __swiotlb_sync_sg_for_cpu(struct device *dev, static void __swiotlb_sync_sg_for_cpu(struct device *dev,
...@@ -265,9 +277,10 @@ static void __swiotlb_sync_sg_for_cpu(struct device *dev, ...@@ -265,9 +277,10 @@ static void __swiotlb_sync_sg_for_cpu(struct device *dev,
struct scatterlist *sg; struct scatterlist *sg;
int i; int i;
for_each_sg(sgl, sg, nelems, i) if (!is_device_dma_coherent(dev))
__dma_unmap_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)), for_each_sg(sgl, sg, nelems, i)
sg->length, dir); __dma_unmap_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)),
sg->length, dir);
swiotlb_sync_sg_for_cpu(dev, sgl, nelems, dir); swiotlb_sync_sg_for_cpu(dev, sgl, nelems, dir);
} }
...@@ -279,9 +292,10 @@ static void __swiotlb_sync_sg_for_device(struct device *dev, ...@@ -279,9 +292,10 @@ static void __swiotlb_sync_sg_for_device(struct device *dev,
int i; int i;
swiotlb_sync_sg_for_device(dev, sgl, nelems, dir); swiotlb_sync_sg_for_device(dev, sgl, nelems, dir);
for_each_sg(sgl, sg, nelems, i) if (!is_device_dma_coherent(dev))
__dma_map_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)), for_each_sg(sgl, sg, nelems, i)
sg->length, dir); __dma_map_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)),
sg->length, dir);
} }
/* vma->vm_page_prot must be set appropriately before calling this function */ /* vma->vm_page_prot must be set appropriately before calling this function */
...@@ -308,28 +322,20 @@ static int __dma_common_mmap(struct device *dev, struct vm_area_struct *vma, ...@@ -308,28 +322,20 @@ static int __dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
return ret; return ret;
} }
static int __swiotlb_mmap_noncoherent(struct device *dev, static int __swiotlb_mmap(struct device *dev,
struct vm_area_struct *vma, struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t dma_addr, size_t size, void *cpu_addr, dma_addr_t dma_addr, size_t size,
struct dma_attrs *attrs) struct dma_attrs *attrs)
{
vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot, false);
return __dma_common_mmap(dev, vma, cpu_addr, dma_addr, size);
}
static int __swiotlb_mmap_coherent(struct device *dev,
struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t dma_addr, size_t size,
struct dma_attrs *attrs)
{ {
/* Just use whatever page_prot attributes were specified */ vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot,
is_device_dma_coherent(dev));
return __dma_common_mmap(dev, vma, cpu_addr, dma_addr, size); return __dma_common_mmap(dev, vma, cpu_addr, dma_addr, size);
} }
struct dma_map_ops noncoherent_swiotlb_dma_ops = { static struct dma_map_ops swiotlb_dma_ops = {
.alloc = __dma_alloc_noncoherent, .alloc = __dma_alloc,
.free = __dma_free_noncoherent, .free = __dma_free,
.mmap = __swiotlb_mmap_noncoherent, .mmap = __swiotlb_mmap,
.map_page = __swiotlb_map_page, .map_page = __swiotlb_map_page,
.unmap_page = __swiotlb_unmap_page, .unmap_page = __swiotlb_unmap_page,
.map_sg = __swiotlb_map_sg_attrs, .map_sg = __swiotlb_map_sg_attrs,
...@@ -341,24 +347,6 @@ struct dma_map_ops noncoherent_swiotlb_dma_ops = { ...@@ -341,24 +347,6 @@ struct dma_map_ops noncoherent_swiotlb_dma_ops = {
.dma_supported = swiotlb_dma_supported, .dma_supported = swiotlb_dma_supported,
.mapping_error = swiotlb_dma_mapping_error, .mapping_error = swiotlb_dma_mapping_error,
}; };
EXPORT_SYMBOL(noncoherent_swiotlb_dma_ops);
struct dma_map_ops coherent_swiotlb_dma_ops = {
.alloc = __dma_alloc_coherent,
.free = __dma_free_coherent,
.mmap = __swiotlb_mmap_coherent,
.map_page = swiotlb_map_page,
.unmap_page = swiotlb_unmap_page,
.map_sg = swiotlb_map_sg_attrs,
.unmap_sg = swiotlb_unmap_sg_attrs,
.sync_single_for_cpu = swiotlb_sync_single_for_cpu,
.sync_single_for_device = swiotlb_sync_single_for_device,
.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
.sync_sg_for_device = swiotlb_sync_sg_for_device,
.dma_supported = swiotlb_dma_supported,
.mapping_error = swiotlb_dma_mapping_error,
};
EXPORT_SYMBOL(coherent_swiotlb_dma_ops);
extern int swiotlb_late_init_with_default_size(size_t default_size); extern int swiotlb_late_init_with_default_size(size_t default_size);
...@@ -427,7 +415,7 @@ static int __init swiotlb_late_init(void) ...@@ -427,7 +415,7 @@ static int __init swiotlb_late_init(void)
{ {
size_t swiotlb_size = min(SZ_64M, MAX_ORDER_NR_PAGES << PAGE_SHIFT); size_t swiotlb_size = min(SZ_64M, MAX_ORDER_NR_PAGES << PAGE_SHIFT);
dma_ops = &noncoherent_swiotlb_dma_ops; dma_ops = &swiotlb_dma_ops;
return swiotlb_late_init_with_default_size(swiotlb_size); return swiotlb_late_init_with_default_size(swiotlb_size);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment