From 4414d9d5879eb6f270a5abddbb47c551419c0b51 Mon Sep 17 00:00:00 2001
From: Ian Lin <ian.lin@infineon.com>
Date: Tue, 2 Jul 2024 21:29:20 -0500
Subject: [PATCH] brcmfmac: add new iovar format for action frame

A new parameter format of iovar "actframe" was applied
for 6G P2P feature which was introduced to H2.
The corresponding driver changes are:
- get interface version while chip initialization
- if the version matches particular one, apply new
parameter format of actframe

Signed-off-by: Ian Lin <ian.lin@infineon.com>
---
 .../broadcom/brcm80211/brcmfmac/cfg80211.c    |  2 +-
 .../broadcom/brcm80211/brcmfmac/cfg80211.h    |  2 ++
 .../broadcom/brcm80211/brcmfmac/common.c      | 16 +++++++++
 .../broadcom/brcm80211/brcmfmac/core.h        |  8 +++++
 .../broadcom/brcm80211/brcmfmac/fwil_types.h  | 14 ++++++++
 .../broadcom/brcm80211/brcmfmac/p2p.c         | 34 +++++++++++++------
 6 files changed, 64 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index 7469e04bf..5d6a11919 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -553,7 +553,7 @@ wl_cfgoce_has_ie(const u8 *ie, const u8 **tlvs, u32 *tlvs_len,
 	return false;
 }
 
-static u8 nl80211_band_to_fwil(enum nl80211_band band)
+u8 nl80211_band_to_fwil(enum nl80211_band band)
 {
 	switch (band) {
 	case NL80211_BAND_2GHZ:
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
index 9afe7a09f..b339dce79 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
@@ -485,6 +485,8 @@ brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_info *cfg)
 	return &cfg->conn_info;
 }
 
+u8 nl80211_band_to_fwil(enum nl80211_band band);
+
 struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
 						  struct cfg80211_ops *ops,
 						  bool p2pdev_forced);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
index a3b975a0f..ad993b555 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
@@ -442,6 +442,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
 	struct brcmf_bus *bus;
 	struct brcmf_rev_info_le revinfo;
 	struct brcmf_rev_info *ri;
+	struct brcmf_wlc_version_le wlc_ver;
 	char *clmver;
 	char *ptr;
 	s32 err;
@@ -556,6 +557,21 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
 	}
 	strscpy(ifp->drvr->fwver, ptr + 1, sizeof(ifp->drvr->fwver));
 
+	/* Get wlc interface version, set to 0 for legacy chip
+	 * that is not supporting wlc_ver iovar
+	 */
+	err = brcmf_fil_iovar_data_get(ifp, "wlc_ver", &wlc_ver, sizeof(wlc_ver));
+	if (err < 0) {
+		ifp->drvr->wlc_ver.wlc_ver_major = 0;
+		ifp->drvr->wlc_ver.wlc_ver_minor = 0;
+	} else {
+		ifp->drvr->wlc_ver.wlc_ver_major = le16_to_cpu(wlc_ver.wlc_ver_major);
+		ifp->drvr->wlc_ver.wlc_ver_minor = le16_to_cpu(wlc_ver.wlc_ver_minor);
+	}
+	brcmf_dbg(TRACE, "wlc interface version, major=%d, minor=%d\n",
+		  ifp->drvr->wlc_ver.wlc_ver_major,
+		  ifp->drvr->wlc_ver.wlc_ver_minor);
+
 	/* Query for 'clmver' to get CLM version info from firmware */
 	memset(buf, 0, sizeof(buf));
 	err = brcmf_fil_iovar_data_get(ifp, "clmver", buf, sizeof(buf));
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
index cb49d610b..608a787c2 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
@@ -97,6 +97,13 @@ struct brcmf_rev_info {
 	u32 nvramrev;
 };
 
