wlan: Monitor Mode.

This change contains startup and exit interface
in case of monitor mode. The purpose of monitor
mode is for device to act as sniffer and recieve
all the packets. It also contains RX path
and conversion API from 80211 to 8023.

Change-Id: I1b946e7bc35870c188f5b5a809ab70c7d2ef554a
CRs-Fixed: 816464
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index 813427f..aa80d4d 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -804,9 +804,28 @@
    beacon_data_t *beacon;
 };
 
+#define NUM_FILTERS_SUPPORTED 1
+struct filter
+{
+   v_MACADDR_t macAddr;
+   v_BOOL_t isA1filter;
+   v_BOOL_t isA2filter;
+   v_BOOL_t isA3filter;
+};
+
 struct hdd_mon_ctx_s
 {
-   hdd_adapter_t *pAdapterForTx;
+  /* start or stop */
+   v_BOOL_t state;
+   /*Conversion of packet required or not*/
+   v_BOOL_t is80211to803ConReq;
+   v_U32_t ChannelNo;
+   v_U32_t ChannelBW;
+   v_BOOL_t crcCheckEnabled;
+   v_U8_t numOfMacFilters;
+   struct filter mmFilters[NUM_FILTERS_SUPPORTED];
+   v_U64_t typeSubtypeBitmap;
+   v_U64_t rsvd;
 };
 
 typedef struct hdd_scaninfo_s
@@ -1126,6 +1145,7 @@
 };
 
 #define WLAN_HDD_GET_STATION_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.station)
+#define WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.monitor)
 #define WLAN_HDD_GET_AP_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.ap)
 #define WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter)  (&(pAdapter)->sessionCtx.station.WextState)
 #define WLAN_HDD_GET_CTX(pAdapter) ((hdd_context_t*)pAdapter->pHddCtx)
@@ -1514,7 +1534,6 @@
                                        tANI_U8 sessionId,
                                        eCsrAbortReason reason);
 VOS_STATUS hdd_processSpoofMacAddrRequest(hdd_context_t *pHddCtx);
-void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter );
 void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter );
 
 void crda_regulatory_entry_default(v_U8_t *countryCode, int domain_id);
diff --git a/CORE/HDD/inc/wlan_hdd_tx_rx.h b/CORE/HDD/inc/wlan_hdd_tx_rx.h
index 7f2ced6..500a09f 100644
--- a/CORE/HDD/inc/wlan_hdd_tx_rx.h
+++ b/CORE/HDD/inc/wlan_hdd_tx_rx.h
@@ -288,6 +288,8 @@
 extern VOS_STATUS hdd_tx_low_resource_cbk( vos_pkt_t *pVosPacket, 
                                            v_VOID_t *userData );
 
+extern VOS_STATUS hdd_rx_packet_monitor_cbk(v_VOID_t *vosContext,vos_pkt_t *pVosPacket, int conversion);
+
 /**============================================================================
   @brief hdd_rx_packet_cbk() - Receive callback registered with TL.
   TL will call this to notify the HDD when a packet was received 
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 68298cd..f8ff768 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -5783,7 +5783,8 @@
                              | BIT(NL80211_IFTYPE_ADHOC)
                              | BIT(NL80211_IFTYPE_P2P_CLIENT)
                              | BIT(NL80211_IFTYPE_P2P_GO)
-                             | BIT(NL80211_IFTYPE_AP);
+                             | BIT(NL80211_IFTYPE_AP)
+                             | BIT(NL80211_IFTYPE_MONITOR);
 
     if( pCfg->advertiseConcurrentOperation )
     {
diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c
index 84d5526..2aafc0c 100644
--- a/CORE/HDD/src/wlan_hdd_hostapd.c
+++ b/CORE/HDD/src/wlan_hdd_hostapd.c
@@ -4852,8 +4852,6 @@
 
     set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
 
-    wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), pAdapter );
-
     return status;
 
 error_wmm_init:
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index 4f3ae49..7bea316 100755
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -4531,6 +4531,11 @@
     return ret;
 }
 
+int hdd_mon_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+  return 0;
+}
+
 #if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
 /**---------------------------------------------------------------------------
 
@@ -5460,8 +5465,6 @@
       return -EINVAL;
    }
 
-   netif_start_queue(dev);
-
    return 0;
 }
 
@@ -5476,6 +5479,11 @@
     return ret;
 }
 
+int hdd_mon_stop(struct net_device *dev)
+{
+  return 0;
+}
+
 /**---------------------------------------------------------------------------
 
   \brief __hdd_stop() - HDD stop function
@@ -6063,12 +6071,12 @@
  };
  static struct net_device_ops wlan_mon_drv_ops = {
       .ndo_open = hdd_mon_open,
-      .ndo_stop = hdd_stop,
+      .ndo_stop = hdd_mon_stop,
       .ndo_uninit = hdd_uninit,
       .ndo_start_xmit = hdd_mon_hard_start_xmit,  
       .ndo_tx_timeout = hdd_tx_timeout,
       .ndo_get_stats = hdd_stats,
-      .ndo_do_ioctl = hdd_ioctl,
+      .ndo_do_ioctl = hdd_mon_ioctl,
       .ndo_set_mac_address = hdd_set_mac_address,
  };
 
@@ -6444,22 +6452,16 @@
 
          hdd_unregister_hostapd(pAdapter, rtnl_held);
          hdd_set_conparam( 0 );
-         wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
          break;
       }
 
       case WLAN_HDD_MONITOR:
       {
-          hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
          if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
          {
             hdd_deinit_tx_rx( pAdapter );
             clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
          }
-         if(NULL != pAdapterforTx)
-         {
-            hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
-         }
          break;
       }
 
@@ -6747,6 +6749,20 @@
    }
    return status;
 }
+void hdd_init_mon_mode (hdd_adapter_t *pAdapter)
+ {
+    hdd_mon_ctx_t *pMonCtx = NULL;
+    pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter);
+
+    pMonCtx->state = 0;
+    pMonCtx->ChannelNo = 1;
+    pMonCtx->ChannelBW = 20;
+    pMonCtx->crcCheckEnabled = 0;
+    pMonCtx->typeSubtypeBitmap = 0xFFFFFFFFFFFF;
+    pMonCtx->is80211to803ConReq = 0;
+    pMonCtx->numOfMacFilters = 0;
+ }
+
 
 hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
                                  const char *iface_name, tSirMacAddr macAddr,
@@ -6903,34 +6919,32 @@
             return NULL;
          }
 
+         // Register wireless extensions
+         if( VOS_STATUS_SUCCESS !=  (status = hdd_register_wext(pAdapter->dev)))
+         {
+              hddLog(VOS_TRACE_LEVEL_FATAL,
+                   "hdd_register_wext() failed with status code %08d [x%08x]",
+                                                      status, status );
+              status = VOS_STATUS_E_FAILURE;
+         }
+
          pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR; 
          pAdapter->device_mode = session_type;
-         status = hdd_register_interface( pAdapter, rtnl_held );
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
          pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
 #else
          pAdapter->dev->open = hdd_mon_open;
          pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
+         pAdapter->dev->stop = hdd_mon_stop;
+         pAdapter->dev->do_ioctl = hdd_mon_ioctl;
 #endif
+         status = hdd_register_interface( pAdapter, rtnl_held );
+         hdd_init_mon_mode( pAdapter );
          hdd_init_tx_rx( pAdapter );
          set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
-         //Set adapter to be used for data tx. It will use either GO or softap.
-         pAdapter->sessionCtx.monitor.pAdapterForTx = 
-                           hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
-         if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
-         {
-            pAdapter->sessionCtx.monitor.pAdapterForTx = 
-                           hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
-         }
-         /* This workqueue will be used to transmit management packet over
-          * monitor interface. */
-         if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
-             hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
-             return NULL;
-         }
-
-         INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
-                   hdd_mon_tx_work_queue);
+         //Stop the Interface TX queue.
+         netif_tx_disable(pAdapter->dev);
+         netif_carrier_off(pAdapter->dev);
       }
          break;
       case WLAN_HDD_FTM:
