wlan: Dump first RX packet details after host wakeup

Dump the packet type, source and destination MAC address, 802.11
type and subtype information for the first RX packet received after
the host wakeup. For 802.11 Data type packet dump information if
the packet received is whether ARP, DHCP or EAPOL packet.

Change-Id: Ia75df0ad4127acc510288edd212e7e91706323b4
CRs-Fixed: 1049180
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index f989f5a..f938a43 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -1431,6 +1431,7 @@
 
    
    v_BOOL_t hdd_wlan_suspended;
+   bool rx_wow_dump;
    
    spinlock_t filter_lock;
    
diff --git a/CORE/HDD/src/wlan_hdd_dev_pwr.c b/CORE/HDD/src/wlan_hdd_dev_pwr.c
index f319b4a..275eeaf 100644
--- a/CORE/HDD/src/wlan_hdd_dev_pwr.c
+++ b/CORE/HDD/src/wlan_hdd_dev_pwr.c
@@ -89,6 +89,7 @@
    /* TM Level 4, MAX TM level, enter IMPS */
    {0, 1, 1000, 500, 10}
 };
+
 #ifdef HAVE_WCNSS_SUSPEND_RESUME_NOTIFY
 static bool suspend_notify_sent;
 #endif
@@ -340,6 +341,7 @@
    /* Set the Station state as Suspended */
    pHddCtx->isWlanSuspended = TRUE;
    pHddCtx->last_suspend_success = 0;
+   pHddCtx->rx_wow_dump = true;
    hdd_wlan_suspend_resume_event(HDD_WLAN_SUSPEND);
    return 0;
 }
diff --git a/CORE/VOSS/inc/vos_api.h b/CORE/VOSS/inc/vos_api.h
index d659281..3cb282e 100644
--- a/CORE/VOSS/inc/vos_api.h
+++ b/CORE/VOSS/inc/vos_api.h
@@ -501,6 +501,9 @@
 v_BOOL_t vos_isUnloadInProgress(void);
 v_BOOL_t vos_isLoadUnloadInProgress(void);
 
+bool vos_get_rx_wow_dump(void);
+void vos_set_rx_wow_dump(bool value);
+
 void vos_probe_threads(void);
 void vos_per_pkt_stats_to_user(void *perPktStat);
 void vos_updatePktStatsInfo(void * pktStat);
