MT6620: add the new driver JB2 V1.0
[firefly-linux-kernel-4.4.55.git] / drivers / mtk_wcn_combo / common / linux / stp_dbg.c
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>
8 #include <linux/err.h>
9 #include <linux/workqueue.h>
10 #include <asm/atomic.h>
11
12 #include <net/sock.h>
13 #include <net/netlink.h>
14 #include <linux/skbuff.h>
15 #include <net/genetlink.h>
16
17 #include <linux/zlib.h>
18 #include <linux/uaccess.h>
19 #include <linux/crc32.h>
20
21 #include "stp_dbg.h"
22 //#include "stp_btm.h"
23 #include "btm_core.h"
24
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
31
32 unsigned int gStpDbgDbgLevel = STP_DBG_LOG_INFO;
33 unsigned int gStpDbgLogOut = 0;
34
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__);}
41
42
43 MTKSTP_DBG_T *g_stp_dbg = NULL;
44
45 #define STP_DBG_FAMILY_NAME        "STP_DBG"
46 #define MAX_BIND_PROCESS    (4)
47
48 enum {
49     __STP_DBG_ATTR_INVALID,
50     STP_DBG_ATTR_MSG,
51     __STP_DBG_ATTR_MAX,
52 };
53 #define STP_DBG_ATTR_MAX       (__STP_DBG_ATTR_MAX - 1)
54
55 enum {
56     __STP_DBG_COMMAND_INVALID,
57     STP_DBG_COMMAND_BIND,
58     STP_DBG_COMMAND_RESET,
59     __STP_DBG_COMMAND_MAX,
60 };
61 #define MTK_WIFI_COMMAND_MAX    (__STP_DBG_COMMAND_MAX - 1)
62
63 static struct genl_family stp_dbg_gnl_family = {
64     .id         = GENL_ID_GENERATE,
65     .hdrsize    = 0,
66     .name       = STP_DBG_FAMILY_NAME,
67     .version    = 1,
68     .maxattr    = STP_DBG_ATTR_MAX,
69 };
70
71 static void stp_dbg_nl_init(void);
72 static void stp_dbg_nl_deinit(void);
73 static int stp_dbg_nl_bind(
74     struct sk_buff *skb,
75     struct genl_info *info
76     );
77 static int stp_dbg_nl_reset(
78     struct sk_buff *skb,
79     struct genl_info *info
80     );
81
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 },
85 };
86
87 /* operation definition */
88 static struct genl_ops stp_dbg_gnl_ops_bind = {
89     .cmd = STP_DBG_COMMAND_BIND,
90     .flags  = 0,
91     .policy = stp_dbg_genl_policy,
92     .doit   = stp_dbg_nl_bind,
93     .dumpit = NULL,
94 };
95
96 static struct genl_ops stp_dbg_gnl_ops_reset = {
97     .cmd = STP_DBG_COMMAND_RESET,
98     .flags  = 0,
99     .policy = stp_dbg_genl_policy,
100     .doit   = stp_dbg_nl_reset,
101     .dumpit = NULL,
102 };
103
104 static unsigned int stp_dbg_seqnum = 0;
105 static int num_bind_process = 0;
106 static pid_t bind_pid[MAX_BIND_PROCESS];
107
108 static P_WCN_CORE_DUMP_T g_core_dump = NULL;
109
110 /* core_dump_timeout_handler - handler of coredump timeout
111  * @ data - core dump object's pointer
112  * 
113  * No return value
114  */
115 static void core_dump_timeout_handler(ULONG data)
116 {
117     P_WCN_CORE_DUMP_T dmp = (P_WCN_CORE_DUMP_T)data;
118     
119     STP_DBG_INFO_FUNC(" start\n");
120     
121     stp_btm_notify_coredump_timeout_wq(g_stp_dbg->btm);
122     
123     STP_DBG_INFO_FUNC(" end\n");
124
125     if (dmp) {
126         dmp->sm = CORE_DUMP_TIMEOUT;
127     }
128 }
129
130
131 /* wcn_core_dump_init - create core dump sys
132  * @ timeout - core dump time out value
133  * 
134  * Return object pointer if success, else NULL
135  */
136 P_WCN_CORE_DUMP_T wcn_core_dump_init(UINT32 timeout)
137 {
138     #define KBYTES (1024*sizeof(char))
139     #define L1_BUF_SIZE (32*KBYTES) 
140     #define L2_BUF_SIZE (512*KBYTES)
141     
142     P_WCN_CORE_DUMP_T core_dmp = NULL;
143     
144     core_dmp = (P_WCN_CORE_DUMP_T)osal_malloc(sizeof(WCN_CORE_DUMP_T));
145     if (!core_dmp) {
146         STP_DBG_ERR_FUNC("alloc mem failed!\n");
147         goto fail;
148     }
149
150     osal_memset(core_dmp, 0, sizeof(WCN_CORE_DUMP_T));
151     
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");
155         goto fail;
156     }
157     wcn_compressor_reset(core_dmp->compressor, 1, GZIP);
158     
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;
163
164     osal_sleepable_lock_init(&core_dmp->dmp_lock);
165     
166     core_dmp->sm = CORE_DUMP_INIT;
167     STP_DBG_INFO_FUNC("create coredump object OK!\n");
168     
169     return core_dmp;
170     
171 fail:
172     if (core_dmp && core_dmp->compressor) {
173         wcn_compressor_deinit(core_dmp->compressor);
174         core_dmp->compressor = NULL;
175     }
176
177     if (core_dmp) {
178         osal_free(core_dmp);
179     }
180
181     osal_sleepable_lock_deinit(&core_dmp->dmp_lock);
182     
183     return NULL;
184 }
185
186
187 /* wcn_core_dump_deinit - destroy core dump object
188  * @ dmp - pointer of object
189  *
190  * Retunr 0 if success, else error code
191  */
192 INT32 wcn_core_dump_deinit(P_WCN_CORE_DUMP_T dmp)
193 {
194     if (dmp && dmp->compressor) {
195         wcn_compressor_deinit(dmp->compressor);
196         dmp->compressor = NULL;
197     }
198
199     if (dmp) {
200         osal_sleepable_lock_deinit(&dmp->dmp_lock);
201         osal_timer_stop(&dmp->dmp_timer);
202         osal_free(dmp);
203     }
204
205     return 0;
206 }
207
208
209 static INT32 wcn_core_dump_check_end(PUINT8 buf, INT32 len)
210 {
211     if (strnstr(buf, "coredump end", len)) {
212         return 1;
213     } else {
214         return 0;
215     } 
216 }
217
218
219 /* wcn_core_dump_in - add a packet to compressor buffer
220  * @ dmp - pointer of object
221  * @ buf - input buffer
222  * @ len - data length
223  * 
224  * Retunr 0 if success; return 1 if find end string; else error code
225  */
226 INT32 wcn_core_dump_in(P_WCN_CORE_DUMP_T dmp, PUINT8 buf, INT32 len)
227 {
228     INT32 ret = 0;
229     INT32 tmp;
230     #define INFO_HEAD "MT6628 FW CORE, "
231     
232     if ((!dmp) || (!buf)) {
233         STP_DBG_ERR_FUNC("invalid pointer!\n");
234         return -1;
235     }
236
237     ret = osal_lock_sleepable_lock(&dmp->dmp_lock);
238     if (ret) {
239         STP_DBG_ERR_FUNC("--->lock dmp->dmp_lock failed, ret=%d\n", ret);
240         return ret;
241     }
242     
243     switch (dmp->sm) {
244         case CORE_DUMP_INIT:
245             wcn_compressor_reset(dmp->compressor, 1, GZIP);
246             osal_timer_start(&dmp->dmp_timer, STP_CORE_DUMP_TIMEOUT);
247             
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';
254             
255             // show coredump start info on UI
256             //osal_dbg_assert_aee("MT662x f/w coredump start", "MT662x firmware coredump start");
257             #if WMT_PLAT_ALPS
258             aee_kernel_dal_show("MT662x coredump start, please wait up to 5 minutes.\n");
259             #endif
260             // parsing data, and check end srting
261             ret = wcn_core_dump_check_end(buf, len);
262             if (ret == 1) {
263                 STP_DBG_INFO_FUNC("core dump end!\n");
264                 dmp->sm = CORE_DUMP_DONE;
265                 wcn_compressor_in(dmp->compressor, buf, len, 1);
266             } else {
267                 dmp->sm = CORE_DUMP_DOING;
268                 wcn_compressor_in(dmp->compressor, buf, len, 0);
269             }
270             break;
271             
272         case CORE_DUMP_DOING:
273             // parsing data, and check end srting
274             ret = wcn_core_dump_check_end(buf, len);
275             if (ret == 1) {
276                 STP_DBG_INFO_FUNC("core dump end!\n");
277                 dmp->sm = CORE_DUMP_DONE;
278                 wcn_compressor_in(dmp->compressor, buf, len, 1);
279             } else {
280                 dmp->sm = CORE_DUMP_DOING;
281                 wcn_compressor_in(dmp->compressor, buf, len, 0);
282             }
283             break;
284             
285         case CORE_DUMP_DONE:
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;
290             break;
291             
292         case CORE_DUMP_TIMEOUT:
293             break;
294         default:
295             break;
296     }
297
298     osal_unlock_sleepable_lock(&dmp->dmp_lock);
299     
300     return ret;
301 }
302
303
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
308  * 
309  * Retunr 0 if success;  else error code
310  */
311 INT32 wcn_core_dump_out(P_WCN_CORE_DUMP_T dmp, PUINT8 *pbuf, PINT32 plen)
312 {
313     INT32 ret = 0;
314     
315     if ((!dmp) || (!pbuf) || (!plen)) {
316         STP_DBG_ERR_FUNC("invalid pointer!\n");
317         return -1;
318     }
319
320     ret = osal_lock_sleepable_lock(&dmp->dmp_lock);
321     if (ret) {
322         STP_DBG_ERR_FUNC("--->lock dmp->dmp_lock failed, ret=%d\n", ret);
323         return ret;
324     }
325     
326     ret = wcn_compressor_out(dmp->compressor, pbuf, plen);
327
328     osal_unlock_sleepable_lock(&dmp->dmp_lock);
329     
330     return ret;
331 }
332
333
334 /* wcn_core_dump_reset - reset core dump sys
335  * @ dmp - pointer of object
336  * @ timeout - core dump time out value
337  *
338  * Retunr 0 if success, else error code
339  */
340 INT32 wcn_core_dump_reset(P_WCN_CORE_DUMP_T dmp, UINT32 timeout)
341 {
342     if (!dmp) {
343         STP_DBG_ERR_FUNC("invalid pointer!\n");
344         return -1;
345     }
346
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);
352
353     return 0;
354 }
355
356
357 /* wcn_core_dump_flush - Fulsh dump data and reset core dump sys
358  *
359  * Retunr 0 if success, else error code
360  */
361 INT32 wcn_core_dump_flush(INT32 rst)
362 {
363     PUINT8 pbuf = NULL;
364     INT32 len = 0;
365
366     if (!g_core_dump) {
367         STP_DBG_ERR_FUNC("invalid pointer!\n");
368         return -1;
369     }
370
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);
373             
374     // show coredump end info on UI
375     //osal_dbg_assert_aee("MT662x f/w coredump end", "MT662x firmware coredump ends");
376     #if WMT_PLAT_ALPS
377     aee_kernel_dal_show("MT662x coredump end\n");
378         
379     // call AEE driver API
380     aed_combo_exception(NULL, 0, (const int*)pbuf, len, (const char*)g_core_dump->info);
381     #endif
382     // reset
383     wcn_core_dump_reset(g_core_dump, STP_CORE_DUMP_TIMEOUT);
384     
385     return 0;
386 }
387
388
389 static INT32 wcn_gzip_compressor(void *worker, UINT8 *in_buf, INT32 in_sz, UINT8 *out_buf, INT32 *out_sz, INT32 finish)
390 {
391     INT32 ret = 0;
392     z_stream *stream = NULL;
393     INT32 tmp = *out_sz;
394
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);
397
398     stream = (z_stream*)worker;
399     if (!stream) {
400         STP_DBG_ERR_FUNC("invalid workspace!\n");
401         return -1;
402     }
403     
404     if (in_sz > 0) {
405         #if 0
406         ret = zlib_deflateReset(stream);
407         if (ret != Z_OK) {
408             STP_DBG_ERR_FUNC("reset failed!\n");
409             return -2;
410         }
411         #endif
412
413         stream->next_in = in_buf;
414         stream->avail_in = in_sz;
415         stream->next_out = out_buf;
416         stream->avail_out = tmp;
417
418                 zlib_deflate(stream, Z_FULL_FLUSH);
419                 
420         if (finish) {
421         while (1) {
422                         int val = zlib_deflate(stream, Z_FINISH);
423                         if (val == Z_OK) {
424                                 continue;
425              } else if (val == Z_STREAM_END) {
426                                 break;
427              } else {
428                             STP_DBG_ERR_FUNC("finish operation failed %d\n", val);
429                             return -3;
430             }
431                 }                       
432         }
433
434                 *out_sz = tmp - stream->avail_out;
435         }
436
437     STP_DBG_INFO_FUNC("out buf 0x%08x, out sz %d\n", (unsigned int)out_buf, *out_sz);
438     
439         return ret;
440 }
441
442
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
447  *
448  * Retunr object's pointer if success, else NULL
449  */
450 P_WCN_COMPRESSOR_T wcn_compressor_init(PUINT8 name, INT32 L1_buf_sz, INT32 L2_buf_sz)
451 {
452     z_stream *pstream = NULL;
453     P_WCN_COMPRESSOR_T compress = NULL;
454     
455     compress = (P_WCN_COMPRESSOR_T)osal_malloc(sizeof(WCN_COMPRESSOR_T));
456     if (!compress) {
457         STP_DBG_ERR_FUNC("alloc compressor failed!\n");
458         goto fail;
459     }
460     
461     osal_memset(compress, 0, sizeof(WCN_COMPRESSOR_T));
462     osal_memcpy(compress->name, name, STP_OJB_NAME_SZ);
463
464     compress->f_compress_en = 0;
465     compress->compress_type = GZIP;
466     
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");
471             goto fail;
472         }
473         pstream = (z_stream*)compress->worker;
474             
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");
478             goto fail;
479         }
480         zlib_deflateInit2(pstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS,
481                           DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
482     }
483     
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;
491
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);
495         goto fail;
496     }
497
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);
501         goto fail;
502     }
503
504     STP_DBG_INFO_FUNC("create compressor OK! L1 %d bytes, L2 %d bytes\n", L1_buf_sz, L2_buf_sz);
505     return compress;
506
507 fail:
508     if (compress) {
509         if (compress->L2_buf) {
510             osal_free(compress->L2_buf);
511             compress->L2_buf = NULL;
512         }
513
514         if (compress->L1_buf) {
515             osal_free(compress->L1_buf);
516             compress->L1_buf = NULL;
517         }
518
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);
524             }
525             osal_free(compress->worker);
526             compress->worker = NULL;
527         }
528             
529         if (compress->worker) {
530             osal_free(compress->worker);
531             compress->worker = NULL;
532         }
533         
534         osal_free(compress);
535         compress = NULL;
536     }
537
538     STP_DBG_ERR_FUNC("init failed!\n");
539      
540     return NULL;
541 }
542
543
544 /* wcn_compressor_deinit - distroy a compressor
545  * @ cprs - compressor's pointer
546  *
547  * Retunr 0 if success, else NULL
548  */
549 INT32 wcn_compressor_deinit(P_WCN_COMPRESSOR_T cprs)
550 {
551     z_stream *pstream = NULL;
552     
553     if (cprs) {
554         if (cprs->L2_buf) {
555             osal_free(cprs->L2_buf);
556             cprs->L2_buf = NULL;
557         }
558         
559         if (cprs->L1_buf) {
560             osal_free(cprs->L1_buf);
561             cprs->L1_buf = NULL;
562         }
563
564         if (cprs->worker) {
565             pstream = (z_stream*)cprs->worker;
566             if ((cprs->compress_type == GZIP) && pstream->workspace) {
567                 zlib_deflateEnd(pstream);
568                 osal_free(pstream->workspace);
569             }
570             osal_free(cprs->worker);
571             cprs->worker = NULL;
572         }
573         
574         cprs->handler = NULL;
575
576         osal_free(cprs);
577     }
578
579     STP_DBG_INFO_FUNC("destroy OK\n");
580     
581     return 0;
582 }
583
584
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
590  *
591  * Retunr 0 if success, else NULL
592  */
593 INT32 wcn_compressor_in(P_WCN_COMPRESSOR_T cprs, PUINT8 buf, INT32 len, INT32 finish)
594 {
595     INT32 tmp_len = 0;
596     INT32 ret = 0;
597     
598     if (!cprs) {
599         STP_DBG_ERR_FUNC("invalid para!\n");
600         return -1;
601     }
602     
603     cprs->uncomp_size += len;
604
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");
608         
609         if (cprs->f_compress_en && cprs->handler) {
610             // need compress
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);
614             if (!ret) {
615                 cprs->crc32 = (crc32(cprs->crc32, cprs->L1_buf, cprs->L1_pos));
616                 cprs->L2_pos += tmp_len;
617
618                 if (finish) {
619                         /* Add 8 byte suffix
620                            ===
621                            32 bits UNCOMPRESS SIZE
622                            32 bits CRC
623                         */
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;
626                         cprs->L2_pos += 8;
627                 }
628                 STP_DBG_INFO_FUNC("compress OK!\n");
629             } else {
630                 STP_DBG_ERR_FUNC("compress error!\n");
631             }
632         } else {
633             // no need compress
634             // Flush L1 buffer to L2 buffer
635             STP_DBG_INFO_FUNC("No need do compress, Put to L2 buf\n");
636             
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;
641         }
642             
643         // reset L1 buf pos
644         cprs->L1_pos = 0;
645
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);
649         } else {
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);
652             cprs->L1_pos += len;
653         }
654     } else {
655         // put to L1 buffer
656         STP_DBG_INFO_FUNC("Put %d bytes to L1 buf\n", len);
657         
658         osal_memcpy(&cprs->L1_buf[cprs->L1_pos], buf, len);
659         cprs->L1_pos += len;
660     }
661
662     return ret;
663 }
664
665
666 /* wcn_compressor_out - get the result data from L2 buffer
667  * @ cprs - compressor's pointer
668  * @ pbuf - point to L2 buffer
669  * @ plen - out len 
670  *
671  * Retunr 0 if success, else NULL
672  */
673 INT32 wcn_compressor_out(P_WCN_COMPRESSOR_T cprs, PUINT8 *pbuf, PINT32 plen)
674 {
675     INT32 ret = 0;
676     INT32 tmp_len = 0;
677
678     if ((!cprs) || (!pbuf) || (!plen)) {
679         STP_DBG_ERR_FUNC("invalid para!\n");
680         return -1;
681     }
682
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;
686         
687         if (cprs->f_compress_en && cprs->handler) {
688             // need compress
689             ret = cprs->handler(cprs->worker, cprs->L1_buf, cprs->L1_pos, &cprs->L2_buf[cprs->L2_pos], &tmp_len, 1);
690
691             if (!ret) {
692                 cprs->crc32 = (crc32(cprs->crc32, cprs->L1_buf, cprs->L1_pos));
693                 cprs->L2_pos += tmp_len;
694
695                 /* Add 8 byte suffix
696                    ===
697                    32 bits UNCOMPRESS SIZE
698                    32 bits CRC
699                 */
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;
702                 cprs->L2_pos += 8;
703
704                 STP_DBG_INFO_FUNC("compress OK!\n");
705             } else {
706                 STP_DBG_ERR_FUNC("compress error!\n");
707             }
708         } else {
709             // no need compress
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;
713         }
714         
715         cprs->L1_pos = 0;
716     }
717
718
719     *pbuf = cprs->L2_buf;
720     *plen = cprs->L2_pos;
721
722     STP_DBG_INFO_FUNC("0x%08x, len %d\n", (unsigned int)*pbuf, *plen);
723     
724 #if 1
725     ret = zlib_deflateReset((z_stream*)cprs->worker);
726     if (ret != Z_OK) {
727         STP_DBG_ERR_FUNC("reset failed!\n");
728         return -2;
729     }
730 #endif
731
732     return 0;
733 }
734
735
736 /* wcn_compressor_reset - reset compressor
737  * @ cprs - compressor's pointer
738  * @ enable - enable/disable compress
739  * @ type - compress algorithm 
740  *
741  * Retunr 0 if success, else NULL
742  */
743 INT32 wcn_compressor_reset(P_WCN_COMPRESSOR_T cprs, UINT8 enable, WCN_COMPRESS_ALG_T type)
744 {
745     if (!cprs) {
746         STP_DBG_ERR_FUNC("invalid para!\n");
747         return -1;
748     }
749
750     cprs->f_compress_en = enable;
751     //cprs->f_compress_en = 0; // disable compress for test
752     cprs->compress_type = type;
753     cprs->L1_pos = 0;
754     cprs->L2_pos = 0;
755     cprs->uncomp_size = 0;
756     cprs->crc32 = 0xffffffffUL;
757
758     STP_DBG_INFO_FUNC("OK! compress algorithm %d\n", type);
759     
760     return 0;
761 }
762
763
764 static void stp_dbg_dump_data(unsigned char *pBuf, char * title,  int len)
765 {
766     int k = 0;
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]);
772     }
773     printk("--end\n");
774 }
775
776
777 static int _stp_dbg_enable(MTKSTP_DBG_T *stp_dbg){
778
779     unsigned long flags;
780
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);
785
786     return 0;
787 }
788
789 static int _stp_dbg_disable(MTKSTP_DBG_T *stp_dbg){
790
791     unsigned long flags;
792
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);
798
799     return 0;
800 }
801
802 static int _stp_dbg_dmp_in(MTKSTP_DBG_T *stp_dbg, char *buf, int len){
803
804     unsigned long flags;
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
808         internalFlag = 1;
809     //#endif
810     spin_lock_irqsave(&(stp_dbg->logsys->lock), flags);
811
812     if(internalFlag){
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)));
819
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;
822         
823         if (0 != gStpDbgLogOut)
824         {
825             STP_DBG_HDR_T *pHdr = NULL;
826             char* pBuf = NULL;
827             unsigned int len =0;
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", \
832                 pHdr->sec,
833                 pHdr->usec,
834                 pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx",
835                 gStpDbgType[pHdr->type],
836                 pHdr->no,
837                 pHdr->len,
838                 pHdr->seq,
839                 pHdr->ack
840
841             );
842             if (0 < len){
843                 stp_dbg_dump_data(pBuf, pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx", len);
844             }
845             
846         }
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);
849     } else {
850         STP_DBG_WARN_FUNC("logsys FULL!\n");
851     }
852
853     spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags);
854
855     return 0;
856 }
857
858 int stp_gdb_notify_btm_dmp_wq(MTKSTP_DBG_T *stp_dbg){
859     int retval = 0;    
860 //#ifndef CONFIG_LOG_STP_INTERNAL
861
862     if(stp_dbg->btm != NULL){
863         retval += stp_btm_notify_wmt_dmp_wq((MTKSTP_BTM_T *)stp_dbg->btm);
864     }
865     
866 //#endif
867
868     return retval;
869 }
870
871 int stp_dbg_log_ctrl (unsigned int on)
872 {
873     if (on != 0)    
874     {
875         gStpDbgLogOut = 1;
876         printk ("STP-DBG: enable pkt log dump out.\n");
877     }
878     else
879     {
880         gStpDbgLogOut = 0;
881         printk ("STP-DBG: disable pkt log dump out.\n");
882     }
883     return 0;
884 }
885
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);
888 }
889
890
891 int stp_dbg_dmp_printk(MTKSTP_DBG_T *stp_dbg)
892 {
893     #define MAX_DMP_NUM 80
894     unsigned long flags;
895     char *pBuf = NULL;
896     int len = 0;
897     STP_DBG_HDR_T *pHdr = NULL;
898     UINT32 dumpSize = 0;
899     UINT32 inIndex = 0;
900     UINT32 outIndex = 0;
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)
906     {
907         outIndex = inIndex;
908     }
909     else
910     {
911         outIndex = ((inIndex + STP_DBG_LOG_ENTRY_NUM) - dumpSize) % STP_DBG_LOG_ENTRY_NUM;
912     }
913     
914     if (dumpSize > MAX_DMP_NUM)
915     {
916         
917         outIndex += (dumpSize - MAX_DMP_NUM);
918         outIndex %= STP_DBG_LOG_ENTRY_NUM;
919         dumpSize = MAX_DMP_NUM;
920         
921     }
922     STP_DBG_INFO_FUNC("loged packet size = %d, in(%d), out(%d)\n", dumpSize, inIndex, outIndex);
923     while(dumpSize > 0){
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", \
929             pHdr->sec,
930             pHdr->usec,
931             pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx",
932             gStpDbgType[pHdr->type],
933             pHdr->no,
934             pHdr->len,
935             pHdr->seq,
936             pHdr->ack
937         );
938         
939         
940         if (0 < len){
941             stp_dbg_dump_data(pBuf, pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx", len);
942         }
943         outIndex = (outIndex >= (STP_DBG_LOG_ENTRY_NUM - 1))?(0):(outIndex + 1);
944         dumpSize--;
945           
946     } 
947
948       
949     spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags);
950
951     return 0;
952 }
953
954 int stp_dbg_dmp_out_ex (char *buf, int *len){
955     return stp_dbg_dmp_out(g_stp_dbg, buf, len);
956 }
957
958 int stp_dbg_dmp_out(MTKSTP_DBG_T *stp_dbg, char *buf, int *len){
959
960     unsigned long flags;
961     int remaining = 0;
962     *len = 0;
963     spin_lock_irqsave(&(stp_dbg->logsys->lock), flags);
964
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);
968
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--;
972
973         STP_DBG_DBG_FUNC("logsys size = %d, out = %d\n", stp_dbg->logsys->size, stp_dbg->logsys->out);
974     } else {
975         STP_DBG_LOUD_FUNC("logsys EMPTY!\n");
976     }
977
978     remaining = (stp_dbg->logsys->size == 0)?(0):(1);
979
980     spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags);
981
982     return remaining;
983 }
984
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){
986
987     struct timeval now;
988
989     if(!hdr){
990         STP_DBG_ERR_FUNC("function invalid\n");
991         return -EINVAL;
992     } else {
993         do_gettimeofday(&now);
994         hdr->dbg_type = dbg_type;
995         hdr->ack = ack;
996         hdr->seq = seq;
997         hdr->sec = now.tv_sec;
998         hdr->usec = now.tv_usec;
999         hdr->crc  = crc;
1000         hdr->dir  = dir;//rx
1001         hdr->dmy  = 0xffffffff;
1002         hdr->len  =  len;
1003         hdr->type = type;
1004         return 0;
1005     }
1006 }
1007
1008 static int
1009 stp_dbg_add_pkt (
1010     MTKSTP_DBG_T*stp_dbg,
1011     struct stp_dbg_pkt_hdr *hdr,
1012     const unsigned char *body
1013     )
1014 {
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;
1019
1020     osal_bug_on(!stp_dbg);
1021
1022     if(hdr->dbg_type == STP_DBG_PKT){
1023         body_sz = (hdr->len <= STP_PKT_SZ)?(hdr->len):(STP_PKT_SZ);
1024     }else{
1025         body_sz = (hdr->len <= STP_DMP_SZ)?(hdr->len):(STP_DMP_SZ);
1026     }
1027
1028     hdr->no = stp_dbg->pkt_trace_no++;
1029     memcpy((uint8_t *)&stp_pkt.hdr, (uint8_t*)hdr, hdr_sz);
1030     if(body != NULL){
1031         memcpy((uint8_t *)&stp_pkt.raw[0], body, body_sz);
1032     }
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)
1036     {
1037         stp_gdb_notify_btm_dmp_wq(stp_dbg);
1038     }
1039
1040     return 0;
1041 }
1042
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) {
1045
1046     struct stp_dbg_pkt_hdr hdr;
1047
1048     if (stp_dbg->is_enable == 0) {
1049         /*dbg is disable,and not to log*/
1050     }
1051     else {
1052         stp_dbg_fill_hdr(&hdr,
1053             (int) type,
1054             (int) ack_no,
1055             (int) seq_no,
1056             (int) crc,
1057             (int) dir,
1058             (int) len,
1059             (int) dbg_type);
1060
1061         stp_dbg_add_pkt(stp_dbg, &hdr, body);
1062     }
1063
1064     return 0;
1065 }
1066
1067 int stp_dbg_enable(MTKSTP_DBG_T *stp_dbg){
1068     return _stp_dbg_enable(stp_dbg);
1069 }
1070
1071 int stp_dbg_disable(MTKSTP_DBG_T *stp_dbg){
1072     return _stp_dbg_disable(stp_dbg);
1073 }
1074
1075 static void stp_dbg_nl_init(void)
1076 {
1077     if(genl_register_family(&stp_dbg_gnl_family) != 0) 
1078     {
1079        STP_DBG_ERR_FUNC("%s(): GE_NELINK family registration fail\n", __func__);
1080     }
1081     else 
1082     {
1083         if(genl_register_ops(&stp_dbg_gnl_family, &stp_dbg_gnl_ops_bind) != 0) 
1084         {
1085            STP_DBG_ERR_FUNC("%s(): BIND operation registration fail\n", __func__);
1086         }
1087
1088         if(genl_register_ops(&stp_dbg_gnl_family, &stp_dbg_gnl_ops_reset) != 0) 
1089         {
1090            STP_DBG_ERR_FUNC("%s(): RESET operation registration fail\n", __func__);
1091         }
1092     }
1093
1094     return;
1095 }
1096
1097 static void stp_dbg_nl_deinit(void)
1098 {
1099     genl_unregister_family(&stp_dbg_gnl_family);
1100     return;
1101 }
1102
1103 static int stp_dbg_nl_bind(
1104     struct sk_buff *skb,
1105     struct genl_info *info
1106     )
1107 {
1108     struct nlattr *na;
1109     char * mydata;
1110
1111     if (info == NULL) 
1112     {
1113         goto out;
1114     }
1115
1116     STP_DBG_INFO_FUNC("%s():->\n", __func__);
1117     
1118     na = info->attrs[STP_DBG_ATTR_MSG];
1119     
1120     if (na) 
1121     {
1122         mydata = (char *)nla_data(na);
1123     }
1124
1125     if(num_bind_process < MAX_BIND_PROCESS) 
1126     {
1127         bind_pid[num_bind_process] = info->snd_pid;
1128         num_bind_process++;
1129         STP_DBG_INFO_FUNC("%s():-> pid  = %d\n", __func__, info->snd_pid);
1130     }
1131     else 
1132     {
1133         STP_DBG_ERR_FUNC("%s(): exceeding binding limit %d\n", __func__, MAX_BIND_PROCESS);
1134     }
1135
1136 out:
1137     return 0;
1138 }
1139
1140 static int stp_dbg_nl_reset(
1141     struct sk_buff *skb,
1142     struct genl_info *info
1143     )
1144 {
1145     STP_DBG_ERR_FUNC("%s(): should not be invoked\n", __func__);
1146
1147     return 0;
1148 }
1149
1150 char
1151 stp_dbg_nl_send(
1152     char *  aucMsg,
1153     unsigned char      cmd
1154     )
1155 {
1156     struct sk_buff *skb = NULL;
1157     void *msg_head = NULL;
1158     int rc = -1;
1159     int i;
1160
1161     if(num_bind_process == 0) 
1162     {
1163         /* no listening process */
1164         STP_DBG_ERR_FUNC("%s(): the process is not invoked\n", __func__);
1165         return 0;
1166     }
1167
1168     for(i = 0 ; i < num_bind_process ; i++) 
1169     {
1170         skb = genlmsg_new(2048, GFP_KERNEL);
1171
1172         if(skb) 
1173         {
1174             msg_head = genlmsg_put(skb, 0, stp_dbg_seqnum++, &stp_dbg_gnl_family, 0, cmd);
1175             if(msg_head == NULL) 
1176             {
1177                 nlmsg_free(skb);
1178                 STP_DBG_ERR_FUNC("%s(): genlmsg_put fail...\n", __func__);
1179                 return -1;
1180             }
1181
1182             rc = nla_put_string(skb, STP_DBG_ATTR_MSG, aucMsg);
1183             if(rc != 0) 
1184             {            
1185                 nlmsg_free(skb);
1186                 STP_DBG_ERR_FUNC("%s(): nla_put_string fail...\n", __func__);
1187                 return -1;
1188             }
1189         
1190             /* finalize the message */
1191             genlmsg_end(skb, msg_head);
1192         
1193             /* sending message */
1194             rc = genlmsg_unicast(&init_net, skb, bind_pid[i]);
1195             if(rc != 0) 
1196             {
1197                 STP_DBG_ERR_FUNC("%s(): genlmsg_unicast fail...\n", __func__);
1198                 return -1;
1199             }
1200         }
1201         else 
1202         {
1203             STP_DBG_ERR_FUNC("%s(): genlmsg_new fail...\n", __func__);
1204             return -1;
1205         }
1206     }
1207
1208     return 0;
1209 }
1210
1211
1212 INT32 stp_dbg_aee_send(unsigned char *aucMsg, INT32 len, INT32 cmd)
1213 {
1214     INT32 ret = 0;
1215
1216     // buffered to compressor
1217     ret = wcn_core_dump_in(g_core_dump, aucMsg, len);
1218     if (ret == 1) {
1219         wcn_core_dump_flush(0);
1220     }
1221
1222     return ret;
1223 }
1224
1225
1226 MTKSTP_DBG_T *stp_dbg_init(void *btm_half){
1227
1228     MTKSTP_DBG_T *stp_dbg= NULL;
1229     STP_DBG_INFO_FUNC("stp-dbg init\n");
1230
1231     stp_dbg = kzalloc(sizeof(MTKSTP_DBG_T), GFP_KERNEL);
1232     if(IS_ERR(stp_dbg)){
1233         STP_DBG_ERR_FUNC("-ENOMEM\n");
1234         goto ERR_EXIT1;
1235     }
1236
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");
1240         goto ERR_EXIT2;
1241     }
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;
1247
1248     if(btm_half != NULL){
1249        stp_dbg->btm = btm_half;
1250     } else {
1251        stp_dbg->btm = NULL;
1252     }
1253
1254     //bind to netlink
1255     stp_dbg_nl_init();
1256     
1257     g_core_dump = wcn_core_dump_init(STP_CORE_DUMP_TIMEOUT);
1258     
1259     return stp_dbg;
1260
1261 ERR_EXIT2:
1262     kfree(stp_dbg);
1263     return NULL;
1264
1265 ERR_EXIT1:
1266     return NULL;
1267 }
1268
1269 int stp_dbg_deinit(MTKSTP_DBG_T *stp_dbg){
1270
1271     STP_DBG_INFO_FUNC("stp-dbg deinit\n");
1272
1273     wcn_core_dump_deinit(g_core_dump);
1274     
1275     //unbind with netlink
1276     stp_dbg_nl_deinit();
1277
1278     if(stp_dbg->logsys){
1279         vfree(stp_dbg->logsys);
1280     }
1281
1282     if(stp_dbg){
1283         kfree(stp_dbg);
1284     }
1285
1286     return 0;
1287 }
1288
1289
1290
1291
1292
1293
1294