blob: ed10cfd489ba59297e5b36a3fa5606730bac41b1 [file] [log] [blame]
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301/*
Siddharth Bhal7bd19932015-03-03 16:54:36 +05302* Copyright (c) 2014-2015 The Linux Foundation. All rights reserved.
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05303*
4* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5*
6*
7* Permission to use, copy, modify, and/or distribute this software for
8* any purpose with or without fee is hereby granted, provided that the
9* above copyright notice and this permission notice appear in all
10* copies.
11*
12* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19* PERFORMANCE OF THIS SOFTWARE.
20*/
21
22/*
23* This file was originally distributed by Qualcomm Atheros, Inc.
24* under proprietary terms before Copyright ownership was assigned
25* to the Linux Foundation.
26*/
27
28/******************************************************************************
29 * wlan_logging_sock_svc.c
30 *
31 ******************************************************************************/
32#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
Vinay Krishna Eranna2c0ac302014-12-17 15:21:40 +053033#include <linux/rtc.h>
Vinay Krishna Eranna0b112622014-04-21 20:17:57 +053034#include <vmalloc.h>
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053035#include <wlan_nlink_srv.h>
36#include <vos_status.h>
37#include <vos_trace.h>
38#include <wlan_nlink_common.h>
39#include <wlan_logging_sock_svc.h>
40#include <vos_types.h>
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053041#include <kthread.h>
Rajesh Babu Prathipati71e9c442014-07-01 22:08:29 +053042#include "vos_memory.h"
Sushant Kaushik1ede3322015-07-07 17:26:50 +053043#include <linux/ratelimit.h>
Ratnam Rachuric798dbe2015-07-17 11:19:44 +053044#include <asm/arch_timer.h>
Abhishek Singh880d7122015-08-26 16:23:04 +053045#include <vos_sched.h>
Sushant Kaushik33200572015-08-05 16:46:20 +053046#include <vos_utils.h>
47
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053048
49#define LOGGING_TRACE(level, args...) \
Siddharth Bhal7bd19932015-03-03 16:54:36 +053050 VOS_TRACE(VOS_MODULE_ID_SVC, level, ## args)
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053051
52/* Global variables */
53
54#define ANI_NL_MSG_LOG_TYPE 89
Vinay Krishna Eranna8382e0e2014-06-18 19:19:58 +053055#define ANI_NL_MSG_READY_IND_TYPE 90
Siddharth Bhal7bd19932015-03-03 16:54:36 +053056#define ANI_NL_MSG_LOG_PKT_TYPE 91
Siddharth Bhalec0b72c2015-05-12 21:35:54 +053057#define ANI_NL_MSG_FW_LOG_PKT_TYPE 92
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053058#define INVALID_PID -1
59
Sushant Kaushik33200572015-08-05 16:46:20 +053060#define MAX_PKTSTATS_LOG_LENGTH 2048
61#define HOST_PKT_STATS_POST_MASK 0x004
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053062#define MAX_LOGMSG_LENGTH 4096
Siddharth Bhalec0b72c2015-05-12 21:35:54 +053063#define LOGGER_MGMT_DATA_PKT_POST_MASK 0x001
Siddharth Bhal7bd19932015-03-03 16:54:36 +053064#define HOST_LOG_POST_MASK 0x002
Siddharth Bhalec0b72c2015-05-12 21:35:54 +053065#define LOGGER_FW_LOG_PKT_POST_MASK 0x003
Sachin Ahuja715aafc2015-07-21 23:35:10 +053066#define LOGGER_FATAL_EVENT_POST_MASK 0x004
c_manjeecfd1efb2015-09-25 19:32:34 +053067#define LOGGER_FW_MEM_DUMP_PKT_POST_MASK 0x005
68#define LOGGER_FW_MEM_DUMP_PKT_POST_DONE_MASK 0x006
69
Siddharth Bhal7bd19932015-03-03 16:54:36 +053070
Siddharth Bhalec0b72c2015-05-12 21:35:54 +053071#define LOGGER_MAX_DATA_MGMT_PKT_Q_LEN (8)
72#define LOGGER_MAX_FW_LOG_PKT_Q_LEN (16)
c_manjeecfd1efb2015-09-25 19:32:34 +053073#define LOGGER_MAX_FW_MEM_DUMP_PKT_Q_LEN (32)
74
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053075
Sushant Kaushik1ede3322015-07-07 17:26:50 +053076#define NL_BDCAST_RATELIMIT_INTERVAL (5*HZ)
Sushant Kaushik8ddaa382015-06-23 12:17:25 +053077#define NL_BDCAST_RATELIMIT_BURST 1
Sushant Kaushik33200572015-08-05 16:46:20 +053078#define PTT_MSG_DIAG_CMDS_TYPE 0x5050
79#define DIAG_TYPE_LOGS 1
80
Sushant Kaushik8ddaa382015-06-23 12:17:25 +053081
Ratnam Rachuric798dbe2015-07-17 11:19:44 +053082/* Qtimer Frequency */
83#define QTIMER_FREQ 19200000
84
Sushant Kaushik8ddaa382015-06-23 12:17:25 +053085static DEFINE_RATELIMIT_STATE(errCnt, \
86 NL_BDCAST_RATELIMIT_INTERVAL, \
87 NL_BDCAST_RATELIMIT_BURST);
Abhishek Singh880d7122015-08-26 16:23:04 +053088/* Timer value for detecting thread stuck issues */
89#define THREAD_STUCK_TIMER_VAL 5000 // 5 seconds
90#define THREAD_STUCK_COUNT 3
Sushant Kaushik8ddaa382015-06-23 12:17:25 +053091
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053092struct log_msg {
93 struct list_head node;
94 unsigned int radio;
95 unsigned int index;
96 /* indicates the current filled log length in logbuf */
97 unsigned int filled_length;
98 /*
99 * Buf to hold the log msg
100 * tAniHdr + log
101 */
102 char logbuf[MAX_LOGMSG_LENGTH];
103};
104
Sachin Ahuja715aafc2015-07-21 23:35:10 +0530105struct logger_log_complete {
106 uint32_t is_fatal;
107 uint32_t indicator;
108 uint32_t reason_code;
109 bool is_report_in_progress;
110 bool is_flush_complete;
111};
112
c_manjeecfd1efb2015-09-25 19:32:34 +0530113struct fw_mem_dump_logging{
114 //It will hold the starting point of mem dump buffer
115 uint8 *fw_dump_start_loc;
116 //It will hold the current loc to tell how much data filled
117 uint8 *fw_dump_current_loc;
118 uint32 fw_dump_max_size;
119 vos_pkt_t *fw_mem_dump_queue;
120 /* Holds number of pkts in fw log vos pkt queue */
121 unsigned int fw_mem_dump_pkt_qcnt;
122 /* Number of dropped pkts for fw dump */
123 unsigned int fw_mem_dump_pkt_drop_cnt;
124 /* Lock to synchronize of queue/dequeue of pkts in fw log pkt queue */
125 spinlock_t fw_mem_dump_lock;
126 /* Fw memory dump state */
127 enum FW_MEM_DUMP_STATE fw_mem_dump_status;
128 /* Completion variable for handling SSR/unload during copy_to_user */
129 struct completion fw_mem_copy_to_user_completion;
130};
131
Sushant Kaushik33200572015-08-05 16:46:20 +0530132struct pkt_stats_msg {
133 struct list_head node;
134 /* indicates the current filled log length in pktlogbuf */
135 struct sk_buff *skb;
136};
137
138struct perPktStatsInfo{
139 v_U32_t lastTxRate; // 802.11 data rate at which the last data frame is transmitted.
140 v_U8_t txAvgRetry; // Average number of retries per 10 packets.
141 v_S7_t avgRssi; // Average of the Beacon RSSI.
142};
c_manjeecfd1efb2015-09-25 19:32:34 +0530143
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530144struct wlan_logging {
145 /* Log Fatal and ERROR to console */
146 bool log_fe_to_console;
147 /* Number of buffers to be used for logging */
148 int num_buf;
149 /* Lock to synchronize access to shared logging resource */
150 spinlock_t spin_lock;
151 /* Holds the free node which can be used for filling logs */
152 struct list_head free_list;
153 /* Holds the filled nodes which needs to be indicated to APP */
154 struct list_head filled_list;
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530155 /* Points to head of logger pkt queue */
156 vos_pkt_t *data_mgmt_pkt_queue;
157 /* Holds number of pkts in vos pkt queue */
158 unsigned int data_mgmt_pkt_qcnt;
159 /* Lock to synchronize of queue/dequeue of pkts in logger pkt queue */
160 spinlock_t data_mgmt_pkt_lock;
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530161 /* Points to head of logger fw log pkt queue */
162 vos_pkt_t *fw_log_pkt_queue;
163 /* Holds number of pkts in fw log vos pkt queue */
164 unsigned int fw_log_pkt_qcnt;
165 /* Lock to synchronize of queue/dequeue of pkts in fw log pkt queue */
166 spinlock_t fw_log_pkt_lock;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530167 /* Wait queue for Logger thread */
168 wait_queue_head_t wait_queue;
169 /* Logger thread */
170 struct task_struct *thread;
171 /* Logging thread sets this variable on exit */
172 struct completion shutdown_comp;
173 /* Indicates to logger thread to exit */
174 bool exit;
175 /* Holds number of dropped logs*/
176 unsigned int drop_count;
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530177 /* Holds number of dropped vos pkts*/
178 unsigned int pkt_drop_cnt;
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530179 /* Holds number of dropped fw log vos pkts*/
180 unsigned int fw_log_pkt_drop_cnt;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530181 /* current logbuf to which the log will be filled to */
182 struct log_msg *pcur_node;
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530183 /* Event flag used for wakeup and post indication*/
184 unsigned long event_flag;
Abhishek Singh880d7122015-08-26 16:23:04 +0530185 /* Timer to detect thread stuck issue */
186 vos_timer_t threadStuckTimer;
187 /* Count for each thread to determine thread stuck */
188 unsigned int mcThreadStuckCount;
189 unsigned int txThreadStuckCount;
190 unsigned int rxThreadStuckCount;
191 /* lock to synchronize access to the thread stuck counts */
192 spinlock_t thread_stuck_lock;
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530193 /* Indicates logger thread is activated */
194 bool is_active;
Sachin Ahuja715aafc2015-07-21 23:35:10 +0530195 /* data structure for log complete event*/
196 struct logger_log_complete log_complete;
197 spinlock_t bug_report_lock;
c_manjeecfd1efb2015-09-25 19:32:34 +0530198 struct fw_mem_dump_logging fw_mem_dump_ctx;
Sushant Kaushik33200572015-08-05 16:46:20 +0530199 int pkt_stat_num_buf;
200 unsigned int pkt_stat_drop_cnt;
201 struct list_head pkt_stat_free_list;
202 struct list_head pkt_stat_filled_list;
203 struct pkt_stats_msg *pkt_stats_pcur_node;
204 /* Index of the messages sent to userspace */
205 unsigned int pkt_stats_msg_idx;
206 bool pkt_stats_enabled;
207 spinlock_t pkt_stats_lock;
208 struct perPktStatsInfo txPktStatsInfo;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530209};
210
211static struct wlan_logging gwlan_logging;
212static struct log_msg *gplog_msg;
Sushant Kaushik33200572015-08-05 16:46:20 +0530213static struct pkt_stats_msg *pkt_stats_buffers;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530214
215/* PID of the APP to log the message */
216static int gapp_pid = INVALID_PID;
Sushant Kaushik9cb1c9c2015-06-23 11:57:10 +0530217static char wlan_logging_ready[] = "WLAN LOGGING READY";
218
219/*
220 * Broadcast Logging service ready indication to any Logging application
221 * Each netlink message will have a message of type tAniMsgHdr inside.
222 */
223void wlan_logging_srv_nl_ready_indication(void)
224{
225 struct sk_buff *skb = NULL;
226 struct nlmsghdr *nlh;
227 tAniNlHdr *wnl = NULL;
228 int payload_len;
229 int err;
230 static int rate_limit;
231
232 payload_len = sizeof(tAniHdr) + sizeof(wlan_logging_ready) +
233 sizeof(wnl->radio);
234 skb = dev_alloc_skb(NLMSG_SPACE(payload_len));
235 if (NULL == skb) {
236 if (!rate_limit) {
237 LOGGING_TRACE(VOS_TRACE_LEVEL_ERROR,
238 "NLINK: skb alloc fail %s", __func__);
239 }
240 rate_limit = 1;
241 return;
242 }
243 rate_limit = 0;
244
245 nlh = nlmsg_put(skb, 0, 0, ANI_NL_MSG_LOG, payload_len,
246 NLM_F_REQUEST);
247 if (NULL == nlh) {
248 LOGGING_TRACE(VOS_TRACE_LEVEL_ERROR,
249 "%s: nlmsg_put() failed for msg size[%d]",
250 __func__, payload_len);
251 kfree_skb(skb);
252 return;
253 }
254
255 wnl = (tAniNlHdr *) nlh;
256 wnl->radio = 0;
257 wnl->wmsg.type = ANI_NL_MSG_READY_IND_TYPE;
258 wnl->wmsg.length = sizeof(wlan_logging_ready);
259 memcpy((char*)&wnl->wmsg + sizeof(tAniHdr),
260 wlan_logging_ready,
261 sizeof(wlan_logging_ready));
262
263 /* sender is in group 1<<0 */
264 NETLINK_CB(skb).dst_group = WLAN_NLINK_MCAST_GRP_ID;
265
266 /*multicast the message to all listening processes*/
267 err = nl_srv_bcast(skb);
268 if (err) {
269 LOGGING_TRACE(VOS_TRACE_LEVEL_INFO_LOW,
270 "NLINK: Ready Indication Send Fail %s, err %d",
271 __func__, err);
272 }
273 return;
274}
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530275
276/* Utility function to send a netlink message to an application
277 * in user space
278 */
279static int wlan_send_sock_msg_to_app(tAniHdr *wmsg, int radio,
280 int src_mod, int pid)
281{
282 int err = -1;
283 int payload_len;
284 int tot_msg_len;
285 tAniNlHdr *wnl = NULL;
286 struct sk_buff *skb;
287 struct nlmsghdr *nlh;
Vinay Krishna Erannab4c6a422015-03-20 18:33:47 +0530288 int wmsg_length = wmsg->length;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530289 static int nlmsg_seq;
290
291 if (radio < 0 || radio > ANI_MAX_RADIOS) {
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530292 pr_err("%s: invalid radio id [%d]",
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530293 __func__, radio);
294 return -EINVAL;
295 }
296
297 payload_len = wmsg_length + sizeof(wnl->radio);
298 tot_msg_len = NLMSG_SPACE(payload_len);
299 skb = dev_alloc_skb(tot_msg_len);
300 if (skb == NULL) {
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530301 pr_err("%s: dev_alloc_skb() failed for msg size[%d]",
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530302 __func__, tot_msg_len);
303 return -ENOMEM;
304 }
305 nlh = nlmsg_put(skb, pid, nlmsg_seq++, src_mod, payload_len,
306 NLM_F_REQUEST);
307 if (NULL == nlh) {
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530308 pr_err("%s: nlmsg_put() failed for msg size[%d]",
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530309 __func__, tot_msg_len);
310 kfree_skb(skb);
311 return -ENOMEM;
312 }
313
314 wnl = (tAniNlHdr *) nlh;
315 wnl->radio = radio;
Rajesh Babu Prathipati71e9c442014-07-01 22:08:29 +0530316 vos_mem_copy(&wnl->wmsg, wmsg, wmsg_length);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530317
318 err = nl_srv_ucast(skb, pid, MSG_DONTWAIT);
Vinay Krishna Eranna8147e702015-03-06 17:43:41 +0530319
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530320 return err;
321}
322
323static void set_default_logtoapp_log_level(void)
324{
325 vos_trace_setValue(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_ALL, VOS_TRUE);
326 vos_trace_setValue(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ALL, VOS_TRUE);
327 vos_trace_setValue(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ALL, VOS_TRUE);
328 vos_trace_setValue(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ALL, VOS_TRUE);
329 vos_trace_setValue(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ALL, VOS_TRUE);
330 vos_trace_setValue(VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ALL,
331 VOS_TRUE);
332 vos_trace_setValue(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ALL, VOS_TRUE);
Kaushik, Sushantac4fa6c2014-12-10 17:07:41 +0530333 vos_trace_setValue(VOS_MODULE_ID_PMC, VOS_TRACE_LEVEL_ALL, VOS_TRUE);
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530334 vos_trace_setValue(VOS_MODULE_ID_SVC, VOS_TRACE_LEVEL_ALL, VOS_TRUE);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530335}
336
337static void clear_default_logtoapp_log_level(void)
338{
339 int module;
340
341 for (module = 0; module < VOS_MODULE_ID_MAX; module++) {
342 vos_trace_setValue(module, VOS_TRACE_LEVEL_NONE,
343 VOS_FALSE);
344 vos_trace_setValue(module, VOS_TRACE_LEVEL_FATAL,
345 VOS_TRUE);
346 vos_trace_setValue(module, VOS_TRACE_LEVEL_ERROR,
347 VOS_TRUE);
348 }
349
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530350 vos_trace_setValue(VOS_MODULE_ID_RSV4, VOS_TRACE_LEVEL_NONE,
351 VOS_FALSE);
352}
353
354/* Need to call this with spin_lock acquired */
355static int wlan_queue_logmsg_for_app(void)
356{
357 char *ptr;
358 int ret = 0;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530359 ptr = &gwlan_logging.pcur_node->logbuf[sizeof(tAniHdr)];
360 ptr[gwlan_logging.pcur_node->filled_length] = '\0';
361
362 *(unsigned short *)(gwlan_logging.pcur_node->logbuf) =
363 ANI_NL_MSG_LOG_TYPE;
364 *(unsigned short *)(gwlan_logging.pcur_node->logbuf + 2) =
365 gwlan_logging.pcur_node->filled_length;
366 list_add_tail(&gwlan_logging.pcur_node->node,
367 &gwlan_logging.filled_list);
368
369 if (!list_empty(&gwlan_logging.free_list)) {
370 /* Get buffer from free list */
371 gwlan_logging.pcur_node =
372 (struct log_msg *)(gwlan_logging.free_list.next);
373 list_del_init(gwlan_logging.free_list.next);
374 } else if (!list_empty(&gwlan_logging.filled_list)) {
375 /* Get buffer from filled list */
376 /* This condition will drop the packet from being
377 * indicated to app
378 */
379 gwlan_logging.pcur_node =
380 (struct log_msg *)(gwlan_logging.filled_list.next);
Vinay Krishna Erannac2532972014-06-26 22:25:19 +0530381 ++gwlan_logging.drop_count;
Sushant Kaushik20a98202014-08-14 16:07:49 +0530382 /* print every 64th drop count */
Sushant Kaushik215778f2015-05-21 14:05:36 +0530383 if (vos_is_multicast_logging() &&
384 (!(gwlan_logging.drop_count % 0x40))) {
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +0530385 pr_err("%s: drop_count = %u index = %d filled_length = %d\n",
Vinay Krishna Erannac2532972014-06-26 22:25:19 +0530386 __func__, gwlan_logging.drop_count,
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +0530387 gwlan_logging.pcur_node->index,
388 gwlan_logging.pcur_node->filled_length);
389 }
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530390 list_del_init(gwlan_logging.filled_list.next);
391 ret = 1;
392 }
393
394 /* Reset the current node values */
395 gwlan_logging.pcur_node->filled_length = 0;
396 return ret;
397}
398
Sushant Kaushik33200572015-08-05 16:46:20 +0530399void wlan_fillTxStruct(void *pktStat)
400{
401 vos_mem_copy(&gwlan_logging.txPktStatsInfo,
402 (struct perPktStatsInfo *)pktStat,
403 sizeof(struct perPktStatsInfo));
404}
405
406bool wlan_isPktStatsEnabled(void)
407{
408 return gwlan_logging.pkt_stats_enabled;
409}
410
411
412
413/* Need to call this with spin_lock acquired */
414static int wlan_queue_pkt_stats_for_app(void)
415{
416 int ret = 0;
417
418 list_add_tail(&gwlan_logging.pkt_stats_pcur_node->node,
419 &gwlan_logging.pkt_stat_filled_list);
420
421 if (!list_empty(&gwlan_logging.pkt_stat_free_list)) {
422 /* Get buffer from free list */
423 gwlan_logging.pkt_stats_pcur_node =
424 (struct pkt_stats_msg *)(gwlan_logging.pkt_stat_free_list.next);
425 list_del_init(gwlan_logging.pkt_stat_free_list.next);
426 } else if (!list_empty(&gwlan_logging.pkt_stat_filled_list)) {
427 /* Get buffer from filled list */
428 /* This condition will drop the packet from being
429 * indicated to app
430 */
431 gwlan_logging.pkt_stats_pcur_node =
432 (struct pkt_stats_msg *)(gwlan_logging.pkt_stat_filled_list.next);
433 ++gwlan_logging.pkt_stat_drop_cnt;
434 /* print every 64th drop count */
435 if (vos_is_multicast_logging() &&
436 (!(gwlan_logging.pkt_stat_drop_cnt % 0x40))) {
437 pr_err("%s: drop_count = %u filled_length = %d\n",
438 __func__, gwlan_logging.pkt_stat_drop_cnt,
439 gwlan_logging.pkt_stats_pcur_node->skb->len);
440 }
441 list_del_init(gwlan_logging.pkt_stat_filled_list.next);
442 ret = 1;
443 }
444
445 /* Reset the current node values */
446 gwlan_logging.pkt_stats_pcur_node-> skb->len = 0;
447 return ret;
448}
449
450int wlan_pkt_stats_to_user(void *perPktStat)
451{
452 bool wake_up_thread = false;
453 tPerPacketStats *pktstats = perPktStat;
454 unsigned long flags;
455 tx_rx_pkt_stats rx_tx_stats;
456 int total_log_len = 0;
457 struct sk_buff *ptr;
458 tpSirMacMgmtHdr hdr;
459 uint32 rateIdx;
460
461 if (!vos_is_multicast_logging())
462 {
463 return -EIO;
464 }
465 if (vos_is_multicast_logging()) {
466
467 vos_mem_zero(&rx_tx_stats, sizeof(tx_rx_pkt_stats));
468
469 if (pktstats->is_rx){
470 rx_tx_stats.ps_hdr.flags = (1 << PKTLOG_FLG_FRM_TYPE_REMOTE_S);
471 }else{
472 rx_tx_stats.ps_hdr.flags = (1 << PKTLOG_FLG_FRM_TYPE_LOCAL_S);
473
474 }
475 /*Send log type as PKTLOG_TYPE_PKT_STAT (9)*/
476 rx_tx_stats.ps_hdr.log_type = PKTLOG_TYPE_PKT_STAT;
477 rx_tx_stats.ps_hdr.timestamp = vos_timer_get_system_ticks();
478 rx_tx_stats.ps_hdr.missed_cnt = 0;
479 rx_tx_stats.ps_hdr.size = sizeof(tx_rx_pkt_stats) -
480 sizeof(pkt_stats_hdr) + pktstats->data_len - IP_PLUS_80211_HDR_LEN;
481
482 rx_tx_stats.stats.flags |= PER_PACKET_ENTRY_FLAGS_TX_SUCCESS;
483 rx_tx_stats.stats.flags |= PER_PACKET_ENTRY_FLAGS_80211_HEADER;
484 if (pktstats->is_rx)
485 rx_tx_stats.stats.flags |= PER_PACKET_ENTRY_FLAGS_DIRECTION_TX;
486
487 hdr = (tpSirMacMgmtHdr)pktstats->data;
488 if (hdr->fc.wep)
489 rx_tx_stats.stats.flags |= PER_PACKET_ENTRY_FLAGS_PROTECTED;
490
491 rx_tx_stats.stats.tid = pktstats->tid;
492 rx_tx_stats.stats.dxe_timestamp = pktstats->dxe_timestamp;
493
494 if (!pktstats->is_rx)
495 {
496 rx_tx_stats.stats.rssi = gwlan_logging.txPktStatsInfo.avgRssi;
497 rx_tx_stats.stats.num_retries = gwlan_logging.txPktStatsInfo.txAvgRetry;
498 rateIdx = gwlan_logging.txPktStatsInfo.lastTxRate;
499 }
500 else
501 {
502 rx_tx_stats.stats.rssi = pktstats->rssi;
503 rx_tx_stats.stats.num_retries = pktstats->num_retries;
504 rateIdx = pktstats->rate_idx;
505
506 }
507 rx_tx_stats.stats.link_layer_transmit_sequence = pktstats->seq_num;
508
509 /* Calculate rate and MCS from rate index */
510 if( rateIdx >= 210 && rateIdx <= 217)
511 rateIdx-=202;
512 if( rateIdx >= 218 && rateIdx <= 225 )
513 rateIdx-=210;
514 get_rate_and_MCS(&rx_tx_stats.stats, rateIdx);
515
516 vos_mem_copy(rx_tx_stats.stats.data,pktstats->data, pktstats->data_len);
517
518 /* 1+1 indicate '\n'+'\0' */
519 total_log_len = sizeof(tx_rx_pkt_stats) + pktstats->data_len - IP_PLUS_80211_HDR_LEN;
520 spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, flags);
521 // wlan logging svc resources are not yet initialized
522 if (!gwlan_logging.pkt_stats_pcur_node) {
523 pr_err("%s, logging svc not initialized", __func__);
524 spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, flags);
525 return -EIO;
526 }
527
528 ;
529
530 /* Check if we can accomodate more log into current node/buffer */
531 if (total_log_len + sizeof(vos_log_pktlog_info) + sizeof(tAniNlHdr) >=
532 skb_tailroom(gwlan_logging.pkt_stats_pcur_node->skb)) {
533 wake_up_thread = true;
534 wlan_queue_pkt_stats_for_app();
535 }
536 ptr = gwlan_logging.pkt_stats_pcur_node->skb;
537
538
539 vos_mem_copy(skb_put(ptr, total_log_len), &rx_tx_stats, total_log_len);
540 spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, flags);
541 /* Wakeup logger thread */
542 if ((true == wake_up_thread)) {
543 /* If there is logger app registered wakeup the logging
544 * thread
545 */
546 set_bit(HOST_PKT_STATS_POST_MASK, &gwlan_logging.event_flag);
547 wake_up_interruptible(&gwlan_logging.wait_queue);
548 }
549 }
550 return 0;
551}
552
553void wlan_disable_and_flush_pkt_stats()
554{
555 unsigned long flags;
556 spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, flags);
557 if(gwlan_logging.pkt_stats_pcur_node->skb->len){
558 wlan_queue_pkt_stats_for_app();
559 }
560 spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, flags);
561 set_bit(HOST_PKT_STATS_POST_MASK, &gwlan_logging.event_flag);
562 wake_up_interruptible(&gwlan_logging.wait_queue);
563}
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530564
565int wlan_log_to_user(VOS_TRACE_LEVEL log_level, char *to_be_sent, int length)
566{
567 /* Add the current time stamp */
568 char *ptr;
Ratnam Rachuric798dbe2015-07-17 11:19:44 +0530569 char tbuf[100];
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530570 int tlen;
571 int total_log_len;
572 unsigned int *pfilled_length;
573 bool wake_up_thread = false;
Pradeep Kumar Goudagunta8526f832014-04-17 14:56:09 +0530574 unsigned long flags;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530575
Ratnam Rachuri3119f8a2015-07-23 14:55:21 +0530576 struct timeval tv;
577 struct rtc_time tm;
Vinay Krishna Eranna2c0ac302014-12-17 15:21:40 +0530578 unsigned long local_time;
Ratnam Rachuric798dbe2015-07-17 11:19:44 +0530579 u64 qtimer_ticks;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530580
Sushant Kaushik215778f2015-05-21 14:05:36 +0530581 if (!vos_is_multicast_logging()) {
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530582 /*
583 * This is to make sure that we print the logs to kmsg console
584 * when no logger app is running. This is also needed to
585 * log the initial messages during loading of driver where even
586 * if app is running it will not be able to
587 * register with driver immediately and start logging all the
588 * messages.
589 */
Vinay Krishna Eranna82337362014-09-06 18:19:03 +0530590 pr_err("%s\n", to_be_sent);
Sushant Kaushik215778f2015-05-21 14:05:36 +0530591 } else {
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530592
Vinay Krishna Eranna2c0ac302014-12-17 15:21:40 +0530593 /* Format the Log time [hr:min:sec.microsec] */
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530594 do_gettimeofday(&tv);
Vinay Krishna Eranna2c0ac302014-12-17 15:21:40 +0530595
596 /* Convert rtc to local time */
597 local_time = (u32)(tv.tv_sec - (sys_tz.tz_minuteswest * 60));
598 rtc_time_to_tm(local_time, &tm);
Ratnam Rachuric798dbe2015-07-17 11:19:44 +0530599 /* Firmware Time Stamp */
600 qtimer_ticks = arch_counter_get_cntpct();
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530601
Ratnam Rachuri3119f8a2015-07-23 14:55:21 +0530602 tlen = snprintf(tbuf, sizeof(tbuf), "[%02d:%02d:%02d.%06lu] [%016llX]"
Sushant Kaushik96e66942015-09-21 12:43:15 +0530603 " [%.5s] ", tm.tm_hour, tm.tm_min, tm.tm_sec, tv.tv_usec,
Ratnam Rachuri3119f8a2015-07-23 14:55:21 +0530604 qtimer_ticks, current->comm);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530605 /* 1+1 indicate '\n'+'\0' */
606 total_log_len = length + tlen + 1 + 1;
607
Pradeep Kumar Goudagunta8526f832014-04-17 14:56:09 +0530608 spin_lock_irqsave(&gwlan_logging.spin_lock, flags);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +0530609
c_hpothu14181752014-12-10 11:52:09 +0530610 // wlan logging svc resources are not yet initialized
611 if (!gwlan_logging.pcur_node) {
612 spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags);
613 return -EIO;
614 }
615
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530616 pfilled_length = &gwlan_logging.pcur_node->filled_length;
617
618 /* Check if we can accomodate more log into current node/buffer */
Sushant Kaushika20112f2015-09-08 15:07:33 +0530619 if (MAX_LOGMSG_LENGTH < (*pfilled_length + sizeof(tAniNlHdr) +
620 total_log_len)) {
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530621 wake_up_thread = true;
622 wlan_queue_logmsg_for_app();
623 pfilled_length = &gwlan_logging.pcur_node->filled_length;
624 }
625
626 ptr = &gwlan_logging.pcur_node->logbuf[sizeof(tAniHdr)];
627
628 /* Assumption here is that we receive logs which is always less than
629 * MAX_LOGMSG_LENGTH, where we can accomodate the
630 * tAniNlHdr + [context][timestamp] + log
631 * VOS_ASSERT if we cannot accomodate the the complete log into
632 * the available buffer.
633 *
634 * Continue and copy logs to the available length and discard the rest.
635 */
636 if (MAX_LOGMSG_LENGTH < (sizeof(tAniNlHdr) + total_log_len)) {
637 VOS_ASSERT(0);
638 total_log_len = MAX_LOGMSG_LENGTH - sizeof(tAniNlHdr) - 2;
639 }
640
Rajesh Babu Prathipati71e9c442014-07-01 22:08:29 +0530641 vos_mem_copy(&ptr[*pfilled_length], tbuf, tlen);
642 vos_mem_copy(&ptr[*pfilled_length + tlen], to_be_sent,
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530643 min(length, (total_log_len - tlen)));
644 *pfilled_length += tlen + min(length, total_log_len - tlen);
645 ptr[*pfilled_length] = '\n';
646 *pfilled_length += 1;
647
Pradeep Kumar Goudagunta8526f832014-04-17 14:56:09 +0530648 spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530649
650 /* Wakeup logger thread */
Vinay Krishna Eranna8382e0e2014-06-18 19:19:58 +0530651 if ((true == wake_up_thread)) {
652 /* If there is logger app registered wakeup the logging
Sushant Kaushik215778f2015-05-21 14:05:36 +0530653 * thread
Vinay Krishna Eranna8382e0e2014-06-18 19:19:58 +0530654 */
Sushant Kaushik215778f2015-05-21 14:05:36 +0530655
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530656 set_bit(HOST_LOG_POST_MASK, &gwlan_logging.event_flag);
Vinay Krishna Eranna8382e0e2014-06-18 19:19:58 +0530657 wake_up_interruptible(&gwlan_logging.wait_queue);
Vinay Krishna Eranna8382e0e2014-06-18 19:19:58 +0530658 }
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530659
Sushant Kaushik215778f2015-05-21 14:05:36 +0530660 if (gwlan_logging.log_fe_to_console
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530661 && ((VOS_TRACE_LEVEL_FATAL == log_level)
662 || (VOS_TRACE_LEVEL_ERROR == log_level))) {
Sushant Kaushik7050ac42015-09-23 11:21:12 +0530663 pr_err("%s %s\n",tbuf, to_be_sent);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530664 }
Sushant Kaushik215778f2015-05-21 14:05:36 +0530665 }
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530666
667 return 0;
668}
669
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530670static int send_fw_log_pkt_to_user(void)
671{
672 int ret = -1;
673 int extra_header_len, nl_payload_len;
674 struct sk_buff *skb = NULL;
675 static int nlmsg_seq;
676 vos_pkt_t *current_pkt;
677 vos_pkt_t *next_pkt;
678 VOS_STATUS status = VOS_STATUS_E_FAILURE;
679 unsigned long flags;
680
681 tAniNlHdr msg_header;
682
683 do {
684 spin_lock_irqsave(&gwlan_logging.fw_log_pkt_lock, flags);
685
686 if (!gwlan_logging.fw_log_pkt_queue) {
687 spin_unlock_irqrestore(
688 &gwlan_logging.fw_log_pkt_lock, flags);
689 return -EIO;
690 }
691
692 /* pick first pkt from queued chain */
693 current_pkt = gwlan_logging.fw_log_pkt_queue;
694
695 /* get the pointer to the next packet in the chain */
696 status = vos_pkt_walk_packet_chain(current_pkt, &next_pkt,
697 TRUE);
698
699 /* both "success" and "empty" are acceptable results */
700 if (!((status == VOS_STATUS_SUCCESS) ||
701 (status == VOS_STATUS_E_EMPTY))) {
702 ++gwlan_logging.fw_log_pkt_drop_cnt;
703 spin_unlock_irqrestore(
704 &gwlan_logging.fw_log_pkt_lock, flags);
705 pr_err("%s: Failure walking packet chain", __func__);
706 return -EIO;
707 }
708
709 /* update queue head with next pkt ptr which could be NULL */
710 gwlan_logging.fw_log_pkt_queue = next_pkt;
711 --gwlan_logging.fw_log_pkt_qcnt;
712 spin_unlock_irqrestore(&gwlan_logging.fw_log_pkt_lock, flags);
713
714 status = vos_pkt_get_os_packet(current_pkt, (v_VOID_t **)&skb,
715 TRUE);
716 if (!VOS_IS_STATUS_SUCCESS(status)) {
717 ++gwlan_logging.fw_log_pkt_drop_cnt;
718 pr_err("%s: Failure extracting skb from vos pkt",
719 __func__);
720 return -EIO;
721 }
722
723 /*return vos pkt since skb is already detached */
724 vos_pkt_return_packet(current_pkt);
725
726 extra_header_len = sizeof(msg_header.radio) + sizeof(tAniHdr);
727 nl_payload_len = NLMSG_ALIGN(extra_header_len + skb->len);
728
729 msg_header.nlh.nlmsg_type = ANI_NL_MSG_LOG;
730 msg_header.nlh.nlmsg_len = nl_payload_len;
731 msg_header.nlh.nlmsg_flags = NLM_F_REQUEST;
732 msg_header.nlh.nlmsg_pid = gapp_pid;
733 msg_header.nlh.nlmsg_seq = nlmsg_seq++;
734
735 msg_header.radio = 0;
736
737 msg_header.wmsg.type = ANI_NL_MSG_FW_LOG_PKT_TYPE;
738 msg_header.wmsg.length = skb->len;
739
740 if (unlikely(skb_headroom(skb) < sizeof(msg_header))) {
741 pr_err("VPKT [%d]: Insufficient headroom, head[%p],"
742 " data[%p], req[%zu]", __LINE__, skb->head,
743 skb->data, sizeof(msg_header));
744 return -EIO;
745 }
746
747 vos_mem_copy(skb_push(skb, sizeof(msg_header)), &msg_header,
748 sizeof(msg_header));
749
750 ret = nl_srv_bcast(skb);
751 if (ret < 0) {
752 pr_info("%s: Send Failed %d drop_count = %u\n",
753 __func__, ret, ++gwlan_logging.fw_log_pkt_drop_cnt);
754 } else {
755 ret = 0;
756 }
757
758 } while (next_pkt);
759
760 return ret;
761}
762
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530763static int send_data_mgmt_log_pkt_to_user(void)
764{
765 int ret = -1;
766 int extra_header_len, nl_payload_len;
767 struct sk_buff *skb = NULL;
768 static int nlmsg_seq;
769 vos_pkt_t *current_pkt;
770 vos_pkt_t *next_pkt;
771 VOS_STATUS status = VOS_STATUS_E_FAILURE;
772 unsigned long flags;
773
774 tAniNlLogHdr msg_header;
775
776 do {
777 spin_lock_irqsave(&gwlan_logging.data_mgmt_pkt_lock, flags);
778
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530779 if (!gwlan_logging.data_mgmt_pkt_queue) {
780 spin_unlock_irqrestore(
781 &gwlan_logging.data_mgmt_pkt_lock, flags);
782 return -EIO;
783 }
784
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530785 /* pick first pkt from queued chain */
786 current_pkt = gwlan_logging.data_mgmt_pkt_queue;
787
788 /* get the pointer to the next packet in the chain */
789 status = vos_pkt_walk_packet_chain(current_pkt, &next_pkt,
790 TRUE);
791
792 /* both "success" and "empty" are acceptable results */
793 if (!((status == VOS_STATUS_SUCCESS) ||
794 (status == VOS_STATUS_E_EMPTY))) {
795 ++gwlan_logging.pkt_drop_cnt;
796 spin_unlock_irqrestore(
797 &gwlan_logging.data_mgmt_pkt_lock, flags);
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530798 pr_err("%s: Failure walking packet chain", __func__);
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530799 return -EIO;
800 }
801
802 /* update queue head with next pkt ptr which could be NULL */
803 gwlan_logging.data_mgmt_pkt_queue = next_pkt;
804 --gwlan_logging.data_mgmt_pkt_qcnt;
805 spin_unlock_irqrestore(&gwlan_logging.data_mgmt_pkt_lock, flags);
806
807 status = vos_pkt_get_os_packet(current_pkt, (v_VOID_t **)&skb,
808 TRUE);
809 if (!VOS_IS_STATUS_SUCCESS(status)) {
810 ++gwlan_logging.pkt_drop_cnt;
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530811 pr_err("%s: Failure extracting skb from vos pkt",
812 __func__);
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530813 return -EIO;
814 }
815
816 /*return vos pkt since skb is already detached */
817 vos_pkt_return_packet(current_pkt);
818
819 extra_header_len = sizeof(msg_header.radio) + sizeof(tAniHdr) +
820 sizeof(msg_header.frameSize);
821 nl_payload_len = NLMSG_ALIGN(extra_header_len + skb->len);
822
823 msg_header.nlh.nlmsg_type = ANI_NL_MSG_LOG;
824 msg_header.nlh.nlmsg_len = nl_payload_len;
825 msg_header.nlh.nlmsg_flags = NLM_F_REQUEST;
Sushant Kaushik215778f2015-05-21 14:05:36 +0530826 msg_header.nlh.nlmsg_pid = 0;
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530827 msg_header.nlh.nlmsg_seq = nlmsg_seq++;
828
829 msg_header.radio = 0;
830
831 msg_header.wmsg.type = ANI_NL_MSG_LOG_PKT_TYPE;
832 msg_header.wmsg.length = skb->len + sizeof(uint32);
833
834 msg_header.frameSize = WLAN_MGMT_LOGGING_FRAMESIZE_128BYTES;
835
836 if (unlikely(skb_headroom(skb) < sizeof(msg_header))) {
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530837 pr_err("VPKT [%d]: Insufficient headroom, head[%p],"
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530838 " data[%p], req[%zu]", __LINE__, skb->head,
839 skb->data, sizeof(msg_header));
840 return -EIO;
841 }
842
843 vos_mem_copy(skb_push(skb, sizeof(msg_header)), &msg_header,
844 sizeof(msg_header));
845
Sushant Kaushik215778f2015-05-21 14:05:36 +0530846 ret = nl_srv_bcast(skb);
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530847 if (ret < 0) {
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530848 pr_info("%s: Send Failed %d drop_count = %u\n",
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530849 __func__, ret, ++gwlan_logging.pkt_drop_cnt);
850 } else {
851 ret = 0;
852 }
853
854 } while (next_pkt);
855
856 return ret;
857}
858
c_manjeecfd1efb2015-09-25 19:32:34 +0530859static int fill_fw_mem_dump_buffer(void)
860{
861 struct sk_buff *skb = NULL;
862 vos_pkt_t *current_pkt;
863 vos_pkt_t *next_pkt;
864 VOS_STATUS status = VOS_STATUS_E_FAILURE;
865 unsigned long flags;
866 int byte_left = 0;
867
868 do {
869 spin_lock_irqsave(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
870
871 if (!gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_queue) {
872 spin_unlock_irqrestore(
873 &gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
874 return -EIO;
875 }
876
877 /* pick first pkt from queued chain */
878 current_pkt = gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_queue;
879
880 /* get the pointer to the next packet in the chain */
881 status = vos_pkt_walk_packet_chain(current_pkt, &next_pkt,
882 TRUE);
883
884 /* both "success" and "empty" are acceptable results */
885 if (!((status == VOS_STATUS_SUCCESS) ||
886 (status == VOS_STATUS_E_EMPTY))) {
887 spin_unlock_irqrestore(
888 &gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
889 pr_err("%s: Failure walking packet chain", __func__);
890 return -EIO;
891 }
892
893 /* update queue head with next pkt ptr which could be NULL */
894 gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_queue = next_pkt;
895 --gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_pkt_qcnt;
896 spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
897
898 status = vos_pkt_get_os_packet(current_pkt, (v_VOID_t **)&skb,
899 VOS_FALSE);
900 if (!VOS_IS_STATUS_SUCCESS(status)) {
901 pr_err("%s: Failure extracting skb from vos pkt",
902 __func__);
903 return -EIO;
904 }
905
906 //Copy data from SKB to mem dump buffer
907 spin_lock_irqsave(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
908 if((skb) && (skb->len != 0))
909 {
910 // Prevent buffer overflow
911 byte_left = ((int)gwlan_logging.fw_mem_dump_ctx.fw_dump_max_size -
912 (int)(gwlan_logging.fw_mem_dump_ctx.fw_dump_current_loc - gwlan_logging.fw_mem_dump_ctx.fw_dump_start_loc));
913 if(skb->len > byte_left)
914 {
915 vos_mem_copy(gwlan_logging.fw_mem_dump_ctx.fw_dump_current_loc, &skb->data, byte_left);
916 //Update the current location ptr
917 gwlan_logging.fw_mem_dump_ctx.fw_dump_current_loc += byte_left;
918 }
919 else
920 {
921 vos_mem_copy(gwlan_logging.fw_mem_dump_ctx.fw_dump_current_loc, &skb->data, skb->len);
922 //Update the current location ptr
923 gwlan_logging.fw_mem_dump_ctx.fw_dump_current_loc += skb->len;
924 }
925 }
926 spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
927 //if(skb)
928 // pr_err("Mem dump buffer overflow byte_left %d skb->len %d", byte_left, skb->len);
929 /*return vos pkt since skb is already detached */
930 vos_pkt_return_packet(current_pkt);
931 } while (next_pkt);
932
933 return 0;
934}
935
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530936static int send_filled_buffers_to_user(void)
937{
938 int ret = -1;
939 struct log_msg *plog_msg;
940 int payload_len;
941 int tot_msg_len;
942 tAniNlHdr *wnl;
943 struct sk_buff *skb = NULL;
944 struct nlmsghdr *nlh;
945 static int nlmsg_seq;
Pradeep Kumar Goudagunta8526f832014-04-17 14:56:09 +0530946 unsigned long flags;
Vinay Krishna Erannac2532972014-06-26 22:25:19 +0530947 static int rate_limit;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530948
949 while (!list_empty(&gwlan_logging.filled_list)
c_manjeecfd1efb2015-09-25 19:32:34 +0530950 && !gwlan_logging.exit) {
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530951
952 skb = dev_alloc_skb(MAX_LOGMSG_LENGTH);
953 if (skb == NULL) {
Vinay Krishna Erannac2532972014-06-26 22:25:19 +0530954 if (!rate_limit) {
955 pr_err("%s: dev_alloc_skb() failed for msg size[%d] drop count = %u\n",
956 __func__, MAX_LOGMSG_LENGTH,
957 gwlan_logging.drop_count);
958 }
959 rate_limit = 1;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530960 ret = -ENOMEM;
961 break;
962 }
Vinay Krishna Erannac2532972014-06-26 22:25:19 +0530963 rate_limit = 0;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530964
Pradeep Kumar Goudagunta8526f832014-04-17 14:56:09 +0530965 spin_lock_irqsave(&gwlan_logging.spin_lock, flags);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530966
967 plog_msg = (struct log_msg *)
968 (gwlan_logging.filled_list.next);
969 list_del_init(gwlan_logging.filled_list.next);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +0530970 spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530971 /* 4 extra bytes for the radio idx */
972 payload_len = plog_msg->filled_length +
973 sizeof(wnl->radio) + sizeof(tAniHdr);
974
975 tot_msg_len = NLMSG_SPACE(payload_len);
Sushant Kaushik215778f2015-05-21 14:05:36 +0530976 nlh = nlmsg_put(skb, 0, nlmsg_seq++,
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530977 ANI_NL_MSG_LOG, payload_len,
978 NLM_F_REQUEST);
979 if (NULL == nlh) {
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +0530980 spin_lock_irqsave(&gwlan_logging.spin_lock, flags);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530981 list_add_tail(&plog_msg->node,
982 &gwlan_logging.free_list);
Pradeep Kumar Goudagunta8526f832014-04-17 14:56:09 +0530983 spin_unlock_irqrestore(&gwlan_logging.spin_lock,
984 flags);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530985 pr_err("%s: drop_count = %u\n", __func__,
986 ++gwlan_logging.drop_count);
987 pr_err("%s: nlmsg_put() failed for msg size[%d]\n",
988 __func__, tot_msg_len);
989 dev_kfree_skb(skb);
990 skb = NULL;
991 ret = -EINVAL;
992 continue;
993 }
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530994
995 wnl = (tAniNlHdr *) nlh;
996 wnl->radio = plog_msg->radio;
Rajesh Babu Prathipati71e9c442014-07-01 22:08:29 +0530997 vos_mem_copy(&wnl->wmsg, plog_msg->logbuf,
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530998 plog_msg->filled_length +
999 sizeof(tAniHdr));
1000
Pradeep Kumar Goudagunta8526f832014-04-17 14:56:09 +05301001 spin_lock_irqsave(&gwlan_logging.spin_lock, flags);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301002 list_add_tail(&plog_msg->node,
1003 &gwlan_logging.free_list);
Pradeep Kumar Goudagunta8526f832014-04-17 14:56:09 +05301004 spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301005
Sushant Kaushik215778f2015-05-21 14:05:36 +05301006 ret = nl_srv_bcast(skb);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301007 if (ret < 0) {
Sushant Kaushik8ddaa382015-06-23 12:17:25 +05301008 if (__ratelimit(&errCnt))
1009 {
1010 pr_info("%s: Send Failed %d drop_count = %u\n",
1011 __func__, ret, gwlan_logging.drop_count);
1012 }
1013 gwlan_logging.drop_count++;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301014 skb = NULL;
c_hpothu0424d042014-11-19 19:37:14 +05301015 break;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301016 } else {
1017 skb = NULL;
1018 ret = 0;
1019 }
1020 }
1021
1022 return ret;
1023}
1024
Sushant Kaushik33200572015-08-05 16:46:20 +05301025
1026static int send_per_pkt_stats_to_user(void)
1027{
1028 int ret = -1;
1029 struct pkt_stats_msg *plog_msg;
1030 unsigned long flags;
1031 struct sk_buff *skb_new = NULL;
1032 vos_log_pktlog_info pktlog;
1033 tAniNlHdr msg_header;
1034 int extra_header_len, nl_payload_len;
1035 static int nlmsg_seq;
1036 static int rate_limit;
1037 int diag_type;
1038
1039 while (!list_empty(&gwlan_logging.pkt_stat_filled_list)
1040 && !gwlan_logging.exit) {
1041 skb_new= dev_alloc_skb(MAX_PKTSTATS_LOG_LENGTH);
1042 if (skb_new == NULL) {
1043 if (!rate_limit) {
1044 pr_err("%s: dev_alloc_skb() failed for msg size[%d] drop count = %u\n",
1045 __func__, MAX_LOGMSG_LENGTH,
1046 gwlan_logging.drop_count);
1047 }
1048 rate_limit = 1;
1049 ret = -ENOMEM;
1050 break;
1051 }
1052
1053 spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, flags);
1054
1055 plog_msg = (struct pkt_stats_msg *)
1056 (gwlan_logging.pkt_stat_filled_list.next);
1057 list_del_init(gwlan_logging.pkt_stat_filled_list.next);
1058 spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, flags);
1059
1060 vos_mem_zero(&pktlog, sizeof(vos_log_pktlog_info));
1061 vos_log_set_code(&pktlog, LOG_WLAN_PKT_LOG_INFO_C);
1062
1063 pktlog.version = VERSION_LOG_WLAN_PKT_LOG_INFO_C;
1064 pktlog.buf_len = plog_msg->skb->len;
1065 vos_log_set_length(&pktlog.log_hdr, plog_msg->skb->len +
1066 sizeof(vos_log_pktlog_info));
1067 pktlog.seq_no = gwlan_logging.pkt_stats_msg_idx++;
1068
1069 if (unlikely(skb_headroom(plog_msg->skb) < sizeof(vos_log_pktlog_info))) {
1070 pr_err("VPKT [%d]: Insufficient headroom, head[%p],"
1071 " data[%p], req[%zu]", __LINE__, plog_msg->skb->head,
1072 plog_msg->skb->data, sizeof(msg_header));
1073 ret = -EIO;
1074 goto err;
1075 }
1076 vos_mem_copy(skb_push(plog_msg->skb, sizeof(vos_log_pktlog_info)), &pktlog,
1077 sizeof(vos_log_pktlog_info));
1078
1079 if (unlikely(skb_headroom(plog_msg->skb) < sizeof(int))) {
1080 pr_err("VPKT [%d]: Insufficient headroom, head[%p],"
1081 " data[%p], req[%zu]", __LINE__, plog_msg->skb->head,
1082 plog_msg->skb->data, sizeof(int));
1083 ret = -EIO;
1084 goto err;
1085 }
1086
1087 diag_type = DIAG_TYPE_LOGS;
1088 vos_mem_copy(skb_push(plog_msg->skb, sizeof(int)), &diag_type,
1089 sizeof(int));
1090
1091 extra_header_len = sizeof(msg_header.radio) + sizeof(tAniHdr);
1092 nl_payload_len = NLMSG_ALIGN(extra_header_len + plog_msg->skb->len);
1093
1094 msg_header.nlh.nlmsg_type = ANI_NL_MSG_PUMAC;
1095 msg_header.nlh.nlmsg_len = nl_payload_len;
1096 msg_header.nlh.nlmsg_flags = NLM_F_REQUEST;
1097 msg_header.nlh.nlmsg_pid = 0;
1098 msg_header.nlh.nlmsg_seq = nlmsg_seq++;
1099
1100 msg_header.radio = 0;
1101
1102 msg_header.wmsg.type = PTT_MSG_DIAG_CMDS_TYPE;
1103 msg_header.wmsg.length = plog_msg->skb->len;
1104
1105 if (unlikely(skb_headroom(plog_msg->skb) < sizeof(msg_header))) {
1106 pr_err("VPKT [%d]: Insufficient headroom, head[%p],"
1107 " data[%p], req[%zu]", __LINE__, plog_msg->skb->head,
1108 plog_msg->skb->data, sizeof(msg_header));
1109 ret = -EIO;
1110 goto err;
1111 }
1112
1113 vos_mem_copy(skb_push(plog_msg->skb, sizeof(msg_header)), &msg_header,
1114 sizeof(msg_header));
1115
1116 ret = nl_srv_bcast(plog_msg->skb);
1117 if (ret < 0) {
1118 pr_info("%s: Send Failed %d drop_count = %u\n",
1119 __func__, ret, ++gwlan_logging.fw_log_pkt_drop_cnt);
1120 } else {
1121 ret = 0;
1122 }
1123err:
1124 spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, flags);
1125 plog_msg->skb = skb_new;
1126 list_add_tail(&plog_msg->node,
1127 &gwlan_logging.pkt_stat_free_list);
1128 spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, flags);
1129 ret = 0;
1130 }
1131
1132 return ret;
1133}
1134
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301135/**
Abhishek Singh880d7122015-08-26 16:23:04 +05301136 * wlan_logging_detect_thread_stuck_cb()- Call back of the
1137 * thread stuck timer to detect thread stuck
1138 * by probing the MC, TX, RX threads and take action if
1139 * Thread doesnt respond.
1140 * @priv: timer data.
1141 * This function is called when the thread stuck timer expire
1142 * to detect thread stuck
1143 * and probe threads.
1144 *
1145 * Return: void
1146 */
1147static void wlan_logging_detect_thread_stuck_cb(void *priv)
1148{
1149 unsigned long flags;
1150
1151 spin_lock_irqsave(&gwlan_logging.thread_stuck_lock, flags);
1152
1153 if ((gwlan_logging.mcThreadStuckCount == THREAD_STUCK_COUNT) ||
1154 (gwlan_logging.txThreadStuckCount == THREAD_STUCK_COUNT) ||
1155 (gwlan_logging.rxThreadStuckCount == THREAD_STUCK_COUNT)) {
1156 spin_unlock_irqrestore(&gwlan_logging.thread_stuck_lock, flags);
1157 pr_err("%s: %s Thread Stuck !!!\n", __func__,
1158 ((gwlan_logging.mcThreadStuckCount == THREAD_STUCK_COUNT)?
1159 "MC" : (gwlan_logging.mcThreadStuckCount ==
1160 THREAD_STUCK_COUNT)? "TX" : "RX"));
1161 VOS_BUG(0);
1162 return;
1163 }
1164
1165 /* Increment the thread stuck count for all threads */
1166 gwlan_logging.mcThreadStuckCount++;
1167 gwlan_logging.txThreadStuckCount++;
1168 gwlan_logging.rxThreadStuckCount++;
1169
1170 spin_unlock_irqrestore(&gwlan_logging.thread_stuck_lock, flags);
1171 vos_probe_threads();
1172
1173 /* Restart the timer */
1174 if (VOS_STATUS_SUCCESS !=
1175 vos_timer_start(&gwlan_logging.threadStuckTimer,
1176 THREAD_STUCK_TIMER_VAL))
1177 pr_err("%s: Unable to start thread stuck timer\n", __func__);
1178}
1179
1180/**
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301181 * wlan_logging_thread() - The WLAN Logger thread
1182 * @Arg - pointer to the HDD context
1183 *
1184 * This thread logs log message to App registered for the logs.
1185 */
1186static int wlan_logging_thread(void *Arg)
1187{
1188 int ret_wait_status = 0;
Vinay Krishna Erannac2532972014-06-26 22:25:19 +05301189 int ret = 0;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301190
1191 set_user_nice(current, -2);
1192
1193#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))
1194 daemonize("wlan_logging_thread");
1195#endif
1196
Abhishek Singh880d7122015-08-26 16:23:04 +05301197 /* Initialize the timer to detect thread stuck issues */
1198 if (vos_timer_init(&gwlan_logging.threadStuckTimer, VOS_TIMER_TYPE_SW,
1199 wlan_logging_detect_thread_stuck_cb, NULL)) {
1200 pr_err("%s: Unable to initialize thread stuck timer\n", __func__);
1201 } else {
1202 if (VOS_STATUS_SUCCESS !=
1203 vos_timer_start(&gwlan_logging.threadStuckTimer,
1204 THREAD_STUCK_TIMER_VAL))
1205 pr_err("%s: Unable to start thread stuck timer\n",
1206 __func__);
1207 else
1208 pr_info("%s: Successfully started thread stuck timer\n",
1209 __func__);
1210 }
1211
1212
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301213 while (!gwlan_logging.exit) {
1214 ret_wait_status = wait_event_interruptible(
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301215 gwlan_logging.wait_queue,
1216 (test_bit(HOST_LOG_POST_MASK, &gwlan_logging.event_flag) ||
Sachin Ahuja715aafc2015-07-21 23:35:10 +05301217 gwlan_logging.exit ||
Abhishek Singh880d7122015-08-26 16:23:04 +05301218 test_bit(LOGGER_MGMT_DATA_PKT_POST_MASK,
1219 &gwlan_logging.event_flag) ||
1220 test_bit(LOGGER_FW_LOG_PKT_POST_MASK,
1221 &gwlan_logging.event_flag) ||
1222 test_bit(LOGGER_FATAL_EVENT_POST_MASK,
c_manjeecfd1efb2015-09-25 19:32:34 +05301223 &gwlan_logging.event_flag) ||
1224 test_bit(LOGGER_FW_MEM_DUMP_PKT_POST_MASK,&gwlan_logging.event_flag) ||
Sushant Kaushik33200572015-08-05 16:46:20 +05301225 test_bit(LOGGER_FW_MEM_DUMP_PKT_POST_DONE_MASK, &gwlan_logging.event_flag)||
1226 test_bit(HOST_PKT_STATS_POST_MASK,
1227 &gwlan_logging.event_flag)));
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301228
1229 if (ret_wait_status == -ERESTARTSYS) {
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301230 pr_err("%s: wait_event return -ERESTARTSYS", __func__);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301231 break;
1232 }
1233
1234 if (gwlan_logging.exit) {
c_hpothu0424d042014-11-19 19:37:14 +05301235 break;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301236 }
1237
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301238 if (test_and_clear_bit(HOST_LOG_POST_MASK,
1239 &gwlan_logging.event_flag)) {
1240 ret = send_filled_buffers_to_user();
1241 if (-ENOMEM == ret) {
1242 msleep(200);
1243 }
1244 }
1245
Siddharth Bhalec0b72c2015-05-12 21:35:54 +05301246 if (test_and_clear_bit(LOGGER_FW_LOG_PKT_POST_MASK,
1247 &gwlan_logging.event_flag)) {
1248 send_fw_log_pkt_to_user();
1249 }
1250
1251 if (test_and_clear_bit(LOGGER_MGMT_DATA_PKT_POST_MASK,
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301252 &gwlan_logging.event_flag)) {
1253 send_data_mgmt_log_pkt_to_user();
Vinay Krishna Erannac2532972014-06-26 22:25:19 +05301254 }
Sachin Ahuja715aafc2015-07-21 23:35:10 +05301255
1256 if (test_and_clear_bit(LOGGER_FATAL_EVENT_POST_MASK,
1257 &gwlan_logging.event_flag)) {
1258 if (gwlan_logging.log_complete.is_flush_complete == true) {
1259 gwlan_logging.log_complete.is_flush_complete = false;
1260 vos_send_fatal_event_done();
1261 }
1262 else {
1263 gwlan_logging.log_complete.is_flush_complete = true;
1264 set_bit(HOST_LOG_POST_MASK,&gwlan_logging.event_flag);
1265 set_bit(LOGGER_FW_LOG_PKT_POST_MASK,&gwlan_logging.event_flag);
1266 set_bit(LOGGER_FATAL_EVENT_POST_MASK,&gwlan_logging.event_flag);
1267 wake_up_interruptible(&gwlan_logging.wait_queue);
1268 }
1269 }
c_manjeecfd1efb2015-09-25 19:32:34 +05301270
1271 if (test_and_clear_bit(LOGGER_FW_MEM_DUMP_PKT_POST_MASK,
1272 &gwlan_logging.event_flag)) {
1273 fill_fw_mem_dump_buffer();
1274 }
1275 if(test_and_clear_bit(LOGGER_FW_MEM_DUMP_PKT_POST_DONE_MASK,&gwlan_logging.event_flag)){
1276 /*indicate to user space that mem dump is complete */
1277 fill_fw_mem_dump_buffer();
1278 wlan_indicate_mem_dump_complete(true);
1279 }
1280
Sushant Kaushik33200572015-08-05 16:46:20 +05301281 if (test_and_clear_bit(HOST_PKT_STATS_POST_MASK,
1282 &gwlan_logging.event_flag)) {
1283 send_per_pkt_stats_to_user();
1284 }
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301285 }
1286
Abhishek Singh880d7122015-08-26 16:23:04 +05301287 vos_timer_destroy(&gwlan_logging.threadStuckTimer);
1288
Vinay Krishna Erannad1d284f2014-10-28 20:09:55 +05301289 complete_and_exit(&gwlan_logging.shutdown_comp, 0);
1290
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301291 return 0;
1292}
1293
1294/*
1295 * Process all the Netlink messages from Logger Socket app in user space
1296 */
1297static int wlan_logging_proc_sock_rx_msg(struct sk_buff *skb)
1298{
1299 tAniNlHdr *wnl;
1300 int radio;
1301 int type;
1302 int ret;
1303
Hanumantha Reddy Pothula05b0b552015-06-18 14:26:10 +05301304 if (TRUE == vos_isUnloadInProgress())
1305 {
1306 pr_info("%s: unload in progress\n",__func__);
1307 return -ENODEV;
1308 }
1309
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301310 wnl = (tAniNlHdr *) skb->data;
1311 radio = wnl->radio;
1312 type = wnl->nlh.nlmsg_type;
1313
1314 if (radio < 0 || radio > ANI_MAX_RADIOS) {
Siddharth Bhalec0b72c2015-05-12 21:35:54 +05301315 pr_err("%s: invalid radio id [%d]\n",
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301316 __func__, radio);
1317 return -EINVAL;
1318 }
1319
1320 if (gapp_pid != INVALID_PID) {
1321 if (wnl->nlh.nlmsg_pid > gapp_pid) {
1322 gapp_pid = wnl->nlh.nlmsg_pid;
1323 }
1324
1325 spin_lock_bh(&gwlan_logging.spin_lock);
1326 if (gwlan_logging.pcur_node->filled_length) {
1327 wlan_queue_logmsg_for_app();
1328 }
1329 spin_unlock_bh(&gwlan_logging.spin_lock);
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301330 set_bit(HOST_LOG_POST_MASK, &gwlan_logging.event_flag);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301331 wake_up_interruptible(&gwlan_logging.wait_queue);
1332 } else {
1333 /* This is to set the default levels (WLAN logging
1334 * default values not the VOS trace default) when
1335 * logger app is registered for the first time.
1336 */
1337 gapp_pid = wnl->nlh.nlmsg_pid;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301338 }
1339
1340 ret = wlan_send_sock_msg_to_app(&wnl->wmsg, 0,
1341 ANI_NL_MSG_LOG, wnl->nlh.nlmsg_pid);
1342 if (ret < 0) {
Siddharth Bhalec0b72c2015-05-12 21:35:54 +05301343 pr_err("wlan_send_sock_msg_to_app: failed");
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301344 }
1345
1346 return ret;
1347}
1348
Sachin Ahuja715aafc2015-07-21 23:35:10 +05301349void wlan_init_log_completion(void)
1350{
1351 gwlan_logging.log_complete.indicator = WLAN_LOG_TYPE_NON_FATAL;
1352 gwlan_logging.log_complete.is_fatal = WLAN_LOG_INDICATOR_UNUSED;
1353 gwlan_logging.log_complete.is_report_in_progress = false;
1354 gwlan_logging.log_complete.reason_code = WLAN_LOG_REASON_CODE_UNUSED;
1355
1356 spin_lock_init(&gwlan_logging.bug_report_lock);
1357}
1358
1359int wlan_set_log_completion(uint32 is_fatal,
1360 uint32 indicator,
1361 uint32 reason_code)
1362{
1363 unsigned long flags;
1364
1365 spin_lock_irqsave(&gwlan_logging.bug_report_lock, flags);
1366 gwlan_logging.log_complete.indicator = indicator;
1367 gwlan_logging.log_complete.is_fatal = is_fatal;
1368 gwlan_logging.log_complete.is_report_in_progress = true;
1369 gwlan_logging.log_complete.reason_code = reason_code;
1370 spin_unlock_irqrestore(&gwlan_logging.bug_report_lock, flags);
Sachin Ahuja715aafc2015-07-21 23:35:10 +05301371 return 0;
1372}
1373void wlan_get_log_completion(uint32 *is_fatal,
1374 uint32 *indicator,
1375 uint32 *reason_code)
1376{
1377 unsigned long flags;
1378
1379 spin_lock_irqsave(&gwlan_logging.bug_report_lock, flags);
1380 *indicator = gwlan_logging.log_complete.indicator;
1381 *is_fatal = gwlan_logging.log_complete.is_fatal;
1382 *reason_code = gwlan_logging.log_complete.reason_code;
1383 gwlan_logging.log_complete.is_report_in_progress = false;
Sachin Ahuja715aafc2015-07-21 23:35:10 +05301384 spin_unlock_irqrestore(&gwlan_logging.bug_report_lock, flags);
Sachin Ahuja715aafc2015-07-21 23:35:10 +05301385}
Sachin Ahujac08f72a2015-09-22 15:25:47 +05301386
Sachin Ahuja715aafc2015-07-21 23:35:10 +05301387bool wlan_is_log_report_in_progress(void)
1388{
1389 return gwlan_logging.log_complete.is_report_in_progress;
1390}
1391
Sachin Ahujac08f72a2015-09-22 15:25:47 +05301392
Sachin Ahuja715aafc2015-07-21 23:35:10 +05301393void wlan_reset_log_report_in_progress(void)
1394{
1395 unsigned long flags;
1396
1397 spin_lock_irqsave(&gwlan_logging.bug_report_lock, flags);
1398 gwlan_logging.log_complete.is_report_in_progress = false;
1399 spin_unlock_irqrestore(&gwlan_logging.bug_report_lock, flags);
1400}
1401
1402
1403void wlan_deinit_log_completion(void)
1404{
1405 return;
1406}
1407
1408
Sushant Kaushik33200572015-08-05 16:46:20 +05301409int wlan_logging_sock_activate_svc(int log_fe_to_console, int num_buf,
1410 int pkt_stats_enabled, int pkt_stats_buff)
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301411{
Sushant Kaushik33200572015-08-05 16:46:20 +05301412 int i, j = 0;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301413 unsigned long irq_flag;
Sushant Kaushik33200572015-08-05 16:46:20 +05301414 bool failure = FALSE;
1415
1416 pr_info("%s: Initalizing FEConsoleLog = %d NumBuff = %d\n",
1417 __func__, log_fe_to_console, num_buf);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301418
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301419 gapp_pid = INVALID_PID;
1420
Vinay Krishna Eranna0b112622014-04-21 20:17:57 +05301421 gplog_msg = (struct log_msg *) vmalloc(
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301422 num_buf * sizeof(struct log_msg));
1423 if (!gplog_msg) {
1424 pr_err("%s: Could not allocate memory\n", __func__);
1425 return -ENOMEM;
1426 }
1427
1428 vos_mem_zero(gplog_msg, (num_buf * sizeof(struct log_msg)));
1429
1430 gwlan_logging.log_fe_to_console = !!log_fe_to_console;
1431 gwlan_logging.num_buf = num_buf;
1432
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301433 spin_lock_irqsave(&gwlan_logging.spin_lock, irq_flag);
1434 INIT_LIST_HEAD(&gwlan_logging.free_list);
1435 INIT_LIST_HEAD(&gwlan_logging.filled_list);
1436
1437 for (i = 0; i < num_buf; i++) {
1438 list_add(&gplog_msg[i].node, &gwlan_logging.free_list);
1439 gplog_msg[i].index = i;
1440 }
1441 gwlan_logging.pcur_node = (struct log_msg *)
1442 (gwlan_logging.free_list.next);
1443 list_del_init(gwlan_logging.free_list.next);
1444 spin_unlock_irqrestore(&gwlan_logging.spin_lock, irq_flag);
Sushant Kaushik33200572015-08-05 16:46:20 +05301445 if(pkt_stats_enabled)
1446 {
1447 pr_info("%s: Initalizing Pkt stats pkt_stats_buff = %d\n",
1448 __func__, pkt_stats_buff);
1449 pkt_stats_buffers = (struct pkt_stats_msg *) kzalloc(
1450 pkt_stats_buff * sizeof(struct pkt_stats_msg), GFP_KERNEL);
1451 if (!pkt_stats_buffers) {
1452 pr_err("%s: Could not allocate memory for Pkt stats\n", __func__);
1453 failure = TRUE;
1454 goto err;
1455 }
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301456
Sushant Kaushik33200572015-08-05 16:46:20 +05301457 gwlan_logging.pkt_stat_num_buf = pkt_stats_buff;
1458
1459 gwlan_logging.pkt_stats_msg_idx = 0;
1460 INIT_LIST_HEAD(&gwlan_logging.pkt_stat_free_list);
1461 INIT_LIST_HEAD(&gwlan_logging.pkt_stat_filled_list);
1462
1463 for (i = 0; i < pkt_stats_buff; i++) {
1464 pkt_stats_buffers[i].skb= dev_alloc_skb(MAX_PKTSTATS_LOG_LENGTH);
1465 if (pkt_stats_buffers[i].skb == NULL)
1466 {
1467 pr_err("%s: Memory alloc failed for skb",__func__);
1468 /* free previously allocated skb and return;*/
1469 for (j = 0; j<i ; j++)
1470 {
1471 dev_kfree_skb(pkt_stats_buffers[j].skb);
1472 }
1473 spin_lock_irqsave(&gwlan_logging.spin_lock, irq_flag);
1474 vos_mem_free(pkt_stats_buffers);
1475 pkt_stats_buffers = NULL;
1476 spin_unlock_irqrestore(&gwlan_logging.spin_lock, irq_flag);
1477 failure = TRUE;
1478 goto err;
1479 }
1480 list_add(&pkt_stats_buffers[i].node,
1481 &gwlan_logging.pkt_stat_free_list);
1482
1483 }
1484 gwlan_logging.pkt_stats_pcur_node = (struct pkt_stats_msg *)
1485 (gwlan_logging.pkt_stat_free_list.next);
1486 list_del_init(gwlan_logging.pkt_stat_free_list.next);
1487 gwlan_logging.pkt_stats_enabled = TRUE;
1488 }
1489err:
1490 if (failure)
1491 gwlan_logging.pkt_stats_enabled = false;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301492 init_waitqueue_head(&gwlan_logging.wait_queue);
1493 gwlan_logging.exit = false;
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301494 clear_bit(HOST_LOG_POST_MASK, &gwlan_logging.event_flag);
Siddharth Bhalec0b72c2015-05-12 21:35:54 +05301495 clear_bit(LOGGER_MGMT_DATA_PKT_POST_MASK, &gwlan_logging.event_flag);
Sachin Ahuja715aafc2015-07-21 23:35:10 +05301496 clear_bit(LOGGER_FW_LOG_PKT_POST_MASK, &gwlan_logging.event_flag);
1497 clear_bit(LOGGER_FATAL_EVENT_POST_MASK, &gwlan_logging.event_flag);
Sushant Kaushik33200572015-08-05 16:46:20 +05301498 clear_bit(HOST_PKT_STATS_POST_MASK, &gwlan_logging.event_flag);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301499 init_completion(&gwlan_logging.shutdown_comp);
1500 gwlan_logging.thread = kthread_create(wlan_logging_thread, NULL,
1501 "wlan_logging_thread");
1502 if (IS_ERR(gwlan_logging.thread)) {
1503 pr_err("%s: Could not Create LogMsg Thread Controller",
1504 __func__);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05301505 spin_lock_irqsave(&gwlan_logging.spin_lock, irq_flag);
Vinay Krishna Eranna6c158fa2014-05-13 00:42:41 +05301506 vfree(gplog_msg);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05301507 gplog_msg = NULL;
1508 gwlan_logging.pcur_node = NULL;
1509 spin_unlock_irqrestore(&gwlan_logging.spin_lock, irq_flag);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301510 return -ENOMEM;
1511 }
1512 wake_up_process(gwlan_logging.thread);
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301513 gwlan_logging.is_active = true;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301514
1515 nl_srv_register(ANI_NL_MSG_LOG, wlan_logging_proc_sock_rx_msg);
1516
Sushant Kaushik9cb1c9c2015-06-23 11:57:10 +05301517 //Broadcast SVC ready message to logging app/s running
1518 wlan_logging_srv_nl_ready_indication();
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301519 return 0;
1520}
1521
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301522int wlan_logging_flush_pkt_queue(void)
1523{
1524 vos_pkt_t *pkt_queue_head;
1525 unsigned long flags;
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301526 spin_lock_irqsave(&gwlan_logging.data_mgmt_pkt_lock, flags);
1527 if (NULL != gwlan_logging.data_mgmt_pkt_queue) {
1528 pkt_queue_head = gwlan_logging.data_mgmt_pkt_queue;
1529 gwlan_logging.data_mgmt_pkt_queue = NULL;
1530 gwlan_logging.pkt_drop_cnt = 0;
1531 gwlan_logging.data_mgmt_pkt_qcnt = 0;
1532 spin_unlock_irqrestore(&gwlan_logging.data_mgmt_pkt_lock,
1533 flags);
1534 vos_pkt_return_packet(pkt_queue_head);
1535 } else {
1536 spin_unlock_irqrestore(&gwlan_logging.data_mgmt_pkt_lock,
1537 flags);
1538 }
1539
Siddharth Bhalec0b72c2015-05-12 21:35:54 +05301540 spin_lock_irqsave(&gwlan_logging.fw_log_pkt_lock, flags);
1541 if (NULL != gwlan_logging.fw_log_pkt_queue) {
1542 pkt_queue_head = gwlan_logging.fw_log_pkt_queue;
1543 gwlan_logging.fw_log_pkt_queue = NULL;
1544 gwlan_logging.fw_log_pkt_drop_cnt = 0;
1545 gwlan_logging.fw_log_pkt_qcnt = 0;
1546 spin_unlock_irqrestore(&gwlan_logging.fw_log_pkt_lock,
1547 flags);
1548 vos_pkt_return_packet(pkt_queue_head);
1549 } else {
1550 spin_unlock_irqrestore(&gwlan_logging.fw_log_pkt_lock,
1551 flags);
1552 }
c_manjeecfd1efb2015-09-25 19:32:34 +05301553 spin_lock_irqsave(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
1554 if (NULL != gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_queue) {
1555 pkt_queue_head = gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_queue;
1556 spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock,
1557 flags);
1558 vos_pkt_return_packet(pkt_queue_head);
1559 wlan_free_fwr_mem_dump_buffer();
1560 } else {
1561 spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock,
1562 flags);
1563 }
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301564 return 0;
1565}
1566
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301567int wlan_logging_sock_deactivate_svc(void)
1568{
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05301569 unsigned long irq_flag;
Sushant Kaushik33200572015-08-05 16:46:20 +05301570 int i;
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05301571
1572 if (!gplog_msg)
1573 return 0;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301574
1575 nl_srv_unregister(ANI_NL_MSG_LOG, wlan_logging_proc_sock_rx_msg);
1576 clear_default_logtoapp_log_level();
1577 gapp_pid = INVALID_PID;
1578
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301579 INIT_COMPLETION(gwlan_logging.shutdown_comp);
Vinay Krishna Erannad1d284f2014-10-28 20:09:55 +05301580 gwlan_logging.exit = true;
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301581 gwlan_logging.is_active = false;
Sushant Kaushik215778f2015-05-21 14:05:36 +05301582 vos_set_multicast_logging(0);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301583 wake_up_interruptible(&gwlan_logging.wait_queue);
Vinay Krishna Erannad1d284f2014-10-28 20:09:55 +05301584 wait_for_completion(&gwlan_logging.shutdown_comp);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301585
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05301586 spin_lock_irqsave(&gwlan_logging.spin_lock, irq_flag);
Vinay Krishna Eranna0b112622014-04-21 20:17:57 +05301587 vfree(gplog_msg);
Sushant Kaushik215778f2015-05-21 14:05:36 +05301588 gplog_msg = NULL;
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05301589 gwlan_logging.pcur_node = NULL;
1590 spin_unlock_irqrestore(&gwlan_logging.spin_lock, irq_flag);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301591
Sushant Kaushik33200572015-08-05 16:46:20 +05301592 spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, irq_flag);
1593 /* free allocated skb */
1594 for (i = 0; i < gwlan_logging.pkt_stat_num_buf; i++)
1595 {
1596 if (pkt_stats_buffers[i].skb)
1597 dev_kfree_skb(pkt_stats_buffers[i].skb);
1598 }
1599 if(pkt_stats_buffers)
1600 vos_mem_free(pkt_stats_buffers);
1601 pkt_stats_buffers = NULL;
1602 gwlan_logging.pkt_stats_pcur_node = NULL;
1603 gwlan_logging.pkt_stats_enabled = false;
1604 spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, irq_flag);
1605
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301606 wlan_logging_flush_pkt_queue();
1607
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301608 return 0;
1609}
1610
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05301611int wlan_logging_sock_init_svc(void)
1612{
1613 spin_lock_init(&gwlan_logging.spin_lock);
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301614 spin_lock_init(&gwlan_logging.data_mgmt_pkt_lock);
Siddharth Bhalec0b72c2015-05-12 21:35:54 +05301615 spin_lock_init(&gwlan_logging.fw_log_pkt_lock);
c_manjeecfd1efb2015-09-25 19:32:34 +05301616 spin_lock_init(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock);
Sushant Kaushik33200572015-08-05 16:46:20 +05301617 spin_lock_init(&gwlan_logging.pkt_stats_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05301618 gapp_pid = INVALID_PID;
1619 gwlan_logging.pcur_node = NULL;
Sushant Kaushik33200572015-08-05 16:46:20 +05301620 gwlan_logging.pkt_stats_pcur_node= NULL;
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05301621
Sachin Ahuja715aafc2015-07-21 23:35:10 +05301622 wlan_init_log_completion();
1623
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05301624 return 0;
1625}
1626
1627int wlan_logging_sock_deinit_svc(void)
1628{
1629 gwlan_logging.pcur_node = NULL;
Sushant Kaushik33200572015-08-05 16:46:20 +05301630 gwlan_logging.pkt_stats_pcur_node = NULL;
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05301631 gapp_pid = INVALID_PID;
1632
Sachin Ahuja715aafc2015-07-21 23:35:10 +05301633 wlan_deinit_log_completion();
1634 return 0;
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05301635}
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301636
Siddharth Bhalec0b72c2015-05-12 21:35:54 +05301637int wlan_queue_data_mgmt_pkt_for_app(vos_pkt_t *pPacket)
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301638{
1639 unsigned long flags;
1640 vos_pkt_t *next_pkt;
1641 vos_pkt_t *free_pkt;
1642 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1643
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301644 spin_lock_irqsave(&gwlan_logging.data_mgmt_pkt_lock, flags);
Siddharth Bhalec0b72c2015-05-12 21:35:54 +05301645 if (gwlan_logging.data_mgmt_pkt_qcnt >= LOGGER_MAX_DATA_MGMT_PKT_Q_LEN) {
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301646 status = vos_pkt_walk_packet_chain(
1647 gwlan_logging.data_mgmt_pkt_queue, &next_pkt, TRUE);
1648 /*both "success" and "empty" are acceptable results*/
1649 if (!((status == VOS_STATUS_SUCCESS) ||
1650 (status == VOS_STATUS_E_EMPTY))) {
1651 ++gwlan_logging.pkt_drop_cnt;
1652 spin_unlock_irqrestore(
1653 &gwlan_logging.data_mgmt_pkt_lock, flags);
Siddharth Bhalec0b72c2015-05-12 21:35:54 +05301654 pr_err("%s: Failure walking packet chain", __func__);
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301655 /*keep returning pkts to avoid low resource cond*/
1656 vos_pkt_return_packet(pPacket);
1657 return VOS_STATUS_E_FAILURE;
1658 }
1659
1660 free_pkt = gwlan_logging.data_mgmt_pkt_queue;
1661 gwlan_logging.data_mgmt_pkt_queue = next_pkt;
1662 /*returning head of pkt queue. latest pkts are important*/
1663 --gwlan_logging.data_mgmt_pkt_qcnt;
1664 spin_unlock_irqrestore(&gwlan_logging.data_mgmt_pkt_lock,
1665 flags);
1666 vos_pkt_return_packet(free_pkt);
1667 } else {
1668 spin_unlock_irqrestore(&gwlan_logging.data_mgmt_pkt_lock,
1669 flags);
1670 }
1671
1672 spin_lock_irqsave(&gwlan_logging.data_mgmt_pkt_lock, flags);
1673
1674 if (gwlan_logging.data_mgmt_pkt_queue) {
1675 vos_pkt_chain_packet(gwlan_logging.data_mgmt_pkt_queue,
1676 pPacket, TRUE);
1677 } else {
1678 gwlan_logging.data_mgmt_pkt_queue = pPacket;
1679 }
1680 ++gwlan_logging.data_mgmt_pkt_qcnt;
1681
1682 spin_unlock_irqrestore(&gwlan_logging.data_mgmt_pkt_lock, flags);
1683
Siddharth Bhalec0b72c2015-05-12 21:35:54 +05301684 set_bit(LOGGER_MGMT_DATA_PKT_POST_MASK, &gwlan_logging.event_flag);
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301685 wake_up_interruptible(&gwlan_logging.wait_queue);
1686
1687 return VOS_STATUS_SUCCESS;
1688}
1689
Sushant Kaushik215778f2015-05-21 14:05:36 +05301690/**
1691 * wlan_logging_set_log_level() - Set the logging level
1692 *
1693 * This function is used to set the logging level of host debug messages
1694 *
1695 * Return: None
1696 */
1697void wlan_logging_set_log_level(void)
1698{
1699 set_default_logtoapp_log_level();
1700}
1701
Siddharth Bhalec0b72c2015-05-12 21:35:54 +05301702int wlan_queue_fw_log_pkt_for_app(vos_pkt_t *pPacket)
1703{
1704 unsigned long flags;
1705 vos_pkt_t *next_pkt;
1706 vos_pkt_t *free_pkt;
1707 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1708
1709 spin_lock_irqsave(&gwlan_logging.fw_log_pkt_lock, flags);
1710 if (gwlan_logging.fw_log_pkt_qcnt >= LOGGER_MAX_FW_LOG_PKT_Q_LEN) {
1711 status = vos_pkt_walk_packet_chain(
1712 gwlan_logging.fw_log_pkt_queue, &next_pkt, TRUE);
1713 /*both "success" and "empty" are acceptable results*/
1714 if (!((status == VOS_STATUS_SUCCESS) ||
1715 (status == VOS_STATUS_E_EMPTY))) {
1716 ++gwlan_logging.fw_log_pkt_drop_cnt;
1717 spin_unlock_irqrestore(
1718 &gwlan_logging.fw_log_pkt_lock, flags);
1719 pr_err("%s: Failure walking packet chain", __func__);
1720 /*keep returning pkts to avoid low resource cond*/
1721 vos_pkt_return_packet(pPacket);
1722 return VOS_STATUS_E_FAILURE;
1723 }
1724
1725 free_pkt = gwlan_logging.fw_log_pkt_queue;
1726 gwlan_logging.fw_log_pkt_queue = next_pkt;
1727 /*returning head of pkt queue. latest pkts are important*/
1728 --gwlan_logging.fw_log_pkt_qcnt;
1729 spin_unlock_irqrestore(&gwlan_logging.fw_log_pkt_lock,
1730 flags);
1731 vos_pkt_return_packet(free_pkt);
1732 } else {
1733 spin_unlock_irqrestore(&gwlan_logging.fw_log_pkt_lock,
1734 flags);
1735 }
1736
1737 spin_lock_irqsave(&gwlan_logging.fw_log_pkt_lock, flags);
1738
1739 if (gwlan_logging.fw_log_pkt_queue) {
1740 vos_pkt_chain_packet(gwlan_logging.fw_log_pkt_queue,
1741 pPacket, TRUE);
1742 } else {
1743 gwlan_logging.fw_log_pkt_queue = pPacket;
1744 }
1745 ++gwlan_logging.fw_log_pkt_qcnt;
1746
1747 spin_unlock_irqrestore(&gwlan_logging.fw_log_pkt_lock, flags);
1748
1749 set_bit(LOGGER_FW_LOG_PKT_POST_MASK, &gwlan_logging.event_flag);
1750 wake_up_interruptible(&gwlan_logging.wait_queue);
1751
1752 return VOS_STATUS_SUCCESS;
1753}
1754
c_manjeecfd1efb2015-09-25 19:32:34 +05301755int wlan_queue_fw_mem_dump_for_app(vos_pkt_t *pPacket)
1756{
1757 unsigned long flags;
1758 vos_pkt_t *next_pkt;
1759 vos_pkt_t *free_pkt;
1760 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1761
1762 spin_lock_irqsave(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
1763 if (gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_pkt_qcnt >= LOGGER_MAX_FW_MEM_DUMP_PKT_Q_LEN) {
1764 status = vos_pkt_walk_packet_chain(
1765 gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_queue, &next_pkt, TRUE);
1766 /*both "success" and "empty" are acceptable results*/
1767 if (!((status == VOS_STATUS_SUCCESS) ||
1768 (status == VOS_STATUS_E_EMPTY))) {
1769 spin_unlock_irqrestore(
1770 &gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
1771 pr_err("%s: Failure walking packet chain", __func__);
1772 /*keep returning pkts to avoid low resource cond*/
1773 vos_pkt_return_packet(pPacket);
1774 return VOS_STATUS_E_FAILURE;
1775 }
1776
1777 free_pkt = gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_queue;
1778 gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_queue = next_pkt;
1779 /*returning head of pkt queue. latest pkts are important*/
1780 --gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_pkt_qcnt;
1781 ++gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_pkt_drop_cnt ;
1782 spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock,
1783 flags);
1784 pr_info("%s : fw mem_dump pkt cnt --> %d\n" ,__func__, gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_pkt_drop_cnt);
1785 vos_pkt_return_packet(free_pkt);
1786 } else {
1787 spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock,
1788 flags);
1789 }
1790
1791 spin_lock_irqsave(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
1792
1793 if (gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_queue) {
1794 vos_pkt_chain_packet(gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_queue,
1795 pPacket, TRUE);
1796 } else {
1797 gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_queue = pPacket;
1798 }
1799 ++gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_pkt_qcnt;
1800
1801 spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
1802
1803 set_bit(LOGGER_FW_MEM_DUMP_PKT_POST_MASK, &gwlan_logging.event_flag);
1804 wake_up_interruptible(&gwlan_logging.wait_queue);
1805
1806 return VOS_STATUS_SUCCESS;
1807}
1808
Siddharth Bhalec0b72c2015-05-12 21:35:54 +05301809int wlan_queue_logpkt_for_app(vos_pkt_t *pPacket, uint32 pkt_type)
1810{
1811 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1812
1813 if (pPacket == NULL) {
1814 pr_err("%s: Null param", __func__);
1815 VOS_ASSERT(0);
1816 return VOS_STATUS_E_FAILURE;
1817 }
1818
1819 if (gwlan_logging.is_active == false) {
1820 /*return all packets queued*/
1821 wlan_logging_flush_pkt_queue();
1822
1823 /*return currently received pkt*/
1824 vos_pkt_return_packet(pPacket);
1825 return VOS_STATUS_E_FAILURE;
1826 }
1827
1828 switch (pkt_type) {
Hanumantha Reddy Pothulae00a7e22015-09-15 20:11:30 +05301829 case WLAN_MGMT_FRAME_LOGS:
Siddharth Bhalec0b72c2015-05-12 21:35:54 +05301830 status = wlan_queue_data_mgmt_pkt_for_app(pPacket);
1831 break;
1832
Hanumantha Reddy Pothulae00a7e22015-09-15 20:11:30 +05301833 case WLAN_FW_LOGS:
Siddharth Bhalec0b72c2015-05-12 21:35:54 +05301834 status = wlan_queue_fw_log_pkt_for_app(pPacket);
1835 break;
c_manjeecfd1efb2015-09-25 19:32:34 +05301836 case WLAN_FW_MEMORY_DUMP:
1837 status = wlan_queue_fw_mem_dump_for_app(pPacket);
1838 break;
Siddharth Bhalec0b72c2015-05-12 21:35:54 +05301839
1840 default:
1841 pr_info("%s: Unknown pkt received %d", __func__, pkt_type);
1842 status = VOS_STATUS_E_INVAL;
1843 break;
1844 };
1845
1846 return status;
1847}
Sushant Kaushik215778f2015-05-21 14:05:36 +05301848
Sachin Ahuja715aafc2015-07-21 23:35:10 +05301849void wlan_process_done_indication(uint8 type, uint32 reason_code)
1850{
Sachin Ahujac08f72a2015-09-22 15:25:47 +05301851<<<<<<< HEAD
Hanumantha Reddy Pothulae00a7e22015-09-15 20:11:30 +05301852 if ((type == WLAN_FW_LOGS) && (wlan_is_log_report_in_progress() == TRUE))
Sachin Ahuja715aafc2015-07-21 23:35:10 +05301853 {
1854 pr_info("%s: Setting LOGGER_FATAL_EVENT\n", __func__);
1855 set_bit(LOGGER_FATAL_EVENT_POST_MASK, &gwlan_logging.event_flag);
c_manjeecfd1efb2015-09-25 19:32:34 +05301856 wake_up_interruptible(&gwlan_logging.wait_queue);
Sachin Ahuja715aafc2015-07-21 23:35:10 +05301857 }
c_manjeecfd1efb2015-09-25 19:32:34 +05301858 if(type == WLAN_FW_MEMORY_DUMP)
1859 {
1860 pr_info("%s: Setting FW MEM DUMP LOGGER event\n", __func__);
1861 set_bit(LOGGER_FW_MEM_DUMP_PKT_POST_DONE_MASK, &gwlan_logging.event_flag);
1862 wake_up_interruptible(&gwlan_logging.wait_queue);
1863 }
1864
Sachin Ahujac08f72a2015-09-22 15:25:47 +05301865=======
1866 if ((type == WLAN_FW_LOGS) && reason_code)
1867 {
1868 if(wlan_is_log_report_in_progress() == TRUE)
1869 {
1870 pr_info("%s : Setting LOGGER_FATAL_EVENT\n", __func__);
1871 set_bit(LOGGER_FATAL_EVENT_POST_MASK, &gwlan_logging.event_flag);
1872 wake_up_interruptible(&gwlan_logging.wait_queue);
1873 }
1874 else
1875 {
1876 /*Firmware Initiated*/
1877 pr_info("%s : FW triggered Fatal Event, reason_code : %d\n", __func__,
1878 reason_code);
1879 wlan_set_log_completion(WLAN_LOG_TYPE_FATAL,
1880 WLAN_LOG_INDICATOR_FIRMWARE,
1881 reason_code);
1882 set_bit(LOGGER_FATAL_EVENT_POST_MASK, &gwlan_logging.event_flag);
1883 wake_up_interruptible(&gwlan_logging.wait_queue);
1884 }
1885 }
1886>>>>>>> 6ea54f9... wlan: Handle fatal event triggered from framework and FW
Sachin Ahuja715aafc2015-07-21 23:35:10 +05301887}
1888
Abhishek Singh880d7122015-08-26 16:23:04 +05301889/**
1890 * wlan_is_logger_thread()- Check if threadid is
1891 * of logger thread
1892 *
1893 * @threadId: passed threadid
1894 *
1895 * This function is called to check if threadid is
1896 * of logger thread.
1897 *
1898 * Return: true if threadid is of logger thread.
1899 */
1900bool wlan_is_logger_thread(int threadId)
1901{
1902 return ((gwlan_logging.thread) &&
1903 (threadId == gwlan_logging.thread->pid));
1904}
1905
1906/**
1907 * wlan_logging_reset_thread_stuck_count()- Callback to
1908 * probe msg sent to Threads.
1909 *
1910 * @threadId: passed threadid
1911 *
1912 * This function is called to by the thread after
1913 * processing the probe msg, with their own thread id.
1914 *
1915 * Return: void.
1916 */
1917void wlan_logging_reset_thread_stuck_count(int threadId)
1918{
1919 unsigned long flags;
1920
1921 spin_lock_irqsave(&gwlan_logging.thread_stuck_lock, flags);
1922 if (vos_sched_is_mc_thread(threadId))
1923 gwlan_logging.mcThreadStuckCount = 0;
1924 else if (vos_sched_is_tx_thread(threadId))
1925 gwlan_logging.txThreadStuckCount = 0;
1926 else if (vos_sched_is_rx_thread(threadId))
1927 gwlan_logging.rxThreadStuckCount = 0;
1928
1929 spin_unlock_irqrestore(&gwlan_logging.thread_stuck_lock, flags);
1930}
1931
Sachin Ahujac08f72a2015-09-22 15:25:47 +05301932<<<<<<< HEAD
c_manjeecfd1efb2015-09-25 19:32:34 +05301933int wlan_fwr_mem_dump_buffer_allocation(void)
1934{
1935 /*Allocate the dump memory as reported by fw.
1936 or if feature not supported just report to the user */
1937 if(gwlan_logging.fw_mem_dump_ctx.fw_dump_max_size <= 0)
1938 {
1939 pr_err("%s: fw_mem_dump_req not supported by firmware", __func__);
1940 return -EFAULT;
1941 }
1942 gwlan_logging.fw_mem_dump_ctx.fw_dump_start_loc =
1943 (uint8 *)vos_mem_vmalloc(gwlan_logging.fw_mem_dump_ctx.fw_dump_max_size);
1944 gwlan_logging.fw_mem_dump_ctx.fw_dump_current_loc = gwlan_logging.fw_mem_dump_ctx.fw_dump_start_loc;
1945 if(NULL == gwlan_logging.fw_mem_dump_ctx.fw_dump_start_loc)
1946 {
1947 pr_err("%s: fw_mem_dump_req alloc failed for size %d bytes", __func__,gwlan_logging.fw_mem_dump_ctx.fw_dump_max_size);
1948 return -ENOMEM;
1949 }
1950 return 0;
1951}
1952
1953/*set the current fw mem dump state*/
1954void wlan_set_fwr_mem_dump_state(enum FW_MEM_DUMP_STATE fw_mem_dump_state)
1955{
1956 unsigned long flags;
1957 spin_lock_irqsave(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
1958 gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_status = fw_mem_dump_state;
1959 spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
1960}
1961/*check for new request validity and free memory if present from previous request */
1962bool wlan_fwr_mem_dump_test_and_set_write_allowed_bit(){
1963 unsigned long flags;
1964 bool ret = false;
1965 bool write_done = false;
1966 spin_lock_irqsave(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
1967
1968 if(gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_status == FW_MEM_DUMP_IDLE){
1969 ret = true;
1970 gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_status = FW_MEM_DUMP_WRITE_IN_PROGRESS;
1971 }
1972 else if(gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_status == FW_MEM_DUMP_WRITE_DONE){
1973 ret = true;
1974 write_done = true;
1975 gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_status = FW_MEM_DUMP_WRITE_IN_PROGRESS;
1976 }
1977 spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
1978 pr_info("%s:fw mem dump state --> %d ", __func__,gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_status);
1979
1980 if(write_done)
1981 wlan_free_fwr_mem_dump_buffer();
1982 return ret;
1983}
1984
1985bool wlan_fwr_mem_dump_test_and_set_read_allowed_bit(){
1986 unsigned long flags;
1987 bool ret=false;
1988 spin_lock_irqsave(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
1989 if(gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_status == FW_MEM_DUMP_WRITE_DONE ||
1990 gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_status == FW_MEM_DUMP_READ_IN_PROGRESS ){
1991 ret = true;
1992 gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_status = FW_MEM_DUMP_READ_IN_PROGRESS;
1993 }
1994 spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
1995 pr_info("%s:fw mem dump state --> %d ", __func__,gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_status);
1996
1997 return ret;
1998}
1999size_t wlan_fwr_mem_dump_fsread_handler(char __user *buf,
2000 size_t count, loff_t *pos)
2001{
2002 if (buf == NULL || gwlan_logging.fw_mem_dump_ctx.fw_dump_start_loc == NULL)
2003 {
2004 pr_err("%s : start loc : %p buf : %p ",__func__,gwlan_logging.fw_mem_dump_ctx.fw_dump_start_loc,buf);
2005 return 0;
2006 }
2007
2008 if (*pos < 0) {
2009 pr_err("Invalid start offset for memdump read");
2010 return 0;
2011 } else if (*pos >= gwlan_logging.fw_mem_dump_ctx.fw_dump_max_size || !count) {
2012 pr_err("No more data to copy");
2013 return 0;
2014 } else if (count > gwlan_logging.fw_mem_dump_ctx.fw_dump_max_size - *pos) {
2015 count = gwlan_logging.fw_mem_dump_ctx.fw_dump_max_size - *pos;
2016 }
2017 if (copy_to_user(buf, gwlan_logging.fw_mem_dump_ctx.fw_dump_start_loc, count)) {
2018 pr_err("copy to user space failed");
2019 return 0;
2020 }
2021
2022 /* offset(pos) should be updated here based on the copy done*/
2023 *pos += count;
2024
2025 return count;
2026}
2027
2028void wlan_free_fwr_mem_dump_buffer (void )
2029{
2030 unsigned long flags;
2031 void * tmp = NULL;
2032 spin_lock_irqsave(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
2033 tmp = gwlan_logging.fw_mem_dump_ctx.fw_dump_start_loc;
2034 gwlan_logging.fw_mem_dump_ctx.fw_dump_start_loc = NULL;
2035 gwlan_logging.fw_mem_dump_ctx.fw_dump_current_loc = NULL;
2036 spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
2037 // Don't set fw_dump_max_size to 0, only free the buffera
2038 if(tmp != NULL)
2039 vos_mem_vfree((void *)tmp);
2040}
2041
2042void wlan_store_fwr_mem_dump_size(uint32 dump_size)
2043{
2044 unsigned long flags;
2045 spin_lock_irqsave(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
2046 //Store the dump size
2047 gwlan_logging.fw_mem_dump_ctx.fw_dump_max_size = dump_size;
2048 spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
2049}
2050/**
2051 * wlan_indicate_mem_dump_complete() - When H2H for mem
2052 * dump finish invoke the handler.
2053 *
2054 * This is a handler used to indicate user space about the
2055 * availability for firmware memory dump via vendor event.
2056 *
2057 * Return: None
2058 */
2059void wlan_indicate_mem_dump_complete(bool status )
2060{
2061 hdd_context_t *hdd_ctx;
2062 void *vos_ctx;
2063 int ret;
2064 struct sk_buff *skb = NULL;
2065 unsigned long flags;
2066
2067 vos_ctx = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
2068 if (!vos_ctx) {
2069 pr_err("Invalid VOS context");
2070 return;
2071 }
2072
2073 hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
2074 if(!hdd_ctx) {
2075 pr_err("Invalid HDD context");
2076 return;
2077 }
2078
2079 ret = wlan_hdd_validate_context(hdd_ctx);
2080 if (0 != ret) {
2081 pr_err("HDD context is not valid");
2082 return;
2083 }
2084
2085 spin_lock_irqsave(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
2086 /*Chnage fw memory dump to indicate write done*/
2087 gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_status = FW_MEM_DUMP_WRITE_DONE;
2088 /*reset dropped packet count upon completion of this request*/
2089 gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_pkt_drop_cnt = 0;
2090 spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
2091
2092 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
2093#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
2094 NULL,
2095#endif
2096 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN,
2097 QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX,
2098 GFP_KERNEL);
2099
2100 if (!skb) {
2101 pr_err("cfg80211_vendor_event_alloc failed");
2102 return;
2103 }
2104 if(status)
2105 {
2106 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MEMDUMP_SIZE,
2107 gwlan_logging.fw_mem_dump_ctx.fw_dump_max_size)) {
2108 pr_err("nla put fail");
2109 goto nla_put_failure;
2110 }
2111 }
2112 else
2113 {
2114 pr_err("memdump failed.Returning size 0 to user");
2115 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MEMDUMP_SIZE,
2116 0)) {
2117 pr_err("nla put fail");
2118 goto nla_put_failure;
2119 }
2120 }
2121
2122 cfg80211_vendor_event(skb, GFP_KERNEL);
2123 pr_info("Memdump event sent successfully to user space : recvd size %d",(int)(gwlan_logging.fw_mem_dump_ctx.fw_dump_current_loc - gwlan_logging.fw_mem_dump_ctx.fw_dump_start_loc));
2124 return;
2125
2126nla_put_failure:
2127 kfree_skb(skb);
2128 return;
2129}
Sachin Ahujac08f72a2015-09-22 15:25:47 +05302130=======
2131#ifdef FEATURE_WLAN_DIAG_SUPPORT
2132/**
2133 * wlan_report_log_completion() - Report bug report completion to userspace
2134 * @is_fatal: Type of event, fatal or not
2135 * @indicator: Source of bug report, framework/host/firmware
2136 * @reason_code: Reason for triggering bug report
2137 *
2138 * This function is used to report the bug report completion to userspace
2139 *
2140 * Return: None
2141 */
2142void wlan_report_log_completion(uint32_t is_fatal,
2143 uint32_t indicator,
2144 uint32_t reason_code)
2145{
2146 WLAN_VOS_DIAG_EVENT_DEF(wlan_diag_event,
2147 struct vos_event_wlan_log_complete);
2148
2149 wlan_diag_event.is_fatal = is_fatal;
2150 wlan_diag_event.indicator = indicator;
2151 wlan_diag_event.reason_code = reason_code;
2152 wlan_diag_event.reserved = 0;
2153
2154 WLAN_VOS_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_LOG_COMPLETE);
2155}
2156#endif
2157>>>>>>> 6ea54f9... wlan: Handle fatal event triggered from framework and FW
c_manjeecfd1efb2015-09-25 19:32:34 +05302158
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05302159#endif /* WLAN_LOGGING_SOCK_SVC_ENABLE */