wlan: Protect ROC ctx with mutex lock during ROC callback and timeout.

Multiple functions running in different thread context can access
the ROC context or alter its elements, after the roc context is
freed or its elements are altered by other functions which can
lead to crash or some other issues.

To address this, protect ROC context and its elements with mutex.
The possible scenarios addressed are during roc callback, roc
timeout and cancel roc.

CRs-Fixed: 901700
Change-Id: I8204dc984e2b0d3000febf12f6588d7112351d14
diff --git a/CORE/HDD/src/wlan_hdd_p2p.c b/CORE/HDD/src/wlan_hdd_p2p.c
index fe8e91d..705cb4e 100644
--- a/CORE/HDD/src/wlan_hdd_p2p.c
+++ b/CORE/HDD/src/wlan_hdd_p2p.c
@@ -173,22 +173,28 @@
 {
     hdd_adapter_t *pAdapter = (hdd_adapter_t*) pCtx;
     hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
-    hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
+    hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
     hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+    rem_on_channel_request_type_t req_type;
+
 
     if (pHddCtx == NULL)
     {
         hddLog(LOGE, "%s: Hdd Context is NULL", __func__);
         return eHAL_STATUS_FAILURE;
     }
-    if (pRemainChanCtx == NULL)
-    {
-       hddLog( LOGW,
-          "%s: No Rem on channel pending for which Rsp is received", __func__);
-       return eHAL_STATUS_SUCCESS;
-    }
 
     mutex_lock(&pHddCtx->roc_lock);
+
+    pRemainChanCtx = cfgState->remain_on_chan_ctx;
+    if (pRemainChanCtx == NULL)
+    {
+        hddLog( LOGW,
+                "%s: No Rem on channel pending for which Rsp is received", __func__);
+        mutex_unlock(&pHddCtx->roc_lock);
+        return eHAL_STATUS_SUCCESS;
+    }
+
     hddLog( VOS_TRACE_LEVEL_INFO,
             "Received ROC rsp (request type %d, channel %d, cookie %llu",
             pRemainChanCtx->rem_on_chan_request,
@@ -196,7 +202,6 @@
             pRemainChanCtx->cookie);
     vos_timer_stop(&pRemainChanCtx->hdd_remain_on_chan_timer);
     vos_timer_destroy(&pRemainChanCtx->hdd_remain_on_chan_timer);
-    mutex_unlock(&pHddCtx->roc_lock);
     if ( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
     {
         if( cfgState->buf )
@@ -220,6 +225,8 @@
         pAdapter->lastRocTs = vos_timer_get_system_time();
     }
 
+    req_type = pRemainChanCtx->rem_on_chan_request;
+    mutex_unlock(&pHddCtx->roc_lock);
 
     if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
          ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
@@ -227,7 +234,7 @@
        )
     {
         tANI_U8 sessionId = pAdapter->sessionId;
-        if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
+        if( REMAIN_ON_CHANNEL_REQUEST == req_type )
         {
             sme_DeregisterMgmtFrame(
                        hHal, sessionId,
@@ -242,12 +249,15 @@
                 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
                 NULL, 0 );
     }
-    if (pRemainChanCtx->action_pkt_buff.frame_ptr != NULL
-       && pRemainChanCtx->action_pkt_buff.frame_length != 0)
-    {
-        vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr);
-    }
     mutex_lock(&pHddCtx->roc_lock);
+    if ( pRemainChanCtx )
+    {
+        if (pRemainChanCtx->action_pkt_buff.frame_ptr != NULL
+                && pRemainChanCtx->action_pkt_buff.frame_length != 0)
+        {
+            vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr);
+        }
+    }
     vos_mem_free( pRemainChanCtx );
     pRemainChanCtx = NULL;
     cfgState->remain_on_chan_ctx = NULL;
@@ -438,7 +448,7 @@
 void wlan_hdd_remain_on_chan_timeout(void *data)
 {
     hdd_adapter_t *pAdapter = (hdd_adapter_t *)data;
-    hdd_remain_on_chan_ctx_t *pRemainChanCtx;
+    hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
     hdd_cfg80211_state_t *cfgState;
     hdd_context_t *pHddCtx;
 
@@ -449,13 +459,16 @@
     }
     pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
     cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
+    mutex_lock(&pHddCtx->roc_lock);
     pRemainChanCtx = cfgState->remain_on_chan_ctx;
+
     if (NULL == pRemainChanCtx)
     {
         hddLog( LOGE, FL("No Remain on channel is pending"));
+        mutex_unlock(&pHddCtx->roc_lock);
         return;
     }
-    mutex_lock(&pHddCtx->roc_lock);
+
     if ( TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress )
     {
         mutex_unlock(&pHddCtx->roc_lock);
@@ -947,7 +960,7 @@
 #endif
     hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
     hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
-    hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
+    hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
     hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
     int status;
     u64 cookie_dummy;
@@ -971,6 +984,7 @@
      * Need to check cookie and cancel accordingly
      */
     mutex_lock(&pHddCtx->roc_lock);
+    pRemainChanCtx = cfgState->remain_on_chan_ctx;
     if( (cfgState->remain_on_chan_ctx == NULL) ||
         (cfgState->remain_on_chan_ctx->cookie != cookie) )
     {