mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 19:00:25 +00:00
![Thomas Gleixner](/assets/img/avatar_default.png)
Based on 1 normalized pattern(s): this program is free software you can redistribute it and or modify it under the terms of the gnu general public license as published by the free software foundation either version 2 of the license or at your optional any later version of the license extracted by the scancode license scanner the SPDX license identifier GPL-2.0-or-later has been chosen to replace the boilerplate/reference in 3 file(s). Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Richard Fontana <rfontana@redhat.com> Reviewed-by: Allison Randal <allison@lohutok.net> Cc: linux-spdx@vger.kernel.org Link: https://lkml.kernel.org/r/20190520075212.713472955@linutronix.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
160 lines
4.3 KiB
C
160 lines
4.3 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
#ifndef __LINUX_CMA_H
|
|
#define __LINUX_CMA_H
|
|
|
|
/*
|
|
* Contiguous Memory Allocator for DMA mapping framework
|
|
* Copyright (c) 2010-2011 by Samsung Electronics.
|
|
* Written by:
|
|
* Marek Szyprowski <m.szyprowski@samsung.com>
|
|
* Michal Nazarewicz <mina86@mina86.com>
|
|
*/
|
|
|
|
/*
|
|
* Contiguous Memory Allocator
|
|
*
|
|
* The Contiguous Memory Allocator (CMA) makes it possible to
|
|
* allocate big contiguous chunks of memory after the system has
|
|
* booted.
|
|
*
|
|
* Why is it needed?
|
|
*
|
|
* Various devices on embedded systems have no scatter-getter and/or
|
|
* IO map support and require contiguous blocks of memory to
|
|
* operate. They include devices such as cameras, hardware video
|
|
* coders, etc.
|
|
*
|
|
* Such devices often require big memory buffers (a full HD frame
|
|
* is, for instance, more then 2 mega pixels large, i.e. more than 6
|
|
* MB of memory), which makes mechanisms such as kmalloc() or
|
|
* alloc_page() ineffective.
|
|
*
|
|
* At the same time, a solution where a big memory region is
|
|
* reserved for a device is suboptimal since often more memory is
|
|
* reserved then strictly required and, moreover, the memory is
|
|
* inaccessible to page system even if device drivers don't use it.
|
|
*
|
|
* CMA tries to solve this issue by operating on memory regions
|
|
* where only movable pages can be allocated from. This way, kernel
|
|
* can use the memory for pagecache and when device driver requests
|
|
* it, allocated pages can be migrated.
|
|
*
|
|
* Driver usage
|
|
*
|
|
* CMA should not be used by the device drivers directly. It is
|
|
* only a helper framework for dma-mapping subsystem.
|
|
*
|
|
* For more information, see kernel-docs in kernel/dma/contiguous.c
|
|
*/
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
#include <linux/device.h>
|
|
|
|
struct cma;
|
|
struct page;
|
|
|
|
#ifdef CONFIG_DMA_CMA
|
|
|
|
extern struct cma *dma_contiguous_default_area;
|
|
|
|
static inline struct cma *dev_get_cma_area(struct device *dev)
|
|
{
|
|
if (dev && dev->cma_area)
|
|
return dev->cma_area;
|
|
return dma_contiguous_default_area;
|
|
}
|
|
|
|
static inline void dev_set_cma_area(struct device *dev, struct cma *cma)
|
|
{
|
|
if (dev)
|
|
dev->cma_area = cma;
|
|
}
|
|
|
|
static inline void dma_contiguous_set_default(struct cma *cma)
|
|
{
|
|
dma_contiguous_default_area = cma;
|
|
}
|
|
|
|
void dma_contiguous_reserve(phys_addr_t addr_limit);
|
|
|
|
int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base,
|
|
phys_addr_t limit, struct cma **res_cma,
|
|
bool fixed);
|
|
|
|
/**
|
|
* dma_declare_contiguous() - reserve area for contiguous memory handling
|
|
* for particular device
|
|
* @dev: Pointer to device structure.
|
|
* @size: Size of the reserved memory.
|
|
* @base: Start address of the reserved memory (optional, 0 for any).
|
|
* @limit: End address of the reserved memory (optional, 0 for any).
|
|
*
|
|
* This function reserves memory for specified device. It should be
|
|
* called by board specific code when early allocator (memblock or bootmem)
|
|
* is still activate.
|
|
*/
|
|
|
|
static inline int dma_declare_contiguous(struct device *dev, phys_addr_t size,
|
|
phys_addr_t base, phys_addr_t limit)
|
|
{
|
|
struct cma *cma;
|
|
int ret;
|
|
ret = dma_contiguous_reserve_area(size, base, limit, &cma, true);
|
|
if (ret == 0)
|
|
dev_set_cma_area(dev, cma);
|
|
|
|
return ret;
|
|
}
|
|
|
|
struct page *dma_alloc_from_contiguous(struct device *dev, size_t count,
|
|
unsigned int order, bool no_warn);
|
|
bool dma_release_from_contiguous(struct device *dev, struct page *pages,
|
|
int count);
|
|
|
|
#else
|
|
|
|
static inline struct cma *dev_get_cma_area(struct device *dev)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline void dev_set_cma_area(struct device *dev, struct cma *cma) { }
|
|
|
|
static inline void dma_contiguous_set_default(struct cma *cma) { }
|
|
|
|
static inline void dma_contiguous_reserve(phys_addr_t limit) { }
|
|
|
|
static inline int dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base,
|
|
phys_addr_t limit, struct cma **res_cma,
|
|
bool fixed)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline
|
|
int dma_declare_contiguous(struct device *dev, phys_addr_t size,
|
|
phys_addr_t base, phys_addr_t limit)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
|
|
static inline
|
|
struct page *dma_alloc_from_contiguous(struct device *dev, size_t count,
|
|
unsigned int order, bool no_warn)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline
|
|
bool dma_release_from_contiguous(struct device *dev, struct page *pages,
|
|
int count)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#endif
|