From 3bbb5b150feb08bcfa6920c3a23df38d2e7b037a Mon Sep 17 00:00:00 2001 From: Madhan Mohan R Date: Fri, 4 Jan 2019 14:42:04 +0530 Subject: [PATCH 031/296] 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 Signed-off-by: Wright Feng Signed-off-by: Chi-hsien Lin --- .../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 dc756dbd0333..f7f3131bb8ba 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h @@ -10,6 +10,7 @@ #include #include #include "debug.h" +#include /* IDs of the 6 default common rings of msgbuf protocol */ #define BRCMF_H2D_MSGRING_CONTROL_SUBMIT 0 @@ -184,6 +185,9 @@ struct brcmf_bus { struct brcmf_bus_msgbuf *msgbuf; struct list_head list; +#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 36af81975855..3981ad62b888 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 6902f8773214..0b907ef4ab9e 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, @@ -1276,6 +1279,9 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo, bus->proto_type = BRCMF_PROTO_BCDC; bus->fwvid = fwvid; 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.25.1