aboutsummaryrefslogtreecommitdiffstats
path: root/lib/genalloc.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2019-06-13 18:56:27 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-06-13 23:34:56 -0400
commit795ee30648c708502da9df637f83c33361d68dcc (patch)
tree83a9204335deb0f02dfcb2e6a033a9cc6d1d21c5 /lib/genalloc.c
parente615a191216e3fb4e9c0d239007f2b0cd48f28bf (diff)
lib/genalloc: introduce chunk owners
The p2pdma facility enables a provider to publish a pool of dma addresses for a consumer to allocate. A genpool is used internally by p2pdma to collect dma resources, 'chunks', to be handed out to consumers. Whenever a consumer allocates a resource it needs to pin the 'struct dev_pagemap' instance that backs the chunk selected by pci_alloc_p2pmem(). Currently that reference is taken globally on the entire provider device. That sets up a lifetime mismatch whereby the p2pdma core needs to maintain hacks to make sure the percpu_ref is not released twice. This lifetime mismatch also stands in the way of a fix to devm_memremap_pages() whereby devm_memremap_pages_release() must wait for the percpu_ref ->release() callback to complete before it can proceed to teardown pages. So, towards fixing this situation, introduce the ability to store a 'chunk owner' at gen_pool_add() time, and a facility to retrieve the owner at gen_pool_{alloc,free}() time. For p2pdma this will be used to store and recall individual dev_pagemap reference counter instances per-chunk. Link: http://lkml.kernel.org/r/155727338118.292046.13407378933221579644.stgit@dwillia2-desk3.amr.corp.intel.com Signed-off-by: Dan Williams <dan.j.williams@intel.com> Reviewed-by: Ira Weiny <ira.weiny@intel.com> Reviewed-by: Logan Gunthorpe <logang@deltatee.com> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: "Jérôme Glisse" <jglisse@redhat.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: "Rafael J. Wysocki" <rafael@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'lib/genalloc.c')
-rw-r--r--lib/genalloc.c51
1 files changed, 25 insertions, 26 deletions
diff --git a/lib/genalloc.c b/lib/genalloc.c
index 7e85d1e37a6e..770c769d7cb7 100644
--- a/lib/genalloc.c
+++ b/lib/genalloc.c
@@ -168,20 +168,21 @@ struct gen_pool *gen_pool_create(int min_alloc_order, int nid)
168EXPORT_SYMBOL(gen_pool_create); 168EXPORT_SYMBOL(gen_pool_create);
169 169
170/** 170/**
171 * gen_pool_add_virt - add a new chunk of special memory to the pool 171 * gen_pool_add_owner- add a new chunk of special memory to the pool
172 * @pool: pool to add new memory chunk to 172 * @pool: pool to add new memory chunk to
173 * @virt: virtual starting address of memory chunk to add to pool 173 * @virt: virtual starting address of memory chunk to add to pool
174 * @phys: physical starting address of memory chunk to add to pool 174 * @phys: physical starting address of memory chunk to add to pool
175 * @size: size in bytes of the memory chunk to add to pool 175 * @size: size in bytes of the memory chunk to add to pool
176 * @nid: node id of the node the chunk structure and bitmap should be 176 * @nid: node id of the node the chunk structure and bitmap should be
177 * allocated on, or -1 177 * allocated on, or -1
178 * @owner: private data the publisher would like to recall at alloc time
178 * 179 *
179 * Add a new chunk of special memory to the specified pool. 180 * Add a new chunk of special memory to the specified pool.
180 * 181 *
181 * Returns 0 on success or a -ve errno on failure. 182 * Returns 0 on success or a -ve errno on failure.
182 */ 183 */
183int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phys, 184int gen_pool_add_owner(struct gen_pool *pool, unsigned long virt, phys_addr_t phys,
184 size_t size, int nid) 185 size_t size, int nid, void *owner)
185{ 186{
186 struct gen_pool_chunk *chunk; 187 struct gen_pool_chunk *chunk;
187 int nbits = size >> pool->min_alloc_order; 188 int nbits = size >> pool->min_alloc_order;
@@ -195,6 +196,7 @@ int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phy
195 chunk->phys_addr = phys; 196 chunk->phys_addr = phys;
196 chunk->start_addr = virt; 197 chunk->start_addr = virt;
197 chunk->end_addr = virt + size - 1; 198 chunk->end_addr = virt + size - 1;
199 chunk->owner = owner;
198 atomic_long_set(&chunk->avail, size); 200 atomic_long_set(&chunk->avail, size);
199 201
200 spin_lock(&pool->lock); 202 spin_lock(&pool->lock);
@@ -203,7 +205,7 @@ int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phy
203 205
204 return 0; 206 return 0;
205} 207}
206EXPORT_SYMBOL(gen_pool_add_virt); 208EXPORT_SYMBOL(gen_pool_add_owner);
207 209
208/** 210/**
209 * gen_pool_virt_to_phys - return the physical address of memory 211 * gen_pool_virt_to_phys - return the physical address of memory
@@ -260,35 +262,20 @@ void gen_pool_destroy(struct gen_pool *pool)
260EXPORT_SYMBOL(gen_pool_destroy); 262EXPORT_SYMBOL(gen_pool_destroy);
261 263
262/** 264/**
263 * gen_pool_alloc - allocate special memory from the pool 265 * gen_pool_alloc_algo_owner - allocate special memory from the pool
264 * @pool: pool to allocate from
265 * @size: number of bytes to allocate from the pool
266 *
267 * Allocate the requested number of bytes from the specified pool.
268 * Uses the pool allocation function (with first-fit algorithm by default).
269 * Can not be used in NMI handler on architectures without
270 * NMI-safe cmpxchg implementation.
271 */
272unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)
273{
274 return gen_pool_alloc_algo(pool, size, pool->algo, pool->data);
275}
276EXPORT_SYMBOL(gen_pool_alloc);
277
278/**
279 * gen_pool_alloc_algo - allocate special memory from the pool
280 * @pool: pool to allocate from 266 * @pool: pool to allocate from
281 * @size: number of bytes to allocate from the pool 267 * @size: number of bytes to allocate from the pool
282 * @algo: algorithm passed from caller 268 * @algo: algorithm passed from caller
283 * @data: data passed to algorithm 269 * @data: data passed to algorithm
270 * @owner: optionally retrieve the chunk owner
284 * 271 *
285 * Allocate the requested number of bytes from the specified pool. 272 * Allocate the requested number of bytes from the specified pool.
286 * Uses the pool allocation function (with first-fit algorithm by default). 273 * Uses the pool allocation function (with first-fit algorithm by default).
287 * Can not be used in NMI handler on architectures without 274 * Can not be used in NMI handler on architectures without
288 * NMI-safe cmpxchg implementation. 275 * NMI-safe cmpxchg implementation.
289 */ 276 */
290unsigned long gen_pool_alloc_algo(struct gen_pool *pool, size_t size, 277unsigned long gen_pool_alloc_algo_owner(struct gen_pool *pool, size_t size,
291 genpool_algo_t algo, void *data) 278 genpool_algo_t algo, void *data, void **owner)
292{ 279{
293 struct gen_pool_chunk *chunk; 280 struct gen_pool_chunk *chunk;
294 unsigned long addr = 0; 281 unsigned long addr = 0;
@@ -299,6 +286,9 @@ unsigned long gen_pool_alloc_algo(struct gen_pool *pool, size_t size,
299 BUG_ON(in_nmi()); 286 BUG_ON(in_nmi());
300#endif 287#endif
301 288
289 if (owner)
290 *owner = NULL;
291
302 if (size == 0) 292 if (size == 0)
303 return 0; 293 return 0;
304 294
@@ -326,12 +316,14 @@ retry:
326 addr = chunk->start_addr + ((unsigned long)start_bit << order); 316 addr = chunk->start_addr + ((unsigned long)start_bit << order);
327 size = nbits << order; 317 size = nbits << order;
328 atomic_long_sub(size, &chunk->avail); 318 atomic_long_sub(size, &chunk->avail);
319 if (owner)
320 *owner = chunk->owner;
329 break; 321 break;
330 } 322 }
331 rcu_read_unlock(); 323 rcu_read_unlock();
332 return addr; 324 return addr;
333} 325}
334EXPORT_SYMBOL(gen_pool_alloc_algo); 326EXPORT_SYMBOL(gen_pool_alloc_algo_owner);
335 327
336/** 328/**
337 * gen_pool_dma_alloc - allocate special memory from the pool for DMA usage 329 * gen_pool_dma_alloc - allocate special memory from the pool for DMA usage
@@ -367,12 +359,14 @@ EXPORT_SYMBOL(gen_pool_dma_alloc);
367 * @pool: pool to free to 359 * @pool: pool to free to
368 * @addr: starting address of memory to free back to pool 360 * @addr: starting address of memory to free back to pool
369 * @size: size in bytes of memory to free 361 * @size: size in bytes of memory to free
362 * @owner: private data stashed at gen_pool_add() time
370 * 363 *
371 * Free previously allocated special memory back to the specified 364 * Free previously allocated special memory back to the specified
372 * pool. Can not be used in NMI handler on architectures without 365 * pool. Can not be used in NMI handler on architectures without
373 * NMI-safe cmpxchg implementation. 366 * NMI-safe cmpxchg implementation.
374 */ 367 */
375void gen_pool_free(struct gen_pool *pool, unsigned long addr, size_t size) 368void gen_pool_free_owner(struct gen_pool *pool, unsigned long addr, size_t size,
369 void **owner)
376{ 370{
377 struct gen_pool_chunk *chunk; 371 struct gen_pool_chunk *chunk;
378 int order = pool->min_alloc_order; 372 int order = pool->min_alloc_order;
@@ -382,6 +376,9 @@ void gen_pool_free(struct gen_pool *pool, unsigned long addr, size_t size)
382 BUG_ON(in_nmi()); 376 BUG_ON(in_nmi());
383#endif 377#endif
384 378
379 if (owner)
380 *owner = NULL;
381
385 nbits = (size + (1UL << order) - 1) >> order; 382 nbits = (size + (1UL << order) - 1) >> order;
386 rcu_read_lock(); 383 rcu_read_lock();
387 list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk) { 384 list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk) {
@@ -392,6 +389,8 @@ void gen_pool_free(struct gen_pool *pool, unsigned long addr, size_t size)
392 BUG_ON(remain); 389 BUG_ON(remain);
393 size = nbits << order; 390 size = nbits << order;
394 atomic_long_add(size, &chunk->avail); 391 atomic_long_add(size, &chunk->avail);
392 if (owner)
393 *owner = chunk->owner;
395 rcu_read_unlock(); 394 rcu_read_unlock();
396 return; 395 return;
397 } 396 }
@@ -399,7 +398,7 @@ void gen_pool_free(struct gen_pool *pool, unsigned long addr, size_t size)
399 rcu_read_unlock(); 398 rcu_read_unlock();
400 BUG(); 399 BUG();
401} 400}
402EXPORT_SYMBOL(gen_pool_free); 401EXPORT_SYMBOL(gen_pool_free_owner);
403 402
404/** 403/**
405 * gen_pool_for_each_chunk - call func for every chunk of generic memory pool 404 * gen_pool_for_each_chunk - call func for every chunk of generic memory pool