OSDN Git Service

cifs: fail i/o on soft mounts if sessionsetup errors out
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / lib / genalloc.c
index 116a166..e3a475b 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/interrupt.h>
 #include <linux/genalloc.h>
 #include <linux/of_device.h>
+#include <linux/vmalloc.h>
 
 static inline size_t chunk_size(const struct gen_pool_chunk *chunk)
 {
@@ -187,14 +188,14 @@ int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phy
        int nbytes = sizeof(struct gen_pool_chunk) +
                                BITS_TO_LONGS(nbits) * sizeof(long);
 
-       chunk = kzalloc_node(nbytes, GFP_KERNEL, nid);
+       chunk = vzalloc_node(nbytes, nid);
        if (unlikely(chunk == NULL))
                return -ENOMEM;
 
        chunk->phys_addr = phys;
        chunk->start_addr = virt;
        chunk->end_addr = virt + size - 1;
-       atomic_set(&chunk->avail, size);
+       atomic_long_set(&chunk->avail, size);
 
        spin_lock(&pool->lock);
        list_add_rcu(&chunk->next_chunk, &pool->chunks);
@@ -251,7 +252,7 @@ void gen_pool_destroy(struct gen_pool *pool)
                bit = find_next_bit(chunk->bits, end_bit, 0);
                BUG_ON(bit < end_bit);
 
-               kfree(chunk);
+               vfree(chunk);
        }
        kfree_const(pool->name);
        kfree(pool);
@@ -273,7 +274,7 @@ unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)
        struct gen_pool_chunk *chunk;
        unsigned long addr = 0;
        int order = pool->min_alloc_order;
-       int nbits, start_bit = 0, end_bit, remain;
+       int nbits, start_bit, end_bit, remain;
 
 #ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
        BUG_ON(in_nmi());
@@ -285,9 +286,10 @@ unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)
        nbits = (size + (1UL << order) - 1) >> order;
        rcu_read_lock();
        list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk) {
-               if (size > atomic_read(&chunk->avail))
+               if (size > atomic_long_read(&chunk->avail))
                        continue;
 
+               start_bit = 0;
                end_bit = chunk_size(chunk) >> order;
 retry:
                start_bit = pool->algo(chunk->bits, end_bit, start_bit, nbits,
@@ -304,7 +306,7 @@ retry:
 
                addr = chunk->start_addr + ((unsigned long)start_bit << order);
                size = nbits << order;
-               atomic_sub(size, &chunk->avail);
+               atomic_long_sub(size, &chunk->avail);
                break;
        }
        rcu_read_unlock();
@@ -370,7 +372,7 @@ void gen_pool_free(struct gen_pool *pool, unsigned long addr, size_t size)
                        remain = bitmap_clear_ll(chunk->bits, start_bit, nbits);
                        BUG_ON(remain);
                        size = nbits << order;
-                       atomic_add(size, &chunk->avail);
+                       atomic_long_add(size, &chunk->avail);
                        rcu_read_unlock();
                        return;
                }
@@ -444,7 +446,7 @@ size_t gen_pool_avail(struct gen_pool *pool)
 
        rcu_read_lock();
        list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk)
-               avail += atomic_read(&chunk->avail);
+               avail += atomic_long_read(&chunk->avail);
        rcu_read_unlock();
        return avail;
 }