From edbe0e75f5ed8eb006cc6c187f6ddd0f6f9dd86a Mon Sep 17 00:00:00 2001
From: JasonHuang <Jason.Huang2@infineon.com>
Date: Mon, 29 Jan 2024 23:38:13 -0600
Subject: [PATCH 242/296] non-upstream: check and set default fcmode of the
 chip

This request came from Amazon facing some t-put issue. Default set
fcmode=2 and then clear fcmode if chip not support proptxstatus. We
can read current fcmode from /sys/kernel/debug/ieee80211/phy0/parameter

Signed-off-by: JasonHuang <Jason.Huang2@infineon.com>
---
 .../wireless/broadcom/brcm80211/brcmfmac/bus.h   | 10 ++++++++++
 .../broadcom/brcm80211/brcmfmac/common.c         |  7 +++++--
 .../wireless/broadcom/brcm80211/brcmfmac/core.c  |  5 +++++
 .../broadcom/brcm80211/brcmfmac/feature.c        |  1 +
 .../broadcom/brcm80211/brcmfmac/feature.h        |  3 ++-
 .../wireless/broadcom/brcm80211/brcmfmac/sdio.c  | 16 ++++++++++++++++
 6 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
index 1c336fde2d48..8c4e58d6f922 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
@@ -108,6 +108,7 @@ struct brcmf_bus_ops {
 	void (*debugfs_create)(struct device *dev);
 	int (*reset)(struct device *dev);
 	void (*remove)(struct device *dev);
+	int (*set_fcmode)(struct device *dev);
 };
 
 
@@ -312,6 +313,15 @@ static inline void brcmf_bus_remove(struct brcmf_bus *bus)
 	bus->ops->remove(bus->dev);
 }
 
+static inline
+int brcmf_bus_set_fcmode(struct brcmf_bus *bus)
+{
+	if (!bus->ops->set_fcmode)
+		return -EOPNOTSUPP;
+
+	return bus->ops->set_fcmode(bus->dev);
+}
+
 /*
  * interface functions from common layer
  */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
index 7225978788f3..b813217044d9 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
@@ -26,6 +26,7 @@
 #include <linux/reboot.h>
 #include <linux/notifier.h>
 #include "pcie.h"
+#include "sdio.h"
 
 MODULE_AUTHOR("Broadcom Corporation");
 MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
@@ -61,7 +62,7 @@ module_param_string(alternative_fw_path, brcmf_firmware_path,
 		    BRCMF_FW_ALTPATH_LEN, 0400);
 MODULE_PARM_DESC(alternative_fw_path, "Alternative firmware path");
 
-static int brcmf_fcmode;
+static int brcmf_fcmode = 2;
 module_param_named(fcmode, brcmf_fcmode, int, 0);
 MODULE_PARM_DESC(fcmode, "Mode of firmware signalled flow control");
 
@@ -736,12 +737,14 @@ static void brcmf_mp_attach(void)
 
 int brcmf_debugfs_param_read(struct seq_file *s, void *data)
 {
+	struct brcmf_bus *bus_if = dev_get_drvdata(s->private);
+
 	seq_printf(s, "%-20s: %s\n", "Name", "Value");
 	seq_printf(s, "%-20s: 0x%x\n", "debug", brcmf_msg_level);
 	seq_printf(s, "%-20s: %s\n", "alternative_fw_path", brcmf_firmware_path);
 	seq_printf(s, "%-20s: %d\n", "p2pon", !!brcmf_p2p_enable);
 	seq_printf(s, "%-20s: %d\n", "feature_disable", brcmf_feature_disable);
-	seq_printf(s, "%-20s: %d\n", "fcmode", brcmf_fcmode);
+	seq_printf(s, "%-20s: %d\n", "fcmode", bus_if->drvr->settings->fcmode);
 	seq_printf(s, "%-20s: %d\n", "roamoff", !!brcmf_roamoff);
 	seq_printf(s, "%-20s: %d\n", "iapp", !!brcmf_iapp_enable);
 	seq_printf(s, "%-20s: %d\n", "eap_restrict", !!brcmf_eap_restrict);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index 96a444438006..ad18635d6eb6 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -33,6 +33,7 @@
 #include "common.h"
 #include "twt.h"
 #include "bt_shared_sdio_ifx.h"
+#include "sdio.h"
 
 #define MAX_WAIT_FOR_8021X_TX			msecs_to_jiffies(950)
 
@@ -1594,6 +1595,10 @@ static int brcmf_bus_started(struct brcmf_pub *drvr, struct cfg80211_ops *ops)
 		goto fail;
 
 	brcmf_feat_attach(drvr);
+	ret = brcmf_bus_set_fcmode(bus_if);
+	/* Set fcmode = 0 for PCIe/USB */
+	if (ret < 0)
+		drvr->settings->fcmode = 0;
 
 	ret = brcmf_proto_init_done(drvr);
 	if (ret < 0)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
index 5832bf158737..7bf3f8f05eb6 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
@@ -50,6 +50,7 @@ static const struct brcmf_feat_fwcap brcmf_fwcap_map[] = {
 	{ BRCMF_FEAT_GCMP, "gcmp" },
 	{ BRCMF_FEAT_OFFLOADS, "offloads" },
 	{ BRCMF_FEAT_ULP, "ulp" },
+	{ BRCMF_FEAT_PROPTXSTATUS, "proptxstatus" },
 };
 
 #ifdef DEBUG
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
index 8ebe078193a4..112e035f9258 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
@@ -74,7 +74,8 @@
 	BRCMF_FEAT_DEF(GCMP) \
 	BRCMF_FEAT_DEF(TWT) \
 	BRCMF_FEAT_DEF(OFFLOADS) \
-	BRCMF_FEAT_DEF(ULP)
+	BRCMF_FEAT_DEF(ULP) \
+	BRCMF_FEAT_DEF(PROPTXSTATUS)
 
 /*
  * Quirks:
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index 11c60a1435d6..acc546f5554c 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -5218,6 +5218,7 @@ static int brcmf_sdio_bus_reset(struct device *dev)
 	return 0;
 }
 
+
 static void brcmf_sdio_bus_remove(struct device *dev)
 {
 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
@@ -5227,6 +5228,20 @@ static void brcmf_sdio_bus_remove(struct device *dev)
 	device_release_driver(&sdiod->func1->dev);
 }
 
+static int brcmf_sdio_bus_set_fcmode(struct device *dev)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+
+	if (!brcmf_feat_is_enabled(bus_if->drvr->iflist[0], BRCMF_FEAT_PROPTXSTATUS)) {
+		bus_if->drvr->settings->fcmode = 0;
+		sdiodev->settings->fcmode = bus_if->drvr->settings->fcmode;
+		brcmf_dbg(INFO, "Set fcmode = %d\n", sdiodev->settings->fcmode);
+	}
+
+	return sdiodev->settings->fcmode;
+}
+
 static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
 	.stop = brcmf_sdio_bus_stop,
 	.preinit = brcmf_sdio_bus_preinit,
@@ -5241,6 +5256,7 @@ static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
 	.debugfs_create = brcmf_sdio_debugfs_create,
 	.reset = brcmf_sdio_bus_reset,
 	.remove = brcmf_sdio_bus_remove,
+	.set_fcmode = brcmf_sdio_bus_set_fcmode
 };
 
 #define BRCMF_SDIO_FW_CODE	0
-- 
2.25.1