+/** wlc interface version */
+struct brcmf_wlc_version {
+	/* wlc interface version numbers */
+	u16	wlc_ver_major;		/**< wlc interface major version number */
+	u16	wlc_ver_minor;		/**< wlc interface minor version number */
+};
+
 /* Common structure for module and instance linkage */
 struct brcmf_pub {
 	/* Linkage ponters */
@@ -132,6 +139,7 @@ struct brcmf_pub {
 	int req_mpc;
 
 	struct brcmf_rev_info revinfo;
+	struct brcmf_wlc_version wlc_ver;
 #ifdef DEBUG
 	struct dentry *dbgfs_dir;
 #endif
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
index 1ce30bc49..bf6b32104 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
@@ -12,6 +12,9 @@
 
 #define BRCMF_FIL_ACTION_FRAME_SIZE	1800
 
+#define BRCMF_AF_PARAM_V2_FW_MAJOR 13
+#define BRCMF_AF_PARAM_V2_FW_MINOR 2
+
 /* ARP Offload feature flags for arp_ol iovar */
 #define BRCMF_ARP_OL_AGENT		0x00000001
 #define BRCMF_ARP_OL_SNOOP		0x00000002
@@ -294,6 +297,17 @@ struct brcmf_fil_af_params_le {
 	struct brcmf_fil_action_frame_le	action_frame;
 };
 
+struct brcmf_fil_af_params_v2_le {
+	__le16					version;
+	__le16					length;
+	__le32					channel;
+	__le32					dwell_time;
+	u8					bssid[ETH_ALEN];
+	u8					band;
+	u8					pad[1];
+	struct brcmf_fil_action_frame_le	action_frame;
+};
+
 struct brcmf_fil_bss_enable_le {
 	__le32 bsscfgidx;
 	__le32 enable;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
index 24d9eb0fb..ae9b2c4fd 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
@@ -1572,8 +1572,9 @@ int brcmf_p2p_notify_action_tx_complete(struct brcmf_if *ifp,
  * brcmf_p2p_tx_action_frame() - send action frame over fil.
  *
  * @p2p: p2p info struct for vif.
+ * @vif: vif to send.
  * @af_params: action frame data/info.
- * @vif: vif to send
+ * @band: nl80211 band info.
  *
  * Send an action frame immediately without doing channel synchronization.
  *
@@ -1582,17 +1583,13 @@ int brcmf_p2p_notify_action_tx_complete(struct brcmf_if *ifp,
  * frame is transmitted.
  */
 static s32 brcmf_p2p_tx_action_frame(struct brcmf_p2p_info *p2p,
+				     struct brcmf_cfg80211_vif *vif,
 				     struct brcmf_fil_af_params_le *af_params,
-				     struct brcmf_cfg80211_vif *vif
-				     )
+				     u8 band)
 {
 	struct brcmf_pub *drvr = p2p->cfg->pub;
 	s32 err = 0;
-	struct brcmf_fil_action_frame_le *action_frame;
-	u16 action_frame_len;
-
-	action_frame = &af_params->action_frame;
-	action_frame_len = le16_to_cpu(action_frame->len);
+	struct brcmf_fil_af_params_v2_le af_params_v2;
 
 	brcmf_dbg(TRACE, "Enter\n");
 
@@ -1600,8 +1597,23 @@ static s32 brcmf_p2p_tx_action_frame(struct brcmf_p2p_info *p2p,
 	clear_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, &p2p->status);
 	clear_bit(BRCMF_P2P_STATUS_ACTION_TX_NOACK, &p2p->status);
 
-	err = brcmf_fil_bsscfg_data_set(vif->ifp, "actframe", af_params,
-					sizeof(*af_params));
+	if (drvr->wlc_ver.wlc_ver_major == BRCMF_AF_PARAM_V2_FW_MAJOR &&
+	    drvr->wlc_ver.wlc_ver_minor >= BRCMF_AF_PARAM_V2_FW_MINOR) {
+		/* set actframe iovar with af_params_v2 */
+		af_params_v2.band = nl80211_band_to_fwil(band);
+		af_params_v2.channel = af_params->channel;
+		af_params_v2.dwell_time = af_params->dwell_time;
+		memcpy(af_params_v2.bssid, af_params->bssid, ETH_ALEN);
+		af_params_v2.action_frame = af_params->action_frame;
+
+		err = brcmf_fil_bsscfg_data_set(vif->ifp, "actframe", &af_params_v2,
+						sizeof(af_params_v2));
+	} else {
+		/* set actframe iovar with af_params */
+		err = brcmf_fil_bsscfg_data_set(vif->ifp, "actframe", af_params,
+						sizeof(*af_params));
+	}
+
 	if (err) {
 		bphy_err(drvr, " sending action frame has failed\n");
 		goto exit;
@@ -1908,7 +1920,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg,
 		if (af_params->channel)
 			msleep(P2P_AF_RETRY_DELAY_TIME);
 
-		ack = !brcmf_p2p_tx_action_frame(p2p, af_params, vif);
+		ack = !brcmf_p2p_tx_action_frame(p2p, vif, af_params, peer_listen_chan->band);
 		tx_retry++;
 		dwell_overflow = brcmf_p2p_check_dwell_overflow(requested_dwell,
 								dwell_jiffies);
-- 
2.39.5 (Apple Git-154)