@@ -7373,9 +7387,6 @@
          break;
 
       case WLAN_HDD_MONITOR:
-#ifdef WLAN_OPEN_SOURCE
-         cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
-#endif
          break;
 
       default:
@@ -7914,28 +7925,6 @@
 
 /**---------------------------------------------------------------------------
   
-  \brief hdd_set_monitor_tx_adapter() - 
-
-   This API initializes the adapter to be used while transmitting on monitor
-   adapter. 
-   
-  \param  - pHddCtx - Pointer to the HDD context.
-            pAdapter - Adapter that will used for TX. This can be NULL.
-  \return - None. 
-  --------------------------------------------------------------------------*/
-void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
-{
-   hdd_adapter_t *pMonAdapter;
-
-   pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
-
-   if( NULL != pMonAdapter )
-   {
-      pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
-   }
-}
-/**---------------------------------------------------------------------------
-  
   \brief hdd_get_operating_channel() -
 
    This API returns the operating channel of the requested device mode 
@@ -8207,6 +8196,55 @@
    spin_unlock(&hdd_context_lock);
 }
 
+void wlan_hdd_mon_close(hdd_context_t *pHddCtx)
+{
+    VOS_STATUS vosStatus;
+    v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
+    struct wiphy *wiphy = pHddCtx->wiphy;
+
+    hdd_adapter_t *pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_MONITOR);
+    if(pAdapter == NULL || pVosContext == NULL)
+    {
+        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pAdapter is NULL",__func__);
+        return ;
+    }
+   hdd_UnregisterWext(pAdapter->dev);
+
+   vos_mon_stop( pVosContext );
+
+   vosStatus = vos_sched_close( pVosContext );
+   if (!VOS_IS_STATUS_SUCCESS(vosStatus))    {
+      VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+         "%s: Failed to close VOSS Scheduler",__func__);
+      VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+   }
+
+   vosStatus = vos_nv_close();
+   if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+   {
+      VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+          "%s: Failed to close NV", __func__);
+      VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+   }
+
+   vos_close(pVosContext);
+
+   #ifdef WLAN_KD_READY_NOTIFIER
+       nl_srv_exit(pHddCtx->ptt_pid);
+   #else
+       nl_srv_exit();
+   #endif
+
+   if (pHddCtx->cfg_ini)
+   {
+       kfree(pHddCtx->cfg_ini);
+       pHddCtx->cfg_ini= NULL;
+   }
+   hdd_close_all_adapters( pHddCtx );
+
+   wiphy_free(wiphy) ;
+
+}
 /**---------------------------------------------------------------------------
 
   \brief hdd_wlan_exit() - HDD WLAN exit function
@@ -8232,7 +8270,13 @@
    ENTER();
 
 
-   if (VOS_FTM_MODE != hdd_get_conparam())
+   if (VOS_MONITOR_MODE == hdd_get_conparam())
+   {
+      hddLog(VOS_TRACE_LEVEL_ERROR,"%s: MONITOR MODE",__func__);
+      wlan_hdd_mon_close(pHddCtx);
+      return;
+   }
+   else if (VOS_FTM_MODE != hdd_get_conparam())
    {
       // Unloading, restart logic is no more required.
       wlan_hdd_restart_deinit(pHddCtx);
@@ -8959,6 +9003,91 @@
    return 0;
 }
 
+int wlan_hdd_mon_open(hdd_context_t *pHddCtx)
+{
+    VOS_STATUS status;
+    v_CONTEXT_t pVosContext= NULL;
+    hdd_adapter_t *pAdapter= NULL;
+
+    pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+
+    if (NULL == pVosContext)
+    {
+        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                    "%s: Trying to open VOSS without a PreOpen", __func__);
+        VOS_ASSERT(0);
+        return VOS_STATUS_E_FAILURE;
+    }
+
+   status = vos_nv_open();
+   if (!VOS_IS_STATUS_SUCCESS(status))
+   {
+       /* NV module cannot be initialized */
+       hddLog( VOS_TRACE_LEVEL_FATAL,
+                "%s: vos_nv_open failed", __func__);
+       return VOS_STATUS_E_FAILURE;
+   }
+
+   status = vos_init_wiphy_from_nv_bin();
+   if (!VOS_IS_STATUS_SUCCESS(status))
+   {
+       /* NV module cannot be initialized */
+       hddLog( VOS_TRACE_LEVEL_FATAL,
+               "%s: vos_init_wiphy failed", __func__);
+       goto err_vos_nv_close;
+   }
+
+   status = vos_open( &pVosContext, pHddCtx->parent_dev);
+   if ( !VOS_IS_STATUS_SUCCESS( status ))
+   {
+      hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
+      goto err_vos_nv_close;
+   }
+
+   status = vos_mon_start( pVosContext );
+   if ( !VOS_IS_STATUS_SUCCESS( status ) )
+   {
+      hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
+      goto err_vosclose;
+   }
+
+   WLANTL_SetMonRxCbk( pVosContext, hdd_rx_packet_monitor_cbk );
+   WDA_featureCapsExchange(pVosContext);
+   wcnss_wlan_set_drvdata(pHddCtx->parent_dev, pHddCtx);
+
+   pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_MONITOR, "wlan%d",
+         wlan_hdd_get_intf_addr(pHddCtx), FALSE );
+   if( pAdapter == NULL )
+   {
+      hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
+      goto err_close_adapter;
+   }
+
+   //Initialize the nlink service
+   if(nl_srv_init() != 0)
+   {
+      hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
+      goto err_close_adapter;
+   }
+   return VOS_STATUS_SUCCESS;
+
+err_close_adapter:
+   hdd_close_all_adapters( pHddCtx );
+   vos_mon_stop( pVosContext );
+err_vosclose:
+   status = vos_sched_close( pVosContext );
+   if (!VOS_IS_STATUS_SUCCESS(status))    {
+      VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+         "%s: Failed to close VOSS Scheduler", __func__);
+      VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
+   }
+   vos_close(pVosContext );
+
+err_vos_nv_close:
+   vos_nv_close();
+
+return status;
+}
 /**---------------------------------------------------------------------------
 
   \brief hdd_11d_scan_done - callback to be executed when 11d scan is
@@ -9300,6 +9429,19 @@
       return VOS_STATUS_SUCCESS;
    }
 
+   if( VOS_MONITOR_MODE == hdd_get_conparam())
+   {
+       if ( VOS_STATUS_SUCCESS != wlan_hdd_mon_open(pHddCtx))
+       {
+          hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_mon_open Failed",__func__);
+          goto err_free_hdd_context;
+       }
+       hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Driver loaded in Monitor Mode",__func__);
+       pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
+       vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
+       return VOS_STATUS_SUCCESS;
+   }
+
    //Open watchdog module
    if(pHddCtx->cfg_ini->fIsLogpEnabled)
    {
@@ -10210,6 +10352,15 @@
    {
       hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
    }
+   else if (VOS_MONITOR_MODE == hdd_get_conparam())
+   {
+       hddLog(VOS_TRACE_LEVEL_INFO,"%s: MONITOR MODE",__func__);
+       pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
+       vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
+       hdd_wlan_exit(pHddCtx);
+       vos_preClose( &pVosContext );
+      goto done;
+   }
    else
    {
       /* We wait for active entry threads to exit from driver
diff --git a/CORE/HDD/src/wlan_hdd_tx_rx.c b/CORE/HDD/src/wlan_hdd_tx_rx.c
index f9243e8..e62c67f 100644
--- a/CORE/HDD/src/wlan_hdd_tx_rx.c
+++ b/CORE/HDD/src/wlan_hdd_tx_rx.c
@@ -63,6 +63,7 @@
 #include "vos_utils.h"
 #include  "sapInternal.h"
 #include  "wlan_hdd_trace.h"
+#include  "wlan_qct_wda.h"
 /*--------------------------------------------------------------------------- 
   Preprocessor definitions and constants
   -------------------------------------------------------------------------*/ 
