linux/arch/powerpc/mm/icswx_pid.c
<<
>>
Prefs
   1/*
   2 *  ICSWX and ACOP/PID Management
   3 *
   4 *  Copyright (C) 2011 Anton Blanchard, IBM Corp. <anton@samba.org>
   5 *
   6 *  This program is free software; you can redistribute it and/or
   7 *  modify it under the terms of the GNU General Public License
   8 *  as published by the Free Software Foundation; either version
   9 *  2 of the License, or (at your option) any later version.
  10 *
  11 */
  12
  13#include <linux/sched.h>
  14#include <linux/kernel.h>
  15#include <linux/errno.h>
  16#include <linux/types.h>
  17#include <linux/mm.h>
  18#include <linux/spinlock.h>
  19#include <linux/idr.h>
  20#include <linux/module.h>
  21#include "icswx.h"
  22
  23#define COP_PID_MIN (COP_PID_NONE + 1)
  24#define COP_PID_MAX (0xFFFF)
  25
  26static DEFINE_SPINLOCK(mmu_context_acop_lock);
  27static DEFINE_IDA(cop_ida);
  28
  29static int new_cop_pid(struct ida *ida, int min_id, int max_id,
  30                       spinlock_t *lock)
  31{
  32        int index;
  33        int err;
  34
  35again:
  36        if (!ida_pre_get(ida, GFP_KERNEL))
  37                return -ENOMEM;
  38
  39        spin_lock(lock);
  40        err = ida_get_new_above(ida, min_id, &index);
  41        spin_unlock(lock);
  42
  43        if (err == -EAGAIN)
  44                goto again;
  45        else if (err)
  46                return err;
  47
  48        if (index > max_id) {
  49                spin_lock(lock);
  50                ida_remove(ida, index);
  51                spin_unlock(lock);
  52                return -ENOMEM;
  53        }
  54
  55        return index;
  56}
  57
  58int get_cop_pid(struct mm_struct *mm)
  59{
  60        int pid;
  61
  62        if (mm->context.cop_pid == COP_PID_NONE) {
  63                pid = new_cop_pid(&cop_ida, COP_PID_MIN, COP_PID_MAX,
  64                                  &mmu_context_acop_lock);
  65                if (pid >= 0)
  66                        mm->context.cop_pid = pid;
  67        }
  68        return mm->context.cop_pid;
  69}
  70
  71int disable_cop_pid(struct mm_struct *mm)
  72{
  73        int free_pid = COP_PID_NONE;
  74
  75        if ((!mm->context.acop) && (mm->context.cop_pid != COP_PID_NONE)) {
  76                free_pid = mm->context.cop_pid;
  77                mm->context.cop_pid = COP_PID_NONE;
  78        }
  79        return free_pid;
  80}
  81
  82void free_cop_pid(int free_pid)
  83{
  84        spin_lock(&mmu_context_acop_lock);
  85        ida_remove(&cop_ida, free_pid);
  86        spin_unlock(&mmu_context_acop_lock);
  87}
  88