wlan_logging_sock_svc.c 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819
  1. /*
  2. * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
  3. * Copyright (c) 2022-2024 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. * wlan_logging_sock_svc.c
  21. *
  22. ******************************************************************************/
  23. #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
  24. #include <linux/vmalloc.h>
  25. #include <wlan_logging_sock_svc.h>
  26. #include <linux/kthread.h>
  27. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0))
  28. #include <linux/panic_notifier.h>
  29. #endif
  30. #include <qdf_time.h>
  31. #include <qdf_trace.h>
  32. #include <qdf_mc_timer.h>
  33. #include <qdf_timer.h>
  34. #include <qdf_lock.h>
  35. #include <wlan_ptt_sock_svc.h>
  36. #include <host_diag_core_event.h>
  37. #include "host_diag_core_log.h"
  38. #include <qdf_event.h>
  39. #include <qdf_module.h>
  40. #include <qdf_str.h>
  41. #ifdef WLAN_FEATURE_CONNECTIVITY_LOGGING
  42. #include <wlan_connectivity_logging.h>
  43. #endif
  44. #include "qdf_ssr_driver_dump.h"
  45. #ifdef CNSS_GENL
  46. #ifdef CONFIG_CNSS_OUT_OF_TREE
  47. #include "cnss_nl.h"
  48. #else
  49. #include <net/cnss_nl.h>
  50. #endif
  51. #endif
  52. #if defined(FEATURE_FW_LOG_PARSING) || defined(FEATURE_WLAN_DIAG_SUPPORT) || \
  53. defined(CONNECTIVITY_PKTLOG)
  54. #include <cds_api.h>
  55. #include "ani_global.h"
  56. #endif
  57. #ifdef CONNECTIVITY_PKTLOG
  58. #include "wma.h"
  59. #include "pktlog_ac.h"
  60. #include <cdp_txrx_misc.h>
  61. #endif
  62. /*
  63. * The following commit was introduced in v5.17:
  64. * cead18552660 ("exit: Rename complete_and_exit to kthread_complete_and_exit")
  65. * Use the old name for kernels before 5.17
  66. */
  67. #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 17, 0))
  68. #define kthread_complete_and_exit(c, s) complete_and_exit(c, s)
  69. #endif
  70. #define MAX_NUM_PKT_LOG 32
  71. #define LOGGING_TRACE(level, args ...) \
  72. QDF_TRACE(QDF_MODULE_ID_HDD, level, ## args)
  73. /* Global variables */
  74. #define ANI_NL_MSG_LOG_TYPE 89
  75. #define ANI_NL_MSG_READY_IND_TYPE 90
  76. #ifndef MAX_LOGMSG_COUNT
  77. #define MAX_LOGMSG_COUNT 256
  78. #endif
  79. #define MAX_LOGMSG_LENGTH 2048
  80. #define MAX_SKBMSG_LENGTH 4096
  81. #define WLAN_LOG_BUFFER_SIZE 2048
  82. #ifdef CONNECTIVITY_PKTLOG
  83. /**
  84. * Buffer to accommodate -
  85. * pktlog buffer (2048 bytes)
  86. * ath_pktlog_hdr (16 bytes)
  87. * pkt_dump (8 bytes)
  88. * extra padding (40 bytes)
  89. *
  90. * Note: pktlog buffer size is dependent on RX_BUFFER_SIZE and
  91. * HTT_T2H_MAX_MSG_SIZE. Adjust WLAN_LOG_BUFFER_SIZE
  92. * based on the above mentioned macros.
  93. */
  94. #define ATH_PKTLOG_HDR_SIZE (sizeof(struct ath_pktlog_hdr))
  95. #define PKT_DUMP_HDR_SIZE (sizeof(struct packet_dump))
  96. #define EXTRA_PADDING 40
  97. #define MAX_PKTSTATS_LENGTH \
  98. ((WLAN_LOG_BUFFER_SIZE) + (ATH_PKTLOG_HDR_SIZE) + \
  99. (PKT_DUMP_HDR_SIZE) + (EXTRA_PADDING))
  100. #else
  101. #define MAX_PKTSTATS_LENGTH WLAN_LOG_BUFFER_SIZE
  102. #endif /* CONNECTIVITY_PKTLOG */
  103. #define MAX_PKTSTATS_BUFF 16
  104. #define HOST_LOG_DRIVER_MSG 0x001
  105. #define HOST_LOG_PER_PKT_STATS 0x002
  106. #define HOST_LOG_FW_FLUSH_COMPLETE 0x003
  107. #define HOST_LOG_DRIVER_CONNECTIVITY_MSG 0x004
  108. #define HOST_LOG_CHIPSET_STATS 0x005
  109. #define FW_LOG_CHIPSET_STATS 0x006
  110. #define DIAG_TYPE_LOGS 1
  111. #define PTT_MSG_DIAG_CMDS_TYPE 0x5050
  112. #define MAX_LOG_LINE 500
  113. /* default rate limit period - 2sec */
  114. #define PANIC_WIFILOG_PRINT_RATE_LIMIT_PERIOD (2*HZ)
  115. /* default burst for rate limit */
  116. #define PANIC_WIFILOG_PRINT_RATE_LIMIT_BURST_DEFAULT 500
  117. DEFINE_RATELIMIT_STATE(panic_wifilog_ratelimit,
  118. PANIC_WIFILOG_PRINT_RATE_LIMIT_PERIOD,
  119. PANIC_WIFILOG_PRINT_RATE_LIMIT_BURST_DEFAULT);
  120. #define FLUSH_LOG_COMPLETION_TIMEOUT 3000
  121. struct log_msg {
  122. struct list_head node;
  123. unsigned int radio;
  124. unsigned int index;
  125. /* indicates the current filled log length in logbuf */
  126. unsigned int filled_length;
  127. /*
  128. * Buf to hold the log msg
  129. * tAniHdr + log
  130. */
  131. char logbuf[MAX_LOGMSG_LENGTH];
  132. };
  133. /**
  134. * struct packet_dump - This data structure contains the
  135. * Tx/Rx packet stats
  136. * @status: Status
  137. * @type: Type
  138. * @driver_ts: driver timestamp
  139. * @fw_ts: fw timestamp
  140. */
  141. struct packet_dump {
  142. unsigned char status;
  143. unsigned char type;
  144. uint32_t driver_ts;
  145. uint16_t fw_ts;
  146. } __attribute__((__packed__));
  147. /**
  148. * struct pkt_stats_msg - This data structure contains the
  149. * pkt stats node for link list
  150. * @node: LinkList node
  151. * @node: Pointer to skb
  152. */
  153. struct pkt_stats_msg {
  154. struct list_head node;
  155. struct sk_buff *skb;
  156. };
  157. #define MAX_FLUSH_TIMER_PERIOD_VALUE 3600000 /* maximum of 1 hour (in ms) */
  158. struct wlan_logging {
  159. /* Console log levels */
  160. uint32_t console_log_levels;
  161. /* Number of buffers to be used for logging */
  162. uint32_t num_buf;
  163. uint32_t buffer_length;
  164. /* Lock to synchronize access to shared logging resource */
  165. spinlock_t spin_lock;
  166. /* Holds the free node which can be used for filling logs */
  167. struct list_head free_list;
  168. /* Holds the filled nodes which needs to be indicated to APP */
  169. struct list_head filled_list;
  170. /* Holds nodes for console printing in case of kernel panic */
  171. struct list_head panic_list;
  172. /* Wait queue for Logger thread */
  173. wait_queue_head_t wait_queue;
  174. /* Logger thread */
  175. struct task_struct *thread;
  176. /* Logging thread sets this variable on exit */
  177. struct completion shutdown_comp;
  178. /* Indicates to logger thread to exit */
  179. bool exit;
  180. /* Holds number of dropped logs */
  181. unsigned int drop_count;
  182. /* current logbuf to which the log will be filled to */
  183. struct log_msg *pcur_node;
  184. /* Event flag used for wakeup and post indication*/
  185. unsigned long eventFlag;
  186. /* Indicates logger thread is activated */
  187. bool is_active;
  188. /* Flush completion check */
  189. bool is_flush_complete;
  190. /* parameters for pkt stats */
  191. struct list_head pkt_stat_free_list;
  192. struct list_head pkt_stat_filled_list;
  193. struct pkt_stats_msg *pkt_stats_pcur_node;
  194. unsigned int pkt_stat_drop_cnt;
  195. spinlock_t pkt_stats_lock;
  196. unsigned int pkt_stats_msg_idx;
  197. qdf_timer_t flush_timer;
  198. bool is_flush_timer_initialized;
  199. uint32_t flush_timer_period;
  200. qdf_spinlock_t flush_timer_lock;
  201. qdf_event_t flush_log_completion;
  202. uint64_t wakup_ts;
  203. uint64_t start_ts;
  204. uint64_t reinitcompletion_ts;
  205. uint64_t set_exit_ts;
  206. uint64_t exit_ts;
  207. };
  208. /* This global variable is intentionally not marked static because it
  209. * is used by offline tools. Please do not use it outside this file.
  210. */
  211. struct wlan_logging gwlan_logging;
  212. static struct pkt_stats_msg *gpkt_stats_buffers;
  213. #ifdef WLAN_LOGGING_BUFFERS_DYNAMICALLY
  214. static struct log_msg *gplog_msg;
  215. static inline QDF_STATUS allocate_log_msg_buffer(void)
  216. {
  217. gplog_msg = qdf_mem_valloc(MAX_LOGMSG_COUNT * sizeof(*gplog_msg));
  218. return gplog_msg ? QDF_STATUS_SUCCESS : QDF_STATUS_E_NOMEM;
  219. }
  220. static inline void free_log_msg_buffer(void)
  221. {
  222. qdf_mem_vfree(gplog_msg);
  223. gplog_msg = NULL;
  224. }
  225. #else
  226. static struct log_msg gplog_msg[MAX_LOGMSG_COUNT];
  227. static inline QDF_STATUS allocate_log_msg_buffer(void)
  228. {
  229. qdf_minidump_log(&gwlan_logging, sizeof(gwlan_logging),
  230. "gwlan_logging");
  231. qdf_minidump_log(gplog_msg, sizeof(gplog_msg), "wlan_logs");
  232. qdf_ssr_driver_dump_register_region("gwlan_logging", &gwlan_logging,
  233. sizeof(gwlan_logging));
  234. qdf_ssr_driver_dump_register_region("wlan_logs", gplog_msg,
  235. sizeof(gplog_msg));
  236. return QDF_STATUS_SUCCESS;
  237. }
  238. static inline void free_log_msg_buffer(void)
  239. {
  240. qdf_ssr_driver_dump_unregister_region("wlan_logs");
  241. qdf_ssr_driver_dump_unregister_region("gwlan_logging");
  242. qdf_minidump_remove(gplog_msg, sizeof(gplog_msg), "wlan_logs");
  243. qdf_minidump_remove(&gwlan_logging, sizeof(gwlan_logging),
  244. "gwlan_logging");
  245. }
  246. #endif
  247. /* Need to call this with spin_lock acquired */
  248. static int wlan_queue_logmsg_for_app(void)
  249. {
  250. char *ptr;
  251. int ret = 0;
  252. ptr = &gwlan_logging.pcur_node->logbuf[sizeof(tAniHdr)];
  253. ptr[gwlan_logging.pcur_node->filled_length] = '\0';
  254. *(unsigned short *)(gwlan_logging.pcur_node->logbuf) =
  255. ANI_NL_MSG_LOG_TYPE;
  256. *(unsigned short *)(gwlan_logging.pcur_node->logbuf + 2) =
  257. gwlan_logging.pcur_node->filled_length;
  258. list_add_tail(&gwlan_logging.pcur_node->node,
  259. &gwlan_logging.filled_list);
  260. if (!list_empty(&gwlan_logging.free_list)) {
  261. /* Get buffer from free list */
  262. gwlan_logging.pcur_node =
  263. (struct log_msg *)(gwlan_logging.free_list.next);
  264. list_del_init(gwlan_logging.free_list.next);
  265. } else if (!list_empty(&gwlan_logging.filled_list)) {
  266. /* Get buffer from filled list */
  267. /* This condition will drop the packet from being
  268. * indicated to app
  269. */
  270. gwlan_logging.pcur_node =
  271. (struct log_msg *)(gwlan_logging.filled_list.next);
  272. ++gwlan_logging.drop_count;
  273. list_del_init(gwlan_logging.filled_list.next);
  274. ret = 1;
  275. }
  276. /* Reset the current node values */
  277. gwlan_logging.pcur_node->filled_length = 0;
  278. return ret;
  279. }
  280. static const char *current_process_name(void)
  281. {
  282. if (in_irq())
  283. return "irq";
  284. if (in_softirq())
  285. return "soft_irq";
  286. return current->comm;
  287. }
  288. /**
  289. * wlan_add_user_log_time_stamp() - populate firmware and kernel timestamps
  290. * @tbuf: Pointer to time stamp buffer
  291. * @tbuf_sz: Time buffer size
  292. * @ts: Time stamp value
  293. *
  294. * For adrastea time stamp is QTIMER raw tick which will be used by cnss_diag
  295. * to convert it into user visible time stamp. In adrstea FW also uses QTIMER
  296. * raw ticks which is needed to synchronize host and fw log time stamps
  297. *
  298. * Also add logcat timestamp so that driver logs and
  299. * logcat logs can be co-related
  300. *
  301. * For discrete solution e.g rome use system tick and convert it into
  302. * seconds.milli seconds
  303. *
  304. * Return: number of characters written in target buffer not including
  305. * trailing '/0'
  306. */
  307. static int wlan_add_user_log_time_stamp(char *tbuf, size_t tbuf_sz, uint64_t ts)
  308. {
  309. char time_buf[20];
  310. qdf_get_time_of_the_day_in_hr_min_sec_usec(time_buf, sizeof(time_buf));
  311. return scnprintf(tbuf, tbuf_sz, "[%.6s][0x%llx]%s",
  312. current_process_name(), (unsigned long long)ts,
  313. time_buf);
  314. }
  315. #ifdef WLAN_MAX_LOGS_PER_SEC
  316. static inline void wlan_panic_on_excessive_logging(void)
  317. {
  318. if (qdf_detected_excessive_logging())
  319. QDF_DEBUG_PANIC("Exceeded %d logs per second",
  320. WLAN_MAX_LOGS_PER_SEC);
  321. }
  322. #else
  323. static inline void wlan_panic_on_excessive_logging(void) {}
  324. #endif /* WLAN_MAX_LOGS_PER_SEC */
  325. #ifdef QDF_TRACE_PRINT_ENABLE
  326. static inline void
  327. log_to_console(QDF_TRACE_LEVEL level, const char *timestamp, const char *msg)
  328. {
  329. if (qdf_detected_excessive_logging()) {
  330. qdf_rl_print_suppressed_inc();
  331. return;
  332. }
  333. qdf_rl_print_suppressed_log();
  334. pr_err("%s %s\n", timestamp, msg);
  335. }
  336. #else
  337. static inline void
  338. log_to_console(QDF_TRACE_LEVEL level, const char *timestamp, const char *msg)
  339. {
  340. switch (level) {
  341. case QDF_TRACE_LEVEL_FATAL:
  342. pr_alert("%s %s\n", timestamp, msg);
  343. wlan_panic_on_excessive_logging();
  344. break;
  345. case QDF_TRACE_LEVEL_ERROR:
  346. pr_err("%s %s\n", timestamp, msg);
  347. wlan_panic_on_excessive_logging();
  348. break;
  349. case QDF_TRACE_LEVEL_WARN:
  350. pr_warn("%s %s\n", timestamp, msg);
  351. wlan_panic_on_excessive_logging();
  352. break;
  353. case QDF_TRACE_LEVEL_INFO:
  354. pr_info("%s %s\n", timestamp, msg);
  355. wlan_panic_on_excessive_logging();
  356. break;
  357. case QDF_TRACE_LEVEL_INFO_HIGH:
  358. case QDF_TRACE_LEVEL_INFO_MED:
  359. case QDF_TRACE_LEVEL_INFO_LOW:
  360. case QDF_TRACE_LEVEL_DEBUG:
  361. default:
  362. /* these levels should not be logged to console */
  363. break;
  364. }
  365. }
  366. #endif
  367. int wlan_log_to_user(QDF_TRACE_LEVEL log_level, char *to_be_sent, int length)
  368. {
  369. char *ptr;
  370. char tbuf[60];
  371. int tlen;
  372. int total_log_len;
  373. unsigned int *pfilled_length;
  374. bool wake_up_thread = false;
  375. unsigned long flags;
  376. uint64_t ts;
  377. /* Add the current time stamp */
  378. ts = qdf_get_log_timestamp();
  379. tlen = wlan_add_user_log_time_stamp(tbuf, sizeof(tbuf), ts);
  380. /* if logging isn't up yet, just dump to dmesg */
  381. if (!gwlan_logging.is_active) {
  382. log_to_console(log_level, tbuf, to_be_sent);
  383. return 0;
  384. }
  385. /* 1+1 indicate '\n'+'\0' */
  386. total_log_len = length + tlen + 1 + 1;
  387. spin_lock_irqsave(&gwlan_logging.spin_lock, flags);
  388. /* wlan logging svc resources are not yet initialized */
  389. if (!gwlan_logging.pcur_node) {
  390. spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags);
  391. return -EIO;
  392. }
  393. pfilled_length = &gwlan_logging.pcur_node->filled_length;
  394. /* Check if we can accommodate more log into current node/buffer */
  395. if ((MAX_LOGMSG_LENGTH - (*pfilled_length +
  396. sizeof(tAniNlHdr))) < total_log_len) {
  397. wake_up_thread = true;
  398. wlan_queue_logmsg_for_app();
  399. pfilled_length = &gwlan_logging.pcur_node->filled_length;
  400. }
  401. ptr = &gwlan_logging.pcur_node->logbuf[sizeof(tAniHdr)];
  402. if (unlikely(MAX_LOGMSG_LENGTH < (sizeof(tAniNlHdr) + total_log_len))) {
  403. /*
  404. * Assumption here is that we receive logs which is less than
  405. * MAX_LOGMSG_LENGTH, where we can accommodate the
  406. * tAniNlHdr + [context][timestamp] + log
  407. * If log length is over MAX_LOGMSG_LENGTH,
  408. * the overflow part will be discarded.
  409. */
  410. length = MAX_LOGMSG_LENGTH - sizeof(tAniNlHdr) - tlen - 2;
  411. /*
  412. * QDF_ASSERT if complete log was not accommodated into
  413. * the available buffer.
  414. */
  415. QDF_ASSERT(0);
  416. }
  417. memcpy(&ptr[*pfilled_length], tbuf, tlen);
  418. memcpy(&ptr[*pfilled_length + tlen], to_be_sent, length);
  419. *pfilled_length += tlen + length;
  420. ptr[*pfilled_length] = '\n';
  421. *pfilled_length += 1;
  422. spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags);
  423. /* Wakeup logger thread */
  424. if (wake_up_thread) {
  425. set_bit(HOST_LOG_DRIVER_MSG, &gwlan_logging.eventFlag);
  426. wake_up_interruptible(&gwlan_logging.wait_queue);
  427. }
  428. if (gwlan_logging.console_log_levels & BIT(log_level))
  429. log_to_console(log_level, tbuf, to_be_sent);
  430. return 0;
  431. }
  432. /**
  433. * nl_srv_bcast_host_logs() - Wrapper to send bcast msgs to host logs mcast grp
  434. * @skb: sk buffer pointer
  435. *
  436. * Sends the bcast message to host logs multicast group with generic nl socket
  437. * if CNSS_GENL is enabled. Else, use the legacy netlink socket to send.
  438. *
  439. * Return: zero on success, error code otherwise
  440. */
  441. #ifdef CNSS_GENL
  442. static int nl_srv_bcast_host_logs(struct sk_buff *skb)
  443. {
  444. return nl_srv_bcast(skb, CLD80211_MCGRP_HOST_LOGS, ANI_NL_MSG_LOG);
  445. }
  446. #else
  447. static int nl_srv_bcast_host_logs(struct sk_buff *skb)
  448. {
  449. return nl_srv_bcast(skb);
  450. }
  451. #endif
  452. #ifdef CONNECTIVITY_PKTLOG
  453. /**
  454. * pkt_stats_fill_headers() - This function adds headers to skb
  455. * @skb: skb to which headers need to be added
  456. *
  457. * Return: 0 on success or Errno on failure
  458. */
  459. static int pkt_stats_fill_headers(struct sk_buff *skb)
  460. {
  461. struct host_log_pktlog_info cds_pktlog;
  462. int cds_pkt_size = sizeof(struct host_log_pktlog_info);
  463. tAniNlHdr msg_header;
  464. int extra_header_len, nl_payload_len;
  465. static int nlmsg_seq;
  466. int diag_type;
  467. qdf_mem_zero(&cds_pktlog, cds_pkt_size);
  468. cds_pktlog.version = VERSION_LOG_WLAN_PKT_LOG_INFO_C;
  469. cds_pktlog.buf_len = skb->len;
  470. cds_pktlog.seq_no = gwlan_logging.pkt_stats_msg_idx++;
  471. host_diag_log_set_code(&cds_pktlog, LOG_WLAN_PKT_LOG_INFO_C);
  472. host_diag_log_set_length(&cds_pktlog.log_hdr, skb->len +
  473. cds_pkt_size);
  474. if (unlikely(skb_headroom(skb) < cds_pkt_size)) {
  475. qdf_nofl_err("VPKT [%d]: Insufficient headroom, head[%pK], data[%pK], req[%zu]",
  476. __LINE__, skb->head, skb->data,
  477. sizeof(msg_header));
  478. return -EIO;
  479. }
  480. qdf_mem_copy(skb_push(skb, cds_pkt_size),
  481. &cds_pktlog, cds_pkt_size);
  482. if (unlikely(skb_headroom(skb) < sizeof(int))) {
  483. qdf_nofl_err("VPKT [%d]: Insufficient headroom, head[%pK], data[%pK], req[%zu]",
  484. __LINE__, skb->head, skb->data,
  485. sizeof(int));
  486. return -EIO;
  487. }
  488. diag_type = DIAG_TYPE_LOGS;
  489. qdf_mem_copy(skb_push(skb, sizeof(int)), &diag_type, sizeof(int));
  490. extra_header_len = sizeof(msg_header.radio) + sizeof(tAniHdr) +
  491. sizeof(struct nlmsghdr);
  492. nl_payload_len = extra_header_len + skb->len;
  493. msg_header.nlh.nlmsg_type = ANI_NL_MSG_PUMAC;
  494. msg_header.nlh.nlmsg_len = nl_payload_len;
  495. msg_header.nlh.nlmsg_flags = NLM_F_REQUEST;
  496. msg_header.nlh.nlmsg_pid = 0;
  497. msg_header.nlh.nlmsg_seq = nlmsg_seq++;
  498. msg_header.radio = 0;
  499. msg_header.wmsg.type = PTT_MSG_DIAG_CMDS_TYPE;
  500. msg_header.wmsg.length = cpu_to_be16(skb->len);
  501. if (unlikely(skb_headroom(skb) < sizeof(msg_header))) {
  502. qdf_nofl_err("VPKT [%d]: Insufficient headroom, head[%pK], data[%pK], req[%zu]",
  503. __LINE__, skb->head, skb->data,
  504. sizeof(msg_header));
  505. return -EIO;
  506. }
  507. qdf_mem_copy(skb_push(skb, sizeof(msg_header)), &msg_header,
  508. sizeof(msg_header));
  509. return 0;
  510. }
  511. /**
  512. * nl_srv_bcast_diag() - Wrapper to send bcast msgs to diag events mcast grp
  513. * @skb: sk buffer pointer
  514. *
  515. * Sends the bcast message to diag events multicast group with generic nl socket
  516. * if CNSS_GENL is enabled. Else, use the legacy netlink socket to send.
  517. *
  518. * Return: zero on success, error code otherwise
  519. */
  520. static int nl_srv_bcast_diag(struct sk_buff *skb)
  521. {
  522. #ifdef CNSS_GENL
  523. return nl_srv_bcast(skb, CLD80211_MCGRP_DIAG_EVENTS, ANI_NL_MSG_PUMAC);
  524. #else
  525. return nl_srv_bcast(skb);
  526. #endif
  527. }
  528. /**
  529. * pktlog_send_per_pkt_stats_to_user() - This function is used to send the per
  530. * packet statistics to the user
  531. *
  532. * This function is used to send the per packet statistics to the user
  533. *
  534. * Return: Success if the message is posted to user
  535. */
  536. static int pktlog_send_per_pkt_stats_to_user(void)
  537. {
  538. int ret = -1;
  539. struct pkt_stats_msg *pstats_msg;
  540. unsigned long flags;
  541. struct sk_buff *skb_new = NULL;
  542. static int rate_limit;
  543. bool free_old_skb = false;
  544. while (!list_empty(&gwlan_logging.pkt_stat_filled_list)
  545. && !gwlan_logging.exit) {
  546. skb_new = dev_alloc_skb(MAX_SKBMSG_LENGTH);
  547. if (!skb_new) {
  548. if (!rate_limit) {
  549. qdf_err("dev_alloc_skb() failed for msg size[%d] drop count = %u",
  550. MAX_SKBMSG_LENGTH,
  551. gwlan_logging.drop_count);
  552. }
  553. rate_limit = 1;
  554. ret = -ENOMEM;
  555. break;
  556. }
  557. spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, flags);
  558. pstats_msg = (struct pkt_stats_msg *)
  559. (gwlan_logging.pkt_stat_filled_list.next);
  560. list_del_init(gwlan_logging.pkt_stat_filled_list.next);
  561. spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, flags);
  562. ret = pkt_stats_fill_headers(pstats_msg->skb);
  563. if (ret < 0) {
  564. qdf_err("Failed to fill headers %d", ret);
  565. free_old_skb = true;
  566. goto err;
  567. }
  568. ret = nl_srv_bcast_diag(pstats_msg->skb);
  569. if (ret < 0) {
  570. qdf_info("Send Failed %d drop_count = %u", ret,
  571. ++gwlan_logging.pkt_stat_drop_cnt);
  572. } else {
  573. ret = 0;
  574. }
  575. err:
  576. /*
  577. * Free old skb in case or error before assigning new skb
  578. * to the free list.
  579. */
  580. if (free_old_skb)
  581. dev_kfree_skb(pstats_msg->skb);
  582. spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, flags);
  583. pstats_msg->skb = skb_new;
  584. list_add_tail(&pstats_msg->node,
  585. &gwlan_logging.pkt_stat_free_list);
  586. spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, flags);
  587. ret = 0;
  588. }
  589. return ret;
  590. }
  591. #else
  592. static inline
  593. int pktlog_send_per_pkt_stats_to_user(void)
  594. {
  595. return 0;
  596. }
  597. #endif
  598. static int send_filled_buffers_to_user(void)
  599. {
  600. int ret = -1;
  601. struct log_msg *plog_msg;
  602. int payload_len;
  603. int tot_msg_len;
  604. tAniNlHdr *wnl;
  605. struct sk_buff *skb = NULL;
  606. struct nlmsghdr *nlh;
  607. static int nlmsg_seq;
  608. unsigned long flags;
  609. static int rate_limit;
  610. while (!list_empty(&gwlan_logging.filled_list)
  611. && !gwlan_logging.exit) {
  612. skb = dev_alloc_skb(MAX_LOGMSG_LENGTH);
  613. if (!skb) {
  614. if (!rate_limit) {
  615. qdf_err("dev_alloc_skb() failed for msg size[%d] drop count = %u",
  616. MAX_LOGMSG_LENGTH,
  617. gwlan_logging.drop_count);
  618. }
  619. rate_limit = 1;
  620. ret = -ENOMEM;
  621. break;
  622. }
  623. rate_limit = 0;
  624. spin_lock_irqsave(&gwlan_logging.spin_lock, flags);
  625. plog_msg = (struct log_msg *)
  626. (gwlan_logging.filled_list.next);
  627. list_del_init(gwlan_logging.filled_list.next);
  628. spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags);
  629. /* 4 extra bytes for the radio idx */
  630. payload_len = plog_msg->filled_length +
  631. sizeof(wnl->radio) + sizeof(tAniHdr);
  632. tot_msg_len = NLMSG_SPACE(payload_len);
  633. nlh = nlmsg_put(skb, 0, nlmsg_seq++,
  634. ANI_NL_MSG_LOG, payload_len, NLM_F_REQUEST);
  635. if (!nlh) {
  636. spin_lock_irqsave(&gwlan_logging.spin_lock, flags);
  637. list_add_tail(&plog_msg->node,
  638. &gwlan_logging.free_list);
  639. spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags);
  640. qdf_err("drop_count = %u", ++gwlan_logging.drop_count);
  641. qdf_err("nlmsg_put() failed for msg size[%d]",
  642. tot_msg_len);
  643. dev_kfree_skb(skb);
  644. skb = NULL;
  645. ret = -EINVAL;
  646. continue;
  647. }
  648. wnl = (tAniNlHdr *) nlh;
  649. wnl->radio = plog_msg->radio;
  650. /* Offset of data buffer from nlmsg_hdr + sizeof(int) radio */
  651. memcpy(nlmsg_data(nlh) + sizeof(wnl->radio), plog_msg->logbuf,
  652. plog_msg->filled_length + sizeof(tAniHdr));
  653. spin_lock_irqsave(&gwlan_logging.spin_lock, flags);
  654. list_add_tail(&plog_msg->node, &gwlan_logging.free_list);
  655. spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags);
  656. ret = nl_srv_bcast_host_logs(skb);
  657. /* print every 64th drop count */
  658. if (ret < 0 && (!(gwlan_logging.drop_count % 0x40))) {
  659. qdf_err("Send Failed %d drop_count = %u",
  660. ret, ++gwlan_logging.drop_count);
  661. }
  662. }
  663. return ret;
  664. }
  665. #ifdef FEATURE_WLAN_DIAG_SUPPORT
  666. /**
  667. * wlan_report_log_completion() - Report bug report completion to userspace
  668. * @is_fatal: Type of event, fatal or not
  669. * @indicator: Source of bug report, framework/host/firmware
  670. * @reason_code: Reason for triggering bug report
  671. * @ring_id: Ring id of logging entities
  672. *
  673. * This function is used to report the bug report completion to userspace
  674. *
  675. * Return: None
  676. */
  677. void wlan_report_log_completion(uint32_t is_fatal,
  678. uint32_t indicator,
  679. uint32_t reason_code,
  680. uint8_t ring_id)
  681. {
  682. WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event,
  683. struct host_event_wlan_log_complete);
  684. wlan_diag_event.is_fatal = is_fatal;
  685. wlan_diag_event.indicator = indicator;
  686. wlan_diag_event.reason_code = reason_code;
  687. wlan_diag_event.reserved = ring_id;
  688. WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_LOG_COMPLETE);
  689. }
  690. #endif
  691. #ifdef FEATURE_WLAN_DIAG_SUPPORT
  692. /**
  693. * send_flush_completion_to_user() - Indicate flush completion to the user
  694. * @ring_id: Ring id of logging entities
  695. *
  696. * This function is used to send the flush completion message to user space
  697. *
  698. * Return: None
  699. */
  700. static void send_flush_completion_to_user(uint8_t ring_id)
  701. {
  702. uint32_t is_fatal, indicator, reason_code;
  703. bool recovery_needed;
  704. cds_get_and_reset_log_completion(&is_fatal,
  705. &indicator, &reason_code, &recovery_needed);
  706. /* Error on purpose, so that it will get logged in the kmsg */
  707. LOGGING_TRACE(QDF_TRACE_LEVEL_DEBUG,
  708. "%s: Sending flush done to userspace reason code %d",
  709. __func__, reason_code);
  710. wlan_report_log_completion(is_fatal, indicator, reason_code, ring_id);
  711. if (recovery_needed)
  712. cds_trigger_recovery(QDF_FLUSH_LOGS);
  713. }
  714. #endif
  715. static void wlan_logging_set_flush_log_completion(void)
  716. {
  717. qdf_event_set(&gwlan_logging.flush_log_completion);
  718. }
  719. QDF_STATUS wlan_logging_wait_for_flush_log_completion(void)
  720. {
  721. qdf_event_reset(&gwlan_logging.flush_log_completion);
  722. return qdf_wait_for_event_completion(
  723. &gwlan_logging.flush_log_completion,
  724. FLUSH_LOG_COMPLETION_TIMEOUT);
  725. }
  726. static void setup_flush_timer(void)
  727. {
  728. qdf_spin_lock(&gwlan_logging.flush_timer_lock);
  729. if (!gwlan_logging.is_flush_timer_initialized ||
  730. (gwlan_logging.flush_timer_period == 0)) {
  731. qdf_spin_unlock(&gwlan_logging.flush_timer_lock);
  732. return;
  733. }
  734. qdf_timer_mod(&gwlan_logging.flush_timer,
  735. gwlan_logging.flush_timer_period);
  736. qdf_spin_unlock(&gwlan_logging.flush_timer_lock);
  737. }
  738. #ifdef WLAN_FEATURE_CONNECTIVITY_LOGGING
  739. static QDF_STATUS
  740. wlan_logging_send_connectivity_event(void)
  741. {
  742. return wlan_connectivity_log_dequeue();
  743. }
  744. #else
  745. static inline QDF_STATUS
  746. wlan_logging_send_connectivity_event(void)
  747. {
  748. return QDF_STATUS_E_NOSUPPORT;
  749. }
  750. #endif
  751. /**
  752. * wlan_logging_thread() - The WLAN Logger thread
  753. * @Arg - pointer to the HDD context
  754. *
  755. * This thread logs log message to App registered for the logs.
  756. */
  757. static int wlan_logging_thread(void *Arg)
  758. {
  759. int ret_wait_status = 0;
  760. int ret = 0;
  761. unsigned long flags;
  762. gwlan_logging.start_ts = qdf_get_log_timestamp();
  763. while (!gwlan_logging.exit) {
  764. setup_flush_timer();
  765. ret_wait_status =
  766. wait_event_interruptible(gwlan_logging.wait_queue,
  767. (!list_empty
  768. (&gwlan_logging.filled_list)
  769. || test_bit(
  770. HOST_LOG_DRIVER_MSG,
  771. &gwlan_logging.eventFlag)
  772. || test_bit(
  773. HOST_LOG_PER_PKT_STATS,
  774. &gwlan_logging.eventFlag)
  775. || test_bit(
  776. HOST_LOG_FW_FLUSH_COMPLETE,
  777. &gwlan_logging.eventFlag)
  778. || test_bit(
  779. HOST_LOG_DRIVER_CONNECTIVITY_MSG,
  780. &gwlan_logging.eventFlag)
  781. || gwlan_logging.exit));
  782. if (ret_wait_status == -ERESTARTSYS) {
  783. qdf_err("wait_event_interruptible returned -ERESTARTSYS");
  784. break;
  785. }
  786. if (gwlan_logging.exit)
  787. break;
  788. if (test_and_clear_bit(HOST_LOG_DRIVER_MSG,
  789. &gwlan_logging.eventFlag)) {
  790. ret = send_filled_buffers_to_user();
  791. if (-ENOMEM == ret)
  792. msleep(200);
  793. #ifdef FEATURE_WLAN_DIAG_SUPPORT
  794. if (WLAN_LOG_INDICATOR_HOST_ONLY ==
  795. cds_get_log_indicator()) {
  796. send_flush_completion_to_user(
  797. RING_ID_DRIVER_DEBUG);
  798. }
  799. #endif
  800. }
  801. if (test_and_clear_bit(HOST_LOG_PER_PKT_STATS,
  802. &gwlan_logging.eventFlag)) {
  803. ret = pktlog_send_per_pkt_stats_to_user();
  804. if (-ENOMEM == ret)
  805. msleep(200);
  806. }
  807. if (test_and_clear_bit(HOST_LOG_FW_FLUSH_COMPLETE,
  808. &gwlan_logging.eventFlag)) {
  809. /* Flush bit could have been set while we were mid
  810. * way in the logging thread. So, need to check other
  811. * buffers like log messages, per packet stats again
  812. * to flush any residual data in them
  813. */
  814. if (gwlan_logging.is_flush_complete == true) {
  815. gwlan_logging.is_flush_complete = false;
  816. #ifdef FEATURE_WLAN_DIAG_SUPPORT
  817. send_flush_completion_to_user(
  818. RING_ID_DRIVER_DEBUG);
  819. #endif
  820. wlan_logging_set_flush_log_completion();
  821. } else {
  822. gwlan_logging.is_flush_complete = true;
  823. /* Flush all current host logs*/
  824. spin_lock_irqsave(&gwlan_logging.spin_lock,
  825. flags);
  826. wlan_queue_logmsg_for_app();
  827. spin_unlock_irqrestore(&gwlan_logging.spin_lock,
  828. flags);
  829. set_bit(HOST_LOG_DRIVER_MSG,
  830. &gwlan_logging.eventFlag);
  831. set_bit(HOST_LOG_PER_PKT_STATS,
  832. &gwlan_logging.eventFlag);
  833. set_bit(HOST_LOG_FW_FLUSH_COMPLETE,
  834. &gwlan_logging.eventFlag);
  835. wake_up_interruptible(
  836. &gwlan_logging.wait_queue);
  837. }
  838. }
  839. /* Dequeue the connectivity_log */
  840. wlan_logging_send_connectivity_event();
  841. clear_bit(HOST_LOG_DRIVER_CONNECTIVITY_MSG,
  842. &gwlan_logging.eventFlag);
  843. }
  844. gwlan_logging.exit_ts = qdf_get_log_timestamp();
  845. kthread_complete_and_exit(&gwlan_logging.shutdown_comp, 0);
  846. return 0;
  847. }
  848. void wlan_logging_set_active(bool active)
  849. {
  850. gwlan_logging.is_active = active;
  851. }
  852. void wlan_set_console_log_levels(uint32_t console_log_levels)
  853. {
  854. gwlan_logging.console_log_levels = console_log_levels;
  855. }
  856. qdf_export_symbol(wlan_set_console_log_levels);
  857. static void flush_log_buffers_timer(void *dummy)
  858. {
  859. wlan_flush_host_logs_for_fatal();
  860. }
  861. int wlan_logging_set_flush_timer(uint32_t milliseconds)
  862. {
  863. if (milliseconds > MAX_FLUSH_TIMER_PERIOD_VALUE) {
  864. QDF_TRACE_ERROR(QDF_MODULE_ID_QDF,
  865. "ERROR! value should be (0 - %d)\n",
  866. MAX_FLUSH_TIMER_PERIOD_VALUE);
  867. return -EINVAL;
  868. }
  869. if (!gwlan_logging.is_active) {
  870. QDF_TRACE_ERROR(QDF_MODULE_ID_QDF,
  871. "WLAN-Logging not active");
  872. return -EINVAL;
  873. }
  874. qdf_spin_lock(&gwlan_logging.flush_timer_lock);
  875. if (!gwlan_logging.is_flush_timer_initialized) {
  876. qdf_spin_unlock(&gwlan_logging.flush_timer_lock);
  877. return -EINVAL;
  878. }
  879. gwlan_logging.flush_timer_period = milliseconds;
  880. if (milliseconds) {
  881. qdf_timer_mod(&gwlan_logging.flush_timer,
  882. gwlan_logging.flush_timer_period);
  883. }
  884. qdf_spin_unlock(&gwlan_logging.flush_timer_lock);
  885. return 0;
  886. }
  887. static int panic_wifilog_ratelimit_print(void)
  888. {
  889. return __ratelimit(&panic_wifilog_ratelimit);
  890. }
  891. /**
  892. * wlan_logging_dump_last_logs() - Panic notifier callback's helper function
  893. *
  894. * This function prints buffered logs one line at a time.
  895. */
  896. static void wlan_logging_dump_last_logs(void)
  897. {
  898. char *log;
  899. struct log_msg *plog_msg;
  900. char textbuf[MAX_LOG_LINE];
  901. unsigned int filled_length;
  902. unsigned int text_len;
  903. unsigned long flags;
  904. /* Iterate over panic list */
  905. pr_err("\n");
  906. while (!list_empty(&gwlan_logging.panic_list)) {
  907. plog_msg = (struct log_msg *)
  908. (gwlan_logging.panic_list.next);
  909. list_del_init(gwlan_logging.panic_list.next);
  910. log = &plog_msg->logbuf[sizeof(tAniHdr)];
  911. filled_length = plog_msg->filled_length;
  912. while (filled_length) {
  913. text_len = qdf_str_copy_all_before_char(log, filled_length,
  914. textbuf,
  915. sizeof(textbuf) - 1,
  916. '\n');
  917. textbuf[text_len] = '\0';
  918. if (panic_wifilog_ratelimit_print())
  919. pr_err("%s\n", textbuf);
  920. if (log[text_len] == '\n')
  921. text_len += 1; /* skip newline */
  922. log += text_len;
  923. filled_length -= text_len;
  924. }
  925. spin_lock_irqsave(&gwlan_logging.spin_lock, flags);
  926. list_add_tail(&plog_msg->node,
  927. &gwlan_logging.free_list);
  928. spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags);
  929. }
  930. }
  931. /**
  932. * wlan_logging_panic_handler() - Panic notifier callback
  933. *
  934. * This function extracts log buffers in filled list and
  935. * current node.Sends them to helper function for printing.
  936. */
  937. static int wlan_logging_panic_handler(struct notifier_block *this,
  938. unsigned long event, void *ptr)
  939. {
  940. char *log;
  941. struct log_msg *plog_msg;
  942. unsigned long flags;
  943. spin_lock_irqsave(&gwlan_logging.spin_lock, flags);
  944. /* Iterate over nodes queued for app */
  945. while (!list_empty(&gwlan_logging.filled_list)) {
  946. plog_msg = (struct log_msg *)
  947. (gwlan_logging.filled_list.next);
  948. list_del_init(gwlan_logging.filled_list.next);
  949. list_add_tail(&plog_msg->node,
  950. &gwlan_logging.panic_list);
  951. }
  952. /* Check current node */
  953. if (gwlan_logging.pcur_node &&
  954. gwlan_logging.pcur_node->filled_length) {
  955. plog_msg = gwlan_logging.pcur_node;
  956. log = &plog_msg->logbuf[sizeof(tAniHdr)];
  957. log[plog_msg->filled_length] = '\0';
  958. list_add_tail(&gwlan_logging.pcur_node->node,
  959. &gwlan_logging.panic_list);
  960. if (!list_empty(&gwlan_logging.free_list)) {
  961. gwlan_logging.pcur_node =
  962. (struct log_msg *)(gwlan_logging.free_list.next);
  963. list_del_init(gwlan_logging.free_list.next);
  964. gwlan_logging.pcur_node->filled_length = 0;
  965. } else
  966. gwlan_logging.pcur_node = NULL;
  967. }
  968. spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags);
  969. wlan_logging_dump_last_logs();
  970. return NOTIFY_DONE;
  971. }
  972. static struct notifier_block panic_nb = {
  973. .notifier_call = wlan_logging_panic_handler,
  974. };
  975. int wlan_logging_notifier_init(bool dump_at_kernel_enable)
  976. {
  977. int ret;
  978. if (gwlan_logging.is_active &&
  979. !dump_at_kernel_enable) {
  980. ret = atomic_notifier_chain_register(&panic_notifier_list,
  981. &panic_nb);
  982. if (ret) {
  983. QDF_TRACE_ERROR(QDF_MODULE_ID_QDF,
  984. "Failed to register panic notifier");
  985. return -EINVAL;
  986. }
  987. }
  988. return 0;
  989. }
  990. int wlan_logging_notifier_deinit(bool dump_at_kernel_enable)
  991. {
  992. if (gwlan_logging.is_active &&
  993. !dump_at_kernel_enable) {
  994. atomic_notifier_chain_unregister(&panic_notifier_list,
  995. &panic_nb);
  996. }
  997. return 0;
  998. }
  999. static void flush_timer_init(void)
  1000. {
  1001. qdf_spinlock_create(&gwlan_logging.flush_timer_lock);
  1002. qdf_timer_init(NULL, &gwlan_logging.flush_timer,
  1003. flush_log_buffers_timer, NULL,
  1004. QDF_TIMER_TYPE_SW);
  1005. gwlan_logging.is_flush_timer_initialized = true;
  1006. gwlan_logging.flush_timer_period = 0;
  1007. }
  1008. static void flush_timer_deinit(void)
  1009. {
  1010. gwlan_logging.is_flush_timer_initialized = false;
  1011. qdf_spin_lock(&gwlan_logging.flush_timer_lock);
  1012. qdf_timer_stop(&gwlan_logging.flush_timer);
  1013. qdf_timer_free(&gwlan_logging.flush_timer);
  1014. qdf_spin_unlock(&gwlan_logging.flush_timer_lock);
  1015. qdf_spinlock_destroy(&gwlan_logging.flush_timer_lock);
  1016. }
  1017. int wlan_logging_sock_init_svc(void)
  1018. {
  1019. int i = 0, j, pkt_stats_size;
  1020. unsigned long irq_flag;
  1021. QDF_STATUS status;
  1022. spin_lock_init(&gwlan_logging.spin_lock);
  1023. spin_lock_init(&gwlan_logging.pkt_stats_lock);
  1024. gwlan_logging.console_log_levels = 0;
  1025. gwlan_logging.num_buf = MAX_LOGMSG_COUNT;
  1026. gwlan_logging.buffer_length = MAX_LOGMSG_LENGTH;
  1027. if (allocate_log_msg_buffer() != QDF_STATUS_SUCCESS) {
  1028. qdf_err("Could not allocate memory for log_msg");
  1029. return -ENOMEM;
  1030. }
  1031. spin_lock_irqsave(&gwlan_logging.spin_lock, irq_flag);
  1032. INIT_LIST_HEAD(&gwlan_logging.free_list);
  1033. INIT_LIST_HEAD(&gwlan_logging.filled_list);
  1034. INIT_LIST_HEAD(&gwlan_logging.panic_list);
  1035. for (i = 0; i < gwlan_logging.num_buf; i++) {
  1036. list_add(&gplog_msg[i].node, &gwlan_logging.free_list);
  1037. gplog_msg[i].index = i;
  1038. }
  1039. gwlan_logging.pcur_node = (struct log_msg *)
  1040. (gwlan_logging.free_list.next);
  1041. list_del_init(gwlan_logging.free_list.next);
  1042. spin_unlock_irqrestore(&gwlan_logging.spin_lock, irq_flag);
  1043. flush_timer_init();
  1044. /* Initialize the pktStats data structure here */
  1045. pkt_stats_size = sizeof(struct pkt_stats_msg);
  1046. gpkt_stats_buffers = qdf_mem_valloc(MAX_PKTSTATS_BUFF * pkt_stats_size);
  1047. if (!gpkt_stats_buffers) {
  1048. qdf_err("Could not allocate memory for Pkt stats");
  1049. goto err1;
  1050. }
  1051. qdf_mem_zero(gpkt_stats_buffers,
  1052. MAX_PKTSTATS_BUFF * pkt_stats_size);
  1053. spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, irq_flag);
  1054. gwlan_logging.pkt_stats_msg_idx = 0;
  1055. INIT_LIST_HEAD(&gwlan_logging.pkt_stat_free_list);
  1056. INIT_LIST_HEAD(&gwlan_logging.pkt_stat_filled_list);
  1057. spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, irq_flag);
  1058. for (i = 0; i < MAX_PKTSTATS_BUFF; i++) {
  1059. gpkt_stats_buffers[i].skb = dev_alloc_skb(MAX_PKTSTATS_LENGTH);
  1060. if (!gpkt_stats_buffers[i].skb) {
  1061. qdf_err("Memory alloc failed for skb");
  1062. /* free previously allocated skb and return */
  1063. for (j = 0; j < i ; j++)
  1064. dev_kfree_skb(gpkt_stats_buffers[j].skb);
  1065. goto err2;
  1066. }
  1067. spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, irq_flag);
  1068. list_add(&gpkt_stats_buffers[i].node,
  1069. &gwlan_logging.pkt_stat_free_list);
  1070. spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, irq_flag);
  1071. }
  1072. spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, irq_flag);
  1073. gwlan_logging.pkt_stats_pcur_node = (struct pkt_stats_msg *)
  1074. (gwlan_logging.pkt_stat_free_list.next);
  1075. list_del_init(gwlan_logging.pkt_stat_free_list.next);
  1076. spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, irq_flag);
  1077. /* Pkt Stats initialization done */
  1078. init_waitqueue_head(&gwlan_logging.wait_queue);
  1079. gwlan_logging.exit = false;
  1080. clear_bit(HOST_LOG_DRIVER_MSG, &gwlan_logging.eventFlag);
  1081. clear_bit(HOST_LOG_PER_PKT_STATS, &gwlan_logging.eventFlag);
  1082. clear_bit(HOST_LOG_FW_FLUSH_COMPLETE, &gwlan_logging.eventFlag);
  1083. clear_bit(HOST_LOG_DRIVER_CONNECTIVITY_MSG, &gwlan_logging.eventFlag);
  1084. clear_bit(HOST_LOG_CHIPSET_STATS, &gwlan_logging.eventFlag);
  1085. clear_bit(FW_LOG_CHIPSET_STATS, &gwlan_logging.eventFlag);
  1086. init_completion(&gwlan_logging.shutdown_comp);
  1087. gwlan_logging.thread = kthread_create(wlan_logging_thread, NULL,
  1088. "wlan_logging_thread");
  1089. if (IS_ERR(gwlan_logging.thread)) {
  1090. qdf_err("Could not Create LogMsg Thread Controller");
  1091. goto err3;
  1092. }
  1093. wake_up_process(gwlan_logging.thread);
  1094. gwlan_logging.wakup_ts = qdf_get_log_timestamp();
  1095. gwlan_logging.is_active = true;
  1096. gwlan_logging.is_flush_complete = false;
  1097. status = qdf_event_create(&gwlan_logging.flush_log_completion);
  1098. if (!QDF_IS_STATUS_SUCCESS(status)) {
  1099. qdf_err("Flush log completion event init failed");
  1100. goto err3;
  1101. }
  1102. return 0;
  1103. err3:
  1104. for (i = 0; i < MAX_PKTSTATS_BUFF; i++) {
  1105. if (gpkt_stats_buffers[i].skb)
  1106. dev_kfree_skb(gpkt_stats_buffers[i].skb);
  1107. }
  1108. err2:
  1109. spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, irq_flag);
  1110. gwlan_logging.pkt_stats_pcur_node = NULL;
  1111. spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, irq_flag);
  1112. qdf_mem_vfree(gpkt_stats_buffers);
  1113. gpkt_stats_buffers = NULL;
  1114. err1:
  1115. flush_timer_deinit();
  1116. spin_lock_irqsave(&gwlan_logging.spin_lock, irq_flag);
  1117. gwlan_logging.pcur_node = NULL;
  1118. spin_unlock_irqrestore(&gwlan_logging.spin_lock, irq_flag);
  1119. free_log_msg_buffer();
  1120. return -ENOMEM;
  1121. }
  1122. int wlan_logging_sock_deinit_svc(void)
  1123. {
  1124. unsigned long irq_flag;
  1125. int i;
  1126. if (!gwlan_logging.pcur_node)
  1127. return 0;
  1128. qdf_event_destroy(&gwlan_logging.flush_log_completion);
  1129. gwlan_logging.reinitcompletion_ts = qdf_get_log_timestamp();
  1130. INIT_COMPLETION(gwlan_logging.shutdown_comp);
  1131. qdf_wmb();
  1132. gwlan_logging.exit = true;
  1133. qdf_wmb();
  1134. gwlan_logging.set_exit_ts = qdf_get_log_timestamp();
  1135. gwlan_logging.is_active = false;
  1136. #if defined(FEATURE_FW_LOG_PARSING) || defined(FEATURE_WLAN_DIAG_SUPPORT)
  1137. cds_set_multicast_logging(0);
  1138. #endif
  1139. gwlan_logging.is_flush_complete = false;
  1140. clear_bit(HOST_LOG_DRIVER_MSG, &gwlan_logging.eventFlag);
  1141. clear_bit(HOST_LOG_PER_PKT_STATS, &gwlan_logging.eventFlag);
  1142. clear_bit(HOST_LOG_FW_FLUSH_COMPLETE, &gwlan_logging.eventFlag);
  1143. clear_bit(HOST_LOG_DRIVER_CONNECTIVITY_MSG, &gwlan_logging.eventFlag);
  1144. clear_bit(HOST_LOG_CHIPSET_STATS, &gwlan_logging.eventFlag);
  1145. clear_bit(FW_LOG_CHIPSET_STATS, &gwlan_logging.eventFlag);
  1146. wake_up_interruptible(&gwlan_logging.wait_queue);
  1147. wait_for_completion(&gwlan_logging.shutdown_comp);
  1148. spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, irq_flag);
  1149. gwlan_logging.pkt_stats_pcur_node = NULL;
  1150. gwlan_logging.pkt_stats_msg_idx = 0;
  1151. gwlan_logging.pkt_stat_drop_cnt = 0;
  1152. for (i = 0; i < MAX_PKTSTATS_BUFF; i++) {
  1153. if (gpkt_stats_buffers[i].skb)
  1154. dev_kfree_skb(gpkt_stats_buffers[i].skb);
  1155. }
  1156. spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, irq_flag);
  1157. qdf_mem_vfree(gpkt_stats_buffers);
  1158. gpkt_stats_buffers = NULL;
  1159. /* Delete the Flush timer then mark pcur_node NULL */
  1160. flush_timer_deinit();
  1161. spin_lock_irqsave(&gwlan_logging.spin_lock, irq_flag);
  1162. gwlan_logging.pcur_node = NULL;
  1163. spin_unlock_irqrestore(&gwlan_logging.spin_lock, irq_flag);
  1164. free_log_msg_buffer();
  1165. return 0;
  1166. }
  1167. /**
  1168. * wlan_logging_set_per_pkt_stats() - This function triggers per packet logging
  1169. *
  1170. * This function is used to send signal to the logger thread for logging per
  1171. * packet stats
  1172. *
  1173. * Return: None
  1174. *
  1175. */
  1176. void wlan_logging_set_per_pkt_stats(void)
  1177. {
  1178. if (gwlan_logging.is_active == false)
  1179. return;
  1180. set_bit(HOST_LOG_PER_PKT_STATS, &gwlan_logging.eventFlag);
  1181. wake_up_interruptible(&gwlan_logging.wait_queue);
  1182. }
  1183. void wlan_logging_set_connectivity_log(void)
  1184. {
  1185. if (gwlan_logging.is_active == false)
  1186. return;
  1187. set_bit(HOST_LOG_DRIVER_CONNECTIVITY_MSG, &gwlan_logging.eventFlag);
  1188. wake_up_interruptible(&gwlan_logging.wait_queue);
  1189. }
  1190. /*
  1191. * wlan_logging_set_fw_flush_complete() - FW log flush completion
  1192. *
  1193. * This function is used to send signal to the logger thread to indicate
  1194. * that the flushing of FW logs is complete by the FW
  1195. *
  1196. * Return: None
  1197. *
  1198. */
  1199. void wlan_logging_set_fw_flush_complete(void)
  1200. {
  1201. if (!gwlan_logging.is_active)
  1202. return;
  1203. set_bit(HOST_LOG_FW_FLUSH_COMPLETE, &gwlan_logging.eventFlag);
  1204. wake_up_interruptible(&gwlan_logging.wait_queue);
  1205. }
  1206. /**
  1207. * wlan_flush_host_logs_for_fatal() - Flush host logs
  1208. *
  1209. * This function is used to send signal to the logger thread to
  1210. * Flush the host logs
  1211. *
  1212. * Return: None
  1213. */
  1214. void wlan_flush_host_logs_for_fatal(void)
  1215. {
  1216. unsigned long flags;
  1217. if (gwlan_logging.flush_timer_period == 0)
  1218. qdf_info("Flush all host logs Setting HOST_LOG_POST_MAS");
  1219. spin_lock_irqsave(&gwlan_logging.spin_lock, flags);
  1220. wlan_queue_logmsg_for_app();
  1221. spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags);
  1222. set_bit(HOST_LOG_DRIVER_MSG, &gwlan_logging.eventFlag);
  1223. wake_up_interruptible(&gwlan_logging.wait_queue);
  1224. }
  1225. #ifdef CONNECTIVITY_PKTLOG
  1226. static uint8_t gtx_count;
  1227. static uint8_t grx_count;
  1228. /**
  1229. * wlan_get_pkt_stats_free_node() - Get the free node for pkt stats
  1230. *
  1231. * This function is used to get the free node for pkt stats from
  1232. * free list/filled list
  1233. *
  1234. * Return: int
  1235. *
  1236. */
  1237. static int wlan_get_pkt_stats_free_node(void)
  1238. {
  1239. int ret = 0;
  1240. list_add_tail(&gwlan_logging.pkt_stats_pcur_node->node,
  1241. &gwlan_logging.pkt_stat_filled_list);
  1242. if (!list_empty(&gwlan_logging.pkt_stat_free_list)) {
  1243. /* Get buffer from free list */
  1244. gwlan_logging.pkt_stats_pcur_node =
  1245. (struct pkt_stats_msg *)(gwlan_logging.pkt_stat_free_list.next);
  1246. list_del_init(gwlan_logging.pkt_stat_free_list.next);
  1247. } else if (!list_empty(&gwlan_logging.pkt_stat_filled_list)) {
  1248. /* Get buffer from filled list. This condition will drop the
  1249. * packet from being indicated to app
  1250. */
  1251. gwlan_logging.pkt_stats_pcur_node =
  1252. (struct pkt_stats_msg *)
  1253. (gwlan_logging.pkt_stat_filled_list.next);
  1254. ++gwlan_logging.pkt_stat_drop_cnt;
  1255. /* print every 64th drop count */
  1256. if (
  1257. cds_is_multicast_logging() &&
  1258. (!(gwlan_logging.pkt_stat_drop_cnt % 0x40))) {
  1259. qdf_err("drop_count = %u",
  1260. gwlan_logging.pkt_stat_drop_cnt);
  1261. }
  1262. list_del_init(gwlan_logging.pkt_stat_filled_list.next);
  1263. ret = 1;
  1264. }
  1265. /* Reset the skb values, essential if dequeued from filled list */
  1266. skb_trim(gwlan_logging.pkt_stats_pcur_node->skb, 0);
  1267. return ret;
  1268. }
  1269. /**
  1270. * wlan_pkt_stats_to_logger_thread() - Add the pkt stats to SKB
  1271. * @pl_hdr: Pointer to pl_hdr
  1272. * @pkt_dump: Pointer to pkt_dump
  1273. * @data: Pointer to data
  1274. *
  1275. * This function adds the pktstats hdr and data to current
  1276. * skb node of free list.
  1277. *
  1278. * Return: None
  1279. */
  1280. void wlan_pkt_stats_to_logger_thread(void *pl_hdr, void *pkt_dump, void *data)
  1281. {
  1282. struct ath_pktlog_hdr *pktlog_hdr;
  1283. struct packet_dump *pkt_stats_dump;
  1284. int total_stats_len = 0;
  1285. bool wake_up_thread = false;
  1286. unsigned long flags;
  1287. struct sk_buff *ptr;
  1288. int hdr_size;
  1289. pktlog_hdr = (struct ath_pktlog_hdr *)pl_hdr;
  1290. if (!pktlog_hdr) {
  1291. qdf_err("Invalid pkt_stats_header");
  1292. return;
  1293. }
  1294. pkt_stats_dump = (struct packet_dump *)pkt_dump;
  1295. total_stats_len = sizeof(struct ath_pktlog_hdr) +
  1296. pktlog_hdr->size;
  1297. spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, flags);
  1298. if (!gwlan_logging.pkt_stats_pcur_node) {
  1299. spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, flags);
  1300. return;
  1301. }
  1302. /* Check if we can accommodate more log into current node/buffer */
  1303. hdr_size = sizeof(struct host_log_pktlog_info) +
  1304. sizeof(tAniNlHdr);
  1305. if ((total_stats_len + hdr_size) >=
  1306. skb_tailroom(gwlan_logging.pkt_stats_pcur_node->skb)) {
  1307. wake_up_thread = true;
  1308. wlan_get_pkt_stats_free_node();
  1309. }
  1310. ptr = gwlan_logging.pkt_stats_pcur_node->skb;
  1311. qdf_mem_copy(skb_put(ptr,
  1312. sizeof(struct ath_pktlog_hdr)),
  1313. pktlog_hdr,
  1314. sizeof(struct ath_pktlog_hdr));
  1315. if (pkt_stats_dump) {
  1316. qdf_mem_copy(skb_put(ptr,
  1317. sizeof(struct packet_dump)),
  1318. pkt_stats_dump,
  1319. sizeof(struct packet_dump));
  1320. pktlog_hdr->size -= sizeof(struct packet_dump);
  1321. }
  1322. if (data)
  1323. qdf_mem_copy(skb_put(ptr,
  1324. pktlog_hdr->size),
  1325. data, pktlog_hdr->size);
  1326. if (pkt_stats_dump && pkt_stats_dump->type == STOP_MONITOR) {
  1327. wake_up_thread = true;
  1328. wlan_get_pkt_stats_free_node();
  1329. }
  1330. spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, flags);
  1331. /* Wakeup logger thread */
  1332. if (true == wake_up_thread) {
  1333. set_bit(HOST_LOG_PER_PKT_STATS, &gwlan_logging.eventFlag);
  1334. wake_up_interruptible(&gwlan_logging.wait_queue);
  1335. }
  1336. }
  1337. /**
  1338. * qdf_hal_tx_status_map() - map Tx completion status with
  1339. * packet dump Tx status
  1340. * @status: Tx completion status
  1341. *
  1342. * Return: packet dump tx_status enum
  1343. */
  1344. static inline enum tx_pkt_fate
  1345. qdf_hal_tx_status_map(enum qdf_dp_tx_rx_status status)
  1346. {
  1347. switch (status) {
  1348. case QDF_TX_RX_STATUS_OK:
  1349. return TX_PKT_FATE_ACKED;
  1350. case QDF_TX_RX_STATUS_FW_DISCARD:
  1351. return TX_PKT_FATE_FW_DROP_OTHER;
  1352. case QDF_TX_RX_STATUS_NO_ACK:
  1353. return TX_PKT_FATE_SENT;
  1354. case QDF_TX_RX_STATUS_DROP:
  1355. return TX_PKT_FATE_DRV_DROP_OTHER;
  1356. case QDF_TX_RX_STATUS_DOWNLOAD_SUCC:
  1357. return TX_PKT_FATE_DRV_QUEUED;
  1358. default:
  1359. return TX_PKT_FATE_DRV_DROP_OTHER;
  1360. }
  1361. }
  1362. /**
  1363. * qdf_hal_rx_status_map() - map Rx status with
  1364. * packet dump Rx status
  1365. * @status: Rx status
  1366. *
  1367. * Return: packet dump rx_status enum
  1368. */
  1369. static inline enum rx_pkt_fate
  1370. qdf_hal_rx_status_map(enum qdf_dp_tx_rx_status status)
  1371. {
  1372. switch (status) {
  1373. case QDF_TX_RX_STATUS_OK:
  1374. return RX_PKT_FATE_SUCCESS;
  1375. case QDF_TX_RX_STATUS_FW_DISCARD:
  1376. return RX_PKT_FATE_FW_DROP_OTHER;
  1377. case QDF_TX_RX_STATUS_DROP:
  1378. return RX_PKT_FATE_DRV_DROP_OTHER;
  1379. case QDF_TX_RX_STATUS_DOWNLOAD_SUCC:
  1380. return RX_PKT_FATE_DRV_QUEUED;
  1381. default:
  1382. return RX_PKT_FATE_DRV_DROP_OTHER;
  1383. }
  1384. }
  1385. /**
  1386. * qdf_hal_pkt_type_map() - map qdf packet type with
  1387. * packet dump packet type
  1388. * @type: packet type
  1389. *
  1390. * Return: Packet dump packet type
  1391. */
  1392. static inline enum pkt_type
  1393. qdf_hal_pkt_type_map(enum qdf_pkt_type type)
  1394. {
  1395. switch (type) {
  1396. case QDF_TX_MGMT_PKT:
  1397. return TX_MGMT_PKT;
  1398. case QDF_TX_DATA_PKT:
  1399. return TX_DATA_PKT;
  1400. case QDF_RX_MGMT_PKT:
  1401. return RX_MGMT_PKT;
  1402. case QDF_RX_DATA_PKT:
  1403. return RX_DATA_PKT;
  1404. default:
  1405. return INVALID_PKT;
  1406. }
  1407. }
  1408. /*
  1409. * send_packetdump() - send packet dump
  1410. * @soc: soc handle
  1411. * @vdev_id: ID of the virtual device handle
  1412. * @netbuf: netbuf
  1413. * @status: status of tx packet
  1414. * @type: type of packet
  1415. *
  1416. * This function is used to send packet dump to HAL layer
  1417. * using wlan_pkt_stats_to_logger_thread
  1418. *
  1419. * Return: None
  1420. *
  1421. */
  1422. static void send_packetdump(ol_txrx_soc_handle soc,
  1423. uint8_t vdev_id, qdf_nbuf_t netbuf,
  1424. uint8_t status, uint8_t type)
  1425. {
  1426. struct ath_pktlog_hdr pktlog_hdr = {0};
  1427. struct packet_dump pd_hdr = {0};
  1428. if (!netbuf) {
  1429. qdf_err("Invalid netbuf");
  1430. return;
  1431. }
  1432. /* Send packet dump only for STA interface */
  1433. if (wlan_op_mode_sta != cdp_get_opmode(soc, vdev_id))
  1434. return;
  1435. pktlog_hdr.flags |= PKTLOG_HDR_SIZE_16;
  1436. pktlog_hdr.log_type = PKTLOG_TYPE_PKT_DUMP;
  1437. pktlog_hdr.size = sizeof(pd_hdr) + netbuf->len;
  1438. pd_hdr.status = status;
  1439. pd_hdr.type = type;
  1440. pd_hdr.driver_ts = qdf_get_monotonic_boottime();
  1441. if ((type == TX_MGMT_PKT) || (type == TX_DATA_PKT))
  1442. gtx_count++;
  1443. else if ((type == RX_MGMT_PKT) || (type == RX_DATA_PKT))
  1444. grx_count++;
  1445. wlan_pkt_stats_to_logger_thread(&pktlog_hdr, &pd_hdr, netbuf->data);
  1446. }
  1447. /*
  1448. * send_packetdump_monitor() - sends start/stop packet dump indication
  1449. * @type: type of packet
  1450. *
  1451. * This function is used to indicate HAL layer to start/stop monitoring
  1452. * of packets
  1453. *
  1454. * Return: None
  1455. *
  1456. */
  1457. static void send_packetdump_monitor(uint8_t type)
  1458. {
  1459. struct ath_pktlog_hdr pktlog_hdr = {0};
  1460. struct packet_dump pd_hdr = {0};
  1461. pktlog_hdr.flags |= PKTLOG_HDR_SIZE_16;
  1462. pktlog_hdr.log_type = PKTLOG_TYPE_PKT_DUMP;
  1463. pktlog_hdr.size = sizeof(pd_hdr);
  1464. pd_hdr.type = type;
  1465. LOGGING_TRACE(QDF_TRACE_LEVEL_DEBUG,
  1466. "fate Tx-Rx %s: type: %d", __func__, type);
  1467. wlan_pkt_stats_to_logger_thread(&pktlog_hdr, &pd_hdr, NULL);
  1468. }
  1469. void wlan_deregister_txrx_packetdump(uint8_t pdev_id)
  1470. {
  1471. void *soc = cds_get_context(QDF_MODULE_ID_SOC);
  1472. if (!soc)
  1473. return;
  1474. if (gtx_count || grx_count) {
  1475. cdp_deregister_packetdump_cb(soc, pdev_id);
  1476. wma_deregister_packetdump_callback();
  1477. send_packetdump_monitor(STOP_MONITOR);
  1478. csr_packetdump_timer_stop();
  1479. gtx_count = 0;
  1480. grx_count = 0;
  1481. } else
  1482. LOGGING_TRACE(QDF_TRACE_LEVEL_DEBUG,
  1483. "%s: deregistered packetdump already", __func__);
  1484. }
  1485. /*
  1486. * check_txrx_packetdump_count() - function to check
  1487. * tx/rx packet dump global counts
  1488. * @pdev_id: datapath pdev identifier
  1489. *
  1490. * This function is used to check global counts of tx/rx
  1491. * packet dump functionality.
  1492. *
  1493. * Return: 1 if either gtx_count or grx_count reached 32
  1494. * 0 otherwise
  1495. *
  1496. */
  1497. static bool check_txrx_packetdump_count(uint8_t pdev_id)
  1498. {
  1499. if (gtx_count == MAX_NUM_PKT_LOG ||
  1500. grx_count == MAX_NUM_PKT_LOG) {
  1501. LOGGING_TRACE(QDF_TRACE_LEVEL_DEBUG,
  1502. "%s gtx_count: %d grx_count: %d deregister packetdump",
  1503. __func__, gtx_count, grx_count);
  1504. wlan_deregister_txrx_packetdump(pdev_id);
  1505. return 1;
  1506. }
  1507. return 0;
  1508. }
  1509. /*
  1510. * tx_packetdump_cb() - tx packet dump callback
  1511. * @soc: soc handle
  1512. * @pdev_id: datapath pdev id
  1513. * @vdev_id: vdev id
  1514. * @netbuf: netbuf
  1515. * @status: status of tx packet
  1516. * @type: packet type
  1517. *
  1518. * This function is used to send tx packet dump to HAL layer
  1519. * and deregister packet dump callbacks
  1520. *
  1521. * Return: None
  1522. *
  1523. */
  1524. static void tx_packetdump_cb(ol_txrx_soc_handle soc,
  1525. uint8_t pdev_id, uint8_t vdev_id,
  1526. qdf_nbuf_t netbuf,
  1527. enum qdf_dp_tx_rx_status status,
  1528. enum qdf_pkt_type type)
  1529. {
  1530. bool temp;
  1531. enum tx_pkt_fate tx_status = qdf_hal_tx_status_map(status);
  1532. enum pkt_type pkt_type = qdf_hal_pkt_type_map(type);
  1533. if (!soc)
  1534. return;
  1535. temp = check_txrx_packetdump_count(pdev_id);
  1536. if (temp)
  1537. return;
  1538. send_packetdump(soc, vdev_id, netbuf, tx_status, pkt_type);
  1539. }
  1540. /*
  1541. * rx_packetdump_cb() - rx packet dump callback
  1542. * @soc: soc handle
  1543. * @pdev_id: datapath pdev id
  1544. * @vdev_id: vdev id
  1545. * @netbuf: netbuf
  1546. * @status: status of rx packet
  1547. * @type: packet type
  1548. *
  1549. * This function is used to send rx packet dump to HAL layer
  1550. * and deregister packet dump callbacks
  1551. *
  1552. * Return: None
  1553. *
  1554. */
  1555. static void rx_packetdump_cb(ol_txrx_soc_handle soc,
  1556. uint8_t pdev_id, uint8_t vdev_id,
  1557. qdf_nbuf_t netbuf,
  1558. enum qdf_dp_tx_rx_status status,
  1559. enum qdf_pkt_type type)
  1560. {
  1561. bool temp;
  1562. enum rx_pkt_fate rx_status = qdf_hal_rx_status_map(status);
  1563. enum pkt_type pkt_type = qdf_hal_pkt_type_map(type);
  1564. if (!soc)
  1565. return;
  1566. temp = check_txrx_packetdump_count(pdev_id);
  1567. if (temp)
  1568. return;
  1569. send_packetdump(soc, vdev_id, netbuf, rx_status, pkt_type);
  1570. }
  1571. void wlan_register_txrx_packetdump(uint8_t pdev_id)
  1572. {
  1573. void *soc = cds_get_context(QDF_MODULE_ID_SOC);
  1574. if (!soc)
  1575. return;
  1576. cdp_register_packetdump_cb(soc, pdev_id,
  1577. tx_packetdump_cb, rx_packetdump_cb);
  1578. wma_register_packetdump_callback(tx_packetdump_cb,
  1579. rx_packetdump_cb);
  1580. send_packetdump_monitor(START_MONITOR);
  1581. gtx_count = 0;
  1582. grx_count = 0;
  1583. csr_packetdump_timer_start();
  1584. }
  1585. #endif /* CONNECTIVITY_PKTLOG */
  1586. #ifdef WLAN_CHIPSET_STATS
  1587. void wlan_set_chipset_stats_bit(void)
  1588. {
  1589. set_bit(HOST_LOG_CHIPSET_STATS, &gwlan_logging.eventFlag);
  1590. set_bit(FW_LOG_CHIPSET_STATS, &gwlan_logging.eventFlag);
  1591. }
  1592. #endif /* WLAN_CHIPSET_STATS */
  1593. #endif /* WLAN_LOGGING_SOCK_SVC_ENABLE */