dp_tx_me.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. * Copyright (c) 2017-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. #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 == NULL) {
  49. qdf_spin_lock_bh(&pdev->tx_mutex);
  50. pdev->me_buf.vaddr = qdf_mem_malloc(pool_size);
  51. if (pdev->me_buf.vaddr == NULL) {
  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. /**
  149. * dp_tx_me_free_descriptor():free ME descriptor
  150. * @pdev_handle:DP_PDEV handle
  151. *
  152. * Return:void
  153. */
  154. void
  155. dp_tx_me_free_descriptor(struct cdp_pdev *pdev_handle)
  156. {
  157. struct dp_pdev *pdev = (struct dp_pdev *) pdev_handle;
  158. qdf_atomic_dec(&pdev->mc_num_vap_attached);
  159. if (atomic_read(&pdev->mc_num_vap_attached) == 0) {
  160. dp_tx_me_exit(pdev);
  161. QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
  162. "Disable MCAST_TO_UCAST");
  163. }
  164. }
  165. /**
  166. * dp_tx_prepare_send_me(): Call to the umac to get the list of clients
  167. * @vdev: DP VDEV handle
  168. * @nbuf: Multicast buffer
  169. *
  170. * Return: no of packets transmitted
  171. */
  172. QDF_STATUS
  173. dp_tx_prepare_send_me(struct dp_vdev *vdev, qdf_nbuf_t nbuf)
  174. {
  175. if (vdev->me_convert) {
  176. if (vdev->me_convert(vdev->osif_vdev, nbuf) > 0)
  177. return QDF_STATUS_SUCCESS;
  178. }
  179. return QDF_STATUS_E_FAILURE;
  180. }
  181. #endif