prima : Handling race condition in driver unload in FTM

wlan_hdd_process_ftm_cmd() function is called in one context
and try to post message to HAL, in the mean time the
wlan_hdd_ftm_close() is called in other context and unload
the driver which causes the crash some times.

Change-Id: I7b7cd4a3449ceb0e8973a37744f86ce67678b1a1
CRs-fixed: 631639
diff --git a/CORE/HDD/src/wlan_hdd_ftm.c b/CORE/HDD/src/wlan_hdd_ftm.c
index 16b818e..85e3cfa 100644
--- a/CORE/HDD/src/wlan_hdd_ftm.c
+++ b/CORE/HDD/src/wlan_hdd_ftm.c
@@ -1433,6 +1433,15 @@
         return VOS_STATUS_E_NOMEM;
     }
 
+    /*release the wlan_hdd_process_ftm_cmd(), if waiting for any response.*/
+    if (pHddCtx->ftm.IsCmdPending == TRUE)
+    {
+        if (vos_event_set(&pHddCtx->ftm.ftm_vos_event)!= VOS_STATUS_SUCCESS)
+        {
+            VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+                                      "%s: vos_event_set failed", __func__);
+        }
+    }
     if(WLAN_FTM_STARTED == pHddCtx->ftm.ftm_state)
     {
         VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
@@ -3078,6 +3087,15 @@
         hddLog(VOS_TRACE_LEVEL_ERROR,"%s: request buffer is null",__func__);
         return ;
     }
+
+    if (vos_is_load_unload_in_progress(VOS_MODULE_ID_HDD, NULL))
+    {
+        VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
+        "%s: Load/Unload in Progress. Ignoring FTM Command %d"
+        , __func__, pRequestBuf->ftmpkt.ftm_cmd_type);
+        return ;
+    }
+
     /*Save the received request*/
     pHddCtx->ftm.pRequestBuf = pRequestBuf;
 
@@ -3198,7 +3216,6 @@
 
         //HEXDUMP("Request:",(char*)pftm_data,cmd_len);
 
-        pHddCtx->ftm.IsCmdPending = TRUE;
 
         /*Post the command to the HAL*/
         if (wlan_ftm_postmsg(pftm_data, cmd_len) != VOS_STATUS_SUCCESS) {
@@ -3207,13 +3224,31 @@
             return;
 
         }
+        /*After successful posting of message the command should be pending*/
+        pHddCtx->ftm.IsCmdPending = TRUE;
+
         /*Wait here until you get the response from HAL*/
         if (vos_wait_single_event(&pHddCtx->ftm.ftm_vos_event, FTM_VOS_EVENT_WAIT_TIME)!= VOS_STATUS_SUCCESS)
         {
-            hddLog(VOS_TRACE_LEVEL_ERROR,
-               "%s: vos_wait_single_event failed",__func__);
+            hddLog(VOS_TRACE_LEVEL_ERROR,"%s: vos_wait_single_event failed",__func__);
+            pHddCtx->ftm.pResponseBuf->ftm_err_code = WLAN_FTM_FAILURE;
+            wlan_ftm_send_response(pHddCtx);
+            pHddCtx->ftm.IsCmdPending = FALSE;
             return;
         }
+        /*This check will handle the case where the completion is sent by
+          wlan_hdd_process_ftm_cmd() and not by the HAL*/
+        if (vos_is_load_unload_in_progress(VOS_MODULE_ID_HDD, NULL))
+        {
+            VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
+            "%s: Load/Unload in Progress. Ignoring FTM Command %d"
+            , __func__, pRequestBuf->ftmpkt.ftm_cmd_type);
+
+            pHddCtx->ftm.pResponseBuf->ftm_err_code = WLAN_FTM_FAILURE;
+            wlan_ftm_send_response(pHddCtx);
+            pHddCtx->ftm.IsCmdPending = FALSE;
+            return ;
+        }
 
         cmd_len = be16_to_cpu(pHddCtx->ftm.wnl->wmsg.length);