diff options
author | Arend van Spriel <arend@broadcom.com> | 2011-11-22 17:21:38 -0800 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-11-28 14:43:28 -0500 |
commit | 5adfeb632c52a6c15e98fa6465bdade6fff915d9 (patch) | |
tree | 3e1284a88a535fedf1933dff75f1b09f344bdf18 /drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | |
parent | 3030794fcae9b07d62a9ff7649a413dff0c88e01 (diff) | |
download | linux-next-5adfeb632c52a6c15e98fa6465bdade6fff915d9.tar.gz |
brcm80211: fmac: separate receiving skb chain from other receive path
In the receive path the buffer used to store the receive data from the
device can be a chain of sk_buff. It has been separated to allow the
use of skb queues.
Reported-by: Johannes Berg <johannes@sipsolutions.net>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: Alwin Beukers <alwin@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Franky Lin <frankyl@broadcom.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c')
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | 97 |
1 files changed, 72 insertions, 25 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index bbaeb2d5c93a..4e75c191c290 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c @@ -204,16 +204,79 @@ int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, return err_ret; } +/* precondition: host controller is claimed */ +static int +brcmf_sdioh_request_data(struct brcmf_sdio_dev *sdiodev, uint write, bool fifo, + uint func, uint addr, struct sk_buff *pkt, uint pktlen) +{ + int err_ret = 0; + + if ((write) && (!fifo)) { + err_ret = sdio_memcpy_toio(sdiodev->func[func], addr, + ((u8 *) (pkt->data)), pktlen); + } else if (write) { + err_ret = sdio_memcpy_toio(sdiodev->func[func], addr, + ((u8 *) (pkt->data)), pktlen); + } else if (fifo) { + err_ret = sdio_readsb(sdiodev->func[func], + ((u8 *) (pkt->data)), addr, pktlen); + } else { + err_ret = sdio_memcpy_fromio(sdiodev->func[func], + ((u8 *) (pkt->data)), + addr, pktlen); + } + + return err_ret; +} + static int brcmf_sdioh_request_packet(struct brcmf_sdio_dev *sdiodev, uint fix_inc, uint write, uint func, uint addr, struct sk_buff *pkt) { bool fifo = (fix_inc == SDIOH_DATA_FIX); + int err_ret = 0; + uint pkt_len = pkt->len; + + brcmf_dbg(TRACE, "Enter\n"); + + brcmf_pm_resume_wait(sdiodev, &sdiodev->request_packet_wait); + if (brcmf_pm_resume_error(sdiodev)) + return -EIO; + + /* Claim host controller */ + sdio_claim_host(sdiodev->func[func]); + + pkt_len += 3; + pkt_len &= 0xFFFFFFFC; + + err_ret = brcmf_sdioh_request_data(sdiodev, write, fifo, func, + addr, pkt, pkt_len); + if (err_ret) { + brcmf_dbg(ERROR, "%s FAILED %p, addr=0x%05x, pkt_len=%d, ERR=0x%08x\n", + write ? "TX" : "RX", pkt, addr, pkt_len, err_ret); + } else { + brcmf_dbg(TRACE, "%s xfr'd %p, addr=0x%05x, len=%d\n", + write ? "TX" : "RX", pkt, addr, pkt_len); + } + + /* Release host controller */ + sdio_release_host(sdiodev->func[func]); + + brcmf_dbg(TRACE, "Exit\n"); + return err_ret; +} + +int +brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc, + uint write, uint func, uint addr, + struct sk_buff_head *pktq) +{ + bool fifo = (fix_inc == SDIOH_DATA_FIX); u32 SGCount = 0; int err_ret = 0; - struct sk_buff *pnext; + struct sk_buff *pkt; brcmf_dbg(TRACE, "Enter\n"); @@ -223,43 +286,27 @@ brcmf_sdioh_request_packet(struct brcmf_sdio_dev *sdiodev, uint fix_inc, /* Claim host controller */ sdio_claim_host(sdiodev->func[func]); - for (pnext = pkt; pnext; pnext = pnext->next) { - uint pkt_len = pnext->len; + + skb_queue_walk(pktq, pkt) { + uint pkt_len = pkt->len; pkt_len += 3; pkt_len &= 0xFFFFFFFC; - if ((write) && (!fifo)) { - err_ret = sdio_memcpy_toio(sdiodev->func[func], addr, - ((u8 *) (pnext->data)), - pkt_len); - } else if (write) { - err_ret = sdio_memcpy_toio(sdiodev->func[func], addr, - ((u8 *) (pnext->data)), - pkt_len); - } else if (fifo) { - err_ret = sdio_readsb(sdiodev->func[func], - ((u8 *) (pnext->data)), - addr, pkt_len); - } else { - err_ret = sdio_memcpy_fromio(sdiodev->func[func], - ((u8 *) (pnext->data)), - addr, pkt_len); - } - + err_ret = brcmf_sdioh_request_data(sdiodev, write, fifo, func, + addr, pkt, pkt_len); if (err_ret) { brcmf_dbg(ERROR, "%s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=0x%08x\n", - write ? "TX" : "RX", pnext, SGCount, addr, + write ? "TX" : "RX", pkt, SGCount, addr, pkt_len, err_ret); } else { brcmf_dbg(TRACE, "%s xfr'd %p[%d], addr=0x%05x, len=%d\n", - write ? "TX" : "RX", pnext, SGCount, addr, + write ? "TX" : "RX", pkt, SGCount, addr, pkt_len); } - if (!fifo) addr += pkt_len; - SGCount++; + SGCount++; } /* Release host controller */ |