dp_tx_me.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /*
  2. * Copyright (c) 2017-2019 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. #include "hal_hw_headers.h"
  19. #include "dp_types.h"
  20. #include "qdf_nbuf.h"
  21. #include "qdf_atomic.h"
  22. #include "qdf_types.h"
  23. #include "dp_tx.h"
  24. #include "dp_tx_desc.h"
  25. #include "dp_internal.h"
  26. #ifdef ATH_SUPPORT_IQUE
  27. #define MAX_ME_BUF_CHUNK 1424
  28. #define ME_US_TO_SEC(_x) ((_x)/(1000 * 1000))
  29. #define ME_CLEAN_WAIT_TIMEOUT (200000) /*200ms*/
  30. #define ME_CLEAN_WAIT_COUNT 400
  31. /**
  32. * dp_tx_me_init():Initialize ME buffer ppol
  33. * @pdev: DP PDEV handle
  34. *
  35. * Return:0 on Succes 1 on failure
  36. */
  37. static inline uint16_t
  38. dp_tx_me_init(struct dp_pdev *pdev)
  39. {
  40. uint16_t i, mc_uc_buf_len, num_pool_elems;
  41. uint32_t pool_size;
  42. struct dp_tx_me_buf_t *p;
  43. mc_uc_buf_len = sizeof(struct dp_tx_me_buf_t);
  44. num_pool_elems = MAX_ME_BUF_CHUNK;
  45. /* Add flow control buffer count */
  46. pool_size = (mc_uc_buf_len) * num_pool_elems;
  47. pdev->me_buf.size = mc_uc_buf_len;
  48. if (!pdev->me_buf.vaddr) {
  49. qdf_spin_lock_bh(&pdev->tx_mutex);
  50. pdev->me_buf.vaddr = qdf_mem_malloc(pool_size);
  51. if (!pdev->me_buf.vaddr) {
  52. qdf_spin_unlock_bh(&pdev->tx_mutex);
  53. QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
  54. "Error allocating memory pool");
  55. return 1;
  56. }
  57. pdev->me_buf.buf_in_use = 0;
  58. pdev->me_buf.freelist =
  59. (struct dp_tx_me_buf_t *) pdev->me_buf.vaddr;
  60. /*
  61. * me_buf looks like this
  62. * |=======+==========================|
  63. * | ptr | Dst MAC |
  64. * |=======+==========================|
  65. */
  66. p = pdev->me_buf.freelist;
  67. for (i = 0; i < num_pool_elems-1; i++) {
  68. p->next = (struct dp_tx_me_buf_t *)
  69. ((char *)p + pdev->me_buf.size);
  70. p = p->next;
  71. }
  72. p->next = NULL;
  73. qdf_spin_unlock_bh(&pdev->tx_mutex);
  74. QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
  75. "ME Pool successfully initialized vaddr - %x \
  76. paddr - %x\n num_elems = %d buf_size - %d"
  77. "pool_size = %d",
  78. pdev->me_buf.vaddr,
  79. (unsigned int)pdev->me_buf.paddr,
  80. (unsigned int)num_pool_elems,
  81. (unsigned int)pdev->me_buf.size,
  82. (unsigned int)pool_size);
  83. } else {
  84. QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
  85. "ME Already Enabled!!");
  86. }
  87. return 0;
  88. }
  89. /**
  90. * dp_tx_me_alloc_descriptor():Allocate ME descriptor
  91. * @pdev_handle: DP PDEV handle
  92. *
  93. * Return:void
  94. */
  95. void
  96. dp_tx_me_alloc_descriptor(struct cdp_pdev *pdev_handle)
  97. {
  98. struct dp_pdev *pdev = (struct dp_pdev *) pdev_handle;
  99. if (qdf_atomic_read(&pdev->mc_num_vap_attached) == 0) {
  100. dp_tx_me_init(pdev);
  101. QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
  102. FL("Enable MCAST_TO_UCAST "));
  103. }
  104. qdf_atomic_inc(&pdev->mc_num_vap_attached);
  105. }
  106. /**
  107. * dp_tx_me_exit():Free memory and other cleanup required for
  108. * multicast unicast conversion
  109. * @pdev - DP_PDEV handle
  110. *
  111. * Return:void
  112. */
  113. void
  114. dp_tx_me_exit(struct dp_pdev *pdev)
  115. {
  116. /* Add flow control buffer count */
  117. uint32_t wait_time = ME_US_TO_SEC(ME_CLEAN_WAIT_TIMEOUT *
  118. ME_CLEAN_WAIT_COUNT);
  119. if (pdev->me_buf.vaddr) {
  120. uint16_t wait_cnt = 0;
  121. QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
  122. "Disabling Mcastenhance"
  123. "This may take some time");
  124. qdf_spin_lock_bh(&pdev->tx_mutex);
  125. while ((pdev->me_buf.buf_in_use > 0) &&
  126. (wait_cnt < ME_CLEAN_WAIT_COUNT)) {
  127. qdf_spin_unlock_bh(&pdev->tx_mutex);
  128. OS_SLEEP(ME_CLEAN_WAIT_TIMEOUT);
  129. wait_cnt++;
  130. qdf_spin_lock_bh(&pdev->tx_mutex);
  131. }
  132. if (pdev->me_buf.buf_in_use > 0) {
  133. QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
  134. "Tx-comp pending for %d "
  135. "ME frames after waiting %ds!!",
  136. pdev->me_buf.buf_in_use, wait_time);
  137. qdf_assert_always(0);
  138. }
  139. qdf_mem_free(pdev->me_buf.vaddr);
  140. pdev->me_buf.vaddr = NULL;
  141. pdev->me_buf.freelist = NULL;
  142. qdf_spin_unlock_bh(&pdev->tx_mutex);
  143. } else {
  144. QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
  145. "ME Already Disabled !!!");
  146. }
  147. }
  148. /* dp_tx_me_desc_flush() - release me resources associated to tx_desc
  149. * @pdev: DP_PDEV handle
  150. *
  151. * This function will free all outstanding ME buffer
  152. * for which either free during
  153. * completion didn't happened or completion is not
  154. * received.
  155. */
  156. void dp_tx_me_desc_flush(struct dp_pdev *pdev)
  157. {
  158. uint8_t i, num_pool;
  159. uint32_t j;
  160. uint32_t num_desc, page_id, offset;
  161. uint16_t num_desc_per_page;
  162. struct dp_soc *soc = pdev->soc;
  163. struct dp_tx_desc_s *tx_desc = NULL;
  164. struct dp_tx_desc_pool_s *tx_desc_pool = NULL;
  165. num_desc = wlan_cfg_get_num_tx_desc(soc->wlan_cfg_ctx);
  166. num_pool = wlan_cfg_get_num_tx_desc_pool(soc->wlan_cfg_ctx);
  167. for (i = 0; i < num_pool; i++) {
  168. tx_desc_pool = &soc->tx_desc[i];
  169. if (!tx_desc_pool || !tx_desc_pool->desc_pages.cacheable_pages)
  170. continue;
  171. num_desc_per_page =
  172. tx_desc_pool->desc_pages.num_element_per_page;
  173. for (j = 0; j < num_desc; j++) {
  174. page_id = j / num_desc_per_page;
  175. offset = j % num_desc_per_page;
  176. tx_desc = dp_tx_desc_find(soc, i, page_id, offset);
  177. if (tx_desc && (tx_desc->pdev == pdev) &&
  178. (tx_desc->flags & DP_TX_DESC_FLAG_ME) &&
  179. (tx_desc->flags & DP_TX_DESC_FLAG_ALLOCATED)) {
  180. dp_tx_comp_free_buf(soc, tx_desc);
  181. dp_tx_desc_release(tx_desc, i);
  182. }
  183. }
  184. }
  185. }
  186. /**
  187. * dp_tx_me_free_descriptor():free ME descriptor
  188. * @pdev_handle:DP_PDEV handle
  189. *
  190. * Return:void
  191. */
  192. void
  193. dp_tx_me_free_descriptor(struct cdp_pdev *pdev_handle)
  194. {
  195. struct dp_pdev *pdev = (struct dp_pdev *) pdev_handle;
  196. qdf_atomic_dec(&pdev->mc_num_vap_attached);
  197. if (atomic_read(&pdev->mc_num_vap_attached) == 0) {
  198. dp_tx_me_desc_flush(pdev);
  199. dp_tx_me_exit(pdev);
  200. QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
  201. "Disable MCAST_TO_UCAST");
  202. }
  203. }
  204. /**
  205. * dp_tx_prepare_send_me(): Call to the umac to get the list of clients
  206. * @vdev: DP VDEV handle
  207. * @nbuf: Multicast buffer
  208. *
  209. * Return: no of packets transmitted
  210. */
  211. QDF_STATUS
  212. dp_tx_prepare_send_me(struct dp_vdev *vdev, qdf_nbuf_t nbuf)
  213. {
  214. if (vdev->me_convert) {
  215. if (vdev->me_convert(vdev->osif_vdev, nbuf) > 0)
  216. return QDF_STATUS_SUCCESS;
  217. }
  218. return QDF_STATUS_E_FAILURE;
  219. }
  220. #endif