2013-06-18 11:29:49

by Arend van Spriel

[permalink] [raw]
Subject: [PATCH 0/8] brcmfmac: scatterlist support in sdio and cleanup

This series contains mostly cleanup patches. The main change is the
support for scatterlist api in sdio part of the brcmfmac driver.

The series is intended for v3.11 and applies to the master branch
of the wireless-next repository.

Arend van Spriel (4):
brcmfmac: rename variable prec to more appropriate name, ie. fifo
brcmfmac: remove dependency with nl80211.h
brcmfmac: consolidate mac_descriptor related function names
brcmfmac: simplify dpc handling using atomic operations

Franky Lin (3):
brcmfmac: remove redundant chip ID check in dhd_sdio
brcmfmac: replace brcmf_sdioh_request_buffer with brcmf_sdio_buffrw
brcmfmac: add sdio sg list support

Hante Meuleman (1):
brcmfmac: Only use credits for bcmc when firmware indicates it.

drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 179 ++++++++++++++++++--
.../net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | 114 +------------
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 174 ++-----------------
drivers/net/wireless/brcm80211/brcmfmac/fweh.h | 3 +-
drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 96 +++++++----
.../net/wireless/brcm80211/brcmfmac/sdio_host.h | 15 +-
6 files changed, 252 insertions(+), 329 deletions(-)

--
1.7.10.4




2013-06-18 11:29:41

by Arend van Spriel

[permalink] [raw]
Subject: [PATCH 8/8] brcmfmac: add sdio sg list support

From: Franky Lin <[email protected]>

Add scatter gather list support for better rx glom performance.

Reviewed-by: Hante Meuleman <[email protected]>
Reviewed-by: Pieter-Paul Giesberts <[email protected]>
Reviewed-by: Arend van Spriel <[email protected]>
Signed-off-by: Franky Lin <[email protected]>
Signed-off-by: Arend van Spriel <[email protected]>
---
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 149 +++++++++++++++++---
.../net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | 73 ----------
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 82 +----------
.../net/wireless/brcm80211/brcmfmac/sdio_host.h | 7 -
4 files changed, 137 insertions(+), 174 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 32a205e..3f8e69c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -22,9 +22,11 @@
#include <linux/pci_ids.h>
#include <linux/sched.h>
#include <linux/completion.h>
+#include <linux/scatterlist.h>
#include <linux/mmc/sdio.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
#include <linux/platform_data/brcmfmac-sdio.h>

#include <defs.h>
@@ -316,34 +318,138 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
* caller has already been padded and aligned.
*/
static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
- bool write, u32 addr, struct sk_buff *pkt)
+ bool write, u32 addr, struct sk_buff_head *pktlist)
{
- uint len;
+ unsigned int req_sz, func_blk_sz, sg_cnt, sg_data_sz, pkt_offset;
+ unsigned int max_blks, max_req_sz;
+ unsigned short max_seg_sz, seg_sz;
+ unsigned char *pkt_data;
+ struct sk_buff *pkt_next = NULL;
+ struct mmc_request mmc_req;
+ struct mmc_command mmc_cmd;
+ struct mmc_data mmc_dat;
+ struct sg_table st;
+ struct scatterlist *sgl;
+ struct mmc_host *host;
+ int ret = 0;
+
+ if (!pktlist->qlen)
+ return -EINVAL;

brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait);
if (brcmf_pm_resume_error(sdiodev))
return -EIO;

/* Single skb use the standard mmc interface */
- if (!pkt->next) {
- len = pkt->len + 3;
- len &= (uint)~3;
+ if (pktlist->qlen == 1) {
+ pkt_next = pktlist->next;
+ req_sz = pkt_next->len + 3;
+ req_sz &= (uint)~3;

if (write)
return sdio_memcpy_toio(sdiodev->func[fn], addr,
- ((u8 *)(pkt->data)), len);
+ ((u8 *)(pkt_next->data)),
+ req_sz);
else if (fn == 1)
return sdio_memcpy_fromio(sdiodev->func[fn],
- ((u8 *)(pkt->data)), addr,
- len);
+ ((u8 *)(pkt_next->data)),
+ addr, req_sz);
else
/* function 2 read is FIFO operation */
return sdio_readsb(sdiodev->func[fn],
- ((u8 *)(pkt->data)), addr, len);
+ ((u8 *)(pkt_next->data)), addr,
+ req_sz);
}