diff --git a/CORE/VOSS/src/vos_api.c b/CORE/VOSS/src/vos_api.c
index 5c76002..747851f 100644
--- a/CORE/VOSS/src/vos_api.c
+++ b/CORE/VOSS/src/vos_api.c
@@ -3212,6 +3212,61 @@
 }
 
 /**
+ *vos_get_rx_wow_dump()
+ *
+ * Return true/flase to dump RX packet
+ *
+ */
+bool vos_get_rx_wow_dump(void)
+{
+    hdd_context_t *pHddCtx = NULL;
+    v_CONTEXT_t pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+
+    if(!pVosContext)
+    {
+       hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
+       return FALSE;
+    }
+
+    pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
+    if(!pHddCtx) {
+       VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+                "%s: HDD context is Null", __func__);
+       return FALSE;
+    }
+
+    return pHddCtx->rx_wow_dump;
+}
+
+/**
+ *vos_set_rx_wow_dump() - Set RX wow pkt dump
+ *@value: Value of RX wow pkt dump
+ *
+ * Return none.
+ *
+ */
+void vos_set_rx_wow_dump(bool value)
+{
+    hdd_context_t *pHddCtx = NULL;
+    v_CONTEXT_t pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+
+    if(!pVosContext)
+    {
+       hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
+       return;
+    }
+
+    pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
+    if(!pHddCtx) {
+       VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+                "%s: HDD context is Null", __func__);
+       return;
+    }
+
+    pHddCtx->rx_wow_dump = value;
+}
+
+/**
  * vos_probe_threads() - VOS API to post messages
  * to all the threads to detect if they are active or not
  *
diff --git a/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c b/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c
index 22c9a01..1480e54 100644
--- a/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c
+++ b/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c
@@ -80,6 +80,9 @@
 #define WDTS_MAX_PAGE_SIZE 4096
 #define WDTS_MAX_RXDB_DATA_SIZE 128
 
+#define MAC_ADDR_ARRAY(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+#define MAC_ADDRESS_STR "%02x:%02x:%02x:%02x:%02x:%02x"
+
 struct WDTS_RxPktInfo
 {
     uint8 rx_bd[WDTS_MAX_RXDB_DATA_SIZE];
@@ -586,6 +589,84 @@
     return;
 }
 
+/**
+ *WDTS_RxPacketDump - Dump Rx packet details
+ *@pFrame: pointer to first Rx buffer received
+ *@pRxMetadata: pointer to RX packet Meta Info
+ *
+ *DTS utility to dump RX packet details.
+ *
+ *Return: None.
+ */
+static void WDTS_RxPacketDump(vos_pkt_t *pFrame,
+                              WDI_DS_RxMetaInfoType *pRxMetadata)
+{
+    tpSirMacMgmtHdr pHdr;
+    struct sk_buff *skb = NULL;
+    uint8_t proto_type;
+    uint8_t flag = 0x0F;
+    wpt_status status;
+
+    if (NULL == pRxMetadata) {
+        VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_ERROR,
+                  "%s: RX Meta data info is NULL", __func__);
+        return;
+    }
+
+    pHdr = (tpSirMacMgmtHdr)pRxMetadata->mpduHeaderPtr;
+
+    /* RX packet type*/
+    if (pRxMetadata->bcast)
+         VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_ERROR,
+                   "%s RX Data frame is BC", __func__);
+    else if (pHdr->da[0] & 0x01)
+         VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_ERROR,
+                   "%s RX Data frame is MC", __func__);
+    else
+         VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_ERROR,
+                   "%s RX Data frame is UC", __func__);
+
+    /* 802.11 packet type, subtype */
+    if (WDI_MAC_MGMT_FRAME == pRxMetadata->type) {
+       VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_ERROR,
+                 "%s: Management subtype:%d SA:"MAC_ADDRESS_STR" DA:"
+                 MAC_ADDRESS_STR, __func__, pRxMetadata->subtype,
+                 MAC_ADDR_ARRAY(pHdr->sa), MAC_ADDR_ARRAY(pHdr->da));
+    } else if (WDI_MAC_CTRL_FRAME == pRxMetadata->type) {
+        VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_ERROR,
+                  "%s: Control subtype:%d SA:"MAC_ADDRESS_STR" DA:"
+                  MAC_ADDRESS_STR, __func__, pRxMetadata->subtype,
+                  MAC_ADDR_ARRAY(pHdr->sa), MAC_ADDR_ARRAY(pHdr->da));
+    } else if (WDI_MAC_DATA_FRAME == pRxMetadata->type) {
+        VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_ERROR,
+                  "%s: Data subtype:%d SA:"MAC_ADDRESS_STR" DA:"
+                  MAC_ADDRESS_STR, __func__, pRxMetadata->subtype,
+                  MAC_ADDR_ARRAY(pHdr->sa), MAC_ADDR_ARRAY(pHdr->da));
+
+        status = vos_pkt_get_os_packet(pFrame, (v_VOID_t **)&skb, 0);
+        if (eWLAN_PAL_STATUS_SUCCESS != status) {
+            VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_ERROR,
+                      "%s: Failure extracting skb from vos pkt", __func__);
+            return;
+        }
+
+        proto_type = vos_pkt_get_proto_type(skb, flag);
+        if (VOS_PKT_PROTO_TYPE_EAPOL & proto_type)
+           VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+                     "%s: RX frame is EAPOL", __func__);
+        else if (VOS_PKT_PROTO_TYPE_DHCP & proto_type)
+           VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+                     "%s: RX frame is DHCP", __func__);
+        else if (VOS_PKT_PROTO_TYPE_ARP & proto_type)
+           VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+                     "%s: RX frame is ARP", __func__);
+
+    } else
+        VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_ERROR,
+                  "%s: Unknown frame SA:"MAC_ADDRESS_STR,
+                   __func__, MAC_ADDR_ARRAY(pHdr->sa));
+}
+
 /* DTS Rx packet function. 
  * This function should be invoked by the transport device to indicate 
  * reception of a frame.
@@ -894,24 +975,31 @@
                vos_copy_80211_data(pFrame, rxStats.data, pRxMetadata->type);
           wpalPerPktSerialize(&rxStats);
       }
-      // Invoke Rx complete callback
-      pClientData->receiveFrameCB(pClientData->pCallbackContext, pFrame);  
+
+      /* Dump first Rx packet after host wakeup */
+      if (vos_get_rx_wow_dump()) {
+          WDTS_RxPacketDump((vos_pkt_t*)pFrame, pRxMetadata);
+          vos_set_rx_wow_dump(false);
+      }
+
+      /* Invoke Rx complete callback */
+      pClientData->receiveFrameCB(pClientData->pCallbackContext, pFrame);
   }
   else
   {
       wpalPacketSetRxLength(pFrame, usMPDULen+ucMPDUHOffset);
       wpalPacketRawTrimHead(pFrame, ucMPDUHOffset);
 
-      //flow control related
+      /* flow control related */
       pRxMetadata->fc = isFcBd;
       pRxMetadata->mclkRxTimestamp = WDI_RX_BD_GET_TIMESTAMP(pBDHeader);
       pRxMetadata->fcStaTxDisabledBitmap = WDI_RX_FC_BD_GET_STA_TX_DISABLED_BITMAP(pBDHeader);
       pRxMetadata->fcSTAValidMask = WDI_RX_FC_BD_GET_STA_VALID_MASK(pBDHeader);
-      // Invoke Rx complete callback
+      /* Invoke Rx complete callback */
       pClientData->receiveFrameCB(pClientData->pCallbackContext, pFrame);  
   }
 
-  //Log the RX Stats
+  /* Log the RX Stats */
   if(gDsTrafficStats.running && pRxMetadata->staId < HAL_NUM_STA)
   {
      if(pRxMetadata->rateIndex < WDTS_MAX_RATE_NUM)