prima: Framework to print system information

Print state information of HDD, SME, PE, WDA and WDI layers
when active command timeout issue is seen. This can be extended
to print system information of other layers if there is necessity
for such information.

Change-Id: Ibce74761f60f33d37ffde0530c2d2635be46cdd7
CRs-Fixed: 851666
diff --git a/CORE/HDD/inc/wlan_hdd_trace.h b/CORE/HDD/inc/wlan_hdd_trace.h
index aef3ef5..f468487 100644
--- a/CORE/HDD/inc/wlan_hdd_trace.h
+++ b/CORE/HDD/inc/wlan_hdd_trace.h
@@ -114,6 +114,8 @@
 
 extern void hddTraceDump(void *pMac, tpvosTraceRecord pRecord, tANI_U16 recIndex);
 extern void hddTraceInit(void);
+void hdd_register_debug_callback(void);
+
 #endif
 
 
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index 940814b..42a789f 100755
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -10628,6 +10628,8 @@
    }
 
    hddTraceInit();
+   hdd_register_debug_callback();
+
 #ifndef MODULE
       /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
        */
diff --git a/CORE/HDD/src/wlan_hdd_trace.c b/CORE/HDD/src/wlan_hdd_trace.c
index a062523..577f314 100644
--- a/CORE/HDD/src/wlan_hdd_trace.c
+++ b/CORE/HDD/src/wlan_hdd_trace.c
@@ -135,3 +135,63 @@
 {
     vosTraceRegister(VOS_MODULE_ID_HDD, (tpvosTraceCb)&hddTraceDump);
 }
+
+/**
+ * hdd_state_info_dump() - prints state information of hdd layer
+ */
+static void hdd_state_info_dump(void)
+{
+    v_CONTEXT_t vos_ctx_ptr;
+    hdd_context_t *hdd_ctx_ptr = NULL;
+    hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
+    VOS_STATUS status;
+    hdd_station_ctx_t *hdd_sta_ctx = NULL;
+    hdd_adapter_t *adapter =NULL;
+
+    /* get the global voss context */
+    vos_ctx_ptr = vos_get_global_context(VOS_MODULE_ID_VOSS, NULL);
+
+    if (NULL != vos_ctx_ptr) {
+        hdd_ctx_ptr = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx_ptr);
+    } else {
+        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                  "%s: Invalid Global VOSS Context", __func__);
+        VOS_ASSERT(0);
+        return;
+    }
+
+    hddLog(LOG1,
+           FL("mScanPending %d isWlanSuspended %d disable_dfs_flag %d"),
+           hdd_ctx_ptr->scan_info.mScanPending,
+           hdd_ctx_ptr->isWlanSuspended, hdd_ctx_ptr->disable_dfs_flag);
+
+    status = hdd_get_front_adapter(hdd_ctx_ptr, &adapter_node);
+
+    while (NULL != adapter_node && VOS_STATUS_SUCCESS == status) {
+       adapter = adapter_node->pAdapter;
+       if (adapter->dev)
+           hddLog(LOG1, FL("device name: %s"), adapter->dev->name);
+       switch (adapter->device_mode) {
+       case WLAN_HDD_INFRA_STATION:
+       case WLAN_HDD_P2P_CLIENT:
+           hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+           hddLog(LOG1, FL("connState: %d device_mode: %d"),
+                  hdd_sta_ctx->conn_info.connState, adapter->device_mode);
+           break;
+
+       default:
+           break;
+       }
+       status = hdd_get_next_adapter(hdd_ctx_ptr, adapter_node, &next);
+       adapter_node = next;
+    }
+}
+
+/**
+ * hdd_register_debug_callback() - registration function for hdd layer
+ * to print hdd state information
+ */
+void hdd_register_debug_callback()
+{
+    vos_register_debug_callback(VOS_MODULE_ID_HDD, &hdd_state_info_dump);
+}
diff --git a/CORE/MAC/src/pe/include/limTrace.h b/CORE/MAC/src/pe/include/limTrace.h
index 13f1e26..24ffb8c 100644
--- a/CORE/MAC/src/pe/include/limTrace.h
+++ b/CORE/MAC/src/pe/include/limTrace.h
@@ -93,6 +93,7 @@
 
 
 void limTraceInit(tpAniSirGlobal pMac);