- brcmf_err("skb chain is not supported yet.\n");
- return -EOPNOTSUPP;
+ host = sdiodev->func[fn]->card->host;
+ func_blk_sz = sdiodev->func[fn]->cur_blksize;
+ /* Blocks per command is limited by host count, host transfer
+ * size and the maximum for IO_RW_EXTENDED of 511 blocks.
+ */
+ max_blks = min_t(unsigned int, host->max_blk_count, 511u);
+ max_req_sz = min_t(unsigned int, host->max_req_size,
+ max_blks * func_blk_sz);
+ max_seg_sz = min_t(unsigned short, host->max_segs, SG_MAX_SINGLE_ALLOC);
+ max_seg_sz = min_t(unsigned short, max_seg_sz, pktlist->qlen);
+ seg_sz = pktlist->qlen;
+ pkt_offset = 0;
+ pkt_next = pktlist->next;
+
+ if (sg_alloc_table(&st, max_seg_sz, GFP_KERNEL))
+ return -ENOMEM;
+
+ while (seg_sz) {
+ req_sz = 0;
+ sg_cnt = 0;
+ memset(&mmc_req, 0, sizeof(struct mmc_request));
+ memset(&mmc_cmd, 0, sizeof(struct mmc_command));
+ memset(&mmc_dat, 0, sizeof(struct mmc_data));
+ sgl = st.sgl;
+ /* prep sg table */
+ while (pkt_next != (struct sk_buff *)pktlist) {
+ pkt_data = pkt_next->data + pkt_offset;
+ sg_data_sz = pkt_next->len - pkt_offset;
+ if (sg_data_sz > host->max_seg_size)
+ sg_data_sz = host->max_seg_size;
+ if (sg_data_sz > max_req_sz - req_sz)
+ sg_data_sz = max_req_sz - req_sz;
+
+ sg_set_buf(sgl, pkt_data, sg_data_sz);
+
+ sg_cnt++;
+ sgl = sg_next(sgl);
+ req_sz += sg_data_sz;
+ pkt_offset += sg_data_sz;
+ if (pkt_offset == pkt_next->len) {
+ pkt_offset = 0;
+ pkt_next = pkt_next->next;
+ }
+
+ if (req_sz >= max_req_sz || sg_cnt >= max_seg_sz)
+ break;
+ }
+ seg_sz -= sg_cnt;
+
+ if (req_sz % func_blk_sz != 0) {
+ brcmf_err("sg request length %u is not %u aligned\n",
+ req_sz, func_blk_sz);
+ sg_free_table(&st);
+ return -ENOTBLK;
+ }
+ mmc_dat.sg = st.sgl;
+ mmc_dat.sg_len = sg_cnt;
+ mmc_dat.blksz = func_blk_sz;
+ mmc_dat.blocks = req_sz / func_blk_sz;
+ mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
+ mmc_cmd.opcode = SD_IO_RW_EXTENDED;
+ mmc_cmd.arg = write ? 1<<31 : 0; /* write flag */
+ mmc_cmd.arg |= (fn & 0x7) << 28; /* SDIO func num */
+ mmc_cmd.arg |= 1<<27; /* block mode */
+ /* incrementing addr for function 1 */
+ mmc_cmd.arg |= (fn == 1) ? 1<<26 : 0;
+ mmc_cmd.arg |= (addr & 0x1FFFF) << 9; /* address */
+ mmc_cmd.arg |= mmc_dat.blocks & 0x1FF; /* block count */
+ mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
+ mmc_req.cmd = &mmc_cmd;
+ mmc_req.data = &mmc_dat;
+ if (fn == 1)
+ addr += req_sz;
+
+ mmc_set_data_timeout(&mmc_dat, sdiodev->func[fn]->card);
+ mmc_wait_for_req(host, &mmc_req);
+
+ ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error;
+ if (ret != 0) {
+ brcmf_err("CMD53 sg block %s failed %d\n",
+ write ? "write" : "read", ret);
+ ret = -EIO;
+ break;
+ }
+ }
+
+ sg_free_table(&st);
+
+ return ret;
}

static int brcmf_sdcard_recv_prepare(struct brcmf_sdio_dev *sdiodev, uint fn,
@@ -400,6 +506,7 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
{
uint width;
int err = 0;
+ struct sk_buff_head pkt_list;

brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n",
fn, addr, pkt->len);
@@ -409,7 +516,10 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
if (err)
goto done;

- err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, pkt);
+ skb_queue_head_init(&pkt_list);
+ skb_queue_tail(&pkt_list, pkt);
+ err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, &pkt_list);
+ skb_dequeue_tail(&pkt_list);

done:
return err;
@@ -431,8 +541,7 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
goto done;

incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
- err = brcmf_sdioh_request_chain(sdiodev, incr_fix, SDIOH_READ, fn, addr,
- pktq);
+ err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, pktq);

done:
return err;
@@ -467,6 +576,7 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
uint width;
uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
int err = 0;
+ struct sk_buff_head pkt_list;

brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n",
fn, addr, pkt->len);
@@ -489,7 +599,10 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
if (width == 4)
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;

- err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, pkt);
+ skb_queue_head_init(&pkt_list);
+ skb_queue_tail(&pkt_list, pkt);
+ err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, &pkt_list);
+ skb_dequeue_tail(&pkt_list);

done:
return err;
@@ -503,6 +616,7 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
struct sk_buff *pkt;
u32 sdaddr;
uint dsize;
+ struct sk_buff_head pkt_list;

dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size);
pkt = dev_alloc_skb(dsize);
@@ -511,6 +625,7 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
return -EIO;
}
pkt->priority = 0;
+ skb_queue_head_init(&pkt_list);

