qdf_idr.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /*
  2. * Copyright (c) 2018 The Linux Foundation. All rights reserved.
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for
  5. * any purpose with or without fee is hereby granted, provided that the
  6. * above copyright notice and this permission notice appear in all
  7. * copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  10. * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  11. * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
  12. * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  13. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  14. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  15. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  16. * PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. /**
  19. * DOC: qdf_idr
  20. * This file provides the ability to map an ID to a pointer
  21. */
  22. /* Include files */
  23. #include <qdf_idr.h>
  24. #include <qdf_module.h>
  25. #define QDF_IDR_START 0x100
  26. #define QDF_IDR_END 0
  27. static int qdf_idr_gpf_flag(void)
  28. {
  29. if (in_interrupt() || irqs_disabled() || in_atomic())
  30. return GFP_ATOMIC;
  31. return GFP_KERNEL;
  32. }
  33. #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)
  34. /**
  35. * __qdf_idr_alloc() - Allocates an unused ID
  36. * @idp: pointer to qdf idr
  37. * @ptr: pointer to be associated with the new ID
  38. * @start: the minimum ID
  39. * @end: the maximum ID
  40. *
  41. * Return: new ID
  42. */
  43. static inline int32_t
  44. __qdf_idr_alloc(qdf_idr *idp, void *ptr, int32_t start, int32_t end)
  45. {
  46. int32_t id = 0;
  47. idr_get_new(&idp->idr, ptr, &id);
  48. return id;
  49. }
  50. #else
  51. static inline int32_t
  52. __qdf_idr_alloc(qdf_idr *idp, void *ptr, int32_t start, int32_t end)
  53. {
  54. return idr_alloc(&idp->idr, ptr, start, end, qdf_idr_gpf_flag());
  55. }
  56. #endif
  57. QDF_STATUS qdf_idr_create(qdf_idr *idp)
  58. {
  59. if (!idp)
  60. return QDF_STATUS_E_INVAL;
  61. qdf_spinlock_create(&idp->lock);
  62. idr_init(&idp->idr);
  63. return QDF_STATUS_SUCCESS;
  64. }
  65. qdf_export_symbol(qdf_idr_create);
  66. QDF_STATUS qdf_idr_destroy(qdf_idr *idp)
  67. {
  68. if (!idp)
  69. return QDF_STATUS_E_INVAL;
  70. qdf_spinlock_destroy(&idp->lock);
  71. idr_destroy(&idp->idr);
  72. return QDF_STATUS_SUCCESS;
  73. }
  74. qdf_export_symbol(qdf_idr_destroy);
  75. QDF_STATUS qdf_idr_alloc(qdf_idr *idp, void *ptr, int32_t *id)
  76. {
  77. int local_id;
  78. if (!idp || !ptr)
  79. return QDF_STATUS_E_INVAL;
  80. qdf_spinlock_acquire(&idp->lock);
  81. local_id = __qdf_idr_alloc(idp, ptr, QDF_IDR_START, QDF_IDR_END);
  82. qdf_spinlock_release(&idp->lock);
  83. if (local_id < QDF_IDR_START)
  84. return QDF_STATUS_E_FAILURE;
  85. *id = local_id;
  86. return QDF_STATUS_SUCCESS;
  87. }
  88. qdf_export_symbol(qdf_idr_alloc);
  89. QDF_STATUS qdf_idr_remove(qdf_idr *idp, int32_t id)
  90. {
  91. if (!idp || id < QDF_IDR_START)
  92. return QDF_STATUS_E_INVAL;
  93. qdf_spinlock_acquire(&idp->lock);
  94. if (idr_find(&idp->idr, id))
  95. idr_remove(&idp->idr, id);
  96. qdf_spinlock_release(&idp->lock);
  97. return QDF_STATUS_SUCCESS;
  98. }
  99. qdf_export_symbol(qdf_idr_remove);
  100. QDF_STATUS qdf_idr_find(qdf_idr *idp, int32_t id, void **ptr)
  101. {
  102. if (!ptr || (id < QDF_IDR_START))
  103. return QDF_STATUS_E_INVAL;
  104. qdf_spinlock_acquire(&idp->lock);
  105. *ptr = idr_find(&idp->idr, id);
  106. qdf_spinlock_release(&idp->lock);
  107. if (!(*ptr))
  108. return QDF_STATUS_E_INVAL;
  109. else
  110. return QDF_STATUS_SUCCESS;
  111. }
  112. qdf_export_symbol(qdf_idr_find);