Commit 7057fd00 authored by Franky Lin's avatar Franky Lin Committed by John W. Linville

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: default avatarHante Meuleman <meuleman@broadcom.com>
Reviewed-by: default avatarPieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarFranky Lin <frankyl@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 03d5c360
...@@ -249,7 +249,9 @@ u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) ...@@ -249,7 +249,9 @@ u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
int retval; int retval;
brcmf_dbg(INFO, "addr:0x%08x\n", addr); brcmf_dbg(INFO, "addr:0x%08x\n", addr);
sdio_claim_host(sdiodev->func[1]);
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false); retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
sdio_release_host(sdiodev->func[1]);
brcmf_dbg(INFO, "data:0x%02x\n", data); brcmf_dbg(INFO, "data:0x%02x\n", data);
if (ret) if (ret)
...@@ -264,7 +266,9 @@ u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) ...@@ -264,7 +266,9 @@ u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
int retval; int retval;
brcmf_dbg(INFO, "addr:0x%08x\n", addr); brcmf_dbg(INFO, "addr:0x%08x\n", addr);
sdio_claim_host(sdiodev->func[1]);
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false); retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
sdio_release_host(sdiodev->func[1]);
brcmf_dbg(INFO, "data:0x%08x\n", data); brcmf_dbg(INFO, "data:0x%08x\n", data);
if (ret) if (ret)
...@@ -279,7 +283,9 @@ void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, ...@@ -279,7 +283,9 @@ void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr,
int retval; int retval;
brcmf_dbg(INFO, "addr:0x%08x, data:0x%02x\n", addr, data); brcmf_dbg(INFO, "addr:0x%08x, data:0x%02x\n", addr, data);
sdio_claim_host(sdiodev->func[1]);
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true); retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
sdio_release_host(sdiodev->func[1]);
if (ret) if (ret)
*ret = retval; *ret = retval;
...@@ -291,7 +297,9 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, ...@@ -291,7 +297,9 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
int retval; int retval;
brcmf_dbg(INFO, "addr:0x%08x, data:0x%08x\n", addr, data); brcmf_dbg(INFO, "addr:0x%08x, data:0x%08x\n", addr, data);
sdio_claim_host(sdiodev->func[1]);
retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true); retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
sdio_release_host(sdiodev->func[1]);
if (ret) if (ret)
*ret = retval; *ret = retval;
...@@ -356,15 +364,20 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, ...@@ -356,15 +364,20 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
fn, addr, pkt->len); fn, addr, pkt->len);
sdio_claim_host(sdiodev->func[1]);
width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr); err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr);
if (err) if (err)
return err; goto done;
incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
err = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_READ, err = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_READ,
fn, addr, pkt); fn, addr, pkt);
done:
sdio_release_host(sdiodev->func[1]);
return err; return err;
} }
...@@ -378,15 +391,20 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, ...@@ -378,15 +391,20 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
fn, addr, pktq->qlen); fn, addr, pktq->qlen);
sdio_claim_host(sdiodev->func[1]);
width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr); err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr);
if (err) if (err)
return err; goto done;
incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
err = brcmf_sdioh_request_chain(sdiodev, incr_fix, SDIOH_READ, fn, addr, err = brcmf_sdioh_request_chain(sdiodev, incr_fix, SDIOH_READ, fn, addr,
pktq); pktq);
done:
sdio_release_host(sdiodev->func[1]);
return err; return err;
} }
...@@ -428,10 +446,12 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, ...@@ -428,10 +446,12 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
if (flags & SDIO_REQ_ASYNC) if (flags & SDIO_REQ_ASYNC)
return -ENOTSUPP; return -ENOTSUPP;
sdio_claim_host(sdiodev->func[1]);
if (bar0 != sdiodev->sbwad) { if (bar0 != sdiodev->sbwad) {
err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
if (err) if (err)
return err; goto done;
sdiodev->sbwad = bar0; sdiodev->sbwad = bar0;
} }
...@@ -443,8 +463,13 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, ...@@ -443,8 +463,13 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
if (width == 4) if (width == 4)
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
return brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn, err = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn,
addr, pkt); addr, pkt);
done:
sdio_release_host(sdiodev->func[1]);
return err;
} }
int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr, 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,8 +510,10 @@ int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
brcmf_dbg(TRACE, "Enter\n"); brcmf_dbg(TRACE, "Enter\n");
/* issue abort cmd52 command through F0 */ /* issue abort cmd52 command through F0 */
sdio_claim_host(sdiodev->func[1]);
brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0, brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0,
SDIO_CCCR_ABORT, &t_func); SDIO_CCCR_ABORT, &t_func);
sdio_release_host(sdiodev->func[1]);
brcmf_dbg(TRACE, "Exit\n"); brcmf_dbg(TRACE, "Exit\n");
return 0; return 0;
......
...@@ -103,7 +103,6 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev, ...@@ -103,7 +103,6 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
if (regaddr == SDIO_CCCR_IOEx) { if (regaddr == SDIO_CCCR_IOEx) {
sdfunc = sdiodev->func[2]; sdfunc = sdiodev->func[2];
if (sdfunc) { if (sdfunc) {
sdio_claim_host(sdfunc);
if (*byte & SDIO_FUNC_ENABLE_2) { if (*byte & SDIO_FUNC_ENABLE_2) {
/* Enable Function 2 */ /* Enable Function 2 */
err_ret = sdio_enable_func(sdfunc); err_ret = sdio_enable_func(sdfunc);
...@@ -119,7 +118,6 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev, ...@@ -119,7 +118,6 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
"Disable F2 failed:%d\n", "Disable F2 failed:%d\n",
err_ret); err_ret);
} }
sdio_release_host(sdfunc);
} }
} else if ((regaddr == SDIO_CCCR_ABORT) || } else if ((regaddr == SDIO_CCCR_ABORT) ||
(regaddr == SDIO_CCCR_IENx)) { (regaddr == SDIO_CCCR_IENx)) {
...@@ -128,17 +126,13 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev, ...@@ -128,17 +126,13 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
if (!sdfunc) if (!sdfunc)
return -ENOMEM; return -ENOMEM;
sdfunc->num = 0; sdfunc->num = 0;
sdio_claim_host(sdfunc);
sdio_writeb(sdfunc, *byte, regaddr, &err_ret); sdio_writeb(sdfunc, *byte, regaddr, &err_ret);
sdio_release_host(sdfunc);
kfree(sdfunc); kfree(sdfunc);
} else if (regaddr < 0xF0) { } else if (regaddr < 0xF0) {
brcmf_dbg(ERROR, "F0 Wr:0x%02x: write disallowed\n", regaddr); brcmf_dbg(ERROR, "F0 Wr:0x%02x: write disallowed\n", regaddr);
err_ret = -EPERM; err_ret = -EPERM;
} else { } else {
sdio_claim_host(sdfunc);
sdio_f0_writeb(sdfunc, *byte, regaddr, &err_ret); sdio_f0_writeb(sdfunc, *byte, regaddr, &err_ret);
sdio_release_host(sdfunc);
} }
return err_ret; return err_ret;
...@@ -159,7 +153,6 @@ int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func, ...@@ -159,7 +153,6 @@ int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func,
/* handle F0 separately */ /* handle F0 separately */
err_ret = brcmf_sdioh_f0_write_byte(sdiodev, regaddr, byte); err_ret = brcmf_sdioh_f0_write_byte(sdiodev, regaddr, byte);
} else { } else {
sdio_claim_host(sdiodev->func[func]);
if (rw) /* CMD52 Write */ if (rw) /* CMD52 Write */
sdio_writeb(sdiodev->func[func], *byte, regaddr, sdio_writeb(sdiodev->func[func], *byte, regaddr,
&err_ret); &err_ret);
...@@ -170,7 +163,6 @@ int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func, ...@@ -170,7 +163,6 @@ int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func,
*byte = sdio_readb(sdiodev->func[func], regaddr, *byte = sdio_readb(sdiodev->func[func], regaddr,
&err_ret); &err_ret);
} }
sdio_release_host(sdiodev->func[func]);
} }
if (err_ret) if (err_ret)
...@@ -197,8 +189,6 @@ int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, ...@@ -197,8 +189,6 @@ int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,
brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait); brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait);
if (brcmf_pm_resume_error(sdiodev)) if (brcmf_pm_resume_error(sdiodev))
return -EIO; return -EIO;
/* Claim host controller */
sdio_claim_host(sdiodev->func[func]);
if (rw) { /* CMD52 Write */ if (rw) { /* CMD52 Write */
if (nbytes == 4) if (nbytes == 4)
...@@ -219,9 +209,6 @@ int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, ...@@ -219,9 +209,6 @@ int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,
brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes); brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes);
} }
/* Release host controller */
sdio_release_host(sdiodev->func[func]);
if (err_ret) if (err_ret)
brcmf_dbg(ERROR, "Failed to %s word, Err: 0x%08x\n", brcmf_dbg(ERROR, "Failed to %s word, Err: 0x%08x\n",
rw ? "write" : "read", err_ret); rw ? "write" : "read", err_ret);
...@@ -275,9 +262,6 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc, ...@@ -275,9 +262,6 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc,
if (brcmf_pm_resume_error(sdiodev)) if (brcmf_pm_resume_error(sdiodev))
return -EIO; return -EIO;
/* Claim host controller */
sdio_claim_host(sdiodev->func[func]);
skb_queue_walk(pktq, pkt) { skb_queue_walk(pktq, pkt) {
uint pkt_len = pkt->len; uint pkt_len = pkt->len;
pkt_len += 3; pkt_len += 3;
...@@ -300,9 +284,6 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc, ...@@ -300,9 +284,6 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc,
SGCount++; SGCount++;
} }
/* Release host controller */
sdio_release_host(sdiodev->func[func]);
brcmf_dbg(TRACE, "Exit\n"); brcmf_dbg(TRACE, "Exit\n");
return err_ret; return err_ret;
} }
...@@ -328,9 +309,6 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, ...@@ -328,9 +309,6 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev,
if (brcmf_pm_resume_error(sdiodev)) if (brcmf_pm_resume_error(sdiodev))
return -EIO; return -EIO;
/* Claim host controller */
sdio_claim_host(sdiodev->func[func]);
pkt_len += 3; pkt_len += 3;
pkt_len &= (uint)~3; pkt_len &= (uint)~3;
...@@ -344,9 +322,6 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, ...@@ -344,9 +322,6 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev,
write ? "TX" : "RX", pkt, addr, pkt_len); write ? "TX" : "RX", pkt, addr, pkt_len);
} }
/* Release host controller */
sdio_release_host(sdiodev->func[func]);
return status; return status;
} }
......
...@@ -2564,6 +2564,8 @@ brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data, ...@@ -2564,6 +2564,8 @@ brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data,
else else
dsize = size; dsize = size;
sdio_claim_host(bus->sdiodev->func[1]);
/* Set the backplane window to include the start address */ /* Set the backplane window to include the start address */
bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev, address); bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev, address);
if (bcmerror) { if (bcmerror) {
...@@ -2605,6 +2607,8 @@ brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data, ...@@ -2605,6 +2607,8 @@ brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data,
brcmf_dbg(ERROR, "FAILED to set window back to 0x%x\n", brcmf_dbg(ERROR, "FAILED to set window back to 0x%x\n",
bus->sdiodev->sbwad); bus->sdiodev->sbwad);
sdio_release_host(bus->sdiodev->func[1]);
return bcmerror; return bcmerror;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment