mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 19:21:31 -04:00
This is the first pull request for the new dma-mapping subsystem
In this new subsystem we'll try to properly maintain all the generic
code related to dma-mapping, and will further consolidate arch code
into common helpers.
This pull request contains:
- removal of the DMA_ERROR_CODE macro, replacing it with calls
to ->mapping_error so that the dma_map_ops instances are
more self contained and can be shared across architectures (me)
- removal of the ->set_dma_mask method, which duplicates the
->dma_capable one in terms of functionality, but requires more
duplicate code.
- various updates for the coherent dma pool and related arm code
(Vladimir)
- various smaller cleanups (me)
-----BEGIN PGP SIGNATURE-----
iQI/BAABCAApFiEEgdbnc3r/njty3Iq9D55TZVIEUYMFAlldmw0LHGhjaEBsc3Qu
ZGUACgkQD55TZVIEUYOiKA/+Ln1mFLSf3nfTzIHa24Bbk8ZTGr0B8TD4Vmyyt8iG
oO3AeaTLn3d6ugbH/uih/tPz8PuyXsdiTC1rI/ejDMiwMTSjW6phSiIHGcStSR9X
VFNhmMFacp7QpUpvxceV0XZYKDViAoQgHeGdp3l+K5h/v4AYePV/v/5RjQPaEyOh
YLbCzETO+24mRWdJxdAqtTW4ovYhzj6XsiJ+pAjlV0+SWU6m5L5E+VAPNi1vqv1H
1O2KeCFvVYEpcnfL3qnkw2timcjmfCfeFAd9mCUAc8mSRBfs3QgDTKw3XdHdtRml
LU2WuA5cpMrOdBO4mVra2plo8E2szvpB1OZZXoKKdCpK3VGwVpVHcTvClK2Ks/3B
GDLieroEQNu2ZIUIdWXf/g2x6le3BcC9MmpkAhnGPqCZ7skaIBO5Cjpxm0zTJAPl
PPY3CMBBEktAvys6DcudOYGixNjKUuAm5lnfpcfTEklFdG0AjhdK/jZOplAFA6w4
LCiy0rGHM8ZbVAaFxbYoFCqgcjnv6EjSiqkJxVI4fu/Q7v9YXfdPnEmE0PJwCVo5
+i7aCLgrYshTdHr/F3e5EuofHN3TDHwXNJKGh/x97t+6tt326QMvDKX059Kxst7R
rFukGbrYvG8Y7yXwrSDbusl443ta0Ht7T1oL4YUoJTZp0nScAyEluDTmrH1JVCsT
R4o=
=0Fso
-----END PGP SIGNATURE-----
Merge tag 'dma-mapping-4.13' of git://git.infradead.org/users/hch/dma-mapping
Pull dma-mapping infrastructure from Christoph Hellwig:
"This is the first pull request for the new dma-mapping subsystem
In this new subsystem we'll try to properly maintain all the generic
code related to dma-mapping, and will further consolidate arch code
into common helpers.
This pull request contains:
- removal of the DMA_ERROR_CODE macro, replacing it with calls to
->mapping_error so that the dma_map_ops instances are more self
contained and can be shared across architectures (me)
- removal of the ->set_dma_mask method, which duplicates the
->dma_capable one in terms of functionality, but requires more
duplicate code.
- various updates for the coherent dma pool and related arm code
(Vladimir)
- various smaller cleanups (me)"
* tag 'dma-mapping-4.13' of git://git.infradead.org/users/hch/dma-mapping: (56 commits)
ARM: dma-mapping: Remove traces of NOMMU code
ARM: NOMMU: Set ARM_DMA_MEM_BUFFERABLE for M-class cpus
ARM: NOMMU: Introduce dma operations for noMMU
drivers: dma-mapping: allow dma_common_mmap() for NOMMU
drivers: dma-coherent: Introduce default DMA pool
drivers: dma-coherent: Account dma_pfn_offset when used with device tree
dma: Take into account dma_pfn_offset
dma-mapping: replace dmam_alloc_noncoherent with dmam_alloc_attrs
dma-mapping: remove dmam_free_noncoherent
crypto: qat - avoid an uninitialized variable warning
au1100fb: remove a bogus dma_free_nonconsistent call
MAINTAINERS: add entry for dma mapping helpers
powerpc: merge __dma_set_mask into dma_set_mask
dma-mapping: remove the set_dma_mask method
powerpc/cell: use the dma_supported method for ops switching
powerpc/cell: clean up fixed mapping dma_ops initialization
tile: remove dma_supported and mapping_error methods
xen-swiotlb: remove xen_swiotlb_set_dma_mask
arm: implement ->dma_supported instead of ->set_dma_mask
mips/loongson64: implement ->dma_supported instead of ->set_dma_mask
...
This commit is contained in:
commit
f72e24a124
75 changed files with 778 additions and 725 deletions
|
|
@ -16,8 +16,27 @@ struct dma_coherent_mem {
|
|||
int flags;
|
||||
unsigned long *bitmap;
|
||||
spinlock_t spinlock;
|
||||
bool use_dev_dma_pfn_offset;
|
||||
};
|
||||
|
||||
static struct dma_coherent_mem *dma_coherent_default_memory __ro_after_init;
|
||||
|
||||
static inline struct dma_coherent_mem *dev_get_coherent_memory(struct device *dev)
|
||||
{
|
||||
if (dev && dev->dma_mem)
|
||||
return dev->dma_mem;
|
||||
return dma_coherent_default_memory;
|
||||
}
|
||||
|
||||
static inline dma_addr_t dma_get_device_base(struct device *dev,
|
||||
struct dma_coherent_mem * mem)
|
||||
{
|
||||
if (mem->use_dev_dma_pfn_offset)
|
||||
return (mem->pfn_base - dev->dma_pfn_offset) << PAGE_SHIFT;
|
||||
else
|
||||
return mem->device_base;
|
||||
}
|
||||
|
||||
static bool dma_init_coherent_memory(
|
||||
phys_addr_t phys_addr, dma_addr_t device_addr, size_t size, int flags,
|
||||
struct dma_coherent_mem **mem)
|
||||
|
|
@ -83,6 +102,9 @@ static void dma_release_coherent_memory(struct dma_coherent_mem *mem)
|
|||
static int dma_assign_coherent_memory(struct device *dev,
|
||||
struct dma_coherent_mem *mem)
|
||||
{
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
if (dev->dma_mem)
|
||||
return -EBUSY;
|
||||
|
||||
|
|
@ -133,7 +155,7 @@ void *dma_mark_declared_memory_occupied(struct device *dev,
|
|||
return ERR_PTR(-EINVAL);
|
||||
|
||||
spin_lock_irqsave(&mem->spinlock, flags);
|
||||
pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
|
||||
pos = PFN_DOWN(device_addr - dma_get_device_base(dev, mem));
|
||||
err = bitmap_allocate_region(mem->bitmap, pos, get_order(size));
|
||||
spin_unlock_irqrestore(&mem->spinlock, flags);
|
||||
|
||||
|
|
@ -161,15 +183,12 @@ EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
|
|||
int dma_alloc_from_coherent(struct device *dev, ssize_t size,
|
||||
dma_addr_t *dma_handle, void **ret)
|
||||
{
|
||||
struct dma_coherent_mem *mem;
|
||||
struct dma_coherent_mem *mem = dev_get_coherent_memory(dev);
|
||||
int order = get_order(size);
|
||||
unsigned long flags;
|
||||
int pageno;
|
||||
int dma_memory_map;
|
||||
|
||||
if (!dev)
|
||||
return 0;
|
||||
mem = dev->dma_mem;
|
||||
if (!mem)
|
||||
return 0;
|
||||
|
||||
|
|
@ -186,7 +205,7 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size,
|
|||
/*
|
||||
* Memory was found in the per-device area.
|
||||
*/
|
||||
*dma_handle = mem->device_base + (pageno << PAGE_SHIFT);
|
||||
*dma_handle = dma_get_device_base(dev, mem) + (pageno << PAGE_SHIFT);
|
||||
*ret = mem->virt_base + (pageno << PAGE_SHIFT);
|
||||
dma_memory_map = (mem->flags & DMA_MEMORY_MAP);
|
||||
spin_unlock_irqrestore(&mem->spinlock, flags);
|
||||
|
|
@ -223,7 +242,7 @@ EXPORT_SYMBOL(dma_alloc_from_coherent);
|
|||
*/
|
||||
int dma_release_from_coherent(struct device *dev, int order, void *vaddr)
|
||||
{
|
||||
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
|
||||
struct dma_coherent_mem *mem = dev_get_coherent_memory(dev);
|
||||
|
||||
if (mem && vaddr >= mem->virt_base && vaddr <
|
||||
(mem->virt_base + (mem->size << PAGE_SHIFT))) {
|
||||
|
|
@ -257,7 +276,7 @@ EXPORT_SYMBOL(dma_release_from_coherent);
|
|||
int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma,
|
||||
void *vaddr, size_t size, int *ret)
|
||||
{
|
||||
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
|
||||
struct dma_coherent_mem *mem = dev_get_coherent_memory(dev);
|
||||
|
||||
if (mem && vaddr >= mem->virt_base && vaddr + size <=
|
||||
(mem->virt_base + (mem->size << PAGE_SHIFT))) {
|
||||
|
|
@ -287,6 +306,8 @@ EXPORT_SYMBOL(dma_mmap_from_coherent);
|
|||
#include <linux/of_fdt.h>
|
||||
#include <linux/of_reserved_mem.h>
|
||||
|
||||
static struct reserved_mem *dma_reserved_default_memory __initdata;
|
||||
|
||||
static int rmem_dma_device_init(struct reserved_mem *rmem, struct device *dev)
|
||||
{
|
||||
struct dma_coherent_mem *mem = rmem->priv;
|
||||
|
|
@ -299,6 +320,7 @@ static int rmem_dma_device_init(struct reserved_mem *rmem, struct device *dev)
|
|||
&rmem->base, (unsigned long)rmem->size / SZ_1M);
|
||||
return -ENODEV;
|
||||
}
|
||||
mem->use_dev_dma_pfn_offset = true;
|
||||
rmem->priv = mem;
|
||||
dma_assign_coherent_memory(dev, mem);
|
||||
return 0;
|
||||
|
|
@ -307,7 +329,8 @@ static int rmem_dma_device_init(struct reserved_mem *rmem, struct device *dev)
|
|||
static void rmem_dma_device_release(struct reserved_mem *rmem,
|
||||
struct device *dev)
|
||||
{
|
||||
dev->dma_mem = NULL;
|
||||
if (dev)
|
||||
dev->dma_mem = NULL;
|
||||
}
|
||||
|
||||
static const struct reserved_mem_ops rmem_dma_ops = {
|
||||
|
|
@ -327,6 +350,12 @@ static int __init rmem_dma_setup(struct reserved_mem *rmem)
|
|||
pr_err("Reserved memory: regions without no-map are not yet supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (of_get_flat_dt_prop(node, "linux,dma-default", NULL)) {
|
||||
WARN(dma_reserved_default_memory,
|
||||
"Reserved memory: region for default DMA coherent area is redefined\n");
|
||||
dma_reserved_default_memory = rmem;
|
||||
}
|
||||
#endif
|
||||
|
||||
rmem->ops = &rmem_dma_ops;
|
||||
|
|
@ -334,5 +363,32 @@ static int __init rmem_dma_setup(struct reserved_mem *rmem)
|
|||
&rmem->base, (unsigned long)rmem->size / SZ_1M);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init dma_init_reserved_memory(void)
|
||||
{
|
||||
const struct reserved_mem_ops *ops;
|
||||
int ret;
|
||||
|
||||
if (!dma_reserved_default_memory)
|
||||
return -ENOMEM;
|
||||
|
||||
ops = dma_reserved_default_memory->ops;
|
||||
|
||||
/*
|
||||
* We rely on rmem_dma_device_init() does not propagate error of
|
||||
* dma_assign_coherent_memory() for "NULL" device.
|
||||
*/
|
||||
ret = ops->device_init(dma_reserved_default_memory, NULL);
|
||||
|
||||
if (!ret) {
|
||||
dma_coherent_default_memory = dma_reserved_default_memory->priv;
|
||||
pr_info("DMA: default coherent area is set\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
core_initcall(dma_init_reserved_memory);
|
||||
|
||||
RESERVEDMEM_OF_DECLARE(dma, "shared-dma-pool", rmem_dma_setup);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -22,20 +22,15 @@ struct dma_devres {
|
|||
size_t size;
|
||||
void *vaddr;
|
||||
dma_addr_t dma_handle;
|
||||
unsigned long attrs;
|
||||
};
|
||||
|
||||
static void dmam_coherent_release(struct device *dev, void *res)
|
||||
static void dmam_release(struct device *dev, void *res)
|
||||
{
|
||||
struct dma_devres *this = res;
|
||||
|
||||
dma_free_coherent(dev, this->size, this->vaddr, this->dma_handle);
|
||||
}
|
||||
|
||||
static void dmam_noncoherent_release(struct device *dev, void *res)
|
||||
{
|
||||
struct dma_devres *this = res;
|
||||
|
||||
dma_free_noncoherent(dev, this->size, this->vaddr, this->dma_handle);
|
||||
dma_free_attrs(dev, this->size, this->vaddr, this->dma_handle,
|
||||
this->attrs);
|
||||
}
|
||||
|
||||
static int dmam_match(struct device *dev, void *res, void *match_data)
|
||||
|
|
@ -69,7 +64,7 @@ void *dmam_alloc_coherent(struct device *dev, size_t size,
|
|||
struct dma_devres *dr;
|
||||
void *vaddr;
|
||||
|
||||
dr = devres_alloc(dmam_coherent_release, sizeof(*dr), gfp);
|
||||
dr = devres_alloc(dmam_release, sizeof(*dr), gfp);
|
||||
if (!dr)
|
||||
return NULL;
|
||||
|
||||
|
|
@ -104,35 +99,35 @@ void dmam_free_coherent(struct device *dev, size_t size, void *vaddr,
|
|||
struct dma_devres match_data = { size, vaddr, dma_handle };
|
||||
|
||||
dma_free_coherent(dev, size, vaddr, dma_handle);
|
||||
WARN_ON(devres_destroy(dev, dmam_coherent_release, dmam_match,
|
||||
&match_data));
|
||||
WARN_ON(devres_destroy(dev, dmam_release, dmam_match, &match_data));
|
||||
}
|
||||
EXPORT_SYMBOL(dmam_free_coherent);
|
||||
|
||||
/**
|
||||
* dmam_alloc_non_coherent - Managed dma_alloc_noncoherent()
|
||||
* dmam_alloc_attrs - Managed dma_alloc_attrs()
|
||||
* @dev: Device to allocate non_coherent memory for
|
||||
* @size: Size of allocation
|
||||
* @dma_handle: Out argument for allocated DMA handle
|
||||
* @gfp: Allocation flags
|
||||
* @attrs: Flags in the DMA_ATTR_* namespace.
|
||||
*
|
||||
* Managed dma_alloc_noncoherent(). Memory allocated using this
|
||||
* function will be automatically released on driver detach.
|
||||
* Managed dma_alloc_attrs(). Memory allocated using this function will be
|
||||
* automatically released on driver detach.
|
||||
*
|
||||
* RETURNS:
|
||||
* Pointer to allocated memory on success, NULL on failure.
|
||||
*/
|
||||
void *dmam_alloc_noncoherent(struct device *dev, size_t size,
|
||||
dma_addr_t *dma_handle, gfp_t gfp)
|
||||
void *dmam_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle,
|
||||
gfp_t gfp, unsigned long attrs)
|
||||
{
|
||||
struct dma_devres *dr;
|
||||
void *vaddr;
|
||||
|
||||
dr = devres_alloc(dmam_noncoherent_release, sizeof(*dr), gfp);
|
||||
dr = devres_alloc(dmam_release, sizeof(*dr), gfp);
|
||||
if (!dr)
|
||||
return NULL;
|
||||
|
||||
vaddr = dma_alloc_noncoherent(dev, size, dma_handle, gfp);
|
||||
vaddr = dma_alloc_attrs(dev, size, dma_handle, gfp, attrs);
|
||||
if (!vaddr) {
|
||||
devres_free(dr);
|
||||
return NULL;
|
||||
|
|
@ -141,32 +136,13 @@ void *dmam_alloc_noncoherent(struct device *dev, size_t size,
|
|||
dr->vaddr = vaddr;
|
||||
dr->dma_handle = *dma_handle;
|
||||
dr->size = size;
|
||||
dr->attrs = attrs;
|
||||
|
||||
devres_add(dev, dr);
|
||||
|
||||
return vaddr;
|
||||
}
|
||||
EXPORT_SYMBOL(dmam_alloc_noncoherent);
|
||||
|
||||
/**
|
||||
* dmam_free_coherent - Managed dma_free_noncoherent()
|
||||
* @dev: Device to free noncoherent memory for
|
||||
* @size: Size of allocation
|
||||
* @vaddr: Virtual address of the memory to free
|
||||
* @dma_handle: DMA handle of the memory to free
|
||||
*
|
||||
* Managed dma_free_noncoherent().
|
||||
*/
|
||||
void dmam_free_noncoherent(struct device *dev, size_t size, void *vaddr,
|
||||
dma_addr_t dma_handle)
|
||||
{
|
||||
struct dma_devres match_data = { size, vaddr, dma_handle };
|
||||
|
||||
dma_free_noncoherent(dev, size, vaddr, dma_handle);
|
||||
WARN_ON(!devres_destroy(dev, dmam_noncoherent_release, dmam_match,
|
||||
&match_data));
|
||||
}
|
||||
EXPORT_SYMBOL(dmam_free_noncoherent);
|
||||
EXPORT_SYMBOL(dmam_alloc_attrs);
|
||||
|
||||
#ifdef CONFIG_HAVE_GENERIC_DMA_COHERENT
|
||||
|
||||
|
|
@ -251,7 +227,7 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
|
|||
void *cpu_addr, dma_addr_t dma_addr, size_t size)
|
||||
{
|
||||
int ret = -ENXIO;
|
||||
#if defined(CONFIG_MMU) && !defined(CONFIG_ARCH_NO_COHERENT_DMA_MMAP)
|
||||
#ifndef CONFIG_ARCH_NO_COHERENT_DMA_MMAP
|
||||
unsigned long user_count = vma_pages(vma);
|
||||
unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
|
||||
unsigned long pfn = page_to_pfn(virt_to_page(cpu_addr));
|
||||
|
|
@ -268,7 +244,7 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
|
|||
user_count << PAGE_SHIFT,
|
||||
vma->vm_page_prot);
|
||||
}
|
||||
#endif /* CONFIG_MMU && !CONFIG_ARCH_NO_COHERENT_DMA_MMAP */
|
||||
#endif /* !CONFIG_ARCH_NO_COHERENT_DMA_MMAP */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue