diff options
-rw-r--r-- | include/linux/genalloc.h | 22 | ||||
-rw-r--r-- | lib/genalloc.c | 45 |
2 files changed, 58 insertions, 9 deletions
diff --git a/include/linux/genalloc.h b/include/linux/genalloc.h index b1c70f10c42b..5bbebda78b02 100644 --- a/include/linux/genalloc.h +++ b/include/linux/genalloc.h | |||
@@ -26,13 +26,33 @@ struct gen_pool { | |||
26 | struct gen_pool_chunk { | 26 | struct gen_pool_chunk { |
27 | spinlock_t lock; | 27 | spinlock_t lock; |
28 | struct list_head next_chunk; /* next chunk in pool */ | 28 | struct list_head next_chunk; /* next chunk in pool */ |
29 | phys_addr_t phys_addr; /* physical starting address of memory chunk */ | ||
29 | unsigned long start_addr; /* starting address of memory chunk */ | 30 | unsigned long start_addr; /* starting address of memory chunk */ |
30 | unsigned long end_addr; /* ending address of memory chunk */ | 31 | unsigned long end_addr; /* ending address of memory chunk */ |
31 | unsigned long bits[0]; /* bitmap for allocating memory chunk */ | 32 | unsigned long bits[0]; /* bitmap for allocating memory chunk */ |
32 | }; | 33 | }; |
33 | 34 | ||
34 | extern struct gen_pool *gen_pool_create(int, int); | 35 | extern struct gen_pool *gen_pool_create(int, int); |
35 | extern int gen_pool_add(struct gen_pool *, unsigned long, size_t, int); | 36 | extern phys_addr_t gen_pool_virt_to_phys(struct gen_pool *pool, unsigned long); |
37 | extern int gen_pool_add_virt(struct gen_pool *, unsigned long, phys_addr_t, | ||
38 | size_t, int); | ||
39 | /** | ||
40 | * gen_pool_add - add a new chunk of special memory to the pool | ||
41 | * @pool: pool to add new memory chunk to | ||
42 | * @addr: starting address of memory chunk to add to pool | ||
43 | * @size: size in bytes of the memory chunk to add to pool | ||
44 | * @nid: node id of the node the chunk structure and bitmap should be | ||
45 | * allocated on, or -1 | ||
46 | * | ||
47 | * Add a new chunk of special memory to the specified pool. | ||
48 | * | ||
49 | * Returns 0 on success or a -ve errno on failure. | ||
50 | */ | ||
51 | static inline int gen_pool_add(struct gen_pool *pool, unsigned long addr, | ||
52 | size_t size, int nid) | ||
53 | { | ||
54 | return gen_pool_add_virt(pool, addr, -1, size, nid); | ||
55 | } | ||
36 | extern void gen_pool_destroy(struct gen_pool *); | 56 | extern void gen_pool_destroy(struct gen_pool *); |
37 | extern unsigned long gen_pool_alloc(struct gen_pool *, size_t); | 57 | extern unsigned long gen_pool_alloc(struct gen_pool *, size_t); |
38 | extern void gen_pool_free(struct gen_pool *, unsigned long, size_t); | 58 | extern void gen_pool_free(struct gen_pool *, unsigned long, size_t); |
diff --git a/lib/genalloc.c b/lib/genalloc.c index 1923f1490e72..577ddf805975 100644 --- a/lib/genalloc.c +++ b/lib/genalloc.c | |||
@@ -39,17 +39,20 @@ struct gen_pool *gen_pool_create(int min_alloc_order, int nid) | |||
39 | EXPORT_SYMBOL(gen_pool_create); | 39 | EXPORT_SYMBOL(gen_pool_create); |
40 | 40 | ||
41 | /** | 41 | /** |
42 | * gen_pool_add - add a new chunk of special memory to the pool | 42 | * gen_pool_add_virt - add a new chunk of special memory to the pool |
43 | * @pool: pool to add new memory chunk to | 43 | * @pool: pool to add new memory chunk to |
44 | * @addr: starting address of memory chunk to add to pool | 44 | * @virt: virtual starting address of memory chunk to add to pool |
45 | * @phys: physical starting address of memory chunk to add to pool | ||
45 | * @size: size in bytes of the memory chunk to add to pool | 46 | * @size: size in bytes of the memory chunk to add to pool |
46 | * @nid: node id of the node the chunk structure and bitmap should be | 47 | * @nid: node id of the node the chunk structure and bitmap should be |
47 | * allocated on, or -1 | 48 | * allocated on, or -1 |
48 | * | 49 | * |
49 | * Add a new chunk of special memory to the specified pool. | 50 | * Add a new chunk of special memory to the specified pool. |
51 | * | ||
52 | * Returns 0 on success or a -ve errno on failure. | ||
50 | */ | 53 | */ |
51 | int gen_pool_add(struct gen_pool *pool, unsigned long addr, size_t size, | 54 | int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phys, |
52 | int nid) | 55 | size_t size, int nid) |
53 | { | 56 | { |
54 | struct gen_pool_chunk *chunk; | 57 | struct gen_pool_chunk *chunk; |
55 | int nbits = size >> pool->min_alloc_order; | 58 | int nbits = size >> pool->min_alloc_order; |
@@ -58,11 +61,12 @@ int gen_pool_add(struct gen_pool *pool, unsigned long addr, size_t size, | |||
58 | 61 | ||
59 | chunk = kmalloc_node(nbytes, GFP_KERNEL | __GFP_ZERO, nid); | 62 | chunk = kmalloc_node(nbytes, GFP_KERNEL | __GFP_ZERO, nid); |
60 | if (unlikely(chunk == NULL)) | 63 | if (unlikely(chunk == NULL)) |
61 | return -1; | 64 | return -ENOMEM; |
62 | 65 | ||
63 | spin_lock_init(&chunk->lock); | 66 | spin_lock_init(&chunk->lock); |
64 | chunk->start_addr = addr; | 67 | chunk->phys_addr = phys; |
65 | chunk->end_addr = addr + size; | 68 | chunk->start_addr = virt; |
69 | chunk->end_addr = virt + size; | ||
66 | 70 | ||
67 | write_lock(&pool->lock); | 71 | write_lock(&pool->lock); |
68 | list_add(&chunk->next_chunk, &pool->chunks); | 72 | list_add(&chunk->next_chunk, &pool->chunks); |
@@ -70,7 +74,32 @@ int gen_pool_add(struct gen_pool *pool, unsigned long addr, size_t size, | |||
70 | 74 | ||
71 | return 0; | 75 | return 0; |
72 | } | 76 | } |
73 | EXPORT_SYMBOL(gen_pool_add); | 77 | EXPORT_SYMBOL(gen_pool_add_virt); |
78 | |||
79 | /** | ||
80 | * gen_pool_virt_to_phys - return the physical address of memory | ||
81 | * @pool: pool to allocate from | ||
82 | * @addr: starting address of memory | ||
83 | * | ||
84 | * Returns the physical address on success, or -1 on error. | ||
85 | */ | ||
86 | phys_addr_t gen_pool_virt_to_phys(struct gen_pool *pool, unsigned long addr) | ||
87 | { | ||
88 | struct list_head *_chunk; | ||
89 | struct gen_pool_chunk *chunk; | ||
90 | |||
91 | read_lock(&pool->lock); | ||
92 | list_for_each(_chunk, &pool->chunks) { | ||
93 | chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk); | ||
94 | |||
95 | if (addr >= chunk->start_addr && addr < chunk->end_addr) | ||
96 | return chunk->phys_addr + addr - chunk->start_addr; | ||
97 | } | ||
98 | read_unlock(&pool->lock); | ||
99 | |||
100 | return -1; | ||
101 | } | ||
102 | EXPORT_SYMBOL(gen_pool_virt_to_phys); | ||
74 | 103 | ||
75 | /** | 104 | /** |
76 | * gen_pool_destroy - destroy a special memory pool | 105 | * gen_pool_destroy - destroy a special memory pool |