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

Reply via email to