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