mac80211: update brcmfmac to the wireless-drivers-next-for-davem-2015-04-09
[openwrt/staging/chunkeey.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)