1 /*
2 * Copyright (c) 2012-2019 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
20 /**
21 * @file htt_fw_stats.c
22 * @brief Provide functions to process FW status retrieved from FW.
23 */
24
25 #include <htc_api.h> /* HTC_PACKET */
26 #include <htt.h> /* HTT_T2H_MSG_TYPE, etc. */
27 #include <qdf_nbuf.h> /* qdf_nbuf_t */
28 #include <qdf_mem.h> /* qdf_mem_set */
29 #include <ol_fw_tx_dbg.h> /* ol_fw_tx_dbg_ppdu_base */
30
31 #include <ol_htt_rx_api.h>
32 #include <ol_txrx_htt_api.h> /* htt_tx_status */
33
34 #include <htt_internal.h>
35
36 #include <wlan_defs.h>
37
38 static char *bw_str_arr[] = {"20MHz", "40MHz", "80MHz", "160MHz"};
39
40 /*
41 * Defined the macro tx_rate_stats_print_cmn()
42 * so that this could be used in both
43 * htt_t2h_stats_tx_rate_stats_print() &
44 * htt_t2h_stats_tx_rate_stats_print_v2().
45 * Each of these functions take a different structure as argument,
46 * but with common fields in the structures--so using a macro
47 * to bypass the strong type-checking of a function seems a simple
48 * trick to use to avoid the code duplication.
49 */
50 #define tx_rate_stats_print_cmn(_tx_rate_info, _concise) \
51 do { \
52 qdf_nofl_info("TX Rate Info:"); \
53 \
54 /* MCS */ \
55 qdf_nofl_info("%s: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d",\
56 "MCS counts (0..9)", \
57 _tx_rate_info->mcs[0], \
58 _tx_rate_info->mcs[1], \
59 _tx_rate_info->mcs[2], \
60 _tx_rate_info->mcs[3], \
61 _tx_rate_info->mcs[4], \
62 _tx_rate_info->mcs[5], \
63 _tx_rate_info->mcs[6], \
64 _tx_rate_info->mcs[7], \
65 _tx_rate_info->mcs[8], \
66 _tx_rate_info->mcs[9]); \
67 \
68 /* SGI */ \
69 qdf_nofl_info("%s: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d",\
70 "SGI counts (0..9)", \
71 _tx_rate_info->sgi[0], \
72 _tx_rate_info->sgi[1], \
73 _tx_rate_info->sgi[2], \
74 _tx_rate_info->sgi[3], \
75 _tx_rate_info->sgi[4], \
76 _tx_rate_info->sgi[5], \
77 _tx_rate_info->sgi[6], \
78 _tx_rate_info->sgi[7], \
79 _tx_rate_info->sgi[8], \
80 _tx_rate_info->sgi[9]); \
81 \
82 /* NSS */ \
83 qdf_nofl_info("NSS counts: 1x1 %d, 2x2 %d, 3x3 %d", \
84 _tx_rate_info->nss[0], \
85 _tx_rate_info->nss[1], _tx_rate_info->nss[2]);\
86 \
87 /* BW */ \
88 if (ARRAY_SIZE(_tx_rate_info->bw) == 3) \
89 qdf_nofl_info("BW counts: %s %d, %s %d, %s %d", \
90 bw_str_arr[0], _tx_rate_info->bw[0], \
91 bw_str_arr[1], _tx_rate_info->bw[1], \
92 bw_str_arr[2], _tx_rate_info->bw[2]); \
93 else if (ARRAY_SIZE(_tx_rate_info->bw) == 4) \
94 qdf_nofl_info("BW counts: %s %d, %s %d, %s %d, %s %d", \
95 bw_str_arr[0], _tx_rate_info->bw[0], \
96 bw_str_arr[1], _tx_rate_info->bw[1], \
97 bw_str_arr[2], _tx_rate_info->bw[2], \
98 bw_str_arr[3], _tx_rate_info->bw[3]); \
99 \
100 \
101 /* Preamble */ \
102 qdf_nofl_info("Preamble (O C H V) counts: %d, %d, %d, %d",\
103 _tx_rate_info->pream[0], \
104 _tx_rate_info->pream[1], \
105 _tx_rate_info->pream[2], \
106 _tx_rate_info->pream[3]); \
107 \
108 /* STBC rate counts */ \
109 qdf_nofl_info("%s: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d",\
110 "STBC rate counts (0..9)", \
111 _tx_rate_info->stbc[0], \
112 _tx_rate_info->stbc[1], \
113 _tx_rate_info->stbc[2], \
114 _tx_rate_info->stbc[3], \
115 _tx_rate_info->stbc[4], \
116 _tx_rate_info->stbc[5], \
117 _tx_rate_info->stbc[6], \
118 _tx_rate_info->stbc[7], \
119 _tx_rate_info->stbc[8], \
120 _tx_rate_info->stbc[9]); \
121 \
122 /* LDPC and TxBF counts */ \
123 qdf_nofl_info("LDPC Counts: %d", _tx_rate_info->ldpc);\
124 qdf_nofl_info("RTS Counts: %d", _tx_rate_info->rts_cnt);\
125 /* RSSI Values for last ack frames */ \
126 qdf_nofl_info("Ack RSSI: %d", _tx_rate_info->ack_rssi);\
127 } while (0)
128
htt_t2h_stats_tx_rate_stats_print(wlan_dbg_tx_rate_info_t * tx_rate_info,int concise)129 static void htt_t2h_stats_tx_rate_stats_print(wlan_dbg_tx_rate_info_t *
130 tx_rate_info, int concise)
131 {
132 tx_rate_stats_print_cmn(tx_rate_info, concise);
133 }
134
htt_t2h_stats_tx_rate_stats_print_v2(wlan_dbg_tx_rate_info_v2_t * tx_rate_info,int concise)135 static void htt_t2h_stats_tx_rate_stats_print_v2(wlan_dbg_tx_rate_info_v2_t *
136 tx_rate_info, int concise)
137 {
138 tx_rate_stats_print_cmn(tx_rate_info, concise);
139 }
140
141 /*
142 * Defined the macro rx_rate_stats_print_cmn()
143 * so that this could be used in both
144 * htt_t2h_stats_rx_rate_stats_print() &
145 * htt_t2h_stats_rx_rate_stats_print_v2().
146 * Each of these functions take a different structure as argument,
147 * but with common fields in the structures -- so using a macro
148 * to bypass the strong type-checking of a function seems a simple
149 * trick to use to avoid the code duplication.
150 */
151 #define rx_rate_stats_print_cmn(_rx_phy_info, _concise) \
152 do { \
153 qdf_nofl_info("RX Rate Info:"); \
154 \
155 /* MCS */ \
156 qdf_nofl_info("%s: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d",\
157 "MCS counts (0..9)", \
158 _rx_phy_info->mcs[0], \
159 _rx_phy_info->mcs[1], \
160 _rx_phy_info->mcs[2], \
161 _rx_phy_info->mcs[3], \
162 _rx_phy_info->mcs[4], \
163 _rx_phy_info->mcs[5], \
164 _rx_phy_info->mcs[6], \
165 _rx_phy_info->mcs[7], \
166 _rx_phy_info->mcs[8], \
167 _rx_phy_info->mcs[9]); \
168 \
169 /* SGI */ \
170 qdf_nofl_info("%s: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d",\
171 "SGI counts (0..9)", \
172 _rx_phy_info->sgi[0], \
173 _rx_phy_info->sgi[1], \
174 _rx_phy_info->sgi[2], \
175 _rx_phy_info->sgi[3], \
176 _rx_phy_info->sgi[4], \
177 _rx_phy_info->sgi[5], \
178 _rx_phy_info->sgi[6], \
179 _rx_phy_info->sgi[7], \
180 _rx_phy_info->sgi[8], \
181 _rx_phy_info->sgi[9]); \
182 \
183 /*
184 * NSS \
185 * nss[0] just holds the count of non-stbc frames that were \
186 * sent at 1x1 rates and nsts holds the count of frames sent \
187 * with stbc. \
188 * It was decided to not include PPDUs sent w/ STBC in nss[0] \
189 * since it would be easier to change the value that needs to \
190 * be printed (from stbc+non-stbc count to only non-stbc count)\
191 * if needed in the future. Hence the addition in the host code\
192 * at this line.
193 */ \
194 qdf_nofl_info("NSS counts: 1x1 %d, 2x2 %d, 3x3 %d, 4x4 %d",\
195 _rx_phy_info->nss[0] + _rx_phy_info->nsts,\
196 _rx_phy_info->nss[1], \
197 _rx_phy_info->nss[2], \
198 _rx_phy_info->nss[3]); \
199 \
200 /* NSTS */ \
201 qdf_nofl_info("NSTS count: %d", _rx_phy_info->nsts); \
202 \
203 /* BW */ \
204 if (ARRAY_SIZE(_rx_phy_info->bw) == 3) \
205 qdf_nofl_info("BW counts: %s %d, %s %d, %s %d", \
206 bw_str_arr[0], _rx_phy_info->bw[0], \
207 bw_str_arr[1], _rx_phy_info->bw[1], \
208 bw_str_arr[2], _rx_phy_info->bw[2]); \
209 else if (ARRAY_SIZE(_rx_phy_info->bw) == 4) \
210 qdf_nofl_info("BW counts: %s %d, %s %d, %s %d, %s %d", \
211 bw_str_arr[0], _rx_phy_info->bw[0], \
212 bw_str_arr[1], _rx_phy_info->bw[1], \
213 bw_str_arr[2], _rx_phy_info->bw[2], \
214 bw_str_arr[3], _rx_phy_info->bw[3]); \
215 \
216 /* Preamble */ \
217 qdf_nofl_info("Preamble counts: %d, %d, %d, %d, %d, %d",\
218 _rx_phy_info->pream[0], \
219 _rx_phy_info->pream[1], \
220 _rx_phy_info->pream[2], \
221 _rx_phy_info->pream[3], \
222 _rx_phy_info->pream[4], \
223 _rx_phy_info->pream[5]); \
224 \
225 /* STBC rate counts */ \
226 qdf_nofl_info("%s: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d",\
227 "STBC rate counts (0..9)", \
228 _rx_phy_info->stbc[0], \
229 _rx_phy_info->stbc[1], \
230 _rx_phy_info->stbc[2], \
231 _rx_phy_info->stbc[3], \
232 _rx_phy_info->stbc[4], \
233 _rx_phy_info->stbc[5], \
234 _rx_phy_info->stbc[6], \
235 _rx_phy_info->stbc[7], \
236 _rx_phy_info->stbc[8], \
237 _rx_phy_info->stbc[9]); \
238 \
239 /* LDPC and TxBF counts */ \
240 qdf_nofl_info("LDPC TXBF Counts: %d, %d", \
241 _rx_phy_info->ldpc, _rx_phy_info->txbf);\
242 /* RSSI Values for last received frames */ \
243 qdf_nofl_info("RSSI (data, mgmt): %d, %d", _rx_phy_info->data_rssi,\
244 _rx_phy_info->mgmt_rssi); \
245 \
246 qdf_nofl_info("RSSI Chain 0 (0x%02x 0x%02x 0x%02x 0x%02x)",\
247 ((_rx_phy_info->rssi_chain0 >> 24) & 0xff),\
248 ((_rx_phy_info->rssi_chain0 >> 16) & 0xff),\
249 ((_rx_phy_info->rssi_chain0 >> 8) & 0xff),\
250 ((_rx_phy_info->rssi_chain0 >> 0) & 0xff));\
251 \
252 qdf_nofl_info("RSSI Chain 1 (0x%02x 0x%02x 0x%02x 0x%02x)",\
253 ((_rx_phy_info->rssi_chain1 >> 24) & 0xff),\
254 ((_rx_phy_info->rssi_chain1 >> 16) & 0xff),\
255 ((_rx_phy_info->rssi_chain1 >> 8) & 0xff),\
256 ((_rx_phy_info->rssi_chain1 >> 0) & 0xff));\
257 \
258 qdf_nofl_info("RSSI Chain 2 (0x%02x 0x%02x 0x%02x 0x%02x)",\
259 ((_rx_phy_info->rssi_chain2 >> 24) & 0xff),\
260 ((_rx_phy_info->rssi_chain2 >> 16) & 0xff),\
261 ((_rx_phy_info->rssi_chain2 >> 8) & 0xff),\
262 ((_rx_phy_info->rssi_chain2 >> 0) & 0xff));\
263 } while (0)
264
htt_t2h_stats_rx_rate_stats_print(wlan_dbg_rx_rate_info_t * rx_phy_info,int concise)265 static void htt_t2h_stats_rx_rate_stats_print(wlan_dbg_rx_rate_info_t *
266 rx_phy_info, int concise)
267 {
268 rx_rate_stats_print_cmn(rx_phy_info, concise);
269 }
270
htt_t2h_stats_rx_rate_stats_print_v2(wlan_dbg_rx_rate_info_v2_t * rx_phy_info,int concise)271 static void htt_t2h_stats_rx_rate_stats_print_v2(wlan_dbg_rx_rate_info_v2_t *
272 rx_phy_info, int concise)
273 {
274 rx_rate_stats_print_cmn(rx_phy_info, concise);
275 }
276
277 static void
htt_t2h_stats_pdev_stats_print(struct wlan_dbg_stats * wlan_pdev_stats,int concise)278 htt_t2h_stats_pdev_stats_print(struct wlan_dbg_stats *wlan_pdev_stats,
279 int concise)
280 {
281 struct wlan_dbg_tx_stats *tx = &wlan_pdev_stats->tx;
282 struct wlan_dbg_rx_stats *rx = &wlan_pdev_stats->rx;
283
284 qdf_nofl_info("WAL Pdev stats:");
285 qdf_nofl_info("### Tx ###");
286
287 /* Num HTT cookies queued to dispatch list */
288 qdf_nofl_info("comp_queued :%d", tx->comp_queued);
289 /* Num HTT cookies dispatched */
290 qdf_nofl_info("comp_delivered :%d", tx->comp_delivered);
291 /* Num MSDU queued to WAL */
292 qdf_nofl_info("msdu_enqued :%d", tx->msdu_enqued);
293 /* Num MPDU queued to WAL */
294 qdf_nofl_info("mpdu_enqued :%d", tx->mpdu_enqued);
295 /* Num MSDUs dropped by WMM limit */
296 qdf_nofl_info("wmm_drop :%d", tx->wmm_drop);
297 /* Num Local frames queued */
298 qdf_nofl_info("local_enqued :%d", tx->local_enqued);
299 /* Num Local frames done */
300 qdf_nofl_info("local_freed :%d", tx->local_freed);
301 /* Num queued to HW */
302 qdf_nofl_info("hw_queued :%d", tx->hw_queued);
303 /* Num PPDU reaped from HW */
304 qdf_nofl_info("hw_reaped :%d", tx->hw_reaped);
305 /* Num underruns */
306 qdf_nofl_info("mac underrun :%d", tx->underrun);
307 /* Num underruns */
308 qdf_nofl_info("phy underrun :%d", tx->phy_underrun);
309 /* Num PPDUs cleaned up in TX abort */
310 qdf_nofl_info("tx_abort :%d", tx->tx_abort);
311 /* Num MPDUs requed by SW */
312 qdf_nofl_info("mpdus_requed :%d", tx->mpdus_requed);
313 /* Excessive retries */
314 #if defined(AR900B)
315 qdf_nofl_info("excess retries :%d", tx->tx_xretry);
316 #endif
317 /* last data rate */
318 qdf_nofl_info("last rc :%d", tx->data_rc);
319 /* scheduler self triggers */
320 qdf_nofl_info("sched self trig :%d", tx->self_triggers);
321 /* SW retry failures */
322 qdf_nofl_info("ampdu retry failed:%d", tx->sw_retry_failure);
323 /* illegal phy rate errors */
324 qdf_nofl_info("illegal rate errs :%d", tx->illgl_rate_phy_err);
325 /* pdev continuous excessive retries */
326 qdf_nofl_info("pdev cont xretry :%d", tx->pdev_cont_xretry);
327 /* pdev continuous excessive retries */
328 qdf_nofl_info("pdev tx timeout :%d", tx->pdev_tx_timeout);
329 /* pdev resets */
330 qdf_nofl_info("pdev resets :%d", tx->pdev_resets);
331 /* PPDU > txop duration */
332 qdf_nofl_info("ppdu txop ovf :%d", tx->txop_ovf);
333 #if defined(AR900B)
334 qdf_nofl_info("seq_posted :%d", tx->seq_posted);
335 qdf_nofl_info("seq_failed_queueing :%d", tx->seq_failed_queueing);
336 qdf_nofl_info("seq_completed :%d", tx->seq_completed);
337 qdf_nofl_info("seq_restarted :%d", tx->seq_restarted);
338 qdf_nofl_info("mu_seq_posted :%d", tx->mu_seq_posted);
339 qdf_nofl_info("mpdus_sw_flush :%d", tx->mpdus_sw_flush);
340 qdf_nofl_info("mpdus_hw_filter :%d", tx->mpdus_hw_filter);
341 qdf_nofl_info("mpdus_truncated :%d", tx->mpdus_truncated);
342 qdf_nofl_info("mpdus_ack_failed :%d", tx->mpdus_ack_failed);
343 qdf_nofl_info("mpdus_expired :%d", tx->mpdus_expired);
344 #endif
345
346 qdf_nofl_info("### Rx ###");
347 /* Cnts any change in ring routing mid-ppdu */
348 qdf_nofl_info("ppdu_route_change :%d", rx->mid_ppdu_route_change);
349 /* Total number of statuses processed */
350 qdf_nofl_info("status_rcvd :%d", rx->status_rcvd);
351 /* Extra frags on rings 0-3 */
352 qdf_nofl_info("r0_frags :%d", rx->r0_frags);
353 qdf_nofl_info("r1_frags :%d", rx->r1_frags);
354 qdf_nofl_info("r2_frags :%d", rx->r2_frags);
355 qdf_nofl_info("r3_frags :%d", rx->r3_frags);
356 /* MSDUs / MPDUs delivered to HTT */
357 qdf_nofl_info("htt_msdus :%d", rx->htt_msdus);
358 qdf_nofl_info("htt_mpdus :%d", rx->htt_mpdus);
359 /* MSDUs / MPDUs delivered to local stack */
360 qdf_nofl_info("loc_msdus :%d", rx->loc_msdus);
361 qdf_nofl_info("loc_mpdus :%d", rx->loc_mpdus);
362 /* AMSDUs that have more MSDUs than the status ring size */
363 qdf_nofl_info("oversize_amsdu :%d", rx->oversize_amsdu);
364 /* Number of PHY errors */
365 qdf_nofl_info("phy_errs :%d", rx->phy_errs);
366 /* Number of PHY errors dropped */
367 qdf_nofl_info("phy_errs dropped :%d", rx->phy_err_drop);
368 /* Number of mpdu errors - FCS, MIC, ENC etc. */
369 qdf_nofl_info("mpdu_errs :%d", rx->mpdu_errs);
370 #if defined(AR900B)
371 qdf_nofl_info("rx_ovfl_errs :%d", rx->rx_ovfl_errs);
372 #endif
373
374 }
375
376 static void
htt_t2h_stats_rx_reorder_stats_print(struct rx_reorder_stats * stats_ptr,int concise)377 htt_t2h_stats_rx_reorder_stats_print(struct rx_reorder_stats *stats_ptr,
378 int concise)
379 {
380 qdf_nofl_info("Rx reorder statistics:");
381 qdf_nofl_info(" %u non-QoS frames received",
382 stats_ptr->deliver_non_qos);
383 qdf_nofl_info(" %u frames received in-order",
384 stats_ptr->deliver_in_order);
385 qdf_nofl_info(" %u frames flushed due to timeout",
386 stats_ptr->deliver_flush_timeout);
387 qdf_nofl_info(" %u frames flushed due to moving out of window",
388 stats_ptr->deliver_flush_oow);
389 qdf_nofl_info(" %u frames flushed due to receiving DELBA",
390 stats_ptr->deliver_flush_delba);
391 qdf_nofl_info(" %u frames discarded due to FCS error",
392 stats_ptr->fcs_error);
393 qdf_nofl_info(" %u frames discarded due to invalid peer",
394 stats_ptr->invalid_peer);
395 qdf_nofl_info
396 (" %u frames discarded due to duplication (non aggregation)",
397 stats_ptr->dup_non_aggr);
398 qdf_nofl_info(" %u frames discarded due to duplication in reorder queue",
399 stats_ptr->dup_in_reorder);
400 qdf_nofl_info(" %u frames discarded due to processed before",
401 stats_ptr->dup_past);
402 qdf_nofl_info(" %u times reorder timeout happened",
403 stats_ptr->reorder_timeout);
404 qdf_nofl_info(" %u times incorrect bar received",
405 stats_ptr->invalid_bar_ssn);
406 qdf_nofl_info(" %u times bar ssn reset happened",
407 stats_ptr->ssn_reset);
408 qdf_nofl_info(" %u times flushed due to peer delete",
409 stats_ptr->deliver_flush_delpeer);
410 qdf_nofl_info(" %u times flushed due to offload",
411 stats_ptr->deliver_flush_offload);
412 qdf_nofl_info(" %u times flushed due to ouf of buffer",
413 stats_ptr->deliver_flush_oob);
414 qdf_nofl_info(" %u MPDU's dropped due to PN check fail",
415 stats_ptr->pn_fail);
416 qdf_nofl_info(" %u MPDU's dropped due to lack of memory",
417 stats_ptr->store_fail);
418 qdf_nofl_info(" %u times tid pool alloc succeeded",
419 stats_ptr->tid_pool_alloc_succ);
420 qdf_nofl_info(" %u times MPDU pool alloc succeeded",
421 stats_ptr->mpdu_pool_alloc_succ);
422 qdf_nofl_info(" %u times MSDU pool alloc succeeded",
423 stats_ptr->msdu_pool_alloc_succ);
424 qdf_nofl_info(" %u times tid pool alloc failed",
425 stats_ptr->tid_pool_alloc_fail);
426 qdf_nofl_info(" %u times MPDU pool alloc failed",
427 stats_ptr->mpdu_pool_alloc_fail);
428 qdf_nofl_info(" %u times MSDU pool alloc failed",
429 stats_ptr->msdu_pool_alloc_fail);
430 qdf_nofl_info(" %u times tid pool freed",
431 stats_ptr->tid_pool_free);
432 qdf_nofl_info(" %u times MPDU pool freed",
433 stats_ptr->mpdu_pool_free);
434 qdf_nofl_info(" %u times MSDU pool freed",
435 stats_ptr->msdu_pool_free);
436 qdf_nofl_info(" %u MSDUs undelivered to HTT, queued to Rx MSDU free list",
437 stats_ptr->msdu_queued);
438 qdf_nofl_info(" %u MSDUs released from Rx MSDU list to MAC ring",
439 stats_ptr->msdu_recycled);
440 qdf_nofl_info(" %u MPDUs with invalid peer but A2 found in AST",
441 stats_ptr->invalid_peer_a2_in_ast);
442 qdf_nofl_info(" %u MPDUs with invalid peer but A3 found in AST",
443 stats_ptr->invalid_peer_a3_in_ast);
444 qdf_nofl_info(" %u MPDUs with invalid peer, Broadcast or Mulitcast frame",
445 stats_ptr->invalid_peer_bmc_mpdus);
446 qdf_nofl_info(" %u MSDUs with err attention word",
447 stats_ptr->rxdesc_err_att);
448 qdf_nofl_info(" %u MSDUs with flag of peer_idx_invalid",
449 stats_ptr->rxdesc_err_peer_idx_inv);
450 qdf_nofl_info(" %u MSDUs with flag of peer_idx_timeout",
451 stats_ptr->rxdesc_err_peer_idx_to);
452 qdf_nofl_info(" %u MSDUs with flag of overflow",
453 stats_ptr->rxdesc_err_ov);
454 qdf_nofl_info(" %u MSDUs with flag of msdu_length_err",
455 stats_ptr->rxdesc_err_msdu_len);
456 qdf_nofl_info(" %u MSDUs with flag of mpdu_length_err",
457 stats_ptr->rxdesc_err_mpdu_len);
458 qdf_nofl_info(" %u MSDUs with flag of tkip_mic_err",
459 stats_ptr->rxdesc_err_tkip_mic);
460 qdf_nofl_info(" %u MSDUs with flag of decrypt_err",
461 stats_ptr->rxdesc_err_decrypt);
462 qdf_nofl_info(" %u MSDUs with flag of fcs_err",
463 stats_ptr->rxdesc_err_fcs);
464 qdf_nofl_info(" %u Unicast frames with invalid peer handler",
465 stats_ptr->rxdesc_uc_msdus_inv_peer);
466 qdf_nofl_info(" %u unicast frame to DUT with invalid peer handler",
467 stats_ptr->rxdesc_direct_msdus_inv_peer);
468 qdf_nofl_info(" %u Broadcast/Multicast frames with invalid peer handler",
469 stats_ptr->rxdesc_bmc_msdus_inv_peer);
470 qdf_nofl_info(" %u MSDUs dropped due to no first MSDU flag",
471 stats_ptr->rxdesc_no_1st_msdu);
472 qdf_nofl_info(" %u MSDUs dropped due to ring overflow",
473 stats_ptr->msdu_drop_ring_ov);
474 qdf_nofl_info(" %u MSDUs dropped due to FC mismatch",
475 stats_ptr->msdu_drop_fc_mismatch);
476 qdf_nofl_info(" %u MSDUs dropped due to mgt frame in Remote ring",
477 stats_ptr->msdu_drop_mgmt_remote_ring);
478 qdf_nofl_info(" %u MSDUs dropped due to misc non error",
479 stats_ptr->msdu_drop_misc);
480 qdf_nofl_info(" %u MSDUs go to offload before reorder",
481 stats_ptr->offload_msdu_wal);
482 qdf_nofl_info(" %u data frame dropped by offload after reorder",
483 stats_ptr->offload_msdu_reorder);
484 qdf_nofl_info(" %u MPDUs with SN in the past & within BA window",
485 stats_ptr->dup_past_within_window);
486 qdf_nofl_info(" %u MPDUs with SN in the past & outside BA window",
487 stats_ptr->dup_past_outside_window);
488 }
489
490 static void
htt_t2h_stats_rx_rem_buf_stats_print(struct rx_remote_buffer_mgmt_stats * stats_ptr,int concise)491 htt_t2h_stats_rx_rem_buf_stats_print(
492 struct rx_remote_buffer_mgmt_stats *stats_ptr, int concise)
493 {
494 qdf_nofl_info("Rx Remote Buffer Statistics:");
495 qdf_nofl_info(" %u MSDU's reaped for Rx processing",
496 stats_ptr->remote_reaped);
497 qdf_nofl_info(" %u MSDU's recycled within firmware",
498 stats_ptr->remote_recycled);
499 qdf_nofl_info(" %u MSDU's stored by Data Rx",
500 stats_ptr->data_rx_msdus_stored);
501 qdf_nofl_info(" %u HTT indications from WAL Rx MSDU",
502 stats_ptr->wal_rx_ind);
503 qdf_nofl_info(" %u HTT indications unconsumed from WAL Rx MSDU",
504 stats_ptr->wal_rx_ind_unconsumed);
505 qdf_nofl_info(" %u HTT indications from Data Rx MSDU",
506 stats_ptr->data_rx_ind);
507 qdf_nofl_info(" %u HTT indications unconsumed from Data Rx MSDU",
508 stats_ptr->data_rx_ind_unconsumed);
509 qdf_nofl_info(" %u HTT indications from ATHBUF",
510 stats_ptr->athbuf_rx_ind);
511 qdf_nofl_info(" %u Remote buffers requested for refill",
512 stats_ptr->refill_buf_req);
513 qdf_nofl_info(" %u Remote buffers filled by host",
514 stats_ptr->refill_buf_rsp);
515 qdf_nofl_info(" %u times MAC has no buffers",
516 stats_ptr->mac_no_bufs);
517 qdf_nofl_info(" %u times f/w write & read indices on MAC ring are equal",
518 stats_ptr->fw_indices_equal);
519 qdf_nofl_info(" %u times f/w has no remote buffers to post to MAC",
520 stats_ptr->host_no_bufs);
521 }
522
523 static void
htt_t2h_stats_txbf_info_buf_stats_print(struct wlan_dbg_txbf_data_stats * stats_ptr)524 htt_t2h_stats_txbf_info_buf_stats_print(
525 struct wlan_dbg_txbf_data_stats *stats_ptr)
526 {
527 qdf_nofl_info("TXBF data Statistics:");
528 qdf_nofl_info("tx_txbf_vht (0..9): %u, %u, %u, %u, %u, %u, %u, %u, %u, %d",
529 stats_ptr->tx_txbf_vht[0],
530 stats_ptr->tx_txbf_vht[1],
531 stats_ptr->tx_txbf_vht[2],
532 stats_ptr->tx_txbf_vht[3],
533 stats_ptr->tx_txbf_vht[4],
534 stats_ptr->tx_txbf_vht[5],
535 stats_ptr->tx_txbf_vht[6],
536 stats_ptr->tx_txbf_vht[7],
537 stats_ptr->tx_txbf_vht[8],
538 stats_ptr->tx_txbf_vht[9]);
539 qdf_nofl_info("rx_txbf_vht (0..9): %u, %u, %u, %u, %u, %u, %u, %u, %u, %u",
540 stats_ptr->rx_txbf_vht[0],
541 stats_ptr->rx_txbf_vht[1],
542 stats_ptr->rx_txbf_vht[2],
543 stats_ptr->rx_txbf_vht[3],
544 stats_ptr->rx_txbf_vht[4],
545 stats_ptr->rx_txbf_vht[5],
546 stats_ptr->rx_txbf_vht[6],
547 stats_ptr->rx_txbf_vht[7],
548 stats_ptr->rx_txbf_vht[8],
549 stats_ptr->rx_txbf_vht[9]);
550 qdf_nofl_info("tx_txbf_ht (0..7): %u, %u, %u, %u, %u, %u, %u, %u",
551 stats_ptr->tx_txbf_ht[0],
552 stats_ptr->tx_txbf_ht[1],
553 stats_ptr->tx_txbf_ht[2],
554 stats_ptr->tx_txbf_ht[3],
555 stats_ptr->tx_txbf_ht[4],
556 stats_ptr->tx_txbf_ht[5],
557 stats_ptr->tx_txbf_ht[6],
558 stats_ptr->tx_txbf_ht[7]);
559 qdf_nofl_info("tx_txbf_ofdm (0..7): %u, %u, %u, %u, %u, %u, %u, %u",
560 stats_ptr->tx_txbf_ofdm[0],
561 stats_ptr->tx_txbf_ofdm[1],
562 stats_ptr->tx_txbf_ofdm[2],
563 stats_ptr->tx_txbf_ofdm[3],
564 stats_ptr->tx_txbf_ofdm[4],
565 stats_ptr->tx_txbf_ofdm[5],
566 stats_ptr->tx_txbf_ofdm[6],
567 stats_ptr->tx_txbf_ofdm[7]);
568 qdf_nofl_info("tx_txbf_cck (0..6): %u, %u, %u, %u, %u, %u, %u",
569 stats_ptr->tx_txbf_cck[0],
570 stats_ptr->tx_txbf_cck[1],
571 stats_ptr->tx_txbf_cck[2],
572 stats_ptr->tx_txbf_cck[3],
573 stats_ptr->tx_txbf_cck[4],
574 stats_ptr->tx_txbf_cck[5],
575 stats_ptr->tx_txbf_cck[6]);
576 }
577
578 static void
htt_t2h_stats_txbf_snd_buf_stats_print(struct wlan_dbg_txbf_snd_stats * stats_ptr)579 htt_t2h_stats_txbf_snd_buf_stats_print(
580 struct wlan_dbg_txbf_snd_stats *stats_ptr)
581 {
582 qdf_nofl_info("TXBF snd Buffer Statistics:");
583 qdf_nofl_info("cbf_20: %u, %u, %u, %u",
584 stats_ptr->cbf_20[0],
585 stats_ptr->cbf_20[1],
586 stats_ptr->cbf_20[2],
587 stats_ptr->cbf_20[3]);
588 qdf_nofl_info("cbf_40: %u, %u, %u, %u",
589 stats_ptr->cbf_40[0],
590 stats_ptr->cbf_40[1],
591 stats_ptr->cbf_40[2],
592 stats_ptr->cbf_40[3]);
593 qdf_nofl_info("cbf_80: %u, %u, %u, %u",
594 stats_ptr->cbf_80[0],
595 stats_ptr->cbf_80[1],
596 stats_ptr->cbf_80[2],
597 stats_ptr->cbf_80[3]);
598 qdf_nofl_info("sounding: %u, %u, %u, %u, %u, %u, %u, %u, %u",
599 stats_ptr->sounding[0],
600 stats_ptr->sounding[1],
601 stats_ptr->sounding[2],
602 stats_ptr->sounding[3],
603 stats_ptr->sounding[4],
604 stats_ptr->sounding[5],
605 stats_ptr->sounding[6],
606 stats_ptr->sounding[7],
607 stats_ptr->sounding[8]);
608 }
609
610 static void
htt_t2h_stats_tx_selfgen_buf_stats_print(struct wlan_dbg_tx_selfgen_stats * stats_ptr)611 htt_t2h_stats_tx_selfgen_buf_stats_print(
612 struct wlan_dbg_tx_selfgen_stats *stats_ptr)
613 {
614 qdf_nofl_info("Tx selfgen Buffer Statistics:");
615 qdf_nofl_info(" %u su_ndpa",
616 stats_ptr->su_ndpa);
617 qdf_nofl_info(" %u mu_ndp",
618 stats_ptr->mu_ndp);
619 qdf_nofl_info(" %u mu_ndpa",
620 stats_ptr->mu_ndpa);
621 qdf_nofl_info(" %u mu_ndp",
622 stats_ptr->mu_ndp);
623 qdf_nofl_info(" %u mu_brpoll_1",
624 stats_ptr->mu_brpoll_1);
625 qdf_nofl_info(" %u mu_brpoll_2",
626 stats_ptr->mu_brpoll_2);
627 qdf_nofl_info(" %u mu_bar_1",
628 stats_ptr->mu_bar_1);
629 qdf_nofl_info(" %u mu_bar_2",
630 stats_ptr->mu_bar_2);
631 qdf_nofl_info(" %u cts_burst",
632 stats_ptr->cts_burst);
633 qdf_nofl_info(" %u su_ndp_err",
634 stats_ptr->su_ndp_err);
635 qdf_nofl_info(" %u su_ndpa_err",
636 stats_ptr->su_ndpa_err);
637 qdf_nofl_info(" %u mu_ndp_err",
638 stats_ptr->mu_ndp_err);
639 qdf_nofl_info(" %u mu_brp1_err",
640 stats_ptr->mu_brp1_err);
641 qdf_nofl_info(" %u mu_brp2_err",
642 stats_ptr->mu_brp2_err);
643 }
644
645 static void
htt_t2h_stats_wifi2_error_stats_print(struct wlan_dbg_wifi2_error_stats * stats_ptr)646 htt_t2h_stats_wifi2_error_stats_print(
647 struct wlan_dbg_wifi2_error_stats *stats_ptr)
648 {
649 int i;
650
651 qdf_nofl_info("Scheduler error Statistics:");
652 qdf_nofl_info("urrn_stats: ");
653 qdf_nofl_info("urrn_stats: %d, %d, %d",
654 stats_ptr->urrn_stats[0],
655 stats_ptr->urrn_stats[1],
656 stats_ptr->urrn_stats[2]);
657 qdf_nofl_info("flush_errs (0..%d): ",
658 WHAL_DBG_FLUSH_REASON_MAXCNT);
659 for (i = 0; i < WHAL_DBG_FLUSH_REASON_MAXCNT; i++)
660 qdf_nofl_info(" %u", stats_ptr->flush_errs[i]);
661 qdf_nofl_info("\n");
662 qdf_nofl_info("schd_stall_errs (0..3): ");
663 qdf_nofl_info("%d, %d, %d, %d",
664 stats_ptr->schd_stall_errs[0],
665 stats_ptr->schd_stall_errs[1],
666 stats_ptr->schd_stall_errs[2],
667 stats_ptr->schd_stall_errs[3]);
668 qdf_nofl_info("schd_cmd_result (0..%d): ",
669 WHAL_DBG_CMD_RESULT_MAXCNT);
670 for (i = 0; i < WHAL_DBG_CMD_RESULT_MAXCNT; i++)
671 qdf_nofl_info(" %u", stats_ptr->schd_cmd_result[i]);
672 qdf_nofl_info("\n");
673 qdf_nofl_info("sifs_status (0..%d): ",
674 WHAL_DBG_SIFS_STATUS_MAXCNT);
675 for (i = 0; i < WHAL_DBG_SIFS_STATUS_MAXCNT; i++)
676 qdf_nofl_info(" %u", stats_ptr->sifs_status[i]);
677 qdf_nofl_info("\n");
678 qdf_nofl_info("phy_errs (0..%d): ",
679 WHAL_DBG_PHY_ERR_MAXCNT);
680 for (i = 0; i < WHAL_DBG_PHY_ERR_MAXCNT; i++)
681 qdf_nofl_info(" %u", stats_ptr->phy_errs[i]);
682 qdf_nofl_info("\n");
683 qdf_nofl_info(" %u rx_rate_inval",
684 stats_ptr->rx_rate_inval);
685 }
686
687 static void
htt_t2h_rx_musu_ndpa_pkts_stats_print(struct rx_txbf_musu_ndpa_pkts_stats * stats_ptr)688 htt_t2h_rx_musu_ndpa_pkts_stats_print(
689 struct rx_txbf_musu_ndpa_pkts_stats *stats_ptr)
690 {
691 qdf_nofl_info("Rx TXBF MU/SU Packets and NDPA Statistics:");
692 qdf_nofl_info(" %u Number of TXBF MU packets received",
693 stats_ptr->number_mu_pkts);
694 qdf_nofl_info(" %u Number of TXBF SU packets received",
695 stats_ptr->number_su_pkts);
696 qdf_nofl_info(" %u Number of TXBF directed NDPA",
697 stats_ptr->txbf_directed_ndpa_count);
698 qdf_nofl_info(" %u Number of TXBF retried NDPA",
699 stats_ptr->txbf_ndpa_retry_count);
700 qdf_nofl_info(" %u Total number of TXBF NDPA",
701 stats_ptr->txbf_total_ndpa_count);
702 }
703
704 #define HTT_TICK_TO_USEC(ticks, microsec_per_tick) (ticks * microsec_per_tick)
htt_rate_flags_to_mhz(uint8_t rate_flags)705 static inline int htt_rate_flags_to_mhz(uint8_t rate_flags)
706 {
707 if (rate_flags & 0x20)
708 return 40; /* WHAL_RC_FLAG_40MHZ */
709 if (rate_flags & 0x40)
710 return 80; /* WHAL_RC_FLAG_80MHZ */
711 if (rate_flags & 0x80)
712 return 160; /* WHAL_RC_FLAG_160MHZ */
713 return 20;
714 }
715
716 #define HTT_FW_STATS_MAX_BLOCK_ACK_WINDOW 64
717
718 static void
htt_t2h_tx_ppdu_bitmaps_pr(uint32_t * queued_ptr,uint32_t * acked_ptr)719 htt_t2h_tx_ppdu_bitmaps_pr(uint32_t *queued_ptr, uint32_t *acked_ptr)
720 {
721 char queued_str[HTT_FW_STATS_MAX_BLOCK_ACK_WINDOW + 1];
722 char acked_str[HTT_FW_STATS_MAX_BLOCK_ACK_WINDOW + 1];
723 int i, j, word;
724
725 qdf_mem_set(queued_str, HTT_FW_STATS_MAX_BLOCK_ACK_WINDOW, '0');
726 qdf_mem_set(acked_str, HTT_FW_STATS_MAX_BLOCK_ACK_WINDOW, '-');
727 i = 0;
728 for (word = 0; word < 2; word++) {
729 uint32_t queued = *(queued_ptr + word);
730 uint32_t acked = *(acked_ptr + word);
731
732 for (j = 0; j < 32; j++, i++) {
733 if (queued & (1 << j)) {
734 queued_str[i] = '1';
735 acked_str[i] = (acked & (1 << j)) ? 'y' : 'N';
736 }
737 }
738 }
739 queued_str[HTT_FW_STATS_MAX_BLOCK_ACK_WINDOW] = '\0';
740 acked_str[HTT_FW_STATS_MAX_BLOCK_ACK_WINDOW] = '\0';
741 qdf_nofl_info("%s\n", queued_str);
742 qdf_nofl_info("%s\n", acked_str);
743 }
744
htt_msg_read16(uint16_t * p16)745 static inline uint16_t htt_msg_read16(uint16_t *p16)
746 {
747 #ifdef BIG_ENDIAN_HOST
748 /*
749 * During upload, the bytes within each uint32_t word were
750 * swapped by the HIF HW. This results in the lower and upper bytes
751 * of each uint16_t to be in the correct big-endian order with
752 * respect to each other, but for each even-index uint16_t to
753 * have its position switched with its successor neighbor uint16_t.
754 * Undo this uint16_t position swapping.
755 */
756 return (((size_t) p16) & 0x2) ? *(p16 - 1) : *(p16 + 1);
757 #else
758 return *p16;
759 #endif
760 }
761
htt_msg_read8(uint8_t * p8)762 static inline uint8_t htt_msg_read8(uint8_t *p8)
763 {
764 #ifdef BIG_ENDIAN_HOST
765 /*
766 * During upload, the bytes within each uint32_t word were
767 * swapped by the HIF HW.
768 * Undo this byte swapping.
769 */
770 switch (((size_t) p8) & 0x3) {
771 case 0:
772 return *(p8 + 3);
773 case 1:
774 return *(p8 + 1);
775 case 2:
776 return *(p8 - 1);
777 default /* 3 */:
778 return *(p8 - 3);
779 }
780 #else
781 return *p8;
782 #endif
783 }
784
htt_make_u8_list_str(uint32_t * aligned_data,char * buffer,int space,int max_elems)785 static void htt_make_u8_list_str(uint32_t *aligned_data,
786 char *buffer, int space, int max_elems)
787 {
788 uint8_t *p8 = (uint8_t *) aligned_data;
789 char *buf_p = buffer;
790
791 while (max_elems-- > 0) {
792 int bytes;
793 uint8_t val;
794
795 val = htt_msg_read8(p8);
796 if (val == 0)
797 /* not enough data to fill the reserved msg buffer*/
798 break;
799
800 bytes = qdf_snprint(buf_p, space, "%d,", val);
801 space -= bytes;
802 if (space > 0)
803 buf_p += bytes;
804 else /* not enough print buffer space for all the data */
805 break;
806 p8++;
807 }
808 if (buf_p == buffer)
809 *buf_p = '\0'; /* nothing was written */
810 else
811 *(buf_p - 1) = '\0'; /* erase the final comma */
812
813 }
814
htt_make_u16_list_str(uint32_t * aligned_data,char * buffer,int space,int max_elems)815 static void htt_make_u16_list_str(uint32_t *aligned_data,
816 char *buffer, int space, int max_elems)
817 {
818 uint16_t *p16 = (uint16_t *) aligned_data;
819 char *buf_p = buffer;
820
821 while (max_elems-- > 0) {
822 int bytes;
823 uint16_t val;
824
825 val = htt_msg_read16(p16);
826 if (val == 0)
827 /* not enough data to fill the reserved msg buffer */
828 break;
829 bytes = qdf_snprint(buf_p, space, "%d,", val);
830 space -= bytes;
831 if (space > 0)
832 buf_p += bytes;
833 else /* not enough print buffer space for all the data */
834 break;
835
836 p16++;
837 }
838 if (buf_p == buffer)
839 *buf_p = '\0'; /* nothing was written */
840 else
841 *(buf_p - 1) = '\0'; /* erase the final comma */
842 }
843
844 static void
htt_t2h_tx_ppdu_log_print(struct ol_fw_tx_dbg_ppdu_msg_hdr * hdr,struct ol_fw_tx_dbg_ppdu_base * record,int length,int concise)845 htt_t2h_tx_ppdu_log_print(struct ol_fw_tx_dbg_ppdu_msg_hdr *hdr,
846 struct ol_fw_tx_dbg_ppdu_base *record,
847 int length, int concise)
848 {
849 int i;
850 int record_size;
851 int calculated_record_size;
852 int num_records;
853
854 record_size = sizeof(*record);
855 calculated_record_size = record_size +
856 hdr->mpdu_bytes_array_len * sizeof(uint16_t);
857 if (calculated_record_size < record_size) {
858 qdf_err("Overflow due to record and hdr->mpdu_bytes_array_len %u",
859 hdr->mpdu_bytes_array_len);
860 return;
861 }
862 record_size = calculated_record_size;
863 calculated_record_size += hdr->mpdu_msdus_array_len * sizeof(uint8_t);
864 if (calculated_record_size < record_size) {
865 qdf_err("Overflow due to hdr->mpdu_msdus_array_len %u",
866 hdr->mpdu_msdus_array_len);
867 return;
868 }
869 record_size = calculated_record_size;
870 calculated_record_size += hdr->msdu_bytes_array_len * sizeof(uint16_t);
871 if (calculated_record_size < record_size) {
872 qdf_err("Overflow due to hdr->msdu_bytes_array_len %u",
873 hdr->msdu_bytes_array_len);
874 return;
875 }
876 record_size = calculated_record_size;
877 num_records = (length - sizeof(*hdr)) / record_size;
878 if (num_records < 0) {
879 qdf_err("Underflow due to length %d", length);
880 return;
881 }
882 qdf_nofl_info("Tx PPDU log elements: num_records %d", num_records);
883
884 for (i = 0; i < num_records; i++) {
885 uint16_t start_seq_num;
886 uint16_t start_pn_lsbs;
887 uint8_t num_mpdus;
888 uint16_t peer_id;
889 uint8_t ext_tid;
890 uint8_t rate_code;
891 uint8_t rate_flags;
892 uint8_t tries;
893 uint8_t complete;
894 uint32_t time_enqueue_us;
895 uint32_t time_completion_us;
896 uint32_t *msg_word = (uint32_t *) record;
897
898 /* fields used for both concise and complete printouts */
899 start_seq_num =
900 ((*(msg_word + OL_FW_TX_DBG_PPDU_START_SEQ_NUM_WORD)) &
901 OL_FW_TX_DBG_PPDU_START_SEQ_NUM_M) >>
902 OL_FW_TX_DBG_PPDU_START_SEQ_NUM_S;
903 complete =
904 ((*(msg_word + OL_FW_TX_DBG_PPDU_COMPLETE_WORD)) &
905 OL_FW_TX_DBG_PPDU_COMPLETE_M) >>
906 OL_FW_TX_DBG_PPDU_COMPLETE_S;
907
908 /* fields used only for complete printouts */
909 if (!concise) {
910 #define BUF_SIZE 80
911 char buf[BUF_SIZE];
912 uint8_t *p8;
913 uint8_t *calculated_p8;
914
915 time_enqueue_us =
916 HTT_TICK_TO_USEC(record->timestamp_enqueue,
917 hdr->microsec_per_tick);
918 time_completion_us =
919 HTT_TICK_TO_USEC(record->timestamp_completion,
920 hdr->microsec_per_tick);
921
922 start_pn_lsbs =
923 ((*(msg_word +
924 OL_FW_TX_DBG_PPDU_START_PN_LSBS_WORD)) &
925 OL_FW_TX_DBG_PPDU_START_PN_LSBS_M) >>
926 OL_FW_TX_DBG_PPDU_START_PN_LSBS_S;
927 num_mpdus =
928 ((*(msg_word +
929 OL_FW_TX_DBG_PPDU_NUM_MPDUS_WORD))&
930 OL_FW_TX_DBG_PPDU_NUM_MPDUS_M) >>
931 OL_FW_TX_DBG_PPDU_NUM_MPDUS_S;
932 peer_id =
933 ((*(msg_word +
934 OL_FW_TX_DBG_PPDU_PEER_ID_WORD)) &
935 OL_FW_TX_DBG_PPDU_PEER_ID_M) >>
936 OL_FW_TX_DBG_PPDU_PEER_ID_S;
937 ext_tid =
938 ((*(msg_word +
939 OL_FW_TX_DBG_PPDU_EXT_TID_WORD)) &
940 OL_FW_TX_DBG_PPDU_EXT_TID_M) >>
941 OL_FW_TX_DBG_PPDU_EXT_TID_S;
942 rate_code =
943 ((*(msg_word +
944 OL_FW_TX_DBG_PPDU_RATE_CODE_WORD))&
945 OL_FW_TX_DBG_PPDU_RATE_CODE_M) >>
946 OL_FW_TX_DBG_PPDU_RATE_CODE_S;
947 rate_flags =
948 ((*(msg_word +
949 OL_FW_TX_DBG_PPDU_RATE_FLAGS_WORD))&
950 OL_FW_TX_DBG_PPDU_RATE_FLAGS_M) >>
951 OL_FW_TX_DBG_PPDU_RATE_FLAGS_S;
952 tries =
953 ((*(msg_word +
954 OL_FW_TX_DBG_PPDU_TRIES_WORD)) &
955 OL_FW_TX_DBG_PPDU_TRIES_M) >>
956 OL_FW_TX_DBG_PPDU_TRIES_S;
957
958 qdf_nofl_info(" - PPDU tx to peer %d, TID %d", peer_id,
959 ext_tid);
960 qdf_nofl_info(" start seq num= %u, start PN LSBs= %#04x",
961 start_seq_num, start_pn_lsbs);
962 qdf_nofl_info(" PPDU: %d MPDUs, (?) MSDUs, %d bytes",
963 num_mpdus,
964 /* num_msdus-not yet computed in target */
965 record->num_bytes);
966 if (complete) {
967 qdf_nofl_info(" enqueued: %u, completed: %u usec)",
968 time_enqueue_us,
969 time_completion_us);
970 qdf_nofl_info(" %d tries, last tx used rate %d ",
971 tries, rate_code);
972 qdf_nofl_info("on %d MHz chan (flags = %#x)",
973 htt_rate_flags_to_mhz
974 (rate_flags), rate_flags);
975 qdf_nofl_info(" enqueued and acked MPDU bitmaps:");
976 htt_t2h_tx_ppdu_bitmaps_pr(msg_word +
977 OL_FW_TX_DBG_PPDU_ENQUEUED_LSBS_WORD,
978 msg_word +
979 OL_FW_TX_DBG_PPDU_BLOCK_ACK_LSBS_WORD);
980 } else {
981 qdf_nofl_info(" enqueued: %d us, not yet completed",
982 time_enqueue_us);
983 }
984 /* skip the regular msg fields to reach the tail area */
985 p8 = (uint8_t *) record;
986 calculated_p8 = p8 + sizeof(struct ol_fw_tx_dbg_ppdu_base);
987 if (calculated_p8 < p8) {
988 qdf_err("Overflow due to record %pK", p8);
989 continue;
990 }
991 p8 = calculated_p8;
992 if (hdr->mpdu_bytes_array_len) {
993 htt_make_u16_list_str((uint32_t *) p8, buf,
994 BUF_SIZE,
995 hdr->
996 mpdu_bytes_array_len);
997 qdf_nofl_info(" MPDU bytes: %s", buf);
998 }
999 calculated_p8 += hdr->mpdu_bytes_array_len * sizeof(uint16_t);
1000 if (calculated_p8 < p8) {
1001 qdf_err("Overflow due to hdr->mpdu_bytes_array_len %u",
1002 hdr->mpdu_bytes_array_len);
1003 continue;
1004 }
1005 p8 = calculated_p8;
1006 if (hdr->mpdu_msdus_array_len) {
1007 htt_make_u8_list_str((uint32_t *) p8, buf,
1008 BUF_SIZE,
1009 hdr->mpdu_msdus_array_len);
1010 qdf_nofl_info(" MPDU MSDUs: %s", buf);
1011 }
1012 calculated_p8 += hdr->mpdu_msdus_array_len * sizeof(uint8_t);
1013 if (calculated_p8 < p8) {
1014 qdf_err("Overflow due to hdr->mpdu_msdus_array_len %u",
1015 hdr->mpdu_msdus_array_len);
1016 continue;
1017 }
1018 p8 = calculated_p8;
1019 if (hdr->msdu_bytes_array_len) {
1020 htt_make_u16_list_str((uint32_t *) p8, buf,
1021 BUF_SIZE,
1022 hdr->
1023 msdu_bytes_array_len);
1024 qdf_nofl_info(" MSDU bytes: %s", buf);
1025 }
1026 } else {
1027 /* concise */
1028 qdf_nofl_info("start seq num = %u ", start_seq_num);
1029 qdf_nofl_info("enqueued and acked MPDU bitmaps:");
1030 if (complete) {
1031 htt_t2h_tx_ppdu_bitmaps_pr(msg_word +
1032 OL_FW_TX_DBG_PPDU_ENQUEUED_LSBS_WORD,
1033 msg_word +
1034 OL_FW_TX_DBG_PPDU_BLOCK_ACK_LSBS_WORD);
1035 } else {
1036 qdf_nofl_info("(not completed)");
1037 }
1038 }
1039 record = (struct ol_fw_tx_dbg_ppdu_base *)
1040 (((uint8_t *) record) + record_size);
1041 }
1042 }
1043
htt_t2h_stats_tidq_stats_print(struct wlan_dbg_tidq_stats * tidq_stats,int concise)1044 static void htt_t2h_stats_tidq_stats_print(
1045 struct wlan_dbg_tidq_stats *tidq_stats, int concise)
1046 {
1047 qdf_nofl_info("TID QUEUE STATS:");
1048 qdf_nofl_info("tid_txq_stats: %u", tidq_stats->wlan_dbg_tid_txq_status);
1049 qdf_nofl_info("num_pkts_queued(0..9):");
1050 qdf_nofl_info("%u, %u, %u, %u, %u, %u, %u, %u, %u, %u",
1051 tidq_stats->txq_st.num_pkts_queued[0],
1052 tidq_stats->txq_st.num_pkts_queued[1],
1053 tidq_stats->txq_st.num_pkts_queued[2],
1054 tidq_stats->txq_st.num_pkts_queued[3],
1055 tidq_stats->txq_st.num_pkts_queued[4],
1056 tidq_stats->txq_st.num_pkts_queued[5],
1057 tidq_stats->txq_st.num_pkts_queued[6],
1058 tidq_stats->txq_st.num_pkts_queued[7],
1059 tidq_stats->txq_st.num_pkts_queued[8],
1060 tidq_stats->txq_st.num_pkts_queued[9]);
1061 qdf_nofl_info("tid_hw_qdepth(0..19):");
1062 qdf_nofl_info("%u, %u, %u, %u, %u, %u, %u, %u, %u, %u",
1063 tidq_stats->txq_st.tid_hw_qdepth[0],
1064 tidq_stats->txq_st.tid_hw_qdepth[1],
1065 tidq_stats->txq_st.tid_hw_qdepth[2],
1066 tidq_stats->txq_st.tid_hw_qdepth[3],
1067 tidq_stats->txq_st.tid_hw_qdepth[4],
1068 tidq_stats->txq_st.tid_hw_qdepth[5],
1069 tidq_stats->txq_st.tid_hw_qdepth[6],
1070 tidq_stats->txq_st.tid_hw_qdepth[7],
1071 tidq_stats->txq_st.tid_hw_qdepth[8],
1072 tidq_stats->txq_st.tid_hw_qdepth[9]);
1073 qdf_nofl_info("%u, %u, %u, %u, %u, %u, %u, %u, %u, %u",
1074 tidq_stats->txq_st.tid_hw_qdepth[10],
1075 tidq_stats->txq_st.tid_hw_qdepth[11],
1076 tidq_stats->txq_st.tid_hw_qdepth[12],
1077 tidq_stats->txq_st.tid_hw_qdepth[13],
1078 tidq_stats->txq_st.tid_hw_qdepth[14],
1079 tidq_stats->txq_st.tid_hw_qdepth[15],
1080 tidq_stats->txq_st.tid_hw_qdepth[16],
1081 tidq_stats->txq_st.tid_hw_qdepth[17],
1082 tidq_stats->txq_st.tid_hw_qdepth[18],
1083 tidq_stats->txq_st.tid_hw_qdepth[19]);
1084 qdf_nofl_info("tid_sw_qdepth(0..19):");
1085 qdf_nofl_info("%u, %u, %u, %u, %u, %u, %u, %u, %u, %u",
1086 tidq_stats->txq_st.tid_sw_qdepth[0],
1087 tidq_stats->txq_st.tid_sw_qdepth[1],
1088 tidq_stats->txq_st.tid_sw_qdepth[2],
1089 tidq_stats->txq_st.tid_sw_qdepth[3],
1090 tidq_stats->txq_st.tid_sw_qdepth[4],
1091 tidq_stats->txq_st.tid_sw_qdepth[5],
1092 tidq_stats->txq_st.tid_sw_qdepth[6],
1093 tidq_stats->txq_st.tid_sw_qdepth[7],
1094 tidq_stats->txq_st.tid_sw_qdepth[8],
1095 tidq_stats->txq_st.tid_sw_qdepth[9]);
1096 qdf_nofl_info("%u, %u, %u, %u, %u, %u, %u, %u, %u, %u",
1097 tidq_stats->txq_st.tid_sw_qdepth[10],
1098 tidq_stats->txq_st.tid_sw_qdepth[11],
1099 tidq_stats->txq_st.tid_sw_qdepth[12],
1100 tidq_stats->txq_st.tid_sw_qdepth[13],
1101 tidq_stats->txq_st.tid_sw_qdepth[14],
1102 tidq_stats->txq_st.tid_sw_qdepth[15],
1103 tidq_stats->txq_st.tid_sw_qdepth[16],
1104 tidq_stats->txq_st.tid_sw_qdepth[17],
1105 tidq_stats->txq_st.tid_sw_qdepth[18],
1106 tidq_stats->txq_st.tid_sw_qdepth[19]);
1107 }
1108
htt_t2h_stats_tx_mu_stats_print(struct wlan_dbg_tx_mu_stats * tx_mu_stats,int concise)1109 static void htt_t2h_stats_tx_mu_stats_print(
1110 struct wlan_dbg_tx_mu_stats *tx_mu_stats, int concise)
1111 {
1112 qdf_nofl_info("TX MU STATS:");
1113 qdf_nofl_info("mu_sch_nusers_2: %u", tx_mu_stats->mu_sch_nusers_2);
1114 qdf_nofl_info("mu_sch_nusers_3: %u", tx_mu_stats->mu_sch_nusers_3);
1115 qdf_nofl_info("mu_mpdus_queued_usr: %u, %u, %u, %u",
1116 tx_mu_stats->mu_mpdus_queued_usr[0],
1117 tx_mu_stats->mu_mpdus_queued_usr[1],
1118 tx_mu_stats->mu_mpdus_queued_usr[2],
1119 tx_mu_stats->mu_mpdus_queued_usr[3]);
1120 qdf_nofl_info("mu_mpdus_tried_usr: %u, %u, %u, %u",
1121 tx_mu_stats->mu_mpdus_tried_usr[0],
1122 tx_mu_stats->mu_mpdus_tried_usr[1],
1123 tx_mu_stats->mu_mpdus_tried_usr[2],
1124 tx_mu_stats->mu_mpdus_tried_usr[3]);
1125 qdf_nofl_info("mu_mpdus_failed_usr: %u, %u, %u, %u",
1126 tx_mu_stats->mu_mpdus_failed_usr[0],
1127 tx_mu_stats->mu_mpdus_failed_usr[1],
1128 tx_mu_stats->mu_mpdus_failed_usr[2],
1129 tx_mu_stats->mu_mpdus_failed_usr[3]);
1130 qdf_nofl_info("mu_mpdus_requeued_usr: %u, %u, %u, %u",
1131 tx_mu_stats->mu_mpdus_requeued_usr[0],
1132 tx_mu_stats->mu_mpdus_requeued_usr[1],
1133 tx_mu_stats->mu_mpdus_requeued_usr[2],
1134 tx_mu_stats->mu_mpdus_requeued_usr[3]);
1135 qdf_nofl_info("mu_err_no_ba_usr: %u, %u, %u, %u",
1136 tx_mu_stats->mu_err_no_ba_usr[0],
1137 tx_mu_stats->mu_err_no_ba_usr[1],
1138 tx_mu_stats->mu_err_no_ba_usr[2],
1139 tx_mu_stats->mu_err_no_ba_usr[3]);
1140 qdf_nofl_info("mu_mpdu_underrun_usr: %u, %u, %u, %u",
1141 tx_mu_stats->mu_mpdu_underrun_usr[0],
1142 tx_mu_stats->mu_mpdu_underrun_usr[1],
1143 tx_mu_stats->mu_mpdu_underrun_usr[2],
1144 tx_mu_stats->mu_mpdu_underrun_usr[3]);
1145 qdf_nofl_info("mu_ampdu_underrun_usr: %u, %u, %u, %u",
1146 tx_mu_stats->mu_ampdu_underrun_usr[0],
1147 tx_mu_stats->mu_ampdu_underrun_usr[1],
1148 tx_mu_stats->mu_ampdu_underrun_usr[2],
1149 tx_mu_stats->mu_ampdu_underrun_usr[3]);
1150
1151 }
1152
htt_t2h_stats_sifs_resp_stats_print(struct wlan_dbg_sifs_resp_stats * sifs_stats,int concise)1153 static void htt_t2h_stats_sifs_resp_stats_print(
1154 struct wlan_dbg_sifs_resp_stats *sifs_stats, int concise)
1155 {
1156 qdf_nofl_info("SIFS RESP STATS:");
1157 qdf_nofl_info("num of ps-poll trigger frames: %u",
1158 sifs_stats->ps_poll_trigger);
1159 qdf_nofl_info("num of uapsd trigger frames: %u",
1160 sifs_stats->uapsd_trigger);
1161 qdf_nofl_info("num of data trigger frames: %u, %u",
1162 sifs_stats->qb_data_trigger[0],
1163 sifs_stats->qb_data_trigger[1]);
1164 qdf_nofl_info("num of bar trigger frames: %u, %u",
1165 sifs_stats->qb_bar_trigger[0],
1166 sifs_stats->qb_bar_trigger[1]);
1167 qdf_nofl_info("num of ppdu transmitted at SIFS interval: %u",
1168 sifs_stats->sifs_resp_data);
1169 qdf_nofl_info("num of ppdu failed to meet SIFS resp timing: %u",
1170 sifs_stats->sifs_resp_err);
1171 }
1172
htt_t2h_stats_print(uint8_t * stats_data,int concise)1173 void htt_t2h_stats_print(uint8_t *stats_data, int concise)
1174 {
1175 uint32_t *msg_word = (uint32_t *) stats_data;
1176 enum htt_dbg_stats_type type;
1177 enum htt_dbg_stats_status status;
1178 int length;
1179
1180 type = HTT_T2H_STATS_CONF_TLV_TYPE_GET(*msg_word);
1181 status = HTT_T2H_STATS_CONF_TLV_STATUS_GET(*msg_word);
1182 length = HTT_T2H_STATS_CONF_TLV_LENGTH_GET(*msg_word);
1183
1184 /* check that we've been given a valid stats type */
1185 if (status == HTT_DBG_STATS_STATUS_SERIES_DONE) {
1186 return;
1187 } else if (status == HTT_DBG_STATS_STATUS_INVALID) {
1188 qdf_debug("Target doesn't support stats type %d", type);
1189 return;
1190 } else if (status == HTT_DBG_STATS_STATUS_ERROR) {
1191 qdf_debug("Target couldn't upload stats type %d (no mem?)",
1192 type);
1193 return;
1194 }
1195 /* got valid (though perhaps partial) stats - process them */
1196 switch (type) {
1197 case HTT_DBG_STATS_WAL_PDEV_TXRX:
1198 {
1199 struct wlan_dbg_stats *wlan_dbg_stats_ptr;
1200
1201 wlan_dbg_stats_ptr =
1202 (struct wlan_dbg_stats *)(msg_word + 1);
1203 htt_t2h_stats_pdev_stats_print(wlan_dbg_stats_ptr,
1204 concise);
1205 break;
1206 }
1207 case HTT_DBG_STATS_RX_REORDER:
1208 {
1209 struct rx_reorder_stats *rx_reorder_stats_ptr;
1210
1211 rx_reorder_stats_ptr =
1212 (struct rx_reorder_stats *)(msg_word + 1);
1213 htt_t2h_stats_rx_reorder_stats_print
1214 (rx_reorder_stats_ptr, concise);
1215 break;
1216 }
1217
1218 case HTT_DBG_STATS_RX_RATE_INFO:
1219 {
1220 wlan_dbg_rx_rate_info_t *rx_phy_info;
1221
1222 rx_phy_info = (wlan_dbg_rx_rate_info_t *) (msg_word + 1);
1223 htt_t2h_stats_rx_rate_stats_print(rx_phy_info, concise);
1224 break;
1225 }
1226 case HTT_DBG_STATS_RX_RATE_INFO_V2:
1227 {
1228 wlan_dbg_rx_rate_info_v2_t *rx_phy_info;
1229
1230 rx_phy_info = (wlan_dbg_rx_rate_info_v2_t *) (msg_word + 1);
1231 htt_t2h_stats_rx_rate_stats_print_v2(rx_phy_info, concise);
1232 break;
1233 }
1234 case HTT_DBG_STATS_TX_PPDU_LOG:
1235 {
1236 struct ol_fw_tx_dbg_ppdu_msg_hdr *hdr;
1237 struct ol_fw_tx_dbg_ppdu_base *record;
1238
1239 if (status == HTT_DBG_STATS_STATUS_PARTIAL
1240 && length == 0) {
1241 qdf_debug("HTT_DBG_STATS_TX_PPDU_LOG -- length = 0!");
1242 break;
1243 }
1244 hdr = (struct ol_fw_tx_dbg_ppdu_msg_hdr *)(msg_word + 1);
1245 record = (struct ol_fw_tx_dbg_ppdu_base *)(hdr + 1);
1246 htt_t2h_tx_ppdu_log_print(hdr, record, length, concise);
1247 }
1248 break;
1249 case HTT_DBG_STATS_TX_RATE_INFO:
1250 {
1251 wlan_dbg_tx_rate_info_t *tx_rate_info;
1252
1253 tx_rate_info = (wlan_dbg_tx_rate_info_t *) (msg_word + 1);
1254 htt_t2h_stats_tx_rate_stats_print(tx_rate_info, concise);
1255 break;
1256 }
1257 case HTT_DBG_STATS_TX_RATE_INFO_V2:
1258 {
1259 wlan_dbg_tx_rate_info_v2_t *tx_rate_info;
1260
1261 tx_rate_info = (wlan_dbg_tx_rate_info_v2_t *) (msg_word + 1);
1262 htt_t2h_stats_tx_rate_stats_print_v2(tx_rate_info, concise);
1263 break;
1264 }
1265 case HTT_DBG_STATS_RX_REMOTE_RING_BUFFER_INFO:
1266 {
1267 struct rx_remote_buffer_mgmt_stats *rx_rem_buf;
1268
1269 rx_rem_buf =
1270 (struct rx_remote_buffer_mgmt_stats *)(msg_word + 1);
1271 htt_t2h_stats_rx_rem_buf_stats_print(rx_rem_buf, concise);
1272 break;
1273 }
1274 case HTT_DBG_STATS_TXBF_INFO:
1275 {
1276 struct wlan_dbg_txbf_data_stats *txbf_info_buf;
1277
1278 txbf_info_buf =
1279 (struct wlan_dbg_txbf_data_stats *)(msg_word + 1);
1280 htt_t2h_stats_txbf_info_buf_stats_print(txbf_info_buf);
1281 break;
1282 }
1283 case HTT_DBG_STATS_SND_INFO:
1284 {
1285 struct wlan_dbg_txbf_snd_stats *txbf_snd_buf;
1286
1287 txbf_snd_buf = (struct wlan_dbg_txbf_snd_stats *)(msg_word + 1);
1288 htt_t2h_stats_txbf_snd_buf_stats_print(txbf_snd_buf);
1289 break;
1290 }
1291 case HTT_DBG_STATS_TX_SELFGEN_INFO:
1292 {
1293 struct wlan_dbg_tx_selfgen_stats *tx_selfgen_buf;
1294
1295 tx_selfgen_buf =
1296 (struct wlan_dbg_tx_selfgen_stats *)(msg_word + 1);
1297 htt_t2h_stats_tx_selfgen_buf_stats_print(tx_selfgen_buf);
1298 break;
1299 }
1300 case HTT_DBG_STATS_ERROR_INFO:
1301 {
1302 struct wlan_dbg_wifi2_error_stats *wifi2_error_buf;
1303
1304 wifi2_error_buf =
1305 (struct wlan_dbg_wifi2_error_stats *)(msg_word + 1);
1306 htt_t2h_stats_wifi2_error_stats_print(wifi2_error_buf);
1307 break;
1308 }
1309 case HTT_DBG_STATS_TXBF_MUSU_NDPA_PKT:
1310 {
1311 struct rx_txbf_musu_ndpa_pkts_stats *rx_musu_ndpa_stats;
1312
1313 rx_musu_ndpa_stats = (struct rx_txbf_musu_ndpa_pkts_stats *)
1314 (msg_word + 1);
1315 htt_t2h_rx_musu_ndpa_pkts_stats_print(rx_musu_ndpa_stats);
1316 break;
1317 }
1318 case HTT_DBG_STATS_TIDQ:
1319 {
1320 struct wlan_dbg_tidq_stats *tidq_stats;
1321
1322 tidq_stats = (struct wlan_dbg_tidq_stats *)(msg_word + 1);
1323 htt_t2h_stats_tidq_stats_print(tidq_stats, concise);
1324 break;
1325 }
1326 case HTT_DBG_STATS_TX_MU_INFO:
1327 {
1328 struct wlan_dbg_tx_mu_stats *tx_mu_stats;
1329
1330 tx_mu_stats = (struct wlan_dbg_tx_mu_stats *)(msg_word + 1);
1331 htt_t2h_stats_tx_mu_stats_print(tx_mu_stats, concise);
1332 break;
1333 }
1334 case HTT_DBG_STATS_SIFS_RESP_INFO:
1335 {
1336 struct wlan_dbg_sifs_resp_stats *sifs_stats;
1337
1338 sifs_stats = (struct wlan_dbg_sifs_resp_stats *)(msg_word + 1);
1339 htt_t2h_stats_sifs_resp_stats_print(sifs_stats, concise);
1340 break;
1341 }
1342 default:
1343 break;
1344 }
1345 }
1346