2 * Copyright (C) 2011-2014 MediaTek Inc.
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.
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.
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/>.
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>
26 #include <net/netlink.h>
27 #include <linux/skbuff.h>
28 #include <net/genetlink.h>
30 #include <linux/zlib.h>
31 #include <linux/uaccess.h>
32 #include <linux/crc32.h>
34 #include "osal_typedef.h"
36 //#include "stp_btm.h"
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
47 unsigned int gStpDbgDbgLevel
= STP_DBG_LOG_INFO
;
48 unsigned int gStpDbgLogOut
= 0;
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__);}
58 MTKSTP_DBG_T
*g_stp_dbg
= NULL
;
60 #define STP_DBG_FAMILY_NAME "STP_DBG"
61 #define MAX_BIND_PROCESS (4)
63 #define STP_DBG_AEE_EXP_API (1)
65 #define STP_DBG_AEE_EXP_API (0)
68 __STP_DBG_ATTR_INVALID
,
72 #define STP_DBG_ATTR_MAX (__STP_DBG_ATTR_MAX - 1)
75 __STP_DBG_COMMAND_INVALID
,
77 STP_DBG_COMMAND_RESET
,
78 __STP_DBG_COMMAND_MAX
,
80 #define MTK_WIFI_COMMAND_MAX (__STP_DBG_COMMAND_MAX - 1)
82 static struct genl_family stp_dbg_gnl_family
= {
83 .id
= GENL_ID_GENERATE
,
85 .name
= STP_DBG_FAMILY_NAME
,
87 .maxattr
= STP_DBG_ATTR_MAX
,
90 static void stp_dbg_nl_init(void);
91 static void stp_dbg_nl_deinit(void);
92 static int stp_dbg_nl_bind(
94 struct genl_info
*info
96 static int stp_dbg_nl_reset(
98 struct genl_info
*info
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
},
106 /* operation definition */
107 static struct genl_ops stp_dbg_gnl_ops_bind
= {
108 .cmd
= STP_DBG_COMMAND_BIND
,
110 .policy
= stp_dbg_genl_policy
,
111 .doit
= stp_dbg_nl_bind
,
115 static struct genl_ops stp_dbg_gnl_ops_reset
= {
116 .cmd
= STP_DBG_COMMAND_RESET
,
118 .policy
= stp_dbg_genl_policy
,
119 .doit
= stp_dbg_nl_reset
,
124 static char* dmaRegsStr
[] = {
125 E2S(CONNSYS_CLK_GATE_STATUS
),
126 E2S(CONSYS_EMI_STATUS
),
131 static unsigned int stp_dbg_seqnum
= 0;
132 static int num_bind_process
= 0;
133 static pid_t bind_pid
[MAX_BIND_PROCESS
];
135 static P_WCN_CORE_DUMP_T g_core_dump
= NULL
;
137 static P_STP_DBG_CPUPCR_T g_stp_dbg_cpupcr
= NULL
;
139 //just show in log at present
140 static P_STP_DBG_DMAREGS_T g_stp_dbg_dmaregs
= NULL
;
142 /* core_dump_timeout_handler - handler of coredump timeout
143 * @ data - core dump object's pointer
147 static void core_dump_timeout_handler(unsigned long data
)
149 P_WCN_CORE_DUMP_T dmp
= (P_WCN_CORE_DUMP_T
)data
;
151 STP_DBG_INFO_FUNC(" start\n");
153 stp_btm_notify_coredump_timeout_wq(g_stp_dbg
->btm
);
155 STP_DBG_INFO_FUNC(" end\n");
158 dmp
->sm
= CORE_DUMP_TIMEOUT
;
163 /* wcn_core_dump_init - create core dump sys
164 * @ timeout - core dump time out value
166 * Return object pointer if success, else NULL
168 P_WCN_CORE_DUMP_T
wcn_core_dump_init(UINT32 timeout
)
170 #define KBYTES (1024*sizeof(char))
171 #define L1_BUF_SIZE (32*KBYTES)
172 #define L2_BUF_SIZE (384*KBYTES)
174 P_WCN_CORE_DUMP_T core_dmp
= NULL
;
176 core_dmp
= (P_WCN_CORE_DUMP_T
)osal_malloc(sizeof(WCN_CORE_DUMP_T
));
178 STP_DBG_ERR_FUNC("alloc mem failed!\n");
182 osal_memset(core_dmp
, 0, sizeof(WCN_CORE_DUMP_T
));
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");
189 wcn_compressor_reset(core_dmp
->compressor
, 1, GZIP
);
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
;
196 osal_sleepable_lock_init(&core_dmp
->dmp_lock
);
198 core_dmp
->sm
= CORE_DUMP_INIT
;
199 STP_DBG_INFO_FUNC("create coredump object OK!\n");
204 if (core_dmp
&& core_dmp
->compressor
) {
205 wcn_compressor_deinit(core_dmp
->compressor
);
206 core_dmp
->compressor
= NULL
;
213 osal_sleepable_lock_deinit(&core_dmp
->dmp_lock
);
219 /* wcn_core_dump_deinit - destroy core dump object
220 * @ dmp - pointer of object
222 * Retunr 0 if success, else error code
224 INT32
wcn_core_dump_deinit(P_WCN_CORE_DUMP_T dmp
)
226 if (dmp
&& dmp
->compressor
) {
227 wcn_compressor_deinit(dmp
->compressor
);
228 dmp
->compressor
= NULL
;
232 osal_sleepable_lock_deinit(&dmp
->dmp_lock
);
233 osal_timer_stop(&dmp
->dmp_timer
);
241 static INT32
wcn_core_dump_check_end(PUINT8 buf
, INT32 len
)
243 if (strnstr(buf
, "coredump end", len
)) {
251 /* wcn_core_dump_in - add a packet to compressor buffer
252 * @ dmp - pointer of object
253 * @ buf - input buffer
254 * @ len - data length
256 * Retunr 0 if success; return 1 if find end string; else error code
258 INT32
wcn_core_dump_in(P_WCN_CORE_DUMP_T dmp
, PUINT8 buf
, INT32 len
)
263 #define INFO_HEAD ";SOC_CONSYS FW CORE, "
265 if ((!dmp
) || (!buf
)) {
266 STP_DBG_ERR_FUNC("invalid pointer!\n");
270 ret
= osal_lock_sleepable_lock(&dmp
->dmp_lock
);
272 STP_DBG_ERR_FUNC("--->lock dmp->dmp_lock failed, ret=%d\n", ret
);
278 wcn_compressor_reset(dmp
->compressor
, 1, GZIP
);
279 osal_timer_start(&dmp
->dmp_timer
, STP_CORE_DUMP_TIMEOUT
);
281 // first package, copy to info buffer
282 osal_strcpy(&dmp
->info
[0], INFO_HEAD
);
284 if(NULL
== (strnstr(buf
,"<ASSERT>",32)))
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';
292 pDtr
= osal_strchr(pStr
,'-');
296 osal_memcpy(&dmp
->info
[osal_strlen(INFO_HEAD
)], buf
, tmp
);
297 dmp
->info
[osal_strlen(dmp
->info
) + 1] = '\0';
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';
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");
312 // parsing data, and check end srting
313 ret
= wcn_core_dump_check_end(buf
, len
);
315 STP_DBG_INFO_FUNC("core dump end!\n");
316 dmp
->sm
= CORE_DUMP_DONE
;
317 wcn_compressor_in(dmp
->compressor
, buf
, len
, 0);
319 dmp
->sm
= CORE_DUMP_DOING
;
320 wcn_compressor_in(dmp
->compressor
, buf
, len
, 0);
324 case CORE_DUMP_DOING
:
325 // parsing data, and check end srting
326 ret
= wcn_core_dump_check_end(buf
, len
);
328 STP_DBG_INFO_FUNC("core dump end!\n");
329 dmp
->sm
= CORE_DUMP_DONE
;
330 wcn_compressor_in(dmp
->compressor
, buf
, len
, 0);
332 dmp
->sm
= CORE_DUMP_DOING
;
333 wcn_compressor_in(dmp
->compressor
, buf
, len
, 0);
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
;
344 case CORE_DUMP_TIMEOUT
:
350 osal_unlock_sleepable_lock(&dmp
->dmp_lock
);
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
361 * Retunr 0 if success; else error code
363 INT32
wcn_core_dump_out(P_WCN_CORE_DUMP_T dmp
, PUINT8
*pbuf
, PINT32 plen
)
367 if ((!dmp
) || (!pbuf
) || (!plen
)) {
368 STP_DBG_ERR_FUNC("invalid pointer!\n");
372 ret
= osal_lock_sleepable_lock(&dmp
->dmp_lock
);
374 STP_DBG_ERR_FUNC("--->lock dmp->dmp_lock failed, ret=%d\n", ret
);
378 ret
= wcn_compressor_out(dmp
->compressor
, pbuf
, plen
);
380 osal_unlock_sleepable_lock(&dmp
->dmp_lock
);
386 /* wcn_core_dump_reset - reset core dump sys
387 * @ dmp - pointer of object
388 * @ timeout - core dump time out value
390 * Retunr 0 if success, else error code
392 INT32
wcn_core_dump_reset(P_WCN_CORE_DUMP_T dmp
, UINT32 timeout
)
395 STP_DBG_ERR_FUNC("invalid pointer!\n");
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);
405 wcn_core_dump_deinit(dmp
);
406 g_core_dump
= wcn_core_dump_init(STP_CORE_DUMP_TIMEOUT
);
411 /* wcn_core_dump_timeout - wait for FW assert info timeout ,this func can collect SYS_FTRACE
413 * Retunr 0 if success
415 #define TIMEOUT_INFO_HEAD "Trigger assert timeout ,just collect SYS_FTRACE to DB"
416 INT32
wcn_core_dump_timeout(void)
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
);
428 #define ENABLE_F_TRACE 0
429 /* wcn_core_dump_flush - Fulsh dump data and reset core dump sys
431 * Retunr 0 if success, else error code
433 INT32
wcn_core_dump_flush(INT32 rst
)
439 STP_DBG_ERR_FUNC("invalid pointer!\n");
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
);
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
452 aed_combo_exception_api(NULL
, 0, (const int*)pbuf
, len
, (const char*)g_core_dump
->info
,DB_OPT_FTRACE
);
454 aed_combo_exception(NULL
, 0, (const int*)pbuf
, len
, (const char*)g_core_dump
->info
);
460 wcn_core_dump_reset(g_core_dump
, STP_CORE_DUMP_TIMEOUT
);
466 static INT32
wcn_gzip_compressor(void *worker
, UINT8
*in_buf
, INT32 in_sz
, UINT8
*out_buf
, INT32
*out_sz
, INT32 finish
)
469 z_stream
*stream
= NULL
;
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
);
475 stream
= (z_stream
*)worker
;
477 STP_DBG_ERR_FUNC("invalid workspace!\n");
483 ret
= zlib_deflateReset(stream
);
485 STP_DBG_ERR_FUNC("reset failed!\n");
490 stream
->next_in
= in_buf
;
491 stream
->avail_in
= in_sz
;
492 stream
->next_out
= out_buf
;
493 stream
->avail_out
= tmp
;
495 zlib_deflate(stream
, Z_FULL_FLUSH
);
499 int val
= zlib_deflate(stream
, Z_FINISH
);
502 } else if (val
== Z_STREAM_END
) {
505 STP_DBG_ERR_FUNC("finish operation failed %d\n", val
);
511 *out_sz
= tmp
- stream
->avail_out
;
514 STP_DBG_INFO_FUNC("out buf 0x%zx, out sz %d\n", (SIZE_T
)out_buf
, *out_sz
);
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
525 * Retunr object's pointer if success, else NULL
527 P_WCN_COMPRESSOR_T
wcn_compressor_init(PUINT8 name
, INT32 L1_buf_sz
, INT32 L2_buf_sz
)
529 z_stream
*pstream
= NULL
;
530 P_WCN_COMPRESSOR_T compress
= NULL
;
532 compress
= (P_WCN_COMPRESSOR_T
)osal_malloc(sizeof(WCN_COMPRESSOR_T
));
534 STP_DBG_ERR_FUNC("alloc compressor failed!\n");
538 osal_memset(compress
, 0, sizeof(WCN_COMPRESSOR_T
));
539 osal_memcpy(compress
->name
, name
, STP_OJB_NAME_SZ
);
541 compress
->f_compress_en
= 0;
542 compress
->compress_type
= GZIP
;
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");
550 pstream
= (z_stream
*)compress
->worker
;
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");
557 zlib_deflateInit2(pstream
, Z_DEFAULT_COMPRESSION
, Z_DEFLATED
, -MAX_WBITS
,
558 DEF_MEM_LEVEL
, Z_DEFAULT_STRATEGY
);
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
;
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
);
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
);
581 STP_DBG_INFO_FUNC("create compressor OK! L1 %d bytes, L2 %d bytes\n", L1_buf_sz
, L2_buf_sz
);
586 if (compress
->L2_buf
) {
587 osal_free(compress
->L2_buf
);
588 compress
->L2_buf
= NULL
;
591 if (compress
->L1_buf
) {
592 osal_free(compress
->L1_buf
);
593 compress
->L1_buf
= NULL
;
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
);
602 osal_free(compress
->worker
);
603 compress
->worker
= NULL
;
606 if (compress
->worker
) {
607 osal_free(compress
->worker
);
608 compress
->worker
= NULL
;
615 STP_DBG_ERR_FUNC("init failed!\n");
621 /* wcn_compressor_deinit - distroy a compressor
622 * @ cprs - compressor's pointer
624 * Retunr 0 if success, else NULL
626 INT32
wcn_compressor_deinit(P_WCN_COMPRESSOR_T cprs
)
628 z_stream
*pstream
= NULL
;
632 osal_free(cprs
->L2_buf
);
637 osal_free(cprs
->L1_buf
);
642 pstream
= (z_stream
*)cprs
->worker
;
643 if ((cprs
->compress_type
== GZIP
) && pstream
->workspace
) {
644 zlib_deflateEnd(pstream
);
645 osal_free(pstream
->workspace
);
647 osal_free(cprs
->worker
);
651 cprs
->handler
= NULL
;
656 STP_DBG_INFO_FUNC("destroy OK\n");
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
668 * Retunr 0 if success, else NULL
670 INT32
wcn_compressor_in(P_WCN_COMPRESSOR_T cprs
, PUINT8 buf
, INT32 len
, INT32 finish
)
676 STP_DBG_ERR_FUNC("invalid para!\n");
680 cprs
->uncomp_size
+= len
;
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");
686 if (cprs
->f_compress_en
&& cprs
->handler
) {
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
);
692 cprs
->crc32
= (crc32(cprs
->crc32
, cprs
->L1_buf
, cprs
->L1_pos
));
693 cprs
->L2_pos
+= tmp_len
;
698 32 bits UNCOMPRESS SIZE
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
;
705 STP_DBG_INFO_FUNC("compress OK!\n");
707 STP_DBG_ERR_FUNC("compress error!\n");
711 // Flush L1 buffer to L2 buffer
712 STP_DBG_INFO_FUNC("No need do compress, Put to L2 buf\n");
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
;
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
);
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
);
733 STP_DBG_INFO_FUNC("Put %d bytes to L1 buf\n", len
);
735 osal_memcpy(&cprs
->L1_buf
[cprs
->L1_pos
], buf
, len
);
743 /* wcn_compressor_out - get the result data from L2 buffer
744 * @ cprs - compressor's pointer
745 * @ pbuf - point to L2 buffer
748 * Retunr 0 if success, else NULL
750 INT32
wcn_compressor_out(P_WCN_COMPRESSOR_T cprs
, PUINT8
*pbuf
, PINT32 plen
)
755 if ((!cprs
) || (!pbuf
) || (!plen
)) {
756 STP_DBG_ERR_FUNC("invalid para!\n");
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
;
764 if (cprs
->f_compress_en
&& cprs
->handler
) {
766 ret
= cprs
->handler(cprs
->worker
, cprs
->L1_buf
, cprs
->L1_pos
, &cprs
->L2_buf
[cprs
->L2_pos
], &tmp_len
, 1);
769 cprs
->crc32
= (crc32(cprs
->crc32
, cprs
->L1_buf
, cprs
->L1_pos
));
770 cprs
->L2_pos
+= tmp_len
;
774 32 bits UNCOMPRESS SIZE
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
;
781 STP_DBG_INFO_FUNC("compress OK!\n");
783 STP_DBG_ERR_FUNC("compress error!\n");
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
;
796 *pbuf
= cprs
->L2_buf
;
797 *plen
= cprs
->L2_pos
;
799 STP_DBG_INFO_FUNC("0x%zx, len %d\n", (SIZE_T
)*pbuf
, *plen
);
805 /* wcn_compressor_reset - reset compressor
806 * @ cprs - compressor's pointer
807 * @ enable - enable/disable compress
808 * @ type - compress algorithm
810 * Retunr 0 if success, else NULL
812 INT32
wcn_compressor_reset(P_WCN_COMPRESSOR_T cprs
, UINT8 enable
, WCN_COMPRESS_ALG_T type
)
815 STP_DBG_ERR_FUNC("invalid para!\n");
819 cprs
->f_compress_en
= enable
;
820 //cprs->f_compress_en = 0; // disable compress for test
821 cprs
->compress_type
= type
;
824 cprs
->uncomp_size
= 0;
825 cprs
->crc32
= 0xffffffffUL
;
827 //zlib_deflateEnd((z_stream*)cprs->worker);
829 STP_DBG_INFO_FUNC("OK! compress algorithm %d\n", type
);
835 static void stp_dbg_dump_data(unsigned char *pBuf
, char * title
, int len
)
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
]);
848 static int _stp_dbg_enable(MTKSTP_DBG_T
*stp_dbg
){
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
);
860 static int _stp_dbg_disable(MTKSTP_DBG_T
*stp_dbg
){
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
);
873 static int _stp_dbg_dmp_in(MTKSTP_DBG_T
*stp_dbg
, char *buf
, int len
){
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
881 spin_lock_irqsave(&(stp_dbg
->logsys
->lock
), flags
);
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
)));
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
;
894 if (0 != gStpDbgLogOut
)
896 STP_DBG_HDR_T
*pHdr
= NULL
;
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", \
905 pHdr
->dir
== PKT_DIR_TX
? "Tx" : "Rx",
906 gStpDbgType
[pHdr
->type
],
914 stp_dbg_dump_data(pBuf
, pHdr
->dir
== PKT_DIR_TX
? "Tx" : "Rx", len
);
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
);
921 STP_DBG_WARN_FUNC("logsys FULL!\n");
924 spin_unlock_irqrestore(&(stp_dbg
->logsys
->lock
), flags
);
929 int stp_gdb_notify_btm_dmp_wq(MTKSTP_DBG_T
*stp_dbg
){
931 //#ifndef CONFIG_LOG_STP_INTERNAL
933 if(stp_dbg
->btm
!= NULL
){
934 retval
+= stp_btm_notify_wmt_dmp_wq((MTKSTP_BTM_T
*)stp_dbg
->btm
);
942 int stp_dbg_log_ctrl (unsigned int on
)
947 printk ("STP-DBG: enable pkt log dump out.\n");
952 printk ("STP-DBG: disable pkt log dump out.\n");
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
);
962 int stp_dbg_dmp_printk(MTKSTP_DBG_T
*stp_dbg
)
964 #define MAX_DMP_NUM 80
968 STP_DBG_HDR_T
*pHdr
= NULL
;
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
)
982 outIndex
= ((inIndex
+ STP_DBG_LOG_ENTRY_NUM
) - dumpSize
) % STP_DBG_LOG_ENTRY_NUM
;
985 if (dumpSize
> MAX_DMP_NUM
)
988 outIndex
+= (dumpSize
- MAX_DMP_NUM
);
989 outIndex
%= STP_DBG_LOG_ENTRY_NUM
;
990 dumpSize
= MAX_DMP_NUM
;
993 STP_DBG_INFO_FUNC("loged packet size = %d, in(%d), out(%d)\n", dumpSize
, inIndex
, outIndex
);
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", \
1002 pHdr
->dir
== PKT_DIR_TX
? "Tx" : "Rx",
1003 gStpDbgType
[pHdr
->type
],
1012 stp_dbg_dump_data(pBuf
, pHdr
->dir
== PKT_DIR_TX
? "Tx" : "Rx", len
);
1014 outIndex
= (outIndex
>= (STP_DBG_LOG_ENTRY_NUM
- 1))?(0):(outIndex
+ 1);
1020 spin_unlock_irqrestore(&(stp_dbg
->logsys
->lock
), flags
);
1025 int stp_dbg_dmp_out_ex (char *buf
, int *len
){
1026 return stp_dbg_dmp_out(g_stp_dbg
, buf
, len
);
1029 int stp_dbg_dmp_out(MTKSTP_DBG_T
*stp_dbg
, char *buf
, int *len
){
1031 unsigned long flags
;
1034 spin_lock_irqsave(&(stp_dbg
->logsys
->lock
), flags
);
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
);
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
--;
1044 STP_DBG_DBG_FUNC("logsys size = %d, out = %d\n", stp_dbg
->logsys
->size
, stp_dbg
->logsys
->out
);
1046 STP_DBG_LOUD_FUNC("logsys EMPTY!\n");
1049 remaining
= (stp_dbg
->logsys
->size
== 0)?(0):(1);
1051 spin_unlock_irqrestore(&(stp_dbg
->logsys
->lock
), flags
);
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
){
1061 STP_DBG_ERR_FUNC("function invalid\n");
1064 do_gettimeofday(&now
);
1065 hdr
->dbg_type
= dbg_type
;
1068 hdr
->sec
= now
.tv_sec
;
1069 hdr
->usec
= now
.tv_usec
;
1072 hdr
->dmy
= 0xffffffff;
1081 MTKSTP_DBG_T
*stp_dbg
,
1082 struct stp_dbg_pkt_hdr
*hdr
,
1083 const unsigned char *body
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;
1093 if(hdr
->dbg_type
== STP_DBG_PKT
){
1094 body_sz
= (hdr
->len
<= STP_PKT_SZ
)?(hdr
->len
):(STP_PKT_SZ
);
1096 body_sz
= (hdr
->len
<= STP_DMP_SZ
)?(hdr
->len
):(STP_DMP_SZ
);
1099 hdr
->no
= stp_dbg
->pkt_trace_no
++;
1100 memcpy((uint8_t *)&stp_pkt
.hdr
, (uint8_t*)hdr
, hdr_sz
);
1102 memcpy((uint8_t *)&stp_pkt
.raw
[0], body
, body_sz
);
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
)
1108 stp_gdb_notify_btm_dmp_wq(stp_dbg
);
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
) {
1117 struct stp_dbg_pkt_hdr hdr
;
1119 if (stp_dbg
->is_enable
== 0) {
1120 /*dbg is disable,and not to log*/
1123 stp_dbg_fill_hdr(&hdr
,
1132 stp_dbg_add_pkt(stp_dbg
, &hdr
, body
);
1138 int stp_dbg_enable(MTKSTP_DBG_T
*stp_dbg
){
1139 return _stp_dbg_enable(stp_dbg
);
1142 int stp_dbg_disable(MTKSTP_DBG_T
*stp_dbg
){
1143 return _stp_dbg_disable(stp_dbg
);
1146 static void stp_dbg_nl_init(void)
1148 if(genl_register_family(&stp_dbg_gnl_family
) != 0)
1150 STP_DBG_ERR_FUNC("%s(): GE_NELINK family registration fail\n", __func__
);
1154 if(genl_register_ops(&stp_dbg_gnl_family
, &stp_dbg_gnl_ops_bind
) != 0)
1156 STP_DBG_ERR_FUNC("%s(): BIND operation registration fail\n", __func__
);
1159 if(genl_register_ops(&stp_dbg_gnl_family
, &stp_dbg_gnl_ops_reset
) != 0)
1161 STP_DBG_ERR_FUNC("%s(): RESET operation registration fail\n", __func__
);
1168 static void stp_dbg_nl_deinit(void)
1170 genl_unregister_family(&stp_dbg_gnl_family
);
1174 static int stp_dbg_nl_bind(
1175 struct sk_buff
*skb
,
1176 struct genl_info
*info
1187 STP_DBG_INFO_FUNC("%s():->\n", __func__
);
1189 na
= info
->attrs
[STP_DBG_ATTR_MSG
];
1193 mydata
= (char *)nla_data(na
);
1196 if(num_bind_process
< MAX_BIND_PROCESS
)
1199 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1200 bind_pid
[num_bind_process
] = info
->snd_pid
;
1202 STP_DBG_INFO_FUNC("%s():-> pid = %d\n", __func__
, info
->snd_pid
);
1204 bind_pid
[num_bind_process
] = info
->snd_portid
;
1206 STP_DBG_INFO_FUNC("%s():-> pid = %d\n", __func__
, info
->snd_portid
);
1211 STP_DBG_ERR_FUNC("%s(): exceeding binding limit %d\n", __func__
, MAX_BIND_PROCESS
);
1218 static int stp_dbg_nl_reset(
1219 struct sk_buff
*skb
,
1220 struct genl_info
*info
1223 STP_DBG_ERR_FUNC("%s(): should not be invoked\n", __func__
);
1234 struct sk_buff
*skb
= NULL
;
1235 void *msg_head
= NULL
;
1239 if(num_bind_process
== 0)
1241 /* no listening process */
1242 STP_DBG_ERR_FUNC("%s(): the process is not invoked\n", __func__
);
1246 for(i
= 0 ; i
< num_bind_process
; i
++)
1248 skb
= genlmsg_new(2048, GFP_KERNEL
);
1252 msg_head
= genlmsg_put(skb
, 0, stp_dbg_seqnum
++, &stp_dbg_gnl_family
, 0, cmd
);
1253 if(msg_head
== NULL
)
1256 STP_DBG_ERR_FUNC("%s(): genlmsg_put fail...\n", __func__
);
1260 rc
= nla_put_string(skb
, STP_DBG_ATTR_MSG
, aucMsg
);
1264 STP_DBG_ERR_FUNC("%s(): nla_put_string fail...\n", __func__
);
1268 /* finalize the message */
1269 genlmsg_end(skb
, msg_head
);
1271 /* sending message */
1272 rc
= genlmsg_unicast(&init_net
, skb
, bind_pid
[i
]);
1275 STP_DBG_ERR_FUNC("%s(): genlmsg_unicast fail...\n", __func__
);
1281 STP_DBG_ERR_FUNC("%s(): genlmsg_new fail...\n", __func__
);
1290 INT32
stp_dbg_aee_send(unsigned char *aucMsg
, INT32 len
, INT32 cmd
)
1294 // buffered to compressor
1295 ret
= wcn_core_dump_in(g_core_dump
, aucMsg
, len
);
1297 wcn_core_dump_flush(0);
1302 UINT8
*_stp_dbg_id_to_task(UINT32 id
)
1318 INT32
_stp_dbg_parser_assert_str(PINT8 str
,ENUM_ASSERT_INFO_PARSER_TYPE type
)
1323 char *pTemp2
= NULL
;
1324 char tempBuf
[64] = {0};
1327 char *parser_sub_string
[] =
1338 STP_DBG_ERR_FUNC("NULL string source\n");
1342 if(!g_stp_dbg_cpupcr
)
1344 STP_DBG_ERR_FUNC("NULL pointer\n");
1349 STP_DBG_DBG_FUNC("source infor:%s\n",pStr
);
1351 case STP_DBG_ASSERT_INFO
:
1352 pDtr
= osal_strstr(pStr
,parser_sub_string
[type
]);
1355 pDtr
+= osal_strlen(parser_sub_string
[type
]);
1356 pTemp
= osal_strchr(pDtr
,' ');
1359 STP_DBG_ERR_FUNC("parser str is NULL,substring(%s)\n",parser_sub_string
[type
]);
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
] = '_';
1367 pTemp
= osal_strchr(pDtr
,'#');
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]);
1375 case STP_DBG_FW_TASK_ID
:
1376 pDtr
= osal_strstr(pStr
,parser_sub_string
[type
]);
1379 pDtr
+= osal_strlen(parser_sub_string
[type
]);
1380 pTemp
= osal_strchr(pDtr
,' ');
1383 STP_DBG_ERR_FUNC("parser str is NULL,substring(%s)\n",parser_sub_string
[type
]);
1387 osal_memcpy(&tempBuf
[0],pDtr
,len
);
1388 tempBuf
[len
] = '\0';
1389 g_stp_dbg_cpupcr
->fwTaskId
= osal_strtol(tempBuf
, NULL
, 16);
1391 STP_DBG_INFO_FUNC("fw task id :%x\n",(UINT32
)osal_strtol(tempBuf
, NULL
, 16));
1393 case STP_DBG_FW_ISR
:
1394 pDtr
= osal_strstr(pStr
,parser_sub_string
[type
]);
1397 pDtr
+= osal_strlen(parser_sub_string
[type
]);
1398 pTemp
= osal_strchr(pDtr
,',');
1401 STP_DBG_ERR_FUNC("parser str is NULL,substring(%s)\n",parser_sub_string
[type
]);
1405 osal_memcpy(&tempBuf
[0],pDtr
,len
);
1406 tempBuf
[len
] = '\0';
1408 g_stp_dbg_cpupcr
->fwIsr
= osal_strtol(tempBuf
, NULL
, 16);
1410 STP_DBG_INFO_FUNC("fw isr str:%x\n",(UINT32
)osal_strtol(tempBuf
, NULL
, 16));
1412 case STP_DBG_FW_IRQ
:
1413 pDtr
= osal_strstr(pStr
,parser_sub_string
[type
]);
1416 pDtr
+= osal_strlen(parser_sub_string
[type
]);
1417 pTemp
= osal_strchr(pDtr
,',');
1420 STP_DBG_ERR_FUNC("parser str is NULL,substring(%s)\n",parser_sub_string
[type
]);
1424 osal_memcpy(&tempBuf
[0],pDtr
,len
);
1425 tempBuf
[len
] = '\0';
1426 g_stp_dbg_cpupcr
->fwRrq
= osal_strtol(tempBuf
, NULL
, 16);
1428 STP_DBG_INFO_FUNC("fw irq value:%x\n",(UINT32
)osal_strtol(tempBuf
, NULL
, 16));
1430 case STP_DBG_ASSERT_TYPE
:
1431 pDtr
= osal_strstr(pStr
,parser_sub_string
[type
]);
1434 pDtr
+= osal_strlen(parser_sub_string
[type
]);
1435 pTemp
= osal_strchr(pDtr
,',');
1438 STP_DBG_ERR_FUNC("parser str is NULL,substring(%s)\n",parser_sub_string
[type
]);
1442 osal_memcpy(&tempBuf
[0],pDtr
,len
);
1443 tempBuf
[len
] = '\0';
1445 if(0 == osal_memcmp(tempBuf
,"*",len
))
1447 osal_memcpy(&g_stp_dbg_cpupcr
->assert_type
[0],"general assert",osal_strlen("general assert"));
1449 if(0 == osal_memcmp(tempBuf
,"Watch Dog Timeout",len
))
1451 osal_memcpy(&g_stp_dbg_cpupcr
->assert_type
[0],"wdt",osal_strlen("wdt"));
1453 if(0 == osal_memcmp(tempBuf
,"RB_FULL",osal_strlen("RB_FULL")))
1455 osal_memcpy(&g_stp_dbg_cpupcr
->assert_type
[0],tempBuf
,len
);
1457 pDtr
= osal_strstr(&g_stp_dbg_cpupcr
->assert_type
[0],"RB_FULL(");
1460 pDtr
+= osal_strlen("RB_FULL(");
1461 pTemp
= osal_strchr(pDtr
,')');
1464 STP_DBG_ERR_FUNC("parser str is NULL,substring(RB_FULL()\n");
1468 osal_memcpy(&tempBuf
[0],pDtr
,len
);
1469 tempBuf
[len
] = '\0';
1471 g_stp_dbg_cpupcr
->fwTaskId
= osal_strtol(tempBuf
, NULL
, 16);
1473 STP_DBG_INFO_FUNC("update fw task id :%x\n",(UINT32
)osal_strtol(tempBuf
, NULL
, 16));
1476 STP_DBG_INFO_FUNC("fw asert type:%s\n",g_stp_dbg_cpupcr
->assert_type
);
1479 STP_DBG_ERR_FUNC("unknow parser type\n");
1485 P_STP_DBG_CPUPCR_T
stp_dbg_cpupcr_init(VOID
)
1487 P_STP_DBG_CPUPCR_T pSdCpupcr
= NULL
;
1489 pSdCpupcr
= (P_STP_DBG_CPUPCR_T
)osal_malloc(osal_sizeof(STP_DBG_CPUPCR_T
));
1491 STP_DBG_ERR_FUNC("stp dbg cpupcr allocate memory fail!\n");
1495 osal_memset(pSdCpupcr
,0,osal_sizeof(STP_DBG_CPUPCR_T
));
1497 osal_sleepable_lock_init(&pSdCpupcr
->lock
);
1502 P_STP_DBG_DMAREGS_T
stp_dbg_dmaregs_init(VOID
)
1504 P_STP_DBG_DMAREGS_T pDmaRegs
= NULL
;
1506 pDmaRegs
= (P_STP_DBG_DMAREGS_T
)osal_malloc(osal_sizeof(STP_DBG_DMAREGS_T
));
1508 STP_DBG_ERR_FUNC("stp dbg dmareg allocate memory fail!\n");
1512 osal_memset(pDmaRegs
,0,osal_sizeof(STP_DBG_DMAREGS_T
));
1514 osal_sleepable_lock_init(&pDmaRegs
->lock
);
1519 VOID
stp_dbg_cpupcr_deinit(P_STP_DBG_CPUPCR_T pCpupcr
)
1523 osal_sleepable_lock_deinit(&pCpupcr
->lock
);
1528 VOID
stp_dbg_dmaregs_deinit(P_STP_DBG_DMAREGS_T pDmaRegs
)
1532 osal_sleepable_lock_deinit(&pDmaRegs
->lock
);
1533 osal_free(pDmaRegs
);
1537 INT32
stp_dbg_poll_cpupcr(UINT32 times
,UINT32 sleep
,UINT32 cmd
)
1541 if(!g_stp_dbg_cpupcr
)
1543 STP_DBG_ERR_FUNC("NULL reference pointer\n");
1549 if(g_stp_dbg_cpupcr
->count
+ times
> STP_DBG_CPUPCR_NUM
)
1551 times
= STP_DBG_CPUPCR_NUM
- g_stp_dbg_cpupcr
->count
;
1554 osal_lock_sleepable_lock(&g_stp_dbg_cpupcr
->lock
);
1556 for(i
= 0;i
< times
;i
++)
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
);
1563 g_stp_dbg_cpupcr
->count
+= times
;
1565 osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr
->lock
);
1568 STP_DBG_INFO_FUNC("stp-dbg: for proc test polling cpupcr\n");
1569 if(times
> STP_DBG_CPUPCR_NUM
)
1571 times
= STP_DBG_CPUPCR_NUM
;
1574 osal_lock_sleepable_lock(&g_stp_dbg_cpupcr
->lock
);
1575 g_stp_dbg_cpupcr
->count
= 0;
1576 for(i
= 0;i
< times
;i
++)
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
);
1583 g_stp_dbg_cpupcr
->count
= times
;
1585 osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr
->lock
);
1591 INT32
stp_dbg_poll_dmaregs(UINT32 times
, UINT32 sleep
)
1595 if(!g_stp_dbg_dmaregs
)
1597 STP_DBG_ERR_FUNC("NULL reference pointer\n");
1601 if(g_stp_dbg_dmaregs
->count
+ times
> STP_DBG_DMAREGS_NUM
)
1603 times
= STP_DBG_DMAREGS_NUM
- g_stp_dbg_dmaregs
->count
;
1606 osal_lock_sleepable_lock(&g_stp_dbg_dmaregs
->lock
);
1608 STP_DBG_WARN_FUNC("---------Now Polling DMA relative Regs ------------- \n");
1609 for(i
= 0;i
< times
;i
++)
1612 for(; k
< DMA_REGS_MAX
; k
++)
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);
1617 osal_sleep_ms(sleep
);
1619 STP_DBG_WARN_FUNC("---------Polling DMA relative Regs End------------- \n");
1620 g_stp_dbg_dmaregs
->count
+= times
;
1622 osal_unlock_sleepable_lock(&g_stp_dbg_dmaregs
->lock
);
1626 INT32
stp_dbg_poll_cuppcr_ctrl(UINT32 en
)
1629 STP_DBG_INFO_FUNC("%s polling cpupcr\n",en
== 0? "start":"stop");
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
);
1637 INT32
stp_dbg_set_version_info(UINT32 chipid
,UINT8
*pRomVer
,UINT8
*wifiVer
,UINT8
*pPatchVer
,UINT8
*pPatchBrh
)
1639 if(g_stp_dbg_cpupcr
)
1641 osal_lock_sleepable_lock(&g_stp_dbg_cpupcr
->lock
);
1642 g_stp_dbg_cpupcr
->chipId
= chipid
;
1646 osal_memcpy(g_stp_dbg_cpupcr
->wifiVer
,wifiVer
,4);
1650 osal_memcpy(g_stp_dbg_cpupcr
->romVer
,pRomVer
,2);
1654 osal_memcpy(g_stp_dbg_cpupcr
->patchVer
,pPatchVer
,8);
1658 osal_memcpy(g_stp_dbg_cpupcr
->branchVer
,pPatchBrh
,4);
1660 osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr
->lock
);
1664 STP_DBG_ERR_FUNC("NULL pointer\n");
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]);
1673 INT32
stp_dbg_set_host_assert_info(UINT32 drv_type
,UINT32 reason
,UINT32 en
)
1675 osal_lock_sleepable_lock(&g_stp_dbg_cpupcr
->lock
);
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
;
1681 osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr
->lock
);
1686 UINT32
stp_dbg_get_host_trigger_assert(VOID
)
1688 return g_stp_dbg_cpupcr
->host_assert_info
.assert_from_host
;
1692 INT32
stp_dbg_set_fw_info(UINT8
*issue_info
,UINT32 len
,ENUM_STP_FW_ISSUE_TYPE issue_type
)
1694 ENUM_ASSERT_INFO_PARSER_TYPE type_index
;
1695 PUINT8 tempbuf
= NULL
;
1699 if(NULL
== issue_info
)
1701 STP_DBG_ERR_FUNC("null issue infor\n");
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
);
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");
1714 if((STP_FW_ASSERT_ISSUE
== issue_type
) || (STP_HOST_TRIGGER_FW_ASSERT
== issue_type
))
1716 tempbuf
= osal_malloc(len
);
1721 osal_memcpy(&tempbuf
[0],issue_info
,len
);
1723 for(i
= 0;i
< len
;i
++)
1725 if(tempbuf
[i
] == '\0')
1729 tempbuf
[len
] = '\0';
1731 STP_DBG_INFO_FUNC("FW assert infor len(%d)\n",len
);
1732 for(i
= 0;i
< len
;i
++)
1736 printk("%c",tempbuf
[i
]);
1740 for(type_index
= STP_DBG_ASSERT_INFO
;type_index
< STP_DBG_PARSER_TYPE_MAX
;type_index
++)
1742 iRet
+= _stp_dbg_parser_assert_str(&tempbuf
[0],type_index
);
1746 STP_DBG_ERR_FUNC("passert assert infor fail(%d)\n",iRet
);
1749 if(STP_HOST_TRIGGER_FW_ASSERT
== issue_type
)
1751 switch(g_stp_dbg_cpupcr
->host_assert_info
.drv_type
) {
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*/
1758 g_stp_dbg_cpupcr
->fwTaskId
= 1;
1761 /*BT stack trigger assert*/
1763 g_stp_dbg_cpupcr
->fwTaskId
= 8;
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;
1770 osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr
->lock
);
1780 else if(STP_FW_NOACK_ISSUE
== issue_type
)
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
)
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
)
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
);
1807 STP_DBG_ERR_FUNC("invalid issue type(%d)\n",issue_type
);
1815 INT32
stp_dbg_cpupcr_infor_format(PPUINT8 buf
,PUINT32 str_len
)
1819 if(!g_stp_dbg_cpupcr
)
1821 STP_DBG_ERR_FUNC("NULL pointer\n");
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
)))
1832 len
+= osal_sprintf(*buf
+ len
,"<branch>Internal Dev</branch>\n\t\t",g_stp_dbg_cpupcr
->branchVer
);
1835 len
+= osal_sprintf(*buf
+ len
,"<branch>W%sMP</branch>\n\t\t",g_stp_dbg_cpupcr
->branchVer
);
1837 len
+= osal_sprintf(*buf
+ len
,"<patch>%s</patch>\n\t\t",g_stp_dbg_cpupcr
->patchVer
);
1839 if(!g_stp_dbg_cpupcr
->wifiVer
[0])
1841 len
+= osal_sprintf(*buf
+ len
,"<wifi>NULL</wifi>\n\t");
1844 len
+= osal_sprintf(*buf
+ len
,"<wifi>%s</wifi>\n\t",g_stp_dbg_cpupcr
->wifiVer
);
1846 len
+= osal_sprintf(*buf
+ len
,"</version>\n\t");
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
))
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
))
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
)
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");
1877 len
+= osal_sprintf(*buf
+ len
,"<irqx>IRQ_0x%x</irqx>\n\t\t\t",g_stp_dbg_cpupcr
->fwRrq
);
1879 len
+= osal_sprintf(*buf
+ len
,"<isr>0x%x</isr>\n\t\t\t",g_stp_dbg_cpupcr
->fwIsr
);
1881 if(STP_FW_ASSERT_ISSUE
== g_stp_dbg_cpupcr
->issue_type
)
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");
1887 if(STP_HOST_TRIGGER_FW_ASSERT
== g_stp_dbg_cpupcr
->issue_type
)
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
);
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");
1905 len
+= osal_sprintf(*buf
+ len
,"<pctrace>");
1906 STP_DBG_INFO_FUNC("stp-dbg:sub len1 for debug(%d)\n",len
);
1908 if(!g_stp_dbg_cpupcr
->count
)
1910 len
+= osal_sprintf(*buf
+ len
,"NULL");
1914 for(i
= 0;i
< g_stp_dbg_cpupcr
->count
;i
++)
1916 len
+= osal_sprintf(*buf
+ len
,"%08x,",g_stp_dbg_cpupcr
->buffer
[i
]);
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);
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
);
1937 MTKSTP_DBG_T
*stp_dbg_init(void *btm_half
){
1939 MTKSTP_DBG_T
*stp_dbg
= NULL
;
1940 STP_DBG_INFO_FUNC("stp-dbg init\n");
1942 stp_dbg
= kzalloc(sizeof(MTKSTP_DBG_T
), GFP_KERNEL
);
1943 if(IS_ERR(stp_dbg
)){
1944 STP_DBG_ERR_FUNC("-ENOMEM\n");
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");
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
;
1959 if(btm_half
!= NULL
){
1960 stp_dbg
->btm
= btm_half
;
1962 stp_dbg
->btm
= NULL
;
1968 g_core_dump
= wcn_core_dump_init(STP_CORE_DUMP_TIMEOUT
);
1970 g_stp_dbg_cpupcr
= stp_dbg_cpupcr_init();
1971 g_stp_dbg_dmaregs
= stp_dbg_dmaregs_init();
1983 int stp_dbg_deinit(MTKSTP_DBG_T
*stp_dbg
){
1985 STP_DBG_INFO_FUNC("stp-dbg deinit\n");
1987 wcn_core_dump_deinit(g_core_dump
);
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();
1994 if(stp_dbg
->logsys
){
1995 vfree(stp_dbg
->logsys
);