/* Determine initial transfer parameters */
sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
@@ -538,8 +653,10 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
skb_put(pkt, dsize);
if (write)
memcpy(pkt->data, data, dsize);
+ skb_queue_tail(&pkt_list, pkt);
bcmerror = brcmf_sdio_buffrw(sdiodev, SDIO_FUNC_1, write,
- sdaddr, pkt);
+ sdaddr, &pkt_list);
+ skb_dequeue_tail(&pkt_list);
if (bcmerror) {
brcmf_err("membytes transfer failed\n");
break;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index 7a3c5bf..289e386 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -211,78 +211,6 @@ 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;
-}
-
-/*
- * This function takes a queue of packets. The packets on the queue
- * are assumed to be properly aligned by the caller.
- */
-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 *pkt;
-
- brcmf_dbg(SDIO, "Enter\n");
-
- brcmf_pm_resume_wait(sdiodev, &sdiodev->request_chain_wait);
- if (brcmf_pm_resume_error(sdiodev))
- return -EIO;
-
- skb_queue_walk(pktq, pkt) {
- uint pkt_len = pkt->len;
- pkt_len += 3;
- pkt_len &= 0xFFFFFFFC;
-
- err_ret = brcmf_sdioh_request_data(sdiodev, write, fifo, func,
- addr, pkt, pkt_len);
- if (err_ret) {
- brcmf_err("%s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=0x%08x\n",
- write ? "TX" : "RX", pkt, SGCount, addr,
- pkt_len, err_ret);
- } else {
- brcmf_dbg(SDIO, "%s xfr'd %p[%d], addr=0x%05x, len=%d\n",
- write ? "TX" : "RX", pkt, SGCount, addr,
- pkt_len);
- }
- if (!fifo)
- addr += pkt_len;
-
- SGCount++;
- }
-
- brcmf_dbg(SDIO, "Exit\n");
- return err_ret;
-}
-
static int brcmf_sdioh_get_cisaddr(struct brcmf_sdio_dev *sdiodev, u32 regaddr)
{
/* read 24 bits and return valid 17 bit addr */
@@ -431,7 +359,6 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
atomic_set(&sdiodev->suspend, false);
init_waitqueue_head(&sdiodev->request_byte_wait);
init_waitqueue_head(&sdiodev->request_word_wait);
- init_waitqueue_head(&sdiodev->request_chain_wait);
init_waitqueue_head(&sdiodev->request_buffer_wait);

brcmf_dbg(SDIO, "F2 found, calling brcmf_sdio_probe...\n");
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index cb22f2f..2641119 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -448,8 +448,6 @@ struct brcmf_sdio {
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 */

@@ -473,8 +471,6 @@ struct brcmf_sdio {
s32 idletime; /* Control for activity timeout */
s32 idlecount; /* Activity timeout counter */
s32 idleclock; /* How to set bus driver when idle */
- s32 sd_rxchain;
- bool use_rxchain; /* If brcmf should use PKT chains */
bool rxflow_mode; /* Rx flow control mode */
bool rxflow; /* Is rx flow control on */
bool alp_only; /* Don't use HT clock (ALP only) */
@@ -1025,29 +1021,6 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx)
bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
}

-/* copy a buffer into a pkt buffer chain */
-static uint brcmf_sdbrcm_glom_from_buf(struct brcmf_sdio *bus, uint len)
-{
- uint n, ret = 0;
- struct sk_buff *p;
- u8 *buf;
-
- buf = bus->dataptr;
-
- /* copy the data */
- skb_queue_walk(&bus->glom, p) {
- n = min_t(uint, p->len, len);
- memcpy(p->data, buf, n);
- buf += n;
- len -= n;
- ret += n;
- if (!len)
- break;
- }
-
- return ret;
-}
-
/* return total length of buffer chain */
static uint brcmf_sdbrcm_glom_len(struct brcmf_sdio *bus)
{
@@ -1201,8 +1174,6 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
int errcode;
u8 doff, sfdoff;

- bool usechain = bus->use_rxchain;
-
struct brcmf_sdio_read rd_new;

/* If packets, issue read(s) and send up packet chain */
@@ -1237,7 +1208,6 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
if (sublen % BRCMF_SDALIGN) {
brcmf_err("sublen %d not multiple of %d\n",
sublen, BRCMF_SDALIGN);
- usechain = false;
}
totlen += sublen;

@@ -1304,27 +1274,9 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
* packet and and copy into the chain.
*/
sdio_claim_host(bus->sdiodev->func[1]);
- if (usechain) {
- errcode = brcmf_sdcard_recv_chain(bus->sdiodev,
- bus->sdiodev->sbwad,
- SDIO_FUNC_2, F2SYNC, &bus->glom);
- } else if (bus->dataptr) {
- errcode = brcmf_sdcard_recv_buf(bus->sdiodev,
- bus->sdiodev->sbwad,
- SDIO_FUNC_2, F2SYNC,
- bus->dataptr, dlen);
- sublen = (u16) brcmf_sdbrcm_glom_from_buf(bus, dlen);
- if (sublen != dlen) {
- brcmf_err("FAILED TO COPY, dlen %d sublen %d\n",
- dlen, sublen);
- errcode = -1;
- }
- pnext = NULL;
- } else {
- brcmf_err("COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n",
- dlen);
- errcode = -1;
- }
+ errcode = brcmf_sdcard_recv_chain(bus->sdiodev,
+ bus->sdiodev->sbwad,
+ SDIO_FUNC_2, F2SYNC, &bus->glom);
sdio_release_host(bus->sdiodev->func[1]);
bus->sdcnt.f2rxdata++;

@@ -3527,9 +3479,6 @@ static void brcmf_sdbrcm_release_malloc(struct brcmf_sdio *bus)
kfree(bus->rxbuf);
bus->rxctl = bus->rxbuf = NULL;
bus->rxlen = 0;
-
- kfree(bus->databuf);
- bus->databuf = NULL;
}

static bool brcmf_sdbrcm_probe_malloc(struct brcmf_sdio *bus)
@@ -3542,29 +3491,10 @@ static bool brcmf_sdbrcm_probe_malloc(struct brcmf_sdio *bus)
ALIGNMENT) + BRCMF_SDALIGN;
bus->rxbuf = kmalloc(bus->rxblen, GFP_ATOMIC);
if (!(bus->rxbuf))
- goto fail;
- }
-
- /* Allocate buffer to receive glomed packet */
- bus->databuf = kmalloc(MAX_DATA_BUF, GFP_ATOMIC);
- if (!(bus->databuf)) {
- /* release rxbuf which was already located as above */
- if (!bus->rxblen)
- kfree(bus->rxbuf);
- goto fail;
+ return false;
}

- /* Align the buffer */
- if ((unsigned long)bus->databuf % BRCMF_SDALIGN)
- bus->dataptr = bus->databuf + (BRCMF_SDALIGN -
- ((unsigned long)bus->databuf % BRCMF_SDALIGN));
- else
- bus->dataptr = bus->databuf;
-
return true;
-
-fail:
- return false;
}

static bool
@@ -3703,10 +3633,6 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus)
bus->blocksize = bus->sdiodev->func[2]->cur_blksize;
bus->roundup = min(max_roundup, bus->blocksize);

- /* bus module does not support packet chaining */
- bus->use_rxchain = false;
- bus->sd_rxchain = false;
-
/* SR state */
bus->sleeping = false;
bus->sr_enabled = false;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
index 991c1501..793df66 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
@@ -170,7 +170,6 @@ struct brcmf_sdio_dev {
atomic_t suspend; /* suspend flag */
wait_queue_head_t request_byte_wait;
wait_queue_head_t request_word_wait;
- wait_queue_head_t request_chain_wait;
wait_queue_head_t request_buffer_wait;
struct device *dev;
struct brcmf_bus *bus_if;
@@ -272,12 +271,6 @@ brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,
uint rw, uint fnc, uint addr,
u32 *word, uint nbyte);

-/* read or write any buffer using cmd53 */
-extern int
-brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc,
- uint write, uint func, uint addr,
- struct sk_buff_head *pktq);
-
/* Watchdog timer interface for pm ops */
extern void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev,
bool enable);
--
1.7.10.4



2013-06-18 11:29:41

by Arend van Spriel

[permalink] [raw]
Subject: [PATCH 6/8] brcmfmac: remove redundant chip ID check in dhd_sdio

From: Franky Lin <[email protected]>

There is an ID table registered to SDIO stack which consists of all SDIO devices
supported by brcmfmac. It is not necessary to have an extra check.

Reviewed-by: Hante Meuleman <[email protected]>
Reviewed-by: Pieter-Paul Giesberts <[email protected]>
Reviewed-by: Arend van Spriel <[email protected]>
Signed-off-by: Franky Lin <[email protected]>
Signed-off-by: Arend van Spriel <[email protected]>
---
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 22 --------------------
1 file changed, 22 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index d4db0c7..cb22f2f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -3509,23 +3509,6 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
return (atomic_read(&bus->ipend) > 0);
}

