wlan: Support for MTRACE.

This fix will move MTRACE funcionality from PE to VOSS

Change-Id: I901f139aa22ccf45ec080cff3ab7506384458251
CRs-Fixed:  592922
diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c
index 0eae64f..626f188 100644
--- a/CORE/HDD/src/wlan_hdd_wext.c
+++ b/CORE/HDD/src/wlan_hdd_wext.c
@@ -113,6 +113,7 @@
 #include "wlan_hdd_dev_pwr.h"
 #include "qc_sap_ioctl.h"
 #include "sme_Api.h"
+#include "vos_trace.h"
 
 #ifdef CONFIG_HAS_EARLYSUSPEND
 extern void hdd_suspend_wlan(struct early_suspend *wlan_suspend);
@@ -125,6 +126,7 @@
 
 #define HDD_FINISH_ULA_TIME_OUT    800
 
+
 extern int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand);
 int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
 
@@ -158,6 +160,7 @@
 #define WE_ENABLE_STRICT_FCC_REG  10
 #define WE_SET_MAX_TX_POWER_2_4   11
 #define WE_SET_MAX_TX_POWER_5_0   12
+#define WE_MTRACE_SELECTIVE_MODULE_LOG_ENABLE_CMD    13
 
 /* Private ioctls and their sub-ioctls */
 #define WLAN_PRIV_SET_NONE_GET_INT    (SIOCIWFIRSTPRIV + 1)
@@ -233,6 +236,8 @@
 #define WE_TDLS_CONFIG_PARAMS   5
 #endif
 
+#define WE_MTRACE_DUMP_CMD    8
+
 #ifdef FEATURE_WLAN_TDLS
 #undef  MAX_VAR_ARGS
 #define MAX_VAR_ARGS         10
@@ -4150,6 +4155,15 @@
            break;
         }
 
+        case WE_MTRACE_SELECTIVE_MODULE_LOG_ENABLE_CMD:
+        {
+           hddLog(LOG1, "%s: SELECTIVE_MODULE_LOG %d arg1",
+                  __func__, set_value);
+           vosTraceEnable(set_value);
+
+           break;
+        }
+
         case WE_ENABLE_STRICT_FCC_REG:
         {
            hdd_context_t *hddCtxt = WLAN_HDD_GET_CTX(pAdapter);
@@ -5081,6 +5095,18 @@
             }
             break;
 
+        case WE_MTRACE_DUMP_CMD:
+            {
+                hddLog(LOG1, "%s: MTRACE_DUMP code %d session %d count %d "
+                       "bitmask_of_module %d ",
+                        __func__, apps_args[0], apps_args[1], apps_args[2],
+                        apps_args[3]);
+                vosTraceDumpAll((void*)hHal , apps_args[0], apps_args[1],
+                                apps_args[2], apps_args[3]);
+
+            }
+            break;
+
         case WE_MCC_CONFIG_CREDENTIAL :
             {
                 cmd = 287; //Command should be updated if there is any change
@@ -7391,6 +7417,11 @@
         0,
         "setStrictFCCreg" },
 
+    {   WE_MTRACE_SELECTIVE_MODULE_LOG_ENABLE_CMD,
+        IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+        0,
+        "setdumplog" },
+
     /* handlers for main ioctl */
     {   WLAN_PRIV_SET_NONE_GET_INT,
         0,
@@ -7614,6 +7645,12 @@
         0,
         "dump" },
 
