icswx_pid.c 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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. #include <linux/sched.h>
  13. #include <linux/kernel.h>
  14. #include <linux/errno.h>
  15. #include <linux/types.h>
  16. #include <linux/mm.h>
  17. #include <linux/spinlock.h>
  18. #include <linux/idr.h>
  19. #include <linux/module.h>
  20. #include "icswx.h"
  21. #define COP_PID_MIN (COP_PID_NONE + 1)
  22. #define COP_PID_MAX (0xFFFF)
  23. static DEFINE_SPINLOCK(mmu_context_acop_lock);
  24. static DEFINE_IDA(cop_ida);
  25. static int new_cop_pid(struct ida *ida, int min_id, int max_id,
  26. spinlock_t *lock)
  27. {
  28. int index;
  29. int err;
  30. again:
  31. if (!ida_pre_get(ida, GFP_KERNEL))
  32. return -ENOMEM;
  33. spin_lock(lock);
  34. err = ida_get_new_above(ida, min_id, &index);
  35. spin_unlock(lock);
  36. if (err == -EAGAIN)
  37. goto again;
  38. else if (err)
  39. return err;
  40. if (index > max_id) {
  41. spin_lock(lock);
  42. ida_remove(ida, index);
  43. spin_unlock(lock);
  44. return -ENOMEM;
  45. }
  46. return index;
  47. }
  48. int get_cop_pid(struct mm_struct *mm)
  49. {
  50. int pid;
  51. if (mm->context.cop_pid == COP_PID_NONE) {
  52. pid = new_cop_pid(&cop_ida, COP_PID_MIN, COP_PID_MAX,
  53. &mmu_context_acop_lock);
  54. if (pid >= 0)
  55. mm->context.cop_pid = pid;
  56. }
  57. return mm->context.cop_pid;
  58. }
  59. int disable_cop_pid(struct mm_struct *mm)
  60. {
  61. int free_pid = COP_PID_NONE;
  62. if ((!mm->context.acop) && (mm->context.cop_pid != COP_PID_NONE)) {
  63. free_pid = mm->context.cop_pid;
  64. mm->context.cop_pid = COP_PID_NONE;
  65. }
  66. return free_pid;
  67. }
  68. void free_cop_pid(int free_pid)
  69. {
  70. spin_lock(&mmu_context_acop_lock);
  71. ida_remove(&cop_ida, free_pid);
  72. spin_unlock(&mmu_context_acop_lock);
  73. }