@@ -89,6 +90,29 @@
 #define HDD_TX_STALL_SSR_THRESHOLD_HIGH   13
 #define HDD_TX_STALL_RECOVERY_THRESHOLD HDD_TX_STALL_SSR_THRESHOLD - 2
 
+int gRatefromIdx[] = {
+ 10,20,55,100,
+ 10,20,55,110,
+ 60,90,120,180,240,360,480,540,
+ 65,130,195,260,390,520,585,650,
+ 72,144,217,289,434,578,650,722,
+ 65,130,195,260,390,520,585,650,
+ 135,270,405,540,810,1080,1215,1350,
+ 150,300,450,600,900,1200,1350,1500,
+ 135,270,405,540,810,1080,1215,1350,
+ 1350,1350,65,130,195,260,390, 520,
+ 585,650,780,1350,1350,1350,1350,1350,
+ 1350,1350,1350,1350,655,722,866,1350,
+ 1350,1350,135,270,405,540,810,1080,
+ 1215,1350,1350,1620,1800,1350,1350,1350,
+ 1350,1350,1350,1200,1350,1500,1350,1800,
+ 2000,1350, 292,585,877,1170,1755,2340,
+ 2632,2925,1350,3510,3900,1350,1350,1350,
+ 1350,1350,1350,1350,2925,3250,1350,3900,
+ 4333
+ };
+
+
 static DEFINE_RATELIMIT_STATE(hdd_tx_timeout_rs,                 \
                               HDD_TX_TIMEOUT_RATELIMIT_INTERVAL, \
                               HDD_TX_TIMEOUT_RATELIMIT_BURST);
