* read directly into the chained packet, or allocate a large
* packet and and copy into the chain.
*/
+ down(&bus->sdsem);
if (usechain) {
errcode = brcmf_sdcard_recv_chain(bus->sdiodev,
bus->sdiodev->sbwad,
dlen);
errcode = -1;
}
+ up(&bus->sdsem);
bus->sdcnt.f2rxdata++;
/* On failure, kill the superframe, allow a couple retries */
pfirst->prev);
}
/* sent any remaining packets up */
- if (bus->glom.qlen) {
- up(&bus->sdsem);
+ if (bus->glom.qlen)
brcmf_rx_frame(bus->sdiodev->dev, ifidx, &bus->glom);
- down(&bus->sdsem);
- }
bus->sdcnt.rxglomframes++;
bus->sdcnt.rxglompkts += bus->glom.qlen;
rd->len_left = rd->len;
/* read header first for unknow frame length */
+ down(&bus->sdsem);
if (!rd->len) {
sdret = brcmf_sdcard_recv_buf(bus->sdiodev,
bus->sdiodev->sbwad,
sdret);
bus->sdcnt.rx_hdrfail++;
brcmf_sdbrcm_rxfail(bus, true, true);
+ up(&bus->sdsem);
continue;
}
if (!brcmf_sdio_hdparser(bus, bus->rxhdr, rd,
BRCMF_SDIO_FT_NORMAL)) {
+ up(&bus->sdsem);
if (!bus->rxpending)
break;
else
rd->len_nxtfrm = 0;
/* treat all packet as event if we don't know */
rd->channel = SDPCM_EVENT_CHANNEL;
+ up(&bus->sdsem);
continue;
}
rd->len_left = rd->len > BRCMF_FIRSTREAD ?
bus->sdiodev->bus_if->dstats.rx_dropped++;
brcmf_sdbrcm_rxfail(bus, false,
RETRYCHAN(rd->channel));
+ up(&bus->sdsem);
continue;
}
skb_pull(pkt, head_read);
sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad,
SDIO_FUNC_2, F2SYNC, pkt);
bus->sdcnt.f2rxdata++;
+ up(&bus->sdsem);
if (sdret < 0) {
brcmf_dbg(ERROR, "read %d bytes from channel %d failed: %d\n",
continue;
}
- /* Unlock during rx call */
- up(&bus->sdsem);
brcmf_rx_packet(bus->sdiodev->dev, ifidx, pkt);
- down(&bus->sdsem);
}
rxcount = maxframes - rxleft;
static void
brcmf_sdbrcm_wait_for_event(struct brcmf_sdio *bus, bool *lockvar)
{
- up(&bus->sdsem);
wait_event_interruptible_timeout(bus->ctrl_wait, !*lockvar, HZ * 2);
- down(&bus->sdsem);
return;
}
if (len & (ALIGNMENT - 1))
len = roundup(len, ALIGNMENT);
+ down(&bus->sdsem);
ret = brcmf_sdcard_send_pkt(bus->sdiodev, bus->sdiodev->sbwad,
SDIO_FUNC_2, F2SYNC, pkt);
bus->sdcnt.f2txdata++;
}
}
+ up(&bus->sdsem);
if (ret == 0)
bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
done:
/* restore pkt buffer pointer before calling tx complete routine */
skb_pull(pkt, SDPCM_HDRLEN + pad);
- up(&bus->sdsem);
brcmf_txcomplete(bus->sdiodev->dev, pkt, ret != 0);
- down(&bus->sdsem);
if (free_pkt)
brcmu_pkt_buf_free_skb(pkt);
/* In poll mode, need to check for other events */
if (!bus->intr && cnt) {
/* Check device status, signal pending interrupt */
+ down(&bus->sdsem);
ret = r_sdreg32(bus, &intstatus,
offsetof(struct sdpcmd_regs,
intstatus));
+ up(&bus->sdsem);
bus->sdcnt.f2txdata++;
if (ret != 0)
break;
/* Turn off the backplane clock (only) */
brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
+ up(&bus->sdsem);
/* Clear the data packet queues */
brcmu_pktq_flush(&bus->txq, true, NULL, NULL);
/* Reset some F2 state stuff */
bus->rxskip = false;
bus->tx_seq = bus->rx_seq = 0;
-
- up(&bus->sdsem);
}
#ifdef CONFIG_BRCMFMAC_SDIO_OOB
intstatus |= brcmf_sdbrcm_hostmail(bus);
}
+ up(&bus->sdsem);
+
/* Generally don't ask for these, can get CRC errors... */
if (intstatus & I_WR_OOSYNC) {
brcmf_dbg(ERROR, "Dongle reports WR_OOSYNC\n");
(bus->clkstate == CLK_AVAIL)) {
int i;
+ down(&bus->sdsem);
err = brcmf_sdcard_send_buf(bus->sdiodev, bus->sdiodev->sbwad,
SDIO_FUNC_2, F2SYNC, bus->ctrl_frame_buf,
(u32) bus->ctrl_frame_len);
} else {
bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
}
+ up(&bus->sdsem);
bus->ctrl_frame_stat = false;
brcmf_sdbrcm_wait_event_wakeup(bus);
}
bus->activity = false;
brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
}
-
- up(&bus->sdsem);
}
static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
/* precondition: IS_ALIGNED((unsigned long)frame, 2) */
- /* Need to lock here to protect txseq and SDIO tx calls */
- down(&bus->sdsem);
-
/* Make sure backplane clock is on */
+ down(&bus->sdsem);
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+ up(&bus->sdsem);
/* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
*(__le16 *) frame = cpu_to_le16((u16) msglen);
frame, min_t(u16, len, 16), "TxHdr:\n");
do {
+ down(&bus->sdsem);
ret = brcmf_tx_frame(bus, frame, len);
+ up(&bus->sdsem);
} while (ret < 0 && retries++ < TXRETRIES);
}
spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
bus->activity = false;
+ down(&bus->sdsem);
brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
+ up(&bus->sdsem);
} else {
spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
}
- up(&bus->sdsem);
-
if (ret)
bus->sdcnt.tx_ctlerrs++;
else
* Read last word in socram to determine
* address of sdpcm_shared structure
*/
+ down(&bus->sdsem);
rv = brcmf_sdbrcm_membytes(bus, false, shaddr,
(u8 *)&addr_le, 4);
+ up(&bus->sdsem);
if (rv < 0)
return rv;
if ((sh->flags & SDPCM_SHARED_TRAP) == 0)
return 0;
+ down(&bus->sdsem);
error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr,
sizeof(struct brcmf_trap_info));
if (error < 0)
return error;
nbytes = brcmf_sdio_dump_console(bus, sh, data, count);
+ up(&bus->sdsem);
if (nbytes < 0)
return nbytes;
return 0;
}
+ down(&bus->sdsem);
if (sh->assert_file_addr != 0) {
error = brcmf_sdbrcm_membytes(bus, false, sh->assert_file_addr,
(u8 *)file, 80);
if (error < 0)
return error;
}
+ up(&bus->sdsem);
res = scnprintf(buf, sizeof(buf),
"dongle assert: %s:%d: assert(%s)\n",
int error;
struct sdpcm_shared sh;
- down(&bus->sdsem);
error = brcmf_sdio_readshared(bus, &sh);
- up(&bus->sdsem);
if (error < 0)
return error;
if (pos != 0)
return 0;
- down(&bus->sdsem);
error = brcmf_sdio_readshared(bus, &sh);
if (error < 0)
goto done;
error += nbytes;
*ppos += error;
done:
- up(&bus->sdsem);
return error;
}
brcmf_dbg(TIMER, "Enter\n");
- down(&bus->sdsem);
-
/* Poll period: check device if appropriate. */
if (bus->poll && (++bus->polltick >= bus->pollrate)) {
u32 intstatus = 0;
bus->console.count += BRCMF_WD_POLL_MS;
if (bus->console.count >= bus->console_interval) {
bus->console.count -= bus->console_interval;
+ down(&bus->sdsem);
/* Make sure backplane clock is on */
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
if (brcmf_sdbrcm_readconsole(bus) < 0)
/* stop on error */
bus->console_interval = 0;
+ up(&bus->sdsem);
}
}
#endif /* DEBUG */
bus->activity = false;
brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
} else {
+ down(&bus->sdsem);
brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
+ up(&bus->sdsem);
}
}
}
- up(&bus->sdsem);
-
return (atomic_read(&bus->ipend) > 0);
}