From d48f445b6e1225bdc79d7d08df4afe77e507f3de Mon Sep 17 00:00:00 2001
From: Carter Chen <carter.chen@infineon.com>
Date: Mon, 24 Feb 2025 23:28:29 -0600
Subject: [PATCH 2/7] brcmfmac: porting auth_status v2 for WPA3 roam fails

[Analysis]:
8950/H2 STA WPA3 roam fails because
when wpa3 external auth request event is sent.

the supplicant might not have the scan result of the target AP
as it is roam scan is triggered independent of supplicant.
If the supplicant doesn't find the Target AP in its scan results,
it uses Hunting and Pecking by default for SAE.

even when the WPA3 Target AP is supporting H2E.
it is leading to auth rejection from the Target AP.

[Fix]:
Update bss information of the Target AP with
which we are starting external auth to the cfg80211 layer.
If the supplicant doesn't find the Target AP in its scan results
it queries the cfg80211 layer for scan results.
Update new structure wl_auth_req_status_info_v2_t
for the auth request status event which
will carry the bss information of the target AP.

Fixes SWLINUX-5005

Signed-off-by: Carter Chen <carter.chen@infineon.com>
---
 .../broadcom/brcm80211/brcmfmac/cfg80211.c    | 64 +++++++++++++++----
 .../broadcom/brcm80211/brcmfmac/fwil_types.h  | 14 ++++
 2 files changed, 66 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index c1b043b..9e670fb 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -8401,23 +8401,63 @@ brcmf_notify_ext_auth_request(struct brcmf_if *ifp,
 	struct brcmf_auth_req_status_le *auth_req =
 		(struct brcmf_auth_req_status_le *)data;
 	s32 err = 0;
+	struct brcmf_auth_req_status_info_le_v2 *auth_req_v2 = NULL;
+	struct brcmf_bss_info_le *bi = NULL;
+	struct brcmf_cfg80211_info *cfg = drvr->config;
 
 	brcmf_dbg(INFO, "Enter: event %s (%d) received\n",
 		  brcmf_fweh_event_name(e->event_code), e->event_code);
 
-	if (e->datalen < sizeof(*auth_req)) {
-		bphy_err(drvr, "Event %s (%d) data too small. Ignore\n",
-			 brcmf_fweh_event_name(e->event_code), e->event_code);
-		return -EINVAL;
-	}
+	if (drvr->wlc_ver.wlc_ver_major > BRCMF_AUTH_STATUS_V2_FW_MAJOR ||
+	    (drvr->wlc_ver.wlc_ver_major == BRCMF_AUTH_STATUS_V2_FW_MAJOR &&
+	    drvr->wlc_ver.wlc_ver_minor >= BRCMF_AUTH_STATUS_V2_FW_MINOR)) {
+		auth_req_v2 = (struct brcmf_auth_req_status_info_le_v2 *)data;
+		if (e->datalen < sizeof(*auth_req_v2)) {
+			brcmf_err("Ext auth req event data too small. Ignoring event\n");
+			return -EINVAL;
+		}
+		/* Inform bss info to cfg80211 layer as during roaming
+		 * Supplicant might not have scan results,if scan results
+		 * are not found the SAE auth uses HNP by default and
+		 * Target AP will reject the connection.
+		 */
+		if (e->datalen > sizeof(*auth_req_v2)) {
+			bi = (struct brcmf_bss_info_le *)&auth_req_v2->bss_info_le;
+			if (bi) {
+				err = brcmf_inform_single_bss(cfg, bi);
+				if (err) {
+					brcmf_err("failed to update bss info, err=%d\n", err);
+					return err;
+				}
+			} else {
+				brcmf_err("External Auth request bss info is null\n");
+				return -EINVAL;
+			}
+		}
+		/* 10 ms delay to update results in cfg80211 */
+		brcmf_delay(10);
+		memset(&params, 0, sizeof(params));
+		params.action = NL80211_EXTERNAL_AUTH_START;
+		params.key_mgmt_suite = ntohl(WLAN_AKM_SUITE_SAE);
+		params.status = WLAN_STATUS_SUCCESS;
+		params.ssid.ssid_len = min_t(u32, IEEE80211_MAX_SSID_LEN, auth_req_v2->ssid_len);
+		memcpy(params.ssid.ssid, auth_req_v2->ssid, params.ssid.ssid_len);
+		memcpy(params.bssid, auth_req_v2->peer_mac, ETH_ALEN);
+	} else {
+		if (e->datalen < sizeof(*auth_req)) {
+			bphy_err(drvr, "Event %s (%d) data too small. Ignore\n",
+				 brcmf_fweh_event_name(e->event_code), e->event_code);
+			return -EINVAL;
+		}
 
-	memset(&params, 0, sizeof(params));
-	params.action = NL80211_EXTERNAL_AUTH_START;
-	params.key_mgmt_suite = ntohl(WLAN_AKM_SUITE_SAE);
-	params.status = WLAN_STATUS_SUCCESS;
-	params.ssid.ssid_len = min_t(u32, 32, le32_to_cpu(auth_req->ssid_len));
-	memcpy(params.ssid.ssid, auth_req->ssid, params.ssid.ssid_len);
-	memcpy(params.bssid, auth_req->peer_mac, ETH_ALEN);
+		memset(&params, 0, sizeof(params));
+		params.action = NL80211_EXTERNAL_AUTH_START;
+		params.key_mgmt_suite = ntohl(WLAN_AKM_SUITE_SAE);
+		params.status = WLAN_STATUS_SUCCESS;
+		params.ssid.ssid_len = min_t(u32, 32, le32_to_cpu(auth_req->ssid_len));
+		memcpy(params.ssid.ssid, auth_req->ssid, params.ssid.ssid_len);
+		memcpy(params.bssid, auth_req->peer_mac, ETH_ALEN);
+	}
 
 	err = cfg80211_external_auth_request(ifp->ndev, &params, GFP_ATOMIC);
 	if (err)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
index 5e4af8c..5efdd18 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
@@ -15,6 +15,9 @@
 #define BRCMF_AF_PARAM_V2_FW_MAJOR 13
 #define BRCMF_AF_PARAM_V2_FW_MINOR 2
 
+#define BRCMF_AUTH_STATUS_V2_FW_MAJOR 13
+#define BRCMF_AUTH_STATUS_V2_FW_MINOR 3
+
 /* ARP Offload feature flags for arp_ol iovar */
 #define BRCMF_ARP_OL_AGENT		0x00000001
 #define BRCMF_ARP_OL_SNOOP		0x00000002
@@ -685,6 +688,17 @@ struct brcmf_auth_req_status_le {
 	u8 pmkid[WLAN_PMKID_LEN];
 };
 
+struct brcmf_auth_req_status_info_le_v2 {
+	__le16	version;
+	__le16	len;
+	__le16  flags;
+	u8 peer_mac[ETH_ALEN];/* peer mac address */
+	__le32 ssid_len;
+	u8 ssid[IEEE80211_MAX_SSID_LEN];
+	u8 pmkid[WLAN_PMKID_LEN];
+	struct brcmf_bss_info_le bss_info_le[];
+};
+
 /**
  * struct brcmf_mf_params_le - management frame parameters for mgmt_frame iovar
  *
-- 
2.25.1