@@ -461,158 +485,9 @@
 
 int hdd_mon_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-   v_U16_t rt_hdr_len;
-   struct ieee80211_hdr *hdr;
-   hdd_adapter_t *pPgBkAdapter, *pAdapter =  WLAN_HDD_GET_PRIV_PTR(dev);
-   struct ieee80211_radiotap_header *rtap_hdr =
-                        (struct ieee80211_radiotap_header *)skb->data;
-
-   /*Supplicant sends the EAPOL packet on monitor interface*/
-   pPgBkAdapter = pAdapter->sessionCtx.monitor.pAdapterForTx;    
-   if(pPgBkAdapter == NULL)
-   {
-      VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
-           "%s: No Adapter to piggy back. Dropping the pkt on monitor inf",
-                                                                 __func__);
-      goto fail; /* too short to be possibly valid */
-   }
- 
-   /* check if toal skb length is greater then radio tab header length of not */
-   if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
-      goto fail; /* too short to be possibly valid */
-   
-   /* check if radio tap header version is correct or not */
-   if (unlikely(rtap_hdr->it_version))
-      goto fail; /* only version 0 is supported */
- 
-   /*Strip off the radio tap header*/
-   rt_hdr_len = ieee80211_get_radiotap_len(skb->data);
- 
-   /* check if skb length if greator then total radio tap header length ot not*/
-   if (unlikely(skb->len < rt_hdr_len))
-      goto fail;
- 
-   /* Update the trans_start for this netdev */  
-   dev->trans_start = jiffies;
-   /*
-    * fix up the pointers accounting for the radiotap
-    * header still being in there.
-    */
-   skb_set_mac_header(skb, rt_hdr_len);
-   skb_set_network_header(skb, rt_hdr_len);
-   skb_set_transport_header(skb, rt_hdr_len); 
-
-   /* Pull rtap header out of the skb */
-   skb_pull(skb, rt_hdr_len);
-  
-   /*Supplicant adds: radiotap Hdr + radiotap data + 80211 Header. So after 
-    * radio tap header and 802.11 header starts 
-    */
-   hdr = (struct ieee80211_hdr *)skb->data;
- 
-   /* Send data frames through the normal Data path. In this path we will 
-    * conver rcvd 802.11 packet to 802.3 packet */
-   if ( (hdr->frame_control & HDD_FRAME_TYPE_MASK)  == HDD_FRAME_TYPE_DATA)
-   { 
-      v_U8_t da[6];
-      v_U8_t sa[6];
-
-      memcpy (da, hdr->addr1, VOS_MAC_ADDR_SIZE);
-      memcpy (sa, hdr->addr2, VOS_MAC_ADDR_SIZE);
- 
-      /* Pull 802.11 MAC header */ 
-      skb_pull(skb, HDD_80211_HEADER_LEN);
- 
-      if ( HDD_FRAME_SUBTYPE_QOSDATA == 
-          (hdr->frame_control & HDD_FRAME_SUBTYPE_MASK))
-      {
-         skb_pull(skb, HDD_80211_HEADER_QOS_CTL);
-      }
-
-      /* Pull LLC header */ 
-      skb_pull(skb, HDD_LLC_HDR_LEN);
-
-      /* Create space for Ethernet header */ 
-      skb_push(skb, HDD_MAC_HDR_SIZE*2);
-      memcpy(&skb->data[0], da, HDD_MAC_HDR_SIZE);
-      memcpy(&skb->data[HDD_DEST_ADDR_OFFSET], sa, HDD_MAC_HDR_SIZE);
-
-      /* Only EAPOL Data packets are allowed through monitor interface */ 
-      if (vos_be16_to_cpu(
-         (*(unsigned short*)&skb->data[HDD_ETHERTYPE_802_1_X_FRAME_OFFSET]) ) 
-                                                     != HDD_ETHERTYPE_802_1_X)
-      {
-         VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_FATAL,
-           "%s: Not a Eapol packet. Drop this frame", __func__);
-         //If not EAPOL frames, drop them.
-         kfree_skb(skb);
-         return NETDEV_TX_OK;
-      }
-
-      skb->protocol = htons(HDD_ETHERTYPE_802_1_X);
- 
-      hdd_hostapd_select_queue(pPgBkAdapter->dev, skb);
-      return hdd_softap_hard_start_xmit( skb, pPgBkAdapter->dev );
-   }
-   else
-   {
-      VOS_STATUS status;
-      WLANTL_ACEnumType ac = 0;
-      skb_list_node_t *pktNode = NULL;
-      v_SIZE_t pktListSize = 0;
-
-      spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
-      //If we have already reached the max queue size, disable the TX queue
-      if ( pAdapter->wmm_tx_queue[ac].count == pAdapter->wmm_tx_queue[ac].max_size)
-      {
-         /* We want to process one packet at a time, so lets disable all TX queues
-           * and re-enable the queues once we get TX feedback for this packet */
-         hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
-         netif_tx_stop_all_queues(pAdapter->dev);
-         pAdapter->isTxSuspended[ac] = VOS_TRUE;
-         spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);      
-         return NETDEV_TX_BUSY;   
-      }
-      spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);      
-
-      //Use the skb->cb field to hold the list node information
-      pktNode = (skb_list_node_t *)&skb->cb;
-
-      //Stick the OS packet inside this node.
-      pktNode->skb = skb;
-
-      INIT_LIST_HEAD(&pktNode->anchor);
-
-      //Insert the OS packet into the appropriate AC queue
-      spin_lock(&pAdapter->wmm_tx_queue[ac].lock);
-      status = hdd_list_insert_back_size( &pAdapter->wmm_tx_queue[ac],
-                                          &pktNode->anchor, &pktListSize );
-      spin_unlock(&pAdapter->wmm_tx_queue[ac].lock);
-
-      if ( !VOS_IS_STATUS_SUCCESS( status ) )
-      {
-         VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
-                "%s:Insert Tx queue failed. Pkt dropped", __func__);
-         kfree_skb(skb);
-         return NETDEV_TX_OK;
-      }
-
-      if ( pktListSize == 1 )
-      {
-         /* In this context we cannot acquire any mutex etc. And to transmit 
-          * this packet we need to call SME API. So to take care of this we will
-          * schedule a workqueue 
-          */
-         schedule_work(&pPgBkAdapter->monTxWorkQueue);
-      }
-      return NETDEV_TX_OK;
-   }
- 
-fail:
-   VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_WARN,
-           "%s: Packet Rcvd at Monitor interface is not proper,"
-           " Dropping the packet",
-            __func__);
+   VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
+           "%s: Packet Rcvd at Monitor interface,"
+             " Dropping the packet",__func__);
    kfree_skb(skb);
    return NETDEV_TX_OK;
 }
