pasid.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. // SPDX-License-Identifier: GPL-2.0+
  2. // Copyright 2017 IBM Corp.
  3. #include "ocxl_internal.h"
  4. struct id_range {
  5. struct list_head list;
  6. u32 start;
  7. u32 end;
  8. };
  9. #ifdef DEBUG
  10. static void dump_list(struct list_head *head, char *type_str)
  11. {
  12. struct id_range *cur;
  13. pr_debug("%s ranges allocated:\n", type_str);
  14. list_for_each_entry(cur, head, list) {
  15. pr_debug("Range %d->%d\n", cur->start, cur->end);
  16. }
  17. }
  18. #endif
  19. static int range_alloc(struct list_head *head, u32 size, int max_id,
  20. char *type_str)
  21. {
  22. struct list_head *pos;
  23. struct id_range *cur, *new;
  24. int rc, last_end;
  25. new = kmalloc(sizeof(struct id_range), GFP_KERNEL);
  26. if (!new)
  27. return -ENOMEM;
  28. pos = head;
  29. last_end = -1;
  30. list_for_each_entry(cur, head, list) {
  31. if ((cur->start - last_end) > size)
  32. break;
  33. last_end = cur->end;
  34. pos = &cur->list;
  35. }
  36. new->start = last_end + 1;
  37. new->end = new->start + size - 1;
  38. if (new->end > max_id) {
  39. kfree(new);
  40. rc = -ENOSPC;
  41. } else {
  42. list_add(&new->list, pos);
  43. rc = new->start;
  44. }
  45. #ifdef DEBUG
  46. dump_list(head, type_str);
  47. #endif
  48. return rc;
  49. }
  50. static void range_free(struct list_head *head, u32 start, u32 size,
  51. char *type_str)
  52. {
  53. bool found = false;
  54. struct id_range *cur, *tmp;
  55. list_for_each_entry_safe(cur, tmp, head, list) {
  56. if (cur->start == start && cur->end == (start + size - 1)) {
  57. found = true;
  58. list_del(&cur->list);
  59. kfree(cur);
  60. break;
  61. }
  62. }
  63. WARN_ON(!found);
  64. #ifdef DEBUG
  65. dump_list(head, type_str);
  66. #endif
  67. }
  68. int ocxl_pasid_afu_alloc(struct ocxl_fn *fn, u32 size)
  69. {
  70. int max_pasid;
  71. if (fn->config.max_pasid_log < 0)
  72. return -ENOSPC;
  73. max_pasid = 1 << fn->config.max_pasid_log;
  74. return range_alloc(&fn->pasid_list, size, max_pasid, "afu pasid");
  75. }
  76. void ocxl_pasid_afu_free(struct ocxl_fn *fn, u32 start, u32 size)
  77. {
  78. return range_free(&fn->pasid_list, start, size, "afu pasid");
  79. }
  80. int ocxl_actag_afu_alloc(struct ocxl_fn *fn, u32 size)
  81. {
  82. int max_actag;
  83. max_actag = fn->actag_enabled;
  84. return range_alloc(&fn->actag_list, size, max_actag, "afu actag");
  85. }
  86. void ocxl_actag_afu_free(struct ocxl_fn *fn, u32 start, u32 size)
  87. {
  88. return range_free(&fn->actag_list, start, size, "afu actag");
  89. }