prima: extscan: Update extscan capabilities.

1. Update structure tpSirEXTScanCapabilitiesEvent with
   more capabilities.
2. Add structure hdd_ext_scan_context which is used for
   implementing blocking mechanism.
3. Add blocking mechanism to send extscan capabilities
   to the upper layer in same context.
4. Remove Mtrace enum TRACE_CODE_SME_RX_HDD_EXTSCAN_
   GET_CAPABILITIES to avoid multiple Mtrace messages in
   sme_EXTScanGetCapabilities

Change-Id: If98d4e421098d558f1ba6f70a6e4d873d5c4463a
CRs-Fixed: 834122
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 0e1b326..704ea8b 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -2361,12 +2361,20 @@
                                                                      NLA_U32 },
 };
 
-static void wlan_hdd_cfg80211_extscan_get_capabilities_ind(void *ctx, void *pMsg)
+/**
+ * wlan_hdd_cfg80211_extscan_get_capabilities_rsp() - response from target
+ * @ctx: hdd global context
+ * @data: capabilities data
+ *
+ * Return: none
+ */
+static void
+wlan_hdd_cfg80211_extscan_get_capabilities_rsp(void *ctx, void *pMsg)
 {
+    struct hdd_ext_scan_context *context;
     hdd_context_t *pHddCtx  = (hdd_context_t *)ctx;
-    struct sk_buff *skb     = NULL;
-    tpSirEXTScanCapabilitiesEvent pData =
-                    (tpSirEXTScanCapabilitiesEvent) pMsg;
+    tSirEXTScanCapabilitiesEvent *data =
+                    (tSirEXTScanCapabilitiesEvent *) pMsg;
 
     ENTER();
 
@@ -2380,74 +2388,142 @@
         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_GET_CAPABILITIES_INDEX,
-                        GFP_KERNEL);
 
-    if (!skb) {
-        hddLog(VOS_TRACE_LEVEL_ERROR,
-                  FL("cfg80211_vendor_event_alloc failed"));
+    vos_spin_lock_acquire(&hdd_context_lock);
+
+    context = &pHddCtx->ext_scan_context;
+    /* validate response received from target*/
+    if (context->request_id != data->requestId)
+    {
+        vos_spin_lock_release(&hdd_context_lock);
+        hddLog(LOGE,
+          FL("Target response id did not match: request_id %d resposne_id %d"),
+          context->request_id, data->requestId);
         return;
     }
-
-    hddLog(VOS_TRACE_LEVEL_INFO, "Req Id (%u)", pData->requestId);
-    hddLog(VOS_TRACE_LEVEL_INFO, "Scan cache size (%u)", pData->scanCacheSize);
-    hddLog(VOS_TRACE_LEVEL_INFO, "Scan buckets (%u)", pData->scanBuckets);
-    hddLog(VOS_TRACE_LEVEL_INFO, "Max AP per scan (%u)", pData->maxApPerScan);
-    hddLog(VOS_TRACE_LEVEL_INFO, "maxRssiSampleSize (%u)",
-                                        pData->maxRssiSampleSize);
-    hddLog(VOS_TRACE_LEVEL_INFO, "maxScanReportingThreshold (%u)",
-                                        pData->maxScanReportingThreshold);
-    hddLog(VOS_TRACE_LEVEL_INFO, "maxHotlistAPs (%u)", pData->maxHotlistAPs);
-    hddLog(VOS_TRACE_LEVEL_INFO, "maxSignificantWifiChangeAPs (%u)",
-                                        pData->maxSignificantWifiChangeAPs);
-    hddLog(VOS_TRACE_LEVEL_INFO, "maxBsidHistoryEntries (%u)",
-                                        pData->maxBsidHistoryEntries);
-
-    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) ||
-        nla_put_u32(skb,
-           QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE,
-           pData->scanCacheSize) ||
-        nla_put_u32(skb,
-           QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS,
-           pData->scanBuckets) ||
-        nla_put_u32(skb,
-           QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN,
-           pData->maxApPerScan) ||
-        nla_put_u32(skb,
-           QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE,
-           pData->maxRssiSampleSize) ||
-        nla_put_u32(skb,
-           QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD,
-           pData->maxScanReportingThreshold) ||
-        nla_put_u32(skb,
-           QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_APS,
-           pData->maxHotlistAPs) ||
-        nla_put_u32(skb,
-           QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS,
-           pData->maxSignificantWifiChangeAPs) ||
-        nla_put_u32(skb,
-           QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES,
-           pData->maxBsidHistoryEntries)) {
-        hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
-        goto nla_put_failure;
+    else
+    {
+        context->capability_response = *data;
+        complete(&context->response_event);
     }
 
-    cfg80211_vendor_event(skb, GFP_KERNEL);
-    EXIT();
-    return;
+    vos_spin_lock_release(&hdd_context_lock);
 
-nla_put_failure:
-    kfree_skb(skb);
     return;
 }
 
