summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
diff options
context:
space:
mode:
authorHante Meuleman2013-06-06 13:17:48 +0200
committerJohn W. Linville2013-06-12 21:02:16 +0200
commitdf50f756966cc07addaae5449a6fd45a17bdb06c (patch)
treee0a8ac79d0241bd1293e61d2bf061753bbf8deaf /drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
parentbrcmfmac: remove fifo bitfield from brcmf_skbuff_cb::if_flags (diff)
downloadkernel-qcow2-linux-df50f756966cc07addaae5449a6fd45a17bdb06c.tar.gz
kernel-qcow2-linux-df50f756966cc07addaae5449a6fd45a17bdb06c.tar.xz
kernel-qcow2-linux-df50f756966cc07addaae5449a6fd45a17bdb06c.zip
brcmfmac: Take bus flowcontrol at credit mgmt into account.
On bus flow control (no more host bus resources to send packets to device) the netif flow control was toggled, however credit management should also take this status into account. Since there are multiple sources handling this flow control necessary spinlocks were added to protect flow control related data/states. Reviewed-by: Arend Van Spriel <arend@broadcom.com> Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Signed-off-by: Hante Meuleman <meuleman@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
index bc2edc04e525..c1930ef5c55f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -431,6 +431,7 @@ struct brcmf_fws_info {
u32 fifo_credit_map;
u32 fifo_delay_map;
unsigned long borrow_defer_timestamp;
+ bool bus_flow_blocked;
};
/*
@@ -1833,6 +1834,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
brcmf_fws_lock(drvr, flags);
if (skcb->mac->suppressed ||
+ fws->bus_flow_blocked ||
brcmf_fws_mac_desc_closed(fws, skcb->mac, fifo) ||
brcmu_pktq_mlen(&skcb->mac->psq, 3 << (fifo * 2)) ||
(!multicast &&
@@ -1905,7 +1907,8 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
brcmf_dbg(TRACE, "enter: fws=%p\n", fws);
brcmf_fws_lock(fws->drvr, flags);
- for (fifo = NL80211_NUM_ACS; fifo >= 0; fifo--) {
+ for (fifo = NL80211_NUM_ACS; fifo >= 0 && !fws->bus_flow_blocked;
+ fifo--) {
brcmf_dbg(TRACE, "fifo %d credit %d\n", fifo,
fws->fifo_credit[fifo]);
for (credit = 0; credit < fws->fifo_credit[fifo]; /* nop */) {
@@ -1915,9 +1918,12 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
if (brcmf_skbcb(skb)->if_flags &
BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK)
credit++;
+ if (fws->bus_flow_blocked)
+ break;
}
if ((fifo == BRCMF_FWS_FIFO_AC_BE) &&
- (credit == fws->fifo_credit[fifo])) {
+ (credit == fws->fifo_credit[fifo]) &&
+ (!fws->bus_flow_blocked)) {
fws->fifo_credit[fifo] -= credit;
while (brcmf_fws_borrow_credit(fws) == 0) {
skb = brcmf_fws_deq(fws, fifo);
@@ -1929,6 +1935,8 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
brcmf_fws_return_credits(fws, fifo, 1);
break;
}
+ if (fws->bus_flow_blocked)
+ break;
}
} else {
fws->fifo_credit[fifo] -= credit;
@@ -2060,3 +2068,12 @@ void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb)
}
brcmf_fws_unlock(fws->drvr, flags);
}
+
+void brcmf_fws_bus_blocked(struct brcmf_pub *drvr, bool flow_blocked)
+{
+ struct brcmf_fws_info *fws = drvr->fws;
+
+ fws->bus_flow_blocked = flow_blocked;
+ if (!flow_blocked)
+ brcmf_fws_schedule_deq(fws);
+}