wlan_roam_debug.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /*
  2. * Copyright (c) 2013-2018, 2020-2021 The Linux Foundation. All rights reserved.
  3. * Copyright (c) 2021 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. * DOC: Roaming debug log operations routines and global data
  21. */
  22. #include <qdf_types.h>
  23. #include <qdf_atomic.h>
  24. #include <qdf_mem.h>
  25. #include <qdf_time.h>
  26. #include <qdf_trace.h>
  27. #include <qdf_module.h>
  28. #include <wlan_cmn.h>
  29. #include "wlan_roam_debug.h"
  30. #ifdef FEATURE_ROAM_DEBUG
  31. static void wlan_roam_rec_print(struct wlan_roam_debug_rec *dbg_rec,
  32. uint32_t idx, uint32_t delta,
  33. bool to_kernel);
  34. static void wlan_conn_rec_print(struct wlan_roam_debug_rec *dbg_rec,
  35. uint32_t idx, uint32_t delta,
  36. bool to_kernel);
  37. #ifdef WLAN_LOGGING_BUFFERS_DYNAMICALLY
  38. static struct wlan_roam_debug_info *global_wlan_roam_debug_table;
  39. /**
  40. * wlan_roam_debug_init() - Allocate log buffer dynamically
  41. *
  42. * Return: none
  43. */
  44. void wlan_roam_debug_init(void)
  45. {
  46. uint8_t i;
  47. global_wlan_roam_debug_table = qdf_mem_valloc(
  48. sizeof(struct wlan_roam_debug_info) * REC_MAX);
  49. QDF_BUG(global_wlan_roam_debug_table);
  50. if (global_wlan_roam_debug_table) {
  51. for (i = 0; i < REC_MAX; i++) {
  52. qdf_atomic_init(&global_wlan_roam_debug_table[i].index);
  53. global_wlan_roam_debug_table[i].num_max_rec =
  54. WLAN_ROAM_DEBUG_MAX_REC;
  55. if (i == REC_ROAM)
  56. global_wlan_roam_debug_table[i].rec_print =
  57. wlan_roam_rec_print;
  58. else
  59. global_wlan_roam_debug_table[i].rec_print =
  60. wlan_conn_rec_print;
  61. }
  62. }
  63. }
  64. qdf_export_symbol(wlan_roam_debug_init);
  65. static inline struct wlan_roam_debug_info *wlan_roam_debug_get_table(
  66. wlan_rec_type type)
  67. {
  68. if (type >= REC_MAX)
  69. return NULL;
  70. return &global_wlan_roam_debug_table[type];
  71. }
  72. /**
  73. * wlan_roam_debug_deinit() - Free log buffer allocated dynamically
  74. *
  75. * Return: none
  76. */
  77. void wlan_roam_debug_deinit(void)
  78. {
  79. qdf_mem_vfree(global_wlan_roam_debug_table);
  80. global_wlan_roam_debug_table = NULL;
  81. }
  82. qdf_export_symbol(wlan_roam_debug_deinit);
  83. #else /* WLAN_LOGGING_BUFFERS_DYNAMICALLY */
  84. /*
  85. * wlan roam debug log is stored in this global structure. It can be accessed
  86. * without requiring any psoc or vdev context. It will be accessible in
  87. * the crash dump without having to dereference complex stack traces.
  88. */
  89. static struct wlan_roam_debug_info global_wlan_roam_debug_table[REC_MAX] = {
  90. [REC_ROAM] = {{ 0 },
  91. .num_max_rec = WLAN_ROAM_DEBUG_MAX_REC,
  92. .rec_print = wlan_roam_rec_print},
  93. [REC_CONN] = {{ 0 },
  94. .num_max_rec = WLAN_ROAM_DEBUG_MAX_REC,
  95. .rec_print = wlan_conn_rec_print},
  96. };
  97. static inline struct wlan_roam_debug_info *wlan_roam_debug_get_table(
  98. wlan_rec_type type)
  99. {
  100. if (type >= REC_MAX)
  101. return NULL;
  102. return &global_wlan_roam_debug_table[type];
  103. }
  104. #endif /* WLAN_LOGGING_BUFFERS_DYNAMICALLY */
  105. /**
  106. * wlan_roam_next_debug_log_index() - atomically increment and wrap around index
  107. * @index: address of index to increment
  108. * @size: wrap around this value
  109. *
  110. * Return: new value of index
  111. */
  112. static int wlan_roam_next_debug_log_index(qdf_atomic_t *index, int size)
  113. {
  114. int i = qdf_atomic_inc_return(index);
  115. if (i == WLAN_ROAM_DEBUG_MAX_REC)
  116. qdf_atomic_sub(WLAN_ROAM_DEBUG_MAX_REC, index);
  117. while (i >= size)
  118. i -= WLAN_ROAM_DEBUG_MAX_REC;
  119. return i;
  120. }
  121. /**
  122. * wlan_roam_debug_log() - Add a debug log entry to wlan roam debug records
  123. * @vdev_id: vdev identifier
  124. * @op: operation identifier
  125. * @peer_id: peer id
  126. * @mac_addr: mac address of peer, can be NULL
  127. * @peer_obj: peer object address, can be NULL
  128. * @arg1: extra argument #1
  129. * @arg2: extra argument #2
  130. *
  131. * Return: none
  132. */
  133. void wlan_roam_debug_log(uint8_t vdev_id, uint8_t op,
  134. uint16_t peer_id, void *mac_addr,
  135. void *peer_obj, uint32_t arg1, uint32_t arg2)
  136. {
  137. wlan_rec_debug_log(REC_ROAM, vdev_id, op, peer_id, mac_addr,
  138. peer_obj, arg1, arg2);
  139. }
  140. qdf_export_symbol(wlan_roam_debug_log);
  141. void wlan_rec_debug_log(wlan_rec_type rec_type, uint8_t vdev_id, uint8_t op,
  142. uint16_t peer_id, const void *mac_addr,
  143. void *peer_obj, uint32_t arg1, uint32_t arg2)
  144. {
  145. uint32_t i;
  146. struct wlan_roam_debug_info *dbg_tbl;
  147. struct wlan_roam_debug_rec *rec;
  148. dbg_tbl = wlan_roam_debug_get_table(rec_type);
  149. if (!dbg_tbl)
  150. return;
  151. i = wlan_roam_next_debug_log_index(
  152. &dbg_tbl->index,
  153. WLAN_ROAM_DEBUG_MAX_REC);
  154. rec = &dbg_tbl->rec[i];
  155. rec->time = qdf_get_log_timestamp();
  156. rec->operation = op;
  157. rec->vdev_id = vdev_id;
  158. rec->peer_id = peer_id;
  159. if (mac_addr)
  160. qdf_mem_copy(rec->mac_addr.bytes, mac_addr,
  161. QDF_MAC_ADDR_SIZE);
  162. else
  163. qdf_mem_zero(rec->mac_addr.bytes,
  164. QDF_MAC_ADDR_SIZE);
  165. rec->peer_obj = peer_obj;
  166. rec->arg1 = arg1;
  167. rec->arg2 = arg2;
  168. }
  169. qdf_export_symbol(wlan_rec_debug_log);
  170. /**
  171. * wlan_roam_debug_string() - convert operation value to printable string
  172. * @op: operation identifier
  173. *
  174. * Return: printable string for the operation
  175. */
  176. static char *wlan_roam_debug_string(uint32_t op)
  177. {
  178. switch (op) {
  179. case DEBUG_PEER_CREATE_SEND:
  180. return "peer create send";
  181. case DEBUG_PEER_CREATE_RESP:
  182. return "peer create resp_event";
  183. case DEBUG_PEER_DELETE_SEND:
  184. return "peer delete send";
  185. case DEBUG_PEER_DELETE_RESP:
  186. return "peer delete resp_event";
  187. case DEBUG_PEER_MAP_EVENT:
  188. return "peer map event";
  189. case DEBUG_PEER_UNMAP_EVENT:
  190. return "peer unmap event";
  191. case DEBUG_PEER_UNREF_DELETE:
  192. return "peer unref delete";
  193. case DEBUG_DELETING_PEER_OBJ:
  194. return "peer obj deleted";
  195. case DEBUG_ROAM_SYNCH_IND:
  196. return "roam synch ind event";
  197. case DEBUG_ROAM_SYNCH_CNF:
  198. return "roam sync conf sent";
  199. case DEBUG_ROAM_SYNCH_FAIL:
  200. return "roam sync fail event";
  201. case DEBUG_ROAM_EVENT:
  202. return "roam event";
  203. case DEBUG_WOW_ROAM_EVENT:
  204. return "wow wakeup roam event";
  205. case DEBUG_BUS_SUSPEND:
  206. return "host suspend";
  207. case DEBUG_BUS_RESUME:
  208. return "host wakeup";
  209. case DEBUG_WOW_REASON:
  210. return "wow wakeup reason";
  211. case DEBUG_CONN_CONNECTING:
  212. return "conn";
  213. case DEBUG_CONN_ASSOCIATION:
  214. return "assoc";
  215. case DEBUG_CONN_CONNECT_RESULT:
  216. return "cnrlt";
  217. case DEBUG_CONN_ROAMING:
  218. return "roaming";
  219. case DEBUG_CONN_ROAMED:
  220. return "roamed";
  221. case DEBUG_CONN_ROAMED_IND:
  222. return "rmind";
  223. case DEBUG_CONN_DISCONNECT:
  224. return "disc";
  225. case DEBUG_CONN_DISCONNECT_HANDLER:
  226. return "dishdr";
  227. case DEBUG_CONN_DISCONNECT_IND:
  228. return "disind";
  229. case DEBUG_CONN_RSO:
  230. return "rso";
  231. default:
  232. return "unknown";
  233. }
  234. }
  235. void wlan_roam_rec_print(struct wlan_roam_debug_rec *dbg_rec,
  236. uint32_t idx, uint32_t delta,
  237. bool to_kernel)
  238. {
  239. roam_debug("index = %5d timestamp = 0x%016llx delta ms = %-12u",
  240. idx, dbg_rec->time, delta);
  241. roam_debug("info = %-24s vdev_id = %-3d mac addr = "QDF_MAC_ADDR_FMT,
  242. wlan_roam_debug_string(dbg_rec->operation),
  243. (int8_t)dbg_rec->vdev_id,
  244. QDF_MAC_ADDR_REF(dbg_rec->mac_addr.bytes));
  245. roam_debug("peer obj = 0x%pK peer_id = %-4d", dbg_rec->peer_obj,
  246. (int8_t)dbg_rec->peer_id);
  247. roam_debug("arg1 = 0x%-8x arg2 = 0x%-8x", dbg_rec->arg1,
  248. dbg_rec->arg2);
  249. }
  250. void wlan_conn_rec_print(struct wlan_roam_debug_rec *dbg_rec,
  251. uint32_t idx, uint32_t delta,
  252. bool to_kernel)
  253. {
  254. if (to_kernel) {
  255. roam_info("i %d ti 0x%08llx ms %u vdv %d %s a1 0x%x a2 0x%x "QDF_MAC_ADDR_FMT,
  256. idx, dbg_rec->time, delta, (int8_t)dbg_rec->vdev_id,
  257. wlan_roam_debug_string(dbg_rec->operation),
  258. dbg_rec->arg1, dbg_rec->arg2,
  259. QDF_MAC_ADDR_REF(dbg_rec->mac_addr.bytes));
  260. } else {
  261. roam_debug("i %d ti 0x%08llx ms %u vdv %d %s a1 0x%x a2 0x%x "QDF_MAC_ADDR_FMT,
  262. idx, dbg_rec->time, delta, (int8_t)dbg_rec->vdev_id,
  263. wlan_roam_debug_string(dbg_rec->operation),
  264. dbg_rec->arg1, dbg_rec->arg2,
  265. QDF_MAC_ADDR_REF(dbg_rec->mac_addr.bytes));
  266. }
  267. }
  268. /**
  269. * wlan_rec_debug_dump_table() - Print the wlan roam debug log records
  270. * print all the valid debug records in the order of timestamp
  271. *
  272. * Return: none
  273. */
  274. void wlan_rec_debug_dump_table(wlan_rec_type rec_type, uint32_t count,
  275. bool to_kernel)
  276. {
  277. uint32_t i;
  278. int32_t current_index;
  279. struct wlan_roam_debug_info *dbg_tbl;
  280. struct wlan_roam_debug_rec *dbg_rec;
  281. uint64_t startt = 0;
  282. uint32_t delta;
  283. #define DEBUG_CLOCK_TICKS_PER_MSEC 19200
  284. if (count > WLAN_ROAM_DEBUG_MAX_REC)
  285. count = WLAN_ROAM_DEBUG_MAX_REC;
  286. dbg_tbl = wlan_roam_debug_get_table(rec_type);
  287. if (!dbg_tbl)
  288. return;
  289. current_index = qdf_atomic_read(&dbg_tbl->index);
  290. if (current_index < 0) {
  291. roam_debug("No records to dump");
  292. return;
  293. }
  294. roam_debug("dump %d rec type %d idx %d", count, rec_type,
  295. current_index);
  296. i = (current_index + WLAN_ROAM_DEBUG_MAX_REC - count) %
  297. WLAN_ROAM_DEBUG_MAX_REC;
  298. do {
  299. /* wrap around */
  300. i = (i + 1) % WLAN_ROAM_DEBUG_MAX_REC;
  301. dbg_rec = &dbg_tbl->rec[i];
  302. /* skip unused entry */
  303. if (dbg_rec->time == 0)
  304. continue;
  305. if (count == 0)
  306. break;
  307. count--;
  308. if (startt == 0)
  309. startt = dbg_rec->time;
  310. /*
  311. * Divide by 19200 == right shift 8 bits, then divide by 75
  312. * 32 bit computation keeps both 32 and 64 bit compilers happy.
  313. * The value will roll over after approx. 33554 seconds.
  314. */
  315. delta = (uint32_t) (((dbg_rec->time - startt) >> 8) &
  316. 0xffffffff);
  317. delta = delta / (DEBUG_CLOCK_TICKS_PER_MSEC >> 8);
  318. if (dbg_tbl->rec_print)
  319. dbg_tbl->rec_print(dbg_rec, i, delta, to_kernel);
  320. } while (i != current_index);
  321. }
  322. qdf_export_symbol(wlan_rec_debug_dump_table);
  323. /**
  324. * wlan_roam_debug_dump_table() - Print the wlan roam debug log records
  325. * print all the valid debug records in the order of timestamp
  326. *
  327. * Return: none
  328. */
  329. void wlan_roam_debug_dump_table(void)
  330. {
  331. wlan_rec_debug_dump_table(REC_ROAM, WLAN_ROAM_DEBUG_MAX_REC, false);
  332. }
  333. qdf_export_symbol(wlan_roam_debug_dump_table);
  334. #endif /* FEATURE_ROAM_DEBUG */