/* * Copyright (c) 2007-2014 Texas Instruments Incorporated - http://www.ti.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @file ti/cmem.h * @brief Describes the interface to the contiguous memory allocator. * * The cmem user interface library wraps file system calls to an associated * kernel module (cmemk.ko), which needs to be loaded in order for calls to * this library to succeed. * * The CMEM kernel module accepts blocks of physical memory and a pool * geometry within those blocks. The blocks and pools can be specified * either in the traditional command line method, or with the new DT * (Device Tree) method. The DT method is the prefered method due to * its control by a system integrator. * * Command line block and pool specification * ----------------------------------------- * * The following is an example of installing the cmem kernel module using * the traditional command line block and pool parameters (a DT example is * shown below): * * @verbatim /sbin/insmod cmemk.ko pools=4x30000,2x500000 phys_start=0x0 phys_end=0x3000000 @endverbatim * - phys_start and phys_end must be specified in hexadecimal format * - phys_start is "inclusive" and phys_end is "exclusive", i.e., * phys_end should be "end address + 1". * - pools must be specified using decimal format (for both number and * size), since using hexadecimal format would visually clutter the * specification due to the use of "x" as a token separator * - it's possible to insmod cmemk.ko without specifying any memory blocks, * in which case CMEM_getPhys() and CMEM_cache*() APIs can still be * utilized by an application, and CMA-based allocations can still be * accomplished (by using blockid as CMEM_CMABLOCKID). * * This particular command creates 2 pools. The first pool is created with 4 * buffers of size 30000 bytes and the second pool is created with 2 buffers * of size 500000 bytes. The CMEM pool buffers start at 0x0 and end at * 0x2FFFFFF (max). * * There is also support for a 2nd, 3rd, or 4th contiguous memory block to * be specified, with all the same features supported for those blocks as * with the 1st. This 2nd block is specified with *_1 parameters (and 3rd * block with *_2, 4th block with *_3). The following example expands upon * the first example above: * * @verbatim /sbin/insmod cmemk.ko pools=4x30000,2x500000 phys_start=0x0 phys_end=0x3000000 pools_1=4x65536 phys_start_1=0x80000000 phys_end_1=0x80010000 @endverbatim * * This particular command, in addition to the pools explained above, * creates 1 pool (with 4 buffers of size 64KB) in a 2nd memory block which * starts at 0x80000000 and ends at 0x8000FFFF (specified as "end + 1" on the * insmod command). * * In order to access blocks beyond the 1st block, new APIs have been added to * CMEM which allow specification of the block ID. * * There is another configuration "switch" for the cmemk.ko kernel module, * which can be specified on the 'insmod' (or 'modprobe') command lines: * useHeapIfPoolUnavailable=[0|1] * * 'useHeapIfPoolUnavailable', when set to 1, will cause pool-based allocations * to fallback to a heap-based allocation if no pool buffer of sufficient size * is available (the CMEM heap is described below). * * Pool buffers are aligned on a module-dependent boundary, and their sizes are * rounded up to this same boundary. This applies to each buffer within a * pool. The total space used by an individual pool will therefore be greater * than (or equal to) the exact amount requested in the installation of the * module. * * The poolid used in the driver calls would be 0 for the first pool and 1 for * the second pool. * * Pool allocations can be requested explicitly by pool number, or more * generally by just a size. For size-based allocations, the pool which best * fits the requested size is automatically chosen. Some CMEM APIs (newer * ones) accept a blockid as a parameter, in order to specify which of the * multiple blocks to operate on. For 'legacy' APIs (ones that existed before * the support for multiple blocks) where a blockid is still needed, block 0 * is assumed. * * There is also support for a general purpose heap. In addition to the 2 * pools described above, a general purpose heap block is created from which * allocations of any size can be requested. Internally, allocation sizes are * rounded up to a module-dependent boundary and allocation addresses are * aligned either to this same boundary or to the requested alignment * (whichever is greater). * * The size of the heap block is the amount of CMEM memory remaining after all * pool allocations. If more heap space is needed than is available after pool * allocations, you must reduce the amount of CMEM memory granted to the pools. * * Buffer allocation is tracked at the file descriptor level by way of a * 'registration' list. The initial allocator of a buffer (the process that * calls CMEM_alloc()) is automatically added to the registration list, * and further processes can become registered for the same buffer by way * of the CMEM_registerAlloc() API (and unregister with the * CMEM_unregister() API). This registration list for each buffer * allows for buffer ownership tracking and cleanup on a * per-file-descriptor basis, so that when a process exits or dies without * having explicitly freed/unregistered its buffers, they get automatically * unregistered (and freed when no more registered file descriptors exist). * Only when the last registered file descriptor frees a buffer (either * explictily, or by auto-cleanup) does a buffer actually get freed back to * the kernel module. * * Block and pool specification using Device Tree (DT) * --------------------------------------------------- * * The Device Tree can be used to specify physical memory blocks and pool * geometry within those blocks, with the same capabilities as the command * line specification. DT specification is preferred over command line * specification for a number of reasons: * - allows specifying the physical "carveout" with direct linkage to * that carveout in the pool specification, thereby eliminating potential * errors that could occur when the physical carveout is defined in one * place and then needing to be specified on the cmemk.ko command line * exactly equivalent to the carveout definition. * - allows a system integrator to define the CMEM specifications without * the need to document instructions for the command line, or prepackage * the command line in some filesystem-based script. * * CMEM allows both DT-specified and command line specified blocks. Each * block is assigned a number that can be later used for allocations in * order to direct the allocation to a particular block. This allows some * blocks to be defined in the DT and other blocks to be later defined * on the CMEM command line. If a particular block number is assigned in * DT and also specified on the CMEM command line then the DT specification * takes precedence and the command line specification is ignored. * * The following DT example snippet illustrates the syntax... * * @code * // Specify reserved physical blocks, using "no-map" to keep Linux away. * // The "reg" property is the base address and size in 32-bit ints. * // This is the generic "reserved-memory" node that might also contain * // other non-CMEM entries. * * reserved-memory { * #address-cells = <1>; * #size-cells = <1>; * ranges; * ... * cmem_block_mem_0: cmem_block_mem@a0000000 { * reg = <0xa0000000 0x10000000>; * no-map; * status = "okay"; * }; * * cmem_block_mem_1: cmem_block_mem@b0000000 { * reg = <0xb0000000 0x02000000>; * no-map; * status = "okay"; * }; * }; * * // The CMEM node is specified below, and can be named arbitrarily ("cmem" * // name chosen here). The node's "compatible" property must contain * // "ti,cmem" in order for CMEM to process it. * * cmem { * compatible = "ti,cmem"; // must be "ti,cmem" * #address-cells = <1>; * #size-cells = <0>; * * status = "okay"; * * // CMEM block specifications along with pool geometry. * // * // The "reg" property is the block identifier, and each child of the * // cmem node must specify a different "reg" value. The domain of * // the block identifier is 0 -> , where nblocks is the * // total amount of DT-specified and command line-specified blocks. * // CMEM currently supports up to 4 blocks (although that can be increased * // by simple comment-directed modifications in cmemk.c). * // * // The "memory-region" property points to the phandle of the * // reserved-memory area. * // * // The "cmem-buf-pools" property contains a variable number of comma- * // separated pools, with each pool specifying the number of buffers and * // the size of each buffer in format. * * cmem_block_0: cmem_block@0 { * reg = <0>; * memory-region = <&cmem_block_mem_0>; * cmem-buf-pools = <1 0x0c000000>, <4 0x01000000>; // 1x192MB, 4x16MB pools * }; * * cmem_block_1: cmem_block@1 { * reg = <1>; * memory-region = <&cmem_block_mem_1>; * cmem-buf-pools = <1 0x02000000>; // 1x32MB pool, remaining carveout is heap. * }; * }; * @endcode * * Decoupled allocation & memory mapping * ------------------------------------- * * For every CMEM_alloc*() API, there is a corresponding "Phys" API that * returns the physical address of the allocation and does *not* do the * user-space memory mapping (mmap()). There is also a corresponding * CMEM_freePhys() to be used for freeing allocations performed by the * "Phys" APIs. The user-space memory mapping is performed with the * CMEM_map()/CMEM_unmap() APIs. This allows large buffer allocations * without the burden of using up a large portion of the application's * virtual address space for the duration of the allocation's existence. * A mapping performed by CMEM_map() doesn't have to be for the whole of * the allocated buffer, it can be for just portions of the buffer (but * must not be larger than the allocated buffer). * * CMEM_map() can be called multiple times for the same physical allocation. * Each invocation of CMEM_map() will allocate a new user virtual address * range for the same physical allocation. * * CMA access * ---------- * * On systems with CMA (Contiguous Memory Allocator) support, CMEM can be used * to allocate CMA buffers. Both heap and pool allocations are supported. A * special block ID, CMEM_CMABLOCKID, is used for these allocations, and * therefore the block-based CMEM APIs must be used (the ones ending in "2", * such as CMEM_alloc2()), where the 'blockid' parameter is CMEM_CMABLOCKID * (instead of 0 or 1). * * CMA always contains, at the minimum, a global area that can be accessed * by any device driver. CMEM treats this global area as a heap, which means * that heap-based allocations can be performed on CMEM_CMABLOCKID. * See the Linux CMA documentation for details on specifying this global area. * Keep in mind that other Linux kernel entities can (and will) also allocate * memory from this global area, so you never really know how much is * available for allocations by CMEM. * * To achieve pool-based allocations from CMA, a special CMEM stub must be * builtin to the kernel, and CMEM must be built with CMEM_KERNEL_STUB=1 for * the 'make' command (which turns into -DCMEM_KERNEL_STUB on the compile * command). This stub processes a kernel command line parameter named * "cmem_cma_pools=..." in the same fashion as the standard CMEM "pools=...". * A separate CMA region (area) is created for each of the separate * "cmem_cma_pools" (where each pool/region is one element of the comma- * separated list). * * The CMEM builtin kernel stub is located in * .../src/cmem/module/kernel/drivers/cmem/cmemk_stub.c * You don't need this stub if you want to allocate only from the CMA * global area. Please see comments at the head of the above file for * instructions on how to incorporate it into your kernel. * * In supporting the pool model of CMEM, a separate CMA region is created for * each pool. A pool consists of n buffers of size s, resulting in a region * that is sized accordingly. CMA places no restrictions on the size of an * allocation from a region, so the buffer size 's' becomes more of a * convention than a hard rule. Given enough free space, any pool can be * used to allocate a buffer of any size, but it is recommended to partition * regions (or, in this case, pools) according to the size of buffers that * will be allocated in order to reduce fragmentation and wasted memory due * to size-based alignment padding. In other words, if your system will be * allocating 10 buffers of size 4096, 8 of size 131072, and 4 of size * 1048576, create pools of * cmem_cma_pools=10x4096,8x131072,4x1048576 * and perform allocations from the respective pool. * * An application doesn't need to know the pool IDs that correspond to the * respective sizes of that pool's buffers. The CMEM_alloc2() API decides * which pool to use according to the requested size of allocation, and will * choose the one that fits most efficiently. Unlike non-CMA pool allocations * where, when the "best fit" pool has no remaining buffers it will choose a * pool with larger available buffers, CMEM_alloc2() won't "promote" a * CMA-based pool allocation to a pool with buffers larger than the the best * fit. * * CMEM supports a kernel command line parameter named "cmem_cma_heapsize". * When assigned, a CMA region of size "cmem_cma_heapsize" is created for use * by CMEM heap allocations for the CMA "block". This heap is then used for * CMEM CMA heap allocations, and the CMA global area is no longer used by * CMEM. This allows CMEM to have full usage of the CMEM CMA heap without * possible allocations by non-CMEM entities in the kernel. */ /** * @defgroup ti_CMEM Contiguous Memory Manager * * @copydoc ti/cmem.h */ #ifndef ti_CMEM_H #define ti_CMEM_H #if defined (__cplusplus) extern "C" { #endif /** @ingroup ti_CMEM */ /*@{*/ #define CMEM_VERSION 0x04140000U #define MAX_POOLS 32 /* magic "block" corresponding to CMA regions */ #define CMEM_CMABLOCKID -1 /* ioctl cmd "flavors" */ #define CMEM_WB 0x00010000 #define CMEM_INV 0x00020000 #define CMEM_HEAP 0x00040000 /**< operation applies to heap */ #define CMEM_POOL 0x00000000 /**< operation applies to a pool */ #define CMEM_CACHED 0x00080000 /**< allocated buffer is cached */ #define CMEM_NONCACHED 0x00000000 /**< allocated buffer is not cached */ #define CMEM_PHYS 0x00100000 #define CMEM_IOCMAGIC 0x0000fe00 /* supported "base" ioctl cmds for the driver. */ #define CMEM_IOCALLOC 1 #define CMEM_IOCALLOCHEAP 2 #define CMEM_IOCFREE 3 #define CMEM_IOCGETPHYS 4 #define CMEM_IOCGETSIZE 5 #define CMEM_IOCGETPOOL 6 #define CMEM_IOCCACHE 7 #define CMEM_IOCGETVERSION 8 #define CMEM_IOCGETBLOCK 9 #define CMEM_IOCREGUSER 10 #define CMEM_IOCGETNUMBLOCKS 11 #define CMEM_IOCCACHEWBINVALL 12 #define CMEM_IOCEXPORTDMABUF 13 /* * New ioctl cmds should use integers greater than the largest current cmd * in order to not break backward compatibility. */ /* supported "flavors" to "base" ioctl cmds for the driver. */ #define CMEM_IOCCACHEWBINV CMEM_IOCCACHE | CMEM_WB | CMEM_INV #define CMEM_IOCCACHEWB CMEM_IOCCACHE | CMEM_WB #define CMEM_IOCCACHEINV CMEM_IOCCACHE | CMEM_INV #define CMEM_IOCALLOCCACHED CMEM_IOCALLOC | CMEM_CACHED #define CMEM_IOCALLOCHEAPCACHED CMEM_IOCALLOCHEAP | CMEM_CACHED #define CMEM_IOCFREEHEAP CMEM_IOCFREE | CMEM_HEAP #define CMEM_IOCFREEPHYS CMEM_IOCFREE | CMEM_PHYS #define CMEM_IOCFREEHEAPPHYS CMEM_IOCFREE | CMEM_HEAP | CMEM_PHYS #define CMEM_IOCCMDMASK 0x000000ff /** * @brief Parameters for CMEM_alloc(), CMEM_alloc2(), CMEM_allocPool(), * CMEM_allocPool2(), CMEM_free(). */ typedef struct CMEM_AllocParams { int type; /**< either #CMEM_HEAP or #CMEM_POOL */ int flags; /**< either #CMEM_CACHED or #CMEM_NONCACHED */ size_t alignment; /**< * only used for heap allocations, must be power of 2 */ } CMEM_AllocParams; struct CMEM_block_struct { void *addr; size_t size; }; struct CMEM_dmabufDesc { void *virtp; int fd_dmabuf; }; extern CMEM_AllocParams CMEM_DEFAULTPARAMS; typedef struct CMEM_BlockAttrs { off_t phys_base; unsigned long long size; } CMEM_BlockAttrs; /** @cond INTERNAL */ /** */ union CMEM_AllocUnion { struct { /**< */ size_t size; size_t align; int blockid; } alloc_heap_inparams; /**< */ struct { /**< */ int poolid; int blockid; } alloc_pool_inparams; /**< */ struct { /**< */ int poolid; int blockid; } get_size_inparams; /**< */ struct { /**< */ unsigned long long size; int blockid; } get_pool_inparams; /**< */ struct { /**< */ unsigned long long physp; unsigned long long size; } alloc_pool_outparams; /**< */ struct { /**< */ unsigned long long physp; unsigned long long size; } get_block_outparams; /**< */ struct { /**< */ int poolid; size_t size; } free_outparams; /**< */ unsigned long long physp; void *virtp; size_t size; int poolid; int blockid; }; /** @endcond */ /** * @brief Initialize the CMEM module. Must be called before other API calls. * * @return 0 for success or -1 for failure. * * @sa CMEM_exit */ int CMEM_init(void); /** * @brief Find the pool that best fits a given buffer size and has a buffer * available. * * @param size The buffer size for which a pool is needed. * * @return A poolid that can be passed to CMEM_allocPool(), or -1 for error. * * @pre Must have called CMEM_init() * * @sa CMEM_allocPool() * @sa CMEM_allocPool2() * @sa CMEM_free() * @sa CMEM_getPool2() */ int CMEM_getPool(unsigned long long size); /** * @brief Find the pool in memory block blockid that best fits a given * buffer size and has a buffer available. * * @param blockid Block number * @param size The buffer size for which a pool is needed. * * @return A poolid that can be passed to CMEM_allocPool2(), or -1 for error. * * @pre Must have called CMEM_init() * * @sa CMEM_allocPool() * @sa CMEM_allocPool2() * @sa CMEM_free() * @sa CMEM_getPool() */ int CMEM_getPool2(int blockid, unsigned long long size); /** * @brief Allocate memory from a specified pool. * * @param poolid The pool from which to allocate memory. * @param params Allocation parameters. * * @remarks @c params->type is ignored - a pool will always be used. * @remarks @c params->alignment is unused, since pool buffers are already * aligned to specific boundaries. * * @return A pointer to the allocated buffer, or NULL for failure. * * @pre Must have called CMEM_init() * * @sa CMEM_alloc() * @sa CMEM_alloc2() * @sa CMEM_allocPool2() * @sa CMEM_registerAlloc() * @sa CMEM_unregister() * @sa CMEM_free() */ void *CMEM_allocPool(int poolid, CMEM_AllocParams *params); /** * @brief Allocate memory from a specified pool in a specified memory block. * * @param blockid The memory block from which to allocate. * @param poolid The pool from which to allocate memory. * @param params Allocation parameters. * * @remarks @c params->type is ignored - a pool will always be used. * @remarks @c params->alignment is unused, since pool buffers are already * aligned to specific boundaries. * * @return A pointer to the allocated buffer, or NULL for failure. * * @pre Must have called CMEM_init() * * @sa CMEM_alloc() * @sa CMEM_alloc2() * @sa CMEM_allocPool() * @sa CMEM_registerAlloc() * @sa CMEM_unregister() * @sa CMEM_free() */ void *CMEM_allocPool2(int blockid, int poolid, CMEM_AllocParams *params); /** * @brief Allocate memory of a specified size * * @param size The size of the buffer to allocate. * @param params Allocation parameters. * * @remarks Used to allocate memory from either a pool, the heap, or the CMA * global area. * If doing a pool allocation, the pool that best fits the requested * size will be selected. Use CMEM_allocPool() to allocate from a * specific pool. * Allocation will be cached or noncached, as specified by params. * params->alignment valid only for heap allocation. * * @return A pointer to the allocated buffer, or NULL for failure. * * @pre Must have called CMEM_init() * * @sa CMEM_allocPool() * @sa CMEM_allocPool2() * @sa CMEM_alloc2() * @sa CMEM_registerAlloc() * @sa CMEM_unregister() * @sa CMEM_free() */ void *CMEM_alloc(size_t size, CMEM_AllocParams *params); /** * @brief Allocate memory of a specified size from a specified memory block * * @param blockid The memory block from which to allocate. * @param size The size of the buffer to allocate. * @param params Allocation parameters. * * @remarks Used to allocate memory from either a pool, the heap, or the CMA * global area. * If doing a pool allocation, the pool that best fits the requested * size will be selected. Use CMEM_allocPool() to allocate from a * specific pool. * * @remarks Allocation will be cached or noncached, as specified by params. * params->alignment valid only for heap allocation. * * @return A pointer to the allocated buffer, or NULL for failure. * * @pre Must have called CMEM_init() * * @sa CMEM_allocPool() * @sa CMEM_allocPool2() * @sa CMEM_alloc() * @sa CMEM_registerAlloc() * @sa CMEM_unregister() * @sa CMEM_free() */ void *CMEM_alloc2(int blockid, size_t size, CMEM_AllocParams *params); /** * @brief Allocate unmapped memory from a specified pool. * * @param poolid The pool from which to allocate memory. * @param params Allocation parameters. * * @remarks @c params->type is ignored - a pool will always be used. * @remarks @c params->alignment is unused, since pool buffers are already * aligned to specific boundaries. * * @return The physical address of the allocated buffer, or NULL for failure. * * @pre Must have called CMEM_init() * * @sa CMEM_allocPhys() * @sa CMEM_allocPhys2() * @sa CMEM_allocPoolPhys2() * @sa CMEM_freePhys() * @sa CMEM_map() */ off_t CMEM_allocPoolPhys(int poolid, CMEM_AllocParams *params); /** * @brief Allocate unmapped memory from a specified pool in a specified * memory block. * * @param blockid The memory block from which to allocate. * @param poolid The pool from which to allocate memory. * @param params Allocation parameters. * * @remarks @c params->type is ignored - a pool will always be used. * @remarks @c params->alignment is unused, since pool buffers are already * aligned to specific boundaries. * * @return The physical address of the allocated buffer, or NULL for failure. * * @pre Must have called CMEM_init() * * @sa CMEM_allocPhys() * @sa CMEM_allocPhys2() * @sa CMEM_allocPoolPhys() * @sa CMEM_freePhys() * @sa CMEM_map() */ off_t CMEM_allocPoolPhys2(int blockid, int poolid, CMEM_AllocParams *params); #if defined(LINUXUTILS_BUILDOS_ANDROID) /** * @brief Allocate unmapped memory from a specified pool in a specified * memory block (Android only). * * @param blockid The memory block from which to allocate. * @param poolid The pool from which to allocate memory. * @param params Allocation parameters. * * @remarks @c params->type is ignored - a pool will always be used. * @remarks @c params->alignment is unused, since pool buffers are already * aligned to specific boundaries. * * @return The physical address of the allocated buffer, or NULL for failure. * * @pre Must have called CMEM_init() * * @sa CMEM_allocPhys() * @sa CMEM_allocPhys2() * @sa CMEM_allocPoolPhys() * @sa CMEM_freePhys() * @sa CMEM_map() */ off64_t CMEM_allocPoolPhys64(int blockid, int poolid, CMEM_AllocParams *params); #endif /** * @brief Allocate unmapped memory of a specified size * * @param size The size of the buffer to allocate. * @param params Allocation parameters. * * @remarks Used to allocate memory from either a pool, the heap, or the CMA * global area. * If doing a pool allocation, the pool that best fits the requested * size will be selected. Use CMEM_allocPool() to allocate from a * specific pool. * Allocation will be cached or noncached, as specified by params. * params->alignment valid only for heap allocation. * * @return The physical address of the allocated buffer, or NULL for failure. * * @pre Must have called CMEM_init() * * @sa CMEM_allocPoolPhys() * @sa CMEM_allocPoolPhys2() * @sa CMEM_allocPhys2() * @sa CMEM_freePhys() * @sa CMEM_map() */ off_t CMEM_allocPhys(size_t size, CMEM_AllocParams *params); /** * @brief Allocate unmapped memory of a specified size from a specified * memory block * * @param blockid The memory block from which to allocate. * @param size The size of the buffer to allocate. * @param params Allocation parameters. * * @remarks Used to allocate memory from either a pool, the heap, or the CMA * global area. * If doing a pool allocation, the pool that best fits the requested * size will be selected. Use CMEM_allocPool() to allocate from a * specific pool. * * @remarks Allocation will be cached or noncached, as specified by params. * params->alignment valid only for heap allocation. * * @return The physical address of the allocated buffer, or NULL for failure. * * @pre Must have called CMEM_init() * * @sa CMEM_allocPoolPhys() * @sa CMEM_allocPoolPhys2() * @sa CMEM_allocPhys() * @sa CMEM_freePhys() * @sa CMEM_map() */ off_t CMEM_allocPhys2(int blockid, size_t size, CMEM_AllocParams *params); #if defined(LINUXUTILS_BUILDOS_ANDROID) /** * @brief Allocate unmapped memory of a specified size from a specified * memory block (Android only) * * @param blockid The memory block from which to allocate. * @param size The size of the buffer to allocate. * @param params Allocation parameters. * * @remarks Used to allocate memory from either a pool, the heap, or the CMA * global area. * If doing a pool allocation, the pool that best fits the requested * size will be selected. Use CMEM_allocPool() to allocate from a * specific pool. * * @remarks Allocation will be cached or noncached, as specified by params. * params->alignment valid only for heap allocation. * * @return The physical address of the allocated buffer, or NULL for failure. * * @pre Must have called CMEM_init() * * @sa CMEM_allocPoolPhys() * @sa CMEM_allocPoolPhys2() * @sa CMEM_allocPhys() * @sa CMEM_freePhys() * @sa CMEM_map() */ off64_t CMEM_allocPhys64(int blockid, size_t size, CMEM_AllocParams *params); #endif /** * @brief Register shared usage of an already-allocated buffer * * @param physp Physical address of the already-allocated buffer. * * @remarks Used to register the calling process for usage of an * already-allocated buffer, for the purpose of shared usage of * the buffer. * * @remarks Allocation properties (such as cached/noncached or heap/pool) * are inherited from original allocation call. * * @return A process-specific pointer to the allocated buffer, or NULL * for failure. * * @pre Must have called some form of CMEM_alloc*() * * @sa CMEM_allocPool() * @sa CMEM_allocPool2() * @sa CMEM_alloc() * @sa CMEM_free() * @sa CMEM_unregister() */ void *CMEM_registerAlloc(off_t physp); #if defined(LINUXUTILS_BUILDOS_ANDROID) /** * @brief Register shared usage of an already-allocated buffer using mmap64 * (Android only) * * @param physp Physical address of the already-allocated buffer. * * @remarks Used to register the calling process for usage of an * already-allocated buffer, for the purpose of shared usage of * the buffer. * * @remarks Allocation properties (such as cached/noncached or heap/pool) * are inherited from original allocation call. * * @return A process-specific pointer to the allocated buffer, or NULL * for failure. * * @pre Must have called some form of CMEM_alloc*() * * @sa CMEM_allocPool() * @sa CMEM_allocPool2() * @sa CMEM_alloc() * @sa CMEM_free() * @sa CMEM_unregister() */ void *CMEM_registerAlloc64(off64_t physp); #endif /** * @brief Free a buffer previously allocated with * CMEM_alloc()/CMEM_allocPool(). * * @param ptr The pointer to the buffer. * @param params Allocation parameters. * * @remarks Use the same CMEM_AllocParams as was used for the allocation. * params->flags is "don't care". params->alignment is "don't * care". * * @return 0 for success or -1 for failure. * * @pre Must have called CMEM_init() * * @sa CMEM_alloc() * @sa CMEM_alloc2() * @sa CMEM_allocPool() * @sa CMEM_allocPool2() * @sa CMEM_registerAlloc() * @sa CMEM_unregister() */ int CMEM_free(void *ptr, CMEM_AllocParams *params); /** * @brief Free an unmapped buffer previously allocated with * CMEM_allocPhys()/CMEM_allocPoolPhys(). * * @param physp The physical address of the buffer. * @param params Allocation parameters. * * @remarks Use the same CMEM_AllocParams as was used for the allocation. * params->flags is "don't care". params->alignment is "don't * care". * * @return 0 for success or -1 for failure. * * @pre Must have called CMEM_init() * * @sa CMEM_allocPhys() * @sa CMEM_allocPhys2() * @sa CMEM_allocPoolPhys() * @sa CMEM_allocPoolPhys2() * @sa CMEM_unmap() */ int CMEM_freePhys(off_t physp, CMEM_AllocParams *params); #if defined(LINUXUTILS_BUILDOS_ANDROID) /** * @brief Free an unmapped buffer previously allocated with * CMEM_allocPhys64()/CMEM_allocPoolPhys64() (Android only). * * @param physp The physical address of the buffer. * @param params Allocation parameters. * * @remarks Use the same CMEM_AllocParams as was used for the allocation. * params->flags is "don't care". params->alignment is "don't * care". * * @return 0 for success or -1 for failure. * * @pre Must have called CMEM_init() * * @sa CMEM_allocPhys() * @sa CMEM_allocPhys2() * @sa CMEM_allocPoolPhys() * @sa CMEM_allocPoolPhys2() * @sa CMEM_unmap() */ int CMEM_freePhys64(off64_t physp, CMEM_AllocParams *params); #endif /** * @brief Unregister use of a buffer previously registered with * CMEM_registerAlloc(). * * @param ptr The pointer to the buffer. * @param params Allocation parameters. * * @remarks Use the same CMEM_AllocParams as was used for the allocation. * params->flags is "don't care". params->alignment is "don't * care". * * @return 0 for success or -1 for failure. * * @pre Must have called CMEM_init() * * @sa CMEM_alloc() * @sa CMEM_alloc2() * @sa CMEM_allocPool() * @sa CMEM_allocPool2() * @sa CMEM_registerAlloc() * @sa CMEM_free() */ int CMEM_unregister(void *ptr, CMEM_AllocParams *params); /** * @brief Get the physical address of a contiguous buffer. * * @param ptr The pointer to the buffer. * * @return The physical address of the buffer or 0 for failure. * * @pre Must have called CMEM_init() */ off_t CMEM_getPhys(void *ptr); #if defined(LINUXUTILS_BUILDOS_ANDROID) /** * @brief Get the physical address of a contiguous buffer (Android only). * * @param ptr The pointer to the buffer. * * @return The physical address of the buffer or 0 for failure. * * @pre Must have called CMEM_init() */ off64_t CMEM_getPhys64(void *ptr); #endif /** * @brief Do a cache writeback/invalidate of the whole cache * * @return Success/failure boolean value * * @pre Must have called CMEM_init() * * @sa CMEM_cacheWb() * @sa CMEM_cacheInv() * @sa CMEM_cacheWbInv() */ int CMEM_cacheWbInvAll(void); /** * @brief Do a cache writeback of the block pointed to by @c ptr/@c size * * @param ptr Pointer to block to writeback * @param size Size in bytes of block to writeback. * * @return Success/failure boolean value * * @pre Must have called CMEM_init() * * @sa CMEM_cacheInv() * @sa CMEM_cacheWbInv() * @sa CMEM_cacheWbInvAll() */ int CMEM_cacheWb(void *ptr, size_t size); /** * @brief Map allocated memory * * @param physp Physical address of the already-allocated buffer. * @param size Size in bytes of block to map. * * @return A pointer to the mapped buffer, or NULL for failure. * * @pre Must have called CMEM_init() * * @sa CMEM_allocPhys() * @sa CMEM_allocPoolPhys() * @sa CMEM_unmap() */ void *CMEM_map(off_t physp, size_t size); #if defined(LINUXUTILS_BUILDOS_ANDROID) /** * @brief Map allocated memory using mmap64 (Android only) * * @param physp Physical address of the already-allocated buffer. * @param size Size in bytes of block to map. * * @return A pointer to the mapped buffer, or NULL for failure. * * @pre Must have called CMEM_init() * * @sa CMEM_allocPhys() * @sa CMEM_allocPoolPhys() * @sa CMEM_unmap() */ void *CMEM_map64(off64_t physp, size_t size); #endif /** * @brief Unmap allocated memory * * @param userp User virtual address of the mapped buffer. * @param size Size in bytes of block to unmap. * * @return Success/failure boolean value * * @pre Must have called CMEM_init() * * @sa CMEM_freePhys() * @sa CMEM_map() */ int CMEM_unmap(void *userp, size_t size); /** * @brief Do a cache invalidate of the block pointed to by @c ptr/@c size * * @param ptr Pointer to block to invalidate * @param size Size in bytes of block to invalidate * * @return Success/failure boolean value * * @pre Must have called CMEM_init() * * @sa CMEM_cacheWb() * @sa CMEM_cacheWbInv() * @sa CMEM_cacheWbInvAll() */ int CMEM_cacheInv(void *ptr, size_t size); /** * @brief Do a cache writeback/invalidate of the block pointed to by * @c ptr/@c size * * @param ptr Pointer to block to writeback/invalidate * @param size Size in bytes of block to writeback/invalidate * * @return Success/failure boolean value * * @pre Must have called CMEM_init() * * @sa CMEM_cacheInv() * @sa CMEM_cacheWb() * @sa CMEM_cacheWbInvAll() */ int CMEM_cacheWbInv(void *ptr, size_t size); /** * @brief Retrieve version from CMEM driver. * * @return Installed CMEM driver's version number. * * @pre Must have called CMEM_init() */ int CMEM_getVersion(void); /** * @brief Retrieve memory block bounds from CMEM driver * * @param pphys_base Pointer to storage for base physical address of * CMEM's memory block * @param psize Pointer to storage for size of CMEM's memory block * * @return Success (0) or failure (-1). * * @pre Must have called CMEM_init() * * @sa CMEM_getBlockAttrs() * @sa CMEM_getNumBlocks() */ int CMEM_getBlock(off_t *pphys_base, unsigned long long *psize); /** * @brief Retrieve extended memory block attributes from CMEM driver * * @param blockid Block number * @param pattrs Pointer to CMEM_BlockAttrs struct * * @return Success (0) or failure (-1). * * @remarks Currently this API returns the same values as CMEM_getBlock(). * * @pre Must have called CMEM_init() * * @sa CMEM_getBlock() * @sa CMEM_getNumBlocks() */ int CMEM_getBlockAttrs(int blockid, CMEM_BlockAttrs *pattrs); /** * @brief Retrieve number of blocks configured into CMEM driver * * @param pnblocks Pointer to storage for holding number of blocks * * @return Success (0) or failure (-1). * * @remarks Blocks are configured into CMEM through the Linux 'insmod' * command. * * @pre Must have called CMEM_init() * * @sa CMEM_getBlock() * @sa CMEM_getBlockAttrs() */ int CMEM_getNumBlocks(int *pnblocks); /** * @brief export as dma_buf a buffer previously allocated with * CMEM_alloc()/CMEM_allocPool(). * * @param ptr The pointer to the buffer. * * * @return 0 for success or -1 for failure. * * @pre Must have called CMEM_init() * * @sa CMEM_alloc() * @sa CMEM_alloc2() * @sa CMEM_allocPool() * @sa CMEM_allocPool2() * @sa CMEM_registerAlloc() * @sa CMEM_unregister() */ int CMEM_export_dmabuf(void *ptr); /** * @brief Finalize the CMEM module. * * @return 0 for success or -1 for failure. * * @remarks After this function has been called, no other CMEM function may be * called (unless CMEM is reinitialized). * * @pre Must have called CMEM_init() * * @sa CMEM_init() */ int CMEM_exit(void); /*@}*/ #if defined (__cplusplus) } #endif #endif