powerpc/numa: Add form 1 NUMA affinity
[safe/jmp/linux-2.6] / arch / powerpc / mm / mmu_context_hash64.c
index dbeb86a..2535828 100644 (file)
 #include <linux/mm.h>
 #include <linux/spinlock.h>
 #include <linux/idr.h>
+#include <linux/module.h>
+#include <linux/gfp.h>
 
 #include <asm/mmu_context.h>
 
 static DEFINE_SPINLOCK(mmu_context_lock);
-static DEFINE_IDR(mmu_context_idr);
+static DEFINE_IDA(mmu_context_ida);
 
 /*
  * The proto-VSID space has 2^35 - 1 segments available for user mappings.
@@ -32,17 +34,17 @@ static DEFINE_IDR(mmu_context_idr);
 #define NO_CONTEXT     0
 #define MAX_CONTEXT    ((1UL << 19) - 1)
 
-int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+int __init_new_context(void)
 {
        int index;
        int err;
 
 again:
-       if (!idr_pre_get(&mmu_context_idr, GFP_KERNEL))
+       if (!ida_pre_get(&mmu_context_ida, GFP_KERNEL))
                return -ENOMEM;
 
        spin_lock(&mmu_context_lock);
-       err = idr_get_new_above(&mmu_context_idr, NULL, 1, &index);
+       err = ida_get_new_above(&mmu_context_ida, 1, &index);
        spin_unlock(&mmu_context_lock);
 
        if (err == -EAGAIN)
@@ -52,27 +54,46 @@ again:
 
        if (index > MAX_CONTEXT) {
                spin_lock(&mmu_context_lock);
-               idr_remove(&mmu_context_idr, index);
+               ida_remove(&mmu_context_ida, index);
                spin_unlock(&mmu_context_lock);
                return -ENOMEM;
        }
 
+       return index;
+}
+EXPORT_SYMBOL_GPL(__init_new_context);
+
+int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+       int index;
+
+       index = __init_new_context();
+       if (index < 0)
+               return index;
+
        /* The old code would re-promote on fork, we don't do that
         * when using slices as it could cause problem promoting slices
         * that have been forced down to 4K
         */
        if (slice_mm_new_context(mm))
                slice_set_user_psize(mm, mmu_virtual_psize);
+       subpage_prot_init_new_context(mm);
        mm->context.id = index;
 
        return 0;
 }
 
-void destroy_context(struct mm_struct *mm)
+void __destroy_context(int context_id)
 {
        spin_lock(&mmu_context_lock);
-       idr_remove(&mmu_context_idr, mm->context.id);
+       ida_remove(&mmu_context_ida, context_id);
        spin_unlock(&mmu_context_lock);
+}
+EXPORT_SYMBOL_GPL(__destroy_context);
 
+void destroy_context(struct mm_struct *mm)
+{
+       __destroy_context(mm->context.id);
+       subpage_prot_free(mm);
        mm->context.id = NO_CONTEXT;
 }