-static bool brcmf_sdbrcm_chipmatch(u16 chipid)
-{
- if (chipid == BCM43143_CHIP_ID)
- return true;
- if (chipid == BCM43241_CHIP_ID)
- return true;
- if (chipid == BCM4329_CHIP_ID)
- return true;
- if (chipid == BCM4330_CHIP_ID)
- return true;
- if (chipid == BCM4334_CHIP_ID)
- return true;
- if (chipid == BCM4335_CHIP_ID)
- return true;
- return false;
-}
-
static void brcmf_sdio_dataworker(struct work_struct *work)
{
struct brcmf_sdio *bus = container_of(work, struct brcmf_sdio,
@@ -3622,11 +3605,6 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
goto fail;
}

- if (!brcmf_sdbrcm_chipmatch((u16) bus->ci->chip)) {
- brcmf_err("unsupported chip: 0x%04x\n", bus->ci->chip);
- goto fail;
- }
-
if (brcmf_sdbrcm_kso_init(bus)) {
brcmf_err("error enabling KSO\n");
goto fail;
--
1.7.10.4



2013-06-18 11:29:49

by Arend van Spriel

[permalink] [raw]
Subject: [PATCH 5/8] brcmfmac: simplify dpc handling using atomic operations

Instead of allocating an empty list item and queue that for
the dpc data worker to dequeue an atomic counter is used.

Reviewed-by: Franky (Zhenhui) Lin <[email protected]>
Reviewed-by: Hante Meuleman <[email protected]>
Reviewed-by: Pieter-Paul Giesberts <[email protected]>
Signed-off-by: Arend van Spriel <[email protected]>
---
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 70 ++++----------------
1 file changed, 12 insertions(+), 58 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 6f3d181..d4db0c7 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -495,8 +495,7 @@ struct brcmf_sdio {

struct workqueue_struct *brcmf_wq;
struct work_struct datawork;
- struct list_head dpc_tsklst;
- spinlock_t dpc_tl_lock;
+ atomic_t dpc_tskcnt;

const struct firmware *firmware;
u32 fw_ptr;
@@ -2061,23 +2060,6 @@ static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus)
}
}

-static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus)
-{
- struct list_head *new_hd;
- unsigned long flags;
-
- if (in_interrupt())
- new_hd = kzalloc(sizeof(struct list_head), GFP_ATOMIC);
- else
- new_hd = kzalloc(sizeof(struct list_head), GFP_KERNEL);
- if (new_hd == NULL)
- return;
-
- spin_lock_irqsave(&bus->dpc_tl_lock, flags);
- list_add_tail(new_hd, &bus->dpc_tsklst);
- spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
-}
-
static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus)
{
u8 idx;
@@ -2312,7 +2294,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
(!atomic_read(&bus->fcstate) &&
brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) &&
data_ok(bus)) || PKT_AVAILABLE()) {
- brcmf_sdbrcm_adddpctsk(bus);
+ atomic_inc(&bus->dpc_tskcnt);
}

/* If we're done for now, turn off clock request. */
@@ -2342,7 +2324,6 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
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;
- unsigned long flags;

brcmf_dbg(TRACE, "Enter\n");

@@ -2381,14 +2362,9 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
qcount[prec] = pktq_plen(&bus->txq, prec);
#endif

- spin_lock_irqsave(&bus->dpc_tl_lock, flags);
- if (list_empty(&bus->dpc_tsklst)) {
- spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
-
- brcmf_sdbrcm_adddpctsk(bus);
+ if (atomic_read(&bus->dpc_tskcnt) == 0) {
+ atomic_inc(&bus->dpc_tskcnt);
queue_work(bus->brcmf_wq, &bus->datawork);
- } else {
- spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
}

return ret;
@@ -2525,7 +2501,6 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
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;
- unsigned long flags;

brcmf_dbg(TRACE, "Enter\n");

@@ -2612,18 +2587,13 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
} while (ret < 0 && retries++ < TXRETRIES);
}

- spin_lock_irqsave(&bus->dpc_tl_lock, flags);
if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) &&
- list_empty(&bus->dpc_tsklst)) {
- spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
-
+ atomic_read(&bus->dpc_tskcnt) == 0) {
bus->activity = false;
sdio_claim_host(bus->sdiodev->func[1]);
brcmf_dbg(INFO, "idle\n");
brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
sdio_release_host(bus->sdiodev->func[1]);
- } else {
- spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
}

if (ret)
@@ -3451,7 +3421,7 @@ void brcmf_sdbrcm_isr(void *arg)
if (!bus->intr)
brcmf_err("isr w/o interrupt configured!\n");

- brcmf_sdbrcm_adddpctsk(bus);
+ atomic_inc(&bus->dpc_tskcnt);
queue_work(bus->brcmf_wq, &bus->datawork);
}

@@ -3460,7 +3430,6 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
#ifdef DEBUG
struct brcmf_bus *bus_if = dev_get_drvdata(bus->sdiodev->dev);
#endif /* DEBUG */
- unsigned long flags;

brcmf_dbg(TIMER, "Enter\n");

