1 #include <linux/kernel.h> // GFP_KERNEL
2 #include <linux/timer.h> //init_timer, add_time, del_timer_sync
3 #include <linux/time.h> //gettimeofday
4 #include <linux/delay.h>
5 #include <linux/slab.h> //kzalloc
6 #include <linux/sched.h> //task's status
7 #include <linux/vmalloc.h>
9 #include <linux/workqueue.h>
10 #include <asm/atomic.h>
13 #include <net/netlink.h>
14 #include <linux/skbuff.h>
15 #include <net/genetlink.h>
17 #include <linux/zlib.h>
18 #include <linux/uaccess.h>
19 #include <linux/crc32.h>
22 //#include "stp_btm.h"
25 #define PFX_STP_DBG "[STPDbg]"
26 #define STP_DBG_LOG_LOUD 4
27 #define STP_DBG_LOG_DBG 3
28 #define STP_DBG_LOG_INFO 2
29 #define STP_DBG_LOG_WARN 1
30 #define STP_DBG_LOG_ERR 0
32 unsigned int gStpDbgDbgLevel = STP_DBG_LOG_INFO;
33 unsigned int gStpDbgLogOut = 0;
35 #define STP_DBG_LOUD_FUNC(fmt, arg...) if(gStpDbgDbgLevel >= STP_DBG_LOG_LOUD){ printk(KERN_DEBUG PFX_STP_DBG "%s: " fmt, __FUNCTION__ ,##arg);}
36 #define STP_DBG_DBG_FUNC(fmt, arg...) if(gStpDbgDbgLevel >= STP_DBG_LOG_DBG){ printk(KERN_DEBUG PFX_STP_DBG "%s: " fmt, __FUNCTION__ ,##arg);}
37 #define STP_DBG_INFO_FUNC(fmt, arg...) if(gStpDbgDbgLevel >= STP_DBG_LOG_INFO){ printk(PFX_STP_DBG "%s: " fmt, __FUNCTION__ ,##arg);}
38 #define STP_DBG_WARN_FUNC(fmt, arg...) if(gStpDbgDbgLevel >= STP_DBG_LOG_WARN){ printk(PFX_STP_DBG "%s: " fmt, __FUNCTION__ ,##arg);}
39 #define STP_DBG_ERR_FUNC(fmt, arg...) if(gStpDbgDbgLevel >= STP_DBG_LOG_ERR){ printk(PFX_STP_DBG "%s: " fmt, __FUNCTION__ ,##arg);}
40 #define STP_DBG_TRC_FUNC(f) if(gStpDbgDbgLevel >= STP_DBG_LOG_DBG){ printk(KERN_DEBUG PFX_STP_DBG "<%s> <%d>\n", __FUNCTION__, __LINE__);}
43 MTKSTP_DBG_T *g_stp_dbg = NULL;
45 #define STP_DBG_FAMILY_NAME "STP_DBG"
46 #define MAX_BIND_PROCESS (4)
49 __STP_DBG_ATTR_INVALID,
53 #define STP_DBG_ATTR_MAX (__STP_DBG_ATTR_MAX - 1)
56 __STP_DBG_COMMAND_INVALID,
58 STP_DBG_COMMAND_RESET,
59 __STP_DBG_COMMAND_MAX,
61 #define MTK_WIFI_COMMAND_MAX (__STP_DBG_COMMAND_MAX - 1)
63 static struct genl_family stp_dbg_gnl_family = {
64 .id = GENL_ID_GENERATE,
66 .name = STP_DBG_FAMILY_NAME,
68 .maxattr = STP_DBG_ATTR_MAX,
71 static void stp_dbg_nl_init(void);
72 static void stp_dbg_nl_deinit(void);
73 static int stp_dbg_nl_bind(
75 struct genl_info *info
77 static int stp_dbg_nl_reset(
79 struct genl_info *info
82 /* attribute policy */
83 static struct nla_policy stp_dbg_genl_policy[STP_DBG_ATTR_MAX + 1] = {
84 [STP_DBG_ATTR_MSG] = { .type = NLA_NUL_STRING },
87 /* operation definition */
88 static struct genl_ops stp_dbg_gnl_ops_bind = {
89 .cmd = STP_DBG_COMMAND_BIND,
91 .policy = stp_dbg_genl_policy,
92 .doit = stp_dbg_nl_bind,
96 static struct genl_ops stp_dbg_gnl_ops_reset = {
97 .cmd = STP_DBG_COMMAND_RESET,
99 .policy = stp_dbg_genl_policy,
100 .doit = stp_dbg_nl_reset,
104 static unsigned int stp_dbg_seqnum = 0;
105 static int num_bind_process = 0;
106 static pid_t bind_pid[MAX_BIND_PROCESS];
108 static P_WCN_CORE_DUMP_T g_core_dump = NULL;
110 /* core_dump_timeout_handler - handler of coredump timeout
111 * @ data - core dump object's pointer
115 static void core_dump_timeout_handler(ULONG data)
117 P_WCN_CORE_DUMP_T dmp = (P_WCN_CORE_DUMP_T)data;
119 STP_DBG_INFO_FUNC(" start\n");
121 stp_btm_notify_coredump_timeout_wq(g_stp_dbg->btm);
123 STP_DBG_INFO_FUNC(" end\n");
126 dmp->sm = CORE_DUMP_TIMEOUT;
131 /* wcn_core_dump_init - create core dump sys
132 * @ timeout - core dump time out value
134 * Return object pointer if success, else NULL
136 P_WCN_CORE_DUMP_T wcn_core_dump_init(UINT32 timeout)
138 #define KBYTES (1024*sizeof(char))
139 #define L1_BUF_SIZE (32*KBYTES)
140 #define L2_BUF_SIZE (512*KBYTES)
142 P_WCN_CORE_DUMP_T core_dmp = NULL;
144 core_dmp = (P_WCN_CORE_DUMP_T)osal_malloc(sizeof(WCN_CORE_DUMP_T));
146 STP_DBG_ERR_FUNC("alloc mem failed!\n");
150 osal_memset(core_dmp, 0, sizeof(WCN_CORE_DUMP_T));
152 core_dmp->compressor = wcn_compressor_init("core_dump_compressor", L1_BUF_SIZE, L2_BUF_SIZE);
153 if (!core_dmp->compressor) {
154 STP_DBG_ERR_FUNC("create compressor failed!\n");
157 wcn_compressor_reset(core_dmp->compressor, 1, GZIP);
159 core_dmp->dmp_timer.timeoutHandler = core_dump_timeout_handler;
160 core_dmp->dmp_timer.timeroutHandlerData = (ULONG)core_dmp;
161 osal_timer_create(&core_dmp->dmp_timer);
162 core_dmp->timeout = timeout;
164 osal_sleepable_lock_init(&core_dmp->dmp_lock);
166 core_dmp->sm = CORE_DUMP_INIT;
167 STP_DBG_INFO_FUNC("create coredump object OK!\n");
172 if (core_dmp && core_dmp->compressor) {
173 wcn_compressor_deinit(core_dmp->compressor);
174 core_dmp->compressor = NULL;
181 osal_sleepable_lock_deinit(&core_dmp->dmp_lock);
187 /* wcn_core_dump_deinit - destroy core dump object
188 * @ dmp - pointer of object
190 * Retunr 0 if success, else error code
192 INT32 wcn_core_dump_deinit(P_WCN_CORE_DUMP_T dmp)
194 if (dmp && dmp->compressor) {
195 wcn_compressor_deinit(dmp->compressor);
196 dmp->compressor = NULL;
200 osal_sleepable_lock_deinit(&dmp->dmp_lock);
201 osal_timer_stop(&dmp->dmp_timer);
209 static INT32 wcn_core_dump_check_end(PUINT8 buf, INT32 len)
211 if (strnstr(buf, "coredump end", len)) {
219 /* wcn_core_dump_in - add a packet to compressor buffer
220 * @ dmp - pointer of object
221 * @ buf - input buffer
222 * @ len - data length
224 * Retunr 0 if success; return 1 if find end string; else error code
226 INT32 wcn_core_dump_in(P_WCN_CORE_DUMP_T dmp, PUINT8 buf, INT32 len)
230 #define INFO_HEAD "MT6628 FW CORE, "
232 if ((!dmp) || (!buf)) {
233 STP_DBG_ERR_FUNC("invalid pointer!\n");
237 ret = osal_lock_sleepable_lock(&dmp->dmp_lock);
239 STP_DBG_ERR_FUNC("--->lock dmp->dmp_lock failed, ret=%d\n", ret);
245 wcn_compressor_reset(dmp->compressor, 1, GZIP);
246 osal_timer_start(&dmp->dmp_timer, STP_CORE_DUMP_TIMEOUT);
248 // first package, copy to info buffer
249 osal_strcpy(&dmp->info[0], INFO_HEAD);
250 tmp = STP_CORE_DUMP_INFO_SZ - osal_strlen(INFO_HEAD);
251 tmp = (len > tmp) ? tmp : len;
252 osal_memcpy(&dmp->info[osal_strlen(INFO_HEAD)], buf, tmp);
253 dmp->info[STP_CORE_DUMP_INFO_SZ] = '\0';
255 // show coredump start info on UI
256 //osal_dbg_assert_aee("MT662x f/w coredump start", "MT662x firmware coredump start");
258 aee_kernel_dal_show("MT662x coredump start, please wait up to 5 minutes.\n");
260 // parsing data, and check end srting
261 ret = wcn_core_dump_check_end(buf, len);
263 STP_DBG_INFO_FUNC("core dump end!\n");
264 dmp->sm = CORE_DUMP_DONE;
265 wcn_compressor_in(dmp->compressor, buf, len, 1);
267 dmp->sm = CORE_DUMP_DOING;
268 wcn_compressor_in(dmp->compressor, buf, len, 0);
272 case CORE_DUMP_DOING:
273 // parsing data, and check end srting
274 ret = wcn_core_dump_check_end(buf, len);
276 STP_DBG_INFO_FUNC("core dump end!\n");
277 dmp->sm = CORE_DUMP_DONE;
278 wcn_compressor_in(dmp->compressor, buf, len, 1);
280 dmp->sm = CORE_DUMP_DOING;
281 wcn_compressor_in(dmp->compressor, buf, len, 0);
286 wcn_compressor_reset(dmp->compressor, 1, GZIP);
287 osal_timer_start(&dmp->dmp_timer, STP_CORE_DUMP_TIMEOUT);
288 wcn_compressor_in(dmp->compressor, buf, len, 0);
289 dmp->sm = CORE_DUMP_DOING;
292 case CORE_DUMP_TIMEOUT:
298 osal_unlock_sleepable_lock(&dmp->dmp_lock);
304 /* wcn_core_dump_out - get compressed data from compressor buffer
305 * @ dmp - pointer of object
306 * @ pbuf - target buffer's pointer
307 * @ len - data length
309 * Retunr 0 if success; else error code
311 INT32 wcn_core_dump_out(P_WCN_CORE_DUMP_T dmp, PUINT8 *pbuf, PINT32 plen)
315 if ((!dmp) || (!pbuf) || (!plen)) {
316 STP_DBG_ERR_FUNC("invalid pointer!\n");
320 ret = osal_lock_sleepable_lock(&dmp->dmp_lock);
322 STP_DBG_ERR_FUNC("--->lock dmp->dmp_lock failed, ret=%d\n", ret);
326 ret = wcn_compressor_out(dmp->compressor, pbuf, plen);
328 osal_unlock_sleepable_lock(&dmp->dmp_lock);
334 /* wcn_core_dump_reset - reset core dump sys
335 * @ dmp - pointer of object
336 * @ timeout - core dump time out value
338 * Retunr 0 if success, else error code
340 INT32 wcn_core_dump_reset(P_WCN_CORE_DUMP_T dmp, UINT32 timeout)
343 STP_DBG_ERR_FUNC("invalid pointer!\n");
347 dmp->sm = CORE_DUMP_INIT;
348 dmp->timeout = timeout;
349 osal_timer_stop(&dmp->dmp_timer);
350 wcn_compressor_reset(dmp->compressor, 1, GZIP);
351 osal_memset(dmp->info, 0, STP_CORE_DUMP_INFO_SZ + 1);
357 /* wcn_core_dump_flush - Fulsh dump data and reset core dump sys
359 * Retunr 0 if success, else error code
361 INT32 wcn_core_dump_flush(INT32 rst)
367 STP_DBG_ERR_FUNC("invalid pointer!\n");
371 wcn_core_dump_out(g_core_dump, &pbuf, &len);
372 STP_DBG_INFO_FUNC("buf 0x%08x, len %d\n", (unsigned int)pbuf, len);
374 // show coredump end info on UI
375 //osal_dbg_assert_aee("MT662x f/w coredump end", "MT662x firmware coredump ends");
377 aee_kernel_dal_show("MT662x coredump end\n");
379 // call AEE driver API
380 aed_combo_exception(NULL, 0, (const int*)pbuf, len, (const char*)g_core_dump->info);
383 wcn_core_dump_reset(g_core_dump, STP_CORE_DUMP_TIMEOUT);
389 static INT32 wcn_gzip_compressor(void *worker, UINT8 *in_buf, INT32 in_sz, UINT8 *out_buf, INT32 *out_sz, INT32 finish)
392 z_stream *stream = NULL;
395 STP_DBG_INFO_FUNC("in buf 0x%08x, in sz %d\n", (unsigned int)in_buf, in_sz);
396 STP_DBG_INFO_FUNC("out buf 0x%08x, out sz %d\n", (unsigned int)out_buf, tmp);
398 stream = (z_stream*)worker;
400 STP_DBG_ERR_FUNC("invalid workspace!\n");
406 ret = zlib_deflateReset(stream);
408 STP_DBG_ERR_FUNC("reset failed!\n");
413 stream->next_in = in_buf;
414 stream->avail_in = in_sz;
415 stream->next_out = out_buf;
416 stream->avail_out = tmp;
418 zlib_deflate(stream, Z_FULL_FLUSH);
422 int val = zlib_deflate(stream, Z_FINISH);
425 } else if (val == Z_STREAM_END) {
428 STP_DBG_ERR_FUNC("finish operation failed %d\n", val);
434 *out_sz = tmp - stream->avail_out;
437 STP_DBG_INFO_FUNC("out buf 0x%08x, out sz %d\n", (unsigned int)out_buf, *out_sz);
443 /* wcn_compressor_init - create a compressor and do init
444 * @ name - compressor's name
445 * @ L1_buf_sz - L1 buffer size
446 * @ L2_buf_sz - L2 buffer size
448 * Retunr object's pointer if success, else NULL
450 P_WCN_COMPRESSOR_T wcn_compressor_init(PUINT8 name, INT32 L1_buf_sz, INT32 L2_buf_sz)
452 z_stream *pstream = NULL;
453 P_WCN_COMPRESSOR_T compress = NULL;
455 compress = (P_WCN_COMPRESSOR_T)osal_malloc(sizeof(WCN_COMPRESSOR_T));
457 STP_DBG_ERR_FUNC("alloc compressor failed!\n");
461 osal_memset(compress, 0, sizeof(WCN_COMPRESSOR_T));
462 osal_memcpy(compress->name, name, STP_OJB_NAME_SZ);
464 compress->f_compress_en = 0;
465 compress->compress_type = GZIP;
467 if (compress->compress_type == GZIP) {
468 compress->worker = osal_malloc(sizeof(z_stream));
469 if (!compress->worker) {
470 STP_DBG_ERR_FUNC("alloc stream failed!\n");
473 pstream = (z_stream*)compress->worker;
475 pstream->workspace = osal_malloc(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL));
476 if (!pstream->workspace) {
477 STP_DBG_ERR_FUNC("alloc workspace failed!\n");
480 zlib_deflateInit2(pstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS,
481 DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
484 compress->handler = wcn_gzip_compressor;
485 compress->L1_buf_sz = L1_buf_sz;
486 compress->L2_buf_sz = L2_buf_sz;
487 compress->L1_pos = 0;
488 compress->L2_pos = 0;
489 compress->uncomp_size = 0;
490 compress->crc32 = 0xffffffffUL;
492 compress->L1_buf = osal_malloc(compress->L1_buf_sz);
493 if (!compress->L1_buf) {
494 STP_DBG_ERR_FUNC("alloc %d bytes for L1 buf failed!\n", compress->L1_buf_sz);
498 compress->L2_buf = osal_malloc(compress->L2_buf_sz);
499 if (!compress->L2_buf) {
500 STP_DBG_ERR_FUNC("alloc %d bytes for L2 buf failed!\n", compress->L2_buf_sz);
504 STP_DBG_INFO_FUNC("create compressor OK! L1 %d bytes, L2 %d bytes\n", L1_buf_sz, L2_buf_sz);
509 if (compress->L2_buf) {
510 osal_free(compress->L2_buf);
511 compress->L2_buf = NULL;
514 if (compress->L1_buf) {
515 osal_free(compress->L1_buf);
516 compress->L1_buf = NULL;
519 if (compress->worker) {
520 pstream = (z_stream*)compress->worker;
521 if ((compress->compress_type == GZIP) && pstream->workspace) {
522 zlib_deflateEnd(pstream);
523 osal_free(pstream->workspace);
525 osal_free(compress->worker);
526 compress->worker = NULL;
529 if (compress->worker) {
530 osal_free(compress->worker);
531 compress->worker = NULL;
538 STP_DBG_ERR_FUNC("init failed!\n");
544 /* wcn_compressor_deinit - distroy a compressor
545 * @ cprs - compressor's pointer
547 * Retunr 0 if success, else NULL
549 INT32 wcn_compressor_deinit(P_WCN_COMPRESSOR_T cprs)
551 z_stream *pstream = NULL;
555 osal_free(cprs->L2_buf);
560 osal_free(cprs->L1_buf);
565 pstream = (z_stream*)cprs->worker;
566 if ((cprs->compress_type == GZIP) && pstream->workspace) {
567 zlib_deflateEnd(pstream);
568 osal_free(pstream->workspace);
570 osal_free(cprs->worker);
574 cprs->handler = NULL;
579 STP_DBG_INFO_FUNC("destroy OK\n");
585 /* wcn_compressor_in - put in a raw data, and compress L1 buffer if need
586 * @ cprs - compressor's pointer
587 * @ buf - raw data buffer
588 * @ len - raw data length
589 * @ finish - core dump finish or not, 1: finished; 0: not finish
591 * Retunr 0 if success, else NULL
593 INT32 wcn_compressor_in(P_WCN_COMPRESSOR_T cprs, PUINT8 buf, INT32 len, INT32 finish)
599 STP_DBG_ERR_FUNC("invalid para!\n");
603 cprs->uncomp_size += len;
605 // check L1 buf valid space
606 if (len > (cprs->L1_buf_sz - cprs->L1_pos)) {
607 STP_DBG_INFO_FUNC("L1 buffer full\n");
609 if (cprs->f_compress_en && cprs->handler) {
611 // compress L1 buffer, and put result to L2 buffer
612 tmp_len = cprs->L2_buf_sz - cprs->L2_pos;
613 ret = cprs->handler(cprs->worker, cprs->L1_buf, cprs->L1_pos, &cprs->L2_buf[cprs->L2_pos], &tmp_len, finish);
615 cprs->crc32 = (crc32(cprs->crc32, cprs->L1_buf, cprs->L1_pos));
616 cprs->L2_pos += tmp_len;
621 32 bits UNCOMPRESS SIZE
624 *(uint32_t *)(&cprs->L2_buf[cprs->L2_pos]) = (cprs->crc32 ^ 0xffffffffUL);
625 *(uint32_t *)(&cprs->L2_buf[cprs->L2_pos + 4]) = cprs->uncomp_size;
628 STP_DBG_INFO_FUNC("compress OK!\n");
630 STP_DBG_ERR_FUNC("compress error!\n");
634 // Flush L1 buffer to L2 buffer
635 STP_DBG_INFO_FUNC("No need do compress, Put to L2 buf\n");
637 tmp_len = cprs->L2_buf_sz - cprs->L2_pos;
638 tmp_len = (cprs->L1_pos > tmp_len) ? tmp_len : cprs->L1_pos;
639 osal_memcpy(&cprs->L2_buf[cprs->L2_pos], cprs->L1_buf, tmp_len);
640 cprs->L2_pos += tmp_len;
646 // put curren data to L1 buf
647 if (len > cprs->L1_buf_sz) {
648 STP_DBG_ERR_FUNC("len=%d, too long err!\n", len);
650 STP_DBG_INFO_FUNC("L1 Flushed, and Put %d bytes to L1 buf\n", len);
651 osal_memcpy(&cprs->L1_buf[cprs->L1_pos], buf, len);
656 STP_DBG_INFO_FUNC("Put %d bytes to L1 buf\n", len);
658 osal_memcpy(&cprs->L1_buf[cprs->L1_pos], buf, len);
666 /* wcn_compressor_out - get the result data from L2 buffer
667 * @ cprs - compressor's pointer
668 * @ pbuf - point to L2 buffer
671 * Retunr 0 if success, else NULL
673 INT32 wcn_compressor_out(P_WCN_COMPRESSOR_T cprs, PUINT8 *pbuf, PINT32 plen)
678 if ((!cprs) || (!pbuf) || (!plen)) {
679 STP_DBG_ERR_FUNC("invalid para!\n");
683 // check if there's L1 data need flush to L2 buffer
684 if (cprs->L1_pos > 0) {
685 tmp_len = cprs->L2_buf_sz - cprs->L2_pos;
687 if (cprs->f_compress_en && cprs->handler) {
689 ret = cprs->handler(cprs->worker, cprs->L1_buf, cprs->L1_pos, &cprs->L2_buf[cprs->L2_pos], &tmp_len, 1);
692 cprs->crc32 = (crc32(cprs->crc32, cprs->L1_buf, cprs->L1_pos));
693 cprs->L2_pos += tmp_len;
697 32 bits UNCOMPRESS SIZE
700 *(uint32_t *)(&cprs->L2_buf[cprs->L2_pos]) = (cprs->crc32 ^ 0xffffffffUL);
701 *(uint32_t *)(&cprs->L2_buf[cprs->L2_pos + 4]) = cprs->uncomp_size;
704 STP_DBG_INFO_FUNC("compress OK!\n");
706 STP_DBG_ERR_FUNC("compress error!\n");
710 tmp_len = (cprs->L1_pos > tmp_len) ? tmp_len : cprs->L1_pos;
711 osal_memcpy(&cprs->L2_buf[cprs->L2_pos], cprs->L1_buf, tmp_len);
712 cprs->L2_pos += tmp_len;
719 *pbuf = cprs->L2_buf;
720 *plen = cprs->L2_pos;
722 STP_DBG_INFO_FUNC("0x%08x, len %d\n", (unsigned int)*pbuf, *plen);
725 ret = zlib_deflateReset((z_stream*)cprs->worker);
727 STP_DBG_ERR_FUNC("reset failed!\n");
736 /* wcn_compressor_reset - reset compressor
737 * @ cprs - compressor's pointer
738 * @ enable - enable/disable compress
739 * @ type - compress algorithm
741 * Retunr 0 if success, else NULL
743 INT32 wcn_compressor_reset(P_WCN_COMPRESSOR_T cprs, UINT8 enable, WCN_COMPRESS_ALG_T type)
746 STP_DBG_ERR_FUNC("invalid para!\n");
750 cprs->f_compress_en = enable;
751 //cprs->f_compress_en = 0; // disable compress for test
752 cprs->compress_type = type;
755 cprs->uncomp_size = 0;
756 cprs->crc32 = 0xffffffffUL;
758 STP_DBG_INFO_FUNC("OK! compress algorithm %d\n", type);
764 static void stp_dbg_dump_data(unsigned char *pBuf, char * title, int len)
767 printk(" %s-len:%d\n", title, len);
768 //printk(" ", title, len);
769 for(k=0; k < len ; k++){
770 if(k%16 == 0 && k != 0) printk("\n ");
771 printk("0x%02x ", pBuf[k]);
777 static int _stp_dbg_enable(MTKSTP_DBG_T *stp_dbg){
781 spin_lock_irqsave(&(stp_dbg->logsys->lock), flags);
782 stp_dbg->pkt_trace_no=0;
783 stp_dbg->is_enable=1;
784 spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags);
789 static int _stp_dbg_disable(MTKSTP_DBG_T *stp_dbg){
793 spin_lock_irqsave(&(stp_dbg->logsys->lock), flags);
794 stp_dbg->pkt_trace_no=0;
795 memset(stp_dbg->logsys, 0, sizeof(MTKSTP_LOG_SYS_T));
796 stp_dbg->is_enable=0;
797 spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags);
802 static int _stp_dbg_dmp_in(MTKSTP_DBG_T *stp_dbg, char *buf, int len){
805 unsigned int internalFlag = stp_dbg->logsys->size < STP_DBG_LOG_ENTRY_NUM;
806 //#ifdef CONFIG_LOG_STP_INTERNAL
807 //Here we record log in this circle buffer, if buffer is full , select to overlap earlier log, logic should be okay
810 spin_lock_irqsave(&(stp_dbg->logsys->lock), flags);
813 stp_dbg->logsys->queue[stp_dbg->logsys->in].id = 0;
814 stp_dbg->logsys->queue[stp_dbg->logsys->in].len = len;
815 memset(&(stp_dbg->logsys->queue[stp_dbg->logsys->in].buffer[0]),
816 0, ((len >= STP_DBG_LOG_ENTRY_SZ)? (STP_DBG_LOG_ENTRY_SZ):(len)));
817 memcpy(&(stp_dbg->logsys->queue[stp_dbg->logsys->in].buffer[0]),
818 buf, ((len >= STP_DBG_LOG_ENTRY_SZ)? (STP_DBG_LOG_ENTRY_SZ):(len)));
820 stp_dbg->logsys->size++;
821 stp_dbg->logsys->size = (stp_dbg->logsys->size > STP_DBG_LOG_ENTRY_NUM) ? STP_DBG_LOG_ENTRY_NUM : stp_dbg->logsys->size;
823 if (0 != gStpDbgLogOut)
825 STP_DBG_HDR_T *pHdr = NULL;
828 pHdr = (STP_DBG_HDR_T *)&(stp_dbg->logsys->queue[stp_dbg->logsys->in].buffer[0]);
829 pBuf = (char *)&(stp_dbg->logsys->queue[stp_dbg->logsys->in].buffer[0]) + sizeof (STP_DBG_HDR_T);
830 len = stp_dbg->logsys->queue[stp_dbg->logsys->in].len - sizeof (STP_DBG_HDR_T);
831 printk("STP-DBG:%d.%ds, %s:pT%sn(%d)l(%d)s(%d)a(%d)\n", \
834 pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx",
835 gStpDbgType[pHdr->type],
843 stp_dbg_dump_data(pBuf, pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx", len);
847 stp_dbg->logsys->in = (stp_dbg->logsys->in >= (STP_DBG_LOG_ENTRY_NUM - 1))?(0):(stp_dbg->logsys->in + 1);
848 STP_DBG_DBG_FUNC("logsys size = %d, in = %d\n", stp_dbg->logsys->size, stp_dbg->logsys->in);
850 STP_DBG_WARN_FUNC("logsys FULL!\n");
853 spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags);
858 int stp_gdb_notify_btm_dmp_wq(MTKSTP_DBG_T *stp_dbg){
860 //#ifndef CONFIG_LOG_STP_INTERNAL
862 if(stp_dbg->btm != NULL){
863 retval += stp_btm_notify_wmt_dmp_wq((MTKSTP_BTM_T *)stp_dbg->btm);
871 int stp_dbg_log_ctrl (unsigned int on)
876 printk ("STP-DBG: enable pkt log dump out.\n");
881 printk ("STP-DBG: disable pkt log dump out.\n");
886 int stp_dbg_dmp_in(MTKSTP_DBG_T *stp_dbg, char *buf, int len){
887 return _stp_dbg_dmp_in(stp_dbg, buf, len);
891 int stp_dbg_dmp_printk(MTKSTP_DBG_T *stp_dbg)
893 #define MAX_DMP_NUM 80
897 STP_DBG_HDR_T *pHdr = NULL;
901 spin_lock_irqsave(&(stp_dbg->logsys->lock), flags);
902 //Not to dequeue from loging system
903 inIndex = stp_dbg->logsys->in;
904 dumpSize = stp_dbg->logsys->size;
905 if (STP_DBG_LOG_ENTRY_NUM == dumpSize)
911 outIndex = ((inIndex + STP_DBG_LOG_ENTRY_NUM) - dumpSize) % STP_DBG_LOG_ENTRY_NUM;
914 if (dumpSize > MAX_DMP_NUM)
917 outIndex += (dumpSize - MAX_DMP_NUM);
918 outIndex %= STP_DBG_LOG_ENTRY_NUM;
919 dumpSize = MAX_DMP_NUM;
922 STP_DBG_INFO_FUNC("loged packet size = %d, in(%d), out(%d)\n", dumpSize, inIndex, outIndex);
924 pHdr = (STP_DBG_HDR_T *)&(stp_dbg->logsys->queue[outIndex].buffer[0]);
925 pBuf = &(stp_dbg->logsys->queue[outIndex].buffer[0]) + sizeof (STP_DBG_HDR_T);
926 len = stp_dbg->logsys->queue[outIndex].len - sizeof (STP_DBG_HDR_T);
927 len = len > STP_PKT_SZ ? STP_PKT_SZ : len;
928 printk("STP-DBG:%d.%ds, %s:pT%sn(%d)l(%d)s(%d)a(%d)\n", \
931 pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx",
932 gStpDbgType[pHdr->type],
941 stp_dbg_dump_data(pBuf, pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx", len);
943 outIndex = (outIndex >= (STP_DBG_LOG_ENTRY_NUM - 1))?(0):(outIndex + 1);
949 spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags);
954 int stp_dbg_dmp_out_ex (char *buf, int *len){
955 return stp_dbg_dmp_out(g_stp_dbg, buf, len);
958 int stp_dbg_dmp_out(MTKSTP_DBG_T *stp_dbg, char *buf, int *len){
963 spin_lock_irqsave(&(stp_dbg->logsys->lock), flags);
965 if(stp_dbg->logsys->size > 0){
966 memcpy(buf, &(stp_dbg->logsys->queue[stp_dbg->logsys->out].buffer[0]),
967 stp_dbg->logsys->queue[stp_dbg->logsys->out].len);
969 (*len) = stp_dbg->logsys->queue[stp_dbg->logsys->out].len;
970 stp_dbg->logsys->out = (stp_dbg->logsys->out >= (STP_DBG_LOG_ENTRY_NUM - 1))?(0):(stp_dbg->logsys->out + 1);
971 stp_dbg->logsys->size--;
973 STP_DBG_DBG_FUNC("logsys size = %d, out = %d\n", stp_dbg->logsys->size, stp_dbg->logsys->out);
975 STP_DBG_LOUD_FUNC("logsys EMPTY!\n");
978 remaining = (stp_dbg->logsys->size == 0)?(0):(1);
980 spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags);
985 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){
990 STP_DBG_ERR_FUNC("function invalid\n");
993 do_gettimeofday(&now);
994 hdr->dbg_type = dbg_type;
997 hdr->sec = now.tv_sec;
998 hdr->usec = now.tv_usec;
1001 hdr->dmy = 0xffffffff;
1010 MTKSTP_DBG_T*stp_dbg,
1011 struct stp_dbg_pkt_hdr *hdr,
1012 const unsigned char *body
1015 //fix the frame size large issues.
1016 static struct stp_dbg_pkt stp_pkt;
1017 uint32_t hdr_sz = sizeof(struct stp_dbg_pkt_hdr);
1018 uint32_t body_sz = 0;
1020 osal_bug_on(!stp_dbg);
1022 if(hdr->dbg_type == STP_DBG_PKT){
1023 body_sz = (hdr->len <= STP_PKT_SZ)?(hdr->len):(STP_PKT_SZ);
1025 body_sz = (hdr->len <= STP_DMP_SZ)?(hdr->len):(STP_DMP_SZ);
1028 hdr->no = stp_dbg->pkt_trace_no++;
1029 memcpy((uint8_t *)&stp_pkt.hdr, (uint8_t*)hdr, hdr_sz);
1031 memcpy((uint8_t *)&stp_pkt.raw[0], body, body_sz);
1033 _stp_dbg_dmp_in(stp_dbg, (char *) &stp_pkt, hdr_sz + body_sz);
1034 //Only FW DMP MSG should inform BTM-CORE to dump packet to native process
1035 if(hdr->dbg_type == STP_DBG_FW_DMP)
1037 stp_gdb_notify_btm_dmp_wq(stp_dbg);
1043 int stp_dbg_log_pkt(MTKSTP_DBG_T *stp_dbg, int dbg_type,
1044 int type, int ack_no, int seq_no, int crc, int dir, int len, const unsigned char *body) {
1046 struct stp_dbg_pkt_hdr hdr;
1048 if (stp_dbg->is_enable == 0) {
1049 /*dbg is disable,and not to log*/
1052 stp_dbg_fill_hdr(&hdr,
1061 stp_dbg_add_pkt(stp_dbg, &hdr, body);
1067 int stp_dbg_enable(MTKSTP_DBG_T *stp_dbg){
1068 return _stp_dbg_enable(stp_dbg);
1071 int stp_dbg_disable(MTKSTP_DBG_T *stp_dbg){
1072 return _stp_dbg_disable(stp_dbg);
1075 static void stp_dbg_nl_init(void)
1077 if(genl_register_family(&stp_dbg_gnl_family) != 0)
1079 STP_DBG_ERR_FUNC("%s(): GE_NELINK family registration fail\n", __func__);
1083 if(genl_register_ops(&stp_dbg_gnl_family, &stp_dbg_gnl_ops_bind) != 0)
1085 STP_DBG_ERR_FUNC("%s(): BIND operation registration fail\n", __func__);
1088 if(genl_register_ops(&stp_dbg_gnl_family, &stp_dbg_gnl_ops_reset) != 0)
1090 STP_DBG_ERR_FUNC("%s(): RESET operation registration fail\n", __func__);
1097 static void stp_dbg_nl_deinit(void)
1099 genl_unregister_family(&stp_dbg_gnl_family);
1103 static int stp_dbg_nl_bind(
1104 struct sk_buff *skb,
1105 struct genl_info *info
1116 STP_DBG_INFO_FUNC("%s():->\n", __func__);
1118 na = info->attrs[STP_DBG_ATTR_MSG];
1122 mydata = (char *)nla_data(na);
1125 if(num_bind_process < MAX_BIND_PROCESS)
1127 bind_pid[num_bind_process] = info->snd_pid;
1129 STP_DBG_INFO_FUNC("%s():-> pid = %d\n", __func__, info->snd_pid);
1133 STP_DBG_ERR_FUNC("%s(): exceeding binding limit %d\n", __func__, MAX_BIND_PROCESS);
1140 static int stp_dbg_nl_reset(
1141 struct sk_buff *skb,
1142 struct genl_info *info
1145 STP_DBG_ERR_FUNC("%s(): should not be invoked\n", __func__);
1156 struct sk_buff *skb = NULL;
1157 void *msg_head = NULL;
1161 if(num_bind_process == 0)
1163 /* no listening process */
1164 STP_DBG_ERR_FUNC("%s(): the process is not invoked\n", __func__);
1168 for(i = 0 ; i < num_bind_process ; i++)
1170 skb = genlmsg_new(2048, GFP_KERNEL);
1174 msg_head = genlmsg_put(skb, 0, stp_dbg_seqnum++, &stp_dbg_gnl_family, 0, cmd);
1175 if(msg_head == NULL)
1178 STP_DBG_ERR_FUNC("%s(): genlmsg_put fail...\n", __func__);
1182 rc = nla_put_string(skb, STP_DBG_ATTR_MSG, aucMsg);
1186 STP_DBG_ERR_FUNC("%s(): nla_put_string fail...\n", __func__);
1190 /* finalize the message */
1191 genlmsg_end(skb, msg_head);
1193 /* sending message */
1194 rc = genlmsg_unicast(&init_net, skb, bind_pid[i]);
1197 STP_DBG_ERR_FUNC("%s(): genlmsg_unicast fail...\n", __func__);
1203 STP_DBG_ERR_FUNC("%s(): genlmsg_new fail...\n", __func__);
1212 INT32 stp_dbg_aee_send(unsigned char *aucMsg, INT32 len, INT32 cmd)
1216 // buffered to compressor
1217 ret = wcn_core_dump_in(g_core_dump, aucMsg, len);
1219 wcn_core_dump_flush(0);
1226 MTKSTP_DBG_T *stp_dbg_init(void *btm_half){
1228 MTKSTP_DBG_T *stp_dbg= NULL;
1229 STP_DBG_INFO_FUNC("stp-dbg init\n");
1231 stp_dbg = kzalloc(sizeof(MTKSTP_DBG_T), GFP_KERNEL);
1232 if(IS_ERR(stp_dbg)){
1233 STP_DBG_ERR_FUNC("-ENOMEM\n");
1237 stp_dbg->logsys = vmalloc(sizeof(MTKSTP_LOG_SYS_T));
1238 if(IS_ERR(stp_dbg->logsys)){
1239 STP_DBG_ERR_FUNC("-ENOMEM stp_gdb->logsys\n");
1242 memset(stp_dbg->logsys, 0, sizeof(MTKSTP_LOG_SYS_T));
1243 spin_lock_init(&(stp_dbg->logsys->lock));
1244 stp_dbg->pkt_trace_no=0;
1245 stp_dbg->is_enable=0;
1246 g_stp_dbg = stp_dbg;
1248 if(btm_half != NULL){
1249 stp_dbg->btm = btm_half;
1251 stp_dbg->btm = NULL;
1257 g_core_dump = wcn_core_dump_init(STP_CORE_DUMP_TIMEOUT);
1269 int stp_dbg_deinit(MTKSTP_DBG_T *stp_dbg){
1271 STP_DBG_INFO_FUNC("stp-dbg deinit\n");
1273 wcn_core_dump_deinit(g_core_dump);
1275 //unbind with netlink
1276 stp_dbg_nl_deinit();
1278 if(stp_dbg->logsys){
1279 vfree(stp_dbg->logsys);