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