+/*
+ * define short names for the global vendor params
+ * used by wlan_hdd_send_ext_scan_capability()
+ */
+#define PARAM_REQUEST_ID \
+    QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
+#define PARAM_STATUS \
+    QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS
+#define MAX_SCAN_CACHE_SIZE \
+    QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE
+#define MAX_SCAN_BUCKETS \
+    QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS
+#define MAX_AP_CACHE_PER_SCAN \
+    QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN
+#define MAX_RSSI_SAMPLE_SIZE \
+    QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE
+#define MAX_SCAN_RPT_THRHOLD \
+    QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD
+#define MAX_HOTLIST_BSSIDS \
+    QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS
+#define MAX_BSSID_HISTORY_ENTRIES \
+    QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES
+#define MAX_HOTLIST_SSIDS \
+    QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS
+
+static int wlan_hdd_send_ext_scan_capability(void *ctx)
+{
+    hdd_context_t *pHddCtx  = (hdd_context_t *)ctx;
+    struct sk_buff *skb     = NULL;
+    int ret;
+    tSirEXTScanCapabilitiesEvent *data;
+    tANI_U32 nl_buf_len;
+
+    ret = wlan_hdd_validate_context(pHddCtx);
+    if (0 != ret)
+    {
+        return ret;
+    }
+
+    data = &(pHddCtx->ext_scan_context.capability_response);
+
+    nl_buf_len = NLMSG_HDRLEN;
+    nl_buf_len += (sizeof(data->requestId) + NLA_HDRLEN) +
+    (sizeof(data->status) + NLA_HDRLEN) +
+    (sizeof(data->scanCacheSize) + NLA_HDRLEN) +
+    (sizeof(data->scanBuckets) + NLA_HDRLEN) +
+    (sizeof(data->maxApPerScan) + NLA_HDRLEN) +
+    (sizeof(data->maxRssiSampleSize) + NLA_HDRLEN) +
+    (sizeof(data->maxScanReportingThreshold) + NLA_HDRLEN) +
+    (sizeof(data->maxHotlistAPs) + NLA_HDRLEN) +
+    (sizeof(data->maxBsidHistoryEntries) + NLA_HDRLEN) +
+    (sizeof(data->maxHotlistSSIDs) + NLA_HDRLEN);
+
+    skb = cfg80211_vendor_cmd_alloc_reply_skb(pHddCtx->wiphy, nl_buf_len);
+
+    if (!skb)
+    {
+        hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
+        return -ENOMEM;
+    }
+
+    hddLog(LOG1, "Req Id (%u) Status (%u)", data->requestId, data->status);
+    hddLog(LOG1, "Scan cache size (%u) Scan buckets (%u) Max AP per scan (%u)",
+           data->scanCacheSize, data->scanBuckets, data->maxApPerScan);
+    hddLog(LOG1, "max_rssi_sample_size (%u) max_scan_reporting_threshold (%u)",
+           data->maxRssiSampleSize, data->maxScanReportingThreshold);
+    hddLog(LOG1, "max_hotlist_bssids (%u) max_bssid_history_entries (%u)"
+           "max_hotlist_ssids (%u)", data->maxHotlistAPs,
+           data->maxBsidHistoryEntries, data->maxHotlistSSIDs);
+
+    if (nla_put_u32(skb, PARAM_REQUEST_ID, data->requestId) ||
+        nla_put_u32(skb, PARAM_STATUS, data->status) ||
+        nla_put_u32(skb, MAX_SCAN_CACHE_SIZE, data->scanCacheSize) ||
+        nla_put_u32(skb, MAX_SCAN_BUCKETS, data->scanBuckets) ||
+        nla_put_u32(skb, MAX_AP_CACHE_PER_SCAN,
+            data->maxApPerScan) ||
+        nla_put_u32(skb, MAX_RSSI_SAMPLE_SIZE,
+            data->maxRssiSampleSize) ||
+        nla_put_u32(skb, MAX_SCAN_RPT_THRHOLD,
+            data->maxScanReportingThreshold) ||
+        nla_put_u32(skb, MAX_HOTLIST_BSSIDS, data->maxHotlistAPs) ||
+        nla_put_u32(skb, MAX_BSSID_HISTORY_ENTRIES,
+            data->maxBsidHistoryEntries) ||
+        nla_put_u32(skb, MAX_HOTLIST_SSIDS, data->maxHotlistSSIDs))
+    {
+        hddLog(LOGE, FL("nla put fail"));
+        goto nla_put_failure;
+    }
+
+    cfg80211_vendor_cmd_reply(skb);
+    return 0;
+
+nla_put_failure:
+    kfree_skb(skb);
+    return -EINVAL;;
+}
+
+/*
+ * done with short names for the global vendor params
+ * used by wlan_hdd_send_ext_scan_capability()
+ */
+#undef PARAM_REQUEST_ID
+#undef PARAM_STATUS
+#undef MAX_SCAN_CACHE_SIZE
+#undef MAX_SCAN_BUCKETS
+#undef MAX_AP_CACHE_PER_SCAN
+#undef MAX_RSSI_SAMPLE_SIZE
+#undef MAX_SCAN_RPT_THRHOLD
+#undef MAX_HOTLIST_BSSIDS
+#undef MAX_SIGNIFICANT_WIFI_CHANGE_APS
+#undef MAX_BSSID_HISTORY_ENTRIES
+#undef MAX_HOTLIST_SSIDS
 
 static void wlan_hdd_cfg80211_extscan_start_rsp(void *ctx, void *pMsg)
 {
@@ -3431,7 +3507,7 @@
         wlan_hdd_cfg80211_extscan_reset_signf_wifi_change_rsp(ctx, pMsg);
         break;
     case SIR_HAL_EXTSCAN_GET_CAPABILITIES_RSP:
-        wlan_hdd_cfg80211_extscan_get_capabilities_ind(ctx, pMsg);
+        wlan_hdd_cfg80211_extscan_get_capabilities_rsp(ctx, pMsg);
         break;
     case SIR_HAL_EXTSCAN_PROGRESS_IND:
         wlan_hdd_cfg80211_extscan_scan_progress_event(ctx, pMsg);
@@ -3469,6 +3545,9 @@
     struct nlattr
         *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
     eHalStatus status;
+    struct hdd_ext_scan_context *context;
+    unsigned long rc;
+    int ret;
 
     ENTER();
 
@@ -3499,7 +3578,6 @@
         return -EINVAL;
     }
 