+void lim_register_debug_callback(void);
 void limTraceReset(tpAniSirGlobal pMac);
 void limTraceUpdateMgmtStat(tpAniSirGlobal pMac, tANI_U8 subtype);
 void limTraceDumpMgmtStat(tpAniSirGlobal pMac, tANI_U8 subtype);
diff --git a/CORE/MAC/src/pe/lim/limApi.c b/CORE/MAC/src/pe/lim/limApi.c
index f4fa99c..f465af7 100644
--- a/CORE/MAC/src/pe/lim/limApi.c
+++ b/CORE/MAC/src/pe/lim/limApi.c
@@ -1055,6 +1055,7 @@
 #ifdef LIM_TRACE_RECORD
     MTRACE(limTraceInit(pMac));
 #endif
+    lim_register_debug_callback();
     return eSIR_SUCCESS;
 }
 
diff --git a/CORE/MAC/src/pe/lim/limTrace.c b/CORE/MAC/src/pe/lim/limTrace.c
index 5ac5ddf..4f996fd 100644
--- a/CORE/MAC/src/pe/lim/limTrace.c
+++ b/CORE/MAC/src/pe/lim/limTrace.c
@@ -303,6 +303,49 @@
     }
 }
 
+/**
+ * lim_state_info_dump() - print state information of lim layer
+  */
+static void lim_state_info_dump(void)
+{
+    tHalHandle hal;
+    tpAniSirGlobal mac;
+    v_CONTEXT_t vos_ctx_ptr;
+
+    /* get the global voss context */
+    vos_ctx_ptr = vos_get_global_context(VOS_MODULE_ID_VOSS, NULL);
+
+    if (NULL == vos_ctx_ptr) {
+        limLog( mac, LOGE, FL("Invalid Global VOSS Context"));
+        VOS_ASSERT(0);
+        return;
+    }
+
+    hal = vos_get_context(VOS_MODULE_ID_PE, vos_ctx_ptr);
+    if (NULL == hal) {
+        limLog( mac, LOGE, FL("Invalid smeContext"));
+        VOS_ASSERT(0);
+        return;
+    }
+
+    mac = PMAC_STRUCT(hal);
+
+    limLog(mac, LOG1, FL("SmeState: %d PrevSmeState: %d MlmState: %d"
+           "PrevMlmState: %d SystemInScanLearnMode: %d ProcessDefdMsgs: %d"
+           "gLimHalScanState: %d"), mac->lim.gLimSmeState,
+           mac->lim.gLimPrevSmeState, mac->lim.gLimMlmState,
+           mac->lim.gLimPrevMlmState, mac->lim.gLimSystemInScanLearnMode,
+           mac->lim.gLimProcessDefdMsgs, mac->lim.gLimHalScanState);
+}
+
+/**
+ * lim_register_debug_callback() - registration function for lim layer
+ * to print lim state information
+  */
+void lim_register_debug_callback()
+{
+    vos_register_debug_callback(VOS_MODULE_ID_PE, &lim_state_info_dump);
+}
 
 void macTraceMsgTx(tpAniSirGlobal pMac, tANI_U8 session, tANI_U32 data)
 {
diff --git a/CORE/SME/inc/smeInside.h b/CORE/SME/inc/smeInside.h
index cf97d96..af429e6 100644
--- a/CORE/SME/inc/smeInside.h
+++ b/CORE/SME/inc/smeInside.h
@@ -223,6 +223,7 @@
 void smeReleaseCommand(tpAniSirGlobal pMac, tSmeCmd *pCmd);
 void purgeSmeSessionCmdList(tpAniSirGlobal pMac, tANI_U32 sessionId,
         tDblLinkList *pList);
+tANI_U32 sme_get_sessionid_from_activeList(tpAniSirGlobal pMac);
 tANI_BOOLEAN smeCommandPending(tpAniSirGlobal pMac);
 tANI_BOOLEAN pmcProcessCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand );
 //this function is used to abort a command where the normal processing of the command
