From 6f7e7883c1ffc719e286245cd7ff1375bdb418c4 Mon Sep 17 00:00:00 2001
From: Carter Chen <carter.chen@infineon.com>
Date: Tue, 28 Nov 2023 20:19:05 -0600
Subject: [PATCH 209/301] non-upstream: new value for roamoff for report
 different event

while roamoff=1, the driver reports BCNLOST_MSG to cfg80211 layer as is.
the customer wants the driver reports DISCONNECTED event to instead.

introduced a new value roamoff=2, for this purpose.
while roamoff=2, once the driver got BCNLOST_MSG from firmware, it calls
cfg80211_disconnected function.


Signed-off-by: Carter Chen <carter.chen@infineon.com>
---
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index 82d605b95..fa051039b 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -8308,29 +8308,44 @@ brcmf_notify_beacon_loss(struct brcmf_if *ifp,
 	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
 	struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
 	struct cfg80211_bss *bss;
+	struct net_device *ndev = ifp->ndev;
 
 	brcmf_dbg(INFO, "Enter: event %s (%d), status=%d\n",
 		  brcmf_fweh_event_name(e->event_code), e->event_code,
 		  e->status);
 
-	if (!ifp->drvr->settings->roamoff)
-		return 0;
+	switch (ifp->drvr->settings->roamoff) {
+	case BRCMF_ROAMOFF_EN_BCNLOST_MSG:
+		/* On beacon loss event, Supplicant triggers new scan request
+		 * with NL80211_SCAN_FLAG_FLUSH Flag set, but lost AP bss entry
+		 * still remained as it is held by cfg as associated. Unlinking this
+		 * current BSS from cfg cached bss list on beacon loss event here,
+		 * would allow supplicant to receive new scanned entries
+		 * without current bss and select new bss to trigger roam.
+		 */
+		bss = cfg80211_get_bss(cfg->wiphy, NULL, profile->bssid, 0, 0,
+				       IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY_ANY);
+		if (bss) {
+			cfg80211_unlink_bss(cfg->wiphy, bss);
+			cfg80211_put_bss(cfg->wiphy, bss);
+		}
 
-	/* On beacon loss event, Supplicant triggers new scan request
-	 * with NL80211_SCAN_FLAG_FLUSH Flag set, but lost AP bss entry
-	 * still remained as it is held by cfg as associated. Unlinking this
-	 * current BSS from cfg cached bss list on beacon loss event here,
-	 * would allow supplicant to receive new scanned entries
-	 * without current bss and select new bss to trigger roam.
-	 */
-	bss = cfg80211_get_bss(cfg->wiphy, NULL, profile->bssid, 0, 0,
-			       IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY_ANY);
-	if (bss) {
-		cfg80211_unlink_bss(cfg->wiphy, bss);
-		cfg80211_put_bss(cfg->wiphy, bss);
-	}
+		cfg80211_cqm_beacon_loss_notify(cfg_to_ndev(cfg), GFP_KERNEL);
+		break;
+	case BRCMF_ROAMOFF_EN_DISCONNECT_EVT:
+		brcmf_link_down(ifp->vif,
+				WLAN_REASON_UNSPECIFIED,
+				true);
+		brcmf_init_prof(ndev_to_prof(ndev));
+		if (ndev != cfg_to_ndev(cfg))
+			complete(&cfg->vif_disabled);
+		brcmf_net_setcarrier(ifp, false);
+		break;
 
-	cfg80211_cqm_beacon_loss_notify(cfg_to_ndev(cfg), GFP_KERNEL);
+	case BRCMF_ROAMOFF_DISABLE:
+	default:
+		break;
+	}
 
 	return 0;
 }
@@ -8633,6 +8648,14 @@ static s32 brcmf_dongle_roam(struct brcmf_if *ifp)
 	__le32 roam_delta[2];
 
 	/* Configure beacon timeout value based upon roaming setting */
+	if (ifp->drvr->settings->roamoff < BRCMF_ROAMOFF_DISABLE ||
+	    ifp->drvr->settings->roamoff >= BRCMF_ROAMOFF_MAX) {
+		bphy_err(drvr,
+			 "roamoff setting is incorrect (%d), reset it\n",
+			 ifp->drvr->settings->roamoff);
+		ifp->drvr->settings->roamoff = BRCMF_ROAMOFF_DISABLE;
+	}
+
 	if (ifp->drvr->settings->roamoff)
 		bcn_timeout = BRCMF_DEFAULT_BCN_TIMEOUT_ROAM_OFF;
 	else
