dp_hist.c 5.8 KB

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