aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorFranky Lin <frankyl@broadcom.com>2012-09-13 15:12:02 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-09-24 14:59:09 -0400
commit7057fd00da45c31a5a927a742d0f43efe4470173 (patch)
tree972538c43f7c831eca50abe1f7242d20c83564d8 /drivers/net/wireless
parent03d5c360dcbcb62cfc45caaca163cce8e10f00d6 (diff)
brcmfmac: raise SDIO host lock to higher level
Use SDIO host lock to protect the entire communication process of register access or data read/write rather than function calls to MMC/SDIO stack only. This can help to avoid unintentional memory access and unexpected interruption. Reviewed-by: Hante Meuleman <meuleman@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Reviewed-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: Franky Lin <frankyl@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')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c37
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c25
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c4
3 files changed, 36 insertions, 30 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 8e7e6928c93..0c1d08ae726 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -249,7 +249,9 @@ u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
249 int retval; 249 int retval;
250 250
251 brcmf_dbg(INFO, "addr:0x%08x\n", addr); 251 brcmf_dbg(INFO, "addr:0x%08x\n", addr);
252 sdio_claim_host(sdiodev->func[1]);
252 retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false); 253 retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
254 sdio_release_host(sdiodev->func[1]);
253 brcmf_dbg(INFO, "data:0x%02x\n", data); 255 brcmf_dbg(INFO, "data:0x%02x\n", data);
254 256
255 if (ret) 257 if (ret)
@@ -264,7 +266,9 @@ u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
264 int retval; 266 int retval;
265 267
266 brcmf_dbg(INFO, "addr:0x%08x\n", addr); 268 brcmf_dbg(INFO, "addr:0x%08x\n", addr);
269 sdio_claim_host(sdiodev->func[1]);
267 retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false); 270 retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
271 sdio_release_host(sdiodev->func[1]);
268 brcmf_dbg(INFO, "data:0x%08x\n", data); 272 brcmf_dbg(INFO, "data:0x%08x\n", data);
269 273
270 if (ret) 274 if (ret)
@@ -279,7 +283,9 @@ void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr,
279 int retval; 283 int retval;
280 284
281 brcmf_dbg(INFO, "addr:0x%08x, data:0x%02x\n", addr, data); 285 brcmf_dbg(INFO, "addr:0x%08x, data:0x%02x\n", addr, data);
286 sdio_claim_host(sdiodev->func[1]);
282 retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true); 287 retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
288 sdio_release_host(sdiodev->func[1]);
283 289
284 if (ret) 290 if (ret)
285 *ret = retval; 291 *ret = retval;
@@ -291,7 +297,9 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
291 int retval; 297 int retval;
292 298
293 brcmf_dbg(INFO, "addr:0x%08x, data:0x%08x\n", addr, data); 299 brcmf_dbg(INFO, "addr:0x%08x, data:0x%08x\n", addr, data);
300 sdio_claim_host(sdiodev->func[1]);
294 retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true); 301 retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
302 sdio_release_host(sdiodev->func[1]);
295 303
296 if (ret) 304 if (ret)
297 *ret = retval; 305 *ret = retval;
@@ -356,15 +364,20 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
356 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", 364 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
357 fn, addr, pkt->len); 365 fn, addr, pkt->len);
358 366
367 sdio_claim_host(sdiodev->func[1]);
368
359 width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; 369 width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
360 err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr); 370 err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr);
361 if (err) 371 if (err)
362 return err; 372 goto done;
363 373
364 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; 374 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
365 err = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_READ, 375 err = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_READ,
366 fn, addr, pkt); 376 fn, addr, pkt);
367 377
378done:
379 sdio_release_host(sdiodev->func[1]);
380
368 return err; 381 return err;
369} 382}
370 383
@@ -378,15 +391,20 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
378 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", 391 brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
379 fn, addr, pktq->qlen); 392 fn, addr, pktq->qlen);
380 393
394 sdio_claim_host(sdiodev->func[1]);
395
381 width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; 396 width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
382 err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr); 397 err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr);
383 if (err) 398 if (err)
384 return err; 399 goto done;
385 400
386 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; 401 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
387 err = brcmf_sdioh_request_chain(sdiodev, incr_fix, SDIOH_READ, fn, addr, 402 err = brcmf_sdioh_request_chain(sdiodev, incr_fix, SDIOH_READ, fn, addr,
388 pktq); 403 pktq);
389 404
405done:
406 sdio_release_host(sdiodev->func[1]);
407
390 return err; 408 return err;
391} 409}
392 410
@@ -428,10 +446,12 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
428 if (flags & SDIO_REQ_ASYNC) 446 if (flags & SDIO_REQ_ASYNC)
429 return -ENOTSUPP; 447 return -ENOTSUPP;
430 448
449 sdio_claim_host(sdiodev->func[1]);
450
431 if (bar0 != sdiodev->sbwad) { 451 if (bar0 != sdiodev->sbwad) {
432 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); 452 err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
433 if (err) 453 if (err)
434 return err; 454 goto done;
435 455
436 sdiodev->sbwad = bar0; 456 sdiodev->sbwad = bar0;
437 } 457 }
@@ -443,8 +463,13 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
443 if (width == 4) 463 if (width == 4)
444 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; 464 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
445 465
446 return brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn, 466 err = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn,
447 addr, pkt); 467 addr, pkt);
468
469done:
470 sdio_release_host(sdiodev->func[1]);
471
472 return err;
448} 473}
449 474
450int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr, 475int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr,
@@ -485,8 +510,10 @@ int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
485 brcmf_dbg(TRACE, "Enter\n"); 510 brcmf_dbg(TRACE, "Enter\n");
486 511
487 /* issue abort cmd52 command through F0 */ 512 /* issue abort cmd52 command through F0 */
513 sdio_claim_host(sdiodev->func[1]);
488 brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0, 514 brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0,
489 SDIO_CCCR_ABORT, &t_func); 515 SDIO_CCCR_ABORT, &t_func);
516 sdio_release_host(sdiodev->func[1]);
490 517
491 brcmf_dbg(TRACE, "Exit\n"); 518 brcmf_dbg(TRACE, "Exit\n");
492 return 0; 519 return 0;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index e0b313c7f5c..70f21a43553 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -103,7 +103,6 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
103 if (regaddr == SDIO_CCCR_IOEx) { 103 if (regaddr == SDIO_CCCR_IOEx) {
104 sdfunc = sdiodev->func[2]; 104 sdfunc = sdiodev->func[2];
105 if (sdfunc) { 105 if (sdfunc) {
106 sdio_claim_host(sdfunc);
107 if (*byte & SDIO_FUNC_ENABLE_2) { 106 if (*byte & SDIO_FUNC_ENABLE_2) {
108 /* Enable Function 2 */ 107 /* Enable Function 2 */
109 err_ret = sdio_enable_func(sdfunc); 108 err_ret = sdio_enable_func(sdfunc);
@@ -119,7 +118,6 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
119 "Disable F2 failed:%d\n", 118 "Disable F2 failed:%d\n",
120 err_ret); 119 err_ret);
121 } 120 }
122 sdio_release_host(sdfunc);
123 } 121 }
124 } else if ((regaddr == SDIO_CCCR_ABORT) || 122 } else if ((regaddr == SDIO_CCCR_ABORT) ||
125 (regaddr == SDIO_CCCR_IENx)) { 123 (regaddr == SDIO_CCCR_IENx)) {
@@ -128,17 +126,13 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
128 if (!sdfunc) 126 if (!sdfunc)
129 return -ENOMEM; 127 return -ENOMEM;
130 sdfunc->num = 0; 128 sdfunc->num = 0;
131 sdio_claim_host(sdfunc);
132 sdio_writeb(sdfunc, *byte, regaddr, &err_ret); 129 sdio_writeb(sdfunc, *byte, regaddr, &err_ret);
133 sdio_release_host(sdfunc);
134 kfree(sdfunc); 130 kfree(sdfunc);
135 } else if (regaddr < 0xF0) { 131 } else if (regaddr < 0xF0) {
136 brcmf_dbg(ERROR, "F0 Wr:0x%02x: write disallowed\n", regaddr); 132 brcmf_dbg(ERROR, "F0 Wr:0x%02x: write disallowed\n", regaddr);
137 err_ret = -EPERM; 133 err_ret = -EPERM;
138 } else { 134 } else {
139 sdio_claim_host(sdfunc);
140 sdio_f0_writeb(sdfunc, *byte, regaddr, &err_ret); 135 sdio_f0_writeb(sdfunc, *byte, regaddr, &err_ret);
141 sdio_release_host(sdfunc);
142 } 136 }
143 137
144 return err_ret; 138 return err_ret;
@@ -159,7 +153,6 @@ int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func,
159 /* handle F0 separately */ 153 /* handle F0 separately */
160 err_ret = brcmf_sdioh_f0_write_byte(sdiodev, regaddr, byte); 154 err_ret = brcmf_sdioh_f0_write_byte(sdiodev, regaddr, byte);
161 } else { 155 } else {
162 sdio_claim_host(sdiodev->func[func]);
163 if (rw) /* CMD52 Write */ 156 if (rw) /* CMD52 Write */
164 sdio_writeb(sdiodev->func[func], *byte, regaddr, 157 sdio_writeb(sdiodev->func[func], *byte, regaddr,
165 &err_ret); 158 &err_ret);
@@ -170,7 +163,6 @@ int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func,
170 *byte = sdio_readb(sdiodev->func[func], regaddr, 163 *byte = sdio_readb(sdiodev->func[func], regaddr,
171 &err_ret); 164 &err_ret);
172 } 165 }
173 sdio_release_host(sdiodev->func[func]);
174 } 166 }
175 167
176 if (err_ret) 168 if (err_ret)
@@ -197,8 +189,6 @@ int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,
197 brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait); 189 brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait);
198 if (brcmf_pm_resume_error(sdiodev)) 190 if (brcmf_pm_resume_error(sdiodev))
199 return -EIO; 191 return -EIO;
200 /* Claim host controller */
201 sdio_claim_host(sdiodev->func[func]);
202 192
203 if (rw) { /* CMD52 Write */ 193 if (rw) { /* CMD52 Write */
204 if (nbytes == 4) 194 if (nbytes == 4)
@@ -219,9 +209,6 @@ int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,
219 brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes); 209 brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes);
220 } 210 }
221 211
222 /* Release host controller */
223 sdio_release_host(sdiodev->func[func]);
224
225 if (err_ret) 212 if (err_ret)
226 brcmf_dbg(ERROR, "Failed to %s word, Err: 0x%08x\n", 213 brcmf_dbg(ERROR, "Failed to %s word, Err: 0x%08x\n",
227 rw ? "write" : "read", err_ret); 214 rw ? "write" : "read", err_ret);
@@ -275,9 +262,6 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc,
275 if (brcmf_pm_resume_error(sdiodev)) 262 if (brcmf_pm_resume_error(sdiodev))
276 return -EIO; 263 return -EIO;
277 264
278 /* Claim host controller */
279 sdio_claim_host(sdiodev->func[func]);
280
281 skb_queue_walk(pktq, pkt) { 265 skb_queue_walk(pktq, pkt) {
282 uint pkt_len = pkt->len; 266 uint pkt_len = pkt->len;
283 pkt_len += 3; 267 pkt_len += 3;
@@ -300,9 +284,6 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc,
300 SGCount++; 284 SGCount++;
301 } 285 }
302 286
303 /* Release host controller */
304 sdio_release_host(sdiodev->func[func]);
305
306 brcmf_dbg(TRACE, "Exit\n"); 287 brcmf_dbg(TRACE, "Exit\n");
307 return err_ret; 288 return err_ret;
308} 289}
@@ -328,9 +309,6 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev,
328 if (brcmf_pm_resume_error(sdiodev)) 309 if (brcmf_pm_resume_error(sdiodev))
329 return -EIO; 310 return -EIO;
330 311
331 /* Claim host controller */
332 sdio_claim_host(sdiodev->func[func]);
333
334 pkt_len += 3; 312 pkt_len += 3;
335 pkt_len &= (uint)~3; 313 pkt_len &= (uint)~3;
336 314
@@ -344,9 +322,6 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev,
344 write ? "TX" : "RX", pkt, addr, pkt_len); 322 write ? "TX" : "RX", pkt, addr, pkt_len);
345 } 323 }
346 324
347 /* Release host controller */
348 sdio_release_host(sdiodev->func[func]);
349
350 return status; 325 return status;
351} 326}
352 327
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 90a3849b41f..619f3cdcb8e 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -2564,6 +2564,8 @@ brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data,
2564 else 2564 else
2565 dsize = size; 2565 dsize = size;
2566 2566
2567 sdio_claim_host(bus->sdiodev->func[1]);
2568
2567 /* Set the backplane window to include the start address */ 2569 /* Set the backplane window to include the start address */
2568 bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev, address); 2570 bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev, address);
2569 if (bcmerror) { 2571 if (bcmerror) {
@@ -2605,6 +2607,8 @@ xfer_done:
2605 brcmf_dbg(ERROR, "FAILED to set window back to 0x%x\n", 2607 brcmf_dbg(ERROR, "FAILED to set window back to 0x%x\n",
2606 bus->sdiodev->sbwad); 2608 bus->sdiodev->sbwad);
2607 2609
2610 sdio_release_host(bus->sdiodev->func[1]);
2611
2608 return bcmerror; 2612 return bcmerror;
2609} 2613}
2610 2614