@@ -2440,6 +2315,138 @@
    return VOS_STATUS_SUCCESS;
 }
 
+static void hdd_mon_add_rx_radiotap_hdr (struct sk_buff *skb,
+             int rtap_len,  v_PVOID_t  pRxPacket, hdd_mon_ctx_t *pMonCtx)
+{
+    u8 rtap_temp[20] = {0};
+    struct ieee80211_radiotap_header *rthdr;
+    unsigned char *pos;
+    u16 rx_flags = 0;
+    u16 rateIdx;
+
+    rateIdx = WDA_GET_RX_MAC_RATE_IDX(pRxPacket);
+
+    rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]);
+
+    /* radiotap header, set always present flags */
+    rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS)   |
+                                    (1 << IEEE80211_RADIOTAP_CHANNEL) |
+                                    (1 << IEEE80211_RADIOTAP_RX_FLAGS));
+    rthdr->it_len = cpu_to_le16(rtap_len);
+
+    pos = (unsigned char *) (rthdr + 1);
+
+    /* IEEE80211_RADIOTAP_FLAGS */
+    *pos = 0;
+    pos++;
+
+    /* IEEE80211_RADIOTAP_RATE */
+    rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
+    *pos = gRatefromIdx[rateIdx]/5;
+
+    pos++;
+
+    /* IEEE80211_RADIOTAP_CHANNEL */
+    put_unaligned_le16(pMonCtx->ChannelNo, pos);
+    pos += 2;
+
+    if ((pos - (u8 *)rthdr) & 1)
+        pos++;
+    put_unaligned_le16(rx_flags, pos);
+    pos += 2;
+
+    memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len);
+}
+
+
+VOS_STATUS  hdd_rx_packet_monitor_cbk(v_VOID_t *vosContext,vos_pkt_t *pVosPacket, int conversion)
+{
+  struct sk_buff *skb = NULL;
+  VOS_STATUS status = VOS_STATUS_E_FAILURE;
+  hdd_adapter_t *pAdapter = NULL;
+  hdd_context_t *pHddCtx = NULL;
+  hdd_mon_ctx_t *pMonCtx = NULL;
+  v_PVOID_t pvBDHeader = NULL;
+  int rxstat;
+  int needed_headroom = 0;
+
+
+  //Sanity check on inputs
+   if ( ( NULL == vosContext ) ||
+        ( NULL == pVosPacket ) )
+   {
+      VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
+                         "%s: Null params being passed", __func__);
+      return VOS_STATUS_E_FAILURE;
+   }
+
+   pHddCtx = (hdd_context_t *)vos_get_context( VOS_MODULE_ID_HDD, vosContext );
+   pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_MONITOR);
+   if ((NULL == pAdapter)  || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) )
+   {
+      VOS_TRACE(VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
+                 FL("Invalid adapter %p for MONITOR MODE"), pAdapter);
+      vos_pkt_return_packet( pVosPacket );
+      return VOS_STATUS_E_FAILURE;
+   }
+
+    status =  WDA_DS_PeekRxPacketInfo( pVosPacket, (v_PVOID_t)&pvBDHeader, 1/*Swap BD*/ );
+    if ( NULL == pvBDHeader )
+    {
+      VOS_TRACE( VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
+                 "Cannot extract BD header");
+      /* Drop packet */
+      vos_pkt_return_packet(pVosPacket);
+      return VOS_STATUS_E_FAILURE;
+    }
+
+   ++pAdapter->hdd_stats.hddTxRxStats.rxChains;
+   status = vos_pkt_get_os_packet( pVosPacket, (v_VOID_t **)&skb, VOS_TRUE );
+   if(!VOS_IS_STATUS_SUCCESS( status ))
+    {
+        ++pAdapter->hdd_stats.hddTxRxStats.rxDropped;
+        VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,
+                               "%s: Failure extracting skb from vos pkt", __func__);
+        vos_pkt_return_packet( pVosPacket );
+        return VOS_STATUS_E_FAILURE;
+    }
+
+    if(!conversion)
+    {
+         pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter);
+         needed_headroom = sizeof(struct ieee80211_radiotap_header) + 9;
+         hdd_mon_add_rx_radiotap_hdr( skb, needed_headroom, pvBDHeader, pMonCtx );
+    }
+
+    skb_reset_mac_header( skb );
+    skb->dev = pAdapter->dev;
+    skb->pkt_type = PACKET_OTHERHOST;
+    skb->protocol = htons(ETH_P_802_2);
+    skb->ip_summed = CHECKSUM_NONE;
+    ++pAdapter->hdd_stats.hddTxRxStats.rxPackets;
+    ++pAdapter->stats.rx_packets;
+    pAdapter->stats.rx_bytes += skb->len;
+
+    rxstat = netif_rx_ni(skb);
+    if (NET_RX_SUCCESS == rxstat)
+    {
+       ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered;
+       ++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count;
+    }
+    else
+    {
+       ++pAdapter->hdd_stats.hddTxRxStats.rxRefused;
+    }
+
+   status = vos_pkt_return_packet( pVosPacket );
+   if(!VOS_IS_STATUS_SUCCESS( status ))
+   {
+      VOS_TRACE( VOS_MODULE_ID_HDD_DATA, VOS_TRACE_LEVEL_ERROR,"%s: Failure returning vos pkt", __func__);
+   }
+   pAdapter->dev->last_rx = jiffies;
+
+return status;
+}
 
 /**============================================================================
   @brief hdd_rx_packet_cbk() - Receive callback registered with TL.
diff --git a/CORE/TL/inc/wlan_qct_tl.h b/CORE/TL/inc/wlan_qct_tl.h
index 0a24b5a..4a4d895 100644
--- a/CORE/TL/inc/wlan_qct_tl.h
+++ b/CORE/TL/inc/wlan_qct_tl.h
@@ -691,6 +691,9 @@
                                             vos_pkt_t**           vosDataBuff,
                                             WLANTL_MetaInfoType*  tlMetaInfo);
 
+typedef VOS_STATUS (*WLANTL_MonRxCBType)( v_PVOID_t              pvosGCtx,
+                                          vos_pkt_t*             vosDataBuff,
+                                          int                    conversion);
 /*----------------------------------------------------------------------------
 
   DESCRIPTION   
@@ -1115,6 +1118,8 @@
   v_BOOL_t enableFrameXlation
 );
 
+VOS_STATUS WLANTL_SetMonRxCbk(v_PVOID_t pvosGCtx, WLANTL_MonRxCBType pfnMonRx);
+void WLANTL_SetIsConversionReq(v_PVOID_t pvosGCtx, v_BOOL_t isConversionReq);
 /*===========================================================================
 
   FUNCTION    WLANTL_RegisterSTAClient
diff --git a/CORE/TL/src/wlan_qct_tl.c b/CORE/TL/src/wlan_qct_tl.c
index 18648f3..10b5864 100644
--- a/CORE/TL/src/wlan_qct_tl.c
+++ b/CORE/TL/src/wlan_qct_tl.c
@@ -1735,6 +1735,34 @@
 
 }
 
+VOS_STATUS WLANTL_SetMonRxCbk(v_PVOID_t pvosGCtx, WLANTL_MonRxCBType pfnMonRx)
+{
+  WLANTL_CbType*  pTLCb = NULL ;
+  pTLCb = VOS_GET_TL_CB(pvosGCtx);
+  if ( NULL == pTLCb )
+  {
+    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+      "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_RegisterSTAClient"));
+    return VOS_STATUS_E_FAULT;
+  }
+  pTLCb->pfnMonRx = pfnMonRx;
+  return VOS_STATUS_SUCCESS;
+}
+
+void WLANTL_SetIsConversionReq(v_PVOID_t pvosGCtx, v_BOOL_t isConversionReq)
+{
+  WLANTL_CbType*  pTLCb = NULL ;
+  pTLCb = VOS_GET_TL_CB(pvosGCtx);
+  if ( NULL == pTLCb )
+  {
+    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+      "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_RegisterSTAClient"));
+    return;
+  }
+  pTLCb->isConversionReq = isConversionReq;
+  return;
+}
+
 
 /*===========================================================================
 
@@ -5751,6 +5779,16 @@
 
     vos_pkt_walk_packet_chain( vosDataBuff, &vosDataBuff, 1/*true*/ );
 
