diff options
author | Franky Lin <frankyl@broadcom.com> | 2012-09-13 15:12:02 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-09-24 14:59:09 -0400 |
commit | 7057fd00da45c31a5a927a742d0f43efe4470173 (patch) | |
tree | 972538c43f7c831eca50abe1f7242d20c83564d8 /drivers/net/wireless | |
parent | 03d5c360dcbcb62cfc45caaca163cce8e10f00d6 (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.c | 37 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | 25 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 4 |
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 | ||
378 | done: | ||
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 | ||
405 | done: | ||
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 | |||
469 | done: | ||
470 | sdio_release_host(sdiodev->func[1]); | ||
471 | |||
472 | return err; | ||
448 | } | 473 | } |
449 | 474 | ||
450 | int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr, | 475 | int 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 | ||