mac80211: backport latest patches except for NVRAM support
[openwrt.git] / package / kernel / mac80211 / patches / 316-brcmfmac-block-the-correct-flowring-when-backup-queu.patch
1 From: Franky Lin <frankyl@broadcom.com>
2 Date: Thu, 20 Aug 2015 22:06:06 +0200
3 Subject: [PATCH] brcmfmac: block the correct flowring when backup queue
4  overflow
5
6 brcmf_flowring_block blocks the last active flowring under the same
7 interface instead of the one provided by caller. This could lead to a
8 dead lock of netif stop if there are more than one flowring under the
9 interface and the traffic is high enough so brcmf_flowring_enqueue can
10 not unblock the ring right away.
11
12 Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
13 Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
14 Signed-off-by: Franky Lin <frankyl@broadcom.com>
15 Signed-off-by: Arend van Spriel <arend@broadcom.com>
16 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
17 ---
18
19 --- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
20 +++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
21 @@ -194,11 +194,15 @@ static void brcmf_flowring_block(struct
22         spin_lock_irqsave(&flow->block_lock, flags);
23  
24         ring = flow->rings[flowid];
25 +       if (ring->blocked == blocked) {
26 +               spin_unlock_irqrestore(&flow->block_lock, flags);
27 +               return;
28 +       }
29         ifidx = brcmf_flowring_ifidx_get(flow, flowid);
30  
31         currently_blocked = false;
32         for (i = 0; i < flow->nrofrings; i++) {
33 -               if (flow->rings[i]) {
34 +               if ((flow->rings[i]) && (i != flowid)) {
35                         ring = flow->rings[i];
36                         if ((ring->status == RING_OPEN) &&
37                             (brcmf_flowring_ifidx_get(flow, i) == ifidx)) {
38 @@ -209,8 +213,8 @@ static void brcmf_flowring_block(struct
39                         }
40                 }
41         }
42 -       ring->blocked = blocked;
43 -       if (currently_blocked == blocked) {
44 +       flow->rings[flowid]->blocked = blocked;
45 +       if (currently_blocked) {
46                 spin_unlock_irqrestore(&flow->block_lock, flags);
47                 return;
48         }