diff --git a/CORE/SME/inc/sme_Trace.h b/CORE/SME/inc/sme_Trace.h
index d5dfc9a..ff11335 100644
--- a/CORE/SME/inc/sme_Trace.h
+++ b/CORE/SME/inc/sme_Trace.h
@@ -156,4 +156,5 @@
 };
 
 void smeTraceInit(tpAniSirGlobal pMac);
+void sme_register_debug_callback(void);
 #endif //__SME_TRACE_H__
diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index 7622b02..375b20b 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -465,6 +465,8 @@
         smeCommandQueueFull++;
         csrLLUnlock(&pMac->roam.roamCmdPendingList);
 
+        vos_state_info_dump_all();
+
         if (pMac->roam.configParam.enableFatalEvent)
         {
             vos_fatal_event_logs_req(WLAN_LOG_TYPE_FATAL,
@@ -1368,6 +1370,7 @@
 #endif
       sme_p2pOpen(pMac);
       smeTraceInit(pMac);
+      sme_register_debug_callback();
 
    }while (0);
 
@@ -7915,6 +7918,21 @@
    return (sessionid);
 }
 
+tANI_U32 sme_get_sessionid_from_activeList(tpAniSirGlobal mac)
+{
+    tListElem *entry = NULL;
+    tSmeCmd *command = NULL;
+    tANI_U32  session_id = 0;
+
+    entry = csrLLPeekHead( &mac->sme.smeCmdActiveList, LL_ACCESS_LOCK );
+    if ( entry ) {
+        command = GET_BASE_ADDR( entry, tSmeCmd, Link );
+        session_id = command->sessionId;
+    }
+
+    return (session_id);
+}
+
 /* ---------------------------------------------------------------------------
 
     \fn sme_GetInfraOperationChannel
@@ -11896,6 +11914,8 @@
         csrLLCount(&pMac->sme.smeCmdActiveList) );
     smeGetCommandQStatus(hHal);
 
+    vos_state_info_dump_all();
+
     if (pMac->roam.configParam.enableFatalEvent)
     {
        vos_fatal_event_logs_req(WLAN_LOG_TYPE_FATAL,
diff --git a/CORE/SME/src/sme_common/sme_Trace.c b/CORE/SME/src/sme_common/sme_Trace.c
index 3e18dcc..cfd5125 100644
--- a/CORE/SME/src/sme_common/sme_Trace.c
+++ b/CORE/SME/src/sme_common/sme_Trace.c
@@ -38,6 +38,8 @@
 #include "macTrace.h"
 #include "sme_Trace.h"
 #include "smeInternal.h"
+#include "smeInside.h"
+
 #ifndef SME_TRACE_RECORD
 void smeTraceInit(tpAniSirGlobal pMac)
 {
@@ -238,4 +240,52 @@
 {
     vosTraceRegister(VOS_MODULE_ID_SME, (tpvosTraceCb)&smeTraceDump);
 }
+
+/**
+ * sme_state_info_dump() - prints state information of sme layer
+ */
+static void sme_state_info_dump(void)
+{
+    tANI_U32  session_id = 0;
+    tHalHandle hal;
+    tpAniSirGlobal mac;
+    v_CONTEXT_t vos_ctx_ptr;
+
+    /* get the global voss context */
+    vos_ctx_ptr = vos_get_global_context(VOS_MODULE_ID_VOSS, NULL);
+
+    if (NULL == vos_ctx_ptr) {
+        smsLog( mac, LOGE, FL("Invalid Global VOSS Context"));
+        VOS_ASSERT(0);
+        return;
+    }
+
+    hal = vos_get_context(VOS_MODULE_ID_SME, vos_ctx_ptr);
+    if (NULL == hal) {
+        smsLog( mac, LOGE, FL("Invalid smeContext"));
+        VOS_ASSERT(0);
+        return;
+    }
+
+    mac = PMAC_STRUCT(hal);
+
+    session_id = sme_get_sessionid_from_activeList(mac);
+    smsLog( mac, LOG1, FL(" SessionId %d for active command"), session_id);
+
+    smsLog(mac, LOG1, FL("NeighborRoamState: %d RoamState: %d"
+           "RoamSubState: %d ConnectState: %d pmcState: %d PmmState: %d"),
+           mac->roam.neighborRoamInfo.neighborRoamState,
+           mac->roam.curState[session_id], mac->roam.curSubState[session_id],
+           mac->roam.roamSession[session_id].connectState, mac->pmc.pmcState,
+           mac->pmm.gPmmState);
+}
+
+/**
+ * sme_register_debug_callback() - registration function sme layer
+ * to print sme state information
+ */
+void sme_register_debug_callback()
+{
+    vos_register_debug_callback(VOS_MODULE_ID_SME, &sme_state_info_dump);
+}
 #endif
