dp_hist.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  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_hw_tx_comp_dbucket: tx hw completion delay bucket in us
  79. * @index_0 = 0_250 us
  80. * @index_1 = 250_500 us
  81. * @index_2 = 500_750 us
  82. * @index_3 = 750_1000 us
  83. * @index_4 = 1000_1500 us
  84. * @index_5 = 1500_2000 us
  85. * @index_6 = 2000_2500 us
  86. * @index_7 = 2500_5000 us
  87. * @index_8 = 5000_6000 us
  88. * @index_9 = 6000_7000 us
  89. * @index_10 = 7000_8000 us
  90. * @index_11 = 8000_9000 us
  91. * @index_12 = 9000+ us
  92. */
  93. static uint16_t dp_hist_hw_tx_comp_dbucket[CDP_HIST_BUCKET_MAX] = {
  94. 0, 250, 500, 750, 1000, 1500, 2000, 2500, 5000, 6000, 7000, 8000, 9000};
  95. static const char *dp_hist_hw_tx_comp_dbucket_str[CDP_HIST_BUCKET_MAX + 1] = {
  96. "0 to 250 us", "250 to 500 us",
  97. "500 to 750 us", "750 to 1000 us",
  98. "1000 to 1500 us", "1500 to 2000 us",
  99. "2000 to 2500 us", "2500 to 5000 us",
  100. "5000 to 6000 us", "6000 to 7000 ms",
  101. "7000 to 8000 us", "8000 to 9000 us", "9000+ us"
  102. };
  103. const char *dp_hist_tx_hw_delay_str(uint8_t index)
  104. {
  105. if (index > CDP_HIST_BUCKET_MAX)
  106. return "Invalid index";
  107. return dp_hist_hw_tx_comp_dbucket_str[index];
  108. }
  109. /*
  110. * dp_hist_delay_percentile_dbucket: tx hw completion delay bucket in delay
  111. * bound percentile
  112. * @index_0 = 0_10
  113. * @index_1 = 10_20
  114. * @index_2 = 20_30
  115. * @index_3 = 30_40
  116. * @index_4 = 40_50
  117. * @index_5 = 50_60
  118. * @index_6 = 60_70
  119. * @index_7 = 70_80
  120. * @index_8 = 80_100
  121. * @index_9 = 90_100
  122. * @index_10 = 100_150
  123. * @index_11 = 150_200
  124. * @index_12 = 200+
  125. */
  126. static uint16_t dp_hist_delay_percentile_dbucket[CDP_HIST_BUCKET_MAX] = {
  127. 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 150, 200};
  128. static
  129. const char *dp_hist_delay_percentile_dbucket_str[CDP_HIST_BUCKET_MAX + 1] = {
  130. "0 to 10%", "10 to 20%",
  131. "20 to 30%", "30 to 40%",
  132. "40 to 50%", "50 to 60%",
  133. "60 to 70%", "70 to 80%",
  134. "80 to 90% ", "90 to 100%",
  135. "100 to 150% ", "150 to 200%", "200+%"
  136. };
  137. const char *dp_hist_delay_percentile_str(uint8_t index)
  138. {
  139. if (index > CDP_HIST_BUCKET_MAX)
  140. return "Invalid index";
  141. return dp_hist_delay_percentile_dbucket_str[index];
  142. }
  143. /*
  144. * dp_hist_find_bucket_idx: Find the bucket index
  145. * @bucket_array: Bucket array
  146. * @value: Frequency value
  147. *
  148. * Return: The bucket index
  149. */
  150. static int dp_hist_find_bucket_idx(int16_t *bucket_array, int value)
  151. {
  152. uint8_t idx = CDP_HIST_BUCKET_0;
  153. for (; idx < (CDP_HIST_BUCKET_MAX - 1); idx++) {
  154. if (value < bucket_array[idx + 1])
  155. break;
  156. }
  157. return idx;
  158. }
  159. /*
  160. * dp_hist_fill_buckets: Fill the histogram frequency buckets
  161. * @hist_bucket: Histogram bukcets
  162. * @value: Frequency value
  163. *
  164. * Return: void
  165. */
  166. static void dp_hist_fill_buckets(struct cdp_hist_bucket *hist_bucket, int value)
  167. {
  168. enum cdp_hist_types hist_type;
  169. int idx = CDP_HIST_BUCKET_MAX;
  170. if (qdf_unlikely(!hist_bucket))
  171. return;
  172. hist_type = hist_bucket->hist_type;
  173. /* Identify the bucket the bucket and update. */
  174. switch (hist_type) {
  175. case CDP_HIST_TYPE_SW_ENQEUE_DELAY:
  176. idx = dp_hist_find_bucket_idx(&dp_hist_sw_enq_dbucket[0],
  177. value);
  178. break;
  179. case CDP_HIST_TYPE_HW_COMP_DELAY:
  180. idx = dp_hist_find_bucket_idx(&dp_hist_fw2hw_dbucket[0],
  181. value);
  182. break;
  183. case CDP_HIST_TYPE_REAP_STACK:
  184. idx = dp_hist_find_bucket_idx(
  185. &dp_hist_reap2stack_bucket[0], value);
  186. break;
  187. case CDP_HIST_TYPE_HW_TX_COMP_DELAY:
  188. idx = dp_hist_find_bucket_idx(
  189. &dp_hist_hw_tx_comp_dbucket[0], value);
  190. break;
  191. case CDP_HIST_TYPE_DELAY_PERCENTILE:
  192. idx = dp_hist_find_bucket_idx(
  193. &dp_hist_delay_percentile_dbucket[0], value);
  194. break;
  195. default:
  196. break;
  197. }
  198. if (idx == CDP_HIST_BUCKET_MAX)
  199. return;
  200. hist_bucket->freq[idx]++;
  201. }
  202. /*
  203. * dp_hist_update_stats: Update histogram stats
  204. * @hist_stats: Hist stats object
  205. * @value: Delay value
  206. *
  207. * Return: void
  208. */
  209. void dp_hist_update_stats(struct cdp_hist_stats *hist_stats, int value)
  210. {
  211. if (qdf_unlikely(!hist_stats))
  212. return;
  213. /*
  214. * Fill the histogram buckets according to the delay
  215. */
  216. dp_hist_fill_buckets(&hist_stats->hist, value);
  217. /*
  218. * Compute the min, max and average. Average computed is weighted
  219. * average
  220. */
  221. if (value < hist_stats->min)
  222. hist_stats->min = value;
  223. if (value > hist_stats->max)
  224. hist_stats->max = value;
  225. if (qdf_unlikely(!hist_stats->avg))
  226. hist_stats->avg = value;
  227. else
  228. hist_stats->avg = (hist_stats->avg + value) / 2;
  229. }
  230. /*
  231. * dp_copy_hist_stats(): Copy the histogram stats
  232. * @src_hist_stats: Source histogram stats
  233. * @dst_hist_stats: Destination histogram stats
  234. *
  235. * Return: void
  236. */
  237. void dp_copy_hist_stats(struct cdp_hist_stats *src_hist_stats,
  238. struct cdp_hist_stats *dst_hist_stats)
  239. {
  240. uint8_t index;
  241. for (index = 0; index < CDP_HIST_BUCKET_MAX; index++)
  242. dst_hist_stats->hist.freq[index] =
  243. src_hist_stats->hist.freq[index];
  244. dst_hist_stats->min = src_hist_stats->min;
  245. dst_hist_stats->max = src_hist_stats->max;
  246. dst_hist_stats->avg = src_hist_stats->avg;
  247. }
  248. /*
  249. * dp_accumulate_hist_stats(): Accumulate the hist src to dst
  250. * @src_hist_stats: Source histogram stats
  251. * @dst_hist_stats: Destination histogram stats
  252. *
  253. * Return: void
  254. */
  255. void dp_accumulate_hist_stats(struct cdp_hist_stats *src_hist_stats,
  256. struct cdp_hist_stats *dst_hist_stats)
  257. {
  258. uint8_t index, hist_stats_valid = 0;
  259. for (index = 0; index < CDP_HIST_BUCKET_MAX; index++) {
  260. dst_hist_stats->hist.freq[index] +=
  261. src_hist_stats->hist.freq[index];
  262. if (src_hist_stats->hist.freq[index])
  263. hist_stats_valid = 1;
  264. }
  265. /*
  266. * If at least one hist-bucket has non-zero count,
  267. * proceed with the detailed calculation.
  268. */
  269. if (hist_stats_valid) {
  270. dst_hist_stats->min = QDF_MIN(src_hist_stats->min,
  271. dst_hist_stats->min);
  272. dst_hist_stats->max = QDF_MAX(src_hist_stats->max,
  273. dst_hist_stats->max);
  274. dst_hist_stats->avg = (src_hist_stats->avg +
  275. dst_hist_stats->avg) >> 1;
  276. }
  277. }
  278. /*
  279. * dp_hist_init(): Initialize the histogram object
  280. * @hist_stats: Hist stats object
  281. * @hist_type: Histogram type
  282. */
  283. void dp_hist_init(struct cdp_hist_stats *hist_stats,
  284. enum cdp_hist_types hist_type)
  285. {
  286. qdf_mem_zero(hist_stats, sizeof(*hist_stats));
  287. hist_stats->min = INT_MAX;
  288. hist_stats->hist.hist_type = hist_type;
  289. }