+    /* handlers for sub-ioctl */
+    {   WE_MTRACE_DUMP_CMD,
+        IW_PRIV_TYPE_INT | MAX_VAR_ARGS,
+        0,
+        "dumplog" },
+
     /* handlers for sub ioctl */
    {
        WE_MCC_CONFIG_CREDENTIAL,
diff --git a/CORE/MAC/inc/macTrace.h b/CORE/MAC/inc/macTrace.h
index 72d9f3c..6c24d49 100644
--- a/CORE/MAC/inc/macTrace.h
+++ b/CORE/MAC/inc/macTrace.h
@@ -70,51 +70,12 @@
 #define MAC_TRACE_GET_MSG_ID(data)       (data & 0xffff)
 
 
-typedef struct  sTraceRecord
-{
-    tANI_U32 time;
-    tANI_U8 module;
-    tANI_U8 code;
-    tANI_U8 session;
-    tANI_U32 data;
-}tTraceRecord, *tpTraceRecord;
-
 #define eLOG_NODROP_MISSED_BEACON_SCENARIO 0
 #define eLOG_PROC_DEAUTH_FRAME_SCENARIO 1
 
-#define MAX_TRACE_RECORDS 2000
-#define INVALID_TRACE_ADDR 0xffffffff
-#define DEFAULT_TRACE_DUMP_COUNT 0
-
-
-
-typedef void (*tpTraceCb)(tpAniSirGlobal, tpTraceRecord, tANI_U16);
-
-
-
-
-typedef struct sTraceData
-{
-    tANI_U32 head;
-    tANI_U32 tail;
-    tANI_U32 num;
-    tANI_U16 numSinceLastDump;
-
-    //Config for controlling the trace
-    tANI_U8 enable;
-    tANI_U16 dumpCount; //will dump after number of records reach this number.
-
-}tTraceData;
-
-
-
-void macTraceInit(tpAniSirGlobal pMac);
 void macTraceReset(tpAniSirGlobal pMac);
 void macTrace(tpAniSirGlobal pMac,  tANI_U8 code, tANI_U8 session, tANI_U32 data);
 void macTraceNew(tpAniSirGlobal pMac,  tANI_U8 module, tANI_U8 code, tANI_U8 session, tANI_U32 data);
-void macTraceDumpAll(tpAniSirGlobal pMac, tANI_U8 code, tANI_U8 session, tANI_U32 count);
-void macTraceCfg(tpAniSirGlobal pMac, tANI_U32 enable, tANI_U32 dumpWhenFull, tANI_U32 code, tANI_U32 session);
-void macTraceRegister( tpAniSirGlobal pMac, VOS_MODULE_ID moduleId,    tpTraceCb traceCb);
 tANI_U8* macTraceGetCfgMsgString( tANI_U16 cfgMsg );
 tANI_U8* macTraceGetLimMsgString( tANI_U16 limMsg );
 tANI_U8* macTraceGetWdaMsgString( tANI_U16 wdaMsg );
diff --git a/CORE/MAC/src/pe/include/limTrace.h b/CORE/MAC/src/pe/include/limTrace.h
index 0313d1e..291457f 100644
--- a/CORE/MAC/src/pe/include/limTrace.h
+++ b/CORE/MAC/src/pe/include/limTrace.h
@@ -62,6 +62,7 @@
 
 #include "limGlobal.h"
 #include "macTrace.h"
+#include "vos_trace.h"
 #ifdef LIM_TRACE_RECORD
 
 
@@ -116,24 +117,13 @@
 void limTraceDumpMgmtStat(tpAniSirGlobal pMac, tANI_U8 subtype);
 tANI_U8* limTraceGetMlmStateString( tANI_U32 mlmState );
 tANI_U8* limTraceGetSmeStateString( tANI_U32 smeState );
-void limTraceDump(tpAniSirGlobal pMac, tpTraceRecord pRecord, tANI_U16 recIndex);
+void limTraceDump(tpAniSirGlobal pMac, tpvosTraceRecord pRecord, tANI_U16 recIndex);
 void macTraceMsgTx(tpAniSirGlobal pMac, tANI_U8 session, tANI_U32 data);
 void macTraceMsgRx(tpAniSirGlobal pMac, tANI_U8 session, tANI_U32 data);
 
 void macTraceMsgRxNew(tpAniSirGlobal pMac, tANI_U8 module, tANI_U8 session, tANI_U32 data);
 void macTraceMsgTxNew(tpAniSirGlobal pMac, tANI_U8 module, tANI_U8 session, tANI_U32 data);
-
-
-
-
-
-#define MTRACE(p) p
-#define NO_SESSION 0xFF
-
-#else
-#define MTRACE(p) {  }
-
-#endif
+#endif //endof LIM_TRACE_RECORD MACRO
 
 #endif
 
diff --git a/CORE/MAC/src/pe/lim/limApi.c b/CORE/MAC/src/pe/lim/limApi.c
index 778c9f7..831c06a 100644
--- a/CORE/MAC/src/pe/lim/limApi.c
+++ b/CORE/MAC/src/pe/lim/limApi.c
@@ -777,7 +777,6 @@
     
     vos_trace_setLevel(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR);
 #endif
-    MTRACE(limTraceInit(pMac));
 
     //Initialize the configurations needed by PE
     if( eSIR_FAILURE == __limInitConfig(pMac))
@@ -1043,6 +1042,15 @@
         return eSIR_FAILURE;
     }
     pMac->lim.deauthMsgCnt = 0;
+
+    /*
+     * peOpen is successful by now, so it is right time to initialize
+     * MTRACE for PE module. if LIM_TRACE_RECORD is not defined in build file
+     * then nothing will be logged for PE module.
+     */
+#ifdef LIM_TRACE_RECORD
+    MTRACE(limTraceInit(pMac));
+#endif
     return eSIR_SUCCESS;
 }
 