+    if( vos_get_conparam() == VOS_MONITOR_MODE )
+      {
+         if( pTLCb->isConversionReq )
+            WLANTL_MonTranslate80211To8023Header(vosTempBuff, pTLCb);
+
+         pTLCb->pfnMonRx(pvosGCtx, vosTempBuff, pTLCb->isConversionReq);
+         vosTempBuff = vosDataBuff;
+         continue;
+      }
+
     /*---------------------------------------------------------------------
       Peek at BD header - do not remove
       !!! Optimize me: only part of header is needed; not entire one
@@ -10246,6 +10284,119 @@
   return VOS_STATUS_SUCCESS;
 }/*WLANTL_Translate80211To8023Header*/
 
+VOS_STATUS
+WLANTL_MonTranslate80211To8023Header
+(
+  vos_pkt_t*      vosDataBuff,
+  WLANTL_CbType*  pTLCb
+)
+{
+   v_U16_t                  usMPDUDOffset;
+   v_U8_t                   ucMPDUHOffset;
+   v_U8_t                   ucMPDUHLen;
+   v_U16_t                  usActualHLen = 0;
+   v_U16_t                  usDataStartOffset = 0;
+   v_PVOID_t                aucBDHeader;
+   WLANTL_8023HeaderType    w8023Header;
+   WLANTL_80211HeaderType   w80211Header;
+   VOS_STATUS               vosStatus;
+   v_U8_t                   aucLLCHeader[WLANTL_LLC_HEADER_LEN];
+
+   WDA_DS_PeekRxPacketInfo( vosDataBuff, (v_PVOID_t)&aucBDHeader, 0 );
+   ucMPDUHOffset = (v_U8_t)WDA_GET_RX_MPDU_HEADER_OFFSET(aucBDHeader);
+   usMPDUDOffset = (v_U16_t)WDA_GET_RX_MPDU_DATA_OFFSET(aucBDHeader);
+   ucMPDUHLen    = (v_U8_t)WDA_GET_RX_MPDU_HEADER_LEN(aucBDHeader);
+   if (usMPDUDOffset > ucMPDUHOffset)
+   {
+      usActualHLen = usMPDUDOffset - ucMPDUHOffset;
+   }
+
+  if ( sizeof(w80211Header) < ucMPDUHLen )
+  {
+     TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
+       "Warning !: Check the header size for the Rx frame structure=%d received=%dn",
+       sizeof(w80211Header), ucMPDUHLen));
+     ucMPDUHLen = sizeof(w80211Header);
+  }
+
+  vosStatus = vos_pkt_pop_head( vosDataBuff, &w80211Header, ucMPDUHLen);
+  if ( VOS_STATUS_SUCCESS != vosStatus )
+  {
+     TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+                "WLAN TL: Failed to pop 80211 header from packet %d",
+                vosStatus));
+
+     return vosStatus;
+  }
+  switch ( w80211Header.wFrmCtrl.fromDS )
+  {
+  case 0:
+    if ( w80211Header.wFrmCtrl.toDS )
+    {
+      vos_mem_copy( w8023Header.vDA, w80211Header.vA3, VOS_MAC_ADDR_SIZE);
+      vos_mem_copy( w8023Header.vSA, w80211Header.vA2, VOS_MAC_ADDR_SIZE);
+      TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
+                  "WLAN TL SoftAP: 802 3 DA %08x SA %08x",
+                  w8023Header.vDA, w8023Header.vSA));
+    }
+    else
+    {
+      vos_mem_copy( w8023Header.vDA, w80211Header.vA1, VOS_MAC_ADDR_SIZE);
+      vos_mem_copy( w8023Header.vSA, w80211Header.vA2, VOS_MAC_ADDR_SIZE);
+    }
+    break;
+  case 1:
+    if ( w80211Header.wFrmCtrl.toDS )
+    {
+      vos_mem_copy( w8023Header.vDA, w80211Header.vA1, VOS_MAC_ADDR_SIZE);
+      vos_mem_copy( w8023Header.vSA, w80211Header.vA2, VOS_MAC_ADDR_SIZE);
+    }
+    else
+    {
+      vos_mem_copy( w8023Header.vDA, w80211Header.vA1, VOS_MAC_ADDR_SIZE);
+      vos_mem_copy( w8023Header.vSA, w80211Header.vA3, VOS_MAC_ADDR_SIZE);
+    }
+    break;
+  }
+  if( usActualHLen > ucMPDUHLen )
+  {
+     usDataStartOffset = usActualHLen - ucMPDUHLen;
+  }
+
+  if ( 0 < usDataStartOffset )
+  {
+    vosStatus = vos_pkt_trim_head( vosDataBuff, usDataStartOffset );
+
+    if ( VOS_STATUS_SUCCESS != vosStatus )
+    {
+      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+                  "WLAN TL: Failed to trim header from packet %d",
+                  vosStatus));
+      return vosStatus;
+    }
+  }
+   // Extract the LLC header
+   vosStatus = vos_pkt_pop_head( vosDataBuff, aucLLCHeader,
+                                 WLANTL_LLC_HEADER_LEN);
+
+   if ( VOS_STATUS_SUCCESS != vosStatus )
+   {
+      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
+                 "WLAN TL: Failed to pop LLC header from packet %d",
+                 vosStatus));
+
+      return vosStatus;
+   }
+
+   //Extract the length
+   vos_mem_copy(&w8023Header.usLenType,
+     &aucLLCHeader[WLANTL_LLC_HEADER_LEN - sizeof(w8023Header.usLenType)],
+     sizeof(w8023Header.usLenType) );
+
+   vos_pkt_push_head(vosDataBuff, &w8023Header, sizeof(w8023Header));
+   return VOS_STATUS_SUCCESS;
+}
+
 /*==========================================================================
   FUNCTION    WLANTL_FindFrameTypeBcMcUc
 
diff --git a/CORE/TL/src/wlan_qct_tli.h b/CORE/TL/src/wlan_qct_tli.h
index 220fbd2..af20126 100644
--- a/CORE/TL/src/wlan_qct_tli.h
+++ b/CORE/TL/src/wlan_qct_tli.h
@@ -890,6 +890,9 @@
   v_BOOL_t                  isBMPS;
   /* Whether WDA_DS_TX_START_XMIT msg is pending or not */
   v_BOOL_t   isTxTranmitMsgPending;
