Merge "wlan: Trigger/handle SAE using cfg80211" into wlan-driver.lnx.1.0
diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c
index b47942a..26be742 100644
--- a/CORE/HDD/src/wlan_hdd_assoc.c
+++ b/CORE/HDD/src/wlan_hdd_assoc.c
@@ -197,6 +197,53 @@
                                                 eRoamCmdStatus roamStatus,
                                                 eCsrRoamResult roamResult );
 
+#if defined(WLAN_FEATURE_SAE) && \
+	defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
+/**
+ * wlan_hdd_sae_callback() - Sends SAE info to supplicant
+ * @adapter: pointer adapter context
+ * @roam_info: pointer to roam info
+ *
+ * This API is used to send required SAE info to trigger SAE in supplicant.
+ *
+ * Return: None
+ */
+static void wlan_hdd_sae_callback(hdd_adapter_t *adapter,
+                                  tCsrRoamInfo *roam_info)
+{
+   hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+   int flags;
+   struct sir_sae_info *sae_info = roam_info->sae_info;
+   struct cfg80211_external_auth_params params = {0};
+
+   if (wlan_hdd_validate_context(hdd_ctx))
+       return;
+   if (!sae_info) {
+       hddLog(LOGE, FL("SAE info in NULL"));
+       return;
+   }
+   flags = vos_get_gfp_flags();
+
+   params.key_mgmt_suite = 0x00;
+   params.key_mgmt_suite |= 0x0F << 8;
+   params.key_mgmt_suite |= 0xAC << 16;
+   params.key_mgmt_suite |= 0x8 << 24;
+
+   params.action = NL80211_EXTERNAL_AUTH_START;
+   vos_mem_copy(params.bssid, sae_info->peer_mac_addr.bytes,
+                VOS_MAC_ADDR_SIZE);
+   vos_mem_copy(params.ssid.ssid, sae_info->ssid.ssId, sae_info->ssid.length);
+   params.ssid.ssid_len = sae_info->ssid.length;
+
+   cfg80211_external_auth_request(adapter->dev, &params, flags);
+   hddLog(LOG1, FL("SAE: sent cmd"));
+}
+#else
+static void wlan_hdd_sae_callback(hdd_adapter_t *adapter,
+                                  tCsrRoamInfo *roam_info)
+{ }
+#endif
+
 v_VOID_t hdd_connSetConnectionState( hdd_station_ctx_t *pHddStaCtx,
                                         eConnectionState connState )
 {
@@ -4333,6 +4380,12 @@
               else
                   hddLog(LOG1, FL("UPDATE_SCAN_RESULT returned NULL"));
          }
+
+       case eCSR_ROAM_SAE_COMPUTE:
+         if (pRoamInfo)
+             wlan_hdd_sae_callback(pAdapter, pRoamInfo);
+         break;
+
        case eCSR_ROAM_STA_CHANNEL_SWITCH:
          {
              hdd_adapter_t *pHostapdAdapter = NULL;
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 6a05948..a3ed21f 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -9141,7 +9141,8 @@
 }
 #endif
 
-#ifdef WLAN_FEATURE_SAE
+#if defined(WLAN_FEATURE_SAE) && \
+        defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
 /**
  * wlan_hdd_cfg80211_set_wiphy_sae_feature() - Indicates support of SAE feature
  * @wiphy: Pointer to wiphy
@@ -19507,6 +19508,64 @@
 }
 #endif
 
+#if defined(WLAN_FEATURE_SAE) && \
+         defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
+/**
+ * __wlan_hdd_cfg80211_external_auth() - Handle external auth
+ * @wiphy: Pointer to wireless phy
+ * @dev: net device
+ * @params: Pointer to external auth params
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+static int
+__wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy, struct net_device *dev,
+                                  struct cfg80211_external_auth_params *params)
+{
+   hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
+   hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+   int ret;
+
+   if (hdd_get_conparam() == VOS_FTM_MODE) {
+       hddLog(VOS_TRACE_LEVEL_ERROR, FL("Command not allowed in FTM mode"));
+       return -EPERM;
+   }
+
+   ret = wlan_hdd_validate_context(hdd_ctx);
+   if (ret)
+       return ret;
+
+   hddLog(VOS_TRACE_LEVEL_DEBUG, FL("external_auth status: %d"),
+          params->status);
+
+   sme_handle_sae_msg(hdd_ctx->hHal, adapter->sessionId, params->status);
+
+   return ret;
+}
+
+/**
+ * wlan_hdd_cfg80211_external_auth() - Handle external auth
+ * @wiphy: Pointer to wireless phy
+ * @dev: net device
+ * @params: Pointer to external auth params
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+static int
+wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
+                                struct net_device *dev,
+                                struct cfg80211_external_auth_params *params)
+{
+   int ret;
+
+   vos_ssr_protect(__func__);
+   ret = __wlan_hdd_cfg80211_external_auth(wiphy, dev, params);
+   vos_ssr_unprotect(__func__);
+
+   return ret;
+}
+#endif
+
 #if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
 static int __wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
                                              struct net_device *dev,
@@ -22548,5 +22607,9 @@
 	.channel_switch = wlan_hdd_cfg80211_channel_switch,
 #endif
 
+#if defined(WLAN_FEATURE_SAE) && \
+      defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
+      .external_auth = wlan_hdd_cfg80211_external_auth,
+#endif
 };
 
diff --git a/CORE/VOSS/src/vos_sched.c b/CORE/VOSS/src/vos_sched.c
index 19d6f0b..2fa2b6a 100644
--- a/CORE/VOSS/src/vos_sched.c
+++ b/CORE/VOSS/src/vos_sched.c
@@ -2226,3 +2226,13 @@
    vos_dump_stack(TX_Thread);
    vos_dump_stack(RX_Thread);
 }
+
+int vos_get_gfp_flags(void)
+{
+   int flags = GFP_KERNEL;
+
+   if (in_interrupt() || in_atomic() || irqs_disabled())
+      flags = GFP_ATOMIC;
+
+   return flags;
+}
diff --git a/CORE/VOSS/src/vos_sched.h b/CORE/VOSS/src/vos_sched.h
index 3a92a65..8d75a8b 100644
--- a/CORE/VOSS/src/vos_sched.h
+++ b/CORE/VOSS/src/vos_sched.h
@@ -550,5 +550,11 @@
 bool vos_is_wd_thread(int threadId);
 void vos_dump_stack(uint8_t value);
 void vos_dump_thread_stacks(int threadId);
-
+/**
+ * vos_get_gfp_flags(): get GFP flags
+ *
+ * Based on the scheduled context, return GFP flags
+ * Return: gfp flags
+ */
+int vos_get_gfp_flags(void);
 #endif // #if !defined __VOSS_SCHED_H