diff --git a/CORE/MAC/src/pe/lim/limLogDump.c b/CORE/MAC/src/pe/lim/limLogDump.c
index 80771c7..437e6bb 100644
--- a/CORE/MAC/src/pe/lim/limLogDump.c
+++ b/CORE/MAC/src/pe/lim/limLogDump.c
@@ -1756,19 +1756,6 @@
     return p;
 }
 
-
-static char* dump_lim_trace_cfg(tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p)
-{
-    MTRACE(macTraceCfg(pMac, arg1, arg2, arg3, arg4);)
-    return p;
-}
-
-static char* dump_lim_trace_dump(tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p)
-{
-    MTRACE(macTraceDumpAll(pMac, (tANI_U8)arg1, (tANI_U8)arg2, arg3);)
-    return p;
-}
-
 static char* dump_lim_set_scan_in_powersave( tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2, tANI_U32 arg3, tANI_U32 arg4, char *p)
 {
     p += log_sprintf( pMac,p, "logDump set scan in powersave to %d \n", arg1);
@@ -2538,8 +2525,6 @@
      * be moved to logDump.c
      */
     {321,   "PE:LIM: Set Log Level <VOS Module> <VOS Log Level>",    dump_lim_update_log_level},
-    {322,   "PE.LIM: Enable/Disable PE Tracing",                     dump_lim_trace_cfg},
-    {323,   "PE.LIM: Trace Dump if enabled",                           dump_lim_trace_dump},
     {331,   "PE.LIM: Send finish scan to LIM",                       dump_lim_finishscan_send},
     {332,   "PE.LIM: force probe rsp send from LIM",                 dump_lim_prb_rsp_send},
     {333,   "PE.SCH: Trigger to generate a beacon",                  dump_sch_beacon_trigger},
diff --git a/CORE/MAC/src/pe/lim/limTrace.c b/CORE/MAC/src/pe/lim/limTrace.c
index 95744c8..b1e2200 100644
--- a/CORE/MAC/src/pe/lim/limTrace.c
+++ b/CORE/MAC/src/pe/lim/limTrace.c
@@ -64,6 +64,7 @@
 
 #include "limTrace.h"
 #include "limTimerUtils.h"
+#include "vos_trace.h"
 
 
 #ifdef LIM_TRACE_RECORD
@@ -139,13 +140,13 @@
 
 void limTraceInit(tpAniSirGlobal pMac)
 {
-    macTraceRegister(pMac,  VOS_MODULE_ID_PE, limTraceDump);
+    vosTraceRegister(VOS_MODULE_ID_PE, (tpvosTraceCb)&limTraceDump);
 }
 
 
 
 
-void limTraceDump(tpAniSirGlobal pMac, tpTraceRecord pRecord, tANI_U16 recIndex)
+void limTraceDump(tpAniSirGlobal pMac, tpvosTraceRecord pRecord, tANI_U16 recIndex)
 {
 
     static char *frameSubtypeStr[LIM_TRACE_MAX_SUBTYPES] =
diff --git a/CORE/SYS/legacy/src/system/src/macInitApi.c b/CORE/SYS/legacy/src/system/src/macInitApi.c
index 23d8a21..2c587d9 100644
--- a/CORE/SYS/legacy/src/system/src/macInitApi.c
+++ b/CORE/SYS/legacy/src/system/src/macInitApi.c
@@ -132,12 +132,6 @@
 
    do
    {
-
-#if defined(TRACE_RECORD)
-      //Enable Tracing
-      macTraceInit(pMac);
-#endif
-
       pMac->pResetMsg = vos_mem_malloc(sizeof(tSirMbMsg));
       if ( NULL == pMac->pResetMsg )
       {
diff --git a/CORE/SYS/legacy/src/utils/src/macTrace.c b/CORE/SYS/legacy/src/utils/src/macTrace.c
index 4f5b2bd..d6f49cd 100644
--- a/CORE/SYS/legacy/src/utils/src/macTrace.c
+++ b/CORE/SYS/legacy/src/utils/src/macTrace.c
@@ -72,11 +72,9 @@
 #include "csrInternal.h"
 #include "limGlobal.h"
 #include "wlan_qct_tl.h"
+#include "vos_trace.h"
 
 #ifdef TRACE_RECORD
-static tTraceRecord gTraceTbl[MAX_TRACE_RECORDS];
-static tTraceData gTraceData;
-static tpTraceCb traceCBTable[VOS_MODULE_ID_MAX];
 
 /* ---------------------------------------------------------------------------
     \fn macTraceGetHDDWlanConnState
@@ -803,8 +801,6 @@
     }
 }
 
-
-
 tANI_U8* macTraceGetLimMsgString( tANI_U16 limMsg )
 {
     switch( limMsg )
@@ -869,9 +865,6 @@
     }
 }
 
-
-
-
 tANI_U8* macTraceGetCfgMsgString( tANI_U16 cfgMsg )
 {
     switch( cfgMsg )
@@ -909,153 +902,21 @@
     //return gVosTraceInfo[moduleId].moduleNameStr;
 }
 
-
-
-
-
-
-
-
-
-
-void macTraceInit(tpAniSirGlobal pMac)
-{
-    tANI_U8 i;
-    gTraceData.head = INVALID_TRACE_ADDR;
-    gTraceData.tail = INVALID_TRACE_ADDR;
-    gTraceData.num = 0;
-    gTraceData.enable = TRUE;
-    gTraceData.dumpCount = DEFAULT_TRACE_DUMP_COUNT;
-    gTraceData.numSinceLastDump = 0;
-
-    for(i=0; i<VOS_MODULE_ID_MAX; i++)
-        traceCBTable[i] = NULL;
-
-}
-
-
-
-
-
 void macTraceReset(tpAniSirGlobal pMac)
 {
 }
 
-
 void macTrace(tpAniSirGlobal pMac,  tANI_U8 code, tANI_U8 session, tANI_U32 data)
 {
     //Today macTrace is being invoked by PE only, need to remove this function once PE is migrated to using new trace API.
     macTraceNew(pMac, VOS_MODULE_ID_PE, code, session, data);
-
-#if 0
-    tpTraceRecord rec = NULL;
-
-    //limLog(pMac, LOGE, "mac Trace code: %d, data: %x, head: %d, tail: %d\n",  code, data, gTraceData.head, gTraceData.tail);
-
-    if(!gTraceData.enable)
-        return;
-    gTraceData.num++;
-
-    if (gTraceData.head == INVALID_TRACE_ADDR)
-    {
-        /* first record */
-        gTraceData.head = 0;
-        gTraceData.tail = 0;
-    }
-    else
-    {
-        /* queue is not empty */
-        tANI_U32 tail = gTraceData.tail + 1;
-
-        if (tail == MAX_TRACE_RECORDS)
-            tail = 0;
-
-        if (gTraceData.head == tail)
-        {
-            /* full */
-            if (++gTraceData.head == MAX_TRACE_RECORDS)
-                gTraceData.head = 0;
-        }
-
-        gTraceData.tail = tail;
-    }
-
-    rec = &gTraceTbl[gTraceData.tail];
-    rec->code = code;
-    rec->session = session;
-    rec->data = data;
-    rec->time = vos_timer_get_system_time();
-    rec->module =  VOS_MODULE_ID_PE;
-    gTraceData.numSinceLastDump ++;
-
-    if(gTraceData.numSinceLastDump == gTraceData.dumpCount)
-        {
-            limLog(pMac, LOGE, "Trace Dump last %d traces\n",  gTraceData.dumpCount);
-            macTraceDumpAll(pMac, 0, 0, gTraceData.dumpCount);
-            gTraceData.numSinceLastDump = 0;
-        }
-    #endif
-
 }
 
-
-
 void macTraceNew(tpAniSirGlobal pMac, tANI_U8 module, tANI_U8 code, tANI_U8 session, tANI_U32 data)
 {
-    tpTraceRecord rec = NULL;
-
-    //limLog(pMac, LOGE, "mac Trace code: %d, data: %x, head: %d, tail: %d\n",  code, data, gTraceData.head, gTraceData.tail);
-
-    if(!gTraceData.enable)
-        return;
-    //If module is not registered, don't record for that module.
-    if(traceCBTable[module] == NULL)
-        return;
-    pe_AcquireGlobalLock( &pMac->lim );
-
-    gTraceData.num++;
-
-    if (gTraceData.head == INVALID_TRACE_ADDR)
-    {
-        /* first record */
-        gTraceData.head = 0;
-        gTraceData.tail = 0;
-    }
-    else
-    {
-        /* queue is not empty */
-        tANI_U32 tail = gTraceData.tail + 1;
-
-        if (tail == MAX_TRACE_RECORDS)
-            tail = 0;
-
-        if (gTraceData.head == tail)
-        {
-            /* full */
-            if (++gTraceData.head == MAX_TRACE_RECORDS)
-                gTraceData.head = 0;
-        }
-
-        gTraceData.tail = tail;
-    }
-
-    rec = &gTraceTbl[gTraceData.tail];
-    rec->code = code;
-    rec->session = session;
-    rec->data = data;
-    rec->time = vos_timer_get_system_time();
-    rec->module =  module;
-    gTraceData.numSinceLastDump ++;
-    pe_ReleaseGlobalLock( &pMac->lim );
-
+    vos_trace(module, code, session, data);
 }
 
-
-
-
-
-
-
 tANI_U8* macTraceMsgString(tpAniSirGlobal pMac, tANI_U32 msgType)
 {
     tANI_U16 msgId = (tANI_U16)MAC_TRACE_GET_MSG_ID(msgType);
@@ -1078,88 +939,4 @@
     }
 }
 
-
-
-
-
-
-void macTraceDumpAll(tpAniSirGlobal pMac, tANI_U8 code, tANI_U8 session, tANI_U32 count)
-{
-    tpTraceRecord pRecord;
-    tANI_S32 i, tail;
-
-
-    if(!gTraceData.enable)
-    {
-        VOS_TRACE( VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR, "Tracing Disabled \n");
-        return;
-    }
-
-    VOS_TRACE( VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR,
-                            "Total Records: %d, Head: %d, Tail: %d\n", gTraceData.num, gTraceData.head, gTraceData.tail);
-
-    pe_AcquireGlobalLock( &pMac->lim );
-    if (gTraceData.head != INVALID_TRACE_ADDR)
-    {
-
-        i = gTraceData.head;
-        tail = gTraceData.tail;
-
-        if (count)
-        {
-            if (count > gTraceData.num)
-                count = gTraceData.num;
-            if (count > MAX_TRACE_RECORDS)
-                count = MAX_TRACE_RECORDS;
-            if(tail >= (count + 1))
-            {
-                i = tail - count + 1;
-            }
-            else
-            {
-                i = MAX_TRACE_RECORDS - ((count + 1) - tail);
-            }
-        }
-
-        pRecord = &gTraceTbl[i];
-
-        for (;;)
-        {
-            if (   (code == 0 || (code == pRecord->code)) &&
-                    (traceCBTable[pRecord->module] != NULL))
-                traceCBTable[pRecord->module](pMac, pRecord, (tANI_U16)i);
-
-            if (i == tail)
-                break;
-            i += 1;
-
-            if (i == MAX_TRACE_RECORDS)
-            {
-                i = 0;
-                pRecord = &gTraceTbl[0];
-            }
-            else
-                pRecord += 1;
-        }
-        gTraceData.numSinceLastDump = 0;
-
-    }
-    pe_ReleaseGlobalLock( &pMac->lim );
-
-}
-
-
-void macTraceCfg(tpAniSirGlobal pMac, tANI_U32 enable, tANI_U32 dumpCount, tANI_U32 code, tANI_U32 session)
-{
-    gTraceData.enable = (tANI_U8)enable;
-    gTraceData.dumpCount= (tANI_U16)dumpCount;
-    gTraceData.numSinceLastDump = 0;
-}
-
-void macTraceRegister( tpAniSirGlobal pMac, VOS_MODULE_ID moduleId,    tpTraceCb traceCb)
-{
-    traceCBTable[moduleId] = traceCb;
-}
-
-
 #endif
diff --git a/CORE/VOSS/inc/vos_trace.h b/CORE/VOSS/inc/vos_trace.h
index 5703b5d..71d4b2b 100644
--- a/CORE/VOSS/inc/vos_trace.h
+++ b/CORE/VOSS/inc/vos_trace.h
@@ -60,6 +60,8 @@
   ------------------------------------------------------------------------*/
 #include  <vos_types.h>  // For VOS_MODULE_ID...
 #include  <stdarg.h>       // For va_list...
+#include  <vos_status.h>
+#include  <i_vos_types.h>
 
 /*-------------------------------------------------------------------------- 
   Type declarations 
@@ -103,9 +105,51 @@
 // TODO: remove this once this is not used on Android
 #define VOS_ENABLE_TRACING 
 #define WCONN_TRACE_KMSG_LOG_BUFF
+#define MAX_VOS_TRACE_RECORDS 4000
+#define INVALID_VOS_TRACE_ADDR 0xffffffff
+#define DEFAULT_VOS_TRACE_DUMP_COUNT 0
 
 #include  <i_vos_trace.h>   
 
+#ifdef TRACE_RECORD
+
+#define MTRACE(p) p
+#define NO_SESSION 0xFF
+
+#else
+#define MTRACE(p) {  }
+
+#endif
+
+/*--------------------------------------------------------------------------
+  Structure definition
+  ------------------------------------------------------------------------*/
+typedef struct  svosTraceRecord
+{
+    v_U32_t time;
+    v_U8_t module;
+    v_U8_t code;
+    v_U8_t session;
+    v_U32_t data;
+}tvosTraceRecord, *tpvosTraceRecord;
+
+typedef struct svosTraceData
+{
+    // MTRACE logs are stored in ring buffer where head represents the position
+    // of first record, tail represents the position of last record added till
+    // now and num is the count of total record added.
+    v_U32_t head;
+    v_U32_t tail;
+    v_U32_t num;
+    v_U16_t numSinceLastDump;
+
+    //Config for controlling the trace
+    v_U8_t enable;
+    v_U16_t dumpCount; //will dump after number of records reach this number.
+
+}tvosTraceData;
+
+
 /*------------------------------------------------------------------------- 
   Function declarations and documenation
   ------------------------------------------------------------------------*/
@@ -169,4 +213,11 @@
 void vos_wconn_trace_exit(void);
 #endif
 
+typedef void (*tpvosTraceCb) (void *pMac, tpvosTraceRecord, v_U16_t);
+void vos_trace(v_U8_t module, v_U8_t code, v_U8_t session, v_U32_t data);
+void vosTraceRegister(VOS_MODULE_ID, tpvosTraceCb);
+VOS_STATUS vos_trace_spin_lock_init(void);
+void vosTraceInit(void);
+void vosTraceEnable(v_U32_t);
+void vosTraceDumpAll(void*, v_U8_t, v_U8_t, v_U32_t, v_U32_t);
 #endif
diff --git a/CORE/VOSS/src/vos_api.c b/CORE/VOSS/src/vos_api.c
index eef928b..af4411c 100644
--- a/CORE/VOSS/src/vos_api.c
+++ b/CORE/VOSS/src/vos_api.c
@@ -85,6 +85,7 @@
 #include "wlan_hdd_cfg80211.h"
 
 #include "sapApi.h"
+#include "vos_trace.h"
 
 
 
@@ -171,6 +172,13 @@
 
    *pVosContext = gpVosContext;
 
+   /* Initialize the spinlock */
+   vos_trace_spin_lock_init();
+   /* it is the right time to initialize MTRACE structures */
+   #if defined(TRACE_RECORD)
+       vosTraceInit();
+   #endif
+
    return VOS_STATUS_SUCCESS;
 
 } /* vos_preOpen()*/