@@ -3476,11 +3445,9 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
if (!bus->intr ||
(bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) {

- spin_lock_irqsave(&bus->dpc_tl_lock, flags);
- if (list_empty(&bus->dpc_tsklst)) {
+ if (atomic_read(&bus->dpc_tskcnt) == 0) {
u8 devpend;
- spin_unlock_irqrestore(&bus->dpc_tl_lock,
- flags);
+
sdio_claim_host(bus->sdiodev->func[1]);
devpend = brcmf_sdio_regrb(bus->sdiodev,
SDIO_CCCR_INTx,
@@ -3489,9 +3456,6 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
intstatus =
devpend & (INTR_STATUS_FUNC1 |
INTR_STATUS_FUNC2);
- } else {
- spin_unlock_irqrestore(&bus->dpc_tl_lock,
- flags);
}

/* If there is something, make like the ISR and
@@ -3500,7 +3464,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
bus->sdcnt.pollcnt++;
atomic_set(&bus->ipend, 1);

- brcmf_sdbrcm_adddpctsk(bus);
+ atomic_inc(&bus->dpc_tskcnt);
queue_work(bus->brcmf_wq, &bus->datawork);
}
}
@@ -3566,20 +3530,11 @@ static void brcmf_sdio_dataworker(struct work_struct *work)
{
struct brcmf_sdio *bus = container_of(work, struct brcmf_sdio,
datawork);
- struct list_head *cur_hd, *tmp_hd;
- unsigned long flags;
-
- spin_lock_irqsave(&bus->dpc_tl_lock, flags);
- list_for_each_safe(cur_hd, tmp_hd, &bus->dpc_tsklst) {
- spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);

+ while (atomic_read(&bus->dpc_tskcnt)) {
brcmf_sdbrcm_dpc(bus);
-
- spin_lock_irqsave(&bus->dpc_tl_lock, flags);
- list_del(cur_hd);
- kfree(cur_hd);
+ atomic_dec(&bus->dpc_tskcnt);
}
- spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
}

static void brcmf_sdbrcm_release_malloc(struct brcmf_sdio *bus)
@@ -3927,8 +3882,7 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
bus->watchdog_tsk = NULL;
}
/* Initialize DPC thread */
- INIT_LIST_HEAD(&bus->dpc_tsklst);
- spin_lock_init(&bus->dpc_tl_lock);
+ atomic_set(&bus->dpc_tskcnt, 0);

/* Assign bus interface call back */
bus->sdiodev->bus_if->dev = bus->sdiodev->dev;
--
1.7.10.4



2013-06-18 11:29:46

by Arend van Spriel

[permalink] [raw]
Subject: [PATCH 4/8] brcmfmac: consolidate mac_descriptor related function names

Just cleaning up and being consistent in naming operations
related to struct brcmf_fws_mac_descriptor objects.

Reviewed-by: Hante Meuleman <[email protected]>
Signed-off-by: Arend van Spriel <[email protected]>
---
drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 53 ++++++++++----------
1 file changed, 26 insertions(+), 27 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
index b702f3e..13e75c4 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -631,8 +631,8 @@ static void brcmf_fws_macdesc_set_name(struct brcmf_fws_info *fws,
desc->interface_id);
}

-static void brcmf_fws_init_mac_descriptor(struct brcmf_fws_mac_descriptor *desc,
- u8 *addr, u8 ifidx)
+static void brcmf_fws_macdesc_init(struct brcmf_fws_mac_descriptor *desc,
+ u8 *addr, u8 ifidx)
{
brcmf_dbg(TRACE,
"enter: desc %p ea=%pM, ifidx=%u\n", desc, addr, ifidx);
@@ -648,7 +648,7 @@ static void brcmf_fws_init_mac_descriptor(struct brcmf_fws_mac_descriptor *desc,
}

static
-void brcmf_fws_clear_mac_descriptor(struct brcmf_fws_mac_descriptor *desc)
+void brcmf_fws_macdesc_deinit(struct brcmf_fws_mac_descriptor *desc)
{
brcmf_dbg(TRACE,
"enter: ea=%pM, ifidx=%u\n", desc->ea, desc->interface_id);
@@ -659,7 +659,7 @@ void brcmf_fws_clear_mac_descriptor(struct brcmf_fws_mac_descriptor *desc)
}

static struct brcmf_fws_mac_descriptor *
-brcmf_fws_mac_descriptor_lookup(struct brcmf_fws_info *fws, u8 *ea)
+brcmf_fws_macdesc_lookup(struct brcmf_fws_info *fws, u8 *ea)
{
struct brcmf_fws_mac_descriptor *entry;
int i;
@@ -678,8 +678,7 @@ brcmf_fws_mac_descriptor_lookup(struct brcmf_fws_info *fws, u8 *ea)
}

static struct brcmf_fws_mac_descriptor*
-brcmf_fws_find_mac_desc(struct brcmf_fws_info *fws, struct brcmf_if *ifp,
- u8 *da)
+brcmf_fws_macdesc_find(struct brcmf_fws_info *fws, struct brcmf_if *ifp, u8 *da)
{
struct brcmf_fws_mac_descriptor *entry = &fws->desc.other;
bool multicast;
@@ -695,7 +694,7 @@ brcmf_fws_find_mac_desc(struct brcmf_fws_info *fws, struct brcmf_if *ifp,
goto done;
}

- entry = brcmf_fws_mac_descriptor_lookup(fws, da);
+ entry = brcmf_fws_macdesc_lookup(fws, da);
if (IS_ERR(entry))
entry = ifp->fws_desc;

@@ -703,9 +702,9 @@ done:
return entry;
}

-static bool brcmf_fws_mac_desc_closed(struct brcmf_fws_info *fws,
- struct brcmf_fws_mac_descriptor *entry,
- int fifo)
+static bool brcmf_fws_macdesc_closed(struct brcmf_fws_info *fws,
+ struct brcmf_fws_mac_descriptor *entry,
+ int fifo)
{
struct brcmf_fws_mac_descriptor *if_entry;
bool closed;
@@ -728,9 +727,9 @@ static bool brcmf_fws_mac_desc_closed(struct brcmf_fws_info *fws,
return closed || !(entry->ac_bitmap & BIT(fifo));
}

-static void brcmf_fws_mac_desc_cleanup(struct brcmf_fws_info *fws,
- struct brcmf_fws_mac_descriptor *entry,
- int ifidx)
+static void brcmf_fws_macdesc_cleanup(struct brcmf_fws_info *fws,
+ struct brcmf_fws_mac_descriptor *entry,
+ int ifidx)
{
if (entry->occupied && (ifidx == -1 || ifidx == entry->interface_id)) {
brcmf_fws_psq_flush(fws, &entry->psq, ifidx);
@@ -782,9 +781,9 @@ static void brcmf_fws_cleanup(struct brcmf_fws_info *fws, int ifidx)
/* cleanup individual nodes */
table = &fws->desc.nodes[0];
for (i = 0; i < ARRAY_SIZE(fws->desc.nodes); i++)
- brcmf_fws_mac_desc_cleanup(fws, &table[i], ifidx);
+ brcmf_fws_macdesc_cleanup(fws, &table[i], ifidx);

- brcmf_fws_mac_desc_cleanup(fws, &fws->desc.other, ifidx);
+ brcmf_fws_macdesc_cleanup(fws, &fws->desc.other, ifidx);
brcmf_fws_bus_txq_cleanup(fws, matchfn, ifidx);
brcmf_fws_hanger_cleanup(fws, matchfn, ifidx);
}
@@ -924,18 +923,18 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
if (entry->occupied) {
brcmf_dbg(TRACE, "deleting %s mac %pM\n",
entry->name, addr);
- brcmf_fws_mac_desc_cleanup(fws, entry, -1);
- brcmf_fws_clear_mac_descriptor(entry);
+ brcmf_fws_macdesc_cleanup(fws, entry, -1);
+ brcmf_fws_macdesc_deinit(entry);
} else
fws->stats.mac_update_failed++;
return 0;
}

- existing = brcmf_fws_mac_descriptor_lookup(fws, addr);
+ existing = brcmf_fws_macdesc_lookup(fws, addr);
if (IS_ERR(existing)) {
if (!entry->occupied) {
entry->mac_handle = mac_handle;
- brcmf_fws_init_mac_descriptor(entry, addr, ifidx);
+ brcmf_fws_macdesc_init(entry, addr, ifidx);
brcmf_fws_macdesc_set_name(fws, entry);
brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT,
BRCMF_FWS_PSQ_LEN);
@@ -949,7 +948,7 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
memcpy(entry, existing,
offsetof(struct brcmf_fws_mac_descriptor, psq));
entry->mac_handle = mac_handle;
- brcmf_fws_clear_mac_descriptor(existing);
+ brcmf_fws_macdesc_deinit(existing);
brcmf_fws_macdesc_set_name(fws, entry);
brcmf_dbg(TRACE, "relocate %s mac %pM\n", entry->name,
addr);
@@ -1189,7 +1188,7 @@ static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo)
for (i = 0; i < num_nodes; i++) {
entry = &table[(node_pos + i) % num_nodes];
if (!entry->occupied ||
- brcmf_fws_mac_desc_closed(fws, entry, fifo))
+ brcmf_fws_macdesc_closed(fws, entry, fifo))
continue;

if (entry->suppressed)
@@ -1810,7 +1809,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)

/* set control buffer information */
skcb->if_flags = 0;
- skcb->mac = brcmf_fws_find_mac_desc(fws, ifp, eh->h_dest);
+ skcb->mac = brcmf_fws_macdesc_find(fws, ifp, eh->h_dest);
skcb->state = BRCMF_FWS_SKBSTATE_NEW;
brcmf_skb_if_flags_set_field(skb, INDEX, ifp->ifidx);
if (!multicast)
@@ -1828,7 +1827,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)

if (skcb->mac->suppressed ||
fws->bus_flow_blocked ||
- brcmf_fws_mac_desc_closed(fws, skcb->mac, fifo) ||
+ brcmf_fws_macdesc_closed(fws, skcb->mac, fifo) ||
brcmu_pktq_mlen(&skcb->mac->psq, 3 << (fifo * 2)) ||
(!multicast &&
brcmf_fws_consume_credit(fws, fifo, skb) < 0)) {
@@ -1850,7 +1849,7 @@ void brcmf_fws_reset_interface(struct brcmf_if *ifp)
if (!entry)
return;

- brcmf_fws_init_mac_descriptor(entry, ifp->mac_addr, ifp->ifidx);
+ brcmf_fws_macdesc_init(entry, ifp->mac_addr, ifp->ifidx);
}

void brcmf_fws_add_interface(struct brcmf_if *ifp)
@@ -1863,7 +1862,7 @@ void brcmf_fws_add_interface(struct brcmf_if *ifp)

entry = &fws->desc.iface[ifp->ifidx];
ifp->fws_desc = entry;
- brcmf_fws_init_mac_descriptor(entry, ifp->mac_addr, ifp->ifidx);
+ brcmf_fws_macdesc_init(entry, ifp->mac_addr, ifp->ifidx);
brcmf_fws_macdesc_set_name(fws, entry);
brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT,
BRCMF_FWS_PSQ_LEN);
@@ -1881,7 +1880,7 @@ void brcmf_fws_del_interface(struct brcmf_if *ifp)
brcmf_fws_lock(ifp->drvr, flags);
ifp->fws_desc = NULL;
brcmf_dbg(TRACE, "deleting %s\n", entry->name);
- brcmf_fws_clear_mac_descriptor(entry);
+ brcmf_fws_macdesc_deinit(entry);
brcmf_fws_cleanup(ifp->drvr->fws, ifp->ifidx);
brcmf_fws_unlock(ifp->drvr, flags);
}
@@ -1986,7 +1985,7 @@ int brcmf_fws_init(struct brcmf_pub *drvr)
}

