提交 dd43a01c 编写于 作者: F Franky Lin 提交者: John W. Linville

brcmfmac: use dynamically allocated control frame buffer

Rxbuf in SDIO interface is used in normal frame and control frame
read. Use dynamically allocated buffer in control frame read path
for post processing to avoid conflicts.
Signed-off-by: NFranky Lin <frankyl@broadcom.com>
Signed-off-by: NJohn W. Linville <linville@tuxdriver.com>
上级 bb451c83
......@@ -533,9 +533,11 @@ struct brcmf_sdio {
u8 *rxbuf; /* Buffer for receiving control packets */
uint rxblen; /* Allocated length of rxbuf */
u8 *rxctl; /* Aligned pointer into rxbuf */
u8 *rxctl_orig; /* pointer for freeing rxctl */
u8 *databuf; /* Buffer for receiving big glom packet */
u8 *dataptr; /* Aligned pointer into databuf */
uint rxlen; /* Length of valid data in buffer */
spinlock_t rxctl_lock; /* protection lock for ctrl frame resources */
u8 sdpcm_ver; /* Bus protocol reported by dongle */
......@@ -1442,21 +1444,24 @@ static void
brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
{
uint rdlen, pad;
u8 *buf = NULL, *rbuf;
int sdret;
brcmf_dbg(TRACE, "Enter\n");
/* Set rxctl for frame (w/optional alignment) */
bus->rxctl = bus->rxbuf;
bus->rxctl += BRCMF_FIRSTREAD;
pad = ((unsigned long)bus->rxctl % BRCMF_SDALIGN);
if (bus->rxblen)
buf = vzalloc(bus->rxblen);
if (!buf) {
brcmf_dbg(ERROR, "no memory for control frame\n");
goto done;
}
rbuf = bus->rxbuf;
pad = ((unsigned long)rbuf % BRCMF_SDALIGN);
if (pad)
bus->rxctl += (BRCMF_SDALIGN - pad);
bus->rxctl -= BRCMF_FIRSTREAD;
rbuf += (BRCMF_SDALIGN - pad);
/* Copy the already-read portion over */
memcpy(bus->rxctl, hdr, BRCMF_FIRSTREAD);
memcpy(buf, hdr, BRCMF_FIRSTREAD);
if (len <= BRCMF_FIRSTREAD)
goto gotpkt;
......@@ -1493,11 +1498,11 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
goto done;
}
/* Read remainder of frame body into the rxctl buffer */
/* Read remain of frame body */
sdret = brcmf_sdcard_recv_buf(bus->sdiodev,
bus->sdiodev->sbwad,
SDIO_FUNC_2,
F2SYNC, (bus->rxctl + BRCMF_FIRSTREAD), rdlen);
F2SYNC, rbuf, rdlen);
bus->sdcnt.f2rxdata++;
/* Control frame failures need retransmission */
......@@ -1507,16 +1512,26 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
bus->sdcnt.rxc_errors++;
brcmf_sdbrcm_rxfail(bus, true, true);
goto done;
}
} else
memcpy(buf + BRCMF_FIRSTREAD, rbuf, rdlen);
gotpkt:
brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_CTL_ON(),
bus->rxctl, len, "RxCtrl:\n");
buf, len, "RxCtrl:\n");
/* Point to valid data and indicate its length */
bus->rxctl += doff;
spin_lock_bh(&bus->rxctl_lock);
if (bus->rxctl) {
brcmf_dbg(ERROR, "last control frame is being processed.\n");
spin_unlock_bh(&bus->rxctl_lock);
vfree(buf);
goto done;
}
bus->rxctl = buf + doff;
bus->rxctl_orig = buf;
bus->rxlen = len - doff;
spin_unlock_bh(&bus->rxctl_lock);
done:
/* Awake any waiters */
......@@ -2023,7 +2038,9 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
brcmf_sdbrcm_free_glom(bus);
/* Clear rx control and wake any waiters */
spin_lock_bh(&bus->rxctl_lock);
bus->rxlen = 0;
spin_unlock_bh(&bus->rxctl_lock);
brcmf_sdbrcm_dcmd_resp_wake(bus);
/* Reset some F2 state stuff */
......@@ -2989,6 +3006,7 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
int timeleft;
uint rxlen = 0;
bool pending;
u8 *buf;
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
struct brcmf_sdio *bus = sdiodev->bus;
......@@ -2998,11 +3016,15 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
/* Wait until control frame is available */
timeleft = brcmf_sdbrcm_dcmd_resp_wait(bus, &bus->rxlen, &pending);
down(&bus->sdsem);
spin_lock_bh(&bus->rxctl_lock);
rxlen = bus->rxlen;
memcpy(msg, bus->rxctl, min(msglen, rxlen));
bus->rxctl = NULL;
buf = bus->rxctl_orig;
bus->rxctl_orig = NULL;
bus->rxlen = 0;
up(&bus->sdsem);
spin_unlock_bh(&bus->rxctl_lock);
vfree(buf);
if (rxlen) {
brcmf_dbg(CTL, "resumed on rxctl frame, got %d expected %d\n",
......@@ -3860,6 +3882,7 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
goto fail;
}
spin_lock_init(&bus->rxctl_lock);
spin_lock_init(&bus->txqlock);
init_waitqueue_head(&bus->ctrl_wait);
init_waitqueue_head(&bus->dcmd_resp_wait);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册