qdf_trace.c 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696
  1. /*
  2. * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved.
  3. *
  4. * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  5. *
  6. *
  7. * Permission to use, copy, modify, and/or distribute this software for
  8. * any purpose with or without fee is hereby granted, provided that the
  9. * above copyright notice and this permission notice appear in all
  10. * copies.
  11. *
  12. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  13. * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  14. * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
  15. * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  16. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  17. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  18. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  19. * PERFORMANCE OF THIS SOFTWARE.
  20. */
  21. /*
  22. * This file was originally distributed by Qualcomm Atheros, Inc.
  23. * under proprietary terms before Copyright ownership was assigned
  24. * to the Linux Foundation.
  25. */
  26. /**
  27. * DOC: qdf_trace
  28. * QCA driver framework (QDF) trace APIs
  29. * Trace, logging, and debugging definitions and APIs
  30. */
  31. /* Include Files */
  32. #include <qdf_trace.h>
  33. #include <wlan_logging_sock_svc.h>
  34. #include "qdf_time.h"
  35. /* Preprocessor definitions and constants */
  36. #define QDF_TRACE_BUFFER_SIZE (512)
  37. enum qdf_timestamp_unit qdf_log_timestamp_type = QDF_LOG_TIMESTAMP_UNIT;
  38. /* macro to map qdf trace levels into the bitmask */
  39. #define QDF_TRACE_LEVEL_TO_MODULE_BITMASK(_level) ((1 << (_level)))
  40. /**
  41. * typedef struct module_trace_info - Trace level for a module, as a bitmask.
  42. * The bits in this mask are ordered by QDF_TRACE_LEVEL. For example,
  43. * each bit represents one of the bits in QDF_TRACE_LEVEL that may be turned
  44. * on to have traces at that level logged, i.e. if QDF_TRACE_LEVEL_ERROR is
  45. * == 2, then if bit 2 (low order) is turned ON, then ERROR traces will be
  46. * printed to the trace log. Note that all bits turned OFF means no traces
  47. * @module_trace_level: trace level
  48. * @module_name_str: 3 character string name for the module
  49. */
  50. typedef struct {
  51. uint16_t module_trace_level;
  52. unsigned char module_name_str[4];
  53. } module_trace_info;
  54. #define QDF_DEFAULT_TRACE_LEVEL \
  55. ((1 << QDF_TRACE_LEVEL_FATAL) | (1 << QDF_TRACE_LEVEL_ERROR))
  56. /* Array of static data that contains all of the per module trace
  57. * information. This includes the trace level for the module and
  58. * the 3 character 'name' of the module for marking the trace logs
  59. */
  60. module_trace_info g_qdf_trace_info[QDF_MODULE_ID_MAX] = {
  61. [QDF_MODULE_ID_TLSHIM] = {QDF_DEFAULT_TRACE_LEVEL, "DP"},
  62. [QDF_MODULE_ID_WMI] = {QDF_DEFAULT_TRACE_LEVEL, "WMI"},
  63. [QDF_MODULE_ID_HDD] = {QDF_DEFAULT_TRACE_LEVEL, "HDD"},
  64. [QDF_MODULE_ID_SME] = {QDF_DEFAULT_TRACE_LEVEL, "SME"},
  65. [QDF_MODULE_ID_PE] = {QDF_DEFAULT_TRACE_LEVEL, "PE "},
  66. [QDF_MODULE_ID_WMA] = {QDF_DEFAULT_TRACE_LEVEL, "WMA"},
  67. [QDF_MODULE_ID_SYS] = {QDF_DEFAULT_TRACE_LEVEL, "SYS"},
  68. [QDF_MODULE_ID_QDF] = {QDF_DEFAULT_TRACE_LEVEL, "QDF"},
  69. [QDF_MODULE_ID_SAP] = {QDF_DEFAULT_TRACE_LEVEL, "SAP"},
  70. [QDF_MODULE_ID_HDD_SOFTAP] = {QDF_DEFAULT_TRACE_LEVEL, "HSP"},
  71. [QDF_MODULE_ID_HDD_DATA] = {QDF_DEFAULT_TRACE_LEVEL, "HDP"},
  72. [QDF_MODULE_ID_HDD_SAP_DATA] = {QDF_DEFAULT_TRACE_LEVEL, "SDP"},
  73. [QDF_MODULE_ID_BMI] = {QDF_DEFAULT_TRACE_LEVEL, "BMI"},
  74. [QDF_MODULE_ID_HIF] = {QDF_DEFAULT_TRACE_LEVEL, "HIF"},
  75. [QDF_MODULE_ID_TXRX] = {QDF_DEFAULT_TRACE_LEVEL, "TRX"},
  76. [QDF_MODULE_ID_HTT] = {QDF_DEFAULT_TRACE_LEVEL, "HTT"},
  77. };
  78. /* Static and Global variables */
  79. static spinlock_t ltrace_lock;
  80. static qdf_trace_record_t g_qdf_trace_tbl[MAX_QDF_TRACE_RECORDS];
  81. /* global qdf trace data */
  82. static t_qdf_trace_data g_qdf_trace_data;
  83. /*
  84. * all the call back functions for dumping MTRACE messages from ring buffer
  85. * are stored in qdf_trace_cb_table,these callbacks are initialized during init
  86. * only so, we will make a copy of these call back functions and maintain in to
  87. * qdf_trace_restore_cb_table. Incase if we make modifications to
  88. * qdf_trace_cb_table, we can certainly retrieve all the call back functions
  89. * back from Restore Table
  90. */
  91. static tp_qdf_trace_cb qdf_trace_cb_table[QDF_MODULE_ID_MAX];
  92. static tp_qdf_trace_cb qdf_trace_restore_cb_table[QDF_MODULE_ID_MAX];
  93. static tp_qdf_state_info_cb qdf_state_info_table[QDF_MODULE_ID_MAX];
  94. #ifdef FEATURE_DP_TRACE
  95. /* Static and Global variables */
  96. static spinlock_t l_dp_trace_lock;
  97. static struct qdf_dp_trace_record_s
  98. g_qdf_dp_trace_tbl[MAX_QDF_DP_TRACE_RECORDS];
  99. /*
  100. * all the options to configure/control DP trace are
  101. * defined in this structure
  102. */
  103. static struct s_qdf_dp_trace_data g_qdf_dp_trace_data;
  104. /*
  105. * all the call back functions for dumping DPTRACE messages from ring buffer
  106. * are stored in qdf_dp_trace_cb_table, callbacks are initialized during init
  107. */
  108. static tp_qdf_dp_trace_cb qdf_dp_trace_cb_table[QDF_DP_TRACE_MAX+1];
  109. #endif
  110. /**
  111. * qdf_trace_set_level() - Set the trace level for a particular module
  112. * @module: Module id
  113. * @level : trace level
  114. *
  115. * Trace level is a member of the QDF_TRACE_LEVEL enumeration indicating
  116. * the severity of the condition causing the trace message to be issued.
  117. * More severe conditions are more likely to be logged.
  118. *
  119. * This is an external API that allows trace levels to be set for each module.
  120. *
  121. * Return: None
  122. */
  123. void qdf_trace_set_level(QDF_MODULE_ID module, QDF_TRACE_LEVEL level)
  124. {
  125. /* make sure the caller is passing in a valid LEVEL */
  126. if (level >= QDF_TRACE_LEVEL_MAX) {
  127. pr_err("%s: Invalid trace level %d passed in!\n", __func__,
  128. level);
  129. return;
  130. }
  131. /* Treat 'none' differently. NONE means we have to run off all
  132. * the bits in the bit mask so none of the traces appear. Anything
  133. * other than 'none' means we need to turn ON a bit in the bitmask
  134. */
  135. if (QDF_TRACE_LEVEL_NONE == level)
  136. g_qdf_trace_info[module].module_trace_level =
  137. QDF_TRACE_LEVEL_NONE;
  138. else
  139. /* set the desired bit in the bit mask for the module trace
  140. * level */
  141. g_qdf_trace_info[module].module_trace_level |=
  142. QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level);
  143. }
  144. EXPORT_SYMBOL(qdf_trace_set_level);
  145. /**
  146. * qdf_trace_set_module_trace_level() - Set module trace level
  147. * @module: Module id
  148. * @level: Trace level for a module, as a bitmask as per 'module_trace_info'
  149. *
  150. * Sets the module trace level where the trace level is given as a bit mask
  151. *
  152. * Return: None
  153. */
  154. void qdf_trace_set_module_trace_level(QDF_MODULE_ID module, uint32_t level)
  155. {
  156. if (module < 0 || module >= QDF_MODULE_ID_MAX) {
  157. pr_err("%s: Invalid module id %d passed\n", __func__, module);
  158. return;
  159. }
  160. g_qdf_trace_info[module].module_trace_level = level;
  161. }
  162. EXPORT_SYMBOL(qdf_trace_set_module_trace_level);
  163. /**
  164. * qdf_trace_set_value() - Set module trace value
  165. * @module: Module id
  166. * @level: Trace level for a module, as a bitmask as per 'module_trace_info'
  167. * @on: set/clear the desired bit in the bit mask
  168. *
  169. * Return: None
  170. */
  171. void qdf_trace_set_value(QDF_MODULE_ID module, QDF_TRACE_LEVEL level,
  172. uint8_t on)
  173. {
  174. /* make sure the caller is passing in a valid LEVEL */
  175. if (level < 0 || level >= QDF_TRACE_LEVEL_MAX) {
  176. pr_err("%s: Invalid trace level %d passed in!\n", __func__,
  177. level);
  178. return;
  179. }
  180. /* make sure the caller is passing in a valid module */
  181. if (module < 0 || module >= QDF_MODULE_ID_MAX) {
  182. pr_err("%s: Invalid module id %d passed in!\n", __func__,
  183. module);
  184. return;
  185. }
  186. /* Treat 'none' differently. NONE means we have to turn off all
  187. the bits in the bit mask so none of the traces appear */
  188. if (QDF_TRACE_LEVEL_NONE == level) {
  189. g_qdf_trace_info[module].module_trace_level =
  190. QDF_TRACE_LEVEL_NONE;
  191. }
  192. /* Treat 'All' differently. All means we have to turn on all
  193. the bits in the bit mask so all of the traces appear */
  194. else if (QDF_TRACE_LEVEL_ALL == level) {
  195. g_qdf_trace_info[module].module_trace_level = 0xFFFF;
  196. } else {
  197. if (on)
  198. /* set the desired bit in the bit mask for the module
  199. trace level */
  200. g_qdf_trace_info[module].module_trace_level |=
  201. QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level);
  202. else
  203. /* clear the desired bit in the bit mask for the module
  204. trace level */
  205. g_qdf_trace_info[module].module_trace_level &=
  206. ~(QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level));
  207. }
  208. }
  209. EXPORT_SYMBOL(qdf_trace_set_value);
  210. /**
  211. * qdf_trace_get_level() - get the trace level
  212. * @module: module Id
  213. * @level: trace level
  214. *
  215. * This is an external API that returns a bool value to signify if a
  216. * particular trace level is set for the specified module.
  217. * A member of the QDF_TRACE_LEVEL enumeration indicating the severity
  218. * of the condition causing the trace message to be issued.
  219. *
  220. * Note that individual trace levels are the only valid values
  221. * for this API. QDF_TRACE_LEVEL_NONE and QDF_TRACE_LEVEL_ALL
  222. * are not valid input and will return false
  223. *
  224. * Return:
  225. * false - the specified trace level for the specified module is OFF
  226. * true - the specified trace level for the specified module is ON
  227. */
  228. bool qdf_trace_get_level(QDF_MODULE_ID module, QDF_TRACE_LEVEL level)
  229. {
  230. bool trace_on = false;
  231. if ((QDF_TRACE_LEVEL_NONE == level) ||
  232. (QDF_TRACE_LEVEL_ALL == level) || (level >= QDF_TRACE_LEVEL_MAX)) {
  233. trace_on = false;
  234. } else {
  235. trace_on = (level & g_qdf_trace_info[module].module_trace_level)
  236. ? true : false;
  237. }
  238. return trace_on;
  239. }
  240. EXPORT_SYMBOL(qdf_trace_get_level);
  241. /**
  242. * qdf_snprintf() - wrapper function to snprintf
  243. * @str_buffer: string Buffer
  244. * @size: defines the size of the data record
  245. * @str_format: Format string in which the message to be logged. This format
  246. * string contains printf-like replacement parameters, which follow
  247. * this parameter in the variable argument list.
  248. *
  249. * Return: None
  250. */
  251. void qdf_snprintf(char *str_buffer, unsigned int size, char *str_format, ...)
  252. {
  253. va_list val;
  254. va_start(val, str_format);
  255. snprintf(str_buffer, size, str_format, val);
  256. va_end(val);
  257. }
  258. EXPORT_SYMBOL(qdf_snprintf);
  259. #ifdef QDF_ENABLE_TRACING
  260. /**
  261. * qdf_trace_msg() - externally called trace function
  262. * @module: Module identifier a member of the QDF_MODULE_ID
  263. * enumeration that identifies the module issuing the trace message.
  264. * @level: Trace level a member of the QDF_TRACE_LEVEL enumeration
  265. * indicating the severity of the condition causing the trace message
  266. * to be issued. More severe conditions are more likely to be logged.
  267. * @str_format: Format string in which the message to be logged. This format
  268. * string contains printf-like replacement parameters, which follow
  269. * this parameter in the variable argument list.
  270. *
  271. * Checks the level of severity and accordingly prints the trace messages
  272. *
  273. * Return: None
  274. */
  275. void qdf_trace_msg(QDF_MODULE_ID module, QDF_TRACE_LEVEL level,
  276. char *str_format, ...)
  277. {
  278. char str_buffer[QDF_TRACE_BUFFER_SIZE];
  279. int n;
  280. /* Print the trace message when the desired level bit is set in
  281. the module tracel level mask */
  282. if (g_qdf_trace_info[module].module_trace_level &
  283. QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level)) {
  284. /* the trace level strings in an array. these are ordered in
  285. * the same order as the trace levels are defined in the enum
  286. * (see QDF_TRACE_LEVEL) so we can index into this array with
  287. * the level and get the right string. The qdf trace levels
  288. * are... none, Fatal, Error, Warning, Info, info_high, info_med,
  289. * info_low, Debug
  290. */
  291. static const char *TRACE_LEVEL_STR[] = { " ", "F ", "E ", "W ",
  292. "I ", "IH", "IM", "IL", "D" };
  293. va_list val;
  294. va_start(val, str_format);
  295. /* print the prefix string into the string buffer... */
  296. n = snprintf(str_buffer, QDF_TRACE_BUFFER_SIZE,
  297. "wlan: [%d:%2s:%3s] ",
  298. in_interrupt() ? 0 : current->pid,
  299. (char *)TRACE_LEVEL_STR[level],
  300. (char *)g_qdf_trace_info[module].module_name_str);
  301. /* print the formatted log message after the prefix string */
  302. if ((n >= 0) && (n < QDF_TRACE_BUFFER_SIZE)) {
  303. vsnprintf(str_buffer + n, QDF_TRACE_BUFFER_SIZE - n,
  304. str_format, val);
  305. #if defined(WLAN_LOGGING_SOCK_SVC_ENABLE)
  306. wlan_log_to_user(level, (char *)str_buffer,
  307. strlen(str_buffer));
  308. #else
  309. pr_err("%s\n", str_buffer);
  310. #endif
  311. }
  312. va_end(val);
  313. }
  314. }
  315. EXPORT_SYMBOL(qdf_trace_msg);
  316. /**
  317. * qdf_trace_display() - Display trace
  318. *
  319. * Return: None
  320. */
  321. void qdf_trace_display(void)
  322. {
  323. QDF_MODULE_ID module_id;
  324. pr_err
  325. (" 1)FATAL 2)ERROR 3)WARN 4)INFO 5)INFO_H 6)INFO_M 7)INFO_L 8)DEBUG\n");
  326. for (module_id = 0; module_id < QDF_MODULE_ID_MAX; ++module_id) {
  327. pr_err
  328. ("%2d)%s %s %s %s %s %s %s %s %s\n",
  329. (int)module_id, g_qdf_trace_info[module_id].module_name_str,
  330. (g_qdf_trace_info[module_id].
  331. module_trace_level & (1 << QDF_TRACE_LEVEL_FATAL)) ? "X" :
  332. " ",
  333. (g_qdf_trace_info[module_id].
  334. module_trace_level & (1 << QDF_TRACE_LEVEL_ERROR)) ? "X" :
  335. " ",
  336. (g_qdf_trace_info[module_id].
  337. module_trace_level & (1 << QDF_TRACE_LEVEL_WARN)) ? "X" :
  338. " ",
  339. (g_qdf_trace_info[module_id].
  340. module_trace_level & (1 << QDF_TRACE_LEVEL_INFO)) ? "X" :
  341. " ",
  342. (g_qdf_trace_info[module_id].
  343. module_trace_level & (1 << QDF_TRACE_LEVEL_INFO_HIGH)) ? "X"
  344. : " ",
  345. (g_qdf_trace_info[module_id].
  346. module_trace_level & (1 << QDF_TRACE_LEVEL_INFO_MED)) ? "X"
  347. : " ",
  348. (g_qdf_trace_info[module_id].
  349. module_trace_level & (1 << QDF_TRACE_LEVEL_INFO_LOW)) ? "X"
  350. : " ",
  351. (g_qdf_trace_info[module_id].
  352. module_trace_level & (1 << QDF_TRACE_LEVEL_DEBUG)) ? "X" :
  353. " ");
  354. }
  355. }
  356. EXPORT_SYMBOL(qdf_trace_display);
  357. #define ROW_SIZE 16
  358. /* Buffer size = data bytes(2 hex chars plus space) + NULL */
  359. #define BUFFER_SIZE ((ROW_SIZE * 3) + 1)
  360. /**
  361. * qdf_trace_hex_dump() - externally called hex dump function
  362. * @module: Module identifier a member of the QDF_MODULE_ID enumeration that
  363. * identifies the module issuing the trace message.
  364. * @level: Trace level a member of the QDF_TRACE_LEVEL enumeration indicating
  365. * the severity of the condition causing the trace message to be
  366. * issued. More severe conditions are more likely to be logged.
  367. * @data: The base address of the buffer to be logged.
  368. * @buf_len: The size of the buffer to be logged.
  369. *
  370. * Checks the level of severity and accordingly prints the trace messages
  371. *
  372. * Return: None
  373. */
  374. void qdf_trace_hex_dump(QDF_MODULE_ID module, QDF_TRACE_LEVEL level,
  375. void *data, int buf_len)
  376. {
  377. const u8 *ptr = data;
  378. int i, linelen, remaining = buf_len;
  379. unsigned char linebuf[BUFFER_SIZE];
  380. if (!(g_qdf_trace_info[module].module_trace_level &
  381. QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level)))
  382. return;
  383. for (i = 0; i < buf_len; i += ROW_SIZE) {
  384. linelen = min(remaining, ROW_SIZE);
  385. remaining -= ROW_SIZE;
  386. hex_dump_to_buffer(ptr + i, linelen, ROW_SIZE, 1,
  387. linebuf, sizeof(linebuf), false);
  388. qdf_trace_msg(module, level, "%.8x: %s", i, linebuf);
  389. }
  390. }
  391. EXPORT_SYMBOL(qdf_trace_hex_dump);
  392. #endif
  393. /**
  394. * qdf_trace_enable() - Enable MTRACE for specific modules
  395. * @bitmask_of_module_id: Bitmask according to enum of the modules.
  396. * 32[dec] = 0010 0000 [bin] <enum of HDD is 5>
  397. * 64[dec] = 0100 0000 [bin] <enum of SME is 6>
  398. * 128[dec] = 1000 0000 [bin] <enum of PE is 7>
  399. * @enable: can be true or false true implies enabling MTRACE false implies
  400. * disabling MTRACE.
  401. *
  402. * Enable MTRACE for specific modules whose bits are set in bitmask and enable
  403. * is true. if enable is false it disables MTRACE for that module. set the
  404. * bitmask according to enum value of the modules.
  405. * This functions will be called when you issue ioctl as mentioned following
  406. * [iwpriv wlan0 setdumplog <value> <enable>].
  407. * <value> - Decimal number, i.e. 64 decimal value shows only SME module,
  408. * 128 decimal value shows only PE module, 192 decimal value shows PE and SME.
  409. *
  410. * Return: None
  411. */
  412. void qdf_trace_enable(uint32_t bitmask_of_module_id, uint8_t enable)
  413. {
  414. int i;
  415. if (bitmask_of_module_id) {
  416. for (i = 0; i < QDF_MODULE_ID_MAX; i++) {
  417. if (((bitmask_of_module_id >> i) & 1)) {
  418. if (enable) {
  419. if (NULL !=
  420. qdf_trace_restore_cb_table[i]) {
  421. qdf_trace_cb_table[i] =
  422. qdf_trace_restore_cb_table[i];
  423. }
  424. } else {
  425. qdf_trace_restore_cb_table[i] =
  426. qdf_trace_cb_table[i];
  427. qdf_trace_cb_table[i] = NULL;
  428. }
  429. }
  430. }
  431. } else {
  432. if (enable) {
  433. for (i = 0; i < QDF_MODULE_ID_MAX; i++) {
  434. if (NULL != qdf_trace_restore_cb_table[i]) {
  435. qdf_trace_cb_table[i] =
  436. qdf_trace_restore_cb_table[i];
  437. }
  438. }
  439. } else {
  440. for (i = 0; i < QDF_MODULE_ID_MAX; i++) {
  441. qdf_trace_restore_cb_table[i] =
  442. qdf_trace_cb_table[i];
  443. qdf_trace_cb_table[i] = NULL;
  444. }
  445. }
  446. }
  447. }
  448. EXPORT_SYMBOL(qdf_trace_enable);
  449. /**
  450. * qdf_trace_init() - initializes qdf trace structures and variables
  451. *
  452. * Called immediately after cds_preopen, so that we can start recording HDD
  453. * events ASAP.
  454. *
  455. * Return: None
  456. */
  457. void qdf_trace_init(void)
  458. {
  459. uint8_t i;
  460. g_qdf_trace_data.head = INVALID_QDF_TRACE_ADDR;
  461. g_qdf_trace_data.tail = INVALID_QDF_TRACE_ADDR;
  462. g_qdf_trace_data.num = 0;
  463. g_qdf_trace_data.enable = true;
  464. g_qdf_trace_data.dump_count = DEFAULT_QDF_TRACE_DUMP_COUNT;
  465. g_qdf_trace_data.num_since_last_dump = 0;
  466. for (i = 0; i < QDF_MODULE_ID_MAX; i++) {
  467. qdf_trace_cb_table[i] = NULL;
  468. qdf_trace_restore_cb_table[i] = NULL;
  469. }
  470. }
  471. EXPORT_SYMBOL(qdf_trace_init);
  472. /**
  473. * qdf_trace() - puts the messages in to ring-buffer
  474. * @module: Enum of module, basically module id.
  475. * @param: Code to be recorded
  476. * @session: Session ID of the log
  477. * @data: Actual message contents
  478. *
  479. * This function will be called from each module who wants record the messages
  480. * in circular queue. Before calling this functions make sure you have
  481. * registered your module with qdf through qdf_trace_register function.
  482. *
  483. * Return: None
  484. */
  485. void qdf_trace(uint8_t module, uint8_t code, uint16_t session, uint32_t data)
  486. {
  487. tp_qdf_trace_record rec = NULL;
  488. unsigned long flags;
  489. if (!g_qdf_trace_data.enable)
  490. return;
  491. /* if module is not registered, don't record for that module */
  492. if (NULL == qdf_trace_cb_table[module])
  493. return;
  494. /* Aquire the lock so that only one thread at a time can fill the ring
  495. * buffer
  496. */
  497. spin_lock_irqsave(&ltrace_lock, flags);
  498. g_qdf_trace_data.num++;
  499. if (g_qdf_trace_data.num > MAX_QDF_TRACE_RECORDS)
  500. g_qdf_trace_data.num = MAX_QDF_TRACE_RECORDS;
  501. if (INVALID_QDF_TRACE_ADDR == g_qdf_trace_data.head) {
  502. /* first record */
  503. g_qdf_trace_data.head = 0;
  504. g_qdf_trace_data.tail = 0;
  505. } else {
  506. /* queue is not empty */
  507. uint32_t tail = g_qdf_trace_data.tail + 1;
  508. if (MAX_QDF_TRACE_RECORDS == tail)
  509. tail = 0;
  510. if (g_qdf_trace_data.head == tail) {
  511. /* full */
  512. if (MAX_QDF_TRACE_RECORDS == ++g_qdf_trace_data.head)
  513. g_qdf_trace_data.head = 0;
  514. }
  515. g_qdf_trace_data.tail = tail;
  516. }
  517. rec = &g_qdf_trace_tbl[g_qdf_trace_data.tail];
  518. rec->code = code;
  519. rec->session = session;
  520. rec->data = data;
  521. rec->time = qdf_get_log_timestamp();
  522. rec->module = module;
  523. rec->pid = (in_interrupt() ? 0 : current->pid);
  524. g_qdf_trace_data.num_since_last_dump++;
  525. spin_unlock_irqrestore(&ltrace_lock, flags);
  526. }
  527. EXPORT_SYMBOL(qdf_trace);
  528. /**
  529. * qdf_trace_spin_lock_init() - initializes the lock variable before use
  530. *
  531. * This function will be called from cds_alloc_global_context, we will have lock
  532. * available to use ASAP
  533. *
  534. * Return: None
  535. */
  536. QDF_STATUS qdf_trace_spin_lock_init(void)
  537. {
  538. spin_lock_init(&ltrace_lock);
  539. return QDF_STATUS_SUCCESS;
  540. }
  541. EXPORT_SYMBOL(qdf_trace_spin_lock_init);
  542. /**
  543. * qdf_trace_register() - registers the call back functions
  544. * @module_iD: enum value of module
  545. * @qdf_trace_callback: call back functions to display the messages in
  546. * particular format.
  547. *
  548. * Registers the call back functions to display the messages in particular
  549. * format mentioned in these call back functions. This functions should be
  550. * called by interested module in their init part as we will be ready to
  551. * register as soon as modules are up.
  552. *
  553. * Return: None
  554. */
  555. void qdf_trace_register(QDF_MODULE_ID module_iD,
  556. tp_qdf_trace_cb qdf_trace_callback)
  557. {
  558. qdf_trace_cb_table[module_iD] = qdf_trace_callback;
  559. }
  560. EXPORT_SYMBOL(qdf_trace_register);
  561. /**
  562. * qdf_trace_dump_all() - Dump data from ring buffer via call back functions
  563. * registered with QDF
  564. * @p_mac: Context of particular module
  565. * @code: Reason code
  566. * @session: Session id of log
  567. * @count: Number of lines to dump starting from tail to head
  568. *
  569. * This function will be called up on issueing ioctl call as mentioned following
  570. * [iwpriv wlan0 dumplog 0 0 <n> <bitmask_of_module>]
  571. *
  572. * <n> - number lines to dump starting from tail to head.
  573. *
  574. * <bitmask_of_module> - if anybody wants to know how many messages were
  575. * recorded for particular module/s mentioned by setbit in bitmask from last
  576. * <n> messages. It is optional, if you don't provide then it will dump
  577. * everything from buffer.
  578. *
  579. * Return: None
  580. */
  581. void qdf_trace_dump_all(void *p_mac, uint8_t code, uint8_t session,
  582. uint32_t count, uint32_t bitmask_of_module)
  583. {
  584. qdf_trace_record_t p_record;
  585. int32_t i, tail;
  586. if (!g_qdf_trace_data.enable) {
  587. QDF_TRACE(QDF_MODULE_ID_SYS,
  588. QDF_TRACE_LEVEL_ERROR, "Tracing Disabled");
  589. return;
  590. }
  591. QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_INFO,
  592. "Total Records: %d, Head: %d, Tail: %d",
  593. g_qdf_trace_data.num, g_qdf_trace_data.head,
  594. g_qdf_trace_data.tail);
  595. /* aquire the lock so that only one thread at a time can read
  596. * the ring buffer
  597. */
  598. spin_lock(&ltrace_lock);
  599. if (g_qdf_trace_data.head != INVALID_QDF_TRACE_ADDR) {
  600. i = g_qdf_trace_data.head;
  601. tail = g_qdf_trace_data.tail;
  602. if (count) {
  603. if (count > g_qdf_trace_data.num)
  604. count = g_qdf_trace_data.num;
  605. if (tail >= (count - 1))
  606. i = tail - count + 1;
  607. else if (count != MAX_QDF_TRACE_RECORDS)
  608. i = MAX_QDF_TRACE_RECORDS - ((count - 1) -
  609. tail);
  610. }
  611. p_record = g_qdf_trace_tbl[i];
  612. /* right now we are not using num_since_last_dump member but
  613. * in future we might re-visit and use this member to track
  614. * how many latest messages got added while we were dumping
  615. * from ring buffer
  616. */
  617. g_qdf_trace_data.num_since_last_dump = 0;
  618. spin_unlock(&ltrace_lock);
  619. for (;; ) {
  620. if ((code == 0 || (code == p_record.code)) &&
  621. (qdf_trace_cb_table[p_record.module] != NULL)) {
  622. if (0 == bitmask_of_module) {
  623. qdf_trace_cb_table[p_record.
  624. module] (p_mac,
  625. &p_record,
  626. (uint16_t)
  627. i);
  628. } else {
  629. if (bitmask_of_module &
  630. (1 << p_record.module)) {
  631. qdf_trace_cb_table[p_record.
  632. module]
  633. (p_mac, &p_record,
  634. (uint16_t) i);
  635. }
  636. }
  637. }
  638. if (i == tail)
  639. break;
  640. i += 1;
  641. spin_lock(&ltrace_lock);
  642. if (MAX_QDF_TRACE_RECORDS == i) {
  643. i = 0;
  644. p_record = g_qdf_trace_tbl[0];
  645. } else {
  646. p_record = g_qdf_trace_tbl[i];
  647. }
  648. spin_unlock(&ltrace_lock);
  649. }
  650. } else {
  651. spin_unlock(&ltrace_lock);
  652. }
  653. }
  654. EXPORT_SYMBOL(qdf_trace_dump_all);
  655. /**
  656. * qdf_register_debugcb_init() - initializes debug callbacks
  657. * to NULL
  658. *
  659. * Return: None
  660. */
  661. void qdf_register_debugcb_init(void)
  662. {
  663. uint8_t i;
  664. for (i = 0; i < QDF_MODULE_ID_MAX; i++)
  665. qdf_state_info_table[i] = NULL;
  666. }
  667. EXPORT_SYMBOL(qdf_register_debugcb_init);
  668. /**
  669. * qdf_register_debug_callback() - stores callback handlers to print
  670. * state information
  671. * @module_id: module id of layer
  672. * @qdf_state_infocb: callback to be registered
  673. *
  674. * This function is used to store callback handlers to print
  675. * state information
  676. *
  677. * Return: None
  678. */
  679. void qdf_register_debug_callback(QDF_MODULE_ID module_id,
  680. tp_qdf_state_info_cb qdf_state_infocb)
  681. {
  682. qdf_state_info_table[module_id] = qdf_state_infocb;
  683. }
  684. EXPORT_SYMBOL(qdf_register_debug_callback);
  685. /**
  686. * qdf_state_info_dump_all() - it invokes callback of layer which registered
  687. * its callback to print its state information.
  688. * @buf: buffer pointer to be passed
  689. * @size: size of buffer to be filled
  690. * @driver_dump_size: actual size of buffer used
  691. *
  692. * Return: QDF_STATUS_SUCCESS on success
  693. */
  694. QDF_STATUS qdf_state_info_dump_all(char *buf, uint16_t size,
  695. uint16_t *driver_dump_size)
  696. {
  697. uint8_t module, ret = QDF_STATUS_SUCCESS;
  698. uint16_t buf_len = size;
  699. char *buf_ptr = buf;
  700. for (module = 0; module < QDF_MODULE_ID_MAX; module++) {
  701. if (NULL != qdf_state_info_table[module]) {
  702. qdf_state_info_table[module](&buf_ptr, &buf_len);
  703. if (!buf_len) {
  704. ret = QDF_STATUS_E_NOMEM;
  705. break;
  706. }
  707. }
  708. }
  709. *driver_dump_size = size - buf_len;
  710. return ret;
  711. }
  712. EXPORT_SYMBOL(qdf_state_info_dump_all);
  713. #ifdef FEATURE_DP_TRACE
  714. static void qdf_dp_unused(struct qdf_dp_trace_record_s *record,
  715. uint16_t index)
  716. {
  717. qdf_print("%s: QDF_DP_TRACE_MAX event should not be generated",
  718. __func__);
  719. }
  720. /**
  721. * qdf_dp_trace_init() - enables the DP trace
  722. * Called during driver load and it enables DP trace
  723. *
  724. * Return: None
  725. */
  726. void qdf_dp_trace_init(void)
  727. {
  728. uint8_t i;
  729. qdf_dp_trace_spin_lock_init();
  730. g_qdf_dp_trace_data.head = INVALID_QDF_DP_TRACE_ADDR;
  731. g_qdf_dp_trace_data.tail = INVALID_QDF_DP_TRACE_ADDR;
  732. g_qdf_dp_trace_data.num = 0;
  733. g_qdf_dp_trace_data.proto_bitmap = QDF_NBUF_PKT_TRAC_TYPE_EAPOL |
  734. QDF_NBUF_PKT_TRAC_TYPE_DHCP | QDF_NBUF_PKT_TRAC_TYPE_MGMT_ACTION;
  735. g_qdf_dp_trace_data.no_of_record = 0;
  736. g_qdf_dp_trace_data.verbosity = QDF_DP_TRACE_VERBOSITY_LOW;
  737. g_qdf_dp_trace_data.enable = true;
  738. for (i = 0; i < ARRAY_SIZE(qdf_dp_trace_cb_table); i++)
  739. qdf_dp_trace_cb_table[i] = qdf_dp_display_record;
  740. qdf_dp_trace_cb_table[QDF_DP_TRACE_TXRX_PACKET_PTR_RECORD] =
  741. qdf_dp_trace_cb_table[QDF_DP_TRACE_TXRX_FAST_PACKET_PTR_RECORD] =
  742. qdf_dp_trace_cb_table[QDF_DP_TRACE_FREE_PACKET_PTR_RECORD] =
  743. qdf_dp_display_ptr_record;
  744. qdf_dp_trace_cb_table[QDF_DP_TRACE_EAPOL_PACKET_RECORD] =
  745. qdf_dp_trace_cb_table[QDF_DP_TRACE_DHCP_PACKET_RECORD] =
  746. qdf_dp_trace_cb_table[QDF_DP_TRACE_ARP_PACKET_RECORD] =
  747. qdf_dp_display_proto_pkt;
  748. qdf_dp_trace_cb_table[QDF_DP_TRACE_MGMT_PACKET_RECORD] =
  749. qdf_dp_display_mgmt_pkt;
  750. qdf_dp_trace_cb_table[QDF_DP_TRACE_EVENT_RECORD] =
  751. qdf_dp_display_event_record;
  752. qdf_dp_trace_cb_table[QDF_DP_TRACE_MAX] = qdf_dp_unused;
  753. }
  754. EXPORT_SYMBOL(qdf_dp_trace_init);
  755. /**
  756. * qdf_dp_trace_set_value() - Configure the value to control DP trace
  757. * @proto_bitmap: defines the protocol to be tracked
  758. * @no_of_records: defines the nth packet which is traced
  759. * @verbosity: defines the verbosity level
  760. *
  761. * Return: None
  762. */
  763. void qdf_dp_trace_set_value(uint8_t proto_bitmap, uint8_t no_of_record,
  764. uint8_t verbosity)
  765. {
  766. g_qdf_dp_trace_data.proto_bitmap = proto_bitmap;
  767. g_qdf_dp_trace_data.no_of_record = no_of_record;
  768. g_qdf_dp_trace_data.verbosity = verbosity;
  769. return;
  770. }
  771. EXPORT_SYMBOL(qdf_dp_trace_set_value);
  772. /**
  773. * qdf_dp_trace_enable_track() - enable the tracing for netbuf
  774. * @code: defines the event
  775. *
  776. * In High verbosity all codes are logged.
  777. * For Med/Low and Default case code which has
  778. * less value than corresponding verbosity codes
  779. * are logged.
  780. *
  781. * Return: true or false depends on whether tracing enabled
  782. */
  783. static bool qdf_dp_trace_enable_track(enum QDF_DP_TRACE_ID code)
  784. {
  785. switch (g_qdf_dp_trace_data.verbosity) {
  786. case QDF_DP_TRACE_VERBOSITY_HIGH:
  787. return true;
  788. case QDF_DP_TRACE_VERBOSITY_MEDIUM:
  789. if (code <= QDF_DP_TRACE_MED_VERBOSITY)
  790. return true;
  791. return false;
  792. case QDF_DP_TRACE_VERBOSITY_LOW:
  793. if (code <= QDF_DP_TRACE_LOW_VERBOSITY)
  794. return true;
  795. return false;
  796. case QDF_DP_TRACE_VERBOSITY_DEFAULT:
  797. if (code <= QDF_DP_TRACE_DEFAULT_VERBOSITY)
  798. return true;
  799. return false;
  800. default:
  801. return false;
  802. }
  803. }
  804. EXPORT_SYMBOL(qdf_dp_trace_enable_track);
  805. /**
  806. * qdf_dp_get_proto_bitmap() - get dp trace proto bitmap
  807. *
  808. * Return: proto bitmap
  809. */
  810. uint8_t qdf_dp_get_proto_bitmap(void)
  811. {
  812. if (g_qdf_dp_trace_data.enable)
  813. return g_qdf_dp_trace_data.proto_bitmap;
  814. else
  815. return 0;
  816. }
  817. /**
  818. * qdf_dp_trace_set_track() - Marks whether the packet needs to be traced
  819. * @nbuf: defines the netbuf
  820. * @dir: direction
  821. *
  822. * Return: None
  823. */
  824. void qdf_dp_trace_set_track(qdf_nbuf_t nbuf, enum qdf_proto_dir dir)
  825. {
  826. uint32_t count = 0;
  827. spin_lock_bh(&l_dp_trace_lock);
  828. if (QDF_TX == dir)
  829. count = ++g_qdf_dp_trace_data.tx_count;
  830. else if (QDF_RX == dir)
  831. count = ++g_qdf_dp_trace_data.rx_count;
  832. if ((g_qdf_dp_trace_data.no_of_record != 0) &&
  833. (count % g_qdf_dp_trace_data.no_of_record == 0)) {
  834. if (QDF_TX == dir)
  835. QDF_NBUF_CB_TX_DP_TRACE(nbuf) = 1;
  836. else if (QDF_RX == dir)
  837. QDF_NBUF_CB_RX_DP_TRACE(nbuf) = 1;
  838. }
  839. spin_unlock_bh(&l_dp_trace_lock);
  840. return;
  841. }
  842. EXPORT_SYMBOL(qdf_dp_trace_set_track);
  843. /**
  844. * dump_hex_trace() - Display the data in buffer
  845. * @buf: buffer which contains data to be displayed
  846. * @buf_len: defines the size of the data to be displayed
  847. *
  848. * Return: None
  849. */
  850. static void dump_hex_trace(char *str, uint8_t *buf, uint8_t buf_len)
  851. {
  852. unsigned char linebuf[BUFFER_SIZE];
  853. const u8 *ptr = buf;
  854. int i, linelen, remaining = buf_len;
  855. /* Dump the bytes in the last line */
  856. for (i = 0; i < buf_len; i += ROW_SIZE) {
  857. linelen = min(remaining, ROW_SIZE);
  858. remaining -= ROW_SIZE;
  859. hex_dump_to_buffer(ptr + i, linelen, ROW_SIZE, 1,
  860. linebuf, sizeof(linebuf), false);
  861. qdf_trace_msg(QDF_MODULE_ID_QDF,
  862. QDF_TRACE_LEVEL_ERROR, "DPT: %s: %s", str, linebuf);
  863. }
  864. }
  865. EXPORT_SYMBOL(dump_hex_trace);
  866. /**
  867. * qdf_dp_code_to_string() - convert dptrace code to string
  868. * @code: dptrace code
  869. *
  870. * Return: string version of code
  871. */
  872. static
  873. const char *qdf_dp_code_to_string(enum QDF_DP_TRACE_ID code)
  874. {
  875. switch (code) {
  876. case QDF_DP_TRACE_DROP_PACKET_RECORD:
  877. return "DROP:";
  878. case QDF_DP_TRACE_EAPOL_PACKET_RECORD:
  879. return "EAPOL:";
  880. case QDF_DP_TRACE_DHCP_PACKET_RECORD:
  881. return "DHCP:";
  882. case QDF_DP_TRACE_ARP_PACKET_RECORD:
  883. return "ARP:";
  884. case QDF_DP_TRACE_MGMT_PACKET_RECORD:
  885. return "MGMT:";
  886. case QDF_DP_TRACE_EVENT_RECORD:
  887. return "EVENT:";
  888. case QDF_DP_TRACE_HDD_TX_PACKET_PTR_RECORD:
  889. return "HDD: TX: PTR:";
  890. case QDF_DP_TRACE_HDD_TX_PACKET_RECORD:
  891. return "HDD: TX: DATA:";
  892. case QDF_DP_TRACE_CE_PACKET_PTR_RECORD:
  893. return "CE: TX: PTR:";
  894. case QDF_DP_TRACE_CE_FAST_PACKET_PTR_RECORD:
  895. return "CE: TX: FAST: PTR:";
  896. case QDF_DP_TRACE_FREE_PACKET_PTR_RECORD:
  897. return "FREE: TX: PTR:";
  898. case QDF_DP_TRACE_RX_HTT_PACKET_PTR_RECORD:
  899. return "HTT: RX: PTR:";
  900. case QDF_DP_TRACE_RX_OFFLOAD_HTT_PACKET_PTR_RECORD:
  901. return "HTT: RX: OF: PTR:";
  902. case QDF_DP_TRACE_RX_HDD_PACKET_PTR_RECORD:
  903. return "HDD: RX: PTR:";
  904. case QDF_DP_TRACE_TXRX_QUEUE_PACKET_PTR_RECORD:
  905. return "TXRX: TX: Q: PTR:";
  906. case QDF_DP_TRACE_TXRX_PACKET_PTR_RECORD:
  907. return "TXRX: TX: PTR:";
  908. case QDF_DP_TRACE_TXRX_FAST_PACKET_PTR_RECORD:
  909. return "TXRX: TX: FAST: PTR:";
  910. case QDF_DP_TRACE_HTT_PACKET_PTR_RECORD:
  911. return "HTT: TX: PTR:";
  912. case QDF_DP_TRACE_HTC_PACKET_PTR_RECORD:
  913. return "HTC: TX: PTR:";
  914. case QDF_DP_TRACE_HIF_PACKET_PTR_RECORD:
  915. return "HIF: TX: PTR:";
  916. case QDF_DP_TRACE_RX_TXRX_PACKET_PTR_RECORD:
  917. return "TXRX: RX: PTR:";
  918. case QDF_DP_TRACE_HDD_TX_TIMEOUT:
  919. return "HDD: STA: TO:";
  920. case QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT:
  921. return "HDD: SAP: TO:";
  922. default:
  923. return "Invalid";
  924. }
  925. }
  926. /**
  927. * qdf_dp_dir_to_str() - convert direction to string
  928. * @dir: direction
  929. *
  930. * Return: string version of direction
  931. */
  932. static const char *qdf_dp_dir_to_str(enum qdf_proto_dir dir)
  933. {
  934. switch (dir) {
  935. case QDF_TX:
  936. return " --> ";
  937. case QDF_RX:
  938. return " <-- ";
  939. default:
  940. return "invalid";
  941. }
  942. }
  943. /**
  944. * qdf_dp_type_to_str() - convert packet type to string
  945. * @type: type
  946. *
  947. * Return: string version of packet type
  948. */
  949. static const char *qdf_dp_type_to_str(enum qdf_proto_type type)
  950. {
  951. switch (type) {
  952. case QDF_PROTO_TYPE_DHCP:
  953. return "DHCP";
  954. case QDF_PROTO_TYPE_EAPOL:
  955. return "EAPOL";
  956. case QDF_PROTO_TYPE_ARP:
  957. return "ARP";
  958. case QDF_PROTO_TYPE_MGMT:
  959. return "MGMT";
  960. case QDF_PROTO_TYPE_EVENT:
  961. return "EVENT";
  962. default:
  963. return "invalid";
  964. }
  965. }
  966. /**
  967. * qdf_dp_subtype_to_str() - convert packet subtype to string
  968. * @type: type
  969. *
  970. * Return: string version of packet subtype
  971. */
  972. static const char *qdf_dp_subtype_to_str(enum qdf_proto_subtype subtype)
  973. {
  974. switch (subtype) {
  975. case QDF_PROTO_EAPOL_M1:
  976. return "M1";
  977. case QDF_PROTO_EAPOL_M2:
  978. return "M2";
  979. case QDF_PROTO_EAPOL_M3:
  980. return "M3";
  981. case QDF_PROTO_EAPOL_M4:
  982. return "M4";
  983. case QDF_PROTO_DHCP_DISCOVER:
  984. return "DISCOVER";
  985. case QDF_PROTO_DHCP_REQUEST:
  986. return "REQUEST";
  987. case QDF_PROTO_DHCP_OFFER:
  988. return "OFFER";
  989. case QDF_PROTO_DHCP_ACK:
  990. return "ACK";
  991. case QDF_PROTO_DHCP_NACK:
  992. return "NACK";
  993. case QDF_PROTO_DHCP_RELEASE:
  994. return "RELEASE";
  995. case QDF_PROTO_DHCP_INFORM:
  996. return "INFORM";
  997. case QDF_PROTO_DHCP_DECLINE:
  998. return "DECLINE";
  999. case QDF_PROTO_ARP_REQ:
  1000. return "REQUEST";
  1001. case QDF_PROTO_ARP_RES:
  1002. return "RESPONSE";
  1003. case QDF_PROTO_MGMT_ASSOC:
  1004. return "ASSOC";
  1005. case QDF_PROTO_MGMT_DISASSOC:
  1006. return "DISASSOC";
  1007. case QDF_PROTO_MGMT_AUTH:
  1008. return "AUTH";
  1009. case QDF_PROTO_MGMT_DEAUTH:
  1010. return "DEAUTH";
  1011. case QDF_ROAM_SYNCH:
  1012. return "ROAM SYNCH";
  1013. case QDF_ROAM_COMPLETE:
  1014. return "ROAM COMPLETE";
  1015. case QDF_ROAM_EVENTID:
  1016. return "ROAM EVENTID";
  1017. default:
  1018. return "invalid";
  1019. }
  1020. }
  1021. /**
  1022. * qdf_dp_enable_check() - check if dptrace is enable or not
  1023. * @nbuf: nbuf
  1024. * @code: dptrace code
  1025. *
  1026. * Return: true/false
  1027. */
  1028. static bool qdf_dp_enable_check(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code,
  1029. enum qdf_proto_dir dir)
  1030. {
  1031. /* Return when Dp trace is not enabled */
  1032. if (!g_qdf_dp_trace_data.enable)
  1033. return false;
  1034. if (qdf_dp_trace_enable_track(code) == false)
  1035. return false;
  1036. if ((nbuf) && ((QDF_NBUF_CB_TX_PACKET_TRACK(nbuf) !=
  1037. QDF_NBUF_TX_PKT_DATA_TRACK) ||
  1038. ((dir == QDF_TX) && (QDF_NBUF_CB_TX_DP_TRACE(nbuf) == 0)) ||
  1039. ((dir == QDF_RX) && (QDF_NBUF_CB_RX_DP_TRACE(nbuf) == 0))))
  1040. return false;
  1041. return true;
  1042. }
  1043. /**
  1044. * qdf_dp_add_record() - add dp trace record
  1045. * @code: dptrace code
  1046. * @data: data pointer
  1047. * @size: size of buffer
  1048. * @print: true to print it in kmsg
  1049. *
  1050. * Return: none
  1051. */
  1052. static void qdf_dp_add_record(enum QDF_DP_TRACE_ID code,
  1053. uint8_t *data, uint8_t size, bool print)
  1054. {
  1055. struct qdf_dp_trace_record_s *rec = NULL;
  1056. int index;
  1057. spin_lock_bh(&l_dp_trace_lock);
  1058. g_qdf_dp_trace_data.num++;
  1059. if (g_qdf_dp_trace_data.num > MAX_QDF_DP_TRACE_RECORDS)
  1060. g_qdf_dp_trace_data.num = MAX_QDF_DP_TRACE_RECORDS;
  1061. if (INVALID_QDF_DP_TRACE_ADDR == g_qdf_dp_trace_data.head) {
  1062. /* first record */
  1063. g_qdf_dp_trace_data.head = 0;
  1064. g_qdf_dp_trace_data.tail = 0;
  1065. } else {
  1066. /* queue is not empty */
  1067. g_qdf_dp_trace_data.tail++;
  1068. if (MAX_QDF_DP_TRACE_RECORDS == g_qdf_dp_trace_data.tail)
  1069. g_qdf_dp_trace_data.tail = 0;
  1070. if (g_qdf_dp_trace_data.head == g_qdf_dp_trace_data.tail) {
  1071. /* full */
  1072. if (MAX_QDF_DP_TRACE_RECORDS ==
  1073. ++g_qdf_dp_trace_data.head)
  1074. g_qdf_dp_trace_data.head = 0;
  1075. }
  1076. }
  1077. rec = &g_qdf_dp_trace_tbl[g_qdf_dp_trace_data.tail];
  1078. index = g_qdf_dp_trace_data.tail;
  1079. rec->code = code;
  1080. rec->size = 0;
  1081. if (data != NULL && size > 0) {
  1082. if (size > QDF_DP_TRACE_RECORD_SIZE)
  1083. size = QDF_DP_TRACE_RECORD_SIZE;
  1084. rec->size = size;
  1085. qdf_mem_copy(rec->data, data, size);
  1086. }
  1087. rec->time = qdf_get_log_timestamp();
  1088. rec->pid = (in_interrupt() ? 0 : current->pid);
  1089. spin_unlock_bh(&l_dp_trace_lock);
  1090. if (g_qdf_dp_trace_data.live_mode || (print == true))
  1091. qdf_dp_trace_cb_table[rec->code] (rec, index);
  1092. }
  1093. /**
  1094. * qdf_log_eapol_pkt() - log EAPOL packet
  1095. * @session_id: vdev_id
  1096. * @skb: skb pointer
  1097. * @dir: direction
  1098. *
  1099. * Return: true/false
  1100. */
  1101. static bool qdf_log_eapol_pkt(uint8_t session_id, struct sk_buff *skb,
  1102. enum qdf_proto_dir dir)
  1103. {
  1104. enum qdf_proto_subtype subtype;
  1105. if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_EAPOL) &&
  1106. ((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_EAPOL ==
  1107. QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
  1108. (dir == QDF_RX && qdf_nbuf_is_ipv4_eapol_pkt(skb) == true))) {
  1109. subtype = qdf_nbuf_get_eapol_subtype(skb);
  1110. DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_EAPOL_PACKET_RECORD,
  1111. session_id, (skb->data + QDF_NBUF_SRC_MAC_OFFSET),
  1112. (skb->data + QDF_NBUF_DEST_MAC_OFFSET),
  1113. QDF_PROTO_TYPE_EAPOL, subtype, dir));
  1114. if (QDF_TX == dir)
  1115. QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
  1116. else if (QDF_RX == dir)
  1117. QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
  1118. return true;
  1119. }
  1120. return false;
  1121. }
  1122. /**
  1123. * qdf_log_dhcp_pkt() - log DHCP packet
  1124. * @session_id: vdev_id
  1125. * @skb: skb pointer
  1126. * @dir: direction
  1127. *
  1128. * Return: true/false
  1129. */
  1130. static bool qdf_log_dhcp_pkt(uint8_t session_id, struct sk_buff *skb,
  1131. enum qdf_proto_dir dir)
  1132. {
  1133. enum qdf_proto_subtype subtype = QDF_PROTO_INVALID;
  1134. if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_DHCP) &&
  1135. ((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_DHCP ==
  1136. QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
  1137. (dir == QDF_RX && qdf_nbuf_is_ipv4_dhcp_pkt(skb) == true))) {
  1138. subtype = qdf_nbuf_get_dhcp_subtype(skb);
  1139. DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_DHCP_PACKET_RECORD,
  1140. session_id, (skb->data + QDF_NBUF_SRC_MAC_OFFSET),
  1141. (skb->data + QDF_NBUF_DEST_MAC_OFFSET),
  1142. QDF_PROTO_TYPE_DHCP, subtype, dir));
  1143. if (QDF_TX == dir)
  1144. QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
  1145. else if (QDF_RX == dir)
  1146. QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
  1147. return true;
  1148. }
  1149. return false;
  1150. }
  1151. /**
  1152. * qdf_log_arp_pkt() - log ARP packet
  1153. * @session_id: vdev_id
  1154. * @skb: skb pointer
  1155. * @dir: direction
  1156. *
  1157. * Return: true/false
  1158. */
  1159. static bool qdf_log_arp_pkt(uint8_t session_id, struct sk_buff *skb,
  1160. enum qdf_proto_dir dir)
  1161. {
  1162. enum qdf_proto_subtype proto_subtype;
  1163. if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ARP) &&
  1164. ((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_ARP ==
  1165. QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
  1166. (dir == QDF_RX && qdf_nbuf_is_ipv4_arp_pkt(skb) == true))) {
  1167. proto_subtype = qdf_nbuf_get_arp_subtype(skb);
  1168. DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_ARP_PACKET_RECORD,
  1169. session_id, (skb->data + QDF_NBUF_SRC_MAC_OFFSET),
  1170. (skb->data + QDF_NBUF_DEST_MAC_OFFSET),
  1171. QDF_PROTO_TYPE_ARP, proto_subtype, dir));
  1172. if (QDF_TX == dir)
  1173. QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
  1174. else if (QDF_RX == dir)
  1175. QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
  1176. return true;
  1177. }
  1178. return false;
  1179. }
  1180. /**
  1181. * qdf_dp_trace_log_pkt() - log packet type enabled through iwpriv
  1182. * @session_id: vdev_id
  1183. * @skb: skb pointer
  1184. * @dir: direction
  1185. *
  1186. * Return: none
  1187. */
  1188. void qdf_dp_trace_log_pkt(uint8_t session_id, struct sk_buff *skb,
  1189. enum qdf_proto_dir dir)
  1190. {
  1191. if (qdf_dp_get_proto_bitmap()) {
  1192. if (qdf_log_arp_pkt(session_id,
  1193. skb, dir) == false) {
  1194. if (qdf_log_dhcp_pkt(session_id,
  1195. skb, dir) == false) {
  1196. if (qdf_log_eapol_pkt(session_id,
  1197. skb, dir) == false) {
  1198. return;
  1199. }
  1200. }
  1201. }
  1202. }
  1203. }
  1204. EXPORT_SYMBOL(qdf_dp_trace_log_pkt);
  1205. /**
  1206. * qdf_dp_display_mgmt_pkt() - display proto packet
  1207. * @record: dptrace record
  1208. * @index: index
  1209. *
  1210. * Return: none
  1211. */
  1212. void qdf_dp_display_mgmt_pkt(struct qdf_dp_trace_record_s *record,
  1213. uint16_t index)
  1214. {
  1215. struct qdf_dp_trace_mgmt_buf *buf =
  1216. (struct qdf_dp_trace_mgmt_buf *)record->data;
  1217. qdf_print("DPT: %04d: %012llu: %s vdev_id %d", index,
  1218. record->time, qdf_dp_code_to_string(record->code),
  1219. buf->vdev_id);
  1220. qdf_print("DPT: Type %s Subtype %s", qdf_dp_type_to_str(buf->type),
  1221. qdf_dp_subtype_to_str(buf->subtype));
  1222. }
  1223. EXPORT_SYMBOL(qdf_dp_display_mgmt_pkt);
  1224. /**
  1225. * qdf_dp_trace_mgmt_pkt() - record mgmt packet
  1226. * @code: dptrace code
  1227. * @vdev_id: vdev id
  1228. * @type: proto type
  1229. * @subtype: proto subtype
  1230. *
  1231. * Return: none
  1232. */
  1233. void qdf_dp_trace_mgmt_pkt(enum QDF_DP_TRACE_ID code, uint8_t vdev_id,
  1234. enum qdf_proto_type type, enum qdf_proto_subtype subtype)
  1235. {
  1236. struct qdf_dp_trace_mgmt_buf buf;
  1237. int buf_size = sizeof(struct qdf_dp_trace_mgmt_buf);
  1238. if (qdf_dp_enable_check(NULL, code, QDF_NA) == false)
  1239. return;
  1240. if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
  1241. QDF_BUG(0);
  1242. buf.type = type;
  1243. buf.subtype = subtype;
  1244. buf.vdev_id = vdev_id;
  1245. qdf_dp_add_record(code, (uint8_t *)&buf, buf_size, true);
  1246. }
  1247. EXPORT_SYMBOL(qdf_dp_trace_mgmt_pkt);
  1248. /**
  1249. * qdf_dp_display_event_record() - display event records
  1250. * @record: dptrace record
  1251. * @index: index
  1252. *
  1253. * Return: none
  1254. */
  1255. void qdf_dp_display_event_record(struct qdf_dp_trace_record_s *record,
  1256. uint16_t index)
  1257. {
  1258. struct qdf_dp_trace_event_buf *buf =
  1259. (struct qdf_dp_trace_event_buf *)record->data;
  1260. qdf_print("DPT: %04d: %012llu: %s vdev_id %d", index,
  1261. record->time, qdf_dp_code_to_string(record->code),
  1262. buf->vdev_id);
  1263. qdf_print("DPT: Type %s Subtype %s", qdf_dp_type_to_str(buf->type),
  1264. qdf_dp_subtype_to_str(buf->subtype));
  1265. }
  1266. EXPORT_SYMBOL(qdf_dp_display_event_record);
  1267. /**
  1268. * qdf_dp_trace_record_event() - record events
  1269. * @code: dptrace code
  1270. * @vdev_id: vdev id
  1271. * @type: proto type
  1272. * @subtype: proto subtype
  1273. *
  1274. * Return: none
  1275. */
  1276. void qdf_dp_trace_record_event(enum QDF_DP_TRACE_ID code, uint8_t vdev_id,
  1277. enum qdf_proto_type type, enum qdf_proto_subtype subtype)
  1278. {
  1279. struct qdf_dp_trace_event_buf buf;
  1280. int buf_size = sizeof(struct qdf_dp_trace_event_buf);
  1281. if (qdf_dp_enable_check(NULL, code, QDF_NA) == false)
  1282. return;
  1283. if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
  1284. QDF_BUG(0);
  1285. buf.type = type;
  1286. buf.subtype = subtype;
  1287. buf.vdev_id = vdev_id;
  1288. qdf_dp_add_record(code, (uint8_t *)&buf, buf_size, true);
  1289. }
  1290. EXPORT_SYMBOL(qdf_dp_trace_record_event);
  1291. /**
  1292. * qdf_dp_display_proto_pkt() - display proto packet
  1293. * @record: dptrace record
  1294. * @index: index
  1295. *
  1296. * Return: none
  1297. */
  1298. void qdf_dp_display_proto_pkt(struct qdf_dp_trace_record_s *record,
  1299. uint16_t index)
  1300. {
  1301. struct qdf_dp_trace_proto_buf *buf =
  1302. (struct qdf_dp_trace_proto_buf *)record->data;
  1303. qdf_print("DPT: %04d: %012llu: %s vdev_id %d", index,
  1304. record->time, qdf_dp_code_to_string(record->code),
  1305. buf->vdev_id);
  1306. qdf_print("DPT: SA: " QDF_MAC_ADDRESS_STR " %s DA: "
  1307. QDF_MAC_ADDRESS_STR " Type %s Subtype %s",
  1308. QDF_MAC_ADDR_ARRAY(buf->sa.bytes), qdf_dp_dir_to_str(buf->dir),
  1309. QDF_MAC_ADDR_ARRAY(buf->da.bytes),
  1310. qdf_dp_type_to_str(buf->type),
  1311. qdf_dp_subtype_to_str(buf->subtype));
  1312. }
  1313. EXPORT_SYMBOL(qdf_dp_display_proto_pkt);
  1314. /**
  1315. * qdf_dp_trace_proto_pkt() - record proto packet
  1316. * @code: dptrace code
  1317. * @vdev_id: vdev id
  1318. * @sa: source mac address
  1319. * @da: destination mac address
  1320. * @type: proto type
  1321. * @subtype: proto subtype
  1322. * @dir: direction
  1323. *
  1324. * Return: none
  1325. */
  1326. void qdf_dp_trace_proto_pkt(enum QDF_DP_TRACE_ID code, uint8_t vdev_id,
  1327. uint8_t *sa, uint8_t *da, enum qdf_proto_type type,
  1328. enum qdf_proto_subtype subtype, enum qdf_proto_dir dir)
  1329. {
  1330. struct qdf_dp_trace_proto_buf buf;
  1331. int buf_size = sizeof(struct qdf_dp_trace_ptr_buf);
  1332. if (qdf_dp_enable_check(NULL, code, dir) == false)
  1333. return;
  1334. if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
  1335. QDF_BUG(0);
  1336. memcpy(&buf.sa, sa, QDF_NET_ETH_LEN);
  1337. memcpy(&buf.da, da, QDF_NET_ETH_LEN);
  1338. buf.dir = dir;
  1339. buf.type = type;
  1340. buf.subtype = subtype;
  1341. buf.vdev_id = vdev_id;
  1342. qdf_dp_add_record(code, (uint8_t *)&buf, buf_size, true);
  1343. }
  1344. EXPORT_SYMBOL(qdf_dp_trace_proto_pkt);
  1345. /**
  1346. * qdf_dp_display_ptr_record() - display record
  1347. * @record: dptrace record
  1348. * @index: index
  1349. *
  1350. * Return: none
  1351. */
  1352. void qdf_dp_display_ptr_record(struct qdf_dp_trace_record_s *record,
  1353. uint16_t index)
  1354. {
  1355. struct qdf_dp_trace_ptr_buf *buf =
  1356. (struct qdf_dp_trace_ptr_buf *)record->data;
  1357. if (record->code == QDF_DP_TRACE_FREE_PACKET_PTR_RECORD)
  1358. qdf_print("DPT: %04d: %012llu: %s msdu_id: %d, status: %d",
  1359. index, record->time,
  1360. qdf_dp_code_to_string(record->code), buf->msdu_id,
  1361. buf->status);
  1362. else
  1363. qdf_print("DPT: %04d: %012llu: %s msdu_id: %d, vdev_id: %d",
  1364. index,
  1365. record->time, qdf_dp_code_to_string(record->code),
  1366. buf->msdu_id, buf->status);
  1367. dump_hex_trace("cookie", (uint8_t *)&buf->cookie, sizeof(buf->cookie));
  1368. }
  1369. EXPORT_SYMBOL(qdf_dp_display_ptr_record);
  1370. /**
  1371. * qdf_dp_trace_ptr() - record dptrace
  1372. * @code: dptrace code
  1373. * @data: data
  1374. * @size: size of data
  1375. * @msdu_id: msdu_id
  1376. * @status: return status
  1377. *
  1378. * Return: none
  1379. */
  1380. void qdf_dp_trace_ptr(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code,
  1381. uint8_t *data, uint8_t size, uint16_t msdu_id, uint16_t status)
  1382. {
  1383. struct qdf_dp_trace_ptr_buf buf;
  1384. int buf_size = sizeof(struct qdf_dp_trace_ptr_buf);
  1385. if (qdf_dp_enable_check(nbuf, code, QDF_TX) == false)
  1386. return;
  1387. if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
  1388. QDF_BUG(0);
  1389. qdf_mem_copy(&buf.cookie, data, size);
  1390. buf.msdu_id = msdu_id;
  1391. buf.status = status;
  1392. qdf_dp_add_record(code, (uint8_t *)&buf, buf_size, false);
  1393. }
  1394. EXPORT_SYMBOL(qdf_dp_trace_ptr);
  1395. /**
  1396. * qdf_dp_display_trace() - Displays a record in DP trace
  1397. * @pRecord : pointer to a record in DP trace
  1398. * @recIndex : record index
  1399. *
  1400. * Return: None
  1401. */
  1402. void qdf_dp_display_record(struct qdf_dp_trace_record_s *pRecord,
  1403. uint16_t recIndex)
  1404. {
  1405. qdf_print("DPT: %04d: %012llu: %s", recIndex,
  1406. pRecord->time, qdf_dp_code_to_string(pRecord->code));
  1407. switch (pRecord->code) {
  1408. case QDF_DP_TRACE_HDD_TX_TIMEOUT:
  1409. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  1410. "HDD TX Timeout\n");
  1411. break;
  1412. case QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT:
  1413. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  1414. "HDD SoftAP TX Timeout\n");
  1415. break;
  1416. case QDF_DP_TRACE_HDD_TX_PACKET_RECORD:
  1417. dump_hex_trace("DATA", pRecord->data, pRecord->size);
  1418. break;
  1419. default:
  1420. dump_hex_trace("cookie", pRecord->data, pRecord->size);
  1421. }
  1422. }
  1423. EXPORT_SYMBOL(qdf_dp_display_record);
  1424. /**
  1425. * qdf_dp_trace() - Stores the data in buffer
  1426. * @nbuf : defines the netbuf
  1427. * @code : defines the event
  1428. * @data : defines the data to be stored
  1429. * @size : defines the size of the data record
  1430. *
  1431. * Return: None
  1432. */
  1433. void qdf_dp_trace(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code,
  1434. uint8_t *data, uint8_t size, enum qdf_proto_dir dir)
  1435. {
  1436. if (qdf_dp_enable_check(nbuf, code, dir) == false)
  1437. return;
  1438. qdf_dp_add_record(code, data, size, false);
  1439. }
  1440. EXPORT_SYMBOL(qdf_dp_trace);
  1441. /**
  1442. * qdf_dp_trace_spin_lock_init() - initializes the lock variable before use
  1443. * This function will be called from cds_alloc_global_context, we will have lock
  1444. * available to use ASAP
  1445. *
  1446. * Return: None
  1447. */
  1448. void qdf_dp_trace_spin_lock_init(void)
  1449. {
  1450. spin_lock_init(&l_dp_trace_lock);
  1451. }
  1452. EXPORT_SYMBOL(qdf_dp_trace_spin_lock_init);
  1453. /**
  1454. * qdf_dp_trace_enable_live_mode() - enable live mode for dptrace
  1455. *
  1456. * Return: none
  1457. */
  1458. void qdf_dp_trace_enable_live_mode(void)
  1459. {
  1460. g_qdf_dp_trace_data.live_mode = 1;
  1461. }
  1462. EXPORT_SYMBOL(qdf_dp_trace_enable_live_mode);
  1463. /**
  1464. * qdf_dp_trace_clear_buffer() - clear dp trace buffer
  1465. *
  1466. * Return: none
  1467. */
  1468. void qdf_dp_trace_clear_buffer(void)
  1469. {
  1470. g_qdf_dp_trace_data.head = INVALID_QDF_DP_TRACE_ADDR;
  1471. g_qdf_dp_trace_data.tail = INVALID_QDF_DP_TRACE_ADDR;
  1472. g_qdf_dp_trace_data.num = 0;
  1473. g_qdf_dp_trace_data.proto_bitmap = QDF_NBUF_PKT_TRAC_TYPE_EAPOL |
  1474. QDF_NBUF_PKT_TRAC_TYPE_DHCP | QDF_NBUF_PKT_TRAC_TYPE_MGMT_ACTION;
  1475. g_qdf_dp_trace_data.no_of_record = 0;
  1476. g_qdf_dp_trace_data.verbosity = QDF_DP_TRACE_VERBOSITY_LOW;
  1477. g_qdf_dp_trace_data.enable = true;
  1478. memset(g_qdf_dp_trace_tbl, 0,
  1479. MAX_QDF_DP_TRACE_RECORDS * sizeof(struct qdf_dp_trace_record_s));
  1480. }
  1481. EXPORT_SYMBOL(qdf_dp_trace_clear_buffer);
  1482. /**
  1483. * qdf_dp_trace_dump_all() - Dump data from ring buffer via call back functions
  1484. * registered with QDF
  1485. * @code: Reason code
  1486. * @count: Number of lines to dump starting from tail to head
  1487. *
  1488. * Return: None
  1489. */
  1490. void qdf_dp_trace_dump_all(uint32_t count)
  1491. {
  1492. struct qdf_dp_trace_record_s p_record;
  1493. int32_t i, tail;
  1494. if (!g_qdf_dp_trace_data.enable) {
  1495. QDF_TRACE(QDF_MODULE_ID_SYS,
  1496. QDF_TRACE_LEVEL_ERROR, "Tracing Disabled");
  1497. return;
  1498. }
  1499. QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_ERROR,
  1500. "Total Records: %d, Head: %d, Tail: %d",
  1501. g_qdf_dp_trace_data.num, g_qdf_dp_trace_data.head,
  1502. g_qdf_dp_trace_data.tail);
  1503. /* aquire the lock so that only one thread at a time can read
  1504. * the ring buffer
  1505. */
  1506. spin_lock_bh(&l_dp_trace_lock);
  1507. if (g_qdf_dp_trace_data.head != INVALID_QDF_DP_TRACE_ADDR) {
  1508. i = g_qdf_dp_trace_data.head;
  1509. tail = g_qdf_dp_trace_data.tail;
  1510. if (count) {
  1511. if (count > g_qdf_dp_trace_data.num)
  1512. count = g_qdf_dp_trace_data.num;
  1513. if (tail >= (count - 1))
  1514. i = tail - count + 1;
  1515. else if (count != MAX_QDF_DP_TRACE_RECORDS)
  1516. i = MAX_QDF_DP_TRACE_RECORDS - ((count - 1) -
  1517. tail);
  1518. }
  1519. p_record = g_qdf_dp_trace_tbl[i];
  1520. spin_unlock_bh(&l_dp_trace_lock);
  1521. for (;; ) {
  1522. qdf_dp_trace_cb_table[p_record.
  1523. code] (&p_record, (uint16_t)i);
  1524. if (i == tail)
  1525. break;
  1526. i += 1;
  1527. spin_lock_bh(&l_dp_trace_lock);
  1528. if (MAX_QDF_DP_TRACE_RECORDS == i)
  1529. i = 0;
  1530. p_record = g_qdf_dp_trace_tbl[i];
  1531. spin_unlock_bh(&l_dp_trace_lock);
  1532. }
  1533. } else {
  1534. spin_unlock_bh(&l_dp_trace_lock);
  1535. }
  1536. }
  1537. EXPORT_SYMBOL(qdf_dp_trace_dump_all);
  1538. #endif