prima: extscan: Update extscan stop API

Add blocking mechanism for ext scan stop APIs at HDD layer
to avoid synchronization problems at HAL layer.

Change-Id: I3ab7ab587fe408523bd28f0cbd58c6a18a830a0c
CRs-Fixed: 834122
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index f618282..562036c 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -2596,52 +2596,35 @@
 {
     tpSirEXTScanStopRspParams pData = (tpSirEXTScanStopRspParams) pMsg;
     hdd_context_t *pHddCtx        = (hdd_context_t *)ctx;
-    struct sk_buff *skb           = NULL;
+    struct hdd_ext_scan_context *context;
 
     ENTER();
 
     if (wlan_hdd_validate_context(pHddCtx)){
         return;
     }
+
     if (!pMsg)
     {
         hddLog(VOS_TRACE_LEVEL_ERROR, FL("pMsg is null"));
         return;
     }
 
-    skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
-                                    NULL,
-#endif
-                                    EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
-                                    QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX,
-                                    GFP_KERNEL);
+    hddLog(VOS_TRACE_LEVEL_INFO, "Req Id %u Status %u", pData->requestId,
+                                                        pData->status);
 
-    if (!skb) {
-        hddLog(VOS_TRACE_LEVEL_ERROR,
-                  FL("cfg80211_vendor_event_alloc failed"));
-        return;
+    context = &pHddCtx->ext_scan_context;
+    spin_lock(&hdd_context_lock);
+    if (context->request_id == pData->requestId) {
+        context->response_status = pData->status ? -EINVAL : 0;
+        complete(&context->response_event);
     }
-    hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering "));
-    hddLog(VOS_TRACE_LEVEL_INFO, "Req Id (%u)", pData->requestId);
+    spin_unlock(&hdd_context_lock);
 
-    if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
-                         pData->requestId) ||
-        nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS, pData->status)) {
-        hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
-        goto nla_put_failure;
-    }
-
-    cfg80211_vendor_event(skb, GFP_KERNEL);
     EXIT();
     return;
-
-nla_put_failure:
-    kfree_skb(skb);
-    return;
 }
 
-
 static void wlan_hdd_cfg80211_extscan_set_bss_hotlist_rsp(void *ctx,
                                                         void *pMsg)
 {
@@ -4613,9 +4596,18 @@
     hdd_context_t *pHddCtx                  = wiphy_priv(wiphy);
     struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
     eHalStatus status;
+    int retval;
+    unsigned long rc;
+    struct hdd_ext_scan_context *context;
+    tANI_U32 request_id;
 
     ENTER();
 
+    if (VOS_FTM_MODE == hdd_get_conparam()) {
+        hddLog(LOGE, FL("Command not allowed in FTM mode"));
+        return -EINVAL;
+    }
+
     status = wlan_hdd_validate_context(pHddCtx);
     if (0 != status)
     {
@@ -4650,6 +4642,12 @@
     reqMsg.sessionId = pAdapter->sessionId;
     hddLog(VOS_TRACE_LEVEL_INFO, FL("Session Id (%d)"), reqMsg.sessionId);
 
+    context = &pHddCtx->ext_scan_context;
+    spin_lock(&hdd_context_lock);
+    INIT_COMPLETION(context->response_event);
+    context->request_id = request_id = reqMsg.sessionId;
+    spin_unlock(&hdd_context_lock);
+
     status = sme_EXTScanStop(pHddCtx->hHal, &reqMsg);
     if (!HAL_STATUS_SUCCESS(status)) {
         hddLog(VOS_TRACE_LEVEL_ERROR,
@@ -4657,6 +4655,24 @@
         return -EINVAL;
     }
 
+    /* request was sent -- wait for the response */
+    rc = wait_for_completion_timeout(&context->response_event,
+                 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
+
+    if (!rc) {
+        hddLog(LOGE, FL("sme_ExtScanStop timed out"));
+        retval = -ETIMEDOUT;
+    } else {
+        spin_lock(&hdd_context_lock);
+        if (context->request_id == request_id)
+            retval = context->response_status;
+        else
+            retval = -EINVAL;
+        spin_unlock(&hdd_context_lock);
+    }
+
+    return retval;
+
     EXIT();
     return 0;
 }