dp_tx_me.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /*
  2. * Copyright (c) 2017 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 "dp_types.h"
  19. #include "qdf_nbuf.h"
  20. #include "qdf_atomic.h"
  21. #include "qdf_types.h"
  22. #include "dp_tx.h"
  23. #include "dp_tx_desc.h"
  24. #include "dp_internal.h"
  25. #ifdef ATH_SUPPORT_IQUE
  26. #define MAX_ME_BUF_CHUNK 1424
  27. #define ME_US_TO_SEC(_x) ((_x)/(1000 * 1000))
  28. #define ME_CLEAN_WAIT_TIMEOUT (200000) /*200ms*/
  29. #define ME_CLEAN_WAIT_COUNT 400
  30. /**
  31. * dp_tx_me_init():Initialize ME buffer ppol
  32. * @pdev: DP PDEV handle
  33. *
  34. * Return:0 on Succes 1 on failure
  35. */
  36. static inline uint16_t
  37. dp_tx_me_init(struct dp_pdev *pdev)
  38. {
  39. uint16_t i, mc_uc_buf_len, num_pool_elems;
  40. uint32_t pool_size;
  41. struct dp_tx_me_buf_t *p;
  42. mc_uc_buf_len = sizeof(struct dp_tx_me_buf_t);
  43. num_pool_elems = MAX_ME_BUF_CHUNK;
  44. /* Add flow control buffer count */
  45. pool_size = (mc_uc_buf_len) * num_pool_elems;
  46. pdev->me_buf.size = mc_uc_buf_len;
  47. if (pdev->me_buf.vaddr == NULL) {
  48. qdf_spin_lock_bh(&pdev->tx_mutex);
  49. pdev->me_buf.vaddr = qdf_mem_malloc(pool_size);
  50. if (pdev->me_buf.vaddr == NULL) {
  51. qdf_spin_unlock_bh(&pdev->tx_mutex);
  52. QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
  53. "Error allocating memory pool");
  54. return 1;
  55. }
  56. pdev->me_buf.buf_in_use = 0;
  57. pdev->me_buf.freelist =
  58. (struct dp_tx_me_buf_t *) pdev->me_buf.vaddr;
  59. /*
  60. * me_buf looks like this
  61. * |=======+==========================|
  62. * | ptr | Dst MAC |
  63. * |=======+==========================|
  64. */
  65. p = pdev->me_buf.freelist;
  66. for (i = 0; i < num_pool_elems-1; i++) {
  67. p->next = (struct dp_tx_me_buf_t *)
  68. ((char *)p + pdev->me_buf.size);
  69. p = p->next;
  70. }
  71. p->next = NULL;
  72. qdf_spin_unlock_bh(&pdev->tx_mutex);
  73. QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
  74. "ME Pool succesfully initialized vaddr - %x \
  75. paddr - %x\n num_elems = %d buf_size - %d"
  76. "pool_size = %d",
  77. pdev->me_buf.vaddr,
  78. (unsigned int)pdev->me_buf.paddr,
  79. (unsigned int)num_pool_elems,
  80. (unsigned int)pdev->me_buf.size,
  81. (unsigned int)pool_size);
  82. } else {
  83. QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
  84. "ME Already Enabled!!");
  85. }
  86. return 0;
  87. }
  88. /**
  89. * dp_tx_me_alloc_descriptor():Allocate ME descriptor
  90. * @pdev_handle: DP PDEV handle
  91. *
  92. * Return:void
  93. */
  94. void
  95. dp_tx_me_alloc_descriptor(struct cdp_pdev *pdev_handle)
  96. {
  97. struct dp_pdev *pdev = (struct dp_pdev *) pdev_handle;
  98. if (qdf_atomic_read(&pdev->mc_num_vap_attached) == 0) {
  99. dp_tx_me_init(pdev);
  100. QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
  101. FL("Enable MCAST_TO_UCAST "));
  102. }
  103. qdf_atomic_inc(&pdev->mc_num_vap_attached);
  104. }
  105. /**
  106. * dp_tx_me_exit():Free memory and other cleanup required for
  107. * multicast unicast conversion
  108. * @pdev - DP_PDEV handle
  109. *
  110. * Return:void
  111. */
  112. static inline void
  113. dp_tx_me_exit(struct dp_pdev *pdev)
  114. {
  115. /* Add flow control buffer count */
  116. uint32_t wait_time = ME_US_TO_SEC(ME_CLEAN_WAIT_TIMEOUT *
  117. ME_CLEAN_WAIT_COUNT);
  118. if (pdev->me_buf.vaddr) {
  119. uint16_t wait_cnt = 0;
  120. QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
  121. "Disabling Mcastenhance"
  122. "This may take some time");
  123. qdf_spin_lock_bh(&pdev->tx_mutex);
  124. while ((pdev->me_buf.buf_in_use > 0) &&
  125. (wait_cnt < ME_CLEAN_WAIT_COUNT)) {
  126. qdf_spin_unlock_bh(&pdev->tx_mutex);
  127. OS_SLEEP(ME_CLEAN_WAIT_TIMEOUT);
  128. wait_cnt++;
  129. qdf_spin_lock_bh(&pdev->tx_mutex);
  130. }
  131. if (pdev->me_buf.buf_in_use > 0) {
  132. QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
  133. "Tx-comp pending for %d "
  134. "ME frames after waiting %ds!!\n",
  135. pdev->me_buf.buf_in_use, wait_time);
  136. qdf_assert_always(0);
  137. }
  138. qdf_mem_free(pdev->me_buf.vaddr);
  139. pdev->me_buf.vaddr = NULL;
  140. pdev->me_buf.freelist = NULL;
  141. qdf_spin_unlock_bh(&pdev->tx_mutex);
  142. } else {
  143. QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
  144. "ME Already Disabled !!!");
  145. }
  146. }
  147. /**
  148. * dp_tx_me_free_descriptor():free ME descriptor
  149. * @pdev_handle:DP_PDEV handle
  150. *
  151. * Return:void
  152. */
  153. void
  154. dp_tx_me_free_descriptor(struct cdp_pdev *pdev_handle)
  155. {
  156. struct dp_pdev *pdev = (struct dp_pdev *) pdev_handle;
  157. qdf_atomic_dec(&pdev->mc_num_vap_attached);
  158. if (atomic_read(&pdev->mc_num_vap_attached) == 0) {
  159. dp_tx_me_exit(pdev);
  160. QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
  161. "Disable MCAST_TO_UCAST");
  162. }
  163. }
  164. /**
  165. * dp_tx_prepare_send_me(): Call to the umac to get the list of clients
  166. * @vdev: DP VDEV handle
  167. * @nbuf: Multicast buffer
  168. *
  169. * Return: no of packets transmitted
  170. */
  171. int32_t
  172. dp_tx_prepare_send_me(struct dp_vdev *vdev, qdf_nbuf_t nbuf)
  173. {
  174. if (vdev->me_convert)
  175. return vdev->me_convert(vdev->osif_vdev, nbuf);
  176. return 0;
  177. }
  178. #endif