dp_hist.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. /*
  2. * Copyright (c) 2020 The Linux Foundation. All rights reserved.
  3. * Copyright (c) 2022-2023 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. #ifndef WLAN_CONFIG_TX_DELAY
  24. /*
  25. * dp_hist_sw_enq_dbucket: Software enqueue delay bucket in ms
  26. * @index_0 = 0_1 ms
  27. * @index_1 = 1_2 ms
  28. * @index_2 = 2_3 ms
  29. * @index_3 = 3_4 ms
  30. * @index_4 = 4_5 ms
  31. * @index_5 = 5_6 ms
  32. * @index_6 = 6_7 ms
  33. * @index_7 = 7_8 ms
  34. * @index_8 = 8_9 ms
  35. * @index_9 = 9_10 ms
  36. * @index_10 = 10_11 ms
  37. * @index_11 = 11_12 ms
  38. * @index_12 = 12+ ms
  39. */
  40. static uint16_t dp_hist_sw_enq_dbucket[CDP_HIST_BUCKET_MAX] = {
  41. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
  42. /*
  43. * cdp_hist_fw2hw_dbucket: HW enqueue to Completion Delay
  44. * @index_0 = 0_10 ms
  45. * @index_1 = 10_20 ms
  46. * @index_2 = 20_30ms
  47. * @index_3 = 30_40 ms
  48. * @index_4 = 40_50 ms
  49. * @index_5 = 50_60 ms
  50. * @index_6 = 60_70 ms
  51. * @index_7 = 70_80 ms
  52. * @index_8 = 80_90 ms
  53. * @index_9 = 90_100 ms
  54. * @index_10 = 100_250 ms
  55. * @index_11 = 250_500 ms
  56. * @index_12 = 500+ ms
  57. */
  58. static uint16_t dp_hist_fw2hw_dbucket[CDP_HIST_BUCKET_MAX] = {
  59. 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 250, 500};
  60. #else
  61. /*
  62. * dp_hist_sw_enq_dbucket: Software enqueue delay bucket in us
  63. * @index_0 = 0_250 us
  64. * @index_1 = 250_500 us
  65. * @index_2 = 500_750 us
  66. * @index_3 = 750_1000 us
  67. * @index_4 = 1000_1500 us
  68. * @index_5 = 1500_2000 us
  69. * @index_6 = 2000_2500 us
  70. * @index_7 = 2500_5000 us
  71. * @index_8 = 5000_6000 us
  72. * @index_9 = 6000_7000 us
  73. * @index_10 = 7000_8000 us
  74. * @index_11 = 8000_9000 us
  75. * @index_12 = 9000+ us
  76. */
  77. static uint16_t dp_hist_sw_enq_dbucket[CDP_HIST_BUCKET_MAX] = {
  78. 0, 250, 500, 750, 1000, 1500, 2000, 2500, 5000, 6000, 7000, 8000, 9000};
  79. /*
  80. * cdp_hist_fw2hw_dbucket: HW enqueue to Completion Delay in us
  81. * @index_0 = 0_250 us
  82. * @index_1 = 250_500 us
  83. * @index_2 = 500_750 us
  84. * @index_3 = 750_1000 us
  85. * @index_4 = 1000_1500 us
  86. * @index_5 = 1500_2000 us
  87. * @index_6 = 2000_2500 us
  88. * @index_7 = 2500_5000 us
  89. * @index_8 = 5000_6000 us
  90. * @index_9 = 6000_7000 us
  91. * @index_10 = 7000_8000 us
  92. * @index_11 = 8000_9000 us
  93. * @index_12 = 9000+ us
  94. */
  95. static uint16_t dp_hist_fw2hw_dbucket[CDP_HIST_BUCKET_MAX] = {
  96. 0, 250, 500, 750, 1000, 1500, 2000, 2500, 5000, 6000, 7000, 8000, 9000};
  97. #endif
  98. /*
  99. * dp_hist_reap2stack_bucket: Reap to stack bucket
  100. * @index_0 = 0_5 ms
  101. * @index_1 = 5_10 ms
  102. * @index_2 = 10_15 ms
  103. * @index_3 = 15_20 ms
  104. * @index_4 = 20_25 ms
  105. * @index_5 = 25_30 ms
  106. * @index_6 = 30_35 ms
  107. * @index_7 = 35_40 ms
  108. * @index_8 = 40_45 ms
  109. * @index_9 = 46_50 ms
  110. * @index_10 = 51_55 ms
  111. * @index_11 = 56_60 ms
  112. * @index_12 = 60+ ms
  113. */
  114. static uint16_t dp_hist_reap2stack_bucket[CDP_HIST_BUCKET_MAX] = {
  115. 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60};
  116. /*
  117. * dp_hist_hw_tx_comp_dbucket: tx hw completion delay bucket in us
  118. * @index_0 = 0_250 us
  119. * @index_1 = 250_500 us
  120. * @index_2 = 500_750 us
  121. * @index_3 = 750_1000 us
  122. * @index_4 = 1000_1500 us
  123. * @index_5 = 1500_2000 us
  124. * @index_6 = 2000_2500 us
  125. * @index_7 = 2500_5000 us
  126. * @index_8 = 5000_6000 us
  127. * @index_9 = 6000_7000 us
  128. * @index_10 = 7000_8000 us
  129. * @index_11 = 8000_9000 us
  130. * @index_12 = 9000+ us
  131. */
  132. static uint16_t dp_hist_hw_tx_comp_dbucket[CDP_HIST_BUCKET_MAX] = {
  133. 0, 250, 500, 750, 1000, 1500, 2000, 2500, 5000, 6000, 7000, 8000, 9000};
  134. static const char *dp_hist_hw_tx_comp_dbucket_str[CDP_HIST_BUCKET_MAX + 1] = {
  135. "0 to 250 us", "250 to 500 us",
  136. "500 to 750 us", "750 to 1000 us",
  137. "1000 to 1500 us", "1500 to 2000 us",
  138. "2000 to 2500 us", "2500 to 5000 us",
  139. "5000 to 6000 us", "6000 to 7000 ms",
  140. "7000 to 8000 us", "8000 to 9000 us", "9000+ us"
  141. };
  142. const char *dp_hist_tx_hw_delay_str(uint8_t index)
  143. {
  144. if (index > CDP_HIST_BUCKET_MAX)
  145. return "Invalid index";
  146. return dp_hist_hw_tx_comp_dbucket_str[index];
  147. }
  148. /*
  149. * dp_hist_delay_percentile_dbucket: tx hw completion delay bucket in delay
  150. * bound percentile
  151. * @index_0 = 0_10
  152. * @index_1 = 10_20
  153. * @index_2 = 20_30
  154. * @index_3 = 30_40
  155. * @index_4 = 40_50
  156. * @index_5 = 50_60
  157. * @index_6 = 60_70
  158. * @index_7 = 70_80
  159. * @index_8 = 80_100
  160. * @index_9 = 90_100
  161. * @index_10 = 100_150
  162. * @index_11 = 150_200
  163. * @index_12 = 200+
  164. */
  165. static uint16_t dp_hist_delay_percentile_dbucket[CDP_HIST_BUCKET_MAX] = {
  166. 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 150, 200};
  167. static
  168. const char *dp_hist_delay_percentile_dbucket_str[CDP_HIST_BUCKET_MAX + 1] = {
  169. "0 to 10%", "10 to 20%",
  170. "20 to 30%", "30 to 40%",
  171. "40 to 50%", "50 to 60%",
  172. "60 to 70%", "70 to 80%",
  173. "80 to 90% ", "90 to 100%",
  174. "100 to 150% ", "150 to 200%", "200+%"
  175. };
  176. const char *dp_hist_delay_percentile_str(uint8_t index)
  177. {
  178. if (index > CDP_HIST_BUCKET_MAX)
  179. return "Invalid index";
  180. return dp_hist_delay_percentile_dbucket_str[index];
  181. }
  182. /**
  183. * dp_hist_find_bucket_idx() - Find the bucket index
  184. * @bucket_array: Bucket array
  185. * @value: Frequency value
  186. *
  187. * Return: The bucket index
  188. */
  189. static int dp_hist_find_bucket_idx(int16_t *bucket_array, int value)
  190. {
  191. uint8_t idx = CDP_HIST_BUCKET_0;
  192. for (; idx < (CDP_HIST_BUCKET_MAX - 1); idx++) {
  193. if (value < bucket_array[idx + 1])
  194. break;
  195. }
  196. return idx;
  197. }
  198. /**
  199. * dp_hist_fill_buckets() - Fill the histogram frequency buckets
  200. * @hist_bucket: Histogram bukcets
  201. * @value: Frequency value
  202. *
  203. * Return: void
  204. */
  205. static void dp_hist_fill_buckets(struct cdp_hist_bucket *hist_bucket, int value)
  206. {
  207. enum cdp_hist_types hist_type;
  208. int idx = CDP_HIST_BUCKET_MAX;
  209. if (qdf_unlikely(!hist_bucket))
  210. return;
  211. hist_type = hist_bucket->hist_type;
  212. /* Identify the bucket the bucket and update. */
  213. switch (hist_type) {
  214. case CDP_HIST_TYPE_SW_ENQEUE_DELAY:
  215. idx = dp_hist_find_bucket_idx(&dp_hist_sw_enq_dbucket[0],
  216. value);
  217. break;
  218. case CDP_HIST_TYPE_HW_COMP_DELAY:
  219. idx = dp_hist_find_bucket_idx(&dp_hist_fw2hw_dbucket[0],
  220. value);
  221. break;
  222. case CDP_HIST_TYPE_REAP_STACK:
  223. idx = dp_hist_find_bucket_idx(
  224. &dp_hist_reap2stack_bucket[0], value);
  225. break;
  226. case CDP_HIST_TYPE_HW_TX_COMP_DELAY:
  227. idx = dp_hist_find_bucket_idx(
  228. &dp_hist_hw_tx_comp_dbucket[0], value);
  229. break;
  230. case CDP_HIST_TYPE_DELAY_PERCENTILE:
  231. idx = dp_hist_find_bucket_idx(
  232. &dp_hist_delay_percentile_dbucket[0], value);
  233. break;
  234. default:
  235. break;
  236. }
  237. if (idx == CDP_HIST_BUCKET_MAX)
  238. return;
  239. hist_bucket->freq[idx]++;
  240. }
  241. void dp_hist_update_stats(struct cdp_hist_stats *hist_stats, int value)
  242. {
  243. if (qdf_unlikely(!hist_stats))
  244. return;
  245. /*
  246. * Fill the histogram buckets according to the delay
  247. */
  248. dp_hist_fill_buckets(&hist_stats->hist, value);
  249. /*
  250. * Compute the min, max and average. Average computed is weighted
  251. * average
  252. */
  253. if (value < hist_stats->min)
  254. hist_stats->min = value;
  255. if (value > hist_stats->max)
  256. hist_stats->max = value;
  257. if (qdf_unlikely(!hist_stats->avg))
  258. hist_stats->avg = value;
  259. else
  260. hist_stats->avg = (hist_stats->avg + value) / 2;
  261. }
  262. void dp_copy_hist_stats(struct cdp_hist_stats *src_hist_stats,
  263. struct cdp_hist_stats *dst_hist_stats)
  264. {
  265. uint8_t index;
  266. for (index = 0; index < CDP_HIST_BUCKET_MAX; index++)
  267. dst_hist_stats->hist.freq[index] =
  268. src_hist_stats->hist.freq[index];
  269. dst_hist_stats->min = src_hist_stats->min;
  270. dst_hist_stats->max = src_hist_stats->max;
  271. dst_hist_stats->avg = src_hist_stats->avg;
  272. }
  273. void dp_accumulate_hist_stats(struct cdp_hist_stats *src_hist_stats,
  274. struct cdp_hist_stats *dst_hist_stats)
  275. {
  276. uint8_t index, hist_stats_valid = 0;
  277. for (index = 0; index < CDP_HIST_BUCKET_MAX; index++) {
  278. dst_hist_stats->hist.freq[index] +=
  279. src_hist_stats->hist.freq[index];
  280. if (src_hist_stats->hist.freq[index])
  281. hist_stats_valid = 1;
  282. }
  283. /*
  284. * If at least one hist-bucket has non-zero count,
  285. * proceed with the detailed calculation.
  286. */
  287. if (hist_stats_valid) {
  288. dst_hist_stats->min = QDF_MIN(src_hist_stats->min,
  289. dst_hist_stats->min);
  290. dst_hist_stats->max = QDF_MAX(src_hist_stats->max,
  291. dst_hist_stats->max);
  292. dst_hist_stats->avg = (src_hist_stats->avg +
  293. dst_hist_stats->avg) >> 1;
  294. }
  295. }
  296. void dp_hist_init(struct cdp_hist_stats *hist_stats,
  297. enum cdp_hist_types hist_type)
  298. {
  299. qdf_mem_zero(hist_stats, sizeof(*hist_stats));
  300. hist_stats->min = INT_MAX;
  301. hist_stats->hist.hist_type = hist_type;
  302. }