adt3-S dhd_driver source code [1/1]
[GitHub/LineageOS/G12/android_hardware_amlogic_kernel-modules_dhd-driver.git] / bcmdhd.100.10.315.x / dhd_mschdbg.c
CommitLineData
84813812
LJ
1/*
2 * DHD debugability support
3 *
4 * <<Broadcom-WL-IPTag/Open:>>
5 *
6 * Copyright (C) 1999-2019, Broadcom.
7 *
8 * Unless you and Broadcom execute a separate written software license
9 * agreement governing use of this software, this software is licensed to you
10 * under the terms of the GNU General Public License version 2 (the "GPL"),
11 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
12 * following added to such license:
13 *
14 * As a special exception, the copyright holders of this software give you
15 * permission to link this software with independent modules, and to copy and
16 * distribute the resulting executable under terms of your choice, provided that
17 * you also meet, for each linked independent module, the terms and conditions of
18 * the license of that module. An independent module is a module which is not
19 * derived from this software. The special exception does not apply to any
20 * modifications of the software.
21 *
22 * Notwithstanding the above, under no circumstances may you combine this
23 * software in any way with any other Broadcom software provided under a license
24 * other than the GPL, without Broadcom's express prior written consent.
25 *
26 * $Id: dhd_mschdbg.c 639872 2016-05-25 05:39:30Z $
27 */
28#ifdef SHOW_LOGTRACE
29#include <typedefs.h>
30#include <osl.h>
31#include <bcmutils.h>
32#include <bcmendian.h>
33#include <dngl_stats.h>
34#include <dhd.h>
35#include <dhd_dbg.h>
36#include <dhd_debug.h>
37#include <dhd_mschdbg.h>
38
39#include <event_log.h>
40#include <event_trace.h>
41#include <msgtrace.h>
42
43static const char *head_log = "";
44#define MSCH_EVENT_HEAD(space) \
45 do { \
46 MSCH_EVENT(("%s_E: ", head_log)); \
47 if (space > 0) { \
48 int ii; \
49 for (ii = 0; ii < space; ii += 4) MSCH_EVENT((" ")); \
50 } \
51 } while (0)
52#define MSCH_EVENT(args) do {if (dhd_msg_level & DHD_EVENT_VAL) printf args;} while (0)
53
54static uint64 solt_start_time[4], req_start_time[4], profiler_start_time[4];
55static uint32 solt_chanspec[4] = {0, }, req_start[4] = {0, };
56static bool lastMessages = FALSE;
57
58#define US_PRE_SEC 1000000
59#define DATA_UNIT_FOR_LOG_CNT 4
60
61static void dhd_mschdbg_us_to_sec(uint32 time_h, uint32 time_l, uint32 *sec, uint32 *remain)
62{
63 uint64 cur_time = ((uint64)(ntoh32(time_h)) << 32) | ntoh32(time_l);
64 uint64 r, u = 0;
65
66 r = cur_time;
67 while (time_h != 0) {
68 u += (uint64)((0xffffffff / US_PRE_SEC)) * time_h;
69 r = cur_time - u * US_PRE_SEC;
70 time_h = (uint32)(r >> 32);
71 }
72
73 *sec = (uint32)(u + ((uint32)(r) / US_PRE_SEC));
74 *remain = (uint32)(r) % US_PRE_SEC;
75}
76
77static char *dhd_mschdbg_display_time(uint32 time_h, uint32 time_l)
78{
79 static char display_time[32];
80 uint32 s, ss;
81
82 if (time_h == 0xffffffff && time_l == 0xffffffff) {
83 snprintf(display_time, 31, "-1");
84 } else {
85 dhd_mschdbg_us_to_sec(time_h, time_l, &s, &ss);
86 snprintf(display_time, 31, "%d.%06d", s, ss);
87 }
88 return display_time;
89}
90
91static void
92dhd_mschdbg_chanspec_list(int sp, char *data, uint16 ptr, uint16 chanspec_cnt)
93{
94 int i, cnt = (int)ntoh16(chanspec_cnt);
95 uint16 *chanspec_list = (uint16 *)(data + ntoh16(ptr));
96 char buf[CHANSPEC_STR_LEN];
97 chanspec_t c;
98
99 MSCH_EVENT_HEAD(sp);
100 MSCH_EVENT(("<chanspec_list>:"));
101 for (i = 0; i < cnt; i++) {
102 c = (chanspec_t)ntoh16(chanspec_list[i]);
103 MSCH_EVENT((" %s", wf_chspec_ntoa(c, buf)));
104 }
105 MSCH_EVENT(("\n"));
106}
107
108static void
109dhd_mschdbg_elem_list(int sp, char *title, char *data, uint16 ptr, uint16 list_cnt)
110{
111 int i, cnt = (int)ntoh16(list_cnt);
112 uint32 *list = (uint32 *)(data + ntoh16(ptr));
113
114 MSCH_EVENT_HEAD(sp);
115 MSCH_EVENT(("%s_list: ", title));
116 for (i = 0; i < cnt; i++) {
117 MSCH_EVENT(("0x%08x->", ntoh32(list[i])));
118 }
119 MSCH_EVENT(("null\n"));
120}
121
122static void
123dhd_mschdbg_req_param_profiler_event_data(int sp, int ver, char *data, uint16 ptr)
124{
125 int sn = sp + 4;
126 msch_req_param_profiler_event_data_t *p =
127 (msch_req_param_profiler_event_data_t *)(data + ntoh16(ptr));
128 uint32 type, flags;
129
130 MSCH_EVENT_HEAD(sp);
131 MSCH_EVENT(("<request parameters>\n"));
132 MSCH_EVENT_HEAD(sn);
133 MSCH_EVENT(("req_type: "));
134
135 type = p->req_type;
136 if (type < 4) {
137 char *req_type[] = {"fixed", "start-flexible", "duration-flexible",
138 "both-flexible"};
139 MSCH_EVENT(("%s", req_type[type]));
140 }
141 else
142 MSCH_EVENT(("unknown(%d)", type));
143
144 flags = ntoh16(p->flags);
145 if (flags & WL_MSCH_REQ_FLAGS_CHAN_CONTIGUOUS)
146 MSCH_EVENT((", CHAN_CONTIGUOUS"));
147 if (flags & WL_MSCH_REQ_FLAGS_MERGE_CONT_SLOTS)
148 MSCH_EVENT((", MERGE_CONT_SLOTS"));
149 if (flags & WL_MSCH_REQ_FLAGS_PREMTABLE)
150 MSCH_EVENT((", PREMTABLE"));
151 if (flags & WL_MSCH_REQ_FLAGS_PREMT_CURTS)
152 MSCH_EVENT((", PREMT_CURTS"));
153 if (flags & WL_MSCH_REQ_FLAGS_PREMT_IMMEDIATE)
154 MSCH_EVENT((", PREMT_IMMEDIATE"));
155 MSCH_EVENT((", priority: %d\n", p->priority));
156
157 MSCH_EVENT_HEAD(sn);
158 MSCH_EVENT(("start-time: %s, duration: %d(us), interval: %d(us)\n",
159 dhd_mschdbg_display_time(p->start_time_h, p->start_time_l),
160 ntoh32(p->duration), ntoh32(p->interval)));
161
162 if (type == WL_MSCH_RT_DUR_FLEX) {
163 MSCH_EVENT_HEAD(sn);
164 MSCH_EVENT(("dur_flex: %d(us)\n", ntoh32(p->flex.dur_flex)));
165 } else if (type == WL_MSCH_RT_BOTH_FLEX) {
166 MSCH_EVENT_HEAD(sn);
167 MSCH_EVENT(("min_dur: %d(us), max_away_dur: %d(us)\n",
168 ntoh32(p->flex.bf.min_dur), ntoh32(p->flex.bf.max_away_dur)));
169
170 MSCH_EVENT_HEAD(sn);
171 MSCH_EVENT(("hi_prio_time: %s, hi_prio_interval: %d(us)\n",
172 dhd_mschdbg_display_time(p->flex.bf.hi_prio_time_h,
173 p->flex.bf.hi_prio_time_l),
174 ntoh32(p->flex.bf.hi_prio_interval)));
175 }
176}
177
178static void
179dhd_mschdbg_timeslot_profiler_event_data(int sp, int ver, char *title, char *data,
180 uint16 ptr, bool empty)
181{
182 int s, sn = sp + 4;
183 msch_timeslot_profiler_event_data_t *p =
184 (msch_timeslot_profiler_event_data_t *)(data + ntoh16(ptr));
185 char *state[] = {"NONE", "CHN_SW", "ONCHAN_FIRE", "OFF_CHN_PREP",
186 "OFF_CHN_DONE", "TS_COMPLETE"};
187
188 MSCH_EVENT_HEAD(sp);
189 MSCH_EVENT(("<%s timeslot>: ", title));
190 if (empty) {
191 MSCH_EVENT((" null\n"));
192 return;
193 }
194 else
195 MSCH_EVENT(("0x%08x\n", ntoh32(p->p_timeslot)));
196
197 s = (int)(ntoh32(p->state));
198 if (s > 5) s = 0;
199
200 MSCH_EVENT_HEAD(sn);
201 MSCH_EVENT(("id: %d, state[%d]: %s, chan_ctxt: [0x%08x]\n",
202 ntoh32(p->timeslot_id), ntoh32(p->state), state[s], ntoh32(p->p_chan_ctxt)));
203
204 MSCH_EVENT_HEAD(sn);
205 MSCH_EVENT(("fire_time: %s",
206 dhd_mschdbg_display_time(p->fire_time_h, p->fire_time_l)));
207
208 MSCH_EVENT((", pre_start_time: %s",
209 dhd_mschdbg_display_time(p->pre_start_time_h, p->pre_start_time_l)));
210
211 MSCH_EVENT((", end_time: %s",
212 dhd_mschdbg_display_time(p->end_time_h, p->end_time_l)));
213
214 MSCH_EVENT((", sch_dur: %s\n",
215 dhd_mschdbg_display_time(p->sch_dur_h, p->sch_dur_l)));
216}
217
218static void
219dhd_mschdbg_req_timing_profiler_event_data(int sp, int ver, char *title, char *data,
220 uint16 ptr, bool empty)
221{
222 int sn = sp + 4;
223 msch_req_timing_profiler_event_data_t *p =
224 (msch_req_timing_profiler_event_data_t *)(data + ntoh16(ptr));
225 uint32 type;
226
227 MSCH_EVENT_HEAD(sp);
228 MSCH_EVENT(("<%s req_timing>: ", title));
229 if (empty) {
230 MSCH_EVENT((" null\n"));
231 return;
232 }
233 else
234 MSCH_EVENT(("0x%08x (prev 0x%08x, next 0x%08x)\n",
235 ntoh32(p->p_req_timing), ntoh32(p->p_prev), ntoh32(p->p_next)));
236
237 MSCH_EVENT_HEAD(sn);
238 MSCH_EVENT(("flags:"));
239 type = ntoh16(p->flags);
240 if ((type & 0x7f) == 0)
241 MSCH_EVENT((" NONE"));
242 else {
243 if (type & WL_MSCH_RC_FLAGS_ONCHAN_FIRE)
244 MSCH_EVENT((" ONCHAN_FIRE"));
245 if (type & WL_MSCH_RC_FLAGS_START_FIRE_DONE)
246 MSCH_EVENT((" START_FIRE"));
247 if (type & WL_MSCH_RC_FLAGS_END_FIRE_DONE)
248 MSCH_EVENT((" END_FIRE"));
249 if (type & WL_MSCH_RC_FLAGS_ONFIRE_DONE)
250 MSCH_EVENT((" ONFIRE_DONE"));
251 if (type & WL_MSCH_RC_FLAGS_SPLIT_SLOT_START)
252 MSCH_EVENT((" SPLIT_SLOT_START"));
253 if (type & WL_MSCH_RC_FLAGS_SPLIT_SLOT_END)
254 MSCH_EVENT((" SPLIT_SLOT_END"));
255 if (type & WL_MSCH_RC_FLAGS_PRE_ONFIRE_DONE)
256 MSCH_EVENT((" PRE_ONFIRE_DONE"));
257 }
258 MSCH_EVENT(("\n"));
259
260 MSCH_EVENT_HEAD(sn);
261 MSCH_EVENT(("pre_start_time: %s",
262 dhd_mschdbg_display_time(p->pre_start_time_h, p->pre_start_time_l)));
263
264 MSCH_EVENT((", start_time: %s",
265 dhd_mschdbg_display_time(p->start_time_h, p->start_time_l)));
266
267 MSCH_EVENT((", end_time: %s\n",
268 dhd_mschdbg_display_time(p->end_time_h, p->end_time_l)));
269
270 if (p->p_timeslot && (p->timeslot_ptr == 0)) {
271 MSCH_EVENT_HEAD(sn);
272 MSCH_EVENT(("<%s timeslot>: 0x%08x\n", title, ntoh32(p->p_timeslot)));
273 } else
274 dhd_mschdbg_timeslot_profiler_event_data(sn, ver, title, data, p->timeslot_ptr,
275 (p->timeslot_ptr == 0));
276}
277
278static void
279dhd_mschdbg_chan_ctxt_profiler_event_data(int sp, int ver, char *data, uint16 ptr, bool empty)
280{
281 int sn = sp + 4;
282 msch_chan_ctxt_profiler_event_data_t *p =
283 (msch_chan_ctxt_profiler_event_data_t *)(data + ntoh16(ptr));
284 chanspec_t c;
285 char buf[CHANSPEC_STR_LEN];
286
287 MSCH_EVENT_HEAD(sp);
288 MSCH_EVENT(("<chan_ctxt>: "));
289 if (empty) {
290 MSCH_EVENT((" null\n"));
291 return;
292 }
293 else
294 MSCH_EVENT(("0x%08x (prev 0x%08x, next 0x%08x)\n",
295 ntoh32(p->p_chan_ctxt), ntoh32(p->p_prev), ntoh32(p->p_next)));
296
297 c = (chanspec_t)ntoh16(p->chanspec);
298
299 MSCH_EVENT_HEAD(sn);
300 MSCH_EVENT(("channel: %s, bf_sch_pending: %s, bf_skipped: %d\n",
301 wf_chspec_ntoa(c, buf), p->bf_sch_pending? "TRUE" : "FALSE",
302 ntoh32(p->bf_skipped_count)));
303
304 MSCH_EVENT_HEAD(sn);
305 MSCH_EVENT(("bf_link: prev 0x%08x, next 0x%08x\n",
306 ntoh32(p->bf_link_prev), ntoh32(p->bf_link_next)));
307
308 MSCH_EVENT_HEAD(sn);
309 MSCH_EVENT(("onchan_time: %s",
310 dhd_mschdbg_display_time(p->onchan_time_h, p->onchan_time_l)));
311 MSCH_EVENT((", actual_onchan_dur: %s",
312 dhd_mschdbg_display_time(p->actual_onchan_dur_h, p->actual_onchan_dur_l)));
313 MSCH_EVENT((", pend_onchan_dur: %s\n",
314 dhd_mschdbg_display_time(p->pend_onchan_dur_h, p->pend_onchan_dur_l)));
315
316 dhd_mschdbg_elem_list(sn, "req_entity", data, p->req_entity_list_ptr,
317 p->req_entity_list_cnt);
318 dhd_mschdbg_elem_list(sn, "bf_entity", data, p->bf_entity_list_ptr,
319 p->bf_entity_list_cnt);
320}
321
322static void
323dhd_mschdbg_req_entity_profiler_event_data(int sp, int ver, char *data, uint16 ptr, bool empty)
324{
325 int sn = sp + 4;
326 msch_req_entity_profiler_event_data_t *p =
327 (msch_req_entity_profiler_event_data_t *)(data + ntoh16(ptr));
328 char buf[CHANSPEC_STR_LEN];
329 chanspec_t c;
330 uint32 flags;
331
332 MSCH_EVENT_HEAD(sp);
333 MSCH_EVENT(("<req_entity>: "));
334 if (empty) {
335 MSCH_EVENT((" null\n"));
336 return;
337 }
338 else
339 MSCH_EVENT(("0x%08x (prev 0x%08x, next 0x%08x)\n",
340 ntoh32(p->p_req_entity), ntoh32(p->req_hdl_link_prev),
341 ntoh32(p->req_hdl_link_next)));
342
343 MSCH_EVENT_HEAD(sn);
344 MSCH_EVENT(("req_hdl: [0x%08x]\n", ntoh32(p->p_req_hdl)));
345
346 MSCH_EVENT_HEAD(sn);
347 MSCH_EVENT(("chan_ctxt_link: prev 0x%08x, next 0x%08x\n",
348 ntoh32(p->chan_ctxt_link_prev), ntoh32(p->chan_ctxt_link_next)));
349 MSCH_EVENT_HEAD(sn);
350 MSCH_EVENT(("rt_specific_link: prev 0x%08x, next 0x%08x\n",
351 ntoh32(p->rt_specific_link_prev), ntoh32(p->rt_specific_link_next)));
352 MSCH_EVENT_HEAD(sn);
353 MSCH_EVENT(("start_fixed_link: prev 0x%08x, next 0x%08x\n",
354 ntoh32(p->start_fixed_link_prev), ntoh32(p->start_fixed_link_next)));
355 MSCH_EVENT_HEAD(sn);
356 MSCH_EVENT(("both_flex_list: prev 0x%08x, next 0x%08x\n",
357 ntoh32(p->both_flex_list_prev), ntoh32(p->both_flex_list_next)));
358
359 c = (chanspec_t)ntoh16(p->chanspec);
360 MSCH_EVENT_HEAD(sn);
361 if (ver >= 2) {
362 MSCH_EVENT(("channel: %s, onchan Id %d, current chan Id %d, priority %d",
363 wf_chspec_ntoa(c, buf), ntoh16(p->onchan_chn_idx), ntoh16(p->cur_chn_idx),
364 ntoh16(p->priority)));
365 flags = ntoh32(p->flags);
366 if (flags & WL_MSCH_ENTITY_FLAG_MULTI_INSTANCE)
367 MSCH_EVENT((" : MULTI_INSTANCE\n"));
368 else
369 MSCH_EVENT(("\n"));
370 MSCH_EVENT_HEAD(sn);
371 MSCH_EVENT(("actual_start_time: %s, ",
372 dhd_mschdbg_display_time(p->actual_start_time_h, p->actual_start_time_l)));
373 MSCH_EVENT(("curts_fire_time: %s, ",
374 dhd_mschdbg_display_time(p->curts_fire_time_h, p->curts_fire_time_l)));
375 } else {
376 MSCH_EVENT(("channel: %s, priority %d, ", wf_chspec_ntoa(c, buf),
377 ntoh16(p->priority)));
378 }
379 MSCH_EVENT(("bf_last_serv_time: %s\n",
380 dhd_mschdbg_display_time(p->bf_last_serv_time_h, p->bf_last_serv_time_l)));
381
382 dhd_mschdbg_req_timing_profiler_event_data(sn, ver, "current", data, p->cur_slot_ptr,
383 (p->cur_slot_ptr == 0));
384 dhd_mschdbg_req_timing_profiler_event_data(sn, ver, "pending", data, p->pend_slot_ptr,
385 (p->pend_slot_ptr == 0));
386
387 if (p->p_chan_ctxt && (p->chan_ctxt_ptr == 0)) {
388 MSCH_EVENT_HEAD(sn);
389 MSCH_EVENT(("<chan_ctxt>: 0x%08x\n", ntoh32(p->p_chan_ctxt)));
390 }
391 else
392 dhd_mschdbg_chan_ctxt_profiler_event_data(sn, ver, data, p->chan_ctxt_ptr,
393 (p->chan_ctxt_ptr == 0));
394}
395
396static void
397dhd_mschdbg_req_handle_profiler_event_data(int sp, int ver, char *data, uint16 ptr, bool empty)
398{
399 int sn = sp + 4;
400 msch_req_handle_profiler_event_data_t *p =
401 (msch_req_handle_profiler_event_data_t *)(data + ntoh16(ptr));
402 uint32 flags;
403
404 MSCH_EVENT_HEAD(sp);
405 MSCH_EVENT(("<req_handle>: "));
406 if (empty) {
407 MSCH_EVENT((" null\n"));
408 return;
409 }
410 else
411 MSCH_EVENT(("0x%08x (prev 0x%08x, next 0x%08x)\n",
412 ntoh32(p->p_req_handle), ntoh32(p->p_prev), ntoh32(p->p_next)));
413
414 dhd_mschdbg_elem_list(sn, "req_entity", data, p->req_entity_list_ptr,
415 p->req_entity_list_cnt);
416 MSCH_EVENT_HEAD(sn);
417 MSCH_EVENT(("cb_func: [0x%08x], cb_func: [0x%08x]",
418 ntoh32(p->cb_func), ntoh32(p->cb_ctxt)));
419 if (ver < 2) {
420 MSCH_EVENT((", chan_cnt: %d", ntoh16(p->chan_cnt)));
421 }
422 flags = ntoh32(p->flags);
423 if (flags & WL_MSCH_REQ_HDL_FLAGS_NEW_REQ)
424 MSCH_EVENT((", NEW_REQ"));
425 MSCH_EVENT(("\n"));
426
427 dhd_mschdbg_req_param_profiler_event_data(sn, ver, data, p->req_param_ptr);
428
429 if (ver >= 2) {
430 MSCH_EVENT_HEAD(sn);
431 MSCH_EVENT(("req_time: %s\n",
432 dhd_mschdbg_display_time(p->req_time_h, p->req_time_l)));
433 MSCH_EVENT_HEAD(sn);
434 MSCH_EVENT(("chan_cnt: %d, chan idx %d, last chan idx %d\n",
435 ntoh16(p->chan_cnt), ntoh16(p->chan_idx), ntoh16(p->last_chan_idx)));
436 if (p->chanspec_list && p->chanspec_cnt) {
437 dhd_mschdbg_chanspec_list(sn, data, p->chanspec_list, p->chanspec_cnt);
438 }
439 }
440}
441
442static void
443dhd_mschdbg_profiler_profiler_event_data(int sp, int ver, char *data, uint16 ptr)
444{
445 msch_profiler_profiler_event_data_t *p =
446 (msch_profiler_profiler_event_data_t *)(data + ntoh16(ptr));
447 uint32 flags;
448
449 MSCH_EVENT_HEAD(sp);
450 MSCH_EVENT(("free list: req_hdl 0x%08x, req_entity 0x%08x,"
451 " chan_ctxt 0x%08x, chanspec 0x%08x\n",
452 ntoh32(p->free_req_hdl_list), ntoh32(p->free_req_entity_list),
453 ntoh32(p->free_chan_ctxt_list), ntoh32(p->free_chanspec_list)));
454
455 MSCH_EVENT_HEAD(sp);
456 MSCH_EVENT(("alloc count: chanspec %d, req_entity %d, req_hdl %d, "
457 "chan_ctxt %d, timeslot %d\n",
458 ntoh16(p->msch_chanspec_alloc_cnt), ntoh16(p->msch_req_entity_alloc_cnt),
459 ntoh16(p->msch_req_hdl_alloc_cnt), ntoh16(p->msch_chan_ctxt_alloc_cnt),
460 ntoh16(p->msch_timeslot_alloc_cnt)));
461
462 dhd_mschdbg_elem_list(sp, "req_hdl", data, p->msch_req_hdl_list_ptr,
463 p->msch_req_hdl_list_cnt);
464 dhd_mschdbg_elem_list(sp, "chan_ctxt", data, p->msch_chan_ctxt_list_ptr,
465 p->msch_chan_ctxt_list_cnt);
466 dhd_mschdbg_elem_list(sp, "req_timing", data, p->msch_req_timing_list_ptr,
467 p->msch_req_timing_list_cnt);
468 dhd_mschdbg_elem_list(sp, "start_fixed", data, p->msch_start_fixed_list_ptr,
469 p->msch_start_fixed_list_cnt);
470 dhd_mschdbg_elem_list(sp, "both_flex_req_entity", data,
471 p->msch_both_flex_req_entity_list_ptr,
472 p->msch_both_flex_req_entity_list_cnt);
473 dhd_mschdbg_elem_list(sp, "start_flex", data, p->msch_start_flex_list_ptr,
474 p->msch_start_flex_list_cnt);
475 dhd_mschdbg_elem_list(sp, "both_flex", data, p->msch_both_flex_list_ptr,
476 p->msch_both_flex_list_cnt);
477
478 if (p->p_cur_msch_timeslot && (p->cur_msch_timeslot_ptr == 0)) {
479 MSCH_EVENT_HEAD(sp);
480 MSCH_EVENT(("<cur_msch timeslot>: 0x%08x\n",
481 ntoh32(p->p_cur_msch_timeslot)));
482 } else
483 dhd_mschdbg_timeslot_profiler_event_data(sp, ver, "cur_msch", data,
484 p->cur_msch_timeslot_ptr, (p->cur_msch_timeslot_ptr == 0));
485
486 if (p->p_next_timeslot && (p->next_timeslot_ptr == 0)) {
487 MSCH_EVENT_HEAD(sp);
488 MSCH_EVENT(("<next timeslot>: 0x%08x\n",
489 ntoh32(p->p_next_timeslot)));
490 } else
491 dhd_mschdbg_timeslot_profiler_event_data(sp, ver, "next", data,
492 p->next_timeslot_ptr, (p->next_timeslot_ptr == 0));
493
494 MSCH_EVENT_HEAD(sp);
495 MSCH_EVENT(("ts_id: %d, ", ntoh32(p->ts_id)));
496 flags = ntoh32(p->flags);
497 if (flags & WL_MSCH_STATE_IN_TIEMR_CTXT)
498 MSCH_EVENT(("IN_TIEMR_CTXT, "));
499 if (flags & WL_MSCH_STATE_SCHD_PENDING)
500 MSCH_EVENT(("SCHD_PENDING, "));
501 MSCH_EVENT(("slotskip_flags: %d, cur_armed_timeslot: 0x%08x\n",
502 (ver >= 2)? ntoh32(p->slotskip_flag) : 0, ntoh32(p->cur_armed_timeslot)));
503 MSCH_EVENT_HEAD(sp);
504 MSCH_EVENT(("flex_list_cnt: %d, service_interval: %d, "
505 "max_lo_prio_interval: %d\n",
506 ntoh16(p->flex_list_cnt), ntoh32(p->service_interval),
507 ntoh32(p->max_lo_prio_interval)));
508}
509
510static void dhd_mschdbg_dump_data(dhd_pub_t *dhdp, void *raw_event_ptr, int type,
511 char *data, int len)
512{
513 uint64 t = 0, tt = 0;
514 uint32 s = 0, ss = 0;
515 int wlc_index, ver;
516
517 ver = (type & WL_MSCH_PROFILER_VER_MASK) >> WL_MSCH_PROFILER_VER_SHIFT;
518 wlc_index = (type & WL_MSCH_PROFILER_WLINDEX_MASK) >> WL_MSCH_PROFILER_WLINDEX_SHIFT;
519 if (wlc_index >= 4)
520 return;
521
522 type &= WL_MSCH_PROFILER_TYPE_MASK;
523 if (type <= WL_MSCH_PROFILER_PROFILE_END) {
524 msch_profiler_event_data_t *pevent = (msch_profiler_event_data_t *)data;
525 tt = ((uint64)(ntoh32(pevent->time_hi)) << 32) | ntoh32(pevent->time_lo);
526 dhd_mschdbg_us_to_sec(pevent->time_hi, pevent->time_lo, &s, &ss);
527 }
528
529 if (lastMessages && (type != WL_MSCH_PROFILER_MESSAGE) &&
530 (type != WL_MSCH_PROFILER_EVENT_LOG)) {
531 MSCH_EVENT_HEAD(0);
532 MSCH_EVENT(("\n"));
533 lastMessages = FALSE;
534 }
535
536 switch (type) {
537 case WL_MSCH_PROFILER_START:
538 MSCH_EVENT_HEAD(0);
539 MSCH_EVENT(("%06d.%06d START\n", s, ss));
540 break;
541
542 case WL_MSCH_PROFILER_EXIT:
543 MSCH_EVENT_HEAD(0);
544 MSCH_EVENT(("%06d.%06d EXIT\n", s, ss));
545 break;
546
547 case WL_MSCH_PROFILER_REQ:
548 {
549 msch_req_profiler_event_data_t *p = (msch_req_profiler_event_data_t *)data;
550 MSCH_EVENT_HEAD(0);
551 MSCH_EVENT(("\n"));
552 MSCH_EVENT_HEAD(0);
553 MSCH_EVENT(("===============================\n"));
554 MSCH_EVENT_HEAD(0);
555 MSCH_EVENT(("%06d.%06d [wl%d] REGISTER:\n", s, ss, wlc_index));
556 dhd_mschdbg_req_param_profiler_event_data(4, ver, data, p->req_param_ptr);
557 dhd_mschdbg_chanspec_list(4, data, p->chanspec_ptr, p->chanspec_cnt);
558 MSCH_EVENT_HEAD(0);
559 MSCH_EVENT(("===============================\n"));
560 MSCH_EVENT_HEAD(0);
561 MSCH_EVENT(("\n"));
562 }
563 break;
564
565 case WL_MSCH_PROFILER_CALLBACK:
566 {
567 msch_callback_profiler_event_data_t *p =
568 (msch_callback_profiler_event_data_t *)data;
569 char buf[CHANSPEC_STR_LEN];
570 chanspec_t chanspec;
571 uint16 cbtype;
572
573 MSCH_EVENT_HEAD(0);
574 MSCH_EVENT(("%06d.%06d [wl%d] CALLBACK: ", s, ss, wlc_index));
575 chanspec = (chanspec_t)ntoh16(p->chanspec);
576 MSCH_EVENT(("req_hdl[0x%08x], channel %s --",
577 ntoh32(p->p_req_hdl), wf_chspec_ntoa(chanspec, buf)));
578
579 cbtype = ntoh16(p->type);
580 if (cbtype & WL_MSCH_CT_ON_CHAN)
581 MSCH_EVENT((" ON_CHAN"));
582 if (cbtype & WL_MSCH_CT_OFF_CHAN)
583 MSCH_EVENT((" OFF_CHAN"));
584 if (cbtype & WL_MSCH_CT_REQ_START)
585 MSCH_EVENT((" REQ_START"));
586 if (cbtype & WL_MSCH_CT_REQ_END)
587 MSCH_EVENT((" REQ_END"));
588 if (cbtype & WL_MSCH_CT_SLOT_START)
589 MSCH_EVENT((" SLOT_START"));
590 if (cbtype & WL_MSCH_CT_SLOT_SKIP)
591 MSCH_EVENT((" SLOT_SKIP"));
592 if (cbtype & WL_MSCH_CT_SLOT_END)
593 MSCH_EVENT((" SLOT_END"));
594 if (cbtype & WL_MSCH_CT_OFF_CHAN_DONE)
595 MSCH_EVENT((" OFF_CHAN_DONE"));
596 if (cbtype & WL_MSCH_CT_PARTIAL)
597 MSCH_EVENT((" PARTIAL"));
598 if (cbtype & WL_MSCH_CT_PRE_ONCHAN)
599 MSCH_EVENT((" PRE_ONCHAN"));
600 if (cbtype & WL_MSCH_CT_PRE_REQ_START)
601 MSCH_EVENT((" PRE_REQ_START"));
602
603 if (cbtype & WL_MSCH_CT_REQ_START) {
604 req_start[wlc_index] = 1;
605 req_start_time[wlc_index] = tt;
606 } else if (cbtype & WL_MSCH_CT_REQ_END) {
607 if (req_start[wlc_index]) {
608 MSCH_EVENT((" : REQ duration %d",
609 (uint32)(tt - req_start_time[wlc_index])));
610 req_start[wlc_index] = 0;
611 }
612 }
613
614 if (cbtype & WL_MSCH_CT_SLOT_START) {
615 solt_chanspec[wlc_index] = p->chanspec;
616 solt_start_time[wlc_index] = tt;
617 } else if (cbtype & WL_MSCH_CT_SLOT_END) {
618 if (p->chanspec == solt_chanspec[wlc_index]) {
619 MSCH_EVENT((" : SLOT duration %d",
620 (uint32)(tt - solt_start_time[wlc_index])));
621 solt_chanspec[wlc_index] = 0;
622 }
623 }
624 MSCH_EVENT(("\n"));
625
626 if (cbtype & (WL_MSCH_CT_ON_CHAN | WL_MSCH_CT_SLOT_SKIP)) {
627 MSCH_EVENT_HEAD(4);
628 if (cbtype & WL_MSCH_CT_ON_CHAN) {
629 MSCH_EVENT(("ID %d onchan idx %d cur_chan_seq_start %s ",
630 ntoh32(p->timeslot_id), ntoh32(p->onchan_idx),
631 dhd_mschdbg_display_time(p->cur_chan_seq_start_time_h,
632 p->cur_chan_seq_start_time_l)));
633 }
634 t = ((uint64)(ntoh32(p->start_time_h)) << 32) |
635 ntoh32(p->start_time_l);
636 MSCH_EVENT(("start %s ",
637 dhd_mschdbg_display_time(p->start_time_h,
638 p->start_time_l)));
639 tt = ((uint64)(ntoh32(p->end_time_h)) << 32) | ntoh32(p->end_time_l);
640 MSCH_EVENT(("end %s duration %d\n",
641 dhd_mschdbg_display_time(p->end_time_h, p->end_time_l),
642 (p->end_time_h == 0xffffffff && p->end_time_l == 0xffffffff)?
643 -1 : (int)(tt - t)));
644 }
645
646 }
647 break;
648
649 case WL_MSCH_PROFILER_EVENT_LOG:
650 {
651 while (len >= (int)WL_MSCH_EVENT_LOG_HEAD_SIZE) {
652 msch_event_log_profiler_event_data_t *p =
653 (msch_event_log_profiler_event_data_t *)data;
654 /* TODO: How to parse MSCH if extended event tag is present ??? */
655 prcd_event_log_hdr_t hdr;
656 int size = WL_MSCH_EVENT_LOG_HEAD_SIZE + p->hdr.count * sizeof(uint32);
657 if (len < size || size > sizeof(msch_event_log_profiler_event_data_t)) {
658 break;
659 }
660 data += size;
661 len -= size;
662 dhd_mschdbg_us_to_sec(p->time_hi, p->time_lo, &s, &ss);
663 MSCH_EVENT_HEAD(0);
664 MSCH_EVENT(("%06d.%06d [wl%d]: ", s, ss, p->hdr.tag));
665 bzero(&hdr, sizeof(hdr));
666 hdr.tag = EVENT_LOG_TAG_MSCHPROFILE;
667 hdr.count = p->hdr.count + 1;
668 /* exclude LSB 2 bits which indicate binary/non-binary data */
669 hdr.fmt_num = ntoh16(p->hdr.fmt_num) >> 2;
670 hdr.fmt_num_raw = ntoh16(p->hdr.fmt_num);
671 if (ntoh16(p->hdr.fmt_num) == DHD_OW_BI_RAW_EVENT_LOG_FMT) {
672 hdr.binary_payload = TRUE;
673 }
674 dhd_dbg_verboselog_printf(dhdp, &hdr, raw_event_ptr, p->data, 0, 0);
675 }
676 lastMessages = TRUE;
677 break;
678 }
679
680 case WL_MSCH_PROFILER_MESSAGE:
681 {
682 msch_message_profiler_event_data_t *p = (msch_message_profiler_event_data_t *)data;
683 MSCH_EVENT_HEAD(0);
684 MSCH_EVENT(("%06d.%06d [wl%d]: %s", s, ss, wlc_index, p->message));
685 lastMessages = TRUE;
686 break;
687 }
688
689 case WL_MSCH_PROFILER_PROFILE_START:
690 profiler_start_time[wlc_index] = tt;
691 MSCH_EVENT_HEAD(0);
692 MSCH_EVENT(("-------------------------------\n"));
693 MSCH_EVENT_HEAD(0);
694 MSCH_EVENT(("%06d.%06d [wl%d] PROFILE DATA:\n", s, ss, wlc_index));
695 dhd_mschdbg_profiler_profiler_event_data(4, ver, data, 0);
696 break;
697
698 case WL_MSCH_PROFILER_PROFILE_END:
699 MSCH_EVENT_HEAD(0);
700 MSCH_EVENT(("%06d.%06d [wl%d] PROFILE END: take time %d\n", s, ss,
701 wlc_index, (uint32)(tt - profiler_start_time[wlc_index])));
702 MSCH_EVENT_HEAD(0);
703 MSCH_EVENT(("-------------------------------\n"));
704 MSCH_EVENT_HEAD(0);
705 MSCH_EVENT(("\n"));
706 break;
707
708 case WL_MSCH_PROFILER_REQ_HANDLE:
709 dhd_mschdbg_req_handle_profiler_event_data(4, ver, data, 0, FALSE);
710 break;
711
712 case WL_MSCH_PROFILER_REQ_ENTITY:
713 dhd_mschdbg_req_entity_profiler_event_data(4, ver, data, 0, FALSE);
714 break;
715
716 case WL_MSCH_PROFILER_CHAN_CTXT:
717 dhd_mschdbg_chan_ctxt_profiler_event_data(4, ver, data, 0, FALSE);
718 break;
719
720 case WL_MSCH_PROFILER_REQ_TIMING:
721 dhd_mschdbg_req_timing_profiler_event_data(4, ver, "msch", data, 0, FALSE);
722 break;
723
724 default:
725 MSCH_EVENT_HEAD(0);
726 MSCH_EVENT(("[wl%d] ERROR: unsupported EVENT reason code:%d; ",
727 wlc_index, type));
728 break;
729 }
730}
731
732void
733wl_mschdbg_event_handler(dhd_pub_t *dhdp, void *raw_event_ptr, int type, void *data, int len)
734{
735 head_log = "MSCH";
736 dhd_mschdbg_dump_data(dhdp, raw_event_ptr, type, (char *)data, len);
737}
738
739void
740wl_mschdbg_verboselog_handler(dhd_pub_t *dhdp, void *raw_event_ptr, prcd_event_log_hdr_t *plog_hdr,
741 uint32 *log_ptr)
742{
743 uint32 log_pyld_len;
744 head_log = "CONSOLE";
745
746 if (plog_hdr->count == 0) {
747 return;
748 }
749 log_pyld_len = (plog_hdr->count - 1) * DATA_UNIT_FOR_LOG_CNT;
750
751 if (plog_hdr->tag == EVENT_LOG_TAG_MSCHPROFILE) {
752 msch_event_log_profiler_event_data_t *p =
753 (msch_event_log_profiler_event_data_t *)log_ptr;
754 /* TODO: How to parse MSCH if extended event tag is present ??? */
755 prcd_event_log_hdr_t hdr;
756 uint32 s, ss;
757
758 if (log_pyld_len < OFFSETOF(msch_event_log_profiler_event_data_t, data) ||
759 log_pyld_len > sizeof(msch_event_log_profiler_event_data_t)) {
760 return;
761 }
762
763 dhd_mschdbg_us_to_sec(p->time_hi, p->time_lo, &s, &ss);
764 MSCH_EVENT_HEAD(0);
765 MSCH_EVENT(("%06d.%06d [wl%d]: ", s, ss, p->hdr.tag));
766 bzero(&hdr, sizeof(hdr));
767 hdr.tag = EVENT_LOG_TAG_MSCHPROFILE;
768 hdr.count = p->hdr.count + 1;
769 /* exclude LSB 2 bits which indicate binary/non-binary data */
770 hdr.fmt_num = ntoh16(p->hdr.fmt_num) >> 2;
771 hdr.fmt_num_raw = ntoh16(p->hdr.fmt_num);
772 if (ntoh16(p->hdr.fmt_num) == DHD_OW_BI_RAW_EVENT_LOG_FMT) {
773 hdr.binary_payload = TRUE;
774 }
775 dhd_dbg_verboselog_printf(dhdp, &hdr, raw_event_ptr, p->data, 0, 0);
776 } else {
777 msch_collect_tlv_t *p = (msch_collect_tlv_t *)log_ptr;
778 int type = ntoh16(p->type);
779 int len = ntoh16(p->size);
780
781 if (log_pyld_len < OFFSETOF(msch_collect_tlv_t, value) + len) {
782 return;
783 }
784
785 dhd_mschdbg_dump_data(dhdp, raw_event_ptr, type, p->value, len);
786 }
787}
788#endif /* SHOW_LOGTRACE */