diff --git a/CORE/VOSS/inc/vos_trace.h b/CORE/VOSS/inc/vos_trace.h
index 76095de..538f58d 100644
--- a/CORE/VOSS/inc/vos_trace.h
+++ b/CORE/VOSS/inc/vos_trace.h
@@ -191,10 +191,16 @@
 v_BOOL_t vos_trace_getLevel( VOS_MODULE_ID module, VOS_TRACE_LEVEL level );
 
 typedef void (*tpvosTraceCb) (void *pMac, tpvosTraceRecord, v_U16_t);
+typedef void (*tp_vos_state_info_cb) (void);
+
 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);
+void vos_register_debug_callback(VOS_MODULE_ID moduleID,
+                                      tp_vos_state_info_cb vosStateInfoCb);
 VOS_STATUS vos_trace_spin_lock_init(void);
 void vosTraceInit(void);
+void vos_register_debugcb_init(void);
 void vosTraceEnable(v_U32_t, v_U8_t enable);
 void vosTraceDumpAll(void*, v_U8_t, v_U8_t, v_U32_t, v_U32_t);
+void vos_state_info_dump_all(void);
 #endif
diff --git a/CORE/VOSS/src/vos_api.c b/CORE/VOSS/src/vos_api.c
index 3e9b7bf..d4d68a8 100644
--- a/CORE/VOSS/src/vos_api.c
+++ b/CORE/VOSS/src/vos_api.c
@@ -168,6 +168,7 @@
    #if defined(TRACE_RECORD)
        vosTraceInit();
    #endif
+   vos_register_debugcb_init();
 
    return VOS_STATUS_SUCCESS;
 
diff --git a/CORE/VOSS/src/vos_trace.c b/CORE/VOSS/src/vos_trace.c
old mode 100755
new mode 100644
index 095e4df..a06b320
--- a/CORE/VOSS/src/vos_trace.c
+++ b/CORE/VOSS/src/vos_trace.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -130,6 +130,8 @@
  */
 static tpvosTraceCb vostraceCBTable[VOS_MODULE_ID_MAX];
 static tpvosTraceCb vostraceRestoreCBTable[VOS_MODULE_ID_MAX];
+static tp_vos_state_info_cb vos_state_info_table[VOS_MODULE_ID_MAX];
+
 /*-------------------------------------------------------------------------
   Functions
   ------------------------------------------------------------------------*/
@@ -451,6 +453,15 @@
     }
 }
 
