mac80211: update brcmfmac to the wireless-drivers-next-for-davem-2015-04-09
[openwrt/svn-archive/archive.git] / package / kernel / mac80211 / patches / 347-brcmfmac-Add-necessary-memory-barriers-for-SDIO.patch
1 From: Hante Meuleman <meuleman@broadcom.com>
2 Date: Wed, 18 Mar 2015 13:25:22 +0100
3 Subject: [PATCH] brcmfmac: Add necessary memory barriers for SDIO.
4
5 SDIO uses a thread to handle all communication with the device,
6 for this data is exchanged between threads. This data needs proper
7 memory barriers to make sure that data "exchange" is going correct.
8
9 Reviewed-by: Arend Van Spriel <arend@broadcom.com>
10 Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
11 Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
12 Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
13 Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
14 Signed-off-by: Arend van Spriel <arend@broadcom.com>
15 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
16 ---
17
18 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
19 +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
20 @@ -507,8 +507,8 @@ struct brcmf_sdio {
21
22 struct workqueue_struct *brcmf_wq;
23 struct work_struct datawork;
24 - atomic_t dpc_tskcnt;
25 - atomic_t dpc_running;
26 + bool dpc_triggered;
27 + bool dpc_running;
28
29 bool txoff; /* Transmit flow-controlled */
30 struct brcmf_sdio_count sdcnt;
31 @@ -2713,6 +2713,7 @@ static void brcmf_sdio_dpc(struct brcmf_
32 err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf,
33 bus->ctrl_frame_len);
34 bus->ctrl_frame_err = err;
35 + wmb();
36 bus->ctrl_frame_stat = false;
37 }
38 sdio_release_host(bus->sdiodev->func[1]);
39 @@ -2734,6 +2735,7 @@ static void brcmf_sdio_dpc(struct brcmf_
40 sdio_claim_host(bus->sdiodev->func[1]);
41 if (bus->ctrl_frame_stat) {
42 bus->ctrl_frame_err = -ENODEV;
43 + wmb();
44 bus->ctrl_frame_stat = false;
45 brcmf_sdio_wait_event_wakeup(bus);
46 }
47 @@ -2744,7 +2746,7 @@ static void brcmf_sdio_dpc(struct brcmf_
48 (!atomic_read(&bus->fcstate) &&
49 brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) &&
50 data_ok(bus))) {
51 - atomic_inc(&bus->dpc_tskcnt);
52 + bus->dpc_triggered = true;
53 }
54 }
55
56 @@ -2940,6 +2942,7 @@ brcmf_sdio_bus_txctl(struct device *dev,
57 /* Send from dpc */
58 bus->ctrl_frame_buf = msg;
59 bus->ctrl_frame_len = msglen;
60 + wmb();
61 bus->ctrl_frame_stat = true;
62
63 brcmf_sdio_trigger_dpc(bus);
64 @@ -2958,6 +2961,7 @@ brcmf_sdio_bus_txctl(struct device *dev,
65 if (!ret) {
66 brcmf_dbg(SDIO, "ctrl_frame complete, err=%d\n",
67 bus->ctrl_frame_err);
68 + rmb();
69 ret = bus->ctrl_frame_err;
70 }
71
72 @@ -3526,8 +3530,8 @@ done:
73
74 void brcmf_sdio_trigger_dpc(struct brcmf_sdio *bus)
75 {
76 - if (atomic_read(&bus->dpc_tskcnt) == 0) {
77 - atomic_inc(&bus->dpc_tskcnt);
78 + if (!bus->dpc_triggered) {
79 + bus->dpc_triggered = true;
80 queue_work(bus->brcmf_wq, &bus->datawork);
81 }
82 }
83 @@ -3558,7 +3562,7 @@ void brcmf_sdio_isr(struct brcmf_sdio *b
84 if (!bus->intr)
85 brcmf_err("isr w/o interrupt configured!\n");
86
87 - atomic_inc(&bus->dpc_tskcnt);
88 + bus->dpc_triggered = true;
89 queue_work(bus->brcmf_wq, &bus->datawork);
90 }
91
92 @@ -3578,7 +3582,7 @@ static void brcmf_sdio_bus_watchdog(stru
93 if (!bus->intr ||
94 (bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) {
95
96 - if (atomic_read(&bus->dpc_tskcnt) == 0) {
97 + if (!bus->dpc_triggered) {
98 u8 devpend;
99
100 sdio_claim_host(bus->sdiodev->func[1]);
101 @@ -3596,7 +3600,7 @@ static void brcmf_sdio_bus_watchdog(stru
102 bus->sdcnt.pollcnt++;
103 atomic_set(&bus->ipend, 1);
104
105 - atomic_inc(&bus->dpc_tskcnt);
106 + bus->dpc_triggered = true;
107 queue_work(bus->brcmf_wq, &bus->datawork);
108 }
109 }
110 @@ -3623,17 +3627,21 @@ static void brcmf_sdio_bus_watchdog(stru
111 #endif /* DEBUG */
112
113 /* On idle timeout clear activity flag and/or turn off clock */
114 - if ((atomic_read(&bus->dpc_tskcnt) == 0) &&
115 - (atomic_read(&bus->dpc_running) == 0) &&
116 - (bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) {
117 - bus->idlecount++;
118 - if (bus->idlecount > bus->idletime) {
119 - brcmf_dbg(SDIO, "idle\n");
120 - sdio_claim_host(bus->sdiodev->func[1]);
121 - brcmf_sdio_wd_timer(bus, 0);
122 + if (!bus->dpc_triggered) {
123 + rmb();
124 + if ((!bus->dpc_running) && (bus->idletime > 0) &&
125 + (bus->clkstate == CLK_AVAIL)) {
126 + bus->idlecount++;
127 + if (bus->idlecount > bus->idletime) {
128 + brcmf_dbg(SDIO, "idle\n");
129 + sdio_claim_host(bus->sdiodev->func[1]);
130 + brcmf_sdio_wd_timer(bus, 0);
131 + bus->idlecount = 0;
132 + brcmf_sdio_bus_sleep(bus, true, false);
133 + sdio_release_host(bus->sdiodev->func[1]);
134 + }
135 + } else {
136 bus->idlecount = 0;
137 - brcmf_sdio_bus_sleep(bus, true, false);
138 - sdio_release_host(bus->sdiodev->func[1]);
139 }
140 } else {
141 bus->idlecount = 0;
142 @@ -3645,13 +3653,14 @@ static void brcmf_sdio_dataworker(struct
143 struct brcmf_sdio *bus = container_of(work, struct brcmf_sdio,
144 datawork);
145
146 - while (atomic_read(&bus->dpc_tskcnt)) {
147 - atomic_set(&bus->dpc_running, 1);
148 - atomic_set(&bus->dpc_tskcnt, 0);
149 + bus->dpc_running = true;
150 + wmb();
151 + while (ACCESS_ONCE(bus->dpc_triggered)) {
152 + bus->dpc_triggered = false;
153 brcmf_sdio_dpc(bus);
154 bus->idlecount = 0;
155 - atomic_set(&bus->dpc_running, 0);
156 }
157 + bus->dpc_running = false;
158 if (brcmf_sdiod_freezing(bus->sdiodev)) {
159 brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DOWN);
160 brcmf_sdiod_try_freeze(bus->sdiodev);
161 @@ -4144,8 +4153,8 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
162 bus->watchdog_tsk = NULL;
163 }
164 /* Initialize DPC thread */
165 - atomic_set(&bus->dpc_tskcnt, 0);
166 - atomic_set(&bus->dpc_running, 0);
167 + bus->dpc_triggered = false;
168 + bus->dpc_running = false;
169
170 /* Assign bus interface call back */
171 bus->sdiodev->bus_if->dev = bus->sdiodev->dev;