Files
build/patch/kernel/archive/sunxi-5.15/patches.cypress/0038-non-upstream-workaround-for-4373-USB-WMM-5.2.27-test.patch

159 lines
5.2 KiB
Diff

From e5ed9db2bf5a899639039f015869b89419855d79 Mon Sep 17 00:00:00 2001
From: Madhan Mohan R <madhanmohan.r@cypress.com>
Date: Fri, 4 Jan 2019 14:42:04 +0530
Subject: [PATCH 038/179] non-upstream: workaround for 4373 USB WMM 5.2.27 test
failure
With the addition of skb_orphan in the datapath, though the throughput
increases in TX path, it introduces an issue by removing the flowcontrol
from upper layer and allowing more data to flow for different access
category.
This workaround is to disable using skb_orphan when running multi-stream
data. This change will not be required in linux 4.15 and later versions.
We only use this feature when Linux version is less than 4.16.0.
Signed-off-by: Raveendran Somu <raveendran.somu@cypress.com>
Signed-off-by: Wright Feng <wright.feng@cypress.com>
Signed-off-by: Chi-hsien Lin <chi-hsien.lin@cypress.com>
---
.../broadcom/brcm80211/brcmfmac/bus.h | 4 ++
.../broadcom/brcm80211/brcmfmac/fwsignal.c | 46 +++++++++++++++++++
.../broadcom/brcm80211/brcmfmac/usb.c | 8 +++-
3 files changed, 57 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
index d2863bcf7f94..d78c2613d6f0 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
@@ -7,6 +7,7 @@
#define BRCMFMAC_BUS_H
#include "debug.h"
+#include <linux/version.h>
/* IDs of the 6 default common rings of msgbuf protocol */
#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT 0
@@ -152,6 +153,9 @@ struct brcmf_bus {
const struct brcmf_bus_ops *ops;
struct brcmf_bus_msgbuf *msgbuf;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0))
+ bool allow_skborphan;
+#endif
};
/*
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
index 19b0f318f93e..4a9d8fbac44c 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
@@ -502,6 +502,9 @@ struct brcmf_fws_info {
bool creditmap_received;
u8 mode;
bool avoid_queueing;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0))
+ int fifo_init_credit[BRCMF_FWS_FIFO_COUNT];
+#endif
};
#define BRCMF_FWS_TLV_DEF(name, id, len) \
@@ -1617,9 +1620,13 @@ static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp,
fws->fifo_credit_map |= 1 << i;
else
fws->fifo_credit_map &= ~(1 << i);
+
WARN_ONCE(fws->fifo_credit[i] < 0,
"fifo_credit[%d] is negative(%d)\n", i,
fws->fifo_credit[i]);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0))
+ fws->fifo_init_credit[i] = fws->fifo_credit[i];
+#endif
}
brcmf_fws_schedule_deq(fws);
brcmf_fws_unlock(fws);
@@ -2197,6 +2204,38 @@ void brcmf_fws_del_interface(struct brcmf_if *ifp)
brcmf_fws_unlock(fws);
}
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0))
+static bool brcmf_fws_ismultistream(struct brcmf_fws_info *fws)
+{
+ bool ret = false;
+ u8 credit_usage = 0;
+
+ /* Check only for BE, VI and VO traffic */
+ u32 delay_map = fws->fifo_delay_map &
+ ((1 << BRCMF_FWS_FIFO_AC_BE) |
+ (1 << BRCMF_FWS_FIFO_AC_VI) |
+ (1 << BRCMF_FWS_FIFO_AC_VO));
+
+ if (hweight_long(delay_map) > 1) {
+ ret = true;
+ } else {
+ if (fws->fifo_credit[BRCMF_FWS_FIFO_AC_BE] <
+ fws->fifo_init_credit[BRCMF_FWS_FIFO_AC_BE])
+ credit_usage++;
+ if (fws->fifo_credit[BRCMF_FWS_FIFO_AC_VI] <
+ fws->fifo_init_credit[BRCMF_FWS_FIFO_AC_VI])
+ credit_usage++;
+ if (fws->fifo_credit[BRCMF_FWS_FIFO_AC_VO] <
+ fws->fifo_init_credit[BRCMF_FWS_FIFO_AC_VO])
+ credit_usage++;
+
+ if (credit_usage > 1)
+ ret = true;
+ }
+ return ret;
+}
+#endif
+
static void brcmf_fws_dequeue_worker(struct work_struct *worker)
{
struct brcmf_fws_info *fws;
@@ -2210,6 +2249,13 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
fws = container_of(worker, struct brcmf_fws_info, fws_dequeue_work);
drvr = fws->drvr;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0))
+ if (brcmf_fws_ismultistream(fws))
+ drvr->bus_if->allow_skborphan = false;
+ else
+ drvr->bus_if->allow_skborphan = true;
+#endif
+
brcmf_fws_lock(fws);
for (fifo = BRCMF_FWS_FIFO_BCMC; fifo >= 0 && !fws->bus_flow_blocked;
fifo--) {
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
index 9b592094609c..65416ebb77bc 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
@@ -639,7 +639,10 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
goto fail;
}
- skb_orphan(skb);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0))
+ if (devinfo->bus_pub.bus->allow_skborphan)
+ skb_orphan(skb);
+#endif
req->skb = skb;
req->devinfo = devinfo;
usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->tx_pipe,
@@ -1287,6 +1290,9 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
bus->ops = &brcmf_usb_bus_ops;
bus->proto_type = BRCMF_PROTO_BCDC;
bus->always_use_fws_queue = true;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0))
+ bus->allow_skborphan = true;
+#endif
#ifdef CONFIG_PM
bus->wowl_supported = true;
#endif
--
2.17.1