@@ -270,6 +278,7 @@
    /* Initialize the timer module */
    vos_timer_module_init();
 
+
    /* Initialize the probe event */
    if (vos_event_init(&gpVosContext->ProbeEvent) != VOS_STATUS_SUCCESS)
    {
diff --git a/CORE/VOSS/src/vos_trace.c b/CORE/VOSS/src/vos_trace.c
index fce27a3..7119e3a 100644
--- a/CORE/VOSS/src/vos_trace.c
+++ b/CORE/VOSS/src/vos_trace.c
@@ -77,6 +77,7 @@
   Include Files
   ------------------------------------------------------------------------*/
 #include <vos_trace.h>
+#include <aniGlobal.h>
 /*--------------------------------------------------------------------------
   Preprocessor definitions and constants
   ------------------------------------------------------------------------*/
@@ -124,8 +125,23 @@
    [VOS_MODULE_ID_HDD_SOFTAP] = { VOS_DEFAULT_TRACE_LEVEL, "HSP" },
    [VOS_MODULE_ID_PMC]        = { VOS_DEFAULT_TRACE_LEVEL, "PMC" },
 };
+/*-------------------------------------------------------------------------
+  Static and Global variables
+  ------------------------------------------------------------------------*/
+static spinlock_t ltraceLock;
 
