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