+void vos_register_debugcb_init()
+{
+    v_U8_t i;
+
+    for (i = 0; i < VOS_MODULE_ID_MAX; i++) {
+        vos_state_info_table[i] = NULL;
+    }
+}
+
 /*-----------------------------------------------------------------------------
   \brief vos_trace() - puts the messages in to ring-buffer
 
@@ -665,3 +676,28 @@
         spin_unlock(&ltraceLock);
     }
 }
+
+/**
+ * vos_register_debug_callback() - stores callback handlers to print
+ *                                                 state information
+ */
+void vos_register_debug_callback(VOS_MODULE_ID moduleID,
+                                      tp_vos_state_info_cb vos_state_infocb)
+{
+    vos_state_info_table[moduleID] = vos_state_infocb;
+}
+
+/**
+ * vos_state_info_dump_all() - it invokes callback of layer which registered
+ * its callback to print its state information.
+ * @cb_context: call back context to be passed
+ */
+void vos_state_info_dump_all()
+{
+    v_U8_t module;
+
+    for (module = 0; module < VOS_MODULE_ID_MAX; module++) {
+         if (NULL != vos_state_info_table[module])
+             vos_state_info_table[module]();
+    }
+}
diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c
index 2a714dd..0e05858 100644
--- a/CORE/WDA/src/wlan_qct_wda.c
+++ b/CORE/WDA/src/wlan_qct_wda.c
@@ -331,7 +331,49 @@
    return CONVERT_WDI2VOS_STATUS(status) ;
 }
 
+/**
+ * wda_state_info_dump() - prints state information of wda layer
+ */
+static void wda_state_info_dump(void)
+{
+    v_CONTEXT_t vos_ctx_ptr = NULL;
+    tWDA_CbContext *wda = NULL ;
 
+    VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+                                       "<------ %s " ,__func__);
+
+    /* Get the Global VOSS Context */
+    vos_ctx_ptr = vos_get_global_context(VOS_MODULE_ID_VOSS, NULL);
+
+    if (NULL != vos_ctx_ptr)
+        wda = (tWDA_CbContext *)vos_get_context( VOS_MODULE_ID_WDA,
+                                                            vos_ctx_ptr );
+    else {
+        VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_FATAL,
+                  "%s: Invalid Global VOSS Context", __func__);
+        VOS_ASSERT(0);
+        return;
+    }
+
+    if (NULL != wda)
+        VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+                   "wdaState: %d linkState: %d", wda->wdaState,
+                                                 wda->linkState);
+    else {
+        VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                           "%s: Invalid WDA Context", __func__);
+        VOS_ASSERT(0);
+    }
+}
+
+/**
+ * wda_register_debug_callback() - registration function for wda layer
+ * to print wda state information
+ */
+static void wda_register_debug_callback(void)
+{
+    vos_register_debug_callback(VOS_MODULE_ID_WDA, &wda_state_info_dump);
+}
 
 /*
  * FUNCTION: WDA_open
@@ -411,6 +453,9 @@
        */
       wdaContext->frameTransRequired = wdiDevCapability.bFrameXtlSupported;
    }
+
+   wda_register_debug_callback();
+
    return status;
 
 error:
diff --git a/CORE/WDI/CP/src/wlan_qct_wdi.c b/CORE/WDI/CP/src/wlan_qct_wdi.c
index 8370a51..d8d523e 100644
--- a/CORE/WDI/CP/src/wlan_qct_wdi.c
+++ b/CORE/WDI/CP/src/wlan_qct_wdi.c
@@ -1575,6 +1575,30 @@
   }
 }
 
+/**
+ * wdi_state_info_dump() - prints state information of wdi layer
+ */
+static void wdi_state_info_dump(void)
+{
+    WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
+                "%s pending commands: %d", __func__,
+                gWDICb.wptPendingQueue.count);
+    WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
+                "uGlobalState %d wdiExpectedResponse: %d",
+                gWDICb.uGlobalState, gWDICb.wdiExpectedResponse);
+}
+
+
+/**
+ * wdi_register_debug_callback() - registration function for wdi layer
+ * to print WDI state information
+  */
+static void wdi_register_debug_callback(void)
+{
+    vos_register_debug_callback(VOS_MODULE_ID_WDI, &wdi_state_info_dump);
+}
+
+
 /*========================================================================
 
                              INITIALIZATION APIs
@@ -1810,6 +1834,9 @@
   pWdiDevCapability->bFrameXtlSupported = eWLAN_PAL_FALSE;
   pWdiDevCapability->ucMaxSTASupported  = gWDICb.ucMaxStations;
   pWdiDevCapability->ucMaxBSSSupported  = gWDICb.ucMaxBssids;
+
+  wdi_register_debug_callback();
+
   return WDI_STATUS_SUCCESS;
 
   /* ERROR handlers