blob: da139722be898dd4cab49430aa5b5ed60f22b067 [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>
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053045
46#define LOGGING_TRACE(level, args...) \
Siddharth Bhal7bd19932015-03-03 16:54:36 +053047 VOS_TRACE(VOS_MODULE_ID_SVC, level, ## args)
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053048
49/* Global variables */
50
51#define ANI_NL_MSG_LOG_TYPE 89
Vinay Krishna Eranna8382e0e2014-06-18 19:19:58 +053052#define ANI_NL_MSG_READY_IND_TYPE 90
Siddharth Bhal7bd19932015-03-03 16:54:36 +053053#define ANI_NL_MSG_LOG_PKT_TYPE 91
Siddharth Bhalec0b72c2015-05-12 21:35:54 +053054#define ANI_NL_MSG_FW_LOG_PKT_TYPE 92
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053055#define INVALID_PID -1
56
57#define MAX_LOGMSG_LENGTH 4096
Siddharth Bhalec0b72c2015-05-12 21:35:54 +053058#define LOGGER_MGMT_DATA_PKT_POST_MASK 0x001
Siddharth Bhal7bd19932015-03-03 16:54:36 +053059#define HOST_LOG_POST_MASK 0x002
Siddharth Bhalec0b72c2015-05-12 21:35:54 +053060#define LOGGER_FW_LOG_PKT_POST_MASK 0x003
Sachin Ahuja715aafc2015-07-21 23:35:10 +053061#define LOGGER_FATAL_EVENT_POST_MASK 0x004
Siddharth Bhal7bd19932015-03-03 16:54:36 +053062
Siddharth Bhalec0b72c2015-05-12 21:35:54 +053063#define LOGGER_MAX_DATA_MGMT_PKT_Q_LEN (8)
64#define LOGGER_MAX_FW_LOG_PKT_Q_LEN (16)
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053065
Sushant Kaushik1ede3322015-07-07 17:26:50 +053066#define NL_BDCAST_RATELIMIT_INTERVAL (5*HZ)
Sushant Kaushik8ddaa382015-06-23 12:17:25 +053067#define NL_BDCAST_RATELIMIT_BURST 1
68
Ratnam Rachuric798dbe2015-07-17 11:19:44 +053069/* Qtimer Frequency */
70#define QTIMER_FREQ 19200000
71
Sushant Kaushik8ddaa382015-06-23 12:17:25 +053072static DEFINE_RATELIMIT_STATE(errCnt, \
73 NL_BDCAST_RATELIMIT_INTERVAL, \
74 NL_BDCAST_RATELIMIT_BURST);
75
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053076struct log_msg {
77 struct list_head node;
78 unsigned int radio;
79 unsigned int index;
80 /* indicates the current filled log length in logbuf */
81 unsigned int filled_length;
82 /*
83 * Buf to hold the log msg
84 * tAniHdr + log
85 */
86 char logbuf[MAX_LOGMSG_LENGTH];
87};
88
Sachin Ahuja715aafc2015-07-21 23:35:10 +053089struct logger_log_complete {
90 uint32_t is_fatal;
91 uint32_t indicator;
92 uint32_t reason_code;
93 bool is_report_in_progress;
94 bool is_flush_complete;
95};
96
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053097struct wlan_logging {
98 /* Log Fatal and ERROR to console */
99 bool log_fe_to_console;
100 /* Number of buffers to be used for logging */
101 int num_buf;
102 /* Lock to synchronize access to shared logging resource */
103 spinlock_t spin_lock;
104 /* Holds the free node which can be used for filling logs */
105 struct list_head free_list;
106 /* Holds the filled nodes which needs to be indicated to APP */
107 struct list_head filled_list;
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530108 /* Points to head of logger pkt queue */
109 vos_pkt_t *data_mgmt_pkt_queue;
110 /* Holds number of pkts in vos pkt queue */
111 unsigned int data_mgmt_pkt_qcnt;
112 /* Lock to synchronize of queue/dequeue of pkts in logger pkt queue */
113 spinlock_t data_mgmt_pkt_lock;
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530114 /* Points to head of logger fw log pkt queue */
115 vos_pkt_t *fw_log_pkt_queue;
116 /* Holds number of pkts in fw log vos pkt queue */
117 unsigned int fw_log_pkt_qcnt;
118 /* Lock to synchronize of queue/dequeue of pkts in fw log pkt queue */
119 spinlock_t fw_log_pkt_lock;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530120 /* Wait queue for Logger thread */
121 wait_queue_head_t wait_queue;
122 /* Logger thread */
123 struct task_struct *thread;
124 /* Logging thread sets this variable on exit */
125 struct completion shutdown_comp;
126 /* Indicates to logger thread to exit */
127 bool exit;
128 /* Holds number of dropped logs*/
129 unsigned int drop_count;
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530130 /* Holds number of dropped vos pkts*/
131 unsigned int pkt_drop_cnt;
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530132 /* Holds number of dropped fw log vos pkts*/
133 unsigned int fw_log_pkt_drop_cnt;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530134 /* current logbuf to which the log will be filled to */
135 struct log_msg *pcur_node;
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530136 /* Event flag used for wakeup and post indication*/
137 unsigned long event_flag;
138 /* Indicates logger thread is activated */
139 bool is_active;
Sachin Ahuja715aafc2015-07-21 23:35:10 +0530140 /* data structure for log complete event*/
141 struct logger_log_complete log_complete;
142 spinlock_t bug_report_lock;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530143};
144
145static struct wlan_logging gwlan_logging;
146static struct log_msg *gplog_msg;
147
148/* PID of the APP to log the message */
149static int gapp_pid = INVALID_PID;
Sushant Kaushik9cb1c9c2015-06-23 11:57:10 +0530150static char wlan_logging_ready[] = "WLAN LOGGING READY";
151
152/*
153 * Broadcast Logging service ready indication to any Logging application
154 * Each netlink message will have a message of type tAniMsgHdr inside.
155 */
156void wlan_logging_srv_nl_ready_indication(void)
157{
158 struct sk_buff *skb = NULL;
159 struct nlmsghdr *nlh;
160 tAniNlHdr *wnl = NULL;
161 int payload_len;
162 int err;
163 static int rate_limit;
164
165 payload_len = sizeof(tAniHdr) + sizeof(wlan_logging_ready) +
166 sizeof(wnl->radio);
167 skb = dev_alloc_skb(NLMSG_SPACE(payload_len));
168 if (NULL == skb) {
169 if (!rate_limit) {
170 LOGGING_TRACE(VOS_TRACE_LEVEL_ERROR,
171 "NLINK: skb alloc fail %s", __func__);
172 }
173 rate_limit = 1;
174 return;
175 }
176 rate_limit = 0;
177
178 nlh = nlmsg_put(skb, 0, 0, ANI_NL_MSG_LOG, payload_len,
179 NLM_F_REQUEST);
180 if (NULL == nlh) {
181 LOGGING_TRACE(VOS_TRACE_LEVEL_ERROR,
182 "%s: nlmsg_put() failed for msg size[%d]",
183 __func__, payload_len);
184 kfree_skb(skb);
185 return;
186 }
187
188 wnl = (tAniNlHdr *) nlh;
189 wnl->radio = 0;
190 wnl->wmsg.type = ANI_NL_MSG_READY_IND_TYPE;
191 wnl->wmsg.length = sizeof(wlan_logging_ready);
192 memcpy((char*)&wnl->wmsg + sizeof(tAniHdr),
193 wlan_logging_ready,
194 sizeof(wlan_logging_ready));
195
196 /* sender is in group 1<<0 */
197 NETLINK_CB(skb).dst_group = WLAN_NLINK_MCAST_GRP_ID;
198
199 /*multicast the message to all listening processes*/
200 err = nl_srv_bcast(skb);
201 if (err) {
202 LOGGING_TRACE(VOS_TRACE_LEVEL_INFO_LOW,
203 "NLINK: Ready Indication Send Fail %s, err %d",
204 __func__, err);
205 }
206 return;
207}
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530208
209/* Utility function to send a netlink message to an application
210 * in user space
211 */
212static int wlan_send_sock_msg_to_app(tAniHdr *wmsg, int radio,
213 int src_mod, int pid)
214{
215 int err = -1;
216 int payload_len;
217 int tot_msg_len;
218 tAniNlHdr *wnl = NULL;
219 struct sk_buff *skb;
220 struct nlmsghdr *nlh;
Vinay Krishna Erannab4c6a422015-03-20 18:33:47 +0530221 int wmsg_length = wmsg->length;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530222 static int nlmsg_seq;
223
224 if (radio < 0 || radio > ANI_MAX_RADIOS) {
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530225 pr_err("%s: invalid radio id [%d]",
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530226 __func__, radio);
227 return -EINVAL;
228 }
229
230 payload_len = wmsg_length + sizeof(wnl->radio);
231 tot_msg_len = NLMSG_SPACE(payload_len);
232 skb = dev_alloc_skb(tot_msg_len);
233 if (skb == NULL) {
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530234 pr_err("%s: dev_alloc_skb() failed for msg size[%d]",
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530235 __func__, tot_msg_len);
236 return -ENOMEM;
237 }
238 nlh = nlmsg_put(skb, pid, nlmsg_seq++, src_mod, payload_len,
239 NLM_F_REQUEST);
240 if (NULL == nlh) {
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530241 pr_err("%s: nlmsg_put() failed for msg size[%d]",
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530242 __func__, tot_msg_len);
243 kfree_skb(skb);
244 return -ENOMEM;
245 }
246
247 wnl = (tAniNlHdr *) nlh;
248 wnl->radio = radio;
Rajesh Babu Prathipati71e9c442014-07-01 22:08:29 +0530249 vos_mem_copy(&wnl->wmsg, wmsg, wmsg_length);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530250
251 err = nl_srv_ucast(skb, pid, MSG_DONTWAIT);
Vinay Krishna Eranna8147e702015-03-06 17:43:41 +0530252
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530253 return err;
254}
255
256static void set_default_logtoapp_log_level(void)
257{
258 vos_trace_setValue(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_ALL, VOS_TRUE);
259 vos_trace_setValue(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ALL, VOS_TRUE);
260 vos_trace_setValue(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ALL, VOS_TRUE);
261 vos_trace_setValue(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ALL, VOS_TRUE);
262 vos_trace_setValue(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ALL, VOS_TRUE);
263 vos_trace_setValue(VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ALL,
264 VOS_TRUE);
265 vos_trace_setValue(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ALL, VOS_TRUE);
Kaushik, Sushantac4fa6c2014-12-10 17:07:41 +0530266 vos_trace_setValue(VOS_MODULE_ID_PMC, VOS_TRACE_LEVEL_ALL, VOS_TRUE);
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530267 vos_trace_setValue(VOS_MODULE_ID_SVC, VOS_TRACE_LEVEL_ALL, VOS_TRUE);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530268}
269
270static void clear_default_logtoapp_log_level(void)
271{
272 int module;
273
274 for (module = 0; module < VOS_MODULE_ID_MAX; module++) {
275 vos_trace_setValue(module, VOS_TRACE_LEVEL_NONE,
276 VOS_FALSE);
277 vos_trace_setValue(module, VOS_TRACE_LEVEL_FATAL,
278 VOS_TRUE);
279 vos_trace_setValue(module, VOS_TRACE_LEVEL_ERROR,
280 VOS_TRUE);
281 }
282
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530283 vos_trace_setValue(VOS_MODULE_ID_RSV4, VOS_TRACE_LEVEL_NONE,
284 VOS_FALSE);
285}
286
287/* Need to call this with spin_lock acquired */
288static int wlan_queue_logmsg_for_app(void)
289{
290 char *ptr;
291 int ret = 0;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530292 ptr = &gwlan_logging.pcur_node->logbuf[sizeof(tAniHdr)];
293 ptr[gwlan_logging.pcur_node->filled_length] = '\0';
294
295 *(unsigned short *)(gwlan_logging.pcur_node->logbuf) =
296 ANI_NL_MSG_LOG_TYPE;
297 *(unsigned short *)(gwlan_logging.pcur_node->logbuf + 2) =
298 gwlan_logging.pcur_node->filled_length;
299 list_add_tail(&gwlan_logging.pcur_node->node,
300 &gwlan_logging.filled_list);
301
302 if (!list_empty(&gwlan_logging.free_list)) {
303 /* Get buffer from free list */
304 gwlan_logging.pcur_node =
305 (struct log_msg *)(gwlan_logging.free_list.next);
306 list_del_init(gwlan_logging.free_list.next);
307 } else if (!list_empty(&gwlan_logging.filled_list)) {
308 /* Get buffer from filled list */
309 /* This condition will drop the packet from being
310 * indicated to app
311 */
312 gwlan_logging.pcur_node =
313 (struct log_msg *)(gwlan_logging.filled_list.next);
Vinay Krishna Erannac2532972014-06-26 22:25:19 +0530314 ++gwlan_logging.drop_count;
Sushant Kaushik20a98202014-08-14 16:07:49 +0530315 /* print every 64th drop count */
Sushant Kaushik215778f2015-05-21 14:05:36 +0530316 if (vos_is_multicast_logging() &&
317 (!(gwlan_logging.drop_count % 0x40))) {
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +0530318 pr_err("%s: drop_count = %u index = %d filled_length = %d\n",
Vinay Krishna Erannac2532972014-06-26 22:25:19 +0530319 __func__, gwlan_logging.drop_count,
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +0530320 gwlan_logging.pcur_node->index,
321 gwlan_logging.pcur_node->filled_length);
322 }
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530323 list_del_init(gwlan_logging.filled_list.next);
324 ret = 1;
325 }
326
327 /* Reset the current node values */
328 gwlan_logging.pcur_node->filled_length = 0;
329 return ret;
330}
331
332
333int wlan_log_to_user(VOS_TRACE_LEVEL log_level, char *to_be_sent, int length)
334{
335 /* Add the current time stamp */
336 char *ptr;
Ratnam Rachuric798dbe2015-07-17 11:19:44 +0530337 char tbuf[100];
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530338 int tlen;
339 int total_log_len;
340 unsigned int *pfilled_length;
341 bool wake_up_thread = false;
Pradeep Kumar Goudagunta8526f832014-04-17 14:56:09 +0530342 unsigned long flags;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530343
Ratnam Rachuri3119f8a2015-07-23 14:55:21 +0530344 struct timeval tv;
345 struct rtc_time tm;
Vinay Krishna Eranna2c0ac302014-12-17 15:21:40 +0530346 unsigned long local_time;
Ratnam Rachuric798dbe2015-07-17 11:19:44 +0530347 u64 qtimer_ticks;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530348
Sushant Kaushik215778f2015-05-21 14:05:36 +0530349 if (!vos_is_multicast_logging()) {
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530350 /*
351 * This is to make sure that we print the logs to kmsg console
352 * when no logger app is running. This is also needed to
353 * log the initial messages during loading of driver where even
354 * if app is running it will not be able to
355 * register with driver immediately and start logging all the
356 * messages.
357 */
Vinay Krishna Eranna82337362014-09-06 18:19:03 +0530358 pr_err("%s\n", to_be_sent);
Sushant Kaushik215778f2015-05-21 14:05:36 +0530359 } else {
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530360
Vinay Krishna Eranna2c0ac302014-12-17 15:21:40 +0530361 /* Format the Log time [hr:min:sec.microsec] */
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530362 do_gettimeofday(&tv);
Vinay Krishna Eranna2c0ac302014-12-17 15:21:40 +0530363
364 /* Convert rtc to local time */
365 local_time = (u32)(tv.tv_sec - (sys_tz.tz_minuteswest * 60));
366 rtc_time_to_tm(local_time, &tm);
Ratnam Rachuric798dbe2015-07-17 11:19:44 +0530367 /* Firmware Time Stamp */
368 qtimer_ticks = arch_counter_get_cntpct();
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530369
Ratnam Rachuri3119f8a2015-07-23 14:55:21 +0530370 tlen = snprintf(tbuf, sizeof(tbuf), "[%02d:%02d:%02d.%06lu] [%016llX]"
371 " [%s] ", tm.tm_hour, tm.tm_min, tm.tm_sec, tv.tv_usec,
372 qtimer_ticks, current->comm);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530373 /* 1+1 indicate '\n'+'\0' */
374 total_log_len = length + tlen + 1 + 1;
375
Pradeep Kumar Goudagunta8526f832014-04-17 14:56:09 +0530376 spin_lock_irqsave(&gwlan_logging.spin_lock, flags);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +0530377
c_hpothu14181752014-12-10 11:52:09 +0530378 // wlan logging svc resources are not yet initialized
379 if (!gwlan_logging.pcur_node) {
380 spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags);
381 return -EIO;
382 }
383
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530384 pfilled_length = &gwlan_logging.pcur_node->filled_length;
385
386 /* Check if we can accomodate more log into current node/buffer */
387 if ((MAX_LOGMSG_LENGTH - (*pfilled_length + sizeof(tAniNlHdr))) <
388 total_log_len) {
389 wake_up_thread = true;
390 wlan_queue_logmsg_for_app();
391 pfilled_length = &gwlan_logging.pcur_node->filled_length;
392 }
393
394 ptr = &gwlan_logging.pcur_node->logbuf[sizeof(tAniHdr)];
395
396 /* Assumption here is that we receive logs which is always less than
397 * MAX_LOGMSG_LENGTH, where we can accomodate the
398 * tAniNlHdr + [context][timestamp] + log
399 * VOS_ASSERT if we cannot accomodate the the complete log into
400 * the available buffer.
401 *
402 * Continue and copy logs to the available length and discard the rest.
403 */
404 if (MAX_LOGMSG_LENGTH < (sizeof(tAniNlHdr) + total_log_len)) {
405 VOS_ASSERT(0);
406 total_log_len = MAX_LOGMSG_LENGTH - sizeof(tAniNlHdr) - 2;
407 }
408
Rajesh Babu Prathipati71e9c442014-07-01 22:08:29 +0530409 vos_mem_copy(&ptr[*pfilled_length], tbuf, tlen);
410 vos_mem_copy(&ptr[*pfilled_length + tlen], to_be_sent,
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530411 min(length, (total_log_len - tlen)));
412 *pfilled_length += tlen + min(length, total_log_len - tlen);
413 ptr[*pfilled_length] = '\n';
414 *pfilled_length += 1;
415
Pradeep Kumar Goudagunta8526f832014-04-17 14:56:09 +0530416 spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530417
418 /* Wakeup logger thread */
Vinay Krishna Eranna8382e0e2014-06-18 19:19:58 +0530419 if ((true == wake_up_thread)) {
420 /* If there is logger app registered wakeup the logging
Sushant Kaushik215778f2015-05-21 14:05:36 +0530421 * thread
Vinay Krishna Eranna8382e0e2014-06-18 19:19:58 +0530422 */
Sushant Kaushik215778f2015-05-21 14:05:36 +0530423
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530424 set_bit(HOST_LOG_POST_MASK, &gwlan_logging.event_flag);
Vinay Krishna Eranna8382e0e2014-06-18 19:19:58 +0530425 wake_up_interruptible(&gwlan_logging.wait_queue);
Vinay Krishna Eranna8382e0e2014-06-18 19:19:58 +0530426 }
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530427
Sushant Kaushik215778f2015-05-21 14:05:36 +0530428 if (gwlan_logging.log_fe_to_console
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530429 && ((VOS_TRACE_LEVEL_FATAL == log_level)
430 || (VOS_TRACE_LEVEL_ERROR == log_level))) {
Vinay Krishna Eranna82337362014-09-06 18:19:03 +0530431 pr_err("%s\n", to_be_sent);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530432 }
Sushant Kaushik215778f2015-05-21 14:05:36 +0530433 }
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530434
435 return 0;
436}
437
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530438static int send_fw_log_pkt_to_user(void)
439{
440 int ret = -1;
441 int extra_header_len, nl_payload_len;
442 struct sk_buff *skb = NULL;
443 static int nlmsg_seq;
444 vos_pkt_t *current_pkt;
445 vos_pkt_t *next_pkt;
446 VOS_STATUS status = VOS_STATUS_E_FAILURE;
447 unsigned long flags;
448
449 tAniNlHdr msg_header;
450
451 do {
452 spin_lock_irqsave(&gwlan_logging.fw_log_pkt_lock, flags);
453
454 if (!gwlan_logging.fw_log_pkt_queue) {
455 spin_unlock_irqrestore(
456 &gwlan_logging.fw_log_pkt_lock, flags);
457 return -EIO;
458 }
459
460 /* pick first pkt from queued chain */
461 current_pkt = gwlan_logging.fw_log_pkt_queue;
462
463 /* get the pointer to the next packet in the chain */
464 status = vos_pkt_walk_packet_chain(current_pkt, &next_pkt,
465 TRUE);
466
467 /* both "success" and "empty" are acceptable results */
468 if (!((status == VOS_STATUS_SUCCESS) ||
469 (status == VOS_STATUS_E_EMPTY))) {
470 ++gwlan_logging.fw_log_pkt_drop_cnt;
471 spin_unlock_irqrestore(
472 &gwlan_logging.fw_log_pkt_lock, flags);
473 pr_err("%s: Failure walking packet chain", __func__);
474 return -EIO;
475 }
476
477 /* update queue head with next pkt ptr which could be NULL */
478 gwlan_logging.fw_log_pkt_queue = next_pkt;
479 --gwlan_logging.fw_log_pkt_qcnt;
480 spin_unlock_irqrestore(&gwlan_logging.fw_log_pkt_lock, flags);
481
482 status = vos_pkt_get_os_packet(current_pkt, (v_VOID_t **)&skb,
483 TRUE);
484 if (!VOS_IS_STATUS_SUCCESS(status)) {
485 ++gwlan_logging.fw_log_pkt_drop_cnt;
486 pr_err("%s: Failure extracting skb from vos pkt",
487 __func__);
488 return -EIO;
489 }
490
491 /*return vos pkt since skb is already detached */
492 vos_pkt_return_packet(current_pkt);
493
494 extra_header_len = sizeof(msg_header.radio) + sizeof(tAniHdr);
495 nl_payload_len = NLMSG_ALIGN(extra_header_len + skb->len);
496
497 msg_header.nlh.nlmsg_type = ANI_NL_MSG_LOG;
498 msg_header.nlh.nlmsg_len = nl_payload_len;
499 msg_header.nlh.nlmsg_flags = NLM_F_REQUEST;
500 msg_header.nlh.nlmsg_pid = gapp_pid;
501 msg_header.nlh.nlmsg_seq = nlmsg_seq++;
502
503 msg_header.radio = 0;
504
505 msg_header.wmsg.type = ANI_NL_MSG_FW_LOG_PKT_TYPE;
506 msg_header.wmsg.length = skb->len;
507
508 if (unlikely(skb_headroom(skb) < sizeof(msg_header))) {
509 pr_err("VPKT [%d]: Insufficient headroom, head[%p],"
510 " data[%p], req[%zu]", __LINE__, skb->head,
511 skb->data, sizeof(msg_header));
512 return -EIO;
513 }
514
515 vos_mem_copy(skb_push(skb, sizeof(msg_header)), &msg_header,
516 sizeof(msg_header));
517
518 ret = nl_srv_bcast(skb);
519 if (ret < 0) {
520 pr_info("%s: Send Failed %d drop_count = %u\n",
521 __func__, ret, ++gwlan_logging.fw_log_pkt_drop_cnt);
522 } else {
523 ret = 0;
524 }
525
526 } while (next_pkt);
527
528 return ret;
529}
530
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530531static int send_data_mgmt_log_pkt_to_user(void)
532{
533 int ret = -1;
534 int extra_header_len, nl_payload_len;
535 struct sk_buff *skb = NULL;
536 static int nlmsg_seq;
537 vos_pkt_t *current_pkt;
538 vos_pkt_t *next_pkt;
539 VOS_STATUS status = VOS_STATUS_E_FAILURE;
540 unsigned long flags;
541
542 tAniNlLogHdr msg_header;
543
544 do {
545 spin_lock_irqsave(&gwlan_logging.data_mgmt_pkt_lock, flags);
546
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530547 if (!gwlan_logging.data_mgmt_pkt_queue) {
548 spin_unlock_irqrestore(
549 &gwlan_logging.data_mgmt_pkt_lock, flags);
550 return -EIO;
551 }
552
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530553 /* pick first pkt from queued chain */
554 current_pkt = gwlan_logging.data_mgmt_pkt_queue;
555
556 /* get the pointer to the next packet in the chain */
557 status = vos_pkt_walk_packet_chain(current_pkt, &next_pkt,
558 TRUE);
559
560 /* both "success" and "empty" are acceptable results */
561 if (!((status == VOS_STATUS_SUCCESS) ||
562 (status == VOS_STATUS_E_EMPTY))) {
563 ++gwlan_logging.pkt_drop_cnt;
564 spin_unlock_irqrestore(
565 &gwlan_logging.data_mgmt_pkt_lock, flags);
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530566 pr_err("%s: Failure walking packet chain", __func__);
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530567 return -EIO;
568 }
569
570 /* update queue head with next pkt ptr which could be NULL */
571 gwlan_logging.data_mgmt_pkt_queue = next_pkt;
572 --gwlan_logging.data_mgmt_pkt_qcnt;
573 spin_unlock_irqrestore(&gwlan_logging.data_mgmt_pkt_lock, flags);
574
575 status = vos_pkt_get_os_packet(current_pkt, (v_VOID_t **)&skb,
576 TRUE);
577 if (!VOS_IS_STATUS_SUCCESS(status)) {
578 ++gwlan_logging.pkt_drop_cnt;
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530579 pr_err("%s: Failure extracting skb from vos pkt",
580 __func__);
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530581 return -EIO;
582 }
583
584 /*return vos pkt since skb is already detached */
585 vos_pkt_return_packet(current_pkt);
586
587 extra_header_len = sizeof(msg_header.radio) + sizeof(tAniHdr) +
588 sizeof(msg_header.frameSize);
589 nl_payload_len = NLMSG_ALIGN(extra_header_len + skb->len);
590
591 msg_header.nlh.nlmsg_type = ANI_NL_MSG_LOG;
592 msg_header.nlh.nlmsg_len = nl_payload_len;
593 msg_header.nlh.nlmsg_flags = NLM_F_REQUEST;
Sushant Kaushik215778f2015-05-21 14:05:36 +0530594 msg_header.nlh.nlmsg_pid = 0;
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530595 msg_header.nlh.nlmsg_seq = nlmsg_seq++;
596
597 msg_header.radio = 0;
598
599 msg_header.wmsg.type = ANI_NL_MSG_LOG_PKT_TYPE;
600 msg_header.wmsg.length = skb->len + sizeof(uint32);
601
602 msg_header.frameSize = WLAN_MGMT_LOGGING_FRAMESIZE_128BYTES;
603
604 if (unlikely(skb_headroom(skb) < sizeof(msg_header))) {
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530605 pr_err("VPKT [%d]: Insufficient headroom, head[%p],"
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530606 " data[%p], req[%zu]", __LINE__, skb->head,
607 skb->data, sizeof(msg_header));
608 return -EIO;
609 }
610
611 vos_mem_copy(skb_push(skb, sizeof(msg_header)), &msg_header,
612 sizeof(msg_header));
613
Sushant Kaushik215778f2015-05-21 14:05:36 +0530614 ret = nl_srv_bcast(skb);
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530615 if (ret < 0) {
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530616 pr_info("%s: Send Failed %d drop_count = %u\n",
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530617 __func__, ret, ++gwlan_logging.pkt_drop_cnt);
618 } else {
619 ret = 0;
620 }
621
622 } while (next_pkt);
623
624 return ret;
625}
626
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530627static int send_filled_buffers_to_user(void)
628{
629 int ret = -1;
630 struct log_msg *plog_msg;
631 int payload_len;
632 int tot_msg_len;
633 tAniNlHdr *wnl;
634 struct sk_buff *skb = NULL;
635 struct nlmsghdr *nlh;
636 static int nlmsg_seq;
Pradeep Kumar Goudagunta8526f832014-04-17 14:56:09 +0530637 unsigned long flags;
Vinay Krishna Erannac2532972014-06-26 22:25:19 +0530638 static int rate_limit;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530639
640 while (!list_empty(&gwlan_logging.filled_list)
641 && !gwlan_logging.exit) {
642
643 skb = dev_alloc_skb(MAX_LOGMSG_LENGTH);
644 if (skb == NULL) {
Vinay Krishna Erannac2532972014-06-26 22:25:19 +0530645 if (!rate_limit) {
646 pr_err("%s: dev_alloc_skb() failed for msg size[%d] drop count = %u\n",
647 __func__, MAX_LOGMSG_LENGTH,
648 gwlan_logging.drop_count);
649 }
650 rate_limit = 1;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530651 ret = -ENOMEM;
652 break;
653 }
Vinay Krishna Erannac2532972014-06-26 22:25:19 +0530654 rate_limit = 0;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530655
Pradeep Kumar Goudagunta8526f832014-04-17 14:56:09 +0530656 spin_lock_irqsave(&gwlan_logging.spin_lock, flags);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530657
658 plog_msg = (struct log_msg *)
659 (gwlan_logging.filled_list.next);
660 list_del_init(gwlan_logging.filled_list.next);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +0530661 spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530662 /* 4 extra bytes for the radio idx */
663 payload_len = plog_msg->filled_length +
664 sizeof(wnl->radio) + sizeof(tAniHdr);
665
666 tot_msg_len = NLMSG_SPACE(payload_len);
Sushant Kaushik215778f2015-05-21 14:05:36 +0530667 nlh = nlmsg_put(skb, 0, nlmsg_seq++,
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530668 ANI_NL_MSG_LOG, payload_len,
669 NLM_F_REQUEST);
670 if (NULL == nlh) {
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +0530671 spin_lock_irqsave(&gwlan_logging.spin_lock, flags);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530672 list_add_tail(&plog_msg->node,
673 &gwlan_logging.free_list);
Pradeep Kumar Goudagunta8526f832014-04-17 14:56:09 +0530674 spin_unlock_irqrestore(&gwlan_logging.spin_lock,
675 flags);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530676 pr_err("%s: drop_count = %u\n", __func__,
677 ++gwlan_logging.drop_count);
678 pr_err("%s: nlmsg_put() failed for msg size[%d]\n",
679 __func__, tot_msg_len);
680 dev_kfree_skb(skb);
681 skb = NULL;
682 ret = -EINVAL;
683 continue;
684 }
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530685
686 wnl = (tAniNlHdr *) nlh;
687 wnl->radio = plog_msg->radio;
Rajesh Babu Prathipati71e9c442014-07-01 22:08:29 +0530688 vos_mem_copy(&wnl->wmsg, plog_msg->logbuf,
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530689 plog_msg->filled_length +
690 sizeof(tAniHdr));
691
Pradeep Kumar Goudagunta8526f832014-04-17 14:56:09 +0530692 spin_lock_irqsave(&gwlan_logging.spin_lock, flags);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530693 list_add_tail(&plog_msg->node,
694 &gwlan_logging.free_list);
Pradeep Kumar Goudagunta8526f832014-04-17 14:56:09 +0530695 spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530696
Sushant Kaushik215778f2015-05-21 14:05:36 +0530697 ret = nl_srv_bcast(skb);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530698 if (ret < 0) {
Sushant Kaushik8ddaa382015-06-23 12:17:25 +0530699 if (__ratelimit(&errCnt))
700 {
701 pr_info("%s: Send Failed %d drop_count = %u\n",
702 __func__, ret, gwlan_logging.drop_count);
703 }
704 gwlan_logging.drop_count++;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530705 skb = NULL;
c_hpothu0424d042014-11-19 19:37:14 +0530706 break;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530707 } else {
708 skb = NULL;
709 ret = 0;
710 }
711 }
712
713 return ret;
714}
715
716/**
717 * wlan_logging_thread() - The WLAN Logger thread
718 * @Arg - pointer to the HDD context
719 *
720 * This thread logs log message to App registered for the logs.
721 */
722static int wlan_logging_thread(void *Arg)
723{
724 int ret_wait_status = 0;
Vinay Krishna Erannac2532972014-06-26 22:25:19 +0530725 int ret = 0;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530726
727 set_user_nice(current, -2);
728
729#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))
730 daemonize("wlan_logging_thread");
731#endif
732
733 while (!gwlan_logging.exit) {
734 ret_wait_status = wait_event_interruptible(
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530735 gwlan_logging.wait_queue,
736 (test_bit(HOST_LOG_POST_MASK, &gwlan_logging.event_flag) ||
Sachin Ahuja715aafc2015-07-21 23:35:10 +0530737 gwlan_logging.exit ||
738 test_bit(LOGGER_MGMT_DATA_PKT_POST_MASK,&gwlan_logging.event_flag) ||
739 test_bit(LOGGER_FW_LOG_PKT_POST_MASK, &gwlan_logging.event_flag) ||
740 test_bit(LOGGER_FATAL_EVENT_POST_MASK, &gwlan_logging.event_flag)));
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530741
742 if (ret_wait_status == -ERESTARTSYS) {
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530743 pr_err("%s: wait_event return -ERESTARTSYS", __func__);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530744 break;
745 }
746
747 if (gwlan_logging.exit) {
c_hpothu0424d042014-11-19 19:37:14 +0530748 break;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530749 }
750
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530751 if (test_and_clear_bit(HOST_LOG_POST_MASK,
752 &gwlan_logging.event_flag)) {
753 ret = send_filled_buffers_to_user();
754 if (-ENOMEM == ret) {
755 msleep(200);
756 }
757 }
758
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530759 if (test_and_clear_bit(LOGGER_FW_LOG_PKT_POST_MASK,
760 &gwlan_logging.event_flag)) {
761 send_fw_log_pkt_to_user();
762 }
763
764 if (test_and_clear_bit(LOGGER_MGMT_DATA_PKT_POST_MASK,
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530765 &gwlan_logging.event_flag)) {
766 send_data_mgmt_log_pkt_to_user();
Vinay Krishna Erannac2532972014-06-26 22:25:19 +0530767 }
Sachin Ahuja715aafc2015-07-21 23:35:10 +0530768
769 if (test_and_clear_bit(LOGGER_FATAL_EVENT_POST_MASK,
770 &gwlan_logging.event_flag)) {
771 if (gwlan_logging.log_complete.is_flush_complete == true) {
772 gwlan_logging.log_complete.is_flush_complete = false;
773 vos_send_fatal_event_done();
774 }
775 else {
776 gwlan_logging.log_complete.is_flush_complete = true;
777 set_bit(HOST_LOG_POST_MASK,&gwlan_logging.event_flag);
778 set_bit(LOGGER_FW_LOG_PKT_POST_MASK,&gwlan_logging.event_flag);
779 set_bit(LOGGER_FATAL_EVENT_POST_MASK,&gwlan_logging.event_flag);
780 wake_up_interruptible(&gwlan_logging.wait_queue);
781 }
782 }
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530783 }
784
Vinay Krishna Erannad1d284f2014-10-28 20:09:55 +0530785 complete_and_exit(&gwlan_logging.shutdown_comp, 0);
786
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530787 return 0;
788}
789
790/*
791 * Process all the Netlink messages from Logger Socket app in user space
792 */
793static int wlan_logging_proc_sock_rx_msg(struct sk_buff *skb)
794{
795 tAniNlHdr *wnl;
796 int radio;
797 int type;
798 int ret;
799
Hanumantha Reddy Pothula05b0b552015-06-18 14:26:10 +0530800 if (TRUE == vos_isUnloadInProgress())
801 {
802 pr_info("%s: unload in progress\n",__func__);
803 return -ENODEV;
804 }
805
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530806 wnl = (tAniNlHdr *) skb->data;
807 radio = wnl->radio;
808 type = wnl->nlh.nlmsg_type;
809
810 if (radio < 0 || radio > ANI_MAX_RADIOS) {
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530811 pr_err("%s: invalid radio id [%d]\n",
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530812 __func__, radio);
813 return -EINVAL;
814 }
815
816 if (gapp_pid != INVALID_PID) {
817 if (wnl->nlh.nlmsg_pid > gapp_pid) {
818 gapp_pid = wnl->nlh.nlmsg_pid;
819 }
820
821 spin_lock_bh(&gwlan_logging.spin_lock);
822 if (gwlan_logging.pcur_node->filled_length) {
823 wlan_queue_logmsg_for_app();
824 }
825 spin_unlock_bh(&gwlan_logging.spin_lock);
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530826 set_bit(HOST_LOG_POST_MASK, &gwlan_logging.event_flag);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530827 wake_up_interruptible(&gwlan_logging.wait_queue);
828 } else {
829 /* This is to set the default levels (WLAN logging
830 * default values not the VOS trace default) when
831 * logger app is registered for the first time.
832 */
833 gapp_pid = wnl->nlh.nlmsg_pid;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530834 }
835
836 ret = wlan_send_sock_msg_to_app(&wnl->wmsg, 0,
837 ANI_NL_MSG_LOG, wnl->nlh.nlmsg_pid);
838 if (ret < 0) {
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530839 pr_err("wlan_send_sock_msg_to_app: failed");
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530840 }
841
842 return ret;
843}
844
Sachin Ahuja715aafc2015-07-21 23:35:10 +0530845void wlan_init_log_completion(void)
846{
847 gwlan_logging.log_complete.indicator = WLAN_LOG_TYPE_NON_FATAL;
848 gwlan_logging.log_complete.is_fatal = WLAN_LOG_INDICATOR_UNUSED;
849 gwlan_logging.log_complete.is_report_in_progress = false;
850 gwlan_logging.log_complete.reason_code = WLAN_LOG_REASON_CODE_UNUSED;
851
852 spin_lock_init(&gwlan_logging.bug_report_lock);
853}
854
855int wlan_set_log_completion(uint32 is_fatal,
856 uint32 indicator,
857 uint32 reason_code)
858{
859 unsigned long flags;
860
861 spin_lock_irqsave(&gwlan_logging.bug_report_lock, flags);
862 gwlan_logging.log_complete.indicator = indicator;
863 gwlan_logging.log_complete.is_fatal = is_fatal;
864 gwlan_logging.log_complete.is_report_in_progress = true;
865 gwlan_logging.log_complete.reason_code = reason_code;
866 spin_unlock_irqrestore(&gwlan_logging.bug_report_lock, flags);
867
868 return 0;
869}
870void wlan_get_log_completion(uint32 *is_fatal,
871 uint32 *indicator,
872 uint32 *reason_code)
873{
874 unsigned long flags;
875
876 spin_lock_irqsave(&gwlan_logging.bug_report_lock, flags);
877 *indicator = gwlan_logging.log_complete.indicator;
878 *is_fatal = gwlan_logging.log_complete.is_fatal;
879 *reason_code = gwlan_logging.log_complete.reason_code;
880 gwlan_logging.log_complete.is_report_in_progress = false;
881
882 spin_unlock_irqrestore(&gwlan_logging.bug_report_lock, flags);
883
884}
885bool wlan_is_log_report_in_progress(void)
886{
887 return gwlan_logging.log_complete.is_report_in_progress;
888}
889
890void wlan_reset_log_report_in_progress(void)
891{
892 unsigned long flags;
893
894 spin_lock_irqsave(&gwlan_logging.bug_report_lock, flags);
895 gwlan_logging.log_complete.is_report_in_progress = false;
896 spin_unlock_irqrestore(&gwlan_logging.bug_report_lock, flags);
897}
898
899
900void wlan_deinit_log_completion(void)
901{
902 return;
903}
904
905
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530906int wlan_logging_sock_activate_svc(int log_fe_to_console, int num_buf)
907{
908 int i = 0;
909 unsigned long irq_flag;
910
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530911 gapp_pid = INVALID_PID;
912
Vinay Krishna Eranna0b112622014-04-21 20:17:57 +0530913 gplog_msg = (struct log_msg *) vmalloc(
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530914 num_buf * sizeof(struct log_msg));
915 if (!gplog_msg) {
916 pr_err("%s: Could not allocate memory\n", __func__);
917 return -ENOMEM;
918 }
919
920 vos_mem_zero(gplog_msg, (num_buf * sizeof(struct log_msg)));
921
922 gwlan_logging.log_fe_to_console = !!log_fe_to_console;
923 gwlan_logging.num_buf = num_buf;
924
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530925 spin_lock_irqsave(&gwlan_logging.spin_lock, irq_flag);
926 INIT_LIST_HEAD(&gwlan_logging.free_list);
927 INIT_LIST_HEAD(&gwlan_logging.filled_list);
928
929 for (i = 0; i < num_buf; i++) {
930 list_add(&gplog_msg[i].node, &gwlan_logging.free_list);
931 gplog_msg[i].index = i;
932 }
933 gwlan_logging.pcur_node = (struct log_msg *)
934 (gwlan_logging.free_list.next);
935 list_del_init(gwlan_logging.free_list.next);
936 spin_unlock_irqrestore(&gwlan_logging.spin_lock, irq_flag);
937
938 init_waitqueue_head(&gwlan_logging.wait_queue);
939 gwlan_logging.exit = false;
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530940 clear_bit(HOST_LOG_POST_MASK, &gwlan_logging.event_flag);
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530941 clear_bit(LOGGER_MGMT_DATA_PKT_POST_MASK, &gwlan_logging.event_flag);
Sachin Ahuja715aafc2015-07-21 23:35:10 +0530942 clear_bit(LOGGER_FW_LOG_PKT_POST_MASK, &gwlan_logging.event_flag);
943 clear_bit(LOGGER_FATAL_EVENT_POST_MASK, &gwlan_logging.event_flag);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530944 init_completion(&gwlan_logging.shutdown_comp);
945 gwlan_logging.thread = kthread_create(wlan_logging_thread, NULL,
946 "wlan_logging_thread");
947 if (IS_ERR(gwlan_logging.thread)) {
948 pr_err("%s: Could not Create LogMsg Thread Controller",
949 __func__);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +0530950 spin_lock_irqsave(&gwlan_logging.spin_lock, irq_flag);
Vinay Krishna Eranna6c158fa2014-05-13 00:42:41 +0530951 vfree(gplog_msg);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +0530952 gplog_msg = NULL;
953 gwlan_logging.pcur_node = NULL;
954 spin_unlock_irqrestore(&gwlan_logging.spin_lock, irq_flag);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530955 return -ENOMEM;
956 }
957 wake_up_process(gwlan_logging.thread);
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530958 gwlan_logging.is_active = true;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530959
960 nl_srv_register(ANI_NL_MSG_LOG, wlan_logging_proc_sock_rx_msg);
961
Sushant Kaushik9cb1c9c2015-06-23 11:57:10 +0530962 //Broadcast SVC ready message to logging app/s running
963 wlan_logging_srv_nl_ready_indication();
Vinay Krishna Erannad938c422014-03-10 17:14:21 +0530964 return 0;
965}
966
Siddharth Bhal7bd19932015-03-03 16:54:36 +0530967int wlan_logging_flush_pkt_queue(void)
968{
969 vos_pkt_t *pkt_queue_head;
970 unsigned long flags;
971
972 spin_lock_irqsave(&gwlan_logging.data_mgmt_pkt_lock, flags);
973 if (NULL != gwlan_logging.data_mgmt_pkt_queue) {
974 pkt_queue_head = gwlan_logging.data_mgmt_pkt_queue;
975 gwlan_logging.data_mgmt_pkt_queue = NULL;
976 gwlan_logging.pkt_drop_cnt = 0;
977 gwlan_logging.data_mgmt_pkt_qcnt = 0;
978 spin_unlock_irqrestore(&gwlan_logging.data_mgmt_pkt_lock,
979 flags);
980 vos_pkt_return_packet(pkt_queue_head);
981 } else {
982 spin_unlock_irqrestore(&gwlan_logging.data_mgmt_pkt_lock,
983 flags);
984 }
985
Siddharth Bhalec0b72c2015-05-12 21:35:54 +0530986 spin_lock_irqsave(&gwlan_logging.fw_log_pkt_lock, flags);
987 if (NULL != gwlan_logging.fw_log_pkt_queue) {
988 pkt_queue_head = gwlan_logging.fw_log_pkt_queue;
989 gwlan_logging.fw_log_pkt_queue = NULL;
990 gwlan_logging.fw_log_pkt_drop_cnt = 0;
991 gwlan_logging.fw_log_pkt_qcnt = 0;
992 spin_unlock_irqrestore(&gwlan_logging.fw_log_pkt_lock,
993 flags);
994 vos_pkt_return_packet(pkt_queue_head);
995 } else {
996 spin_unlock_irqrestore(&gwlan_logging.fw_log_pkt_lock,
997 flags);
998 }
999
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301000 return 0;
1001}
1002
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301003int wlan_logging_sock_deactivate_svc(void)
1004{
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05301005 unsigned long irq_flag;
1006
1007 if (!gplog_msg)
1008 return 0;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301009
1010 nl_srv_unregister(ANI_NL_MSG_LOG, wlan_logging_proc_sock_rx_msg);
1011 clear_default_logtoapp_log_level();
1012 gapp_pid = INVALID_PID;
1013
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301014 INIT_COMPLETION(gwlan_logging.shutdown_comp);
Vinay Krishna Erannad1d284f2014-10-28 20:09:55 +05301015 gwlan_logging.exit = true;
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301016 gwlan_logging.is_active = false;
Sushant Kaushik215778f2015-05-21 14:05:36 +05301017 vos_set_multicast_logging(0);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301018 wake_up_interruptible(&gwlan_logging.wait_queue);
Vinay Krishna Erannad1d284f2014-10-28 20:09:55 +05301019 wait_for_completion(&gwlan_logging.shutdown_comp);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301020
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05301021 spin_lock_irqsave(&gwlan_logging.spin_lock, irq_flag);
Vinay Krishna Eranna0b112622014-04-21 20:17:57 +05301022 vfree(gplog_msg);
Sushant Kaushik215778f2015-05-21 14:05:36 +05301023 gplog_msg = NULL;
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05301024 gwlan_logging.pcur_node = NULL;
1025 spin_unlock_irqrestore(&gwlan_logging.spin_lock, irq_flag);
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301026
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301027 wlan_logging_flush_pkt_queue();
1028
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301029 return 0;
1030}
1031
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05301032int wlan_logging_sock_init_svc(void)
1033{
1034 spin_lock_init(&gwlan_logging.spin_lock);
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301035 spin_lock_init(&gwlan_logging.data_mgmt_pkt_lock);
Siddharth Bhalec0b72c2015-05-12 21:35:54 +05301036 spin_lock_init(&gwlan_logging.fw_log_pkt_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05301037 gapp_pid = INVALID_PID;
1038 gwlan_logging.pcur_node = NULL;
1039
Sachin Ahuja715aafc2015-07-21 23:35:10 +05301040 wlan_init_log_completion();
1041
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05301042 return 0;
1043}
1044
1045int wlan_logging_sock_deinit_svc(void)
1046{
1047 gwlan_logging.pcur_node = NULL;
1048 gapp_pid = INVALID_PID;
1049
Sachin Ahuja715aafc2015-07-21 23:35:10 +05301050 wlan_deinit_log_completion();
1051 return 0;
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05301052}
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301053
Siddharth Bhalec0b72c2015-05-12 21:35:54 +05301054int wlan_queue_data_mgmt_pkt_for_app(vos_pkt_t *pPacket)
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301055{
1056 unsigned long flags;
1057 vos_pkt_t *next_pkt;
1058 vos_pkt_t *free_pkt;
1059 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1060
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301061 spin_lock_irqsave(&gwlan_logging.data_mgmt_pkt_lock, flags);
Siddharth Bhalec0b72c2015-05-12 21:35:54 +05301062 if (gwlan_logging.data_mgmt_pkt_qcnt >= LOGGER_MAX_DATA_MGMT_PKT_Q_LEN) {
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301063 status = vos_pkt_walk_packet_chain(
1064 gwlan_logging.data_mgmt_pkt_queue, &next_pkt, TRUE);
1065 /*both "success" and "empty" are acceptable results*/
1066 if (!((status == VOS_STATUS_SUCCESS) ||
1067 (status == VOS_STATUS_E_EMPTY))) {
1068 ++gwlan_logging.pkt_drop_cnt;
1069 spin_unlock_irqrestore(
1070 &gwlan_logging.data_mgmt_pkt_lock, flags);
Siddharth Bhalec0b72c2015-05-12 21:35:54 +05301071 pr_err("%s: Failure walking packet chain", __func__);
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301072 /*keep returning pkts to avoid low resource cond*/
1073 vos_pkt_return_packet(pPacket);
1074 return VOS_STATUS_E_FAILURE;
1075 }
1076
1077 free_pkt = gwlan_logging.data_mgmt_pkt_queue;
1078 gwlan_logging.data_mgmt_pkt_queue = next_pkt;
1079 /*returning head of pkt queue. latest pkts are important*/
1080 --gwlan_logging.data_mgmt_pkt_qcnt;
1081 spin_unlock_irqrestore(&gwlan_logging.data_mgmt_pkt_lock,
1082 flags);
1083 vos_pkt_return_packet(free_pkt);
1084 } else {
1085 spin_unlock_irqrestore(&gwlan_logging.data_mgmt_pkt_lock,
1086 flags);
1087 }
1088
1089 spin_lock_irqsave(&gwlan_logging.data_mgmt_pkt_lock, flags);
1090
1091 if (gwlan_logging.data_mgmt_pkt_queue) {
1092 vos_pkt_chain_packet(gwlan_logging.data_mgmt_pkt_queue,
1093 pPacket, TRUE);
1094 } else {
1095 gwlan_logging.data_mgmt_pkt_queue = pPacket;
1096 }
1097 ++gwlan_logging.data_mgmt_pkt_qcnt;
1098
1099 spin_unlock_irqrestore(&gwlan_logging.data_mgmt_pkt_lock, flags);
1100
Siddharth Bhalec0b72c2015-05-12 21:35:54 +05301101 set_bit(LOGGER_MGMT_DATA_PKT_POST_MASK, &gwlan_logging.event_flag);
Siddharth Bhal7bd19932015-03-03 16:54:36 +05301102 wake_up_interruptible(&gwlan_logging.wait_queue);
1103
1104 return VOS_STATUS_SUCCESS;
1105}
1106
Sushant Kaushik215778f2015-05-21 14:05:36 +05301107/**
1108 * wlan_logging_set_log_level() - Set the logging level
1109 *
1110 * This function is used to set the logging level of host debug messages
1111 *
1112 * Return: None
1113 */
1114void wlan_logging_set_log_level(void)
1115{
1116 set_default_logtoapp_log_level();
1117}
1118
Siddharth Bhalec0b72c2015-05-12 21:35:54 +05301119int wlan_queue_fw_log_pkt_for_app(vos_pkt_t *pPacket)
1120{
1121 unsigned long flags;
1122 vos_pkt_t *next_pkt;
1123 vos_pkt_t *free_pkt;
1124 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1125
1126 spin_lock_irqsave(&gwlan_logging.fw_log_pkt_lock, flags);
1127 if (gwlan_logging.fw_log_pkt_qcnt >= LOGGER_MAX_FW_LOG_PKT_Q_LEN) {
1128 status = vos_pkt_walk_packet_chain(
1129 gwlan_logging.fw_log_pkt_queue, &next_pkt, TRUE);
1130 /*both "success" and "empty" are acceptable results*/
1131 if (!((status == VOS_STATUS_SUCCESS) ||
1132 (status == VOS_STATUS_E_EMPTY))) {
1133 ++gwlan_logging.fw_log_pkt_drop_cnt;
1134 spin_unlock_irqrestore(
1135 &gwlan_logging.fw_log_pkt_lock, flags);
1136 pr_err("%s: Failure walking packet chain", __func__);
1137 /*keep returning pkts to avoid low resource cond*/
1138 vos_pkt_return_packet(pPacket);
1139 return VOS_STATUS_E_FAILURE;
1140 }
1141
1142 free_pkt = gwlan_logging.fw_log_pkt_queue;
1143 gwlan_logging.fw_log_pkt_queue = next_pkt;
1144 /*returning head of pkt queue. latest pkts are important*/
1145 --gwlan_logging.fw_log_pkt_qcnt;
1146 spin_unlock_irqrestore(&gwlan_logging.fw_log_pkt_lock,
1147 flags);
1148 vos_pkt_return_packet(free_pkt);
1149 } else {
1150 spin_unlock_irqrestore(&gwlan_logging.fw_log_pkt_lock,
1151 flags);
1152 }
1153
1154 spin_lock_irqsave(&gwlan_logging.fw_log_pkt_lock, flags);
1155
1156 if (gwlan_logging.fw_log_pkt_queue) {
1157 vos_pkt_chain_packet(gwlan_logging.fw_log_pkt_queue,
1158 pPacket, TRUE);
1159 } else {
1160 gwlan_logging.fw_log_pkt_queue = pPacket;
1161 }
1162 ++gwlan_logging.fw_log_pkt_qcnt;
1163
1164 spin_unlock_irqrestore(&gwlan_logging.fw_log_pkt_lock, flags);
1165
1166 set_bit(LOGGER_FW_LOG_PKT_POST_MASK, &gwlan_logging.event_flag);
1167 wake_up_interruptible(&gwlan_logging.wait_queue);
1168
1169 return VOS_STATUS_SUCCESS;
1170}
1171
1172int wlan_queue_logpkt_for_app(vos_pkt_t *pPacket, uint32 pkt_type)
1173{
1174 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1175
1176 if (pPacket == NULL) {
1177 pr_err("%s: Null param", __func__);
1178 VOS_ASSERT(0);
1179 return VOS_STATUS_E_FAILURE;
1180 }
1181
1182 if (gwlan_logging.is_active == false) {
1183 /*return all packets queued*/
1184 wlan_logging_flush_pkt_queue();
1185
1186 /*return currently received pkt*/
1187 vos_pkt_return_packet(pPacket);
1188 return VOS_STATUS_E_FAILURE;
1189 }
1190
1191 switch (pkt_type) {
1192 case LOG_PKT_TYPE_DATA_MGMT:
1193 status = wlan_queue_data_mgmt_pkt_for_app(pPacket);
1194 break;
1195
1196 case LOG_PKT_TYPE_FW_LOG:
1197 status = wlan_queue_fw_log_pkt_for_app(pPacket);
1198 break;
1199
1200 default:
1201 pr_info("%s: Unknown pkt received %d", __func__, pkt_type);
1202 status = VOS_STATUS_E_INVAL;
1203 break;
1204 };
1205
1206 return status;
1207}
Sushant Kaushik215778f2015-05-21 14:05:36 +05301208
Sachin Ahuja715aafc2015-07-21 23:35:10 +05301209
1210void wlan_process_done_indication(uint8 type, uint32 reason_code)
1211{
1212 if ((type == WLAN_QXDM_LOGGING) && (wlan_is_log_report_in_progress() == TRUE))
1213 {
1214 pr_info("%s: Setting LOGGER_FATAL_EVENT\n", __func__);
1215 set_bit(LOGGER_FATAL_EVENT_POST_MASK, &gwlan_logging.event_flag);
1216 wake_up_interruptible(&gwlan_logging.wait_queue);
1217 }
1218}
1219
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05301220#endif /* WLAN_LOGGING_SOCK_SVC_ENABLE */