+  WLANTL_MonRxCBType           pfnMonRx;
+  v_BOOL_t              isConversionReq;
+
 }WLANTL_CbType;
 
 /*==========================================================================
@@ -1386,9 +1389,15 @@
   v_U8_t          ucHeaderLen,
   WLANTL_CbType*  pTLCb,
   v_U8_t          ucSTAId,
-  v_BOOL_t	  bForwardIAPPwithLLC
+  v_BOOL_t       bForwardIAPPwithLLC
 );
 
+VOS_STATUS
+WLANTL_MonTranslate80211To8023Header
+(
+  vos_pkt_t*      vosDataBuff,
+  WLANTL_CbType*  pTLCb
+);
 /*==========================================================================
   FUNCTION    WLANTL_FindFrameTypeBcMcUc
 
diff --git a/CORE/VOSS/inc/vos_api.h b/CORE/VOSS/inc/vos_api.h
index 0bb3c99..b0a802c 100644
--- a/CORE/VOSS/inc/vos_api.h
+++ b/CORE/VOSS/inc/vos_api.h
@@ -111,7 +111,9 @@
 
 VOS_STATUS vos_open( v_CONTEXT_t *pVosContext, void *devHandle );
 
+VOS_STATUS vos_mon_start( v_CONTEXT_t vosContext );
 
+VOS_STATUS vos_mon_stop( v_CONTEXT_t vosContext );
 
 VOS_STATUS vos_start( v_CONTEXT_t vosContext ); 
 
diff --git a/CORE/VOSS/src/vos_api.c b/CORE/VOSS/src/vos_api.c
index 1e24ce1..4326adc 100644
--- a/CORE/VOSS/src/vos_api.c
+++ b/CORE/VOSS/src/vos_api.c
@@ -589,6 +589,176 @@
    return VOS_STATUS_SUCCESS;
 }
 
+VOS_STATUS vos_mon_start( v_CONTEXT_t vosContext )
+{
+  VOS_STATUS vStatus          = VOS_STATUS_SUCCESS;
+  pVosContextType pVosContext = (pVosContextType)vosContext;
+
+  if (pVosContext == NULL)
+   {
+       VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+          "%s: mismatch in context",__func__);
+       return VOS_STATUS_E_FAILURE;
+   }
+
+  if (( pVosContext->pWDAContext == NULL) || ( pVosContext->pTLContext == NULL))
+  {
+     if (pVosContext->pWDAContext == NULL)
+        VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+            "%s: WDA NULL context", __func__);
+     else
+        VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+            "%s: TL NULL context", __func__);
+
+     return VOS_STATUS_E_FAILURE;
+  }
+
+   /* Reset wda wait event */
+   vos_event_reset(&pVosContext->wdaCompleteEvent);
+
+   /*call WDA pre start*/
+   vStatus = WDA_preStart(pVosContext);
+   if (!VOS_IS_STATUS_SUCCESS(vStatus))
+   {
+      VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR,
+             "Failed to WDA prestart ");
+      VOS_ASSERT(0);
+      return VOS_STATUS_E_FAILURE;
+   }
+
+   /* Need to update time out of complete */
+   vStatus = vos_wait_single_event( &pVosContext->wdaCompleteEvent, 1000);
+   if ( vStatus != VOS_STATUS_SUCCESS )
+   {
+      if ( vStatus == VOS_STATUS_E_TIMEOUT )
+      {
+         VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+          "%s: Timeout occurred before WDA complete",__func__);
+      }
+      else
+      {
+         VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+           "%s: WDA_preStart reporting  other error",__func__);
+      }
+      VOS_ASSERT( 0 );
+      return VOS_STATUS_E_FAILURE;
+   }
+
+    vStatus = WDA_NVDownload_Start(pVosContext);
+
+    if ( vStatus != VOS_STATUS_SUCCESS )
+    {
+       VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+                   "%s: Failed to start NV Download",__func__);
+       return VOS_STATUS_E_FAILURE;
+    }
+
+    vStatus = vos_wait_single_event(&(pVosContext->wdaCompleteEvent), 1000 * 30);
+
+    if ( vStatus != VOS_STATUS_SUCCESS )
+    {
+       if ( vStatus == VOS_STATUS_E_TIMEOUT )
+       {
+          VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+                     "%s: Timeout occurred before WDA_NVDownload_Start complete",__func__);
+       }
+       else
+       {
+         VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+                    "%s: WDA_NVDownload_Start reporting  other error",__func__);
+       }
+       VOS_ASSERT(0);
+       return VOS_STATUS_E_FAILURE;
+    }
+
+    vStatus = WDA_start(pVosContext);
+    if (vStatus != VOS_STATUS_SUCCESS)
+    {
+       VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+                 "%s: Failed to start WDA",__func__);
+       return VOS_STATUS_E_FAILURE;
+    }
+
+  /** START TL */
+  vStatus = WLANTL_Start(pVosContext);
+  if (!VOS_IS_STATUS_SUCCESS(vStatus))
+  {
+    VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
+               "%s: Failed to start TL", __func__);
+    goto err_wda_stop;
+  }
+
+  return VOS_STATUS_SUCCESS;
+
+err_wda_stop:
+   vos_event_reset(&(pVosContext->wdaCompleteEvent));
+   WDA_stop(pVosContext, HAL_STOP_TYPE_RF_KILL);
+   vStatus = vos_wait_single_event(&(pVosContext->wdaCompleteEvent), 1000);
+   if(vStatus != VOS_STATUS_SUCCESS)
+   {
+      if(vStatus == VOS_STATUS_E_TIMEOUT)
+      {
+         VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+                   "%s: Timeout occurred before WDA_stop complete",__func__);
+
+      }
+      else
+      {
+        VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+                  "%s: WDA_stop reporting  other error",__func__);
+      }
+      VOS_ASSERT(0);
+   }
+  return VOS_STATUS_E_FAILURE;
+}
+
+VOS_STATUS vos_mon_stop( v_CONTEXT_t vosContext )
+{
+  VOS_STATUS vosStatus;
+
+  vos_event_reset( &(gpVosContext->wdaCompleteEvent) );
+
+  vosStatus = WDA_stop( vosContext, HAL_STOP_TYPE_RF_KILL );
+
+  if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+  {
+     VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+         "%s: Failed to stop WDA", __func__);
+     VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+     WDA_setNeedShutdown(vosContext);
+  }
+  else
+  {
+    vosStatus = vos_wait_single_event( &(gpVosContext->wdaCompleteEvent),
+                                       VOS_WDA_STOP_TIMEOUT );
+
+    if ( vosStatus != VOS_STATUS_SUCCESS )
+    {
+       if ( vosStatus == VOS_STATUS_E_TIMEOUT )
+       {
+          VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+           "%s: Timeout occurred before WDA complete", __func__);
+       }
+       else
+       {
+          VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+           "%s: WDA_stop reporting other error", __func__ );
+       }
+       WDA_setNeedShutdown(vosContext);
+    }
+  }
+
+  vosStatus = WLANTL_Stop( vosContext );
+  if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+  {
+     VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+         "%s: Failed to stop TL", __func__);
+     VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
+  }
+
+  return VOS_STATUS_SUCCESS;
+}
+
 /*---------------------------------------------------------------------------
   
   \brief vos_start() - Start the Libra SW Modules