import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / connectivity / conn_soc / common / linux / pri / stp_dbg.c
1 /*
2 * Copyright (C) 2011-2014 MediaTek Inc.
3 *
4 * This program is free software: you can redistribute it and/or modify it under the terms of the
5 * GNU General Public License version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 * See the GNU General Public License for more details.
10 *
11 * You should have received a copy of the GNU General Public License along with this program.
12 * If not, see <http://www.gnu.org/licenses/>.
13 */
14 #include <linux/kernel.h> // GFP_KERNEL
15 #include <linux/timer.h> //init_timer, add_time, del_timer_sync
16 #include <linux/time.h> //gettimeofday
17 #include <linux/delay.h>
18 #include <linux/slab.h> //kzalloc
19 #include <linux/sched.h> //task's status
20 #include <linux/vmalloc.h>
21 #include <linux/err.h>
22 #include <linux/workqueue.h>
23 #include <asm/atomic.h>
24
25 #include <net/sock.h>
26 #include <net/netlink.h>
27 #include <linux/skbuff.h>
28 #include <net/genetlink.h>
29
30 #include <linux/zlib.h>
31 #include <linux/uaccess.h>
32 #include <linux/crc32.h>
33
34 #include "osal_typedef.h"
35 #include "stp_dbg.h"
36 //#include "stp_btm.h"
37 #include "btm_core.h"
38 #include "wmt_plat.h"
39
40 #define PFX_STP_DBG "[STPDbg]"
41 #define STP_DBG_LOG_LOUD 4
42 #define STP_DBG_LOG_DBG 3
43 #define STP_DBG_LOG_INFO 2
44 #define STP_DBG_LOG_WARN 1
45 #define STP_DBG_LOG_ERR 0
46
47 unsigned int gStpDbgDbgLevel = STP_DBG_LOG_INFO;
48 unsigned int gStpDbgLogOut = 0;
49
50 #define STP_DBG_LOUD_FUNC(fmt, arg...) if(gStpDbgDbgLevel >= STP_DBG_LOG_LOUD){ printk(KERN_DEBUG PFX_STP_DBG "%s: " fmt, __FUNCTION__ ,##arg);}
51 #define STP_DBG_DBG_FUNC(fmt, arg...) if(gStpDbgDbgLevel >= STP_DBG_LOG_DBG){ printk(KERN_DEBUG PFX_STP_DBG "%s: " fmt, __FUNCTION__ ,##arg);}
52 #define STP_DBG_INFO_FUNC(fmt, arg...) if(gStpDbgDbgLevel >= STP_DBG_LOG_INFO){ printk(PFX_STP_DBG "%s: " fmt, __FUNCTION__ ,##arg);}
53 #define STP_DBG_WARN_FUNC(fmt, arg...) if(gStpDbgDbgLevel >= STP_DBG_LOG_WARN){ printk(PFX_STP_DBG "%s: " fmt, __FUNCTION__ ,##arg);}
54 #define STP_DBG_ERR_FUNC(fmt, arg...) if(gStpDbgDbgLevel >= STP_DBG_LOG_ERR){ printk(PFX_STP_DBG "%s: " fmt, __FUNCTION__ ,##arg);}
55 #define STP_DBG_TRC_FUNC(f) if(gStpDbgDbgLevel >= STP_DBG_LOG_DBG){ printk(KERN_DEBUG PFX_STP_DBG "<%s> <%d>\n", __FUNCTION__, __LINE__);}
56
57
58 MTKSTP_DBG_T *g_stp_dbg = NULL;
59
60 #define STP_DBG_FAMILY_NAME "STP_DBG"
61 #define MAX_BIND_PROCESS (4)
62 #ifdef WMT_PLAT_ALPS
63 #define STP_DBG_AEE_EXP_API (1)
64 #else
65 #define STP_DBG_AEE_EXP_API (0)
66 #endif
67 enum {
68 __STP_DBG_ATTR_INVALID,
69 STP_DBG_ATTR_MSG,
70 __STP_DBG_ATTR_MAX,
71 };
72 #define STP_DBG_ATTR_MAX (__STP_DBG_ATTR_MAX - 1)
73
74 enum {
75 __STP_DBG_COMMAND_INVALID,
76 STP_DBG_COMMAND_BIND,
77 STP_DBG_COMMAND_RESET,
78 __STP_DBG_COMMAND_MAX,
79 };
80 #define MTK_WIFI_COMMAND_MAX (__STP_DBG_COMMAND_MAX - 1)
81
82 static struct genl_family stp_dbg_gnl_family = {
83 .id = GENL_ID_GENERATE,
84 .hdrsize = 0,
85 .name = STP_DBG_FAMILY_NAME,
86 .version = 1,
87 .maxattr = STP_DBG_ATTR_MAX,
88 };
89
90 static void stp_dbg_nl_init(void);
91 static void stp_dbg_nl_deinit(void);
92 static int stp_dbg_nl_bind(
93 struct sk_buff *skb,
94 struct genl_info *info
95 );
96 static int stp_dbg_nl_reset(
97 struct sk_buff *skb,
98 struct genl_info *info
99 );
100
101 /* attribute policy */
102 static struct nla_policy stp_dbg_genl_policy[STP_DBG_ATTR_MAX + 1] = {
103 [STP_DBG_ATTR_MSG] = { .type = NLA_NUL_STRING },
104 };
105
106 /* operation definition */
107 static struct genl_ops stp_dbg_gnl_ops_bind = {
108 .cmd = STP_DBG_COMMAND_BIND,
109 .flags = 0,
110 .policy = stp_dbg_genl_policy,
111 .doit = stp_dbg_nl_bind,
112 .dumpit = NULL,
113 };
114
115 static struct genl_ops stp_dbg_gnl_ops_reset = {
116 .cmd = STP_DBG_COMMAND_RESET,
117 .flags = 0,
118 .policy = stp_dbg_genl_policy,
119 .doit = stp_dbg_nl_reset,
120 .dumpit = NULL,
121 };
122
123 #define E2S(x) #x
124 static char* dmaRegsStr[] = {
125 E2S(CONNSYS_CLK_GATE_STATUS),
126 E2S(CONSYS_EMI_STATUS),
127 E2S(SYSRAM1),
128 E2S(SYSRAM2),
129 E2S(SYSRAM3)
130 };
131 static unsigned int stp_dbg_seqnum = 0;
132 static int num_bind_process = 0;
133 static pid_t bind_pid[MAX_BIND_PROCESS];
134
135 static P_WCN_CORE_DUMP_T g_core_dump = NULL;
136
137 static P_STP_DBG_CPUPCR_T g_stp_dbg_cpupcr = NULL;
138
139 //just show in log at present
140 static P_STP_DBG_DMAREGS_T g_stp_dbg_dmaregs = NULL;
141
142 /* core_dump_timeout_handler - handler of coredump timeout
143 * @ data - core dump object's pointer
144 *
145 * No return value
146 */
147 static void core_dump_timeout_handler(unsigned long data)
148 {
149 P_WCN_CORE_DUMP_T dmp = (P_WCN_CORE_DUMP_T)data;
150
151 STP_DBG_INFO_FUNC(" start\n");
152
153 stp_btm_notify_coredump_timeout_wq(g_stp_dbg->btm);
154
155 STP_DBG_INFO_FUNC(" end\n");
156
157 if (dmp) {
158 dmp->sm = CORE_DUMP_TIMEOUT;
159 }
160 }
161
162
163 /* wcn_core_dump_init - create core dump sys
164 * @ timeout - core dump time out value
165 *
166 * Return object pointer if success, else NULL
167 */
168 P_WCN_CORE_DUMP_T wcn_core_dump_init(UINT32 timeout)
169 {
170 #define KBYTES (1024*sizeof(char))
171 #define L1_BUF_SIZE (32*KBYTES)
172 #define L2_BUF_SIZE (384*KBYTES)
173
174 P_WCN_CORE_DUMP_T core_dmp = NULL;
175
176 core_dmp = (P_WCN_CORE_DUMP_T)osal_malloc(sizeof(WCN_CORE_DUMP_T));
177 if (!core_dmp) {
178 STP_DBG_ERR_FUNC("alloc mem failed!\n");
179 goto fail;
180 }
181
182 osal_memset(core_dmp, 0, sizeof(WCN_CORE_DUMP_T));
183
184 core_dmp->compressor = wcn_compressor_init("core_dump_compressor", L1_BUF_SIZE, L2_BUF_SIZE);
185 if (!core_dmp->compressor) {
186 STP_DBG_ERR_FUNC("create compressor failed!\n");
187 goto fail;
188 }
189 wcn_compressor_reset(core_dmp->compressor, 1, GZIP);
190
191 core_dmp->dmp_timer.timeoutHandler = core_dump_timeout_handler;
192 core_dmp->dmp_timer.timeroutHandlerData = (unsigned long)core_dmp;
193 osal_timer_create(&core_dmp->dmp_timer);
194 core_dmp->timeout = timeout;
195
196 osal_sleepable_lock_init(&core_dmp->dmp_lock);
197
198 core_dmp->sm = CORE_DUMP_INIT;
199 STP_DBG_INFO_FUNC("create coredump object OK!\n");
200
201 return core_dmp;
202
203 fail:
204 if (core_dmp && core_dmp->compressor) {
205 wcn_compressor_deinit(core_dmp->compressor);
206 core_dmp->compressor = NULL;
207 }
208
209 if (core_dmp) {
210 osal_free(core_dmp);
211 }
212
213 osal_sleepable_lock_deinit(&core_dmp->dmp_lock);
214
215 return NULL;
216 }
217
218
219 /* wcn_core_dump_deinit - destroy core dump object
220 * @ dmp - pointer of object
221 *
222 * Retunr 0 if success, else error code
223 */
224 INT32 wcn_core_dump_deinit(P_WCN_CORE_DUMP_T dmp)
225 {
226 if (dmp && dmp->compressor) {
227 wcn_compressor_deinit(dmp->compressor);
228 dmp->compressor = NULL;
229 }
230
231 if (dmp) {
232 osal_sleepable_lock_deinit(&dmp->dmp_lock);
233 osal_timer_stop(&dmp->dmp_timer);
234 osal_free(dmp);
235 }
236
237 return 0;
238 }
239
240
241 static INT32 wcn_core_dump_check_end(PUINT8 buf, INT32 len)
242 {
243 if (strnstr(buf, "coredump end", len)) {
244 return 1;
245 } else {
246 return 0;
247 }
248 }
249
250
251 /* wcn_core_dump_in - add a packet to compressor buffer
252 * @ dmp - pointer of object
253 * @ buf - input buffer
254 * @ len - data length
255 *
256 * Retunr 0 if success; return 1 if find end string; else error code
257 */
258 INT32 wcn_core_dump_in(P_WCN_CORE_DUMP_T dmp, PUINT8 buf, INT32 len)
259 {
260 INT32 ret = 0;
261 INT32 tmp;
262
263 #define INFO_HEAD ";SOC_CONSYS FW CORE, "
264
265 if ((!dmp) || (!buf)) {
266 STP_DBG_ERR_FUNC("invalid pointer!\n");
267 return -1;
268 }
269
270 ret = osal_lock_sleepable_lock(&dmp->dmp_lock);
271 if (ret) {
272 STP_DBG_ERR_FUNC("--->lock dmp->dmp_lock failed, ret=%d\n", ret);
273 return ret;
274 }
275
276 switch (dmp->sm) {
277 case CORE_DUMP_INIT:
278 wcn_compressor_reset(dmp->compressor, 1, GZIP);
279 osal_timer_start(&dmp->dmp_timer, STP_CORE_DUMP_TIMEOUT);
280
281 // first package, copy to info buffer
282 osal_strcpy(&dmp->info[0], INFO_HEAD);
283
284 if(NULL == (strnstr(buf,"<ASSERT>",32)))
285 {
286 osal_memcpy(&dmp->info[osal_strlen(INFO_HEAD)], "Fw warm reset exception...", osal_strlen("Fw warm reset exception..."));
287 dmp->info[osal_strlen(INFO_HEAD) + osal_strlen("Fw warm reset exception...") + 1] = '\0';
288 }else{
289 char *pStr = buf;
290 char *pDtr = NULL;
291
292 pDtr = osal_strchr(pStr,'-');
293 if(NULL != pDtr)
294 {
295 tmp = pDtr - pStr;
296 osal_memcpy(&dmp->info[osal_strlen(INFO_HEAD)], buf, tmp);
297 dmp->info[osal_strlen(dmp->info) + 1] = '\0';
298 }else
299 {
300 tmp = STP_CORE_DUMP_INFO_SZ - osal_strlen(INFO_HEAD);
301 tmp = (len > tmp) ? tmp : len;
302 osal_memcpy(&dmp->info[osal_strlen(INFO_HEAD)], buf, tmp);
303 dmp->info[STP_CORE_DUMP_INFO_SZ] = '\0';
304 }
305
306 }
307 // show coredump start info on UI
308 //osal_dbg_assert_aee("MT662x f/w coredump start", "MT662x firmware coredump start");
309 #if STP_DBG_AEE_EXP_API
310 aee_kernel_dal_show("SOC_CONSYS coredump start ....\n");
311 #endif
312 // parsing data, and check end srting
313 ret = wcn_core_dump_check_end(buf, len);
314 if (ret == 1) {
315 STP_DBG_INFO_FUNC("core dump end!\n");
316 dmp->sm = CORE_DUMP_DONE;
317 wcn_compressor_in(dmp->compressor, buf, len, 0);
318 } else {
319 dmp->sm = CORE_DUMP_DOING;
320 wcn_compressor_in(dmp->compressor, buf, len, 0);
321 }
322 break;
323
324 case CORE_DUMP_DOING:
325 // parsing data, and check end srting
326 ret = wcn_core_dump_check_end(buf, len);
327 if (ret == 1) {
328 STP_DBG_INFO_FUNC("core dump end!\n");
329 dmp->sm = CORE_DUMP_DONE;
330 wcn_compressor_in(dmp->compressor, buf, len, 0);
331 } else {
332 dmp->sm = CORE_DUMP_DOING;
333 wcn_compressor_in(dmp->compressor, buf, len, 0);
334 }
335 break;
336
337 case CORE_DUMP_DONE:
338 wcn_compressor_reset(dmp->compressor, 1, GZIP);
339 osal_timer_start(&dmp->dmp_timer, STP_CORE_DUMP_TIMEOUT);
340 wcn_compressor_in(dmp->compressor, buf, len, 0);
341 dmp->sm = CORE_DUMP_DOING;
342 break;
343
344 case CORE_DUMP_TIMEOUT:
345 break;
346 default:
347 break;
348 }
349
350 osal_unlock_sleepable_lock(&dmp->dmp_lock);
351
352 return ret;
353 }
354
355
356 /* wcn_core_dump_out - get compressed data from compressor buffer
357 * @ dmp - pointer of object
358 * @ pbuf - target buffer's pointer
359 * @ len - data length
360 *
361 * Retunr 0 if success; else error code
362 */
363 INT32 wcn_core_dump_out(P_WCN_CORE_DUMP_T dmp, PUINT8 *pbuf, PINT32 plen)
364 {
365 INT32 ret = 0;
366
367 if ((!dmp) || (!pbuf) || (!plen)) {
368 STP_DBG_ERR_FUNC("invalid pointer!\n");
369 return -1;
370 }
371
372 ret = osal_lock_sleepable_lock(&dmp->dmp_lock);
373 if (ret) {
374 STP_DBG_ERR_FUNC("--->lock dmp->dmp_lock failed, ret=%d\n", ret);
375 return ret;
376 }
377
378 ret = wcn_compressor_out(dmp->compressor, pbuf, plen);
379
380 osal_unlock_sleepable_lock(&dmp->dmp_lock);
381
382 return ret;
383 }
384
385
386 /* wcn_core_dump_reset - reset core dump sys
387 * @ dmp - pointer of object
388 * @ timeout - core dump time out value
389 *
390 * Retunr 0 if success, else error code
391 */
392 INT32 wcn_core_dump_reset(P_WCN_CORE_DUMP_T dmp, UINT32 timeout)
393 {
394 if (!dmp) {
395 STP_DBG_ERR_FUNC("invalid pointer!\n");
396 return -1;
397 }
398
399 dmp->sm = CORE_DUMP_INIT;
400 dmp->timeout = timeout;
401 osal_timer_stop(&dmp->dmp_timer);
402 wcn_compressor_reset(dmp->compressor, 1, GZIP);
403 osal_memset(dmp->info, 0, STP_CORE_DUMP_INFO_SZ + 1);
404
405 wcn_core_dump_deinit(dmp);
406 g_core_dump = wcn_core_dump_init(STP_CORE_DUMP_TIMEOUT);
407
408 return 0;
409 }
410
411 /* wcn_core_dump_timeout - wait for FW assert info timeout ,this func can collect SYS_FTRACE
412 *
413 * Retunr 0 if success
414 */
415 #define TIMEOUT_INFO_HEAD "Trigger assert timeout ,just collect SYS_FTRACE to DB"
416 INT32 wcn_core_dump_timeout(void)
417 {
418 PUINT8 pbuf;
419 INT32 len;
420
421 pbuf = "Trigger assert timeout";
422 len = osal_strlen("Trigger assert timeout");
423 osal_strcpy(&g_core_dump->info[0], TIMEOUT_INFO_HEAD);
424 aed_combo_exception(NULL, 0, (const int*)pbuf, len, (const char*)g_core_dump->info);
425 return 0;
426 }
427
428 #define ENABLE_F_TRACE 0
429 /* wcn_core_dump_flush - Fulsh dump data and reset core dump sys
430 *
431 * Retunr 0 if success, else error code
432 */
433 INT32 wcn_core_dump_flush(INT32 rst)
434 {
435 PUINT8 pbuf = NULL;
436 INT32 len = 0;
437
438 if (!g_core_dump) {
439 STP_DBG_ERR_FUNC("invalid pointer!\n");
440 return -1;
441 }
442
443 wcn_core_dump_out(g_core_dump, &pbuf, &len);
444 STP_DBG_INFO_FUNC("buf 0x%zx, len %d\n", (SIZE_T)pbuf, len);
445
446 // show coredump end info on UI
447 //osal_dbg_assert_aee("MT662x f/w coredump end", "MT662x firmware coredump ends");
448 #if STP_DBG_AEE_EXP_API
449 aee_kernel_dal_show("++ SOC_CONSYS coredump get successfully ++\n");
450 // call AEE driver API
451 #if ENABLE_F_TRACE
452 aed_combo_exception_api(NULL, 0, (const int*)pbuf, len, (const char*)g_core_dump->info,DB_OPT_FTRACE);
453 #else
454 aed_combo_exception(NULL, 0, (const int*)pbuf, len, (const char*)g_core_dump->info);
455 #endif
456
457 #endif
458
459 // reset
460 wcn_core_dump_reset(g_core_dump, STP_CORE_DUMP_TIMEOUT);
461
462 return 0;
463 }
464
465
466 static INT32 wcn_gzip_compressor(void *worker, UINT8 *in_buf, INT32 in_sz, UINT8 *out_buf, INT32 *out_sz, INT32 finish)
467 {
468 INT32 ret = 0;
469 z_stream *stream = NULL;
470 INT32 tmp = *out_sz;
471
472 STP_DBG_INFO_FUNC("in buf 0x%zx, in sz %d\n", (SIZE_T)in_buf, in_sz);
473 STP_DBG_INFO_FUNC("out buf 0x%zx, out sz %d\n", (SIZE_T)out_buf, tmp);
474
475 stream = (z_stream*)worker;
476 if (!stream) {
477 STP_DBG_ERR_FUNC("invalid workspace!\n");
478 return -1;
479 }
480
481 if (in_sz > 0) {
482 #if 0
483 ret = zlib_deflateReset(stream);
484 if (ret != Z_OK) {
485 STP_DBG_ERR_FUNC("reset failed!\n");
486 return -2;
487 }
488 #endif
489
490 stream->next_in = in_buf;
491 stream->avail_in = in_sz;
492 stream->next_out = out_buf;
493 stream->avail_out = tmp;
494
495 zlib_deflate(stream, Z_FULL_FLUSH);
496
497 if (finish) {
498 while (1) {
499 int val = zlib_deflate(stream, Z_FINISH);
500 if (val == Z_OK) {
501 continue;
502 } else if (val == Z_STREAM_END) {
503 break;
504 } else {
505 STP_DBG_ERR_FUNC("finish operation failed %d\n", val);
506 return -3;
507 }
508 }
509 }
510
511 *out_sz = tmp - stream->avail_out;
512 }
513
514 STP_DBG_INFO_FUNC("out buf 0x%zx, out sz %d\n", (SIZE_T)out_buf, *out_sz);
515
516 return ret;
517 }
518
519
520 /* wcn_compressor_init - create a compressor and do init
521 * @ name - compressor's name
522 * @ L1_buf_sz - L1 buffer size
523 * @ L2_buf_sz - L2 buffer size
524 *
525 * Retunr object's pointer if success, else NULL
526 */
527 P_WCN_COMPRESSOR_T wcn_compressor_init(PUINT8 name, INT32 L1_buf_sz, INT32 L2_buf_sz)
528 {
529 z_stream *pstream = NULL;
530 P_WCN_COMPRESSOR_T compress = NULL;
531
532 compress = (P_WCN_COMPRESSOR_T)osal_malloc(sizeof(WCN_COMPRESSOR_T));
533 if (!compress) {
534 STP_DBG_ERR_FUNC("alloc compressor failed!\n");
535 goto fail;
536 }
537
538 osal_memset(compress, 0, sizeof(WCN_COMPRESSOR_T));
539 osal_memcpy(compress->name, name, STP_OJB_NAME_SZ);
540
541 compress->f_compress_en = 0;
542 compress->compress_type = GZIP;
543
544 if (compress->compress_type == GZIP) {
545 compress->worker = osal_malloc(sizeof(z_stream));
546 if (!compress->worker) {
547 STP_DBG_ERR_FUNC("alloc stream failed!\n");
548 goto fail;
549 }
550 pstream = (z_stream*)compress->worker;
551
552 pstream->workspace = osal_malloc(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL));
553 if (!pstream->workspace) {
554 STP_DBG_ERR_FUNC("alloc workspace failed!\n");
555 goto fail;
556 }
557 zlib_deflateInit2(pstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS,
558 DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
559 }
560
561 compress->handler = wcn_gzip_compressor;
562 compress->L1_buf_sz = L1_buf_sz;
563 compress->L2_buf_sz = L2_buf_sz;
564 compress->L1_pos = 0;
565 compress->L2_pos = 0;
566 compress->uncomp_size = 0;
567 compress->crc32 = 0xffffffffUL;
568
569 compress->L1_buf = osal_malloc(compress->L1_buf_sz);
570 if (!compress->L1_buf) {
571 STP_DBG_ERR_FUNC("alloc %d bytes for L1 buf failed!\n", compress->L1_buf_sz);
572 goto fail;
573 }
574
575 compress->L2_buf = osal_malloc(compress->L2_buf_sz);
576 if (!compress->L2_buf) {
577 STP_DBG_ERR_FUNC("alloc %d bytes for L2 buf failed!\n", compress->L2_buf_sz);
578 goto fail;
579 }
580
581 STP_DBG_INFO_FUNC("create compressor OK! L1 %d bytes, L2 %d bytes\n", L1_buf_sz, L2_buf_sz);
582 return compress;
583
584 fail:
585 if (compress) {
586 if (compress->L2_buf) {
587 osal_free(compress->L2_buf);
588 compress->L2_buf = NULL;
589 }
590
591 if (compress->L1_buf) {
592 osal_free(compress->L1_buf);
593 compress->L1_buf = NULL;
594 }
595
596 if (compress->worker) {
597 pstream = (z_stream*)compress->worker;
598 if ((compress->compress_type == GZIP) && pstream->workspace) {
599 zlib_deflateEnd(pstream);
600 osal_free(pstream->workspace);
601 }
602 osal_free(compress->worker);
603 compress->worker = NULL;
604 }
605
606 if (compress->worker) {
607 osal_free(compress->worker);
608 compress->worker = NULL;
609 }
610
611 osal_free(compress);
612 compress = NULL;
613 }
614
615 STP_DBG_ERR_FUNC("init failed!\n");
616
617 return NULL;
618 }
619
620
621 /* wcn_compressor_deinit - distroy a compressor
622 * @ cprs - compressor's pointer
623 *
624 * Retunr 0 if success, else NULL
625 */
626 INT32 wcn_compressor_deinit(P_WCN_COMPRESSOR_T cprs)
627 {
628 z_stream *pstream = NULL;
629
630 if (cprs) {
631 if (cprs->L2_buf) {
632 osal_free(cprs->L2_buf);
633 cprs->L2_buf = NULL;
634 }
635
636 if (cprs->L1_buf) {
637 osal_free(cprs->L1_buf);
638 cprs->L1_buf = NULL;
639 }
640
641 if (cprs->worker) {
642 pstream = (z_stream*)cprs->worker;
643 if ((cprs->compress_type == GZIP) && pstream->workspace) {
644 zlib_deflateEnd(pstream);
645 osal_free(pstream->workspace);
646 }
647 osal_free(cprs->worker);
648 cprs->worker = NULL;
649 }
650
651 cprs->handler = NULL;
652
653 osal_free(cprs);
654 }
655
656 STP_DBG_INFO_FUNC("destroy OK\n");
657
658 return 0;
659 }
660
661
662 /* wcn_compressor_in - put in a raw data, and compress L1 buffer if need
663 * @ cprs - compressor's pointer
664 * @ buf - raw data buffer
665 * @ len - raw data length
666 * @ finish - core dump finish or not, 1: finished; 0: not finish
667 *
668 * Retunr 0 if success, else NULL
669 */
670 INT32 wcn_compressor_in(P_WCN_COMPRESSOR_T cprs, PUINT8 buf, INT32 len, INT32 finish)
671 {
672 INT32 tmp_len = 0;
673 INT32 ret = 0;
674
675 if (!cprs) {
676 STP_DBG_ERR_FUNC("invalid para!\n");
677 return -1;
678 }
679
680 cprs->uncomp_size += len;
681
682 // check L1 buf valid space
683 if (len > (cprs->L1_buf_sz - cprs->L1_pos)) {
684 STP_DBG_INFO_FUNC("L1 buffer full\n");
685
686 if (cprs->f_compress_en && cprs->handler) {
687 // need compress
688 // compress L1 buffer, and put result to L2 buffer
689 tmp_len = cprs->L2_buf_sz - cprs->L2_pos;
690 ret = cprs->handler(cprs->worker, cprs->L1_buf, cprs->L1_pos, &cprs->L2_buf[cprs->L2_pos], &tmp_len, finish);
691 if (!ret) {
692 cprs->crc32 = (crc32(cprs->crc32, cprs->L1_buf, cprs->L1_pos));
693 cprs->L2_pos += tmp_len;
694
695 if (finish) {
696 /* Add 8 byte suffix
697 ===
698 32 bits UNCOMPRESS SIZE
699 32 bits CRC
700 */
701 *(uint32_t *)(&cprs->L2_buf[cprs->L2_pos]) = (cprs->crc32 ^ 0xffffffffUL);
702 *(uint32_t *)(&cprs->L2_buf[cprs->L2_pos + 4]) = cprs->uncomp_size;
703 cprs->L2_pos += 8;
704 }
705 STP_DBG_INFO_FUNC("compress OK!\n");
706 } else {
707 STP_DBG_ERR_FUNC("compress error!\n");
708 }
709 } else {
710 // no need compress
711 // Flush L1 buffer to L2 buffer
712 STP_DBG_INFO_FUNC("No need do compress, Put to L2 buf\n");
713
714 tmp_len = cprs->L2_buf_sz - cprs->L2_pos;
715 tmp_len = (cprs->L1_pos > tmp_len) ? tmp_len : cprs->L1_pos;
716 osal_memcpy(&cprs->L2_buf[cprs->L2_pos], cprs->L1_buf, tmp_len);
717 cprs->L2_pos += tmp_len;
718 }
719
720 // reset L1 buf pos
721 cprs->L1_pos = 0;
722
723 // put curren data to L1 buf
724 if (len > cprs->L1_buf_sz) {
725 STP_DBG_ERR_FUNC("len=%d, too long err!\n", len);
726 } else {
727 STP_DBG_INFO_FUNC("L1 Flushed, and Put %d bytes to L1 buf\n", len);
728 osal_memcpy(&cprs->L1_buf[cprs->L1_pos], buf, len);
729 cprs->L1_pos += len;
730 }
731 } else {
732 // put to L1 buffer
733 STP_DBG_INFO_FUNC("Put %d bytes to L1 buf\n", len);
734
735 osal_memcpy(&cprs->L1_buf[cprs->L1_pos], buf, len);
736 cprs->L1_pos += len;
737 }
738
739 return ret;
740 }
741
742
743 /* wcn_compressor_out - get the result data from L2 buffer
744 * @ cprs - compressor's pointer
745 * @ pbuf - point to L2 buffer
746 * @ plen - out len
747 *
748 * Retunr 0 if success, else NULL
749 */
750 INT32 wcn_compressor_out(P_WCN_COMPRESSOR_T cprs, PUINT8 *pbuf, PINT32 plen)
751 {
752 INT32 ret = 0;
753 INT32 tmp_len = 0;
754
755 if ((!cprs) || (!pbuf) || (!plen)) {
756 STP_DBG_ERR_FUNC("invalid para!\n");
757 return -1;
758 }
759
760 // check if there's L1 data need flush to L2 buffer
761 if (cprs->L1_pos > 0) {
762 tmp_len = cprs->L2_buf_sz - cprs->L2_pos;
763
764 if (cprs->f_compress_en && cprs->handler) {
765 // need compress
766 ret = cprs->handler(cprs->worker, cprs->L1_buf, cprs->L1_pos, &cprs->L2_buf[cprs->L2_pos], &tmp_len, 1);
767
768 if (!ret) {
769 cprs->crc32 = (crc32(cprs->crc32, cprs->L1_buf, cprs->L1_pos));
770 cprs->L2_pos += tmp_len;
771
772 /* Add 8 byte suffix
773 ===
774 32 bits UNCOMPRESS SIZE
775 32 bits CRC
776 */
777 *(uint32_t *)(&cprs->L2_buf[cprs->L2_pos]) = (cprs->crc32 ^ 0xffffffffUL);
778 *(uint32_t *)(&cprs->L2_buf[cprs->L2_pos + 4]) = cprs->uncomp_size;
779 cprs->L2_pos += 8;
780
781 STP_DBG_INFO_FUNC("compress OK!\n");
782 } else {
783 STP_DBG_ERR_FUNC("compress error!\n");
784 }
785 } else {
786 // no need compress
787 tmp_len = (cprs->L1_pos > tmp_len) ? tmp_len : cprs->L1_pos;
788 osal_memcpy(&cprs->L2_buf[cprs->L2_pos], cprs->L1_buf, tmp_len);
789 cprs->L2_pos += tmp_len;
790 }
791
792 cprs->L1_pos = 0;
793 }
794
795
796 *pbuf = cprs->L2_buf;
797 *plen = cprs->L2_pos;
798
799 STP_DBG_INFO_FUNC("0x%zx, len %d\n", (SIZE_T)*pbuf, *plen);
800
801 return 0;
802 }
803
804
805 /* wcn_compressor_reset - reset compressor
806 * @ cprs - compressor's pointer
807 * @ enable - enable/disable compress
808 * @ type - compress algorithm
809 *
810 * Retunr 0 if success, else NULL
811 */
812 INT32 wcn_compressor_reset(P_WCN_COMPRESSOR_T cprs, UINT8 enable, WCN_COMPRESS_ALG_T type)
813 {
814 if (!cprs) {
815 STP_DBG_ERR_FUNC("invalid para!\n");
816 return -1;
817 }
818
819 cprs->f_compress_en = enable;
820 //cprs->f_compress_en = 0; // disable compress for test
821 cprs->compress_type = type;
822 cprs->L1_pos = 0;
823 cprs->L2_pos = 0;
824 cprs->uncomp_size = 0;
825 cprs->crc32 = 0xffffffffUL;
826
827 //zlib_deflateEnd((z_stream*)cprs->worker);
828
829 STP_DBG_INFO_FUNC("OK! compress algorithm %d\n", type);
830
831 return 0;
832 }
833
834
835 static void stp_dbg_dump_data(unsigned char *pBuf, char * title, int len)
836 {
837 int k = 0;
838 printk(" %s-len:%d\n", title, len);
839 //printk(" ", title, len);
840 for(k=0; k < len ; k++){
841 if(k%16 == 0 && k != 0) printk("\n ");
842 printk("0x%02x ", pBuf[k]);
843 }
844 printk("--end\n");
845 }
846
847
848 static int _stp_dbg_enable(MTKSTP_DBG_T *stp_dbg){
849
850 unsigned long flags;
851
852 spin_lock_irqsave(&(stp_dbg->logsys->lock), flags);
853 stp_dbg->pkt_trace_no=0;
854 stp_dbg->is_enable=1;
855 spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags);
856
857 return 0;
858 }
859
860 static int _stp_dbg_disable(MTKSTP_DBG_T *stp_dbg){
861
862 unsigned long flags;
863
864 spin_lock_irqsave(&(stp_dbg->logsys->lock), flags);
865 stp_dbg->pkt_trace_no=0;
866 memset(stp_dbg->logsys, 0, sizeof(MTKSTP_LOG_SYS_T));
867 stp_dbg->is_enable=0;
868 spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags);
869
870 return 0;
871 }
872
873 static int _stp_dbg_dmp_in(MTKSTP_DBG_T *stp_dbg, char *buf, int len){
874
875 unsigned long flags;
876 unsigned int internalFlag = stp_dbg->logsys->size < STP_DBG_LOG_ENTRY_NUM;
877 //#ifdef CONFIG_LOG_STP_INTERNAL
878 //Here we record log in this circle buffer, if buffer is full , select to overlap earlier log, logic should be okay
879 internalFlag = 1;
880 //#endif
881 spin_lock_irqsave(&(stp_dbg->logsys->lock), flags);
882
883 if(internalFlag){
884 stp_dbg->logsys->queue[stp_dbg->logsys->in].id = 0;
885 stp_dbg->logsys->queue[stp_dbg->logsys->in].len = len;
886 memset(&(stp_dbg->logsys->queue[stp_dbg->logsys->in].buffer[0]),
887 0, ((len >= STP_DBG_LOG_ENTRY_SZ)? (STP_DBG_LOG_ENTRY_SZ):(len)));
888 memcpy(&(stp_dbg->logsys->queue[stp_dbg->logsys->in].buffer[0]),
889 buf, ((len >= STP_DBG_LOG_ENTRY_SZ)? (STP_DBG_LOG_ENTRY_SZ):(len)));
890
891 stp_dbg->logsys->size++;
892 stp_dbg->logsys->size = (stp_dbg->logsys->size > STP_DBG_LOG_ENTRY_NUM) ? STP_DBG_LOG_ENTRY_NUM : stp_dbg->logsys->size;
893
894 if (0 != gStpDbgLogOut)
895 {
896 STP_DBG_HDR_T *pHdr = NULL;
897 char* pBuf = NULL;
898 unsigned int len =0;
899 pHdr = (STP_DBG_HDR_T *)&(stp_dbg->logsys->queue[stp_dbg->logsys->in].buffer[0]);
900 pBuf = (char *)&(stp_dbg->logsys->queue[stp_dbg->logsys->in].buffer[0]) + sizeof (STP_DBG_HDR_T);
901 len = stp_dbg->logsys->queue[stp_dbg->logsys->in].len - sizeof (STP_DBG_HDR_T);
902 printk("STP-DBG:%d.%ds, %s:pT%sn(%d)l(%d)s(%d)a(%d)\n", \
903 pHdr->sec,
904 pHdr->usec,
905 pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx",
906 gStpDbgType[pHdr->type],
907 pHdr->no,
908 pHdr->len,
909 pHdr->seq,
910 pHdr->ack
911
912 );
913 if (0 < len){
914 stp_dbg_dump_data(pBuf, pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx", len);
915 }
916
917 }
918 stp_dbg->logsys->in = (stp_dbg->logsys->in >= (STP_DBG_LOG_ENTRY_NUM - 1))?(0):(stp_dbg->logsys->in + 1);
919 STP_DBG_DBG_FUNC("logsys size = %d, in = %d\n", stp_dbg->logsys->size, stp_dbg->logsys->in);
920 } else {
921 STP_DBG_WARN_FUNC("logsys FULL!\n");
922 }
923
924 spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags);
925
926 return 0;
927 }
928
929 int stp_gdb_notify_btm_dmp_wq(MTKSTP_DBG_T *stp_dbg){
930 int retval = 0;
931 //#ifndef CONFIG_LOG_STP_INTERNAL
932
933 if(stp_dbg->btm != NULL){
934 retval += stp_btm_notify_wmt_dmp_wq((MTKSTP_BTM_T *)stp_dbg->btm);
935 }
936
937 //#endif
938
939 return retval;
940 }
941
942 int stp_dbg_log_ctrl (unsigned int on)
943 {
944 if (on != 0)
945 {
946 gStpDbgLogOut = 1;
947 printk ("STP-DBG: enable pkt log dump out.\n");
948 }
949 else
950 {
951 gStpDbgLogOut = 0;
952 printk ("STP-DBG: disable pkt log dump out.\n");
953 }
954 return 0;
955 }
956
957 int stp_dbg_dmp_in(MTKSTP_DBG_T *stp_dbg, char *buf, int len){
958 return _stp_dbg_dmp_in(stp_dbg, buf, len);
959 }
960
961
962 int stp_dbg_dmp_printk(MTKSTP_DBG_T *stp_dbg)
963 {
964 #define MAX_DMP_NUM 80
965 unsigned long flags;
966 char *pBuf = NULL;
967 int len = 0;
968 STP_DBG_HDR_T *pHdr = NULL;
969 UINT32 dumpSize = 0;
970 UINT32 inIndex = 0;
971 UINT32 outIndex = 0;
972 spin_lock_irqsave(&(stp_dbg->logsys->lock), flags);
973 //Not to dequeue from loging system
974 inIndex = stp_dbg->logsys->in;
975 dumpSize = stp_dbg->logsys->size;
976 if (STP_DBG_LOG_ENTRY_NUM == dumpSize)
977 {
978 outIndex = inIndex;
979 }
980 else
981 {
982 outIndex = ((inIndex + STP_DBG_LOG_ENTRY_NUM) - dumpSize) % STP_DBG_LOG_ENTRY_NUM;
983 }
984
985 if (dumpSize > MAX_DMP_NUM)
986 {
987
988 outIndex += (dumpSize - MAX_DMP_NUM);
989 outIndex %= STP_DBG_LOG_ENTRY_NUM;
990 dumpSize = MAX_DMP_NUM;
991
992 }
993 STP_DBG_INFO_FUNC("loged packet size = %d, in(%d), out(%d)\n", dumpSize, inIndex, outIndex);
994 while(dumpSize > 0){
995 pHdr = (STP_DBG_HDR_T *)&(stp_dbg->logsys->queue[outIndex].buffer[0]);
996 pBuf = &(stp_dbg->logsys->queue[outIndex].buffer[0]) + sizeof (STP_DBG_HDR_T);
997 len = stp_dbg->logsys->queue[outIndex].len - sizeof (STP_DBG_HDR_T);
998 len = len > STP_PKT_SZ ? STP_PKT_SZ : len;
999 printk("STP-DBG:%d.%ds, %s:pT%sn(%d)l(%d)s(%d)a(%d)\n", \
1000 pHdr->sec,
1001 pHdr->usec,
1002 pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx",
1003 gStpDbgType[pHdr->type],
1004 pHdr->no,
1005 pHdr->len,
1006 pHdr->seq,
1007 pHdr->ack
1008 );
1009
1010
1011 if (0 < len){
1012 stp_dbg_dump_data(pBuf, pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx", len);
1013 }
1014 outIndex = (outIndex >= (STP_DBG_LOG_ENTRY_NUM - 1))?(0):(outIndex + 1);
1015 dumpSize--;
1016
1017 }
1018
1019
1020 spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags);
1021
1022 return 0;
1023 }
1024
1025 int stp_dbg_dmp_out_ex (char *buf, int *len){
1026 return stp_dbg_dmp_out(g_stp_dbg, buf, len);
1027 }
1028
1029 int stp_dbg_dmp_out(MTKSTP_DBG_T *stp_dbg, char *buf, int *len){
1030
1031 unsigned long flags;
1032 int remaining = 0;
1033 *len = 0;
1034 spin_lock_irqsave(&(stp_dbg->logsys->lock), flags);
1035
1036 if(stp_dbg->logsys->size > 0){
1037 memcpy(buf, &(stp_dbg->logsys->queue[stp_dbg->logsys->out].buffer[0]),
1038 stp_dbg->logsys->queue[stp_dbg->logsys->out].len);
1039
1040 (*len) = stp_dbg->logsys->queue[stp_dbg->logsys->out].len;
1041 stp_dbg->logsys->out = (stp_dbg->logsys->out >= (STP_DBG_LOG_ENTRY_NUM - 1))?(0):(stp_dbg->logsys->out + 1);
1042 stp_dbg->logsys->size--;
1043
1044 STP_DBG_DBG_FUNC("logsys size = %d, out = %d\n", stp_dbg->logsys->size, stp_dbg->logsys->out);
1045 } else {
1046 STP_DBG_LOUD_FUNC("logsys EMPTY!\n");
1047 }
1048
1049 remaining = (stp_dbg->logsys->size == 0)?(0):(1);
1050
1051 spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags);
1052
1053 return remaining;
1054 }
1055
1056 static int stp_dbg_fill_hdr(struct stp_dbg_pkt_hdr *hdr, int type, int ack, int seq, int crc, int dir, int len, int dbg_type){
1057
1058 struct timeval now;
1059
1060 if(!hdr){
1061 STP_DBG_ERR_FUNC("function invalid\n");
1062 return -EINVAL;
1063 } else {
1064 do_gettimeofday(&now);
1065 hdr->dbg_type = dbg_type;
1066 hdr->ack = ack;
1067 hdr->seq = seq;
1068 hdr->sec = now.tv_sec;
1069 hdr->usec = now.tv_usec;
1070 hdr->crc = crc;
1071 hdr->dir = dir;//rx
1072 hdr->dmy = 0xffffffff;
1073 hdr->len = len;
1074 hdr->type = type;
1075 return 0;
1076 }
1077 }
1078
1079 static int
1080 stp_dbg_add_pkt (
1081 MTKSTP_DBG_T*stp_dbg,
1082 struct stp_dbg_pkt_hdr *hdr,
1083 const unsigned char *body
1084 )
1085 {
1086 //fix the frame size large issues.
1087 static struct stp_dbg_pkt stp_pkt;
1088 uint32_t hdr_sz = sizeof(struct stp_dbg_pkt_hdr);
1089 uint32_t body_sz = 0;
1090
1091 BUG_ON(!stp_dbg);
1092
1093 if(hdr->dbg_type == STP_DBG_PKT){
1094 body_sz = (hdr->len <= STP_PKT_SZ)?(hdr->len):(STP_PKT_SZ);
1095 }else{
1096 body_sz = (hdr->len <= STP_DMP_SZ)?(hdr->len):(STP_DMP_SZ);
1097 }
1098
1099 hdr->no = stp_dbg->pkt_trace_no++;
1100 memcpy((uint8_t *)&stp_pkt.hdr, (uint8_t*)hdr, hdr_sz);
1101 if(body != NULL){
1102 memcpy((uint8_t *)&stp_pkt.raw[0], body, body_sz);
1103 }
1104 _stp_dbg_dmp_in(stp_dbg, (char *) &stp_pkt, hdr_sz + body_sz);
1105 //Only FW DMP MSG should inform BTM-CORE to dump packet to native process
1106 if(hdr->dbg_type == STP_DBG_FW_DMP)
1107 {
1108 stp_gdb_notify_btm_dmp_wq(stp_dbg);
1109 }
1110
1111 return 0;
1112 }
1113
1114 int stp_dbg_log_pkt(MTKSTP_DBG_T *stp_dbg, int dbg_type,
1115 int type, int ack_no, int seq_no, int crc, int dir, int len, const unsigned char *body) {
1116
1117 struct stp_dbg_pkt_hdr hdr;
1118
1119 if (stp_dbg->is_enable == 0) {
1120 /*dbg is disable,and not to log*/
1121 }
1122 else {
1123 stp_dbg_fill_hdr(&hdr,
1124 (int) type,
1125 (int) ack_no,
1126 (int) seq_no,
1127 (int) crc,
1128 (int) dir,
1129 (int) len,
1130 (int) dbg_type);
1131
1132 stp_dbg_add_pkt(stp_dbg, &hdr, body);
1133 }
1134
1135 return 0;
1136 }
1137
1138 int stp_dbg_enable(MTKSTP_DBG_T *stp_dbg){
1139 return _stp_dbg_enable(stp_dbg);
1140 }
1141
1142 int stp_dbg_disable(MTKSTP_DBG_T *stp_dbg){
1143 return _stp_dbg_disable(stp_dbg);
1144 }
1145
1146 static void stp_dbg_nl_init(void)
1147 {
1148 if(genl_register_family(&stp_dbg_gnl_family) != 0)
1149 {
1150 STP_DBG_ERR_FUNC("%s(): GE_NELINK family registration fail\n", __func__);
1151 }
1152 else
1153 {
1154 if(genl_register_ops(&stp_dbg_gnl_family, &stp_dbg_gnl_ops_bind) != 0)
1155 {
1156 STP_DBG_ERR_FUNC("%s(): BIND operation registration fail\n", __func__);
1157 }
1158
1159 if(genl_register_ops(&stp_dbg_gnl_family, &stp_dbg_gnl_ops_reset) != 0)
1160 {
1161 STP_DBG_ERR_FUNC("%s(): RESET operation registration fail\n", __func__);
1162 }
1163 }
1164
1165 return;
1166 }
1167
1168 static void stp_dbg_nl_deinit(void)
1169 {
1170 genl_unregister_family(&stp_dbg_gnl_family);
1171 return;
1172 }
1173
1174 static int stp_dbg_nl_bind(
1175 struct sk_buff *skb,
1176 struct genl_info *info
1177 )
1178 {
1179 struct nlattr *na;
1180 char * mydata;
1181
1182 if (info == NULL)
1183 {
1184 goto out;
1185 }
1186
1187 STP_DBG_INFO_FUNC("%s():->\n", __func__);
1188
1189 na = info->attrs[STP_DBG_ATTR_MSG];
1190
1191 if (na)
1192 {
1193 mydata = (char *)nla_data(na);
1194 }
1195
1196 if(num_bind_process < MAX_BIND_PROCESS)
1197 {
1198
1199 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1200 bind_pid[num_bind_process] = info->snd_pid;
1201 num_bind_process++;
1202 STP_DBG_INFO_FUNC("%s():-> pid = %d\n", __func__, info->snd_pid);
1203 #else
1204 bind_pid[num_bind_process] = info->snd_portid;
1205 num_bind_process++;
1206 STP_DBG_INFO_FUNC("%s():-> pid = %d\n", __func__, info->snd_portid);
1207 #endif
1208 }
1209 else
1210 {
1211 STP_DBG_ERR_FUNC("%s(): exceeding binding limit %d\n", __func__, MAX_BIND_PROCESS);
1212 }
1213
1214 out:
1215 return 0;
1216 }
1217
1218 static int stp_dbg_nl_reset(
1219 struct sk_buff *skb,
1220 struct genl_info *info
1221 )
1222 {
1223 STP_DBG_ERR_FUNC("%s(): should not be invoked\n", __func__);
1224
1225 return 0;
1226 }
1227
1228 char
1229 stp_dbg_nl_send(
1230 char * aucMsg,
1231 unsigned char cmd
1232 )
1233 {
1234 struct sk_buff *skb = NULL;
1235 void *msg_head = NULL;
1236 int rc = -1;
1237 int i;
1238
1239 if(num_bind_process == 0)
1240 {
1241 /* no listening process */
1242 STP_DBG_ERR_FUNC("%s(): the process is not invoked\n", __func__);
1243 return 0;
1244 }
1245
1246 for(i = 0 ; i < num_bind_process ; i++)
1247 {
1248 skb = genlmsg_new(2048, GFP_KERNEL);
1249
1250 if(skb)
1251 {
1252 msg_head = genlmsg_put(skb, 0, stp_dbg_seqnum++, &stp_dbg_gnl_family, 0, cmd);
1253 if(msg_head == NULL)
1254 {
1255 nlmsg_free(skb);
1256 STP_DBG_ERR_FUNC("%s(): genlmsg_put fail...\n", __func__);
1257 return -1;
1258 }
1259
1260 rc = nla_put_string(skb, STP_DBG_ATTR_MSG, aucMsg);
1261 if(rc != 0)
1262 {
1263 nlmsg_free(skb);
1264 STP_DBG_ERR_FUNC("%s(): nla_put_string fail...\n", __func__);
1265 return -1;
1266 }
1267
1268 /* finalize the message */
1269 genlmsg_end(skb, msg_head);
1270
1271 /* sending message */
1272 rc = genlmsg_unicast(&init_net, skb, bind_pid[i]);
1273 if(rc != 0)
1274 {
1275 STP_DBG_ERR_FUNC("%s(): genlmsg_unicast fail...\n", __func__);
1276 return -1;
1277 }
1278 }
1279 else
1280 {
1281 STP_DBG_ERR_FUNC("%s(): genlmsg_new fail...\n", __func__);
1282 return -1;
1283 }
1284 }
1285
1286 return 0;
1287 }
1288
1289
1290 INT32 stp_dbg_aee_send(unsigned char *aucMsg, INT32 len, INT32 cmd)
1291 {
1292 INT32 ret = 0;
1293
1294 // buffered to compressor
1295 ret = wcn_core_dump_in(g_core_dump, aucMsg, len);
1296 if (ret == 1) {
1297 wcn_core_dump_flush(0);
1298 }
1299
1300 return ret;
1301 }
1302 UINT8 *_stp_dbg_id_to_task(UINT32 id)
1303 {
1304 UINT8 *taskStr[] =
1305 {
1306 "Task_WMT",
1307 "Task_BT",
1308 "Task_Wifi",
1309 "Task_Tst",
1310 "Task_FM",
1311 "Task_Idle",
1312 "Task_DrvStp",
1313 "Task_DrvBtif",
1314 "Task_NatBt"
1315 };
1316 return taskStr[id];
1317 }
1318 INT32 _stp_dbg_parser_assert_str(PINT8 str,ENUM_ASSERT_INFO_PARSER_TYPE type)
1319 {
1320 char *pStr = NULL;
1321 char *pDtr = NULL;
1322 char *pTemp = NULL;
1323 char *pTemp2 = NULL;
1324 char tempBuf[64] = {0};
1325 UINT32 len = 0;
1326
1327 char *parser_sub_string[] =
1328 {
1329 "<ASSERT> ",
1330 "id=",
1331 "isr=",
1332 "irq=",
1333 "rc="
1334 };
1335
1336 if(!str)
1337 {
1338 STP_DBG_ERR_FUNC("NULL string source\n");
1339 return -1;
1340 }
1341
1342 if(!g_stp_dbg_cpupcr)
1343 {
1344 STP_DBG_ERR_FUNC("NULL pointer\n");
1345 return -2;
1346 }
1347
1348 pStr = str;
1349 STP_DBG_DBG_FUNC("source infor:%s\n",pStr);
1350 switch(type){
1351 case STP_DBG_ASSERT_INFO:
1352 pDtr = osal_strstr(pStr,parser_sub_string[type]);
1353 if(NULL != pDtr)
1354 {
1355 pDtr += osal_strlen(parser_sub_string[type]);
1356 pTemp = osal_strchr(pDtr,' ');
1357 }else
1358 {
1359 STP_DBG_ERR_FUNC("parser str is NULL,substring(%s)\n",parser_sub_string[type]);
1360 return -3;
1361 }
1362 len = pTemp - pDtr;
1363 osal_memcpy(&g_stp_dbg_cpupcr->assert_info[0],"assert@",osal_strlen("assert@"));
1364 osal_memcpy(&g_stp_dbg_cpupcr->assert_info[osal_strlen("assert@")],pDtr,len);
1365 g_stp_dbg_cpupcr->assert_info[osal_strlen("assert@") + len] = '_';
1366
1367 pTemp = osal_strchr(pDtr,'#');
1368 pTemp += 1;
1369
1370 pTemp2 = osal_strchr(pTemp,' ');
1371 osal_memcpy(&g_stp_dbg_cpupcr->assert_info[osal_strlen("assert@") + len + 1],pTemp,pTemp2 - pTemp);
1372 g_stp_dbg_cpupcr->assert_info[osal_strlen("assert@") + len + 1 + pTemp2 - pTemp] = '\0';
1373 STP_DBG_INFO_FUNC("assert info:%s\n",&g_stp_dbg_cpupcr->assert_info[0]);
1374 break;
1375 case STP_DBG_FW_TASK_ID:
1376 pDtr = osal_strstr(pStr,parser_sub_string[type]);
1377 if(NULL != pDtr)
1378 {
1379 pDtr += osal_strlen(parser_sub_string[type]);
1380 pTemp = osal_strchr(pDtr,' ');
1381 }else
1382 {
1383 STP_DBG_ERR_FUNC("parser str is NULL,substring(%s)\n",parser_sub_string[type]);
1384 return -3;
1385 }
1386 len = pTemp - pDtr;
1387 osal_memcpy(&tempBuf[0],pDtr,len);
1388 tempBuf[len] = '\0';
1389 g_stp_dbg_cpupcr->fwTaskId = osal_strtol(tempBuf, NULL, 16);
1390
1391 STP_DBG_INFO_FUNC("fw task id :%x\n",(UINT32)osal_strtol(tempBuf, NULL, 16));
1392 break;
1393 case STP_DBG_FW_ISR:
1394 pDtr = osal_strstr(pStr,parser_sub_string[type]);
1395 if(NULL != pDtr)
1396 {
1397 pDtr += osal_strlen(parser_sub_string[type]);
1398 pTemp = osal_strchr(pDtr,',');
1399 }else
1400 {
1401 STP_DBG_ERR_FUNC("parser str is NULL,substring(%s)\n",parser_sub_string[type]);
1402 return -3;
1403 }
1404 len = pTemp - pDtr;
1405 osal_memcpy(&tempBuf[0],pDtr,len);
1406 tempBuf[len] = '\0';
1407
1408 g_stp_dbg_cpupcr->fwIsr = osal_strtol(tempBuf, NULL, 16);
1409
1410 STP_DBG_INFO_FUNC("fw isr str:%x\n",(UINT32)osal_strtol(tempBuf, NULL, 16));
1411 break;
1412 case STP_DBG_FW_IRQ:
1413 pDtr = osal_strstr(pStr,parser_sub_string[type]);
1414 if(NULL != pDtr)
1415 {
1416 pDtr += osal_strlen(parser_sub_string[type]);
1417 pTemp = osal_strchr(pDtr,',');
1418 }else
1419 {
1420 STP_DBG_ERR_FUNC("parser str is NULL,substring(%s)\n",parser_sub_string[type]);
1421 return -3;
1422 }
1423 len = pTemp - pDtr;
1424 osal_memcpy(&tempBuf[0],pDtr,len);
1425 tempBuf[len] = '\0';
1426 g_stp_dbg_cpupcr->fwRrq = osal_strtol(tempBuf, NULL, 16);
1427
1428 STP_DBG_INFO_FUNC("fw irq value:%x\n",(UINT32)osal_strtol(tempBuf, NULL, 16));
1429 break;
1430 case STP_DBG_ASSERT_TYPE:
1431 pDtr = osal_strstr(pStr,parser_sub_string[type]);
1432 if(NULL != pDtr)
1433 {
1434 pDtr += osal_strlen(parser_sub_string[type]);
1435 pTemp = osal_strchr(pDtr,',');
1436 }else
1437 {
1438 STP_DBG_ERR_FUNC("parser str is NULL,substring(%s)\n",parser_sub_string[type]);
1439 return -3;
1440 }
1441 len = pTemp - pDtr;
1442 osal_memcpy(&tempBuf[0],pDtr,len);
1443 tempBuf[len] = '\0';
1444
1445 if(0 == osal_memcmp(tempBuf,"*",len))
1446 {
1447 osal_memcpy(&g_stp_dbg_cpupcr->assert_type[0],"general assert",osal_strlen("general assert"));
1448 }
1449 if(0 == osal_memcmp(tempBuf,"Watch Dog Timeout",len))
1450 {
1451 osal_memcpy(&g_stp_dbg_cpupcr->assert_type[0],"wdt",osal_strlen("wdt"));
1452 }
1453 if(0 == osal_memcmp(tempBuf,"RB_FULL",osal_strlen("RB_FULL")))
1454 {
1455 osal_memcpy(&g_stp_dbg_cpupcr->assert_type[0],tempBuf,len);
1456
1457 pDtr = osal_strstr(&g_stp_dbg_cpupcr->assert_type[0],"RB_FULL(");
1458 if(NULL != pDtr)
1459 {
1460 pDtr += osal_strlen("RB_FULL(");
1461 pTemp = osal_strchr(pDtr,')');
1462 }else
1463 {
1464 STP_DBG_ERR_FUNC("parser str is NULL,substring(RB_FULL()\n");
1465 return -4;
1466 }
1467 len = pTemp - pDtr;
1468 osal_memcpy(&tempBuf[0],pDtr,len);
1469 tempBuf[len] = '\0';
1470
1471 g_stp_dbg_cpupcr->fwTaskId = osal_strtol(tempBuf, NULL, 16);
1472
1473 STP_DBG_INFO_FUNC("update fw task id :%x\n",(UINT32)osal_strtol(tempBuf, NULL, 16));
1474 }
1475
1476 STP_DBG_INFO_FUNC("fw asert type:%s\n",g_stp_dbg_cpupcr->assert_type);
1477 break;
1478 default:
1479 STP_DBG_ERR_FUNC("unknow parser type\n");
1480 break;
1481 }
1482
1483 return 0;
1484 }
1485 P_STP_DBG_CPUPCR_T stp_dbg_cpupcr_init(VOID)
1486 {
1487 P_STP_DBG_CPUPCR_T pSdCpupcr = NULL;
1488
1489 pSdCpupcr = (P_STP_DBG_CPUPCR_T)osal_malloc(osal_sizeof(STP_DBG_CPUPCR_T));
1490 if(!pSdCpupcr){
1491 STP_DBG_ERR_FUNC("stp dbg cpupcr allocate memory fail!\n");
1492 return NULL;
1493 }
1494
1495 osal_memset(pSdCpupcr,0,osal_sizeof(STP_DBG_CPUPCR_T));
1496
1497 osal_sleepable_lock_init(&pSdCpupcr->lock);
1498
1499 return pSdCpupcr;
1500 }
1501
1502 P_STP_DBG_DMAREGS_T stp_dbg_dmaregs_init(VOID)
1503 {
1504 P_STP_DBG_DMAREGS_T pDmaRegs = NULL;
1505
1506 pDmaRegs = (P_STP_DBG_DMAREGS_T)osal_malloc(osal_sizeof(STP_DBG_DMAREGS_T));
1507 if(!pDmaRegs){
1508 STP_DBG_ERR_FUNC("stp dbg dmareg allocate memory fail!\n");
1509 return NULL;
1510 }
1511
1512 osal_memset(pDmaRegs,0,osal_sizeof(STP_DBG_DMAREGS_T));
1513
1514 osal_sleepable_lock_init(&pDmaRegs->lock);
1515
1516 return pDmaRegs;
1517 }
1518
1519 VOID stp_dbg_cpupcr_deinit(P_STP_DBG_CPUPCR_T pCpupcr)
1520 {
1521 if(pCpupcr)
1522 {
1523 osal_sleepable_lock_deinit(&pCpupcr->lock);
1524 osal_free(pCpupcr);
1525 pCpupcr = NULL;
1526 }
1527 }
1528 VOID stp_dbg_dmaregs_deinit(P_STP_DBG_DMAREGS_T pDmaRegs)
1529 {
1530 if(pDmaRegs)
1531 {
1532 osal_sleepable_lock_deinit(&pDmaRegs->lock);
1533 osal_free(pDmaRegs);
1534 pDmaRegs = NULL;
1535 }
1536 }
1537 INT32 stp_dbg_poll_cpupcr(UINT32 times,UINT32 sleep,UINT32 cmd)
1538 {
1539 INT32 i = 0;
1540
1541 if(!g_stp_dbg_cpupcr)
1542 {
1543 STP_DBG_ERR_FUNC("NULL reference pointer\n");
1544 return -1;
1545 }
1546
1547 if(!cmd)
1548 {
1549 if(g_stp_dbg_cpupcr->count + times > STP_DBG_CPUPCR_NUM)
1550 {
1551 times = STP_DBG_CPUPCR_NUM - g_stp_dbg_cpupcr->count;
1552 }
1553
1554 osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock);
1555
1556 for(i = 0;i < times;i++)
1557 {
1558 STP_DBG_INFO_FUNC("i:%d,cpupcr:%08x\n",i,wmt_plat_read_cpupcr());
1559 //osal_memcpy(&g_stp_dbg_cpupcr->buffer[i],(UINT8*)(CONSYS_REG_READ(CONSYS_CPUPCR_REG)),osal_sizeof(UINT32));
1560 g_stp_dbg_cpupcr->buffer[g_stp_dbg_cpupcr->count + i] = wmt_plat_read_cpupcr();
1561 osal_sleep_ms(sleep);
1562 }
1563 g_stp_dbg_cpupcr->count += times;
1564
1565 osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock);
1566 }else
1567 {
1568 STP_DBG_INFO_FUNC("stp-dbg: for proc test polling cpupcr\n");
1569 if(times > STP_DBG_CPUPCR_NUM)
1570 {
1571 times = STP_DBG_CPUPCR_NUM;
1572 }
1573
1574 osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock);
1575 g_stp_dbg_cpupcr->count = 0;
1576 for(i = 0;i < times;i++)
1577 {
1578 STP_DBG_INFO_FUNC("i:%d,cpupcr:%08x\n",i,wmt_plat_read_cpupcr());
1579 //osal_memcpy(&g_stp_dbg_cpupcr->buffer[i],(UINT8*)(CONSYS_REG_READ(CONSYS_CPUPCR_REG)),osal_sizeof(UINT32));
1580 g_stp_dbg_cpupcr->buffer[i] = wmt_plat_read_cpupcr();
1581 osal_sleep_ms(sleep);
1582 }
1583 g_stp_dbg_cpupcr->count = times;
1584
1585 osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock);
1586
1587 }
1588 return 0;
1589 }
1590
1591 INT32 stp_dbg_poll_dmaregs(UINT32 times, UINT32 sleep)
1592 {
1593 INT32 i = 0;
1594
1595 if(!g_stp_dbg_dmaregs)
1596 {
1597 STP_DBG_ERR_FUNC("NULL reference pointer\n");
1598 return -1;
1599 }
1600
1601 if(g_stp_dbg_dmaregs->count + times > STP_DBG_DMAREGS_NUM)
1602 {
1603 times = STP_DBG_DMAREGS_NUM - g_stp_dbg_dmaregs->count;
1604 }
1605
1606 osal_lock_sleepable_lock(&g_stp_dbg_dmaregs->lock);
1607
1608 STP_DBG_WARN_FUNC("---------Now Polling DMA relative Regs ------------- \n");
1609 for(i = 0;i < times;i++)
1610 {
1611 INT32 k = 0;
1612 for(; k < DMA_REGS_MAX; k++)
1613 {
1614 STP_DBG_WARN_FUNC("times:%d,i:%d reg: %s, regs:%08x\n",times, i, dmaRegsStr[k], wmt_plat_read_dmaregs(k));
1615 //g_stp_dbg_dmaregs->dmaIssue[k][g_stp_dbg_dmaregs->count + i] = wmt_plat_read_dmaregs(k);
1616 }
1617 osal_sleep_ms(sleep);
1618 }
1619 STP_DBG_WARN_FUNC("---------Polling DMA relative Regs End------------- \n");
1620 g_stp_dbg_dmaregs->count += times;
1621
1622 osal_unlock_sleepable_lock(&g_stp_dbg_dmaregs->lock);
1623 return 0;
1624 }
1625
1626 INT32 stp_dbg_poll_cuppcr_ctrl(UINT32 en)
1627 {
1628
1629 STP_DBG_INFO_FUNC("%s polling cpupcr\n",en == 0? "start":"stop");
1630
1631 osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock);
1632 g_stp_dbg_cpupcr->stop_flag = en;
1633 osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock);
1634 return 0;
1635 }
1636
1637 INT32 stp_dbg_set_version_info(UINT32 chipid,UINT8 *pRomVer,UINT8 *wifiVer,UINT8 *pPatchVer,UINT8 *pPatchBrh)
1638 {
1639 if(g_stp_dbg_cpupcr)
1640 {
1641 osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock);
1642 g_stp_dbg_cpupcr->chipId = chipid;
1643
1644 if(wifiVer)
1645 {
1646 osal_memcpy(g_stp_dbg_cpupcr->wifiVer,wifiVer,4);
1647 }
1648 if(pRomVer)
1649 {
1650 osal_memcpy(g_stp_dbg_cpupcr->romVer,pRomVer,2);
1651 }
1652 if(pPatchVer)
1653 {
1654 osal_memcpy(g_stp_dbg_cpupcr->patchVer,pPatchVer,8);
1655 }
1656 if(pPatchBrh)
1657 {
1658 osal_memcpy(g_stp_dbg_cpupcr->branchVer,pPatchBrh,4);
1659 }
1660 osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock);
1661 }
1662 else
1663 {
1664 STP_DBG_ERR_FUNC("NULL pointer\n");
1665 return -1;
1666 }
1667 STP_DBG_INFO_FUNC("chipid(0x%x),wifiver(%s),romver(%s),patchver(%s),branchver(%s)\n",
1668 g_stp_dbg_cpupcr->chipId,g_stp_dbg_cpupcr->wifiVer,&g_stp_dbg_cpupcr->romVer[0],
1669 &g_stp_dbg_cpupcr->patchVer[0],&g_stp_dbg_cpupcr->branchVer[0]);
1670 return 0;
1671 }
1672
1673 INT32 stp_dbg_set_host_assert_info(UINT32 drv_type,UINT32 reason,UINT32 en)
1674 {
1675 osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock);
1676
1677 g_stp_dbg_cpupcr->host_assert_info.assert_from_host = en;
1678 g_stp_dbg_cpupcr->host_assert_info.drv_type = drv_type;
1679 g_stp_dbg_cpupcr->host_assert_info.reason = reason;
1680
1681 osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock);
1682
1683 return 0;
1684 }
1685
1686 UINT32 stp_dbg_get_host_trigger_assert(VOID)
1687 {
1688 return g_stp_dbg_cpupcr->host_assert_info.assert_from_host;
1689 }
1690
1691
1692 INT32 stp_dbg_set_fw_info(UINT8 *issue_info,UINT32 len,ENUM_STP_FW_ISSUE_TYPE issue_type)
1693 {
1694 ENUM_ASSERT_INFO_PARSER_TYPE type_index;
1695 PUINT8 tempbuf = NULL;
1696 UINT32 i = 0;
1697 INT32 iRet = 0;
1698
1699 if(NULL == issue_info)
1700 {
1701 STP_DBG_ERR_FUNC("null issue infor\n");
1702 return -1;
1703 }
1704 STP_DBG_INFO_FUNC("issue type(%d)\n",issue_type);
1705 g_stp_dbg_cpupcr->issue_type = issue_type;
1706 osal_memset(&g_stp_dbg_cpupcr->assert_info[0],0,STP_ASSERT_INFO_SIZE);
1707
1708 /*print patch version when assert happened*/
1709 STP_DBG_INFO_FUNC("=======================================\n");
1710 STP_DBG_INFO_FUNC("[consys patch]patch version:%s\n",g_stp_dbg_cpupcr->patchVer);
1711 STP_DBG_INFO_FUNC("[consys patch]ALPS branch:%s\n",g_stp_dbg_cpupcr->branchVer);
1712 STP_DBG_INFO_FUNC("=======================================\n");
1713
1714 if((STP_FW_ASSERT_ISSUE == issue_type) || (STP_HOST_TRIGGER_FW_ASSERT == issue_type))
1715 {
1716 tempbuf = osal_malloc(len);
1717 if(!tempbuf)
1718 {
1719 return -2;
1720 }
1721 osal_memcpy(&tempbuf[0],issue_info,len);
1722
1723 for(i = 0;i < len;i++)
1724 {
1725 if(tempbuf[i] == '\0')
1726 tempbuf[i] = '?';
1727 }
1728
1729 tempbuf[len] = '\0';
1730 #if 0
1731 STP_DBG_INFO_FUNC("FW assert infor len(%d)\n",len);
1732 for(i = 0;i < len;i++)
1733 {
1734 if(0 == len%64)
1735 printk("\n");
1736 printk("%c",tempbuf[i]);
1737 }
1738 printk("\n");
1739 #endif
1740 for(type_index = STP_DBG_ASSERT_INFO;type_index < STP_DBG_PARSER_TYPE_MAX;type_index ++)
1741 {
1742 iRet += _stp_dbg_parser_assert_str(&tempbuf[0],type_index);
1743 }
1744 if(iRet)
1745 {
1746 STP_DBG_ERR_FUNC("passert assert infor fail(%d)\n",iRet);
1747 }
1748
1749 if(STP_HOST_TRIGGER_FW_ASSERT == issue_type)
1750 {
1751 switch(g_stp_dbg_cpupcr->host_assert_info.drv_type) {
1752 case 0:
1753 STP_DBG_INFO_FUNC("bt trigger assert\n");
1754 osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock);
1755 if(31 != g_stp_dbg_cpupcr->host_assert_info.reason)
1756 /*BT firmware trigger assert*/
1757 {
1758 g_stp_dbg_cpupcr->fwTaskId = 1;
1759
1760 }else
1761 /*BT stack trigger assert*/
1762 {
1763 g_stp_dbg_cpupcr->fwTaskId = 8;
1764 }
1765
1766 g_stp_dbg_cpupcr->host_assert_info.assert_from_host = 0;
1767 //g_stp_dbg_cpupcr->host_assert_info.drv_type = 0;
1768 //g_stp_dbg_cpupcr->host_assert_info.reason = 0;
1769
1770 osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock);
1771
1772 break;
1773 default:
1774 break;
1775 }
1776
1777 }
1778 osal_free(tempbuf);
1779 }
1780 else if(STP_FW_NOACK_ISSUE == issue_type)
1781 {
1782 osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock);
1783 osal_memcpy(&g_stp_dbg_cpupcr->assert_info[0],issue_info,len);
1784 g_stp_dbg_cpupcr->fwTaskId = 6;
1785 g_stp_dbg_cpupcr->fwRrq = 0;
1786 g_stp_dbg_cpupcr->fwIsr = 0;
1787 osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock);
1788 }else if(STP_DBG_PROC_TEST == issue_type)
1789 {
1790 osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock);
1791 osal_memcpy(&g_stp_dbg_cpupcr->assert_info[0],issue_info,len);
1792 g_stp_dbg_cpupcr->fwTaskId = 0;
1793 g_stp_dbg_cpupcr->fwRrq = 0;
1794 g_stp_dbg_cpupcr->fwIsr = 0;
1795 osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock);
1796 }else if(STP_FW_WARM_RST_ISSUE == issue_type)
1797 {
1798 osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock);
1799 osal_memcpy(&g_stp_dbg_cpupcr->assert_info[0],issue_info,len);
1800 g_stp_dbg_cpupcr->fwTaskId = 0;
1801 g_stp_dbg_cpupcr->fwRrq = 0;
1802 g_stp_dbg_cpupcr->fwIsr = 0;
1803 osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock);
1804 }
1805 else
1806 {
1807 STP_DBG_ERR_FUNC("invalid issue type(%d)\n",issue_type);
1808 return -3;
1809 }
1810
1811 return iRet;
1812 }
1813
1814
1815 INT32 stp_dbg_cpupcr_infor_format(PPUINT8 buf,PUINT32 str_len)
1816 {
1817 UINT32 len = 0;
1818 UINT32 i = 0;
1819 if(!g_stp_dbg_cpupcr)
1820 {
1821 STP_DBG_ERR_FUNC("NULL pointer\n");
1822 return -1;
1823 }
1824
1825 /*format common information about issue*/
1826 len = osal_sprintf(*buf,"<main>\n\t");
1827 len += osal_sprintf(*buf + len,"<chipid>\n\t\tMT%x\n\t</chipid>\n\t",g_stp_dbg_cpupcr->chipId);
1828 len += osal_sprintf(*buf + len,"<version>\n\t\t");
1829 len += osal_sprintf(*buf + len,"<rom>%s</rom>\n\t\t",g_stp_dbg_cpupcr->romVer);
1830 if(!(osal_memcmp(g_stp_dbg_cpupcr->branchVer,"ALPS",STP_PATCH_BRANCH_SZIE)))
1831 {
1832 len += osal_sprintf(*buf + len,"<branch>Internal Dev</branch>\n\t\t",g_stp_dbg_cpupcr->branchVer);
1833 }else
1834 {
1835 len += osal_sprintf(*buf + len,"<branch>W%sMP</branch>\n\t\t",g_stp_dbg_cpupcr->branchVer);
1836 }
1837 len += osal_sprintf(*buf + len,"<patch>%s</patch>\n\t\t",g_stp_dbg_cpupcr->patchVer);
1838
1839 if(!g_stp_dbg_cpupcr->wifiVer[0])
1840 {
1841 len += osal_sprintf(*buf + len,"<wifi>NULL</wifi>\n\t");
1842 }else
1843 {
1844 len += osal_sprintf(*buf + len,"<wifi>%s</wifi>\n\t",g_stp_dbg_cpupcr->wifiVer);
1845 }
1846 len += osal_sprintf(*buf + len,"</version>\n\t");
1847
1848 /*format issue information: no ack, assert*/
1849 len += osal_sprintf(*buf + len,"<issue>\n\t\t<classification>\n\t\t\t");
1850 if((STP_FW_NOACK_ISSUE == g_stp_dbg_cpupcr->issue_type) ||
1851 (STP_DBG_PROC_TEST == g_stp_dbg_cpupcr->issue_type) ||
1852 (STP_FW_WARM_RST_ISSUE == g_stp_dbg_cpupcr->issue_type))
1853 {
1854 len += osal_sprintf(*buf + len,"%s\n\t\t</classification>\n\t\t<rc>\n\t\t\t",g_stp_dbg_cpupcr->assert_info);
1855 len += osal_sprintf(*buf + len,"NULL\n\t\t</rc>\n\t</issue>\n\t");
1856 len += osal_sprintf(*buf + len,"<hint>\n\t\t<time_align>NULL</time_align>\n\t\t");
1857 len += osal_sprintf(*buf + len,"<host>NULL</host>\n\t\t");
1858 len += osal_sprintf(*buf + len,"<client>\n\t\t\t<task>%s</task>\n\t\t\t",_stp_dbg_id_to_task(g_stp_dbg_cpupcr->fwTaskId));
1859 len += osal_sprintf(*buf + len,"<irqx>IRQ_0x%x</irqx>\n\t\t\t",g_stp_dbg_cpupcr->fwRrq);
1860 len += osal_sprintf(*buf + len,"<isr>0x%x</isr>\n\t\t\t",g_stp_dbg_cpupcr->fwIsr);
1861 len += osal_sprintf(*buf + len,"<drv_type>NULL</drv_type>\n\t\t\t");
1862 len += osal_sprintf(*buf + len,"<reason>NULL</reason>\n\t\t\t");
1863 }else if((STP_FW_ASSERT_ISSUE == g_stp_dbg_cpupcr->issue_type) ||
1864 (STP_HOST_TRIGGER_FW_ASSERT == g_stp_dbg_cpupcr->issue_type))
1865 {
1866 len += osal_sprintf(*buf + len,"%s\n\t\t</classification>\n\t\t<rc>\n\t\t\t",g_stp_dbg_cpupcr->assert_info);
1867 len += osal_sprintf(*buf + len,"%s\n\t\t</rc>\n\t</issue>\n\t",g_stp_dbg_cpupcr->assert_type);
1868 len += osal_sprintf(*buf + len,"<hint>\n\t\t<time_align>NULL</time_align>\n\t\t");
1869 len += osal_sprintf(*buf + len,"<host>NULL</host>\n\t\t");
1870 len += osal_sprintf(*buf + len,"<client>\n\t\t\t<task>%s</task>\n\t\t\t",_stp_dbg_id_to_task(g_stp_dbg_cpupcr->fwTaskId));
1871 if(32 == g_stp_dbg_cpupcr->host_assert_info.reason)
1872 {
1873 /*handling wmt turn on/off bt cmd has ack but no evt issue*/
1874 len += osal_sprintf(*buf + len,"<irqx>NULL</irqx>\n\t\t\t");
1875 }else
1876 {
1877 len += osal_sprintf(*buf + len,"<irqx>IRQ_0x%x</irqx>\n\t\t\t",g_stp_dbg_cpupcr->fwRrq);
1878 }
1879 len += osal_sprintf(*buf + len,"<isr>0x%x</isr>\n\t\t\t",g_stp_dbg_cpupcr->fwIsr);
1880
1881 if(STP_FW_ASSERT_ISSUE == g_stp_dbg_cpupcr->issue_type)
1882 {
1883 len += osal_sprintf(*buf + len,"<drv_type>NULL</drv_type>\n\t\t\t");
1884 len += osal_sprintf(*buf + len,"<reason>NULL</reason>\n\t\t\t");
1885 }
1886
1887 if(STP_HOST_TRIGGER_FW_ASSERT == g_stp_dbg_cpupcr->issue_type)
1888 {
1889 len += osal_sprintf(*buf + len,"<drv_type>%d</drv_type>\n\t\t\t",g_stp_dbg_cpupcr->host_assert_info.drv_type);
1890 len += osal_sprintf(*buf + len,"<reason>%d</reason>\n\t\t\t",g_stp_dbg_cpupcr->host_assert_info.reason);
1891 }
1892 }else
1893 {
1894 len += osal_sprintf(*buf + len,"NULL\n\t\t</classification>\n\t\t<rc>\n\t\t\t");
1895 len += osal_sprintf(*buf + len,"NULL\n\t\t</rc>\n\t</issue>\n\t");
1896 len += osal_sprintf(*buf + len,"<hint>\n\t\t<time_align>NULL</time_align>\n\t\t");
1897 len += osal_sprintf(*buf + len,"<host>NULL</host>\n\t\t");
1898 len += osal_sprintf(*buf + len,"<client>\n\t\t\t<task>NULL</task>\n\t\t\t");
1899 len += osal_sprintf(*buf + len,"<irqx>NULL</irqx>\n\t\t\t");
1900 len += osal_sprintf(*buf + len,"<isr>NULL</isr>\n\t\t\t");
1901 len += osal_sprintf(*buf + len,"<drv_type>NULL</drv_type>\n\t\t\t");
1902 len += osal_sprintf(*buf + len,"<reason>NULL</reason>\n\t\t\t");
1903 }
1904
1905 len += osal_sprintf(*buf + len,"<pctrace>");
1906 STP_DBG_INFO_FUNC("stp-dbg:sub len1 for debug(%d)\n",len);
1907
1908 if(!g_stp_dbg_cpupcr->count)
1909 {
1910 len += osal_sprintf(*buf + len,"NULL");
1911 }
1912 else
1913 {
1914 for(i = 0;i < g_stp_dbg_cpupcr->count;i++)
1915 {
1916 len += osal_sprintf(*buf + len,"%08x,",g_stp_dbg_cpupcr->buffer[i]);
1917 }
1918 }
1919 STP_DBG_INFO_FUNC("stp-dbg:sub len2 for debug(%d)\n",len);
1920 len += osal_sprintf(*buf + len,"</pctrace>\n\t\t\t");
1921 len += osal_sprintf(*buf + len,"<extension>NULL</extension>\n\t\t</client>\n\t</hint>\n</main>\n");
1922 STP_DBG_INFO_FUNC("buffer len[%d]\n",len);
1923 //STP_DBG_INFO_FUNC("Format infor:\n%s\n",*buf);
1924 *str_len = len;
1925
1926 osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock);
1927 osal_memset(&g_stp_dbg_cpupcr->buffer[0],0,STP_DBG_CPUPCR_NUM);
1928 g_stp_dbg_cpupcr->count = 0;
1929 g_stp_dbg_cpupcr->host_assert_info.reason = 0;
1930 g_stp_dbg_cpupcr->host_assert_info.drv_type = 0;
1931 osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock);
1932
1933 return 0;
1934
1935 }
1936
1937 MTKSTP_DBG_T *stp_dbg_init(void *btm_half){
1938
1939 MTKSTP_DBG_T *stp_dbg= NULL;
1940 STP_DBG_INFO_FUNC("stp-dbg init\n");
1941
1942 stp_dbg = kzalloc(sizeof(MTKSTP_DBG_T), GFP_KERNEL);
1943 if(IS_ERR(stp_dbg)){
1944 STP_DBG_ERR_FUNC("-ENOMEM\n");
1945 goto ERR_EXIT1;
1946 }
1947
1948 stp_dbg->logsys = vmalloc(sizeof(MTKSTP_LOG_SYS_T));
1949 if(IS_ERR(stp_dbg->logsys)){
1950 STP_DBG_ERR_FUNC("-ENOMEM stp_gdb->logsys\n");
1951 goto ERR_EXIT2;
1952 }
1953 memset(stp_dbg->logsys, 0, sizeof(MTKSTP_LOG_SYS_T));
1954 spin_lock_init(&(stp_dbg->logsys->lock));
1955 stp_dbg->pkt_trace_no=0;
1956 stp_dbg->is_enable=0;
1957 g_stp_dbg = stp_dbg;
1958
1959 if(btm_half != NULL){
1960 stp_dbg->btm = btm_half;
1961 } else {
1962 stp_dbg->btm = NULL;
1963 }
1964
1965 //bind to netlink
1966 stp_dbg_nl_init();
1967
1968 g_core_dump = wcn_core_dump_init(STP_CORE_DUMP_TIMEOUT);
1969
1970 g_stp_dbg_cpupcr = stp_dbg_cpupcr_init();
1971 g_stp_dbg_dmaregs = stp_dbg_dmaregs_init();
1972
1973 return stp_dbg;
1974
1975 ERR_EXIT2:
1976 kfree(stp_dbg);
1977 return NULL;
1978
1979 ERR_EXIT1:
1980 return NULL;
1981 }
1982
1983 int stp_dbg_deinit(MTKSTP_DBG_T *stp_dbg){
1984
1985 STP_DBG_INFO_FUNC("stp-dbg deinit\n");
1986
1987 wcn_core_dump_deinit(g_core_dump);
1988
1989 stp_dbg_cpupcr_deinit(g_stp_dbg_cpupcr);
1990 stp_dbg_dmaregs_deinit(g_stp_dbg_dmaregs);
1991 //unbind with netlink
1992 stp_dbg_nl_deinit();
1993
1994 if(stp_dbg->logsys){
1995 vfree(stp_dbg->logsys);
1996 }
1997
1998 if(stp_dbg){
1999 kfree(stp_dbg);
2000 }
2001
2002 return 0;
2003 }
2004
2005
2006
2007
2008
2009
2010