mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 11:50:43 +09:00
ANDROID: GKI: add dma_map_ops remap/unremap operations
Trimmed down version of: 4008eb493aa2 "iommu/arm-smmu: Merge of smmu changes from 4.14" which includes only changes required for removed-dma-pool driver. Bug: 145617272 Signed-off-by: Swathi Sridhar <swatsrid@codeaurora.org> Signed-off-by: Suren Baghdasaryan <surenb@google.com> Change-Id: I4b9ae665aaf8aabf89c3b158bc38db458f31657a
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
static int swiotlb __ro_after_init;
|
||||
|
||||
@@ -321,6 +322,56 @@ static int __swiotlb_dma_supported(struct device *hwdev, u64 mask)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void *arm64_dma_remap(struct device *dev, void *cpu_addr,
|
||||
dma_addr_t handle, size_t size,
|
||||
unsigned long attrs)
|
||||
{
|
||||
struct page *page = phys_to_page(dma_to_phys(dev, handle));
|
||||
bool coherent = is_device_dma_coherent(dev);
|
||||
pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL, coherent);
|
||||
unsigned long offset = handle & ~PAGE_MASK;
|
||||
struct vm_struct *area;
|
||||
unsigned long addr;
|
||||
|
||||
size = PAGE_ALIGN(size + offset);
|
||||
|
||||
/*
|
||||
* DMA allocation can be mapped to user space, so lets
|
||||
* set VM_USERMAP flags too.
|
||||
*/
|
||||
area = get_vm_area(size, VM_USERMAP);
|
||||
if (!area)
|
||||
return NULL;
|
||||
|
||||
addr = (unsigned long)area->addr;
|
||||
area->phys_addr = __pfn_to_phys(page_to_pfn(page));
|
||||
|
||||
if (ioremap_page_range(addr, addr + size, area->phys_addr, prot)) {
|
||||
vunmap((void *)addr);
|
||||
return NULL;
|
||||
}
|
||||
return (void *)addr + offset;
|
||||
}
|
||||
|
||||
static void arm64_dma_unremap(struct device *dev, void *remapped_addr,
|
||||
size_t size)
|
||||
{
|
||||
struct vm_struct *area;
|
||||
|
||||
size = PAGE_ALIGN(size);
|
||||
remapped_addr = (void *)((unsigned long)remapped_addr & PAGE_MASK);
|
||||
|
||||
area = find_vm_area(remapped_addr);
|
||||
if (!area) {
|
||||
WARN(1, "trying to free invalid coherent area: %pK\n",
|
||||
remapped_addr);
|
||||
return;
|
||||
}
|
||||
vunmap(remapped_addr);
|
||||
flush_tlb_kernel_range((unsigned long)remapped_addr,
|
||||
(unsigned long)(remapped_addr + size));
|
||||
}
|
||||
|
||||
static int __swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t addr)
|
||||
{
|
||||
if (swiotlb)
|
||||
@@ -343,6 +394,8 @@ static const struct dma_map_ops arm64_swiotlb_dma_ops = {
|
||||
.sync_sg_for_device = __swiotlb_sync_sg_for_device,
|
||||
.dma_supported = __swiotlb_dma_supported,
|
||||
.mapping_error = __swiotlb_dma_mapping_error,
|
||||
.remap = arm64_dma_remap,
|
||||
.unremap = arm64_dma_unremap,
|
||||
};
|
||||
|
||||
static int __init atomic_pool_init(void)
|
||||
|
||||
@@ -70,6 +70,11 @@
|
||||
*/
|
||||
#define DMA_ATTR_PRIVILEGED (1UL << 9)
|
||||
|
||||
/*
|
||||
* DMA_ATTR_SKIP_ZEROING: Do not zero mapping.
|
||||
*/
|
||||
#define DMA_ATTR_SKIP_ZEROING (1UL << 11)
|
||||
|
||||
/*
|
||||
* A dma_addr_t can hold any valid DMA or bus address for the platform.
|
||||
* It can be given to a device to use as a DMA source or target. A CPU cannot
|
||||
@@ -130,6 +135,10 @@ struct dma_map_ops {
|
||||
enum dma_data_direction direction);
|
||||
int (*mapping_error)(struct device *dev, dma_addr_t dma_addr);
|
||||
int (*dma_supported)(struct device *dev, u64 mask);
|
||||
void *(*remap)(struct device *dev, void *cpu_addr, dma_addr_t handle,
|
||||
size_t size, unsigned long attrs);
|
||||
void (*unremap)(struct device *dev, void *remapped_address,
|
||||
size_t size);
|
||||
#ifdef ARCH_HAS_DMA_GET_REQUIRED_MASK
|
||||
u64 (*get_required_mask)(struct device *dev);
|
||||
#endif
|
||||
@@ -608,6 +617,35 @@ static inline int dma_set_mask(struct device *dev, u64 mask)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
static inline void *dma_remap(struct device *dev, void *cpu_addr,
|
||||
dma_addr_t dma_handle, size_t size, unsigned long attrs)
|
||||
{
|
||||
const struct dma_map_ops *ops = get_dma_ops(dev);
|
||||
|
||||
if (!ops->remap) {
|
||||
WARN_ONCE(1, "Remap function not implemented for %pS\n",
|
||||
ops->remap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ops->remap(dev, cpu_addr, dma_handle, size, attrs);
|
||||
}
|
||||
|
||||
|
||||
static inline void dma_unremap(struct device *dev, void *remapped_addr,
|
||||
size_t size)
|
||||
{
|
||||
const struct dma_map_ops *ops = get_dma_ops(dev);
|
||||
|
||||
if (!ops->unremap) {
|
||||
WARN_ONCE(1, "unremap function not implemented for %pS\n",
|
||||
ops->unremap);
|
||||
return;
|
||||
}
|
||||
|
||||
return ops->unremap(dev, remapped_addr, size);
|
||||
}
|
||||
|
||||
|
||||
static inline u64 dma_get_mask(struct device *dev)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user