40b0b3f8fb2d8 (Thomas Gleixner 2019-06-03 07:44:46 +0200 1) // SPDX-License-Identifier: GPL-2.0-only
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 2) /*
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 3) * Basic general purpose allocator for managing special purpose
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 4) * memory, for example, memory that is not managed by the regular
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 5) * kmalloc/kfree interface. Uses for this includes on-device special
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 6) * memory, uncached memory etc.
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 7) *
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 8) * It is safe to use the allocator in NMI handlers and other special
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 9) * unblockable contexts that could otherwise deadlock on locks. This
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 10) * is implemented by using atomic operations and retries on any
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 11) * conflicts. The disadvantage is that there may be livelocks in
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 12) * extreme cases. For better scalability, one allocator can be used
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 13) * for each CPU.
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 14) *
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 15) * The lockless operation only works if there is enough memory
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 16) * available. If new memory is added to the pool a lock has to be
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 17) * still taken. So any user relying on locklessness has to ensure
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 18) * that sufficient memory is preallocated.
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 19) *
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 20) * The basic atomic operation of this allocator is cmpxchg on long.
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 21) * On architectures that don't have NMI-safe cmpxchg implementation,
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 22) * the allocator can NOT be used in NMI handler. So code uses the
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 23) * allocator in NMI handler should depend on
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 24) * CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG.
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 25) *
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 26) * Copyright 2005 (C) Jes Sorensen <jes@trained-monkey.org>
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 27) */
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 28)
5a0e3ad6af866 (Tejun Heo 2010-03-24 17:04:11 +0900 29) #include <linux/slab.h>
8bc3bcc93a2b4 (Paul Gortmaker 2011-11-16 21:29:17 -0500 30) #include <linux/export.h>
243797f59b748 (Akinobu Mita 2009-12-15 16:48:31 -0800 31) #include <linux/bitmap.h>
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 32) #include <linux/rculist.h>
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 33) #include <linux/interrupt.h>
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 34) #include <linux/genalloc.h>
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 35) #include <linux/of_device.h>
35004f2e55807 (Olof Johansson 2019-01-05 13:21:18 -0800 36) #include <linux/vmalloc.h>
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 37)
674470d97958a (Joonyoung Shim 2013-09-11 14:21:43 -0700 38) static inline size_t chunk_size(const struct gen_pool_chunk *chunk)
674470d97958a (Joonyoung Shim 2013-09-11 14:21:43 -0700 39) {
674470d97958a (Joonyoung Shim 2013-09-11 14:21:43 -0700 40) return chunk->end_addr - chunk->start_addr + 1;
674470d97958a (Joonyoung Shim 2013-09-11 14:21:43 -0700 41) }
674470d97958a (Joonyoung Shim 2013-09-11 14:21:43 -0700 42)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 43) static int set_bits_ll(unsigned long *addr, unsigned long mask_to_set)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 44) {
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 45) unsigned long val, nval;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 46)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 47) nval = *addr;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 48) do {
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 49) val = nval;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 50) if (val & mask_to_set)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 51) return -EBUSY;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 52) cpu_relax();
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 53) } while ((nval = cmpxchg(addr, val, val | mask_to_set)) != val);
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 54)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 55) return 0;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 56) }
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 57)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 58) static int clear_bits_ll(unsigned long *addr, unsigned long mask_to_clear)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 59) {
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 60) unsigned long val, nval;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 61)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 62) nval = *addr;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 63) do {
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 64) val = nval;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 65) if ((val & mask_to_clear) != mask_to_clear)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 66) return -EBUSY;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 67) cpu_relax();
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 68) } while ((nval = cmpxchg(addr, val, val & ~mask_to_clear)) != val);
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 69)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 70) return 0;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 71) }
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 72)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 73) /*
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 74) * bitmap_set_ll - set the specified number of bits at the specified position
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 75) * @map: pointer to a bitmap
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 76) * @start: a bit position in @map
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 77) * @nr: number of bits to set
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 78) *
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 79) * Set @nr bits start from @start in @map lock-lessly. Several users
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 80) * can set/clear the same bitmap simultaneously without lock. If two
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 81) * users set the same bit, one user will return remain bits, otherwise
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 82) * return 0.
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 83) */
0e24465d33138 (Huang Shijie 2021-02-25 17:21:17 -0800 84) static unsigned long
0e24465d33138 (Huang Shijie 2021-02-25 17:21:17 -0800 85) bitmap_set_ll(unsigned long *map, unsigned long start, unsigned long nr)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 86) {
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 87) unsigned long *p = map + BIT_WORD(start);
36845663843fc (Huang Shijie 2020-12-29 15:14:58 -0800 88) const unsigned long size = start + nr;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 89) int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 90) unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 91)
36845663843fc (Huang Shijie 2020-12-29 15:14:58 -0800 92) while (nr >= bits_to_set) {
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 93) if (set_bits_ll(p, mask_to_set))
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 94) return nr;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 95) nr -= bits_to_set;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 96) bits_to_set = BITS_PER_LONG;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 97) mask_to_set = ~0UL;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 98) p++;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 99) }
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 100) if (nr) {
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 101) mask_to_set &= BITMAP_LAST_WORD_MASK(size);
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 102) if (set_bits_ll(p, mask_to_set))
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 103) return nr;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 104) }
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 105)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 106) return 0;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 107) }
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 108)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 109) /*
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 110) * bitmap_clear_ll - clear the specified number of bits at the specified position
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 111) * @map: pointer to a bitmap
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 112) * @start: a bit position in @map
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 113) * @nr: number of bits to set
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 114) *
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 115) * Clear @nr bits start from @start in @map lock-lessly. Several users
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 116) * can set/clear the same bitmap simultaneously without lock. If two
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 117) * users clear the same bit, one user will return remain bits,
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 118) * otherwise return 0.
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 119) */
36845663843fc (Huang Shijie 2020-12-29 15:14:58 -0800 120) static unsigned long
36845663843fc (Huang Shijie 2020-12-29 15:14:58 -0800 121) bitmap_clear_ll(unsigned long *map, unsigned long start, unsigned long nr)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 122) {
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 123) unsigned long *p = map + BIT_WORD(start);
36845663843fc (Huang Shijie 2020-12-29 15:14:58 -0800 124) const unsigned long size = start + nr;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 125) int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 126) unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 127)
36845663843fc (Huang Shijie 2020-12-29 15:14:58 -0800 128) while (nr >= bits_to_clear) {
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 129) if (clear_bits_ll(p, mask_to_clear))
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 130) return nr;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 131) nr -= bits_to_clear;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 132) bits_to_clear = BITS_PER_LONG;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 133) mask_to_clear = ~0UL;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 134) p++;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 135) }
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 136) if (nr) {
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 137) mask_to_clear &= BITMAP_LAST_WORD_MASK(size);
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 138) if (clear_bits_ll(p, mask_to_clear))
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 139) return nr;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 140) }
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 141)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 142) return 0;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 143) }
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 144)
a58cbd7c249f3 (Dean Nelson 2006-10-02 02:17:01 -0700 145) /**
a58cbd7c249f3 (Dean Nelson 2006-10-02 02:17:01 -0700 146) * gen_pool_create - create a new special memory pool
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 147) * @min_alloc_order: log base 2 of number of bytes each bitmap bit represents
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 148) * @nid: node id of the node the pool structure should be allocated on, or -1
a58cbd7c249f3 (Dean Nelson 2006-10-02 02:17:01 -0700 149) *
a58cbd7c249f3 (Dean Nelson 2006-10-02 02:17:01 -0700 150) * Create a new special memory pool that can be used to manage special purpose
a58cbd7c249f3 (Dean Nelson 2006-10-02 02:17:01 -0700 151) * memory not managed by the regular kmalloc/kfree interface.
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 152) */
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 153) struct gen_pool *gen_pool_create(int min_alloc_order, int nid)
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 154) {
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 155) struct gen_pool *pool;
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 156)
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 157) pool = kmalloc_node(sizeof(struct gen_pool), GFP_KERNEL, nid);
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 158) if (pool != NULL) {
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 159) spin_lock_init(&pool->lock);
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 160) INIT_LIST_HEAD(&pool->chunks);
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 161) pool->min_alloc_order = min_alloc_order;
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 162) pool->algo = gen_pool_first_fit;
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 163) pool->data = NULL;
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 164) pool->name = NULL;
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 165) }
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 166) return pool;
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 167) }
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 168) EXPORT_SYMBOL(gen_pool_create);
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 169)
a58cbd7c249f3 (Dean Nelson 2006-10-02 02:17:01 -0700 170) /**
795ee30648c70 (Dan Williams 2019-06-13 15:56:27 -0700 171) * gen_pool_add_owner- add a new chunk of special memory to the pool
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 172) * @pool: pool to add new memory chunk to
3c8f370ded348 (Jean-Christophe PLAGNIOL-VILLARD 2011-05-24 17:13:34 -0700 173) * @virt: virtual starting address of memory chunk to add to pool
3c8f370ded348 (Jean-Christophe PLAGNIOL-VILLARD 2011-05-24 17:13:34 -0700 174) * @phys: physical starting address of memory chunk to add to pool
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 175) * @size: size in bytes of the memory chunk to add to pool
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 176) * @nid: node id of the node the chunk structure and bitmap should be
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 177) * allocated on, or -1
795ee30648c70 (Dan Williams 2019-06-13 15:56:27 -0700 178) * @owner: private data the publisher would like to recall at alloc time
a58cbd7c249f3 (Dean Nelson 2006-10-02 02:17:01 -0700 179) *
a58cbd7c249f3 (Dean Nelson 2006-10-02 02:17:01 -0700 180) * Add a new chunk of special memory to the specified pool.
3c8f370ded348 (Jean-Christophe PLAGNIOL-VILLARD 2011-05-24 17:13:34 -0700 181) *
3c8f370ded348 (Jean-Christophe PLAGNIOL-VILLARD 2011-05-24 17:13:34 -0700 182) * Returns 0 on success or a -ve errno on failure.
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 183) */
795ee30648c70 (Dan Williams 2019-06-13 15:56:27 -0700 184) int gen_pool_add_owner(struct gen_pool *pool, unsigned long virt, phys_addr_t phys,
795ee30648c70 (Dan Williams 2019-06-13 15:56:27 -0700 185) size_t size, int nid, void *owner)
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 186) {
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 187) struct gen_pool_chunk *chunk;
36845663843fc (Huang Shijie 2020-12-29 15:14:58 -0800 188) unsigned long nbits = size >> pool->min_alloc_order;
36845663843fc (Huang Shijie 2020-12-29 15:14:58 -0800 189) unsigned long nbytes = sizeof(struct gen_pool_chunk) +
eedce141cd2da (Thadeu Lima de Souza Cascardo 2012-10-25 13:37:51 -0700 190) BITS_TO_LONGS(nbits) * sizeof(long);
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 191)
6862d2fc81859 (Huang Shijie 2019-01-03 15:26:51 -0800 192) chunk = vzalloc_node(nbytes, nid);
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 193) if (unlikely(chunk == NULL))
3c8f370ded348 (Jean-Christophe PLAGNIOL-VILLARD 2011-05-24 17:13:34 -0700 194) return -ENOMEM;
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 195)
3c8f370ded348 (Jean-Christophe PLAGNIOL-VILLARD 2011-05-24 17:13:34 -0700 196) chunk->phys_addr = phys;
3c8f370ded348 (Jean-Christophe PLAGNIOL-VILLARD 2011-05-24 17:13:34 -0700 197) chunk->start_addr = virt;
674470d97958a (Joonyoung Shim 2013-09-11 14:21:43 -0700 198) chunk->end_addr = virt + size - 1;
795ee30648c70 (Dan Williams 2019-06-13 15:56:27 -0700 199) chunk->owner = owner;
36a3d1dd4e16b (Stephen Bates 2017-11-17 15:28:16 -0800 200) atomic_long_set(&chunk->avail, size);
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 201)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 202) spin_lock(&pool->lock);
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 203) list_add_rcu(&chunk->next_chunk, &pool->chunks);
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 204) spin_unlock(&pool->lock);
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 205)
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 206) return 0;
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 207) }
795ee30648c70 (Dan Williams 2019-06-13 15:56:27 -0700 208) EXPORT_SYMBOL(gen_pool_add_owner);
3c8f370ded348 (Jean-Christophe PLAGNIOL-VILLARD 2011-05-24 17:13:34 -0700 209)
3c8f370ded348 (Jean-Christophe PLAGNIOL-VILLARD 2011-05-24 17:13:34 -0700 210) /**
3c8f370ded348 (Jean-Christophe PLAGNIOL-VILLARD 2011-05-24 17:13:34 -0700 211) * gen_pool_virt_to_phys - return the physical address of memory
3c8f370ded348 (Jean-Christophe PLAGNIOL-VILLARD 2011-05-24 17:13:34 -0700 212) * @pool: pool to allocate from
3c8f370ded348 (Jean-Christophe PLAGNIOL-VILLARD 2011-05-24 17:13:34 -0700 213) * @addr: starting address of memory
3c8f370ded348 (Jean-Christophe PLAGNIOL-VILLARD 2011-05-24 17:13:34 -0700 214) *
3c8f370ded348 (Jean-Christophe PLAGNIOL-VILLARD 2011-05-24 17:13:34 -0700 215) * Returns the physical address on success, or -1 on error.
3c8f370ded348 (Jean-Christophe PLAGNIOL-VILLARD 2011-05-24 17:13:34 -0700 216) */
3c8f370ded348 (Jean-Christophe PLAGNIOL-VILLARD 2011-05-24 17:13:34 -0700 217) phys_addr_t gen_pool_virt_to_phys(struct gen_pool *pool, unsigned long addr)
3c8f370ded348 (Jean-Christophe PLAGNIOL-VILLARD 2011-05-24 17:13:34 -0700 218) {
3c8f370ded348 (Jean-Christophe PLAGNIOL-VILLARD 2011-05-24 17:13:34 -0700 219) struct gen_pool_chunk *chunk;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 220) phys_addr_t paddr = -1;
3c8f370ded348 (Jean-Christophe PLAGNIOL-VILLARD 2011-05-24 17:13:34 -0700 221)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 222) rcu_read_lock();
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 223) list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk) {
674470d97958a (Joonyoung Shim 2013-09-11 14:21:43 -0700 224) if (addr >= chunk->start_addr && addr <= chunk->end_addr) {
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 225) paddr = chunk->phys_addr + (addr - chunk->start_addr);
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 226) break;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 227) }
3c8f370ded348 (Jean-Christophe PLAGNIOL-VILLARD 2011-05-24 17:13:34 -0700 228) }
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 229) rcu_read_unlock();
3c8f370ded348 (Jean-Christophe PLAGNIOL-VILLARD 2011-05-24 17:13:34 -0700 230)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 231) return paddr;
3c8f370ded348 (Jean-Christophe PLAGNIOL-VILLARD 2011-05-24 17:13:34 -0700 232) }
3c8f370ded348 (Jean-Christophe PLAGNIOL-VILLARD 2011-05-24 17:13:34 -0700 233) EXPORT_SYMBOL(gen_pool_virt_to_phys);
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 234)
a58cbd7c249f3 (Dean Nelson 2006-10-02 02:17:01 -0700 235) /**
a58cbd7c249f3 (Dean Nelson 2006-10-02 02:17:01 -0700 236) * gen_pool_destroy - destroy a special memory pool
322acc96d4bd3 (Steve Wise 2006-10-02 02:17:00 -0700 237) * @pool: pool to destroy
a58cbd7c249f3 (Dean Nelson 2006-10-02 02:17:01 -0700 238) *
a58cbd7c249f3 (Dean Nelson 2006-10-02 02:17:01 -0700 239) * Destroy the specified special memory pool. Verifies that there are no
a58cbd7c249f3 (Dean Nelson 2006-10-02 02:17:01 -0700 240) * outstanding allocations.
322acc96d4bd3 (Steve Wise 2006-10-02 02:17:00 -0700 241) */
322acc96d4bd3 (Steve Wise 2006-10-02 02:17:00 -0700 242) void gen_pool_destroy(struct gen_pool *pool)
322acc96d4bd3 (Steve Wise 2006-10-02 02:17:00 -0700 243) {
322acc96d4bd3 (Steve Wise 2006-10-02 02:17:00 -0700 244) struct list_head *_chunk, *_next_chunk;
322acc96d4bd3 (Steve Wise 2006-10-02 02:17:00 -0700 245) struct gen_pool_chunk *chunk;
322acc96d4bd3 (Steve Wise 2006-10-02 02:17:00 -0700 246) int order = pool->min_alloc_order;
36845663843fc (Huang Shijie 2020-12-29 15:14:58 -0800 247) unsigned long bit, end_bit;
322acc96d4bd3 (Steve Wise 2006-10-02 02:17:00 -0700 248)
322acc96d4bd3 (Steve Wise 2006-10-02 02:17:00 -0700 249) list_for_each_safe(_chunk, _next_chunk, &pool->chunks) {
322acc96d4bd3 (Steve Wise 2006-10-02 02:17:00 -0700 250) chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk);
322acc96d4bd3 (Steve Wise 2006-10-02 02:17:00 -0700 251) list_del(&chunk->next_chunk);
322acc96d4bd3 (Steve Wise 2006-10-02 02:17:00 -0700 252)
674470d97958a (Joonyoung Shim 2013-09-11 14:21:43 -0700 253) end_bit = chunk_size(chunk) >> order;
322acc96d4bd3 (Steve Wise 2006-10-02 02:17:00 -0700 254) bit = find_next_bit(chunk->bits, end_bit, 0);
322acc96d4bd3 (Steve Wise 2006-10-02 02:17:00 -0700 255) BUG_ON(bit < end_bit);
322acc96d4bd3 (Steve Wise 2006-10-02 02:17:00 -0700 256)
6862d2fc81859 (Huang Shijie 2019-01-03 15:26:51 -0800 257) vfree(chunk);
322acc96d4bd3 (Steve Wise 2006-10-02 02:17:00 -0700 258) }
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 259) kfree_const(pool->name);
322acc96d4bd3 (Steve Wise 2006-10-02 02:17:00 -0700 260) kfree(pool);
322acc96d4bd3 (Steve Wise 2006-10-02 02:17:00 -0700 261) }
322acc96d4bd3 (Steve Wise 2006-10-02 02:17:00 -0700 262) EXPORT_SYMBOL(gen_pool_destroy);
322acc96d4bd3 (Steve Wise 2006-10-02 02:17:00 -0700 263)
a58cbd7c249f3 (Dean Nelson 2006-10-02 02:17:01 -0700 264) /**
795ee30648c70 (Dan Williams 2019-06-13 15:56:27 -0700 265) * gen_pool_alloc_algo_owner - allocate special memory from the pool
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 266) * @pool: pool to allocate from
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 267) * @size: number of bytes to allocate from the pool
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 268) * @algo: algorithm passed from caller
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 269) * @data: data passed to algorithm
795ee30648c70 (Dan Williams 2019-06-13 15:56:27 -0700 270) * @owner: optionally retrieve the chunk owner
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 271) *
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 272) * Allocate the requested number of bytes from the specified pool.
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 273) * Uses the pool allocation function (with first-fit algorithm by default).
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 274) * Can not be used in NMI handler on architectures without
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 275) * NMI-safe cmpxchg implementation.
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 276) */
795ee30648c70 (Dan Williams 2019-06-13 15:56:27 -0700 277) unsigned long gen_pool_alloc_algo_owner(struct gen_pool *pool, size_t size,
795ee30648c70 (Dan Williams 2019-06-13 15:56:27 -0700 278) genpool_algo_t algo, void *data, void **owner)
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 279) {
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 280) struct gen_pool_chunk *chunk;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 281) unsigned long addr = 0;
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 282) int order = pool->min_alloc_order;
36845663843fc (Huang Shijie 2020-12-29 15:14:58 -0800 283) unsigned long nbits, start_bit, end_bit, remain;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 284)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 285) #ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 286) BUG_ON(in_nmi());
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 287) #endif
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 288)
795ee30648c70 (Dan Williams 2019-06-13 15:56:27 -0700 289) if (owner)
795ee30648c70 (Dan Williams 2019-06-13 15:56:27 -0700 290) *owner = NULL;
795ee30648c70 (Dan Williams 2019-06-13 15:56:27 -0700 291)
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 292) if (size == 0)
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 293) return 0;
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 294)
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 295) nbits = (size + (1UL << order) - 1) >> order;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 296) rcu_read_lock();
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 297) list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk) {
36a3d1dd4e16b (Stephen Bates 2017-11-17 15:28:16 -0800 298) if (size > atomic_long_read(&chunk->avail))
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 299) continue;
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 300)
62e931fac45b1 (Daniel Mentz 2016-10-27 17:46:59 -0700 301) start_bit = 0;
674470d97958a (Joonyoung Shim 2013-09-11 14:21:43 -0700 302) end_bit = chunk_size(chunk) >> order;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 303) retry:
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 304) start_bit = algo(chunk->bits, end_bit, start_bit,
52fbf1134d479 (Alexey Skidanov 2019-01-03 15:26:44 -0800 305) nbits, data, pool, chunk->start_addr);
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 306) if (start_bit >= end_bit)
243797f59b748 (Akinobu Mita 2009-12-15 16:48:31 -0800 307) continue;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 308) remain = bitmap_set_ll(chunk->bits, start_bit, nbits);
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 309) if (remain) {
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 310) remain = bitmap_clear_ll(chunk->bits, start_bit,
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 311) nbits - remain);
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 312) BUG_ON(remain);
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 313) goto retry;
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 314) }
243797f59b748 (Akinobu Mita 2009-12-15 16:48:31 -0800 315)
243797f59b748 (Akinobu Mita 2009-12-15 16:48:31 -0800 316) addr = chunk->start_addr + ((unsigned long)start_bit << order);
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 317) size = nbits << order;
36a3d1dd4e16b (Stephen Bates 2017-11-17 15:28:16 -0800 318) atomic_long_sub(size, &chunk->avail);
795ee30648c70 (Dan Williams 2019-06-13 15:56:27 -0700 319) if (owner)
795ee30648c70 (Dan Williams 2019-06-13 15:56:27 -0700 320) *owner = chunk->owner;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 321) break;
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 322) }
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 323) rcu_read_unlock();
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 324) return addr;
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 325) }
795ee30648c70 (Dan Williams 2019-06-13 15:56:27 -0700 326) EXPORT_SYMBOL(gen_pool_alloc_algo_owner);
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 327)
684f0d3d14f27 (Nicolin Chen 2013-11-12 15:09:52 -0800 328) /**
684f0d3d14f27 (Nicolin Chen 2013-11-12 15:09:52 -0800 329) * gen_pool_dma_alloc - allocate special memory from the pool for DMA usage
684f0d3d14f27 (Nicolin Chen 2013-11-12 15:09:52 -0800 330) * @pool: pool to allocate from
684f0d3d14f27 (Nicolin Chen 2013-11-12 15:09:52 -0800 331) * @size: number of bytes to allocate from the pool
da83a722959a8 (Fredrik Noring 2019-05-29 13:28:39 +0300 332) * @dma: dma-view physical address return value. Use %NULL if unneeded.
684f0d3d14f27 (Nicolin Chen 2013-11-12 15:09:52 -0800 333) *
684f0d3d14f27 (Nicolin Chen 2013-11-12 15:09:52 -0800 334) * Allocate the requested number of bytes from the specified pool.
684f0d3d14f27 (Nicolin Chen 2013-11-12 15:09:52 -0800 335) * Uses the pool allocation function (with first-fit algorithm by default).
684f0d3d14f27 (Nicolin Chen 2013-11-12 15:09:52 -0800 336) * Can not be used in NMI handler on architectures without
684f0d3d14f27 (Nicolin Chen 2013-11-12 15:09:52 -0800 337) * NMI-safe cmpxchg implementation.
da83a722959a8 (Fredrik Noring 2019-05-29 13:28:39 +0300 338) *
da83a722959a8 (Fredrik Noring 2019-05-29 13:28:39 +0300 339) * Return: virtual address of the allocated memory, or %NULL on failure
684f0d3d14f27 (Nicolin Chen 2013-11-12 15:09:52 -0800 340) */
684f0d3d14f27 (Nicolin Chen 2013-11-12 15:09:52 -0800 341) void *gen_pool_dma_alloc(struct gen_pool *pool, size_t size, dma_addr_t *dma)
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 342) {
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 343) return gen_pool_dma_alloc_algo(pool, size, dma, pool->algo, pool->data);
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 344) }
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 345) EXPORT_SYMBOL(gen_pool_dma_alloc);
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 346)
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 347) /**
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 348) * gen_pool_dma_alloc_algo - allocate special memory from the pool for DMA
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 349) * usage with the given pool algorithm
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 350) * @pool: pool to allocate from
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 351) * @size: number of bytes to allocate from the pool
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 352) * @dma: DMA-view physical address return value. Use %NULL if unneeded.
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 353) * @algo: algorithm passed from caller
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 354) * @data: data passed to algorithm
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 355) *
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 356) * Allocate the requested number of bytes from the specified pool. Uses the
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 357) * given pool allocation function. Can not be used in NMI handler on
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 358) * architectures without NMI-safe cmpxchg implementation.
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 359) *
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 360) * Return: virtual address of the allocated memory, or %NULL on failure
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 361) */
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 362) void *gen_pool_dma_alloc_algo(struct gen_pool *pool, size_t size,
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 363) dma_addr_t *dma, genpool_algo_t algo, void *data)
684f0d3d14f27 (Nicolin Chen 2013-11-12 15:09:52 -0800 364) {
684f0d3d14f27 (Nicolin Chen 2013-11-12 15:09:52 -0800 365) unsigned long vaddr;
684f0d3d14f27 (Nicolin Chen 2013-11-12 15:09:52 -0800 366)
684f0d3d14f27 (Nicolin Chen 2013-11-12 15:09:52 -0800 367) if (!pool)
684f0d3d14f27 (Nicolin Chen 2013-11-12 15:09:52 -0800 368) return NULL;
684f0d3d14f27 (Nicolin Chen 2013-11-12 15:09:52 -0800 369)
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 370) vaddr = gen_pool_alloc_algo(pool, size, algo, data);
684f0d3d14f27 (Nicolin Chen 2013-11-12 15:09:52 -0800 371) if (!vaddr)
684f0d3d14f27 (Nicolin Chen 2013-11-12 15:09:52 -0800 372) return NULL;
684f0d3d14f27 (Nicolin Chen 2013-11-12 15:09:52 -0800 373)
0368dfd01ae3b (Lad, Prabhakar 2014-01-29 14:05:37 -0800 374) if (dma)
0368dfd01ae3b (Lad, Prabhakar 2014-01-29 14:05:37 -0800 375) *dma = gen_pool_virt_to_phys(pool, vaddr);
684f0d3d14f27 (Nicolin Chen 2013-11-12 15:09:52 -0800 376)
684f0d3d14f27 (Nicolin Chen 2013-11-12 15:09:52 -0800 377) return (void *)vaddr;
684f0d3d14f27 (Nicolin Chen 2013-11-12 15:09:52 -0800 378) }
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 379) EXPORT_SYMBOL(gen_pool_dma_alloc_algo);
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 380)
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 381) /**
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 382) * gen_pool_dma_alloc_align - allocate special memory from the pool for DMA
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 383) * usage with the given alignment
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 384) * @pool: pool to allocate from
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 385) * @size: number of bytes to allocate from the pool
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 386) * @dma: DMA-view physical address return value. Use %NULL if unneeded.
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 387) * @align: alignment in bytes for starting address
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 388) *
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 389) * Allocate the requested number bytes from the specified pool, with the given
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 390) * alignment restriction. Can not be used in NMI handler on architectures
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 391) * without NMI-safe cmpxchg implementation.
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 392) *
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 393) * Return: virtual address of the allocated memory, or %NULL on failure
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 394) */
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 395) void *gen_pool_dma_alloc_align(struct gen_pool *pool, size_t size,
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 396) dma_addr_t *dma, int align)
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 397) {
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 398) struct genpool_data_align data = { .align = align };
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 399)
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 400) return gen_pool_dma_alloc_algo(pool, size, dma,
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 401) gen_pool_first_fit_align, &data);
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 402) }
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 403) EXPORT_SYMBOL(gen_pool_dma_alloc_align);
684f0d3d14f27 (Nicolin Chen 2013-11-12 15:09:52 -0800 404)
da83a722959a8 (Fredrik Noring 2019-05-29 13:28:39 +0300 405) /**
da83a722959a8 (Fredrik Noring 2019-05-29 13:28:39 +0300 406) * gen_pool_dma_zalloc - allocate special zeroed memory from the pool for
da83a722959a8 (Fredrik Noring 2019-05-29 13:28:39 +0300 407) * DMA usage
da83a722959a8 (Fredrik Noring 2019-05-29 13:28:39 +0300 408) * @pool: pool to allocate from
da83a722959a8 (Fredrik Noring 2019-05-29 13:28:39 +0300 409) * @size: number of bytes to allocate from the pool
da83a722959a8 (Fredrik Noring 2019-05-29 13:28:39 +0300 410) * @dma: dma-view physical address return value. Use %NULL if unneeded.
da83a722959a8 (Fredrik Noring 2019-05-29 13:28:39 +0300 411) *
da83a722959a8 (Fredrik Noring 2019-05-29 13:28:39 +0300 412) * Allocate the requested number of zeroed bytes from the specified pool.
da83a722959a8 (Fredrik Noring 2019-05-29 13:28:39 +0300 413) * Uses the pool allocation function (with first-fit algorithm by default).
da83a722959a8 (Fredrik Noring 2019-05-29 13:28:39 +0300 414) * Can not be used in NMI handler on architectures without
da83a722959a8 (Fredrik Noring 2019-05-29 13:28:39 +0300 415) * NMI-safe cmpxchg implementation.
da83a722959a8 (Fredrik Noring 2019-05-29 13:28:39 +0300 416) *
da83a722959a8 (Fredrik Noring 2019-05-29 13:28:39 +0300 417) * Return: virtual address of the allocated zeroed memory, or %NULL on failure
da83a722959a8 (Fredrik Noring 2019-05-29 13:28:39 +0300 418) */
da83a722959a8 (Fredrik Noring 2019-05-29 13:28:39 +0300 419) void *gen_pool_dma_zalloc(struct gen_pool *pool, size_t size, dma_addr_t *dma)
da83a722959a8 (Fredrik Noring 2019-05-29 13:28:39 +0300 420) {
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 421) return gen_pool_dma_zalloc_algo(pool, size, dma, pool->algo, pool->data);
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 422) }
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 423) EXPORT_SYMBOL(gen_pool_dma_zalloc);
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 424)
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 425) /**
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 426) * gen_pool_dma_zalloc_algo - allocate special zeroed memory from the pool for
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 427) * DMA usage with the given pool algorithm
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 428) * @pool: pool to allocate from
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 429) * @size: number of bytes to allocate from the pool
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 430) * @dma: DMA-view physical address return value. Use %NULL if unneeded.
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 431) * @algo: algorithm passed from caller
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 432) * @data: data passed to algorithm
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 433) *
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 434) * Allocate the requested number of zeroed bytes from the specified pool. Uses
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 435) * the given pool allocation function. Can not be used in NMI handler on
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 436) * architectures without NMI-safe cmpxchg implementation.
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 437) *
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 438) * Return: virtual address of the allocated zeroed memory, or %NULL on failure
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 439) */
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 440) void *gen_pool_dma_zalloc_algo(struct gen_pool *pool, size_t size,
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 441) dma_addr_t *dma, genpool_algo_t algo, void *data)
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 442) {
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 443) void *vaddr = gen_pool_dma_alloc_algo(pool, size, dma, algo, data);
da83a722959a8 (Fredrik Noring 2019-05-29 13:28:39 +0300 444)
da83a722959a8 (Fredrik Noring 2019-05-29 13:28:39 +0300 445) if (vaddr)
da83a722959a8 (Fredrik Noring 2019-05-29 13:28:39 +0300 446) memset(vaddr, 0, size);
da83a722959a8 (Fredrik Noring 2019-05-29 13:28:39 +0300 447)
da83a722959a8 (Fredrik Noring 2019-05-29 13:28:39 +0300 448) return vaddr;
da83a722959a8 (Fredrik Noring 2019-05-29 13:28:39 +0300 449) }
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 450) EXPORT_SYMBOL(gen_pool_dma_zalloc_algo);
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 451)
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 452) /**
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 453) * gen_pool_dma_zalloc_align - allocate special zeroed memory from the pool for
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 454) * DMA usage with the given alignment
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 455) * @pool: pool to allocate from
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 456) * @size: number of bytes to allocate from the pool
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 457) * @dma: DMA-view physical address return value. Use %NULL if unneeded.
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 458) * @align: alignment in bytes for starting address
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 459) *
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 460) * Allocate the requested number of zeroed bytes from the specified pool,
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 461) * with the given alignment restriction. Can not be used in NMI handler on
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 462) * architectures without NMI-safe cmpxchg implementation.
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 463) *
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 464) * Return: virtual address of the allocated zeroed memory, or %NULL on failure
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 465) */
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 466) void *gen_pool_dma_zalloc_align(struct gen_pool *pool, size_t size,
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 467) dma_addr_t *dma, int align)
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 468) {
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 469) struct genpool_data_align data = { .align = align };
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 470)
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 471) return gen_pool_dma_zalloc_algo(pool, size, dma,
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 472) gen_pool_first_fit_align, &data);
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 473) }
cf394fc5f7155 (Fredrik Noring 2019-06-25 17:05:58 +0200 474) EXPORT_SYMBOL(gen_pool_dma_zalloc_align);
684f0d3d14f27 (Nicolin Chen 2013-11-12 15:09:52 -0800 475)
a58cbd7c249f3 (Dean Nelson 2006-10-02 02:17:01 -0700 476) /**
ea83df73aaa3b (Jonathan Corbet 2019-10-03 12:40:30 -0600 477) * gen_pool_free_owner - free allocated special memory back to the pool
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 478) * @pool: pool to free to
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 479) * @addr: starting address of memory to free back to pool
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 480) * @size: size in bytes of memory to free
795ee30648c70 (Dan Williams 2019-06-13 15:56:27 -0700 481) * @owner: private data stashed at gen_pool_add() time
a58cbd7c249f3 (Dean Nelson 2006-10-02 02:17:01 -0700 482) *
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 483) * Free previously allocated special memory back to the specified
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 484) * pool. Can not be used in NMI handler on architectures without
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 485) * NMI-safe cmpxchg implementation.
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 486) */
795ee30648c70 (Dan Williams 2019-06-13 15:56:27 -0700 487) void gen_pool_free_owner(struct gen_pool *pool, unsigned long addr, size_t size,
795ee30648c70 (Dan Williams 2019-06-13 15:56:27 -0700 488) void **owner)
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 489) {
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 490) struct gen_pool_chunk *chunk;
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 491) int order = pool->min_alloc_order;
36845663843fc (Huang Shijie 2020-12-29 15:14:58 -0800 492) unsigned long start_bit, nbits, remain;
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 493)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 494) #ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 495) BUG_ON(in_nmi());
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 496) #endif
929f97276bcf7 (Dean Nelson 2006-06-23 02:03:21 -0700 497)
795ee30648c70 (Dan Williams 2019-06-13 15:56:27 -0700 498) if (owner)
795ee30648c70 (Dan Williams 2019-06-13 15:56:27 -0700 499) *owner = NULL;
795ee30648c70 (Dan Williams 2019-06-13 15:56:27 -0700 500)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 501) nbits = (size + (1UL << order) - 1) >> order;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 502) rcu_read_lock();
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 503) list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk) {
674470d97958a (Joonyoung Shim 2013-09-11 14:21:43 -0700 504) if (addr >= chunk->start_addr && addr <= chunk->end_addr) {
674470d97958a (Joonyoung Shim 2013-09-11 14:21:43 -0700 505) BUG_ON(addr + size - 1 > chunk->end_addr);
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 506) start_bit = (addr - chunk->start_addr) >> order;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 507) remain = bitmap_clear_ll(chunk->bits, start_bit, nbits);
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 508) BUG_ON(remain);
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 509) size = nbits << order;
36a3d1dd4e16b (Stephen Bates 2017-11-17 15:28:16 -0800 510) atomic_long_add(size, &chunk->avail);
795ee30648c70 (Dan Williams 2019-06-13 15:56:27 -0700 511) if (owner)
795ee30648c70 (Dan Williams 2019-06-13 15:56:27 -0700 512) *owner = chunk->owner;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 513) rcu_read_unlock();
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 514) return;
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 515) }
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 516) }
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 517) rcu_read_unlock();
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 518) BUG();
f14f75b81187c (Jes Sorensen 2005-06-21 17:15:02 -0700 519) }
795ee30648c70 (Dan Williams 2019-06-13 15:56:27 -0700 520) EXPORT_SYMBOL(gen_pool_free_owner);
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 521)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 522) /**
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 523) * gen_pool_for_each_chunk - call func for every chunk of generic memory pool
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 524) * @pool: the generic memory pool
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 525) * @func: func to call
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 526) * @data: additional data used by @func
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 527) *
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 528) * Call @func for every chunk of generic memory pool. The @func is
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 529) * called with rcu_read_lock held.
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 530) */
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 531) void gen_pool_for_each_chunk(struct gen_pool *pool,
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 532) void (*func)(struct gen_pool *pool, struct gen_pool_chunk *chunk, void *data),
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 533) void *data)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 534) {
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 535) struct gen_pool_chunk *chunk;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 536)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 537) rcu_read_lock();
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 538) list_for_each_entry_rcu(chunk, &(pool)->chunks, next_chunk)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 539) func(pool, chunk, data);
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 540) rcu_read_unlock();
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 541) }
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 542) EXPORT_SYMBOL(gen_pool_for_each_chunk);
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 543)
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 544) /**
964975ac6677c (Huang Shijie 2019-12-04 16:52:03 -0800 545) * gen_pool_has_addr - checks if an address falls within the range of a pool
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 546) * @pool: the generic memory pool
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 547) * @start: start address
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 548) * @size: size of the region
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 549) *
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 550) * Check if the range of addresses falls within the specified pool. Returns
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 551) * true if the entire range is contained in the pool and false otherwise.
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 552) */
964975ac6677c (Huang Shijie 2019-12-04 16:52:03 -0800 553) bool gen_pool_has_addr(struct gen_pool *pool, unsigned long start,
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 554) size_t size)
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 555) {
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 556) bool found = false;
ad3d5d2f7deca (Toshi Kikuchi 2015-02-12 15:02:18 -0800 557) unsigned long end = start + size - 1;
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 558) struct gen_pool_chunk *chunk;
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 559)
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 560) rcu_read_lock();
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 561) list_for_each_entry_rcu(chunk, &(pool)->chunks, next_chunk) {
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 562) if (start >= chunk->start_addr && start <= chunk->end_addr) {
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 563) if (end <= chunk->end_addr) {
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 564) found = true;
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 565) break;
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 566) }
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 567) }
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 568) }
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 569) rcu_read_unlock();
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 570) return found;
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 571) }
964975ac6677c (Huang Shijie 2019-12-04 16:52:03 -0800 572) EXPORT_SYMBOL(gen_pool_has_addr);
9efb3a421d55d (Laura Abbott 2014-10-09 15:26:38 -0700 573)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 574) /**
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 575) * gen_pool_avail - get available free space of the pool
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 576) * @pool: pool to get available free space
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 577) *
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 578) * Return available free space of the specified pool.
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 579) */
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 580) size_t gen_pool_avail(struct gen_pool *pool)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 581) {
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 582) struct gen_pool_chunk *chunk;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 583) size_t avail = 0;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 584)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 585) rcu_read_lock();
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 586) list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk)
36a3d1dd4e16b (Stephen Bates 2017-11-17 15:28:16 -0800 587) avail += atomic_long_read(&chunk->avail);
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 588) rcu_read_unlock();
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 589) return avail;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 590) }
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 591) EXPORT_SYMBOL_GPL(gen_pool_avail);
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 592)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 593) /**
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 594) * gen_pool_size - get size in bytes of memory managed by the pool
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 595) * @pool: pool to get size
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 596) *
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 597) * Return size in bytes of memory managed by the pool.
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 598) */
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 599) size_t gen_pool_size(struct gen_pool *pool)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 600) {
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 601) struct gen_pool_chunk *chunk;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 602) size_t size = 0;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 603)
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 604) rcu_read_lock();
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 605) list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk)
674470d97958a (Joonyoung Shim 2013-09-11 14:21:43 -0700 606) size += chunk_size(chunk);
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 607) rcu_read_unlock();
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 608) return size;
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 609) }
7f184275aa306 (Huang Ying 2011-07-13 13:14:24 +0800 610) EXPORT_SYMBOL_GPL(gen_pool_size);
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 611)
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 612) /**
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 613) * gen_pool_set_algo - set the allocation algorithm
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 614) * @pool: pool to change allocation algorithm
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 615) * @algo: custom algorithm function
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 616) * @data: additional data used by @algo
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 617) *
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 618) * Call @algo for each memory allocation in the pool.
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 619) * If @algo is NULL use gen_pool_first_fit as default
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 620) * memory allocation function.
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 621) */
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 622) void gen_pool_set_algo(struct gen_pool *pool, genpool_algo_t algo, void *data)
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 623) {
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 624) rcu_read_lock();
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 625)
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 626) pool->algo = algo;
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 627) if (!pool->algo)
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 628) pool->algo = gen_pool_first_fit;
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 629)
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 630) pool->data = data;
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 631)
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 632) rcu_read_unlock();
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 633) }
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 634) EXPORT_SYMBOL(gen_pool_set_algo);
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 635)
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 636) /**
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 637) * gen_pool_first_fit - find the first available region
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 638) * of memory matching the size requirement (no alignment constraint)
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 639) * @map: The address to base the search on
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 640) * @size: The bitmap size in bits
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 641) * @start: The bitnumber to start searching at
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 642) * @nr: The number of zeroed bits we're looking for
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 643) * @data: additional data - unused
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 644) * @pool: pool to find the fit region memory from
9d6ecac093a24 (Alex Shi 2021-05-06 18:03:46 -0700 645) * @start_addr: not used in this function
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 646) */
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 647) unsigned long gen_pool_first_fit(unsigned long *map, unsigned long size,
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 648) unsigned long start, unsigned int nr, void *data,
52fbf1134d479 (Alexey Skidanov 2019-01-03 15:26:44 -0800 649) struct gen_pool *pool, unsigned long start_addr)
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 650) {
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 651) return bitmap_find_next_zero_area(map, size, start, nr, 0);
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 652) }
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 653) EXPORT_SYMBOL(gen_pool_first_fit);
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 654)
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 655) /**
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 656) * gen_pool_first_fit_align - find the first available region
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 657) * of memory matching the size requirement (alignment constraint)
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 658) * @map: The address to base the search on
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 659) * @size: The bitmap size in bits
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 660) * @start: The bitnumber to start searching at
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 661) * @nr: The number of zeroed bits we're looking for
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 662) * @data: data for alignment
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 663) * @pool: pool to get order from
9d6ecac093a24 (Alex Shi 2021-05-06 18:03:46 -0700 664) * @start_addr: start addr of alloction chunk
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 665) */
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 666) unsigned long gen_pool_first_fit_align(unsigned long *map, unsigned long size,
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 667) unsigned long start, unsigned int nr, void *data,
52fbf1134d479 (Alexey Skidanov 2019-01-03 15:26:44 -0800 668) struct gen_pool *pool, unsigned long start_addr)
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 669) {
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 670) struct genpool_data_align *alignment;
52fbf1134d479 (Alexey Skidanov 2019-01-03 15:26:44 -0800 671) unsigned long align_mask, align_off;
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 672) int order;
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 673)
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 674) alignment = data;
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 675) order = pool->min_alloc_order;
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 676) align_mask = ((alignment->align + (1UL << order) - 1) >> order) - 1;
52fbf1134d479 (Alexey Skidanov 2019-01-03 15:26:44 -0800 677) align_off = (start_addr & (alignment->align - 1)) >> order;
52fbf1134d479 (Alexey Skidanov 2019-01-03 15:26:44 -0800 678)
52fbf1134d479 (Alexey Skidanov 2019-01-03 15:26:44 -0800 679) return bitmap_find_next_zero_area_off(map, size, start, nr,
52fbf1134d479 (Alexey Skidanov 2019-01-03 15:26:44 -0800 680) align_mask, align_off);
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 681) }
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 682) EXPORT_SYMBOL(gen_pool_first_fit_align);
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 683)
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 684) /**
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 685) * gen_pool_fixed_alloc - reserve a specific region
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 686) * @map: The address to base the search on
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 687) * @size: The bitmap size in bits
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 688) * @start: The bitnumber to start searching at
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 689) * @nr: The number of zeroed bits we're looking for
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 690) * @data: data for alignment
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 691) * @pool: pool to get order from
9d6ecac093a24 (Alex Shi 2021-05-06 18:03:46 -0700 692) * @start_addr: not used in this function
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 693) */
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 694) unsigned long gen_pool_fixed_alloc(unsigned long *map, unsigned long size,
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 695) unsigned long start, unsigned int nr, void *data,
52fbf1134d479 (Alexey Skidanov 2019-01-03 15:26:44 -0800 696) struct gen_pool *pool, unsigned long start_addr)
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 697) {
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 698) struct genpool_data_fixed *fixed_data;
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 699) int order;
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 700) unsigned long offset_bit;
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 701) unsigned long start_bit;
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 702)
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 703) fixed_data = data;
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 704) order = pool->min_alloc_order;
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 705) offset_bit = fixed_data->offset >> order;
0e6e01ff694ee (Zhao Qiang 2015-11-30 10:48:54 +0800 706) if (WARN_ON(fixed_data->offset & ((1UL << order) - 1)))
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 707) return size;
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 708)
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 709) start_bit = bitmap_find_next_zero_area(map, size,
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 710) start + offset_bit, nr, 0);
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 711) if (start_bit != offset_bit)
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 712) start_bit = size;
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 713) return start_bit;
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 714) }
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 715) EXPORT_SYMBOL(gen_pool_fixed_alloc);
b26981c8f743d (Zhao Qiang 2015-11-30 10:48:53 +0800 716)
505e3be6c0824 (Laura Abbott 2014-10-09 15:26:35 -0700 717) /**
505e3be6c0824 (Laura Abbott 2014-10-09 15:26:35 -0700 718) * gen_pool_first_fit_order_align - find the first available region
505e3be6c0824 (Laura Abbott 2014-10-09 15:26:35 -0700 719) * of memory matching the size requirement. The region will be aligned
505e3be6c0824 (Laura Abbott 2014-10-09 15:26:35 -0700 720) * to the order of the size specified.
505e3be6c0824 (Laura Abbott 2014-10-09 15:26:35 -0700 721) * @map: The address to base the search on
505e3be6c0824 (Laura Abbott 2014-10-09 15:26:35 -0700 722) * @size: The bitmap size in bits
505e3be6c0824 (Laura Abbott 2014-10-09 15:26:35 -0700 723) * @start: The bitnumber to start searching at
505e3be6c0824 (Laura Abbott 2014-10-09 15:26:35 -0700 724) * @nr: The number of zeroed bits we're looking for
505e3be6c0824 (Laura Abbott 2014-10-09 15:26:35 -0700 725) * @data: additional data - unused
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 726) * @pool: pool to find the fit region memory from
9d6ecac093a24 (Alex Shi 2021-05-06 18:03:46 -0700 727) * @start_addr: not used in this function
505e3be6c0824 (Laura Abbott 2014-10-09 15:26:35 -0700 728) */
505e3be6c0824 (Laura Abbott 2014-10-09 15:26:35 -0700 729) unsigned long gen_pool_first_fit_order_align(unsigned long *map,
505e3be6c0824 (Laura Abbott 2014-10-09 15:26:35 -0700 730) unsigned long size, unsigned long start,
52fbf1134d479 (Alexey Skidanov 2019-01-03 15:26:44 -0800 731) unsigned int nr, void *data, struct gen_pool *pool,
52fbf1134d479 (Alexey Skidanov 2019-01-03 15:26:44 -0800 732) unsigned long start_addr)
505e3be6c0824 (Laura Abbott 2014-10-09 15:26:35 -0700 733) {
505e3be6c0824 (Laura Abbott 2014-10-09 15:26:35 -0700 734) unsigned long align_mask = roundup_pow_of_two(nr) - 1;
505e3be6c0824 (Laura Abbott 2014-10-09 15:26:35 -0700 735)
505e3be6c0824 (Laura Abbott 2014-10-09 15:26:35 -0700 736) return bitmap_find_next_zero_area(map, size, start, nr, align_mask);
505e3be6c0824 (Laura Abbott 2014-10-09 15:26:35 -0700 737) }
505e3be6c0824 (Laura Abbott 2014-10-09 15:26:35 -0700 738) EXPORT_SYMBOL(gen_pool_first_fit_order_align);
505e3be6c0824 (Laura Abbott 2014-10-09 15:26:35 -0700 739)
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 740) /**
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 741) * gen_pool_best_fit - find the best fitting region of memory
ade29d4fdbe67 (Bhaskar Chowdhury 2021-05-06 18:03:34 -0700 742) * matching the size requirement (no alignment constraint)
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 743) * @map: The address to base the search on
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 744) * @size: The bitmap size in bits
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 745) * @start: The bitnumber to start searching at
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 746) * @nr: The number of zeroed bits we're looking for
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 747) * @data: additional data - unused
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 748) * @pool: pool to find the fit region memory from
9d6ecac093a24 (Alex Shi 2021-05-06 18:03:46 -0700 749) * @start_addr: not used in this function
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 750) *
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 751) * Iterate over the bitmap to find the smallest free region
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 752) * which we can allocate the memory.
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 753) */
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 754) unsigned long gen_pool_best_fit(unsigned long *map, unsigned long size,
de2dd0eb30af5 (Zhao Qiang 2015-11-30 10:48:52 +0800 755) unsigned long start, unsigned int nr, void *data,
52fbf1134d479 (Alexey Skidanov 2019-01-03 15:26:44 -0800 756) struct gen_pool *pool, unsigned long start_addr)
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 757) {
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 758) unsigned long start_bit = size;
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 759) unsigned long len = size + 1;
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 760) unsigned long index;
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 761)
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 762) index = bitmap_find_next_zero_area(map, size, start, nr, 0);
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 763)
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 764) while (index < size) {
36845663843fc (Huang Shijie 2020-12-29 15:14:58 -0800 765) unsigned long next_bit = find_next_bit(map, size, index + nr);
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 766) if ((next_bit - index) < len) {
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 767) len = next_bit - index;
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 768) start_bit = index;
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 769) if (len == nr)
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 770) return start_bit;
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 771) }
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 772) index = bitmap_find_next_zero_area(map, size,
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 773) next_bit + 1, nr, 0);
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 774) }
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 775)
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 776) return start_bit;
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 777) }
ca279cf1065fb (Benjamin Gaignard 2012-10-04 17:13:20 -0700 778) EXPORT_SYMBOL(gen_pool_best_fit);
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 779)
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 780) static void devm_gen_pool_release(struct device *dev, void *res)
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 781) {
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 782) gen_pool_destroy(*(struct gen_pool **)res);
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 783) }
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 784)
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 785) static int devm_gen_pool_match(struct device *dev, void *res, void *data)
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 786) {
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 787) struct gen_pool **p = res;
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 788)
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 789) /* NULL data matches only a pool without an assigned name */
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 790) if (!data && !(*p)->name)
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 791) return 1;
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 792)
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 793) if (!data || !(*p)->name)
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 794) return 0;
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 795)
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 796) return !strcmp((*p)->name, data);
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 797) }
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 798)
73858173593c3 (Vladimir Zapolskiy 2015-09-04 15:47:43 -0700 799) /**
73858173593c3 (Vladimir Zapolskiy 2015-09-04 15:47:43 -0700 800) * gen_pool_get - Obtain the gen_pool (if any) for a device
73858173593c3 (Vladimir Zapolskiy 2015-09-04 15:47:43 -0700 801) * @dev: device to retrieve the gen_pool from
73858173593c3 (Vladimir Zapolskiy 2015-09-04 15:47:43 -0700 802) * @name: name of a gen_pool or NULL, identifies a particular gen_pool on device
73858173593c3 (Vladimir Zapolskiy 2015-09-04 15:47:43 -0700 803) *
73858173593c3 (Vladimir Zapolskiy 2015-09-04 15:47:43 -0700 804) * Returns the gen_pool for the device if one is present, or NULL.
73858173593c3 (Vladimir Zapolskiy 2015-09-04 15:47:43 -0700 805) */
73858173593c3 (Vladimir Zapolskiy 2015-09-04 15:47:43 -0700 806) struct gen_pool *gen_pool_get(struct device *dev, const char *name)
73858173593c3 (Vladimir Zapolskiy 2015-09-04 15:47:43 -0700 807) {
73858173593c3 (Vladimir Zapolskiy 2015-09-04 15:47:43 -0700 808) struct gen_pool **p;
73858173593c3 (Vladimir Zapolskiy 2015-09-04 15:47:43 -0700 809)
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 810) p = devres_find(dev, devm_gen_pool_release, devm_gen_pool_match,
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 811) (void *)name);
73858173593c3 (Vladimir Zapolskiy 2015-09-04 15:47:43 -0700 812) if (!p)
73858173593c3 (Vladimir Zapolskiy 2015-09-04 15:47:43 -0700 813) return NULL;
73858173593c3 (Vladimir Zapolskiy 2015-09-04 15:47:43 -0700 814) return *p;
73858173593c3 (Vladimir Zapolskiy 2015-09-04 15:47:43 -0700 815) }
73858173593c3 (Vladimir Zapolskiy 2015-09-04 15:47:43 -0700 816) EXPORT_SYMBOL_GPL(gen_pool_get);
73858173593c3 (Vladimir Zapolskiy 2015-09-04 15:47:43 -0700 817)
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 818) /**
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 819) * devm_gen_pool_create - managed gen_pool_create
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 820) * @dev: device that provides the gen_pool
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 821) * @min_alloc_order: log base 2 of number of bytes each bitmap bit represents
73858173593c3 (Vladimir Zapolskiy 2015-09-04 15:47:43 -0700 822) * @nid: node selector for allocated gen_pool, %NUMA_NO_NODE for all nodes
73858173593c3 (Vladimir Zapolskiy 2015-09-04 15:47:43 -0700 823) * @name: name of a gen_pool or NULL, identifies a particular gen_pool on device
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 824) *
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 825) * Create a new special memory pool that can be used to manage special purpose
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 826) * memory not managed by the regular kmalloc/kfree interface. The pool will be
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 827) * automatically destroyed by the device management code.
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 828) */
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 829) struct gen_pool *devm_gen_pool_create(struct device *dev, int min_alloc_order,
73858173593c3 (Vladimir Zapolskiy 2015-09-04 15:47:43 -0700 830) int nid, const char *name)
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 831) {
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 832) struct gen_pool **ptr, *pool;
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 833) const char *pool_name = NULL;
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 834)
73858173593c3 (Vladimir Zapolskiy 2015-09-04 15:47:43 -0700 835) /* Check that genpool to be created is uniquely addressed on device */
73858173593c3 (Vladimir Zapolskiy 2015-09-04 15:47:43 -0700 836) if (gen_pool_get(dev, name))
73858173593c3 (Vladimir Zapolskiy 2015-09-04 15:47:43 -0700 837) return ERR_PTR(-EINVAL);
73858173593c3 (Vladimir Zapolskiy 2015-09-04 15:47:43 -0700 838)
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 839) if (name) {
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 840) pool_name = kstrdup_const(name, GFP_KERNEL);
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 841) if (!pool_name)
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 842) return ERR_PTR(-ENOMEM);
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 843) }
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 844)
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 845) ptr = devres_alloc(devm_gen_pool_release, sizeof(*ptr), GFP_KERNEL);
310ee9e8f370f (Jan Kara 2015-02-13 14:36:47 -0800 846) if (!ptr)
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 847) goto free_pool_name;
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 848)
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 849) pool = gen_pool_create(min_alloc_order, nid);
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 850) if (!pool)
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 851) goto free_devres;
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 852)
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 853) *ptr = pool;
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 854) pool->name = pool_name;
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 855) devres_add(dev, ptr);
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 856)
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 857) return pool;
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 858)
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 859) free_devres:
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 860) devres_free(ptr);
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 861) free_pool_name:
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 862) kfree_const(pool_name);
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 863)
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 864) return ERR_PTR(-ENOMEM);
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 865) }
b724aa213df7a (Michal Simek 2014-12-02 15:59:45 -0800 866) EXPORT_SYMBOL(devm_gen_pool_create);
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 867)
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 868) #ifdef CONFIG_OF
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 869) /**
abdd4a7025282 (Vladimir Zapolskiy 2015-06-30 15:00:07 -0700 870) * of_gen_pool_get - find a pool by phandle property
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 871) * @np: device node
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 872) * @propname: property name containing phandle(s)
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 873) * @index: index into the phandle array
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 874) *
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 875) * Returns the pool that contains the chunk starting at the physical
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 876) * address of the device tree node pointed at by the phandle property,
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 877) * or NULL if not found.
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 878) */
abdd4a7025282 (Vladimir Zapolskiy 2015-06-30 15:00:07 -0700 879) struct gen_pool *of_gen_pool_get(struct device_node *np,
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 880) const char *propname, int index)
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 881) {
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 882) struct platform_device *pdev;
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 883) struct device_node *np_pool, *parent;
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 884) const char *name = NULL;
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 885) struct gen_pool *pool = NULL;
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 886)
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 887) np_pool = of_parse_phandle(np, propname, index);
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 888) if (!np_pool)
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 889) return NULL;
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 890)
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 891) pdev = of_find_device_by_node(np_pool);
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 892) if (!pdev) {
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 893) /* Check if named gen_pool is created by parent node device */
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 894) parent = of_get_parent(np_pool);
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 895) pdev = of_find_device_by_node(parent);
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 896) of_node_put(parent);
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 897)
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 898) of_property_read_string(np_pool, "label", &name);
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 899) if (!name)
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 900) name = np_pool->name;
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 901) }
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 902) if (pdev)
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 903) pool = gen_pool_get(&pdev->dev, name);
6f3aabd183984 (Vladimir Zapolskiy 2014-09-25 16:05:25 -0700 904) of_node_put(np_pool);
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 905)
c98c36355dd6d (Vladimir Zapolskiy 2015-09-04 15:47:47 -0700 906) return pool;
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 907) }
abdd4a7025282 (Vladimir Zapolskiy 2015-06-30 15:00:07 -0700 908) EXPORT_SYMBOL_GPL(of_gen_pool_get);
9375db07adeae (Philipp Zabel 2013-04-29 16:17:10 -0700 909) #endif /* CONFIG_OF */