Applied. Regards, Vladimir
On Tue, 2007-01-16 at 13:52 -0600, Steve Wise wrote: > Provide generic allocator backport to 2.6.20. > > This is needed even on kernels that might have genalloc because it > may not be configured into the running kernel. Right now the only > subsystem that turns on the generic allocator config option is IA64. > So chances are good that 2.6.20 kernels will _not_ have this compiled in. > So we just backport it to all supported kernels. > > To avoid collisions with kernels that _do_ have this compiled in, > change the names of the exported symbols in the backport. > > Changes to genalloc.h: > > - Change exported symbol names by prepending ib_ > - added #defines for original exported symbol names to new names. Thus > code calling the allocator doesn't need to change. > > EG: #define gen_pool_alloc ib_gen_pool alloc > > Signed-off-by: Steve Wise <[EMAIL PROTECTED]> > --- > > .../backport/2.6.20/include/linux/genalloc.h | 42 +++++ > .../backport/2.6.20/include/src/genalloc.c | 198 > +++++++++++++++++++++++ > .../backport/2.6.20/linux_genalloc_to_2.6.20.patch | 17 ++ > 3 files changed, 257 insertions(+), 0 deletions(-) > > diff --git a/kernel_addons/backport/2.6.20/include/linux/genalloc.h > b/kernel_addons/backport/2.6.20/include/linux/genalloc.h > new file mode 100644 > index 0000000..3c23c68 > --- /dev/null > +++ b/kernel_addons/backport/2.6.20/include/linux/genalloc.h > @@ -0,0 +1,42 @@ > +/* > + * Basic general purpose allocator for managing special purpose memory > + * not managed by the regular kmalloc/kfree interface. > + * Uses for this includes on-device special memory, uncached memory > + * etc. > + * > + * This source code is licensed under the GNU General Public License, > + * Version 2. See the file COPYING for more details. > + */ > + > + > +/* > + * General purpose special memory pool descriptor. > + */ > +struct gen_pool { > + rwlock_t lock; > + struct list_head chunks; /* list of chunks in this pool */ > + int min_alloc_order; /* minimum allocation order */ > +}; > + > +/* > + * General purpose special memory pool chunk descriptor. > + */ > +struct gen_pool_chunk { > + spinlock_t lock; > + struct list_head next_chunk; /* next chunk in pool */ > + unsigned long start_addr; /* starting address of memory chunk */ > + unsigned long end_addr; /* ending address of memory chunk */ > + unsigned long bits[0]; /* bitmap for allocating memory chunk */ > +}; > + > +extern struct gen_pool *ib_gen_pool_create(int, int); > +extern int ib_gen_pool_add(struct gen_pool *, unsigned long, size_t, int); > +extern void ib_gen_pool_destroy(struct gen_pool *); > +extern unsigned long ib_gen_pool_alloc(struct gen_pool *, size_t); > +extern void ib_gen_pool_free(struct gen_pool *, unsigned long, size_t); > + > +#define gen_pool_create ib_gen_pool_create > +#define gen_pool_add ib_gen_pool_add > +#define gen_pool_destroy ib_gen_pool_destroy > +#define gen_pool_alloc ib_gen_pool_alloc > +#define gen_pool_free ib_gen_pool_free > diff --git a/kernel_addons/backport/2.6.20/include/src/genalloc.c > b/kernel_addons/backport/2.6.20/include/src/genalloc.c > new file mode 100644 > index 0000000..75ae68c > --- /dev/null > +++ b/kernel_addons/backport/2.6.20/include/src/genalloc.c > @@ -0,0 +1,198 @@ > +/* > + * Basic general purpose allocator for managing special purpose memory > + * not managed by the regular kmalloc/kfree interface. > + * Uses for this includes on-device special memory, uncached memory > + * etc. > + * > + * Copyright 2005 (C) Jes Sorensen <[EMAIL PROTECTED]> > + * > + * This source code is licensed under the GNU General Public License, > + * Version 2. See the file COPYING for more details. > + */ > + > +#include <linux/module.h> > +#include <linux/genalloc.h> > + > + > +/** > + * gen_pool_create - create a new special memory pool > + * @min_alloc_order: log base 2 of number of bytes each bitmap bit represents > + * @nid: node id of the node the pool structure should be allocated on, or -1 > + * > + * Create a new special memory pool that can be used to manage special > purpose > + * memory not managed by the regular kmalloc/kfree interface. > + */ > +struct gen_pool *gen_pool_create(int min_alloc_order, int nid) > +{ > + struct gen_pool *pool; > + > + pool = kmalloc_node(sizeof(struct gen_pool), GFP_KERNEL, nid); > + if (pool != NULL) { > + rwlock_init(&pool->lock); > + INIT_LIST_HEAD(&pool->chunks); > + pool->min_alloc_order = min_alloc_order; > + } > + return pool; > +} > +EXPORT_SYMBOL(gen_pool_create); > + > +/** > + * gen_pool_add - add a new chunk of special memory to the pool > + * @pool: pool to add new memory chunk to > + * @addr: starting address of memory chunk to add to pool > + * @size: size in bytes of the memory chunk to add to pool > + * @nid: node id of the node the chunk structure and bitmap should be > + * allocated on, or -1 > + * > + * Add a new chunk of special memory to the specified pool. > + */ > +int gen_pool_add(struct gen_pool *pool, unsigned long addr, size_t size, > + int nid) > +{ > + struct gen_pool_chunk *chunk; > + int nbits = size >> pool->min_alloc_order; > + int nbytes = sizeof(struct gen_pool_chunk) + > + (nbits + BITS_PER_BYTE - 1) / BITS_PER_BYTE; > + > + chunk = kmalloc_node(nbytes, GFP_KERNEL, nid); > + if (unlikely(chunk == NULL)) > + return -1; > + > + memset(chunk, 0, nbytes); > + spin_lock_init(&chunk->lock); > + chunk->start_addr = addr; > + chunk->end_addr = addr + size; > + > + write_lock(&pool->lock); > + list_add(&chunk->next_chunk, &pool->chunks); > + write_unlock(&pool->lock); > + > + return 0; > +} > +EXPORT_SYMBOL(gen_pool_add); > + > +/** > + * gen_pool_destroy - destroy a special memory pool > + * @pool: pool to destroy > + * > + * Destroy the specified special memory pool. Verifies that there are no > + * outstanding allocations. > + */ > +void gen_pool_destroy(struct gen_pool *pool) > +{ > + struct list_head *_chunk, *_next_chunk; > + struct gen_pool_chunk *chunk; > + int order = pool->min_alloc_order; > + int bit, end_bit; > + > + > + write_lock(&pool->lock); > + list_for_each_safe(_chunk, _next_chunk, &pool->chunks) { > + chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk); > + list_del(&chunk->next_chunk); > + > + end_bit = (chunk->end_addr - chunk->start_addr) >> order; > + bit = find_next_bit(chunk->bits, end_bit, 0); > + BUG_ON(bit < end_bit); > + > + kfree(chunk); > + } > + kfree(pool); > + return; > +} > +EXPORT_SYMBOL(gen_pool_destroy); > + > +/** > + * gen_pool_alloc - allocate special memory from the pool > + * @pool: pool to allocate from > + * @size: number of bytes to allocate from the pool > + * > + * Allocate the requested number of bytes from the specified pool. > + * Uses a first-fit algorithm. > + */ > +unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size) > +{ > + struct list_head *_chunk; > + struct gen_pool_chunk *chunk; > + unsigned long addr, flags; > + int order = pool->min_alloc_order; > + int nbits, bit, start_bit, end_bit; > + > + if (size == 0) > + return 0; > + > + nbits = (size + (1UL << order) - 1) >> order; > + > + read_lock(&pool->lock); > + list_for_each(_chunk, &pool->chunks) { > + chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk); > + > + end_bit = (chunk->end_addr - chunk->start_addr) >> order; > + end_bit -= nbits + 1; > + > + spin_lock_irqsave(&chunk->lock, flags); > + bit = -1; > + while (bit + 1 < end_bit) { > + bit = find_next_zero_bit(chunk->bits, end_bit, bit + 1); > + if (bit >= end_bit) > + break; > + > + start_bit = bit; > + if (nbits > 1) { > + bit = find_next_bit(chunk->bits, bit + nbits, > + bit + 1); > + if (bit - start_bit < nbits) > + continue; > + } > + > + addr = chunk->start_addr + > + ((unsigned long)start_bit << order); > + while (nbits--) > + __set_bit(start_bit++, &chunk->bits); > + spin_unlock_irqrestore(&chunk->lock, flags); > + read_unlock(&pool->lock); > + return addr; > + } > + spin_unlock_irqrestore(&chunk->lock, flags); > + } > + read_unlock(&pool->lock); > + return 0; > +} > +EXPORT_SYMBOL(gen_pool_alloc); > + > +/** > + * gen_pool_free - free allocated special memory back to the pool > + * @pool: pool to free to > + * @addr: starting address of memory to free back to pool > + * @size: size in bytes of memory to free > + * > + * Free previously allocated special memory back to the specified pool. > + */ > +void gen_pool_free(struct gen_pool *pool, unsigned long addr, size_t size) > +{ > + struct list_head *_chunk; > + struct gen_pool_chunk *chunk; > + unsigned long flags; > + int order = pool->min_alloc_order; > + int bit, nbits; > + > + nbits = (size + (1UL << order) - 1) >> order; > + > + read_lock(&pool->lock); > + list_for_each(_chunk, &pool->chunks) { > + chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk); > + > + if (addr >= chunk->start_addr && addr < chunk->end_addr) { > + BUG_ON(addr + size > chunk->end_addr); > + spin_lock_irqsave(&chunk->lock, flags); > + bit = (addr - chunk->start_addr) >> order; > + while (nbits--) > + __clear_bit(bit++, &chunk->bits); > + spin_unlock_irqrestore(&chunk->lock, flags); > + break; > + } > + } > + BUG_ON(nbits > 0); > + read_unlock(&pool->lock); > +} > +EXPORT_SYMBOL(gen_pool_free); > diff --git a/kernel_patches/backport/2.6.20/linux_genalloc_to_2.6.20.patch > b/kernel_patches/backport/2.6.20/linux_genalloc_to_2.6.20.patch > new file mode 100644 > index 0000000..93fee2b > --- /dev/null > +++ b/kernel_patches/backport/2.6.20/linux_genalloc_to_2.6.20.patch > @@ -0,0 +1,17 @@ > +diff --git a/drivers/infiniband/core/Makefile > b/drivers/infiniband/core/Makefile > +index 163d991..2cd239f 100644 > +--- a/drivers/infiniband/core/Makefile > ++++ b/drivers/infiniband/core/Makefile > +@@ -30,3 +30,5 @@ ib_ucm-y := ucm.o > + > + ib_uverbs-y := uverbs_main.o uverbs_cmd.o uverbs_mem.o > \ > + uverbs_marshall.o > ++ > ++ib_core-y += genalloc.o > +diff --git a/drivers/infiniband/core/genalloc.c > b/drivers/infiniband/core/genalloc.c > +new file mode 100644 > +index 0000000..96a48fe > +--- /dev/null > ++++ b/drivers/infiniband/core/genalloc.c > +@@ -0,0 +1 @@ > ++#include "src/genalloc.c" > > _______________________________________________ > openib-general mailing list > openib-general@openib.org > http://openib.org/mailman/listinfo/openib-general > > To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general _______________________________________________ openib-general mailing list openib-general@openib.org http://openib.org/mailman/listinfo/openib-general To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general