brcmf_fws_hanger_init(&drvr->fws->hanger);
- brcmf_fws_init_mac_descriptor(&drvr->fws->desc.other, NULL, 0);
+ brcmf_fws_macdesc_init(&drvr->fws->desc.other, NULL, 0);
brcmf_fws_macdesc_set_name(drvr->fws, &drvr->fws->desc.other);
brcmu_pktq_init(&drvr->fws->desc.other.psq, BRCMF_FWS_PSQ_PREC_COUNT,
BRCMF_FWS_PSQ_LEN);
--
1.7.10.4



2013-06-18 11:29:49

by Arend van Spriel

[permalink] [raw]
Subject: [PATCH 3/8] brcmfmac: remove dependency with nl80211.h

The firmware-signalling code used NL80211_NUM_ACS, but it has
its own definition enum brcmf_fws_fifo, which is more appropriate
to use. This effectively removes the need to include nl80211.h.

Reviewed-by: Hante Meuleman <[email protected]>
Signed-off-by: Arend van Spriel <[email protected]>
---
drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
index e66b723..b702f3e 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -22,7 +22,6 @@
#include <linux/etherdevice.h>
#include <linux/err.h>
#include <linux/jiffies.h>
-#include <uapi/linux/nl80211.h>
#include <net/cfg80211.h>

#include <brcmu_utils.h>
@@ -142,7 +141,7 @@ static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id)
#define BRCMF_FWS_FLOWCONTROL_HIWATER 128
#define BRCMF_FWS_FLOWCONTROL_LOWATER 64

-#define BRCMF_FWS_PSQ_PREC_COUNT ((NL80211_NUM_ACS + 1) * 2)
+#define BRCMF_FWS_PSQ_PREC_COUNT ((BRCMF_FWS_FIFO_COUNT + 1) * 2)
#define BRCMF_FWS_PSQ_LEN 256

#define BRCMF_FWS_HTOD_FLAG_PKTFROMHOST 0x01
--
1.7.10.4



2013-06-18 11:29:46

by Arend van Spriel

[permalink] [raw]
Subject: [PATCH 7/8] brcmfmac: replace brcmf_sdioh_request_buffer with brcmf_sdio_buffrw

From: Franky Lin <[email protected]>

Introducing a new SDIO block data access interface function
brcmf_sdio_buffrw. It will act as a unified interface function for any block
data access to WiFi dongle through SDIO interface. This patch enables
the support for single skb transmission.

Reviewed-by: Hante Meuleman <[email protected]>
Reviewed-by: Pieter-Paul Giesberts <[email protected]>
Reviewed-by: Arend van Spriel <[email protected]>
Signed-off-by: Franky Lin <[email protected]>
Signed-off-by: Arend van Spriel <[email protected]>
---
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 58 ++++++++++++++++----
.../net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | 41 +-------------
.../net/wireless/brcm80211/brcmfmac/sdio_host.h | 8 +--
3 files changed, 53 insertions(+), 54 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 4891e3d..32a205e 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -303,6 +303,49 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
*ret = retval;
}

+/**
+ * brcmf_sdio_buffrw - SDIO interface function for block data access
+ * @sdiodev: brcmfmac sdio device
+ * @fn: SDIO function number
+ * @write: direction flag
+ * @addr: dongle memory address as source/destination
+ * @pkt: skb pointer
+ *
+ * This function takes the respbonsibility as the interface function to MMC
+ * stack for block data access. It assumes that the skb passed down by the
+ * caller has already been padded and aligned.
+ */
+static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
+ bool write, u32 addr, struct sk_buff *pkt)
+{
+ uint len;
+
+ brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait);
+ if (brcmf_pm_resume_error(sdiodev))
+ return -EIO;
+
+ /* Single skb use the standard mmc interface */
+ if (!pkt->next) {
+ len = pkt->len + 3;
+ len &= (uint)~3;
+
+ if (write)
+ return sdio_memcpy_toio(sdiodev->func[fn], addr,
+ ((u8 *)(pkt->data)), len);
+ else if (fn == 1)
+ return sdio_memcpy_fromio(sdiodev->func[fn],
+ ((u8 *)(pkt->data)), addr,
+ len);
+ else
+ /* function 2 read is FIFO operation */
+ return sdio_readsb(sdiodev->func[fn],
+ ((u8 *)(pkt->data)), addr, len);
+ }
+
+ brcmf_err("skb chain is not supported yet.\n");
+ return -EOPNOTSUPP;
+}
+
static int brcmf_sdcard_recv_prepare(struct brcmf_sdio_dev *sdiodev, uint fn,
uint flags, uint width, u32 *addr)
{
@@ -355,7 +398,6 @@ int
brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
uint flags, struct sk_buff *pkt)
{
- uint incr_fix;
uint width;
int err = 0;

@@ -367,9 +409,7 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
if (err)
goto done;

- incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
- err = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_READ,
- fn, addr, pkt);
+ err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, pkt);

done:
return err;
@@ -424,7 +464,6 @@ int
brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
uint flags, struct sk_buff *pkt)
{
- uint incr_fix;
uint width;
uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
int err = 0;
@@ -446,13 +485,11 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,

addr &= SBSDIO_SB_OFT_ADDR_MASK;

- incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
if (width == 4)
addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;

- err = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn,
- addr, pkt);
+ err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, pkt);

done:
return err;
@@ -501,9 +538,8 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
skb_put(pkt, dsize);
if (write)
memcpy(pkt->data, data, dsize);
- bcmerror = brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_INC,
- write, SDIO_FUNC_1,
- sdaddr, pkt);
+ bcmerror = brcmf_sdio_buffrw(sdiodev, SDIO_FUNC_1, write,
+ sdaddr, pkt);
if (bcmerror) {
brcmf_err("membytes transfer failed\n");
break;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index 11400b3..7a3c5bf 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -66,7 +66,7 @@ MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
static struct brcmfmac_sdio_platform_data *brcmfmac_sdio_pdata;


-static bool
+bool
brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev)
{
bool is_err = false;
@@ -76,7 +76,7 @@ brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev)
return is_err;
}

-static void
+void
brcmf_pm_resume_wait(struct brcmf_sdio_dev *sdiodev, wait_queue_head_t *wq)
{
#ifdef CONFIG_PM_SLEEP
@@ -283,43 +283,6 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc,
return err_ret;
}

-/*
- * This function takes a single DMA-able packet.
- */
-int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev,
- uint fix_inc, uint write, uint func, uint addr,
- struct sk_buff *pkt)
-{
- int status;
- uint pkt_len;
- bool fifo = (fix_inc == SDIOH_DATA_FIX);
-
- brcmf_dbg(SDIO, "Enter\n");
-
- if (pkt == NULL)
- return -EINVAL;
- pkt_len = pkt->len;
-
- brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait);
- if (brcmf_pm_resume_error(sdiodev))
- return -EIO;
-
- pkt_len += 3;
- pkt_len &= (uint)~3;
-
- status = brcmf_sdioh_request_data(sdiodev, write, fifo, func,
- addr, pkt, pkt_len);
- if (status) {
- brcmf_err("%s FAILED %p, addr=0x%05x, pkt_len=%d, ERR=0x%08x\n",
- write ? "TX" : "RX", pkt, addr, pkt_len, status);
- } else {
- brcmf_dbg(SDIO, "%s xfr'd %p, addr=0x%05x, len=%d\n",
- write ? "TX" : "RX", pkt, addr, pkt_len);
- }
-
- return status;
-}
-
static int brcmf_sdioh_get_cisaddr(struct brcmf_sdio_dev *sdiodev, u32 regaddr)
{
/* read 24 bits and return valid 17 bit addr */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
index 7c1b633..991c1501 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
@@ -274,10 +274,6 @@ brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,

/* read or write any buffer using cmd53 */
extern int
-brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev,
- uint fix_inc, uint rw, uint fnc_num, u32 addr,
- struct sk_buff *pkt);
-extern int
brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc,
uint write, uint func, uint addr,
struct sk_buff_head *pktq);
@@ -291,4 +287,8 @@ extern void brcmf_sdbrcm_disconnect(void *ptr);
extern void brcmf_sdbrcm_isr(void *arg);