@@ -8646,10 +8669,10 @@ static s32 brcmf_dongle_roam(struct brcmf_if *ifp)
 	/* Enable/Disable built-in roaming to allow supplicant to take care of
 	 * roaming.
 	 */
-	brcmf_dbg(INFO, "Internal Roaming = %s\n",
-		  ifp->drvr->settings->roamoff ? "Off" : "On");
+	brcmf_dbg(INFO, "Internal Roaming = %s, Mode:%d\n",
+		  ifp->drvr->settings->roamoff ? "Off" : "On", ifp->drvr->settings->roamoff);
 	err = brcmf_fil_iovar_int_set(ifp, "roam_off",
-				      ifp->drvr->settings->roamoff);
+				      ifp->drvr->settings->roamoff ? 1 : 0);
 	if (err) {
 		bphy_err(drvr, "roam_off error (%d)\n", err);
 		goto roam_setup_done;
@@ -9618,7 +9641,7 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
 
 	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_TDLS))
 		wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
-	if (!ifp->drvr->settings->roamoff)
+	if (ifp->drvr->settings->roamoff == BRCMF_ROAMOFF_DISABLE)
 		wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
 	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_FWSUP)) {
 		wiphy_ext_feature_set(wiphy,
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
index 21660abd6..61cf90af1 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
@@ -67,7 +67,8 @@ MODULE_PARM_DESC(fcmode, "Mode of firmware signalled flow control");
 
 static int brcmf_roamoff;
 module_param_named(roamoff, brcmf_roamoff, int, 0400);
-MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine");
+MODULE_PARM_DESC(roamoff,
+		 "Do not use fw roaming engine: 0=use fw_roam, 1=fw_roam off & report BCNLOST_MSG, 2=fw_roam off & report DISCONNECTED");
 
 static int brcmf_iapp_enable;
 module_param_named(iapp, brcmf_iapp_enable, int, 0);
@@ -741,7 +742,7 @@ struct brcmf_mp_device *brcmf_get_module_param(struct device *dev,
 	settings->p2p_enable = !!brcmf_p2p_enable;
 	settings->feature_disable = brcmf_feature_disable;
 	settings->fcmode = brcmf_fcmode;
-	settings->roamoff = !!brcmf_roamoff;
+	settings->roamoff = brcmf_roamoff;
 	settings->iapp = !!brcmf_iapp_enable;
 	settings->eap_restrict = !!brcmf_eap_restrict;
 	settings->default_pm = !!brcmf_max_pm ? PM_MAX : PM_FAST;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
index c36479a9e..fc4ccae67 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
@@ -54,7 +54,7 @@ struct brcmf_mp_device {
 	bool		p2p_enable;
 	unsigned int	feature_disable;
 	int		fcmode;
-	bool		roamoff;
+	unsigned int	roamoff;
 	bool		iapp;
 	bool		eap_restrict;
 	int		default_pm;
@@ -78,6 +78,25 @@ struct brcmf_mp_device {
 	bool		pkt_prio;
 };
 
+/**
+ * enum brcmf_roamoff_mode - using fw roaming and report event mode if not use it.
+ *
+ * @BRCMF_ROAMOFF_DISABLE: use firmware roaming engine
+ * @BRCMF_ROAMOFF_EN_BCNLOST_MSG:
+ *	don't use firmware roaming engine, and report to cfg80211 layer by BCNLOST_MSG event
+ * @BRCMF_ROAMOFF_EN_DISCONNECT_EVT:
+ *	don't use firmware roaming engine, and report to cfg80211 layer by DISCONNECT event
+ * @BRCMF_ROAMOFF_MAX:
+ *	for sanity checking purpose.
+ */
+
+enum brcmf_roamoff_mode {
+	BRCMF_ROAMOFF_DISABLE = 0,
+	BRCMF_ROAMOFF_EN_BCNLOST_MSG = 1,
+	BRCMF_ROAMOFF_EN_DISCONNECT_EVT = 2,
+	BRCMF_ROAMOFF_MAX
+};
+
 void brcmf_c_set_joinpref_default(struct brcmf_if *ifp);
 
 struct brcmf_mp_device *brcmf_get_module_param(struct device *dev,
