wbuff.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. /*
  2. * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
  3. * Copyright (c) 2021, 2023 Qualcomm Innovation Center, Inc. All rights reserved.
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for
  6. * any purpose with or without fee is hereby granted, provided that the
  7. * above copyright notice and this permission notice appear in all
  8. * copies.
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  11. * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  12. * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
  13. * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  14. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  15. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  16. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  17. * PERFORMANCE OF THIS SOFTWARE.
  18. */
  19. /**
  20. * DOC: wbuff.c
  21. * wbuff buffer management APIs
  22. */
  23. #include <wbuff.h>
  24. #include "i_wbuff.h"
  25. /*
  26. * Allocation holder array for all wbuff registered modules
  27. */
  28. struct wbuff_holder wbuff;
  29. /**
  30. * wbuff_get_pool_slot_from_len() - get pool_slot from length
  31. * @len: length of the buffer
  32. *
  33. * Return: pool slot
  34. */
  35. static uint8_t wbuff_get_pool_slot_from_len(uint16_t len)
  36. {
  37. if ((len > 0) && (len <= WBUFF_LEN_POOL0))
  38. return WBUFF_POOL_0;
  39. else if ((len > WBUFF_LEN_POOL0) && (len <= WBUFF_LEN_POOL1))
  40. return WBUFF_POOL_1;
  41. else if ((len > WBUFF_LEN_POOL1) && (len <= WBUFF_LEN_POOL2))
  42. return WBUFF_POOL_2;
  43. else
  44. return WBUFF_POOL_3;
  45. }
  46. /**
  47. * wbuff_get_len_from_pool_slot() - get len from pool slot
  48. * @pool_slot: wbuff pool_slot
  49. *
  50. * Return: nbuf length from pool slot
  51. */
  52. static uint32_t wbuff_get_len_from_pool_slot(uint16_t pool_slot)
  53. {
  54. uint32_t len = 0;
  55. switch (pool_slot) {
  56. case 0:
  57. len = WBUFF_LEN_POOL0;
  58. break;
  59. case 1:
  60. len = WBUFF_LEN_POOL1;
  61. break;
  62. case 2:
  63. len = WBUFF_LEN_POOL2;
  64. break;
  65. case 3:
  66. len = WBUFF_LEN_POOL3;
  67. break;
  68. default:
  69. len = 0;
  70. }
  71. return len;
  72. }
  73. /**
  74. * wbuff_get_free_mod_slot() - get free module slot
  75. *
  76. * Return: module slot
  77. */
  78. static uint8_t wbuff_get_free_mod_slot(void)
  79. {
  80. uint8_t mslot = 0;
  81. for (mslot = 0; mslot < WBUFF_MAX_MODULES; mslot++) {
  82. qdf_spin_lock_bh(&wbuff.mod[mslot].lock);
  83. if (!wbuff.mod[mslot].registered) {
  84. wbuff.mod[mslot].registered = true;
  85. qdf_spin_unlock_bh(&wbuff.mod[mslot].lock);
  86. break;
  87. }
  88. qdf_spin_unlock_bh(&wbuff.mod[mslot].lock);
  89. }
  90. return mslot;
  91. }
  92. /**
  93. * wbuff_is_valid_alloc_req() - validate alloc request
  94. * @req: allocation request from registered module
  95. * @num: number of pools required
  96. *
  97. * Return: true if valid wbuff_alloc_request
  98. * false if invalid wbuff_alloc_request
  99. */
  100. static bool wbuff_is_valid_alloc_req(struct wbuff_alloc_request *req,
  101. uint8_t num)
  102. {
  103. uint16_t psize = 0;
  104. uint8_t alloc = 0, pslot = 0;
  105. for (alloc = 0; alloc < num; alloc++) {
  106. pslot = req[alloc].slot;
  107. psize = req[alloc].size;
  108. if ((pslot > WBUFF_MAX_POOLS - 1) ||
  109. (psize > wbuff_alloc_max[pslot]))
  110. return false;
  111. }
  112. return true;
  113. }
  114. /**
  115. * wbuff_prepare_nbuf() - allocate nbuf
  116. * @mslot: module slot
  117. * @pslot: pool slot
  118. * @len: length of the buffer
  119. * @reserve: nbuf headroom to start with
  120. * @align: alignment for the nbuf
  121. *
  122. * Return: nbuf if success
  123. * NULL if failure
  124. */
  125. static qdf_nbuf_t wbuff_prepare_nbuf(uint8_t mslot, uint8_t pslot,
  126. uint32_t len, int reserve, int align)
  127. {
  128. qdf_nbuf_t buf;
  129. unsigned long dev_scratch = 0;
  130. buf = qdf_nbuf_alloc(NULL, roundup(len + reserve, align), reserve,
  131. align, false);
  132. if (!buf)
  133. return NULL;
  134. dev_scratch = mslot;
  135. dev_scratch <<= WBUFF_MSLOT_SHIFT;
  136. dev_scratch |= ((pslot << WBUFF_PSLOT_SHIFT) | 1);
  137. qdf_nbuf_set_dev_scratch(buf, dev_scratch);
  138. return buf;
  139. }
  140. /**
  141. * wbuff_is_valid_handle() - validate wbuff handle
  142. * @handle: wbuff handle passed by module
  143. *
  144. * Return: true - valid wbuff_handle
  145. * false - invalid wbuff_handle
  146. */
  147. static bool wbuff_is_valid_handle(struct wbuff_handle *handle)
  148. {
  149. if ((handle) && (handle->id < WBUFF_MAX_MODULES) &&
  150. (wbuff.mod[handle->id].registered))
  151. return true;
  152. return false;
  153. }
  154. QDF_STATUS wbuff_module_init(void)
  155. {
  156. struct wbuff_module *mod = NULL;
  157. uint8_t mslot = 0, pslot = 0;
  158. if (!qdf_nbuf_is_dev_scratch_supported()) {
  159. wbuff.initialized = false;
  160. return QDF_STATUS_E_NOSUPPORT;
  161. }
  162. for (mslot = 0; mslot < WBUFF_MAX_MODULES; mslot++) {
  163. mod = &wbuff.mod[mslot];
  164. qdf_spinlock_create(&mod->lock);
  165. for (pslot = 0; pslot < WBUFF_MAX_POOLS; pslot++)
  166. mod->pool[pslot] = NULL;
  167. mod->registered = false;
  168. }
  169. wbuff.initialized = true;
  170. return QDF_STATUS_SUCCESS;
  171. }
  172. QDF_STATUS wbuff_module_deinit(void)
  173. {
  174. struct wbuff_module *mod = NULL;
  175. uint8_t mslot = 0;
  176. if (!wbuff.initialized)
  177. return QDF_STATUS_E_INVAL;
  178. wbuff.initialized = false;
  179. for (mslot = 0; mslot < WBUFF_MAX_MODULES; mslot++) {
  180. mod = &wbuff.mod[mslot];
  181. if (mod->registered)
  182. wbuff_module_deregister((struct wbuff_mod_handle *)
  183. &mod->handle);
  184. qdf_spinlock_destroy(&mod->lock);
  185. }
  186. return QDF_STATUS_SUCCESS;
  187. }
  188. struct wbuff_mod_handle *
  189. wbuff_module_register(struct wbuff_alloc_request *req, uint8_t num,
  190. int reserve, int align)
  191. {
  192. struct wbuff_module *mod = NULL;
  193. qdf_nbuf_t buf = NULL;
  194. uint32_t len = 0;
  195. uint16_t idx = 0, psize = 0;
  196. uint8_t alloc = 0, mslot = 0, pslot = 0;
  197. if (!wbuff.initialized)
  198. return NULL;
  199. if ((num == 0) || (num > WBUFF_MAX_POOLS))
  200. return NULL;
  201. if (!wbuff_is_valid_alloc_req(req, num))
  202. return NULL;
  203. mslot = wbuff_get_free_mod_slot();
  204. if (mslot == WBUFF_MAX_MODULES)
  205. return NULL;
  206. mod = &wbuff.mod[mslot];
  207. mod->handle.id = mslot;
  208. for (alloc = 0; alloc < num; alloc++) {
  209. pslot = req[alloc].slot;
  210. psize = req[alloc].size;
  211. len = wbuff_get_len_from_pool_slot(pslot);
  212. /**
  213. * Allocate pool_cnt number of buffers for
  214. * the pool given by pslot
  215. */
  216. for (idx = 0; idx < psize; idx++) {
  217. buf = wbuff_prepare_nbuf(mslot, pslot, len, reserve,
  218. align);
  219. if (!buf)
  220. continue;
  221. if (!mod->pool[pslot]) {
  222. qdf_nbuf_set_next(buf, NULL);
  223. mod->pool[pslot] = buf;
  224. } else {
  225. qdf_nbuf_set_next(buf, mod->pool[pslot]);
  226. mod->pool[pslot] = buf;
  227. }
  228. }
  229. }
  230. mod->reserve = reserve;
  231. mod->align = align;
  232. return (struct wbuff_mod_handle *)&mod->handle;
  233. }
  234. QDF_STATUS wbuff_module_deregister(struct wbuff_mod_handle *hdl)
  235. {
  236. struct wbuff_handle *handle;
  237. struct wbuff_module *mod = NULL;
  238. uint8_t mslot = 0, pslot = 0;
  239. qdf_nbuf_t first = NULL, buf = NULL;
  240. handle = (struct wbuff_handle *)hdl;
  241. if ((!wbuff.initialized) || (!wbuff_is_valid_handle(handle)))
  242. return QDF_STATUS_E_INVAL;
  243. mslot = handle->id;
  244. mod = &wbuff.mod[mslot];
  245. qdf_spin_lock_bh(&mod->lock);
  246. for (pslot = 0; pslot < WBUFF_MAX_POOLS; pslot++) {
  247. first = mod->pool[pslot];
  248. while (first) {
  249. buf = first;
  250. first = qdf_nbuf_next(buf);
  251. qdf_nbuf_free(buf);
  252. }
  253. }
  254. mod->registered = false;
  255. qdf_spin_unlock_bh(&mod->lock);
  256. return QDF_STATUS_SUCCESS;
  257. }
  258. qdf_nbuf_t wbuff_buff_get(struct wbuff_mod_handle *hdl, uint32_t len,
  259. const char *func_name, uint32_t line_num)
  260. {
  261. struct wbuff_handle *handle;
  262. struct wbuff_module *mod = NULL;
  263. uint8_t mslot = 0;
  264. uint8_t pslot = 0;
  265. qdf_nbuf_t buf = NULL;
  266. handle = (struct wbuff_handle *)hdl;
  267. if ((!wbuff.initialized) || (!wbuff_is_valid_handle(handle)) || !len ||
  268. (len > WBUFF_MAX_BUFFER_SIZE))
  269. return NULL;
  270. mslot = handle->id;
  271. pslot = wbuff_get_pool_slot_from_len(len);
  272. mod = &wbuff.mod[mslot];
  273. qdf_spin_lock_bh(&mod->lock);
  274. if (mod->pool[pslot]) {
  275. buf = mod->pool[pslot];
  276. mod->pool[pslot] = qdf_nbuf_next(buf);
  277. mod->pending_returns++;
  278. }
  279. qdf_spin_unlock_bh(&mod->lock);
  280. if (buf) {
  281. qdf_nbuf_set_next(buf, NULL);
  282. qdf_net_buf_debug_update_node(buf, func_name, line_num);
  283. }
  284. return buf;
  285. }
  286. qdf_nbuf_t wbuff_buff_put(qdf_nbuf_t buf)
  287. {
  288. qdf_nbuf_t buffer = buf;
  289. unsigned long slot_info = 0;
  290. uint8_t mslot = 0, pslot = 0;
  291. if (!wbuff.initialized)
  292. return buffer;
  293. slot_info = qdf_nbuf_get_dev_scratch(buf);
  294. if (!slot_info)
  295. return buffer;
  296. mslot = (slot_info & WBUFF_MSLOT_BITMASK) >> WBUFF_MSLOT_SHIFT;
  297. pslot = (slot_info & WBUFF_PSLOT_BITMASK) >> WBUFF_PSLOT_SHIFT;
  298. if (mslot >= WBUFF_MAX_MODULES || pslot >= WBUFF_MAX_POOLS)
  299. return NULL;
  300. qdf_nbuf_reset(buffer, wbuff.mod[mslot].reserve, wbuff.mod[mslot].
  301. align);
  302. qdf_spin_lock_bh(&wbuff.mod[mslot].lock);
  303. if (wbuff.mod[mslot].registered) {
  304. qdf_nbuf_set_next(buffer, wbuff.mod[mslot].pool[pslot]);
  305. wbuff.mod[mslot].pool[pslot] = buffer;
  306. wbuff.mod[mslot].pending_returns--;
  307. buffer = NULL;
  308. }
  309. qdf_spin_unlock_bh(&wbuff.mod[mslot].lock);
  310. return buffer;
  311. }