Commit 38b0b0dd authored by Franky Lin's avatar Franky Lin Committed by John W. Linville

brcmfmac: protect consecutive SDIO access with sdio_claim_host

Semaphore sdsem is used to protect consecutive memory access
through SDIO bus. Same functionality is provided by sdio_claim_host/
sdio_release_host interface as well. Replace sdsem with
sdio_claim_host.
Signed-off-by: default avatarFranky Lin <frankyl@broadcom.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 7cdf57d3
...@@ -84,6 +84,8 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) ...@@ -84,6 +84,8 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
return ret; return ret;
sdiodev->irq_wake = true; sdiodev->irq_wake = true;
sdio_claim_host(sdiodev->func[1]);
/* must configure SDIO_CCCR_IENx to enable irq */ /* must configure SDIO_CCCR_IENx to enable irq */
data = brcmf_sdio_regrb(sdiodev, SDIO_CCCR_IENx, &ret); data = brcmf_sdio_regrb(sdiodev, SDIO_CCCR_IENx, &ret);
data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1; data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
...@@ -95,6 +97,8 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) ...@@ -95,6 +97,8 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
data |= SDIO_SEPINT_ACT_HI; data |= SDIO_SEPINT_ACT_HI;
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret); brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret);
sdio_release_host(sdiodev->func[1]);
return 0; return 0;
} }
...@@ -102,8 +106,10 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev) ...@@ -102,8 +106,10 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
{ {
brcmf_dbg(TRACE, "Entering\n"); brcmf_dbg(TRACE, "Entering\n");
sdio_claim_host(sdiodev->func[1]);
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL); brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL); brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
sdio_release_host(sdiodev->func[1]);
if (sdiodev->irq_wake) { if (sdiodev->irq_wake) {
disable_irq_wake(sdiodev->irq); disable_irq_wake(sdiodev->irq);
...@@ -249,9 +255,7 @@ u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) ...@@ -249,9 +255,7 @@ 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)
...@@ -266,9 +270,7 @@ u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) ...@@ -266,9 +270,7 @@ 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)
...@@ -283,9 +285,7 @@ void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, ...@@ -283,9 +285,7 @@ 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;
...@@ -297,9 +297,7 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, ...@@ -297,9 +297,7 @@ 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;
...@@ -364,8 +362,6 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, ...@@ -364,8 +362,6 @@ 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)
...@@ -376,8 +372,6 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, ...@@ -376,8 +372,6 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
fn, addr, pkt); fn, addr, pkt);
done: done:
sdio_release_host(sdiodev->func[1]);
return err; return err;
} }
...@@ -391,8 +385,6 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, ...@@ -391,8 +385,6 @@ 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)
...@@ -403,8 +395,6 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, ...@@ -403,8 +395,6 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
pktq); pktq);
done: done:
sdio_release_host(sdiodev->func[1]);
return err; return err;
} }
...@@ -446,8 +436,6 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, ...@@ -446,8 +436,6 @@ 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)
...@@ -467,8 +455,6 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, ...@@ -467,8 +455,6 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
addr, pkt); addr, pkt);
done: done:
sdio_release_host(sdiodev->func[1]);
return err; return err;
} }
...@@ -510,10 +496,8 @@ int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn) ...@@ -510,10 +496,8 @@ 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;
......
...@@ -372,9 +372,7 @@ static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev) ...@@ -372,9 +372,7 @@ static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev)
} }
/* Enable Function 1 */ /* Enable Function 1 */
sdio_claim_host(sdiodev->func[1]);
err_ret = sdio_enable_func(sdiodev->func[1]); err_ret = sdio_enable_func(sdiodev->func[1]);
sdio_release_host(sdiodev->func[1]);
if (err_ret) if (err_ret)
brcmf_dbg(ERROR, "Failed to enable F1 Err: 0x%08x\n", err_ret); brcmf_dbg(ERROR, "Failed to enable F1 Err: 0x%08x\n", err_ret);
...@@ -393,16 +391,14 @@ int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev) ...@@ -393,16 +391,14 @@ int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev)
sdiodev->num_funcs = 2; sdiodev->num_funcs = 2;
sdio_claim_host(sdiodev->func[1]); sdio_claim_host(sdiodev->func[1]);
err_ret = sdio_set_block_size(sdiodev->func[1], SDIO_FUNC1_BLOCKSIZE); err_ret = sdio_set_block_size(sdiodev->func[1], SDIO_FUNC1_BLOCKSIZE);
sdio_release_host(sdiodev->func[1]);
if (err_ret) { if (err_ret) {
brcmf_dbg(ERROR, "Failed to set F1 blocksize\n"); brcmf_dbg(ERROR, "Failed to set F1 blocksize\n");
goto out; goto out;
} }
sdio_claim_host(sdiodev->func[2]);
err_ret = sdio_set_block_size(sdiodev->func[2], SDIO_FUNC2_BLOCKSIZE); err_ret = sdio_set_block_size(sdiodev->func[2], SDIO_FUNC2_BLOCKSIZE);
sdio_release_host(sdiodev->func[2]);
if (err_ret) { if (err_ret) {
brcmf_dbg(ERROR, "Failed to set F2 blocksize\n"); brcmf_dbg(ERROR, "Failed to set F2 blocksize\n");
goto out; goto out;
...@@ -411,6 +407,7 @@ int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev) ...@@ -411,6 +407,7 @@ int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev)
brcmf_sdioh_enablefuncs(sdiodev); brcmf_sdioh_enablefuncs(sdiodev);
out: out:
sdio_release_host(sdiodev->func[1]);
brcmf_dbg(TRACE, "Done\n"); brcmf_dbg(TRACE, "Done\n");
return err_ret; return err_ret;
} }
......
...@@ -584,8 +584,6 @@ struct brcmf_sdio { ...@@ -584,8 +584,6 @@ struct brcmf_sdio {
struct list_head dpc_tsklst; struct list_head dpc_tsklst;
spinlock_t dpc_tl_lock; spinlock_t dpc_tl_lock;
struct semaphore sdsem;
const struct firmware *firmware; const struct firmware *firmware;
u32 fw_ptr; u32 fw_ptr;
...@@ -1274,7 +1272,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) ...@@ -1274,7 +1272,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
* read directly into the chained packet, or allocate a large * read directly into the chained packet, or allocate a large
* packet and and copy into the chain. * packet and and copy into the chain.
*/ */
down(&bus->sdsem); sdio_claim_host(bus->sdiodev->func[1]);
if (usechain) { if (usechain) {
errcode = brcmf_sdcard_recv_chain(bus->sdiodev, errcode = brcmf_sdcard_recv_chain(bus->sdiodev,
bus->sdiodev->sbwad, bus->sdiodev->sbwad,
...@@ -1296,7 +1294,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) ...@@ -1296,7 +1294,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
dlen); dlen);
errcode = -1; errcode = -1;
} }
up(&bus->sdsem); sdio_release_host(bus->sdiodev->func[1]);
bus->sdcnt.f2rxdata++; bus->sdcnt.f2rxdata++;
/* On failure, kill the superframe, allow a couple retries */ /* On failure, kill the superframe, allow a couple retries */
...@@ -1305,6 +1303,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) ...@@ -1305,6 +1303,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
dlen, errcode); dlen, errcode);
bus->sdiodev->bus_if->dstats.rx_errors++; bus->sdiodev->bus_if->dstats.rx_errors++;
sdio_claim_host(bus->sdiodev->func[1]);
if (bus->glomerr++ < 3) { if (bus->glomerr++ < 3) {
brcmf_sdbrcm_rxfail(bus, true, true); brcmf_sdbrcm_rxfail(bus, true, true);
} else { } else {
...@@ -1313,6 +1312,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) ...@@ -1313,6 +1312,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
bus->sdcnt.rxglomfail++; bus->sdcnt.rxglomfail++;
brcmf_sdbrcm_free_glom(bus); brcmf_sdbrcm_free_glom(bus);
} }
sdio_release_host(bus->sdiodev->func[1]);
return 0; return 0;
} }
...@@ -1322,8 +1322,10 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) ...@@ -1322,8 +1322,10 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
rd_new.seq_num = rxseq; rd_new.seq_num = rxseq;
rd_new.len = dlen; rd_new.len = dlen;
sdio_claim_host(bus->sdiodev->func[1]);
errcode = -!brcmf_sdio_hdparser(bus, pfirst->data, &rd_new, errcode = -!brcmf_sdio_hdparser(bus, pfirst->data, &rd_new,
BRCMF_SDIO_FT_SUPER); BRCMF_SDIO_FT_SUPER);
sdio_release_host(bus->sdiodev->func[1]);
bus->cur_read.len = rd_new.len_nxtfrm << 4; bus->cur_read.len = rd_new.len_nxtfrm << 4;
/* Remove superframe header, remember offset */ /* Remove superframe header, remember offset */
...@@ -1339,9 +1341,11 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) ...@@ -1339,9 +1341,11 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
rd_new.len = pnext->len; rd_new.len = pnext->len;
rd_new.seq_num = rxseq++; rd_new.seq_num = rxseq++;
sdio_claim_host(bus->sdiodev->func[1]);
errcode = -!brcmf_sdio_hdparser(bus, pnext->data, errcode = -!brcmf_sdio_hdparser(bus, pnext->data,
&rd_new, &rd_new,
BRCMF_SDIO_FT_SUB); BRCMF_SDIO_FT_SUB);
sdio_release_host(bus->sdiodev->func[1]);
brcmf_dbg_hex_dump(BRCMF_GLOM_ON(), brcmf_dbg_hex_dump(BRCMF_GLOM_ON(),
pnext->data, 32, "subframe:\n"); pnext->data, 32, "subframe:\n");
...@@ -1351,6 +1355,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) ...@@ -1351,6 +1355,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
if (errcode) { if (errcode) {
/* Terminate frame on error, request /* Terminate frame on error, request
a couple retries */ a couple retries */
sdio_claim_host(bus->sdiodev->func[1]);
if (bus->glomerr++ < 3) { if (bus->glomerr++ < 3) {
/* Restore superframe header space */ /* Restore superframe header space */
skb_push(pfirst, sfdoff); skb_push(pfirst, sfdoff);
...@@ -1361,6 +1366,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) ...@@ -1361,6 +1366,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
bus->sdcnt.rxglomfail++; bus->sdcnt.rxglomfail++;
brcmf_sdbrcm_free_glom(bus); brcmf_sdbrcm_free_glom(bus);
} }
sdio_release_host(bus->sdiodev->func[1]);
bus->cur_read.len = 0; bus->cur_read.len = 0;
return 0; return 0;
} }
...@@ -1585,7 +1591,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) ...@@ -1585,7 +1591,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
rd->len_left = rd->len; rd->len_left = rd->len;
/* read header first for unknow frame length */ /* read header first for unknow frame length */
down(&bus->sdsem); sdio_claim_host(bus->sdiodev->func[1]);
if (!rd->len) { if (!rd->len) {
sdret = brcmf_sdcard_recv_buf(bus->sdiodev, sdret = brcmf_sdcard_recv_buf(bus->sdiodev,
bus->sdiodev->sbwad, bus->sdiodev->sbwad,
...@@ -1598,7 +1604,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) ...@@ -1598,7 +1604,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
sdret); sdret);
bus->sdcnt.rx_hdrfail++; bus->sdcnt.rx_hdrfail++;
brcmf_sdbrcm_rxfail(bus, true, true); brcmf_sdbrcm_rxfail(bus, true, true);
up(&bus->sdsem); sdio_release_host(bus->sdiodev->func[1]);
continue; continue;
} }
...@@ -1608,7 +1614,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) ...@@ -1608,7 +1614,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
if (!brcmf_sdio_hdparser(bus, bus->rxhdr, rd, if (!brcmf_sdio_hdparser(bus, bus->rxhdr, rd,
BRCMF_SDIO_FT_NORMAL)) { BRCMF_SDIO_FT_NORMAL)) {
up(&bus->sdsem); sdio_release_host(bus->sdiodev->func[1]);
if (!bus->rxpending) if (!bus->rxpending)
break; break;
else else
...@@ -1624,7 +1630,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) ...@@ -1624,7 +1630,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
rd->len_nxtfrm = 0; rd->len_nxtfrm = 0;
/* treat all packet as event if we don't know */ /* treat all packet as event if we don't know */
rd->channel = SDPCM_EVENT_CHANNEL; rd->channel = SDPCM_EVENT_CHANNEL;
up(&bus->sdsem); sdio_release_host(bus->sdiodev->func[1]);
continue; continue;
} }
rd->len_left = rd->len > BRCMF_FIRSTREAD ? rd->len_left = rd->len > BRCMF_FIRSTREAD ?
...@@ -1642,7 +1648,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) ...@@ -1642,7 +1648,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
bus->sdiodev->bus_if->dstats.rx_dropped++; bus->sdiodev->bus_if->dstats.rx_dropped++;
brcmf_sdbrcm_rxfail(bus, false, brcmf_sdbrcm_rxfail(bus, false,
RETRYCHAN(rd->channel)); RETRYCHAN(rd->channel));
up(&bus->sdsem); sdio_release_host(bus->sdiodev->func[1]);
continue; continue;
} }
skb_pull(pkt, head_read); skb_pull(pkt, head_read);
...@@ -1651,15 +1657,17 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) ...@@ -1651,15 +1657,17 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad,
SDIO_FUNC_2, F2SYNC, pkt); SDIO_FUNC_2, F2SYNC, pkt);
bus->sdcnt.f2rxdata++; bus->sdcnt.f2rxdata++;
up(&bus->sdsem); sdio_release_host(bus->sdiodev->func[1]);
if (sdret < 0) { if (sdret < 0) {
brcmf_dbg(ERROR, "read %d bytes from channel %d failed: %d\n", brcmf_dbg(ERROR, "read %d bytes from channel %d failed: %d\n",
rd->len, rd->channel, sdret); rd->len, rd->channel, sdret);
brcmu_pkt_buf_free_skb(pkt); brcmu_pkt_buf_free_skb(pkt);
bus->sdiodev->bus_if->dstats.rx_errors++; bus->sdiodev->bus_if->dstats.rx_errors++;
sdio_claim_host(bus->sdiodev->func[1]);
brcmf_sdbrcm_rxfail(bus, true, brcmf_sdbrcm_rxfail(bus, true,
RETRYCHAN(rd->channel)); RETRYCHAN(rd->channel));
sdio_release_host(bus->sdiodev->func[1]);
continue; continue;
} }
...@@ -1670,6 +1678,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) ...@@ -1670,6 +1678,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
} else { } else {
memcpy(bus->rxhdr, pkt->data, SDPCM_HDRLEN); memcpy(bus->rxhdr, pkt->data, SDPCM_HDRLEN);
rd_new.seq_num = rd->seq_num; rd_new.seq_num = rd->seq_num;
sdio_claim_host(bus->sdiodev->func[1]);
if (!brcmf_sdio_hdparser(bus, bus->rxhdr, &rd_new, if (!brcmf_sdio_hdparser(bus, bus->rxhdr, &rd_new,
BRCMF_SDIO_FT_NORMAL)) { BRCMF_SDIO_FT_NORMAL)) {
rd->len = 0; rd->len = 0;
...@@ -1682,9 +1691,11 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) ...@@ -1682,9 +1691,11 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
roundup(rd_new.len, 16) >> 4); roundup(rd_new.len, 16) >> 4);
rd->len = 0; rd->len = 0;
brcmf_sdbrcm_rxfail(bus, true, true); brcmf_sdbrcm_rxfail(bus, true, true);
sdio_release_host(bus->sdiodev->func[1]);
brcmu_pkt_buf_free_skb(pkt); brcmu_pkt_buf_free_skb(pkt);
continue; continue;
} }
sdio_release_host(bus->sdiodev->func[1]);
rd->len_nxtfrm = rd_new.len_nxtfrm; rd->len_nxtfrm = rd_new.len_nxtfrm;
rd->channel = rd_new.channel; rd->channel = rd_new.channel;
rd->dat_offset = rd_new.dat_offset; rd->dat_offset = rd_new.dat_offset;
...@@ -1700,7 +1711,9 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) ...@@ -1700,7 +1711,9 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
rd_new.seq_num); rd_new.seq_num);
/* Force retry w/normal header read */ /* Force retry w/normal header read */
rd->len = 0; rd->len = 0;
sdio_claim_host(bus->sdiodev->func[1]);
brcmf_sdbrcm_rxfail(bus, false, true); brcmf_sdbrcm_rxfail(bus, false, true);
sdio_release_host(bus->sdiodev->func[1]);
brcmu_pkt_buf_free_skb(pkt); brcmu_pkt_buf_free_skb(pkt);
continue; continue;
} }
...@@ -1723,7 +1736,9 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) ...@@ -1723,7 +1736,9 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
} else { } else {
brcmf_dbg(ERROR, "%s: glom superframe w/o " brcmf_dbg(ERROR, "%s: glom superframe w/o "
"descriptor!\n", __func__); "descriptor!\n", __func__);
sdio_claim_host(bus->sdiodev->func[1]);
brcmf_sdbrcm_rxfail(bus, false, false); brcmf_sdbrcm_rxfail(bus, false, false);
sdio_release_host(bus->sdiodev->func[1]);
} }
/* prepare the descriptor for the next read */ /* prepare the descriptor for the next read */
rd->len = rd->len_nxtfrm << 4; rd->len = rd->len_nxtfrm << 4;
...@@ -1879,7 +1894,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, ...@@ -1879,7 +1894,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
if (len & (ALIGNMENT - 1)) if (len & (ALIGNMENT - 1))
len = roundup(len, ALIGNMENT); len = roundup(len, ALIGNMENT);
down(&bus->sdsem); sdio_claim_host(bus->sdiodev->func[1]);
ret = brcmf_sdcard_send_pkt(bus->sdiodev, bus->sdiodev->sbwad, ret = brcmf_sdcard_send_pkt(bus->sdiodev, bus->sdiodev->sbwad,
SDIO_FUNC_2, F2SYNC, pkt); SDIO_FUNC_2, F2SYNC, pkt);
bus->sdcnt.f2txdata++; bus->sdcnt.f2txdata++;
...@@ -1907,7 +1922,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, ...@@ -1907,7 +1922,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
} }
} }
up(&bus->sdsem); sdio_release_host(bus->sdiodev->func[1]);
if (ret == 0) if (ret == 0)
bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
...@@ -1955,11 +1970,11 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes) ...@@ -1955,11 +1970,11 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
/* In poll mode, need to check for other events */ /* In poll mode, need to check for other events */
if (!bus->intr && cnt) { if (!bus->intr && cnt) {
/* Check device status, signal pending interrupt */ /* Check device status, signal pending interrupt */
down(&bus->sdsem); sdio_claim_host(bus->sdiodev->func[1]);
ret = r_sdreg32(bus, &intstatus, ret = r_sdreg32(bus, &intstatus,
offsetof(struct sdpcmd_regs, offsetof(struct sdpcmd_regs,
intstatus)); intstatus));
up(&bus->sdsem); sdio_release_host(bus->sdiodev->func[1]);
bus->sdcnt.f2txdata++; bus->sdcnt.f2txdata++;
if (ret != 0) if (ret != 0)
break; break;
...@@ -1996,7 +2011,7 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev) ...@@ -1996,7 +2011,7 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
bus->watchdog_tsk = NULL; bus->watchdog_tsk = NULL;
} }
down(&bus->sdsem); sdio_claim_host(bus->sdiodev->func[1]);
/* Enable clock for device interrupts */ /* Enable clock for device interrupts */
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
...@@ -2030,7 +2045,7 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev) ...@@ -2030,7 +2045,7 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
/* Turn off the backplane clock (only) */ /* Turn off the backplane clock (only) */
brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
up(&bus->sdsem); sdio_release_host(bus->sdiodev->func[1]);
/* Clear the data packet queues */ /* Clear the data packet queues */
brcmu_pktq_flush(&bus->txq, true, NULL, NULL); brcmu_pktq_flush(&bus->txq, true, NULL, NULL);
...@@ -2132,7 +2147,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) ...@@ -2132,7 +2147,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
brcmf_dbg(TRACE, "Enter\n"); brcmf_dbg(TRACE, "Enter\n");
down(&bus->sdsem); sdio_claim_host(bus->sdiodev->func[1]);
/* If waiting for HTAVAIL, check status */ /* If waiting for HTAVAIL, check status */
if (bus->clkstate == CLK_PENDING) { if (bus->clkstate == CLK_PENDING) {
...@@ -2186,9 +2201,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) ...@@ -2186,9 +2201,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
/* Pending interrupt indicates new device status */ /* Pending interrupt indicates new device status */
if (atomic_read(&bus->ipend) > 0) { if (atomic_read(&bus->ipend) > 0) {
atomic_set(&bus->ipend, 0); atomic_set(&bus->ipend, 0);
sdio_claim_host(bus->sdiodev->func[1]);
err = brcmf_sdio_intr_rstatus(bus); err = brcmf_sdio_intr_rstatus(bus);
sdio_release_host(bus->sdiodev->func[1]);
} }
/* Start with leftover status bits */ /* Start with leftover status bits */
...@@ -2217,7 +2230,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) ...@@ -2217,7 +2230,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
intstatus |= brcmf_sdbrcm_hostmail(bus); intstatus |= brcmf_sdbrcm_hostmail(bus);
} }
up(&bus->sdsem); sdio_release_host(bus->sdiodev->func[1]);
/* Generally don't ask for these, can get CRC errors... */ /* Generally don't ask for these, can get CRC errors... */
if (intstatus & I_WR_OOSYNC) { if (intstatus & I_WR_OOSYNC) {
...@@ -2265,7 +2278,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) ...@@ -2265,7 +2278,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
(bus->clkstate == CLK_AVAIL)) { (bus->clkstate == CLK_AVAIL)) {
int i; int i;
down(&bus->sdsem); sdio_claim_host(bus->sdiodev->func[1]);
err = brcmf_sdcard_send_buf(bus->sdiodev, bus->sdiodev->sbwad, err = brcmf_sdcard_send_buf(bus->sdiodev, bus->sdiodev->sbwad,
SDIO_FUNC_2, F2SYNC, bus->ctrl_frame_buf, SDIO_FUNC_2, F2SYNC, bus->ctrl_frame_buf,
(u32) bus->ctrl_frame_len); (u32) bus->ctrl_frame_len);
...@@ -2299,7 +2312,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) ...@@ -2299,7 +2312,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
} else { } else {
bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
} }
up(&bus->sdsem); sdio_release_host(bus->sdiodev->func[1]);
bus->ctrl_frame_stat = false; bus->ctrl_frame_stat = false;
brcmf_sdbrcm_wait_event_wakeup(bus); brcmf_sdbrcm_wait_event_wakeup(bus);
} }
...@@ -2329,7 +2342,9 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) ...@@ -2329,7 +2342,9 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
if ((bus->clkstate != CLK_PENDING) if ((bus->clkstate != CLK_PENDING)
&& bus->idletime == BRCMF_IDLE_IMMEDIATE) { && bus->idletime == BRCMF_IDLE_IMMEDIATE) {
bus->activity = false; bus->activity = false;
sdio_claim_host(bus->sdiodev->func[1]);
brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
sdio_release_host(bus->sdiodev->func[1]);
} }
} }
...@@ -2622,9 +2637,9 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) ...@@ -2622,9 +2637,9 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
/* precondition: IS_ALIGNED((unsigned long)frame, 2) */ /* precondition: IS_ALIGNED((unsigned long)frame, 2) */
/* Make sure backplane clock is on */ /* Make sure backplane clock is on */
down(&bus->sdsem); sdio_claim_host(bus->sdiodev->func[1]);
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
up(&bus->sdsem); sdio_release_host(bus->sdiodev->func[1]);
/* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */ /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
*(__le16 *) frame = cpu_to_le16((u16) msglen); *(__le16 *) frame = cpu_to_le16((u16) msglen);
...@@ -2666,9 +2681,9 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) ...@@ -2666,9 +2681,9 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
frame, min_t(u16, len, 16), "TxHdr:\n"); frame, min_t(u16, len, 16), "TxHdr:\n");
do { do {
down(&bus->sdsem); sdio_claim_host(bus->sdiodev->func[1]);
ret = brcmf_tx_frame(bus, frame, len); ret = brcmf_tx_frame(bus, frame, len);
up(&bus->sdsem); sdio_release_host(bus->sdiodev->func[1]);
} while (ret < 0 && retries++ < TXRETRIES); } while (ret < 0 && retries++ < TXRETRIES);
} }
...@@ -2678,9 +2693,9 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) ...@@ -2678,9 +2693,9 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
bus->activity = false; bus->activity = false;
down(&bus->sdsem); sdio_claim_host(bus->sdiodev->func[1]);
brcmf_sdbrcm_clkctl(bus, CLK_NONE, true); brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
up(&bus->sdsem); sdio_release_host(bus->sdiodev->func[1]);
} else { } else {
spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
} }
...@@ -2714,10 +2729,10 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus, ...@@ -2714,10 +2729,10 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
* Read last word in socram to determine * Read last word in socram to determine
* address of sdpcm_shared structure * address of sdpcm_shared structure
*/ */
down(&bus->sdsem); sdio_claim_host(bus->sdiodev->func[1]);
rv = brcmf_sdbrcm_membytes(bus, false, shaddr, rv = brcmf_sdbrcm_membytes(bus, false, shaddr,
(u8 *)&addr_le, 4); (u8 *)&addr_le, 4);
up(&bus->sdsem); sdio_claim_host(bus->sdiodev->func[1]);
if (rv < 0) if (rv < 0)
return rv; return rv;
...@@ -2736,8 +2751,10 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus, ...@@ -2736,8 +2751,10 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
} }
/* Read hndrte_shared structure */ /* Read hndrte_shared structure */
sdio_claim_host(bus->sdiodev->func[1]);
rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&sh_le, rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&sh_le,
sizeof(struct sdpcm_shared_le)); sizeof(struct sdpcm_shared_le));
sdio_release_host(bus->sdiodev->func[1]);
if (rv < 0) if (rv < 0)
return rv; return rv;
...@@ -2840,14 +2857,14 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh, ...@@ -2840,14 +2857,14 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh,
if ((sh->flags & SDPCM_SHARED_TRAP) == 0) if ((sh->flags & SDPCM_SHARED_TRAP) == 0)
return 0; return 0;
down(&bus->sdsem); sdio_claim_host(bus->sdiodev->func[1]);
error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr, error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr,
sizeof(struct brcmf_trap_info)); sizeof(struct brcmf_trap_info));
if (error < 0) if (error < 0)
return error; return error;
nbytes = brcmf_sdio_dump_console(bus, sh, data, count); nbytes = brcmf_sdio_dump_console(bus, sh, data, count);
up(&bus->sdsem); sdio_release_host(bus->sdiodev->func[1]);
if (nbytes < 0) if (nbytes < 0)
return nbytes; return nbytes;
...@@ -2893,7 +2910,7 @@ static int brcmf_sdio_assert_info(struct brcmf_sdio *bus, ...@@ -2893,7 +2910,7 @@ static int brcmf_sdio_assert_info(struct brcmf_sdio *bus,
return 0; return 0;
} }
down(&bus->sdsem); sdio_claim_host(bus->sdiodev->func[1]);
if (sh->assert_file_addr != 0) { if (sh->assert_file_addr != 0) {
error = brcmf_sdbrcm_membytes(bus, false, sh->assert_file_addr, error = brcmf_sdbrcm_membytes(bus, false, sh->assert_file_addr,
(u8 *)file, 80); (u8 *)file, 80);
...@@ -2906,7 +2923,7 @@ static int brcmf_sdio_assert_info(struct brcmf_sdio *bus, ...@@ -2906,7 +2923,7 @@ static int brcmf_sdio_assert_info(struct brcmf_sdio *bus,
if (error < 0) if (error < 0)
return error; return error;
} }
up(&bus->sdsem); sdio_release_host(bus->sdiodev->func[1]);
res = scnprintf(buf, sizeof(buf), res = scnprintf(buf, sizeof(buf),
"dongle assert: %s:%d: assert(%s)\n", "dongle assert: %s:%d: assert(%s)\n",
...@@ -3366,13 +3383,16 @@ brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus) ...@@ -3366,13 +3383,16 @@ brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
{ {
bool ret; bool ret;
/* Download the firmware */ sdio_claim_host(bus->sdiodev->func[1]);
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
ret = _brcmf_sdbrcm_download_firmware(bus) == 0; ret = _brcmf_sdbrcm_download_firmware(bus) == 0;
brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
sdio_release_host(bus->sdiodev->func[1]);
return ret; return ret;
} }
...@@ -3401,7 +3421,7 @@ static int brcmf_sdbrcm_bus_init(struct device *dev) ...@@ -3401,7 +3421,7 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
bus->sdcnt.tickcnt = 0; bus->sdcnt.tickcnt = 0;
brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
down(&bus->sdsem); sdio_claim_host(bus->sdiodev->func[1]);
/* Make sure backplane clock is on, needed to generate F2 interrupt */ /* Make sure backplane clock is on, needed to generate F2 interrupt */
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
...@@ -3470,7 +3490,7 @@ static int brcmf_sdbrcm_bus_init(struct device *dev) ...@@ -3470,7 +3490,7 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
exit: exit:
up(&bus->sdsem); sdio_release_host(bus->sdiodev->func[1]);
return ret; return ret;
} }
...@@ -3533,9 +3553,11 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) ...@@ -3533,9 +3553,11 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
u8 devpend; u8 devpend;
spin_unlock_irqrestore(&bus->dpc_tl_lock, spin_unlock_irqrestore(&bus->dpc_tl_lock,
flags); flags);
sdio_claim_host(bus->sdiodev->func[1]);
devpend = brcmf_sdio_regrb(bus->sdiodev, devpend = brcmf_sdio_regrb(bus->sdiodev,
SDIO_CCCR_INTx, SDIO_CCCR_INTx,
NULL); NULL);
sdio_release_host(bus->sdiodev->func[1]);
intstatus = intstatus =
devpend & (INTR_STATUS_FUNC1 | devpend & (INTR_STATUS_FUNC1 |
INTR_STATUS_FUNC2); INTR_STATUS_FUNC2);
...@@ -3565,13 +3587,13 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) ...@@ -3565,13 +3587,13 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
bus->console.count += BRCMF_WD_POLL_MS; bus->console.count += BRCMF_WD_POLL_MS;
if (bus->console.count >= bus->console_interval) { if (bus->console.count >= bus->console_interval) {
bus->console.count -= bus->console_interval; bus->console.count -= bus->console_interval;
down(&bus->sdsem); sdio_claim_host(bus->sdiodev->func[1]);
/* Make sure backplane clock is on */ /* Make sure backplane clock is on */
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
if (brcmf_sdbrcm_readconsole(bus) < 0) if (brcmf_sdbrcm_readconsole(bus) < 0)
/* stop on error */ /* stop on error */
bus->console_interval = 0; bus->console_interval = 0;
up(&bus->sdsem); sdio_release_host(bus->sdiodev->func[1]);
} }
} }
#endif /* DEBUG */ #endif /* DEBUG */
...@@ -3584,9 +3606,9 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) ...@@ -3584,9 +3606,9 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
bus->activity = false; bus->activity = false;
brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS); brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
} else { } else {
down(&bus->sdsem); sdio_claim_host(bus->sdiodev->func[1]);
brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
up(&bus->sdsem); sdio_release_host(bus->sdiodev->func[1]);
} }
} }
} }
...@@ -3685,6 +3707,8 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva) ...@@ -3685,6 +3707,8 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
bus->alp_only = true; bus->alp_only = true;
sdio_claim_host(bus->sdiodev->func[1]);
pr_debug("F1 signature read @0x18000000=0x%4x\n", pr_debug("F1 signature read @0x18000000=0x%4x\n",
brcmf_sdio_regrl(bus->sdiodev, SI_ENUM_BASE, NULL)); brcmf_sdio_regrl(bus->sdiodev, SI_ENUM_BASE, NULL));
...@@ -3732,6 +3756,8 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva) ...@@ -3732,6 +3756,8 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
reg_val = brcmf_sdio_regrl(bus->sdiodev, reg_addr, NULL); reg_val = brcmf_sdio_regrl(bus->sdiodev, reg_addr, NULL);
brcmf_sdio_regwl(bus->sdiodev, reg_addr, reg_val | CC_BPRESEN, NULL); brcmf_sdio_regwl(bus->sdiodev, reg_addr, reg_val | CC_BPRESEN, NULL);
sdio_release_host(bus->sdiodev->func[1]);
brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN); brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);
/* Locate an appropriately-aligned portion of hdrbuf */ /* Locate an appropriately-aligned portion of hdrbuf */
...@@ -3747,6 +3773,7 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva) ...@@ -3747,6 +3773,7 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
return true; return true;
fail: fail:
sdio_release_host(bus->sdiodev->func[1]);
return false; return false;
} }
...@@ -3754,6 +3781,8 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus) ...@@ -3754,6 +3781,8 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus)
{ {
brcmf_dbg(TRACE, "Enter\n"); brcmf_dbg(TRACE, "Enter\n");
sdio_claim_host(bus->sdiodev->func[1]);
/* Disable F2 to clear any intermediate frame state on the dongle */ /* Disable F2 to clear any intermediate frame state on the dongle */
brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx, brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx,
SDIO_FUNC_ENABLE_1, NULL); SDIO_FUNC_ENABLE_1, NULL);
...@@ -3764,6 +3793,8 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus) ...@@ -3764,6 +3793,8 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus)
/* Done with backplane-dependent accesses, can drop clock... */ /* Done with backplane-dependent accesses, can drop clock... */
brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
sdio_release_host(bus->sdiodev->func[1]);
/* ...and initialize clock/power states */ /* ...and initialize clock/power states */
bus->clkstate = CLK_SDONLY; bus->clkstate = CLK_SDONLY;
bus->idletime = BRCMF_IDLE_INTERVAL; bus->idletime = BRCMF_IDLE_INTERVAL;
...@@ -3819,8 +3850,10 @@ static void brcmf_sdbrcm_release_dongle(struct brcmf_sdio *bus) ...@@ -3819,8 +3850,10 @@ static void brcmf_sdbrcm_release_dongle(struct brcmf_sdio *bus)
brcmf_dbg(TRACE, "Enter\n"); brcmf_dbg(TRACE, "Enter\n");
if (bus->ci) { if (bus->ci) {
sdio_claim_host(bus->sdiodev->func[1]);
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
sdio_release_host(bus->sdiodev->func[1]);
brcmf_sdio_chip_detach(&bus->ci); brcmf_sdio_chip_detach(&bus->ci);
if (bus->vars && bus->varsz) if (bus->vars && bus->varsz)
kfree(bus->vars); kfree(bus->vars);
...@@ -3905,9 +3938,6 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) ...@@ -3905,9 +3938,6 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
bus->timer.data = (unsigned long)bus; bus->timer.data = (unsigned long)bus;
bus->timer.function = brcmf_sdbrcm_watchdog; bus->timer.function = brcmf_sdbrcm_watchdog;
/* Initialize thread based operation and lock */
sema_init(&bus->sdsem, 1);
/* Initialize watchdog thread */ /* Initialize watchdog thread */
init_completion(&bus->watchdog_wait); init_completion(&bus->watchdog_wait);
bus->watchdog_tsk = kthread_run(brcmf_sdbrcm_watchdog_thread, bus->watchdog_tsk = kthread_run(brcmf_sdbrcm_watchdog_thread,
......
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