From f522b85f3e95c053521cdb969e0d0cdf8de69613 Mon Sep 17 00:00:00 2001
From: avishad verma <avishad.verma@infineon.com>
Date: Fri, 5 Jan 2024 06:45:59 -0600
Subject: [PATCH 275/296] brcmfmac: fix CERT-11N: Traffic Differentiation in
 Single BSS with 802.11n STA

Increased PSQ Size from 256 to 256*8.
Increased Low and High Watermark accordingly.
Added Module param to use the old config if required.

Issue:While running muliple streams of 2-BE and 1-VO,
It has been observed the PSQ LOW Watermark is reached.
Reason for reaching Low Mark is VO is borrowing all credits
from BE and BK, causing BE packets to accumulate in PSQ.
Netif queue is stopped once the PSQ Low watermark is reached.
During this queue stop period, PSQ will not be having any VO
packets, causing a drop in VO traffic and WMM test failure.
PSQ size is increased to avoid Netif queue stop.


Signed-off-by: avishad verma <avishad.verma@infineon.com>
---
 .../broadcom/brcm80211/brcmfmac/common.c      |  7 ++++
 .../broadcom/brcm80211/brcmfmac/common.h      |  1 +
 .../broadcom/brcm80211/brcmfmac/fwsignal.c    | 41 ++++++++++++++-----
 3 files changed, 38 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
index 8ef5837d3da0..b7480c7817f5 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
@@ -142,6 +142,10 @@ static int brcmf_idle_time_zero;
 module_param_named(idle_time_zero, brcmf_idle_time_zero, int, 0644);
 MODULE_PARM_DESC(idle_time_zero, "Set idle interval to zero");
 
+static int brcmf_short_psq;
+module_param_named(short_psq, brcmf_short_psq, int, 0);
+MODULE_PARM_DESC(short_psq, "Use shorter PS Queue");
+
 static struct brcmfmac_platform_data *brcmfmac_pdata;
 struct brcmf_mp_global_t brcmf_mp_global;
 
@@ -783,6 +787,7 @@ int brcmf_debugfs_param_read(struct seq_file *s, void *data)
 	seq_printf(s, "%-20s: %d\n", "txglomsz", brcmf_sdiod_txglomsz);
 	seq_printf(s, "%-20s: %d\n", "bt_over_sdio", !!brcmf_bt_over_sdio);
 	seq_printf(s, "%-20s: %d\n", "idle_time_zero", !!brcmf_idle_time_zero);
+	seq_printf(s, "%-20s: %d\n", "short_psq", !!brcmf_short_psq);
 
 	return 0;
 }
@@ -846,6 +851,8 @@ struct brcmf_mp_device *brcmf_get_module_param(struct device *dev,
 
 	settings->bt_over_sdio = !!brcmf_bt_over_sdio;
 	brcmf_dbg(INFO, "bt_over_sdio: %d\n", settings->bt_over_sdio);
+	settings->short_psq = !!brcmf_short_psq;
+	brcmf_dbg(INFO, "brcmf_short_psq: %d\n", settings->short_psq);
 
 	settings->idleclk_disable = brcmf_sdio_idleclk_disable;
 	brcmf_dbg(INFO, "idleclk_disable: %d\n", settings->idleclk_disable);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
index 422fe83793f4..f2fb78d7dddf 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
@@ -85,6 +85,7 @@ struct brcmf_mp_device {
 	unsigned int	offload_prof;
 	unsigned int	offload_feat;
 	bool		bt_over_sdio;
+	bool		short_psq;
 	struct brcmfmac_pd_cc *country_codes;
 	const char	*board_type;
 	unsigned char	mac[ETH_ALEN];
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
index b4a812543712..8b7cf9c1127a 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
@@ -149,11 +149,14 @@ static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id)
 
 #define BRCMF_FWS_HOSTIF_FLOWSTATE_OFF			0
 #define BRCMF_FWS_HOSTIF_FLOWSTATE_ON			1
-#define BRCMF_FWS_FLOWCONTROL_HIWATER			128
-#define BRCMF_FWS_FLOWCONTROL_LOWATER			64
+#define BRCMF_FWS_FLOWCONTROL_HIWATER			((256 * 8) - 256)
+#define BRCMF_FWS_FLOWCONTROL_LOWATER			256
+#define BRCMF_FWS_FLOWCONTROL_SHQUEUE_HIWATER		128
+#define BRCMF_FWS_FLOWCONTROL_SHQUEUE_LOWATER		64
 
 #define BRCMF_FWS_PSQ_PREC_COUNT		((BRCMF_FWS_FIFO_COUNT + 1) * 2)
-#define BRCMF_FWS_PSQ_LEN				256
+#define BRCMF_FWS_PSQ_LEN				(256 * 8)
+#define BRCMF_FWS_SHQUEUE_PSQ_LEN			256
 
 #define BRCMF_FWS_HTOD_FLAG_PKTFROMHOST			0x01
 #define BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED		0x02
@@ -505,6 +508,9 @@ struct brcmf_fws_info {
 #if (KERNEL_VERSION(4, 16, 0) > LINUX_VERSION_CODE)
 	int fifo_init_credit[BRCMF_FWS_FIFO_COUNT];
 #endif
+	int fws_psq_len;
+	int fws_psq_hi_water;
+	int fws_psq_low_water;
 };
 
 #define BRCMF_FWS_TLV_DEF(name, id, len) \
@@ -964,11 +970,11 @@ brcmf_fws_flow_control_check(struct brcmf_fws_info *fws, struct pktq *pq,
 		return;
 
 	if ((ifp->netif_stop & BRCMF_NETIF_STOP_REASON_FWS_FC) &&
-	    pq->len <= BRCMF_FWS_FLOWCONTROL_LOWATER)
+	    pq->len <= fws->fws_psq_low_water)
 		brcmf_txflowblock_if(ifp,
 				     BRCMF_NETIF_STOP_REASON_FWS_FC, false);
 	if (!(ifp->netif_stop & BRCMF_NETIF_STOP_REASON_FWS_FC) &&
-	    pq->len >= BRCMF_FWS_FLOWCONTROL_HIWATER) {
+	    pq->len >= fws->fws_psq_hi_water) {
 		fws->stats.fws_flow_block++;
 		brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_FWS_FC, true);
 	}
@@ -1014,8 +1020,9 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
 			entry->mac_handle = mac_handle;
 			brcmf_fws_macdesc_init(entry, addr, ifidx);
 			brcmf_fws_macdesc_set_name(fws, entry);
-			brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT,
-					BRCMF_FWS_PSQ_LEN);
+			brcmu_pktq_init(&entry->psq,
+					BRCMF_FWS_PSQ_PREC_COUNT,
+					fws->fws_psq_len);
 			brcmf_fws_unlock(fws);
 			brcmf_dbg(TRACE, "add %s mac %pM\n", entry->name, addr);
 		} else {
@@ -2177,8 +2184,9 @@ void brcmf_fws_add_interface(struct brcmf_if *ifp)
 	ifp->fws_desc = entry;
 	brcmf_fws_macdesc_init(entry, ifp->mac_addr, ifp->ifidx);
 	brcmf_fws_macdesc_set_name(fws, entry);
-	brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT,
-			BRCMF_FWS_PSQ_LEN);
+	brcmu_pktq_init(&entry->psq,
+			BRCMF_FWS_PSQ_PREC_COUNT,
+			fws->fws_psq_len);
 	brcmf_dbg(TRACE, "added %s\n", entry->name);
 }
 
@@ -2401,6 +2409,16 @@ struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr)
 	fws->drvr = drvr;
 	fws->fcmode = drvr->settings->fcmode;
 
+	if (drvr->settings->short_psq) {
+		fws->fws_psq_len = BRCMF_FWS_SHQUEUE_PSQ_LEN;
+		fws->fws_psq_hi_water = BRCMF_FWS_FLOWCONTROL_SHQUEUE_HIWATER;
+		fws->fws_psq_low_water = BRCMF_FWS_FLOWCONTROL_SHQUEUE_LOWATER;
+	} else {
+		fws->fws_psq_len = BRCMF_FWS_PSQ_LEN;
+		fws->fws_psq_hi_water = BRCMF_FWS_FLOWCONTROL_HIWATER;
+		fws->fws_psq_low_water = BRCMF_FWS_FLOWCONTROL_LOWATER;
+	}
+
 	if (!drvr->bus_if->always_use_fws_queue &&
 	    (fws->fcmode == BRCMF_FWS_FCMODE_NONE)) {
 		fws->avoid_queueing = true;
@@ -2468,8 +2486,9 @@ struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr)
 	brcmf_fws_macdesc_init(&fws->desc.other, NULL, 0);
 	brcmf_fws_macdesc_set_name(fws, &fws->desc.other);
 	brcmf_dbg(INFO, "added %s\n", fws->desc.other.name);
-	brcmu_pktq_init(&fws->desc.other.psq, BRCMF_FWS_PSQ_PREC_COUNT,
-			BRCMF_FWS_PSQ_LEN);
+	brcmu_pktq_init(&fws->desc.other.psq,
+			BRCMF_FWS_PSQ_PREC_COUNT,
+			fws->fws_psq_len);
 
 	brcmf_dbg(INFO, "%s bdcv2 tlv signaling [%x]\n",
 		  fws->fw_signals ? "enabled" : "disabled", tlv);
-- 
2.25.1

