dp_hist.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /*
  2. * Copyright (c) 2020 The Linux Foundation. All rights reserved.
  3. * Copyright (c) 2022 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. #include <qdf_util.h>
  20. #include <qdf_mem.h>
  21. #include <cdp_txrx_hist_struct.h>
  22. #include "dp_hist.h"
  23. /*
  24. * dp_hist_sw_enq_dbucket: Sofware enqueue delay bucket in ms
  25. * @index_0 = 0_1 ms
  26. * @index_1 = 1_2 ms
  27. * @index_2 = 2_3 ms
  28. * @index_3 = 3_4 ms
  29. * @index_4 = 4_5 ms
  30. * @index_5 = 5_6 ms
  31. * @index_6 = 6_7 ms
  32. * @index_7 = 7_8 ms
  33. * @index_8 = 8_9 ms
  34. * @index_9 = 9_10 ms
  35. * @index_10 = 10_11 ms
  36. * @index_11 = 11_12 ms
  37. * @index_12 = 12+ ms
  38. */
  39. static uint16_t dp_hist_sw_enq_dbucket[CDP_HIST_BUCKET_MAX] = {
  40. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
  41. /*
  42. * cdp_hist_fw2hw_dbucket: HW enqueue to Completion Delay
  43. * @index_0 = 0_10 ms
  44. * @index_1 = 10_20 ms
  45. * @index_2 = 20_30ms
  46. * @index_3 = 30_40 ms
  47. * @index_4 = 40_50 ms
  48. * @index_5 = 50_60 ms
  49. * @index_6 = 60_70 ms
  50. * @index_7 = 70_80 ms
  51. * @index_8 = 80_90 ms
  52. * @index_9 = 90_100 ms
  53. * @index_10 = 100_250 ms
  54. * @index_11 = 250_500 ms
  55. * @index_12 = 500+ ms
  56. */
  57. static uint16_t dp_hist_fw2hw_dbucket[CDP_HIST_BUCKET_MAX] = {
  58. 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 250, 500};
  59. /*
  60. * dp_hist_reap2stack_bucket: Reap to stack bucket
  61. * @index_0 = 0_5 ms
  62. * @index_1 = 5_10 ms
  63. * @index_2 = 10_15 ms
  64. * @index_3 = 15_20 ms
  65. * @index_4 = 20_25 ms
  66. * @index_5 = 25_30 ms
  67. * @index_6 = 30_35 ms
  68. * @index_7 = 35_40 ms
  69. * @index_8 = 40_45 ms
  70. * @index_9 = 46_50 ms
  71. * @index_10 = 51_55 ms
  72. * @index_11 = 56_60 ms
  73. * @index_12 = 60+ ms
  74. */
  75. static uint16_t dp_hist_reap2stack_bucket[CDP_HIST_BUCKET_MAX] = {
  76. 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60};
  77. /*
  78. * dp_hist_find_bucket_idx: Find the bucket index
  79. * @bucket_array: Bucket array
  80. * @value: Frequency value
  81. *
  82. * Return: The bucket index
  83. */
  84. static int dp_hist_find_bucket_idx(int16_t *bucket_array, int value)
  85. {
  86. uint8_t idx = CDP_HIST_BUCKET_0;
  87. for (; idx < (CDP_HIST_BUCKET_MAX - 1); idx++) {
  88. if (value < bucket_array[idx + 1])
  89. break;
  90. }
  91. return idx;
  92. }
  93. /*
  94. * dp_hist_fill_buckets: Fill the histogram frequency buckets
  95. * @hist_bucket: Histogram bukcets
  96. * @value: Frequency value
  97. *
  98. * Return: void
  99. */
  100. static void dp_hist_fill_buckets(struct cdp_hist_bucket *hist_bucket, int value)
  101. {
  102. enum cdp_hist_types hist_type;
  103. int idx = CDP_HIST_BUCKET_MAX;
  104. if (qdf_unlikely(!hist_bucket))
  105. return;
  106. hist_type = hist_bucket->hist_type;
  107. /* Identify the bucket the bucket and update. */
  108. switch (hist_type) {
  109. case CDP_HIST_TYPE_SW_ENQEUE_DELAY:
  110. idx = dp_hist_find_bucket_idx(&dp_hist_sw_enq_dbucket[0],
  111. value);
  112. break;
  113. case CDP_HIST_TYPE_HW_COMP_DELAY:
  114. idx = dp_hist_find_bucket_idx(&dp_hist_fw2hw_dbucket[0],
  115. value);
  116. break;
  117. case CDP_HIST_TYPE_REAP_STACK:
  118. idx = dp_hist_find_bucket_idx(
  119. &dp_hist_reap2stack_bucket[0], value);
  120. break;
  121. default:
  122. break;
  123. }
  124. if (idx == CDP_HIST_BUCKET_MAX)
  125. return;
  126. hist_bucket->freq[idx]++;
  127. }
  128. /*
  129. * dp_hist_update_stats: Update histogram stats
  130. * @hist_stats: Hist stats object
  131. * @value: Delay value
  132. *
  133. * Return: void
  134. */
  135. void dp_hist_update_stats(struct cdp_hist_stats *hist_stats, int value)
  136. {
  137. if (qdf_unlikely(!hist_stats))
  138. return;
  139. /*
  140. * Fill the histogram buckets according to the delay
  141. */
  142. dp_hist_fill_buckets(&hist_stats->hist, value);
  143. /*
  144. * Compute the min, max and average. Average computed is weighted
  145. * average
  146. */
  147. if (value < hist_stats->min)
  148. hist_stats->min = value;
  149. if (value > hist_stats->max)
  150. hist_stats->max = value;
  151. if (qdf_unlikely(!hist_stats->avg))
  152. hist_stats->avg = value;
  153. else
  154. hist_stats->avg = (hist_stats->avg + value) / 2;
  155. }
  156. /*
  157. * dp_copy_hist_stats(): Copy the histogram stats
  158. * @src_hist_stats: Source histogram stats
  159. * @dst_hist_stats: Destination histogram stats
  160. *
  161. * Return: void
  162. */
  163. void dp_copy_hist_stats(struct cdp_hist_stats *src_hist_stats,
  164. struct cdp_hist_stats *dst_hist_stats)
  165. {
  166. uint8_t index;
  167. for (index = 0; index < CDP_HIST_BUCKET_MAX; index++)
  168. dst_hist_stats->hist.freq[index] =
  169. src_hist_stats->hist.freq[index];
  170. dst_hist_stats->min = src_hist_stats->min;
  171. dst_hist_stats->max = src_hist_stats->max;
  172. dst_hist_stats->avg = src_hist_stats->avg;
  173. }
  174. /*
  175. * dp_accumulate_hist_stats(): Accumulate the hist src to dst
  176. * @src_hist_stats: Source histogram stats
  177. * @dst_hist_stats: Destination histogram stats
  178. *
  179. * Return: void
  180. */
  181. void dp_accumulate_hist_stats(struct cdp_hist_stats *src_hist_stats,
  182. struct cdp_hist_stats *dst_hist_stats)
  183. {
  184. uint8_t index, hist_stats_valid = 0;
  185. for (index = 0; index < CDP_HIST_BUCKET_MAX; index++) {
  186. dst_hist_stats->hist.freq[index] +=
  187. src_hist_stats->hist.freq[index];
  188. if (src_hist_stats->hist.freq[index])
  189. hist_stats_valid = 1;
  190. }
  191. /*
  192. * If at least one hist-bucket has non-zero count,
  193. * proceed with the detailed calculation.
  194. */
  195. if (hist_stats_valid) {
  196. dst_hist_stats->min = QDF_MIN(src_hist_stats->min,
  197. dst_hist_stats->min);
  198. dst_hist_stats->max = QDF_MAX(src_hist_stats->max,
  199. dst_hist_stats->max);
  200. dst_hist_stats->avg = (src_hist_stats->avg +
  201. dst_hist_stats->avg) >> 1;
  202. }
  203. }
  204. /*
  205. * dp_hist_init(): Initialize the histogram object
  206. * @hist_stats: Hist stats object
  207. * @hist_type: Histogram type
  208. */
  209. void dp_hist_init(struct cdp_hist_stats *hist_stats,
  210. enum cdp_hist_types hist_type)
  211. {
  212. qdf_mem_zero(hist_stats, sizeof(*hist_stats));
  213. hist_stats->min = INT_MAX;
  214. hist_stats->hist.hist_type = hist_type;
  215. }