#ifndef __LINUX_CMA_H #define __LINUX_CMA_H /* linux/include/linux/cma.h * * Contiguous Memory Allocator framework * Copyright (c) 2010 by Samsung Electronics. * Written by Michal Nazarewicz (m.nazarewicz@samsung.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation */ /* * See Documentation/contiguous-memory.txt for details. */ #include #include #define CMA_MAGIC (('c' << 24) | ('M' << 16) | ('a' << 8) | 0x42) enum { CMA_REQ_DEV_KIND, CMA_REQ_FROM_REG }; /** * An information about area exportable to user space. * @magic: must always be CMA_MAGIC. * @type: type of the request. * @spec: either "dev/kind\0" or "regions\0" depending on @type. * In any case, the string must be NUL terminated. * additionally, in the latter case scanning stops at * semicolon (';'). * @size: size of the chunk to allocate. * @alignment: desired alignment of the chunk (must be power of two or zero). * @start: when ioctl() finishes this stores physical address of the chunk. */ struct cma_alloc_request { __u32 magic; __u32 type; /* __u64 to be compatible accross 32 and 64 bit systems. */ __u64 size; __u64 alignment; __u64 start; char spec[32]; }; #define IOCTL_CMA_ALLOC _IOWR('p', 0, struct cma_alloc_request) /***************************** Kernel level API *****************************/ #ifdef __KERNEL__ #include #include #if defined CONFIG_CMA_SYSFS # include #endif struct device; struct cma_info; /* * Don't call it directly, use cma_alloc(), cma_alloc_from() or * cma_alloc_from_region(). */ dma_addr_t __must_check __cma_alloc(const struct device *dev, const char *type, size_t size, dma_addr_t alignment); /* Don't call it directly, use cma_info() or cma_info_about(). */ int __cma_info(struct cma_info *info, const struct device *dev, const char *type); /** * cma_alloc - allocates contiguous chunk of memory. * @dev: The device to perform allocation for. * @type: A type of memory to allocate. Platform may define * several different types of memory and device drivers * can then request chunks of different types. Usually it's * safe to pass NULL here which is the same as passing * "common". * @size: Size of the memory to allocate in bytes. * @alignment: Desired alignment in bytes. Must be a power of two or * zero. If alignment is less then a page size it will be * set to page size. If unsure, pass zero here. * * On error returns a negative error cast to dma_addr_t. Use * IS_ERR_VALUE() to check if returned value is indeed an error. * Otherwise bus address of the chunk is returned. */ static inline dma_addr_t __must_check cma_alloc(const struct device *dev, const char *type, size_t size, dma_addr_t alignment) { return dev ? __cma_alloc(dev, type, size, alignment) : -EINVAL; } /** * struct cma_info - information about regions returned by cma_info(). * @lower_bound: The smallest address that is possible to be * allocated for given (dev, type) pair. * @upper_bound: The one byte after the biggest address that is * possible to be allocated for given (dev, type) * pair. * @total_size: Total size of regions mapped to (dev, type) pair. * @free_size: Total free size in all of the regions mapped to (dev, type) * pair. Because of possible race conditions, it is not * guaranteed that the value will be correct -- it gives only * an approximation. * @count: Number of regions mapped to (dev, type) pair. */ struct cma_info { dma_addr_t lower_bound, upper_bound; size_t total_size, free_size; unsigned count; }; /** * cma_info - queries information about regions. * @info: Pointer to a structure where to save the information. * @dev: The device to query information for. * @type: A type of memory to query information for. * If unsure, pass NULL here which is equal to passing * "common". * * On error returns a negative error, zero otherwise. */ static inline int cma_info(struct cma_info *info, const struct device *dev, const char *type) { return dev ? __cma_info(info, dev, type) : -EINVAL; } /** * cma_free - frees a chunk of memory. * @addr: Beginning of the chunk. * * Returns -ENOENT if there is no chunk at given location; otherwise * zero. In the former case issues a warning. */ int cma_free(dma_addr_t addr); /** * cma_get_virt - frees virtual address of cma memory. * @phys: physical addrress * @size: size of memory * @noncached : 0 is cached, 1 is non-cached. * * Returns -ENOENT if there is no chunk at given location; otherwise * zero. In the former case issues a warning. */ void *cma_get_virt(dma_addr_t phys, dma_addr_t size, int noncached); /****************************** Lower lever API *****************************/ /** * cma_alloc_from - allocates contiguous chunk of memory from named regions. * @regions: Comma separated list of region names. Terminated by NUL * byte or a semicolon. * @size: Size of the memory to allocate in bytes. * @alignment: Desired alignment in bytes. Must be a power of two or * zero. If alignment is less then a page size it will be * set to page size. If unsure, pass zero here. * * On error returns a negative error cast to dma_addr_t. Use * IS_ERR_VALUE() to check if returned value is indeed an error. * Otherwise bus address of the chunk is returned. */ static inline dma_addr_t __must_check cma_alloc_from(const char *regions, size_t size, dma_addr_t alignment) { return __cma_alloc(NULL, regions, size, alignment); } /** * cma_info_about - queries information about named regions. * @info: Pointer to a structure where to save the information. * @regions: Comma separated list of region names. Terminated by NUL * byte or a semicolon. * * On error returns a negative error, zero otherwise. */ static inline int cma_info_about(struct cma_info *info, const const char *regions) { return __cma_info(info, NULL, regions); } struct cma_allocator; /** * struct cma_region - a region reserved for CMA allocations. * @name: Unique name of the region. Read only. * @start: Bus address of the region in bytes. Always aligned at * least to a full page. Read only. * @size: Size of the region in bytes. Multiply of a page size. * Read only. * @free_space: Free space in the region. Read only. * @alignment: Desired alignment of the region in bytes. A power of two, * always at least page size. Early. * @alloc: Allocator used with this region. NULL means allocator is * not attached. Private. * @alloc_name: Allocator name read from cmdline. Private. This may be * different from @alloc->name. * @private_data: Allocator's private data. * @users: Number of chunks allocated in this region. * @list: Entry in list of regions. Private. * @used: Whether region was already used, ie. there was at least * one allocation request for. Private. * @registered: Whether this region has been registered. Read only. * @reserved: Whether this region has been reserved. Early. Read only. * @copy_name: Whether @name and @alloc_name needs to be copied when * this region is converted from early to normal. Early. * Private. * @free_alloc_name: Whether @alloc_name was kmalloced(). Private. * * Regions come in two types: an early region and normal region. The * former can be reserved or not-reserved. Fields marked as "early" * are only meaningful in early regions. * * Early regions are important only during initialisation. The list * of early regions is built from the "cma" command line argument or * platform defaults. Platform initialisation code is responsible for * reserving space for unreserved regions that are placed on * cma_early_regions list. * * Later, during CMA initialisation all reserved regions from the * cma_early_regions list are registered as normal regions and can be * used using standard mechanisms. */ struct cma_region { const char *name; dma_addr_t start; size_t size; union { size_t free_space; /* Normal region */ dma_addr_t alignment; /* Early region */ }; struct cma_allocator *alloc; const char *alloc_name; void *private_data; unsigned users; struct list_head list; #if defined CONFIG_CMA_SYSFS struct kobject kobj; #endif unsigned used:1; unsigned registered:1; unsigned reserved:1; unsigned copy_name:1; unsigned free_alloc_name:1; }; /** * cma_region_register() - registers a region. * @reg: Region to region. * * Region's start and size must be set. * * If name is set the region will be accessible using normal mechanism * like mapping or cma_alloc_from() function otherwise it will be * a private region and accessible only using the * cma_alloc_from_region() function. * * If alloc is set function will try to initialise given allocator * (and will return error if it failes). Otherwise alloc_name may * point to a name of an allocator to use (if not set, the default * will be used). * * All other fields are ignored and/or overwritten. * * Returns zero or negative error. In particular, -EADDRINUSE if * region overlap with already existing region. */ int __must_check cma_region_register(struct cma_region *reg); /** * cma_region_unregister() - unregisters a region. * @reg: Region to unregister. * * Region is unregistered only if there are no chunks allocated for * it. Otherwise, function returns -EBUSY. * * On success returs zero. */ int __must_check cma_region_unregister(struct cma_region *reg); /** * cma_alloc_from_region() - allocates contiguous chunk of memory from region. * @reg: Region to allocate chunk from. * @size: Size of the memory to allocate in bytes. * @alignment: Desired alignment in bytes. Must be a power of two or * zero. If alignment is less then a page size it will be * set to page size. If unsure, pass zero here. * * On error returns a negative error cast to dma_addr_t. Use * IS_ERR_VALUE() to check if returned value is indeed an error. * Otherwise bus address of the chunk is returned. */ dma_addr_t __must_check cma_alloc_from_region(struct cma_region *reg, size_t size, dma_addr_t alignment); /****************************** Allocators API ******************************/ /** * struct cma_chunk - an allocated contiguous chunk of memory. * @start: Bus address in bytes. * @size: Size in bytes. * @free_space: Free space in region in bytes. Read only. * @reg: Region this chunk belongs to. * @by_start: A node in an red-black tree with all chunks sorted by * start address. * * The cma_allocator::alloc() operation need to set only the @start * and @size fields. The rest is handled by the caller (ie. CMA * glue). */ struct cma_chunk { dma_addr_t start; size_t size; struct cma_region *reg; struct rb_node by_start; }; /** * struct cma_allocator - a CMA allocator. * @name: Allocator's unique name * @init: Initialises an allocator on given region. * @cleanup: Cleans up after init. May assume that there are no chunks * allocated in given region. * @alloc: Allocates a chunk of memory of given size in bytes and * with given alignment. Alignment is a power of * two (thus non-zero) and callback does not need to check it. * May also assume that it is the only call that uses given * region (ie. access to the region is synchronised with * a mutex). This has to allocate the chunk object (it may be * contained in a bigger structure with allocator-specific data. * Required. * @free: Frees allocated chunk. May also assume that it is the only * call that uses given region. This has to free() the chunk * object as well. Required. * @list: Entry in list of allocators. Private. */ struct cma_allocator { const char *name; int (*init)(struct cma_region *reg); void (*cleanup)(struct cma_region *reg); struct cma_chunk *(*alloc)(struct cma_region *reg, size_t size, dma_addr_t alignment); void (*free)(struct cma_chunk *chunk); struct list_head list; }; /** * cma_allocator_register() - Registers an allocator. * @alloc: Allocator to register. * * Adds allocator to the list of allocators managed by CMA. * * All of the fields of cma_allocator structure must be set except for * the optional name and the list's head which will be overriden * anyway. * * Returns zero or negative error code. */ int cma_allocator_register(struct cma_allocator *alloc); /**************************** Initialisation API ****************************/ /** * cma_set_defaults() - specifies default command line parameters. * @regions: A zero-sized entry terminated list of early regions. * This array must not be placed in __initdata section. * @map: Map attribute. * * This function should be called prior to cma_early_regions_reserve() * and after early parameters have been parsed. * * Returns zero or negative error. */ int __init cma_set_defaults(struct cma_region *regions, const char *map); /** * cma_early_regions - a list of early regions. * * Platform needs to allocate space for each of the region before * initcalls are executed. If space is reserved, the reserved flag * must be set. Platform initialisation code may choose to use * cma_early_regions_allocate(). * * Later, during CMA initialisation all reserved regions from the * cma_early_regions list are registered as normal regions and can be * used using standard mechanisms. */ extern struct list_head cma_early_regions __initdata; /** * cma_early_region_register() - registers an early region. * @reg: Region to add. * * Region's size, start and alignment must be set (however the last * two can be zero). If name is set the region will be accessible * using normal mechanism like mapping or cma_alloc_from() function * otherwise it will be a private region accessible only using the * cma_alloc_from_region(). * * During platform initialisation, space is reserved for early * regions. Later, when CMA initialises, the early regions are * "converted" into normal regions. If cma_region::alloc is set, CMA * will then try to setup given allocator on the region. Failure to * do so will result in the region not being registered even though * the space for it will still be reserved. If cma_region::alloc is * not set, allocator will be attached to the region on first use and * the value of cma_region::alloc_name will be taken into account if * set. * * All other fields are ignored and/or overwritten. * * Returns zero or negative error. No checking if regions overlap is * performed. */ int __init __must_check cma_early_region_register(struct cma_region *reg); /** * cma_early_region_reserve() - reserves a physically contiguous memory region. * @reg: Early region to reserve memory for. * * If platform supports bootmem this is the first allocator this * function tries to use. If that failes (or bootmem is not * supported) function tries to use memblec if it is available. * * On success sets reg->reserved flag. * * Returns zero or negative error. */ int __init cma_early_region_reserve(struct cma_region *reg); /** * cma_early_regions_reserve() - helper function for reserving early regions. * @reserve: Callbac function used to reserve space for region. Needs * to return non-negative if allocation succeeded, negative * error otherwise. NULL means cma_early_region_alloc() will * be used. * * This function traverses the %cma_early_regions list and tries to * reserve memory for each early region. It uses the @reserve * callback function for that purpose. The reserved flag of each * region is updated accordingly. */ void __init cma_early_regions_reserve(int (*reserve)(struct cma_region *reg)); #else #define cma_set_defaults(regions, map) ((int)0) #define cma_early_region_reserve(region) ((int)-EOPNOTSUPP) #define cma_early_regions_reserve(reserve) do { } while (0) #endif #ifdef CONFIG_CMA bool cma_is_registered_region(phys_addr_t start, size_t size); #else #define cma_is_registered_region(start, size) (false) #endif #endif