1f14f75b8SJes Sorensen /* 27f184275SHuang Ying * Basic general purpose allocator for managing special purpose 37f184275SHuang Ying * memory, for example, memory that is not managed by the regular 47f184275SHuang Ying * kmalloc/kfree interface. Uses for this includes on-device special 57f184275SHuang Ying * memory, uncached memory etc. 67f184275SHuang Ying * 77f184275SHuang Ying * It is safe to use the allocator in NMI handlers and other special 87f184275SHuang Ying * unblockable contexts that could otherwise deadlock on locks. This 97f184275SHuang Ying * is implemented by using atomic operations and retries on any 107f184275SHuang Ying * conflicts. The disadvantage is that there may be livelocks in 117f184275SHuang Ying * extreme cases. For better scalability, one allocator can be used 127f184275SHuang Ying * for each CPU. 137f184275SHuang Ying * 147f184275SHuang Ying * The lockless operation only works if there is enough memory 157f184275SHuang Ying * available. If new memory is added to the pool a lock has to be 167f184275SHuang Ying * still taken. So any user relying on locklessness has to ensure 177f184275SHuang Ying * that sufficient memory is preallocated. 187f184275SHuang Ying * 197f184275SHuang Ying * The basic atomic operation of this allocator is cmpxchg on long. 207f184275SHuang Ying * On architectures that don't have NMI-safe cmpxchg implementation, 217f184275SHuang Ying * the allocator can NOT be used in NMI handler. So code uses the 227f184275SHuang Ying * allocator in NMI handler should depend on 237f184275SHuang Ying * CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG. 24f14f75b8SJes Sorensen * 25f14f75b8SJes Sorensen * This source code is licensed under the GNU General Public License, 26f14f75b8SJes Sorensen * Version 2. See the file COPYING for more details. 27f14f75b8SJes Sorensen */ 28f14f75b8SJes Sorensen 29f14f75b8SJes Sorensen 306aae6e03SJean-Christophe PLAGNIOL-VILLARD #ifndef __GENALLOC_H__ 316aae6e03SJean-Christophe PLAGNIOL-VILLARD #define __GENALLOC_H__ 32*9375db07SPhilipp Zabel 33*9375db07SPhilipp Zabel struct device; 34*9375db07SPhilipp Zabel struct device_node; 35*9375db07SPhilipp Zabel 36ca279cf1SBenjamin Gaignard /** 37ca279cf1SBenjamin Gaignard * Allocation callback function type definition 38ca279cf1SBenjamin Gaignard * @map: Pointer to bitmap 39ca279cf1SBenjamin Gaignard * @size: The bitmap size in bits 40ca279cf1SBenjamin Gaignard * @start: The bitnumber to start searching at 41ca279cf1SBenjamin Gaignard * @nr: The number of zeroed bits we're looking for 42ca279cf1SBenjamin Gaignard * @data: optional additional data used by @genpool_algo_t 43ca279cf1SBenjamin Gaignard */ 44ca279cf1SBenjamin Gaignard typedef unsigned long (*genpool_algo_t)(unsigned long *map, 45ca279cf1SBenjamin Gaignard unsigned long size, 46ca279cf1SBenjamin Gaignard unsigned long start, 47ca279cf1SBenjamin Gaignard unsigned int nr, 48ca279cf1SBenjamin Gaignard void *data); 49ca279cf1SBenjamin Gaignard 50f14f75b8SJes Sorensen /* 51929f9727SDean Nelson * General purpose special memory pool descriptor. 52f14f75b8SJes Sorensen */ 53f14f75b8SJes Sorensen struct gen_pool { 547f184275SHuang Ying spinlock_t lock; 55929f9727SDean Nelson struct list_head chunks; /* list of chunks in this pool */ 56929f9727SDean Nelson int min_alloc_order; /* minimum allocation order */ 57ca279cf1SBenjamin Gaignard 58ca279cf1SBenjamin Gaignard genpool_algo_t algo; /* allocation function */ 59ca279cf1SBenjamin Gaignard void *data; 60f14f75b8SJes Sorensen }; 61f14f75b8SJes Sorensen 62929f9727SDean Nelson /* 63929f9727SDean Nelson * General purpose special memory pool chunk descriptor. 64929f9727SDean Nelson */ 65929f9727SDean Nelson struct gen_pool_chunk { 66929f9727SDean Nelson struct list_head next_chunk; /* next chunk in pool */ 677f184275SHuang Ying atomic_t avail; 683c8f370dSJean-Christophe PLAGNIOL-VILLARD phys_addr_t phys_addr; /* physical starting address of memory chunk */ 69929f9727SDean Nelson unsigned long start_addr; /* starting address of memory chunk */ 70929f9727SDean Nelson unsigned long end_addr; /* ending address of memory chunk */ 71929f9727SDean Nelson unsigned long bits[0]; /* bitmap for allocating memory chunk */ 72929f9727SDean Nelson }; 73929f9727SDean Nelson 74929f9727SDean Nelson extern struct gen_pool *gen_pool_create(int, int); 753c8f370dSJean-Christophe PLAGNIOL-VILLARD extern phys_addr_t gen_pool_virt_to_phys(struct gen_pool *pool, unsigned long); 763c8f370dSJean-Christophe PLAGNIOL-VILLARD extern int gen_pool_add_virt(struct gen_pool *, unsigned long, phys_addr_t, 773c8f370dSJean-Christophe PLAGNIOL-VILLARD size_t, int); 783c8f370dSJean-Christophe PLAGNIOL-VILLARD /** 793c8f370dSJean-Christophe PLAGNIOL-VILLARD * gen_pool_add - add a new chunk of special memory to the pool 803c8f370dSJean-Christophe PLAGNIOL-VILLARD * @pool: pool to add new memory chunk to 813c8f370dSJean-Christophe PLAGNIOL-VILLARD * @addr: starting address of memory chunk to add to pool 823c8f370dSJean-Christophe PLAGNIOL-VILLARD * @size: size in bytes of the memory chunk to add to pool 833c8f370dSJean-Christophe PLAGNIOL-VILLARD * @nid: node id of the node the chunk structure and bitmap should be 843c8f370dSJean-Christophe PLAGNIOL-VILLARD * allocated on, or -1 853c8f370dSJean-Christophe PLAGNIOL-VILLARD * 863c8f370dSJean-Christophe PLAGNIOL-VILLARD * Add a new chunk of special memory to the specified pool. 873c8f370dSJean-Christophe PLAGNIOL-VILLARD * 883c8f370dSJean-Christophe PLAGNIOL-VILLARD * Returns 0 on success or a -ve errno on failure. 893c8f370dSJean-Christophe PLAGNIOL-VILLARD */ 903c8f370dSJean-Christophe PLAGNIOL-VILLARD static inline int gen_pool_add(struct gen_pool *pool, unsigned long addr, 913c8f370dSJean-Christophe PLAGNIOL-VILLARD size_t size, int nid) 923c8f370dSJean-Christophe PLAGNIOL-VILLARD { 933c8f370dSJean-Christophe PLAGNIOL-VILLARD return gen_pool_add_virt(pool, addr, -1, size, nid); 943c8f370dSJean-Christophe PLAGNIOL-VILLARD } 95322acc96SSteve Wise extern void gen_pool_destroy(struct gen_pool *); 96929f9727SDean Nelson extern unsigned long gen_pool_alloc(struct gen_pool *, size_t); 97929f9727SDean Nelson extern void gen_pool_free(struct gen_pool *, unsigned long, size_t); 987f184275SHuang Ying extern void gen_pool_for_each_chunk(struct gen_pool *, 997f184275SHuang Ying void (*)(struct gen_pool *, struct gen_pool_chunk *, void *), void *); 1007f184275SHuang Ying extern size_t gen_pool_avail(struct gen_pool *); 1017f184275SHuang Ying extern size_t gen_pool_size(struct gen_pool *); 102ca279cf1SBenjamin Gaignard 103ca279cf1SBenjamin Gaignard extern void gen_pool_set_algo(struct gen_pool *pool, genpool_algo_t algo, 104ca279cf1SBenjamin Gaignard void *data); 105ca279cf1SBenjamin Gaignard 106ca279cf1SBenjamin Gaignard extern unsigned long gen_pool_first_fit(unsigned long *map, unsigned long size, 107ca279cf1SBenjamin Gaignard unsigned long start, unsigned int nr, void *data); 108ca279cf1SBenjamin Gaignard 109ca279cf1SBenjamin Gaignard extern unsigned long gen_pool_best_fit(unsigned long *map, unsigned long size, 110ca279cf1SBenjamin Gaignard unsigned long start, unsigned int nr, void *data); 111ca279cf1SBenjamin Gaignard 112*9375db07SPhilipp Zabel extern struct gen_pool *devm_gen_pool_create(struct device *dev, 113*9375db07SPhilipp Zabel int min_alloc_order, int nid); 114*9375db07SPhilipp Zabel extern struct gen_pool *dev_get_gen_pool(struct device *dev); 115*9375db07SPhilipp Zabel 116*9375db07SPhilipp Zabel #ifdef CONFIG_OF 117*9375db07SPhilipp Zabel extern struct gen_pool *of_get_named_gen_pool(struct device_node *np, 118*9375db07SPhilipp Zabel const char *propname, int index); 119*9375db07SPhilipp Zabel #else 120*9375db07SPhilipp Zabel static inline struct gen_pool *of_get_named_gen_pool(struct device_node *np, 121*9375db07SPhilipp Zabel const char *propname, int index) 122*9375db07SPhilipp Zabel { 123*9375db07SPhilipp Zabel return NULL; 124*9375db07SPhilipp Zabel } 125*9375db07SPhilipp Zabel #endif 1266aae6e03SJean-Christophe PLAGNIOL-VILLARD #endif /* __GENALLOC_H__ */ 127