-
+static tvosTraceRecord gvosTraceTbl[MAX_VOS_TRACE_RECORDS];
+// Global vosTraceData
+static tvosTraceData gvosTraceData;
+/*
+ * all the call back functions for dumping MTRACE messages from ring buffer
+ * are stored in vostraceCBTable,these callbacks are initialized during init only
+ * so, we will make a copy of these call back functions and maintain in to
+ * vostraceRestoreCBTable. Incase if we make modifications to vostraceCBTable,
+ * we can certainly retrieve all the call back functions back from Restore Table
+ */
+static tpvosTraceCb vostraceCBTable[VOS_MODULE_ID_MAX];
+static tpvosTraceCb vostraceRestoreCBTable[VOS_MODULE_ID_MAX];
 /*-------------------------------------------------------------------------
   Functions
   ------------------------------------------------------------------------*/
@@ -426,3 +442,281 @@
 }
 
 #endif
+
+/*-----------------------------------------------------------------------------
+  \brief vosTraceEnable() - Enable MTRACE for specific modules whose bits are
+  set in bitmask. set the bitmask according to enum value of the modules.
+
+  this functions will be called when you issue ioctl as mentioned following
+  [iwpriv wlan0 setdumplog <value>].
+  <value> - Decimal number, i.e. 64 decimal value shows only SME module,
+  128 decimal value shows only PE module, 192 decimal value shows PE and SME.
+
+  \param - bitmask_of_moduleId - as explained above set bitmask according to
+  enum of the modules.
+  32 [dec]  = 0010 0000 [bin] <enum of HDD is 5>
+  64 [dec]  = 0100 0000 [bin] <enum of SME is 6>
+  128 [dec] = 1000 0000 [bin] <enum of PE is 7>
+  ---------------------------------------------------------------------------*/
+void vosTraceEnable(v_U32_t bitmask_of_moduleId)
+{
+    int i;
+    if (bitmask_of_moduleId)
+    {
+       for (i=0; i<VOS_MODULE_ID_MAX; i++)
+       {
+           if (!((bitmask_of_moduleId >> i) & 1 ))
+           {
+              vostraceRestoreCBTable[i] = vostraceCBTable[i];
+              vostraceCBTable[i] = NULL;
+           }
+       }
+    }
+    else
+    {
+       for (i=0; i<VOS_MODULE_ID_MAX; i++)
+       {
+           if (NULL != vostraceRestoreCBTable[i])
+           {
+              vostraceCBTable[i] = vostraceRestoreCBTable[i];
+           }
+       }
+    }
+}
+
+/*-----------------------------------------------------------------------------
+  \brief vosTraceInit() - Initializes vos trace structures and variables.
+
+  Called immediately after vos_preopen, so that we can start recording HDD
+  events ASAP.
+  ----------------------------------------------------------------------------*/
+void vosTraceInit()
+{
+    v_U8_t i;
+    gvosTraceData.head = INVALID_VOS_TRACE_ADDR;
+    gvosTraceData.tail = INVALID_VOS_TRACE_ADDR;
+    gvosTraceData.num = 0;
+    gvosTraceData.enable = TRUE;
+    gvosTraceData.dumpCount = DEFAULT_VOS_TRACE_DUMP_COUNT;
+    gvosTraceData.numSinceLastDump = 0;
+
+    for (i=0; i<VOS_MODULE_ID_MAX; i++)
+    {
+        vostraceCBTable[i] = NULL;
+        vostraceRestoreCBTable[i] = NULL;
+    }
+}
+
+/*-----------------------------------------------------------------------------
+  \brief vos_trace() - puts the messages in to ring-buffer
+
+  This function will be called from each module who wants record the messages
+  in circular queue. Before calling this functions make sure you have
+  registered your module with voss through vosTraceRegister function.
+
+  \param module - enum of module, basically module id.
+  \param code -
+  \param session -
+  \param data - actual message contents.
+  ----------------------------------------------------------------------------*/
+void vos_trace(v_U8_t module, v_U8_t code, v_U8_t session, v_U32_t data)
+{
+    tpvosTraceRecord rec = NULL;
+
+
+    if (!gvosTraceData.enable)
+    {
+        return;
+    }
+    //If module is not registered, don't record for that module.
+    if (NULL == vostraceCBTable[module])
+    {
+        return;
+    }
+
+    /* Aquire the lock so that only one thread at a time can fill the ring buffer */
+    spin_lock(&ltraceLock);
+
+    gvosTraceData.num++;
+
+    if (gvosTraceData.num > MAX_VOS_TRACE_RECORDS)
+    {
+        gvosTraceData.num = MAX_VOS_TRACE_RECORDS;
+    }
+
+    if (INVALID_VOS_TRACE_ADDR == gvosTraceData.head)
+    {
+        /* first record */
+        gvosTraceData.head = 0;
+        gvosTraceData.tail = 0;
+    }
+    else
+    {
+        /* queue is not empty */
+        v_U32_t tail = gvosTraceData.tail + 1;
+
+        if (MAX_VOS_TRACE_RECORDS == tail)
+        {
+            tail = 0;
+        }
+
+        if (gvosTraceData.head == tail)
+        {
+            /* full */
+            if (MAX_VOS_TRACE_RECORDS == ++gvosTraceData.head)
+            {
+                gvosTraceData.head = 0;
+            }
+        }
+
+        gvosTraceData.tail = tail;
+    }
+
+    rec = &gvosTraceTbl[gvosTraceData.tail];
+    rec->code = code;
+    rec->session = session;
+    rec->data = data;
+    rec->time = vos_timer_get_system_time();
+    rec->module =  module;
+    gvosTraceData.numSinceLastDump ++;
+    spin_unlock(&ltraceLock);
+}
+
+
+/*-----------------------------------------------------------------------------
+  \brief vos_trace_spin_lock_init() - Initializes the lock variable before use
+
+  This function will be called from vos_preOpen, we will have lock available
+  to use ASAP.
+  ----------------------------------------------------------------------------*/
+VOS_STATUS vos_trace_spin_lock_init()
+{
+    spin_lock_init(&ltraceLock);
+
+    return VOS_STATUS_SUCCESS;
+}
+
+/*-----------------------------------------------------------------------------
+  \brief vosTraceRegister() - Registers the call back functions to display the
+  messages in particular format mentioned in these call back functions.
+
+  this functions should be called by interested module in their init part as
+  we will be ready to register as soon as modules are up.
+
+  \param moduleID - enum value of module
+  \param vostraceCb - call back functions to display the messages in particular
+  format.
+  ----------------------------------------------------------------------------*/
+void vosTraceRegister(VOS_MODULE_ID moduleID, tpvosTraceCb vostraceCb)
+{
+    vostraceCBTable[moduleID] = vostraceCb;
+}
+
+/*------------------------------------------------------------------------------
+  \brief vosTraceDumpAll() - Dump data from ring buffer via call back functions
+  registered with VOSS
+
+  This function will be called up on issueing ioctl call as mentioned following
+  [iwpriv wlan0 dumplog 0 0 <n> <bitmask_of_module>]
+
+  <n> - number lines to dump starting from tail to head.
+
+  <bitmask_of_module> - if anybody wants to know how many messages were recorded
+  for particular module/s mentioned by setbit in bitmask from last <n> messages.
+  it is optional, if you don't provide then it will dump everything from buffer.
+
+  \param pMac - context of particular module
+  \param code -
+  \param session -
+  \param count - number of lines to dump starting from tail to head
+  ----------------------------------------------------------------------------*/
+void vosTraceDumpAll(void *pMac, v_U8_t code, v_U8_t session,
+                     v_U32_t count, v_U32_t bitmask_of_module)
+{
+    tvosTraceRecord pRecord;
+    tANI_S32 i, tail;
+
+
+    if (!gvosTraceData.enable)
+    {
+        VOS_TRACE( VOS_MODULE_ID_SYS,
+                   VOS_TRACE_LEVEL_ERROR, "Tracing Disabled");
+        return;
+    }
+
+    VOS_TRACE( VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR,
+               "Total Records: %d, Head: %d, Tail: %d",
+               gvosTraceData.num, gvosTraceData.head, gvosTraceData.tail);
+
+    /* Aquire the lock so that only one thread at a time can read the ring buffer */
+    spin_lock(&ltraceLock);
+
+    if (gvosTraceData.head != INVALID_VOS_TRACE_ADDR)
+    {
+        i = gvosTraceData.head;
+        tail = gvosTraceData.tail;
+
+        if (count)
+        {
+            if (count > gvosTraceData.num)
+            {
+                count = gvosTraceData.num;
+            }
+            if (tail >= (count - 1))
+            {
+                i = tail - count + 1;
+            }
+            else if (count != MAX_VOS_TRACE_RECORDS)
+            {
+                i = MAX_VOS_TRACE_RECORDS - ((count - 1) - tail);
+            }
+        }
+
+        pRecord = gvosTraceTbl[i];
+        /* right now we are not using numSinceLastDump member but in future
+           we might re-visit and use this member to track how many latest
+           messages got added while we were dumping from ring buffer */
+        gvosTraceData.numSinceLastDump = 0;
+        spin_unlock(&ltraceLock);
+        for (;;)
+        {
+            if ((code == 0 || (code == pRecord.code)) &&
+                    (vostraceCBTable[pRecord.module] != NULL))
+            {
+                if (0 == bitmask_of_module)
+                {
+                   vostraceCBTable[pRecord.module](pMac, &pRecord, (v_U16_t)i);
+                }
+                else
+                {
+                   if (bitmask_of_module & (1 << pRecord.module))
+                   {
+                      vostraceCBTable[pRecord.module](pMac, &pRecord, (v_U16_t)i);
+                   }
+                }
+            }
+
+            if (i == tail)
+            {
+                break;
+            }
+            i += 1;
+
+            spin_lock(&ltraceLock);
+            if (MAX_VOS_TRACE_RECORDS == i)
+            {
+                i = 0;
+                pRecord= gvosTraceTbl[0];
+            }
+            else
+            {
+                pRecord = gvosTraceTbl[i];
+            }
+            spin_unlock(&ltraceLock);
+        }
+    }
+    else
+    {
+        spin_unlock(&ltraceLock);
+    }
+}