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:
Suren Baghdasaryan
2020-02-24 10:00:12 -08:00
parent 30485f206e
commit 0e5bee4422
2 changed files with 91 additions and 0 deletions

View File

@@ -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)

View File

@@ -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)
{