From 68e82f9f899997f6268fb6d9cc03fe82ea813c2c Mon Sep 17 00:00:00 2001
From: Carter Chen <carter.chen@infineon.com>
Date: Mon, 29 Apr 2024 04:11:00 -0500
Subject: [PATCH] non-upstream: provide the iw command to set/get value which
 maps to wl wnm command

iw command for wnm_wl_cap
- original read: wl wnm
- after read:
iw dev wlp58s0 vendor send 0x000319 0x1b 0xff 0xff

- original write: wl wnm 1
- after write:
iw dev wlp58s0 vendor send 0x000319 0x1b 0x05 0x05(MSB)

Signed-off-by: Carter Chen <carter.chen@infineon.com>
---
 .../broadcom/brcm80211/brcmfmac/vendor.c      |  9 ++++-
 .../broadcom/brcm80211/brcmfmac/vendor_ifx.c  | 37 ++++++++++++++++++-
 .../broadcom/brcm80211/brcmfmac/vendor_ifx.h  | 12 ++++--
 3 files changed, 51 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c
index ed618babc..853d0c383 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c
@@ -333,7 +333,7 @@ const struct wiphy_vendor_command brcmf_vendor_cmds[] = {
 			   (WIPHY_VENDOR_CMD_NEED_WDEV |
 				WIPHY_VENDOR_CMD_NEED_NETDEV),
 			ifx_vendor_attr_wnm_policy,
-			ifx_cfg80211_vndr_cmds_wnm),
+			ifx_cfg80211_vndr_cmds_wnm_max_idle),
 		.maxattr = IFX_VENDOR_ATTR_WNM_MAX
 	},
 	{
@@ -343,6 +343,13 @@ const struct wiphy_vendor_command brcmf_vendor_cmds[] = {
 			VENDOR_CMD_RAW_DATA,
 			ifx_cfg80211_vndr_cmds_hwcaps),
 	},
+	{
+		IFX_SUBCMD(WNM_WL_CAP,
+			   (WIPHY_VENDOR_CMD_NEED_WDEV |
+			    WIPHY_VENDOR_CMD_NEED_NETDEV),
+			   VENDOR_CMD_RAW_DATA,
+			   ifx_cfg80211_vndr_cmds_wnm_wl_cap)
+	},
 };
 
 const struct nl80211_vendor_cmd_info brcmf_vendor_events[] = {
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor_ifx.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor_ifx.c
index 0d704773e..a44f14792 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor_ifx.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor_ifx.c
@@ -627,8 +627,9 @@ int ifx_cfg80211_vndr_cmds_giantrx(struct wiphy *wiphy,
 	return ret;
 }
 
-int ifx_cfg80211_vndr_cmds_wnm(struct wiphy *wiphy,
-			       struct wireless_dev *wdev, const void  *data, int len)
+int ifx_cfg80211_vndr_cmds_wnm_max_idle(struct wiphy *wiphy,
+					struct wireless_dev *wdev,
+					const void  *data, int len)
 {
 	int tmp, attr_type = 0, wnm_param = 0, ret = 0;
 	const struct nlattr *attr_iter, *wnm_param_iter;
@@ -640,6 +641,7 @@ int ifx_cfg80211_vndr_cmds_wnm(struct wiphy *wiphy,
 
 	vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
 	ifp = vif->ifp;
+
 	nla_for_each_attr(attr_iter, data, len, tmp) {
 		attr_type = nla_type(attr_iter);
 
@@ -742,3 +744,34 @@ int ifx_cfg80211_vndr_cmds_hwcaps(struct wiphy *wiphy,
 
 	return ret;
 }
+
+int ifx_cfg80211_vndr_cmds_wnm_wl_cap(struct wiphy *wiphy,
+				      struct wireless_dev *wdev,
+				      const void *data, int len)
+{
+	int ret = 0;
+	struct brcmf_cfg80211_vif *vif;
+	struct brcmf_if *ifp;
+	int val = *(s32 *)data;
+	s32 buf = 0;
+
+	vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
+	ifp = vif->ifp;
+
+	if (val == 0xffff) {
+		ret = brcmf_fil_iovar_int_get(ifp, "wnm", &buf);
+		if (ret) {
+			brcmf_err("get wnm_wl_cap error:%d\n", ret);
+			return ret;
+		}
+
+		brcmf_dbg(INFO, "get wnm_wl_cap: %d\n", buf);
+		ifx_cfg80211_vndr_send_cmd_reply(wiphy, &buf, sizeof(int));
+	} else {
+		ret = brcmf_fil_iovar_int_set(ifp, "wnm", val);
+		if (ret)
+			brcmf_err("set wnm_wl_cap error:%d\n", ret);
+	}
+
+	return ret;
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor_ifx.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor_ifx.h
index d5e722cd8..944720fdd 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor_ifx.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor_ifx.h
@@ -142,7 +142,8 @@ enum ifx_nl80211_vendor_subcmds {
 	SCMD(RSV24)		= 24,
 	SCMD(WNM)		= 25,
 	SCMD(HWCAPS)		= 26,
-	SCMD(MAX)		= 27
+	SCMD(WNM_WL_CAP)	= 27,
+	SCMD(MAX)		= 28
 };
 
 /*
@@ -725,12 +726,15 @@ int ifx_cfg80211_vndr_cmds_mpc(struct wiphy *wiphy,
 int ifx_cfg80211_vndr_cmds_giantrx(struct wiphy *wiphy,
 				   struct wireless_dev *wdev,
 				   const void *data, int len);
-int ifx_cfg80211_vndr_cmds_wnm(struct wiphy *wiphy,
-			       struct wireless_dev *wdev,
-			       const void *data, int len);
+int ifx_cfg80211_vndr_cmds_wnm_max_idle(struct wiphy *wiphy,
+					struct wireless_dev *wdev,
+					const void *data, int len);
 int ifx_cfg80211_vndr_cmds_hwcaps(struct wiphy *wiphy,
 				  struct wireless_dev *wdev,
 				  const void *data, int len);
+int ifx_cfg80211_vndr_cmds_wnm_wl_cap(struct wiphy *wiphy,
+				      struct wireless_dev *wdev,
+				      const void *data, int len);
 
 #endif /* IFX_VENDOR_H */
 
-- 
2.39.5 (Apple Git-154)