-
     reqMsg.requestId = nla_get_u32(
               tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
     hddLog(VOS_TRACE_LEVEL_INFO, FL("Req Id (%d)"), reqMsg.requestId);
@@ -3507,12 +3585,32 @@
     reqMsg.sessionId = pAdapter->sessionId;
     hddLog(VOS_TRACE_LEVEL_INFO, FL("Session Id (%d)"), reqMsg.sessionId);
 
+    vos_spin_lock_acquire(&hdd_context_lock);
+    context = &pHddCtx->ext_scan_context;
+    context->request_id = reqMsg.requestId;
+    INIT_COMPLETION(context->response_event);
+    vos_spin_lock_release(&hdd_context_lock);
+
     status = sme_EXTScanGetCapabilities(pHddCtx->hHal, &reqMsg);
     if (!HAL_STATUS_SUCCESS(status)) {
         hddLog(VOS_TRACE_LEVEL_ERROR,
                FL("sme_EXTScanGetCapabilities failed(err=%d)"), status);
         return -EINVAL;
     }
+
+    rc = wait_for_completion_timeout(&context->response_event,
+             msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
+    if (!rc) {
+        hddLog(LOGE, FL("Target response timed out"));
+        return -ETIMEDOUT;
+    }
+
+    ret = wlan_hdd_send_ext_scan_capability(pHddCtx);
+    if (ret)
+        hddLog(LOGE, FL("Failed to send ext scan capability to user space"));
+
+    return ret;
+
     EXIT();
     return 0;
 }