extern void brcmf_sdbrcm_wd_timer(struct brcmf_sdio *bus, uint wdtick);
+
+extern void brcmf_pm_resume_wait(struct brcmf_sdio_dev *sdiodev,
+ wait_queue_head_t *wq);
+extern bool brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev);
#endif /* _BRCM_SDH_H_ */
--
1.7.10.4



2013-06-18 11:29:44

by Arend van Spriel

[permalink] [raw]
Subject: [PATCH 2/8] brcmfmac: rename variable prec to more appropriate name, ie. fifo

The term prec (precedence) is different from the fifo number. Rename
use of prec with fifo to be consistent and clear.

Reviewed-by: Hante Meuleman <[email protected]>
Signed-off-by: Arend van Spriel <[email protected]>
---
drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
index 1d8fa7d..e66b723 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -839,7 +839,7 @@ static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb)

static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws,
struct brcmf_fws_mac_descriptor *entry,
- int prec, bool send_immediately)
+ int fifo, bool send_immediately)
{
struct sk_buff *skb;
struct brcmf_bus *bus;
@@ -848,10 +848,10 @@ static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws,
u32 len;

/* check delayedQ and suppressQ in one call using bitmap */
- if (brcmu_pktq_mlen(&entry->psq, 3 << (prec * 2)) == 0)
- entry->traffic_pending_bmp &= ~NBITVAL(prec);
+ if (brcmu_pktq_mlen(&entry->psq, 3 << (fifo * 2)) == 0)
+ entry->traffic_pending_bmp &= ~NBITVAL(fifo);
else
- entry->traffic_pending_bmp |= NBITVAL(prec);
+ entry->traffic_pending_bmp |= NBITVAL(fifo);

entry->send_tim_signal = false;
if (entry->traffic_lastreported_bmp != entry->traffic_pending_bmp)
--
1.7.10.4



2013-06-18 11:29:49

by Arend van Spriel

[permalink] [raw]
Subject: [PATCH 1/8] brcmfmac: Only use credits for bcmc when firmware indicates it.

From: Hante Meuleman <[email protected]>

The firmware will sent an event message when bc/mc traffic should
be sent to the device using credit mechanism.

Reviewed-by: Arend Van Spriel <[email protected]>
Signed-off-by: Hante Meuleman <[email protected]>
Signed-off-by: Arend van Spriel <[email protected]>
---
drivers/net/wireless/brcm80211/brcmfmac/fweh.h | 3 +-
drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 32 +++++++++++++++++++-
2 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h
index 6ec5db9..e679214 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h
@@ -101,7 +101,8 @@ struct brcmf_event;
BRCMF_ENUM_DEF(P2P_PROBEREQ_MSG, 72) \
BRCMF_ENUM_DEF(DCS_REQUEST, 73) \
BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) \
- BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75)
+ BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75) \
+ BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127)

#define BRCMF_ENUM_DEF(id, val) \
BRCMF_E_##id = (val),
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
index 70f70ce..1d8fa7d 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -426,6 +426,7 @@ struct brcmf_fws_info {
struct brcmf_fws_stats stats;
struct brcmf_fws_hanger hanger;
enum brcmf_fws_fcmode fcmode;
+ bool bcmc_credit_check;
struct brcmf_fws_macdesc_table desc;
struct workqueue_struct *fws_wq;
struct work_struct fws_dequeue_work;
@@ -1438,6 +1439,20 @@ static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp,
return 0;
}

+static int brcmf_fws_notify_bcmc_credit_support(struct brcmf_if *ifp,
+ const struct brcmf_event_msg *e,
+ void *data)
+{
+ struct brcmf_fws_info *fws = ifp->drvr->fws;
+ ulong flags;
+
+ brcmf_fws_lock(ifp->drvr, flags);
+ if (fws)
+ fws->bcmc_credit_check = true;
+ brcmf_fws_unlock(ifp->drvr, flags);
+ return 0;
+}
+
int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
struct sk_buff *skb)
{
@@ -1806,6 +1821,12 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
eh->h_dest, multicast, fifo);

brcmf_fws_lock(drvr, flags);
+ /* multicast credit support is conditional, setting
+ * flag to false to assure credit is consumed below.
+ */
+ if (fws->bcmc_credit_check)
+ multicast = false;
+
if (skcb->mac->suppressed ||
fws->bus_flow_blocked ||
brcmf_fws_mac_desc_closed(fws, skcb->mac, fifo) ||
@@ -1878,7 +1899,8 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
brcmf_fws_lock(fws->drvr, flags);
for (fifo = NL80211_NUM_ACS; fifo >= 0 && !fws->bus_flow_blocked;
fifo--) {
- while (fws->fifo_credit[fifo]) {
+ while ((fws->fifo_credit[fifo]) || ((!fws->bcmc_credit_check) &&
+ (fifo == BRCMF_FWS_FIFO_BCMC))) {
skb = brcmf_fws_deq(fws, fifo);
if (!skb)
break;
@@ -1947,6 +1969,13 @@ int brcmf_fws_init(struct brcmf_pub *drvr)
brcmf_err("register credit map handler failed\n");
goto fail;
}
+ rc = brcmf_fweh_register(drvr, BRCMF_E_BCMC_CREDIT_SUPPORT,
+ brcmf_fws_notify_bcmc_credit_support);
+ if (rc < 0) {
+ brcmf_err("register bcmc credit handler failed\n");
+ brcmf_fweh_unregister(drvr, BRCMF_E_FIFO_CREDIT_MAP);
+ goto fail;
+ }

/* setting the iovar may fail if feature is unsupported
* so leave the rc as is so driver initialization can
@@ -1971,6 +2000,7 @@ int brcmf_fws_init(struct brcmf_pub *drvr)
return 0;

fail_event:
+ brcmf_fweh_unregister(drvr, BRCMF_E_BCMC_CREDIT_SUPPORT);
brcmf_fweh_unregister(drvr, BRCMF_E_FIFO_CREDIT_MAP);
fail:
brcmf_fws_deinit(drvr);
--
1.7.10.4