dhd_mschdbg.c 26 KB

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