mac80211: update brcmfmac to the wireless-drivers-next-for-davem-2015-04-09
[openwrt.git] / package / kernel / mac80211 / patches / 337-brcmfmac-Fix-possible-race-condition.patch
1 From: Hante Meuleman <meuleman@broadcom.com>
2 Date: Fri, 6 Mar 2015 18:40:40 +0100
3 Subject: [PATCH] brcmfmac: Fix possible race-condition.
4
5 SDIO is using a "shared" variable to handoff ctl frames to DPC
6 and to see when they are done. In a timeout situation this can
7 lead to erroneous situation where DPC started to handle the ctl
8 frame while the timeout expired. This patch will fix this by
9 adding locking around the shared variable.
10
11 Reviewed-by: Arend Van Spriel <arend@broadcom.com>
12 Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
13 Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
14 Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
15 Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
16 Signed-off-by: Arend van Spriel <arend@broadcom.com>
17 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
18 ---
19
20 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
21 +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
22 @@ -2700,11 +2700,13 @@ static void brcmf_sdio_dpc(struct brcmf_
23         if (bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL) &&
24             data_ok(bus)) {
25                 sdio_claim_host(bus->sdiodev->func[1]);
26 -               err = brcmf_sdio_tx_ctrlframe(bus,  bus->ctrl_frame_buf,
27 -                                             bus->ctrl_frame_len);
28 +               if (bus->ctrl_frame_stat) {
29 +                       err = brcmf_sdio_tx_ctrlframe(bus,  bus->ctrl_frame_buf,
30 +                                                     bus->ctrl_frame_len);
31 +                       bus->ctrl_frame_err = err;
32 +                       bus->ctrl_frame_stat = false;
33 +               }
34                 sdio_release_host(bus->sdiodev->func[1]);
35 -               bus->ctrl_frame_err = err;
36 -               bus->ctrl_frame_stat = false;
37                 brcmf_sdio_wait_event_wakeup(bus);
38         }
39         /* Send queued frames (limit 1 if rx may still be pending) */
40 @@ -2720,9 +2722,13 @@ static void brcmf_sdio_dpc(struct brcmf_
41                 brcmf_err("failed backplane access over SDIO, halting operation\n");
42                 atomic_set(&bus->intstatus, 0);
43                 if (bus->ctrl_frame_stat) {
44 -                       bus->ctrl_frame_err = -ENODEV;
45 -                       bus->ctrl_frame_stat = false;
46 -                       brcmf_sdio_wait_event_wakeup(bus);
47 +                       sdio_claim_host(bus->sdiodev->func[1]);
48 +                       if (bus->ctrl_frame_stat) {
49 +                               bus->ctrl_frame_err = -ENODEV;
50 +                               bus->ctrl_frame_stat = false;
51 +                               brcmf_sdio_wait_event_wakeup(bus);
52 +                       }
53 +                       sdio_release_host(bus->sdiodev->func[1]);
54                 }
55         } else if (atomic_read(&bus->intstatus) ||
56                    atomic_read(&bus->ipend) > 0 ||
57 @@ -2930,15 +2936,20 @@ brcmf_sdio_bus_txctl(struct device *dev,
58         brcmf_sdio_trigger_dpc(bus);
59         wait_event_interruptible_timeout(bus->ctrl_wait, !bus->ctrl_frame_stat,
60                                          msecs_to_jiffies(CTL_DONE_TIMEOUT));
61 -
62 -       if (!bus->ctrl_frame_stat) {
63 +       ret = 0;
64 +       if (bus->ctrl_frame_stat) {
65 +               sdio_claim_host(bus->sdiodev->func[1]);
66 +               if (bus->ctrl_frame_stat) {
67 +                       brcmf_dbg(SDIO, "ctrl_frame timeout\n");
68 +                       bus->ctrl_frame_stat = false;
69 +                       ret = -ETIMEDOUT;
70 +               }
71 +               sdio_release_host(bus->sdiodev->func[1]);
72 +       }
73 +       if (!ret) {
74                 brcmf_dbg(SDIO, "ctrl_frame complete, err=%d\n",
75                           bus->ctrl_frame_err);
76                 ret = bus->ctrl_frame_err;
77 -       } else {
78 -               brcmf_dbg(SDIO, "ctrl_frame timeout\n");
79 -               bus->ctrl_frame_stat = false;
80 -               ret = -ETIMEDOUT;
81         }
82  
83         if (ret)