* [PATCH 00/12] brcmfmac: fixes for MMC hosts without scatter-gather
@ 2013-10-15 13:44 Arend van Spriel
2013-10-15 13:44 ` [PATCH 01/12] brcmfmac: store address in trace_brcmf_hexdump() Arend van Spriel
` (12 more replies)
0 siblings, 13 replies; 14+ messages in thread
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
On our internal test setups it turned out that the MMC host controller
did not support scatterlists (struct mmc_host::max_segs == 1). It took
a number of patches to cleanup and support this. While at it some debug
trace functions were modified and added.
Arend van Spriel (12):
brcmfmac: store address in trace_brcmf_hexdump()
brcmfmac: add tracepoint for capturing the SDPCM header
brcmfmac: rename variable max_seg_sz to max_seg_cnt for clarity
brcmfmac: determine host controller related variables during probe
brcmfmac: rework scatter-gather code in brcmf_sdio_buffrw()
brcmfmac: rename brcmf_sdio_buffrw()
brcmfmac: rework single packet transfers
brcmfmac: verify result of brcmf_sdio_addrprep() calls
brcmfmac: remove stale code from brcmf_sdcard_recv_chain()
brcmfmac: fix brcmf_sdcard_send_pkt() for host without sg support
brcmfmac: fix brcmf_sdio_txpkt_prep() for host without sg support
brcmfmac: fix brcmf_sdcard_recv_chain() for host without sg support
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 186 +++++++++++---------
.../net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | 17 ++
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 111 +++++++-----
.../net/wireless/brcm80211/brcmfmac/sdio_host.h | 6 +-
.../net/wireless/brcm80211/brcmfmac/tracepoint.h | 21 ++-
5 files changed, 216 insertions(+), 125 deletions(-)
--
1.7.10.4
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 01/12] brcmfmac: store address in trace_brcmf_hexdump()
2013-10-15 13:44 [PATCH 00/12] brcmfmac: fixes for MMC hosts without scatter-gather Arend van Spriel
@ 2013-10-15 13:44 ` Arend van Spriel
2013-10-15 13:44 ` [PATCH 02/12] brcmfmac: add tracepoint for capturing the SDPCM header Arend van Spriel
` (11 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
The trace function trace_brcmf_hexdump() stores the length, but
having the address of the buffer being dumped helps putting it
in context.
Reviewed-by: Franky Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h
index bc29171..4605a1d 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h
@@ -78,13 +78,15 @@ TRACE_EVENT(brcmf_hexdump,
TP_ARGS(data, len),
TP_STRUCT__entry(
__field(unsigned long, len)
+ __field(unsigned long, addr)
__dynamic_array(u8, hdata, len)
),
TP_fast_assign(
__entry->len = len;
+ __entry->addr = (unsigned long)data;
memcpy(__get_dynamic_array(hdata), data, len);
),
- TP_printk("hexdump [length=%lu]", __entry->len)
+ TP_printk("hexdump [addr=%lx, length=%lu]", __entry->addr, __entry->len)
);
TRACE_EVENT(brcmf_bdchdr,
--
1.7.10.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 02/12] brcmfmac: add tracepoint for capturing the SDPCM header
2013-10-15 13:44 [PATCH 00/12] brcmfmac: fixes for MMC hosts without scatter-gather Arend van Spriel
2013-10-15 13:44 ` [PATCH 01/12] brcmfmac: store address in trace_brcmf_hexdump() Arend van Spriel
@ 2013-10-15 13:44 ` Arend van Spriel
2013-10-15 13:44 ` [PATCH 03/12] brcmfmac: rename variable max_seg_sz to max_seg_cnt for clarity Arend van Spriel
` (10 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
Having the SDPCM header information in the traces is a valuable
piece of information.
Reviewed-by: Franky Lin <frankyl@broadcom.com>
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 3 +++
drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h | 17 +++++++++++++++++
2 files changed, 20 insertions(+)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 67f05db..ab1c919 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -1147,6 +1147,8 @@ static int brcmf_sdio_hdparse(struct brcmf_sdio *bus, u8 *header,
u8 rx_seq, fc, tx_seq_max;
u32 swheader;
+ trace_brcmf_sdpcm_hdr(false, header);
+
/* hw header */
len = get_unaligned_le16(header);
checksum = get_unaligned_le16(header + sizeof(u16));
@@ -1269,6 +1271,7 @@ static void brcmf_sdio_hdpack(struct brcmf_sdio *bus, u8 *header,
SDPCM_DOFFSET_MASK;
*(((__le32 *)header) + 1) = cpu_to_le32(sw_header);
*(((__le32 *)header) + 2) = 0;
+ trace_brcmf_sdpcm_hdr(true, header);
}
static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h
index 4605a1d..3c67529 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h
@@ -110,6 +110,23 @@ TRACE_EVENT(brcmf_bdchdr,
TP_printk("bdc: prio=%d siglen=%d", __entry->prio, __entry->siglen)
);
+TRACE_EVENT(brcmf_sdpcm_hdr,
+ TP_PROTO(bool tx, void *data),
+ TP_ARGS(tx, data),
+ TP_STRUCT__entry(
+ __field(u8, tx)
+ __field(u16, len)
+ __array(u8, hdr, 12)
+ ),
+ TP_fast_assign(
+ memcpy(__entry->hdr, data, 12);
+ __entry->len = __entry->hdr[0] | (__entry->hdr[1] << 8);
+ __entry->tx = tx ? 1 : 0;
+ ),
+ TP_printk("sdpcm: %s len %u, seq %d", __entry->tx ? "TX" : "RX",
+ __entry->len, __entry->hdr[4])
+);
+
#ifdef CONFIG_BRCM_TRACING
#undef TRACE_INCLUDE_PATH
--
1.7.10.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 03/12] brcmfmac: rename variable max_seg_sz to max_seg_cnt for clarity
2013-10-15 13:44 [PATCH 00/12] brcmfmac: fixes for MMC hosts without scatter-gather Arend van Spriel
2013-10-15 13:44 ` [PATCH 01/12] brcmfmac: store address in trace_brcmf_hexdump() Arend van Spriel
2013-10-15 13:44 ` [PATCH 02/12] brcmfmac: add tracepoint for capturing the SDPCM header Arend van Spriel
@ 2013-10-15 13:44 ` Arend van Spriel
2013-10-15 13:44 ` [PATCH 04/12] brcmfmac: determine host controller related variables during probe Arend van Spriel
` (9 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
The variable max_seg_sz in brcmf_sdio_buffrw() respresents the maximum
number of buffers that can be sent in one MMC transfer request. Rename
it to max_seg_cnt to avoid confusion.
Reviewed-by: Franky Lin <frankyl@broadcom.com>
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index e13b1a6..5dfc96c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -332,7 +332,7 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
{
unsigned int req_sz, func_blk_sz, sg_cnt, sg_data_sz, pkt_offset;
unsigned int max_blks, max_req_sz, orig_offset, dst_offset;
- unsigned short max_seg_sz, seg_sz;
+ unsigned short max_seg_cnt, seg_sz;
unsigned char *pkt_data, *orig_data, *dst_data;
struct sk_buff *pkt_next = NULL, *local_pkt_next;
struct sk_buff_head local_list, *target_list;
@@ -406,13 +406,14 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
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, target_list->qlen);
+ max_seg_cnt = min_t(unsigned short, host->max_segs,
+ SG_MAX_SINGLE_ALLOC);
+ max_seg_cnt = min_t(unsigned short, max_seg_cnt, target_list->qlen);
seg_sz = target_list->qlen;
pkt_offset = 0;
pkt_next = target_list->next;
- if (sg_alloc_table(&st, max_seg_sz, GFP_KERNEL)) {
+ if (sg_alloc_table(&st, max_seg_cnt, GFP_KERNEL)) {
ret = -ENOMEM;
goto exit;
}
@@ -444,7 +445,7 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
pkt_next = pkt_next->next;
}
- if (req_sz >= max_req_sz || sg_cnt >= max_seg_sz)
+ if (req_sz >= max_req_sz || sg_cnt >= max_seg_cnt)
break;
}
seg_sz -= sg_cnt;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 04/12] brcmfmac: determine host controller related variables during probe
2013-10-15 13:44 [PATCH 00/12] brcmfmac: fixes for MMC hosts without scatter-gather Arend van Spriel
` (2 preceding siblings ...)
2013-10-15 13:44 ` [PATCH 03/12] brcmfmac: rename variable max_seg_sz to max_seg_cnt for clarity Arend van Spriel
@ 2013-10-15 13:44 ` Arend van Spriel
2013-10-15 13:44 ` [PATCH 05/12] brcmfmac: rework scatter-gather code in brcmf_sdio_buffrw() Arend van Spriel
` (8 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
Instead of determining the limits for scatter-gather MMC transfer
request upon each transmit it is now determined during the probe
of the SDIO function.
Reviewed-by: Franky Lin <frankyl@broadcom.com>
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 23 ++++++--------------
.../net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | 17 +++++++++++++++
.../net/wireless/brcm80211/brcmfmac/sdio_host.h | 4 ++++
3 files changed, 28 insertions(+), 16 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 5dfc96c..8c4b506 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -26,7 +26,6 @@
#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>
@@ -331,7 +330,7 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
bool write, u32 addr, struct sk_buff_head *pktlist)
{
unsigned int req_sz, func_blk_sz, sg_cnt, sg_data_sz, pkt_offset;
- unsigned int max_blks, max_req_sz, orig_offset, dst_offset;
+ unsigned int max_req_sz, orig_offset, dst_offset;
unsigned short max_seg_cnt, seg_sz;
unsigned char *pkt_data, *orig_data, *dst_data;
struct sk_buff *pkt_next = NULL, *local_pkt_next;
@@ -341,7 +340,6 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
struct mmc_data mmc_dat;
struct sg_table st;
struct scatterlist *sgl;
- struct mmc_host *host;
int ret = 0;
if (!pktlist->qlen)
@@ -398,17 +396,10 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
target_list = &local_list;
}
- 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_cnt = min_t(unsigned short, host->max_segs,
- SG_MAX_SINGLE_ALLOC);
- max_seg_cnt = min_t(unsigned short, max_seg_cnt, target_list->qlen);
+ max_req_sz = sdiodev->max_request_size;
+ max_seg_cnt = min_t(unsigned short, sdiodev->max_segment_count,
+ target_list->qlen);
seg_sz = target_list->qlen;
pkt_offset = 0;
pkt_next = target_list->next;
@@ -429,8 +420,8 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
while (pkt_next != (struct sk_buff *)target_list) {
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 > sdiodev->max_segment_size)
+ sg_data_sz = sdiodev->max_segment_size;
if (sg_data_sz > max_req_sz - req_sz)
sg_data_sz = max_req_sz - req_sz;
@@ -476,7 +467,7 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
addr += req_sz;
mmc_set_data_timeout(&mmc_dat, sdiodev->func[fn]->card);
- mmc_wait_for_req(host, &mmc_req);
+ mmc_wait_for_req(sdiodev->func[fn]->card->host, &mmc_req);
ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error;
if (ret != 0) {
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index 2a23bf2..905704e 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -21,6 +21,7 @@
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
#include <linux/suspend.h>
#include <linux/errno.h>
#include <linux/sched.h> /* request_irq() */
@@ -315,6 +316,8 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
int err;
struct brcmf_sdio_dev *sdiodev;
struct brcmf_bus *bus_if;
+ struct mmc_host *host;
+ uint max_blocks;
brcmf_dbg(SDIO, "Enter\n");
brcmf_dbg(SDIO, "Class=%x\n", func->class);
@@ -361,6 +364,20 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
brcmf_err("F2 error, probe failed %d...\n", err);
goto fail;
}
+
+ /*
+ * determine host related variables after brcmf_sdio_probe()
+ * as func->cur_blksize is properly set and F2 init has been
+ * completed successfully.
+ */
+ host = func->card->host;
+ sdiodev->sg_support = host->max_segs > 1;
+ max_blocks = min_t(uint, host->max_blk_count, 511u);
+ sdiodev->max_request_size = min_t(uint, host->max_req_size,
+ max_blocks * func->cur_blksize);
+ sdiodev->max_segment_count = min_t(uint, host->max_segs,
+ SG_MAX_SINGLE_ALLOC);
+ sdiodev->max_segment_size = host->max_seg_size;
brcmf_dbg(SDIO, "F2 init completed...\n");
return 0;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
index 2b5407f..59c456f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
@@ -178,6 +178,10 @@ struct brcmf_sdio_dev {
bool irq_en; /* irq enable flags */
spinlock_t irq_en_lock;
bool irq_wake; /* irq wake enable flags */
+ bool sg_support;
+ uint max_request_size;
+ ushort max_segment_count;
+ uint max_segment_size;
};
/* Register/deregister interrupt handler. */
--
1.7.10.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 05/12] brcmfmac: rework scatter-gather code in brcmf_sdio_buffrw()
2013-10-15 13:44 [PATCH 00/12] brcmfmac: fixes for MMC hosts without scatter-gather Arend van Spriel
` (3 preceding siblings ...)
2013-10-15 13:44 ` [PATCH 04/12] brcmfmac: determine host controller related variables during probe Arend van Spriel
@ 2013-10-15 13:44 ` Arend van Spriel
2013-10-15 13:44 ` [PATCH 06/12] brcmfmac: rename brcmf_sdio_buffrw() Arend van Spriel
` (7 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
Moving a number of assignments outside of the loop as they are
the same for each request.
Reviewed-by: Franky Lin <frankyl@broadcom.com>
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 34 ++++++++++++----------
1 file changed, 19 insertions(+), 15 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 8c4b506..ea716a4 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -409,12 +409,26 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
goto exit;
}
+ memset(&mmc_req, 0, sizeof(struct mmc_request));
+ memset(&mmc_cmd, 0, sizeof(struct mmc_command));
+ memset(&mmc_dat, 0, sizeof(struct mmc_data));
+
+ mmc_dat.sg = st.sgl;
+ mmc_dat.blksz = 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 */
+ /* for function 1 the addr will be incremented */
+ mmc_cmd.arg |= (fn == 1) ? 1<<26 : 0;
+ mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
+ mmc_req.cmd = &mmc_cmd;
+ mmc_req.data = &mmc_dat;
+
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 *)target_list) {
@@ -447,22 +461,12 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
ret = -ENOTBLK;
goto exit;
}
- 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;
+ /* incrementing addr for function 1 */
if (fn == 1)
addr += req_sz;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 06/12] brcmfmac: rename brcmf_sdio_buffrw()
2013-10-15 13:44 [PATCH 00/12] brcmfmac: fixes for MMC hosts without scatter-gather Arend van Spriel
` (4 preceding siblings ...)
2013-10-15 13:44 ` [PATCH 05/12] brcmfmac: rework scatter-gather code in brcmf_sdio_buffrw() Arend van Spriel
@ 2013-10-15 13:44 ` Arend van Spriel
2013-10-15 13:44 ` [PATCH 07/12] brcmfmac: rework single packet transfers Arend van Spriel
` (6 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
The function brcmf_sdio_buffrw() is intended to be used for
transfering list of packets using scatter-gather functionality.
Rename function to brcmf_sdio_sglist_rw() to clarify this.
Reviewed-by: Franky Lin <frankyl@broadcom.com>
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index ea716a4..344b2d2 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -315,7 +315,7 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
}
/**
- * brcmf_sdio_buffrw - SDIO interface function for block data access
+ * brcmf_sdio_sglist_rw - SDIO interface function for block data access
* @sdiodev: brcmfmac sdio device
* @fn: SDIO function number
* @write: direction flag
@@ -326,8 +326,9 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
* 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_head *pktlist)
+static int brcmf_sdio_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn,
+ bool write, u32 addr,
+ struct sk_buff_head *pktlist)
{
unsigned int req_sz, func_blk_sz, sg_cnt, sg_data_sz, pkt_offset;
unsigned int max_req_sz, orig_offset, dst_offset;
@@ -554,7 +555,7 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
skb_queue_head_init(&pkt_list);
skb_queue_tail(&pkt_list, pkt);
- err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, &pkt_list);
+ err = brcmf_sdio_sglist_rw(sdiodev, fn, false, addr, &pkt_list);
skb_dequeue_tail(&pkt_list);
done:
@@ -577,7 +578,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_sdio_buffrw(sdiodev, fn, false, addr, pktq);
+ err = brcmf_sdio_sglist_rw(sdiodev, fn, false, addr, pktq);
done:
return err;
@@ -622,7 +623,7 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
brcmf_sdio_addrprep(sdiodev, width, &addr);
- err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, pktq);
+ err = brcmf_sdio_sglist_rw(sdiodev, fn, true, addr, pktq);
return err;
}
@@ -673,8 +674,8 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
if (write)
memcpy(pkt->data, data, dsize);
skb_queue_tail(&pkt_list, pkt);
- bcmerror = brcmf_sdio_buffrw(sdiodev, SDIO_FUNC_1, write,
- sdaddr, &pkt_list);
+ bcmerror = brcmf_sdio_sglist_rw(sdiodev, SDIO_FUNC_1, write,
+ sdaddr, &pkt_list);
skb_dequeue_tail(&pkt_list);
if (bcmerror) {
brcmf_err("membytes transfer failed\n");
--
1.7.10.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 07/12] brcmfmac: rework single packet transfers
2013-10-15 13:44 [PATCH 00/12] brcmfmac: fixes for MMC hosts without scatter-gather Arend van Spriel
` (5 preceding siblings ...)
2013-10-15 13:44 ` [PATCH 06/12] brcmfmac: rename brcmf_sdio_buffrw() Arend van Spriel
@ 2013-10-15 13:44 ` Arend van Spriel
2013-10-15 13:44 ` [PATCH 08/12] brcmfmac: verify result of brcmf_sdio_addrprep() calls Arend van Spriel
` (5 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
The function brcmf_sdio_sglist_rw() does a different code path
when packet queue length is 1. Move this to a separate function
reducing overhead in the calling context.
Reviewed-by: Franky Lin <frankyl@broadcom.com>
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 81 +++++++++++-----------
1 file changed, 40 insertions(+), 41 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 344b2d2..da02816 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -314,6 +314,34 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
*ret = retval;
}
+static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
+ bool write, u32 addr, struct sk_buff *pkt)
+{
+ unsigned int req_sz;
+
+ brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait);
+ if (brcmf_pm_resume_error(sdiodev))
+ return -EIO;
+
+ /* Single skb use the standard mmc interface */
+ req_sz = pkt->len + 3;
+ req_sz &= (uint)~3;
+
+ if (write)
+ return sdio_memcpy_toio(sdiodev->func[fn], addr,
+ ((u8 *)(pkt->data)),
+ req_sz);
+ else if (fn == 1)
+ return sdio_memcpy_fromio(sdiodev->func[fn],
+ ((u8 *)(pkt->data)),
+ addr, req_sz);
+ else
+ /* function 2 read is FIFO operation */
+ return sdio_readsb(sdiodev->func[fn],
+ ((u8 *)(pkt->data)), addr,
+ req_sz);
+}
+
/**
* brcmf_sdio_sglist_rw - SDIO interface function for block data access
* @sdiodev: brcmfmac sdio device
@@ -350,27 +378,6 @@ static int brcmf_sdio_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn,
if (brcmf_pm_resume_error(sdiodev))
return -EIO;
- /* Single skb use the standard mmc interface */
- 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_next->data)),
- req_sz);
- else if (fn == 1)
- return sdio_memcpy_fromio(sdiodev->func[fn],
- ((u8 *)(pkt_next->data)),
- addr, req_sz);
- else
- /* function 2 read is FIFO operation */
- return sdio_readsb(sdiodev->func[fn],
- ((u8 *)(pkt_next->data)), addr,
- req_sz);
- }
-
target_list = pktlist;
/* for host with broken sg support, prepare a page aligned list */
__skb_queue_head_init(&local_list);
@@ -543,7 +550,6 @@ 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);
@@ -553,10 +559,7 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
if (err)
goto done;
- skb_queue_head_init(&pkt_list);
- skb_queue_tail(&pkt_list, pkt);
- err = brcmf_sdio_sglist_rw(sdiodev, fn, false, addr, &pkt_list);
- skb_dequeue_tail(&pkt_list);
+ err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, pkt);
done:
return err;
@@ -589,7 +592,7 @@ brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
uint flags, u8 *buf, uint nbytes)
{
struct sk_buff *mypkt;
- struct sk_buff_head pktq;
+ uint width;
int err;
mypkt = brcmu_pkt_buf_get_skb(nbytes);
@@ -600,10 +603,11 @@ brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
}
memcpy(mypkt->data, buf, nbytes);
- __skb_queue_head_init(&pktq);
- __skb_queue_tail(&pktq, mypkt);
- err = brcmf_sdcard_send_pkt(sdiodev, addr, fn, flags, &pktq);
- __skb_dequeue_tail(&pktq);
+
+ width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
+ brcmf_sdio_addrprep(sdiodev, width, &addr);
+
+ err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, mypkt);
brcmu_pkt_buf_free_skb(mypkt);
return err;
@@ -615,7 +619,6 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
uint flags, struct sk_buff_head *pktq)
{
uint width;
- int err = 0;
brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n",
fn, addr, pktq->qlen);
@@ -623,9 +626,9 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
brcmf_sdio_addrprep(sdiodev, width, &addr);
- err = brcmf_sdio_sglist_rw(sdiodev, fn, true, addr, pktq);
-
- return err;
+ if (pktq->qlen == 1)
+ return brcmf_sdio_buffrw(sdiodev, fn, true, addr, pktq->next);
+ return brcmf_sdio_sglist_rw(sdiodev, fn, true, addr, pktq);
}
int
@@ -636,7 +639,6 @@ 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);
@@ -645,7 +647,6 @@ 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;
@@ -673,10 +674,8 @@ 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_sglist_rw(sdiodev, SDIO_FUNC_1, write,
- sdaddr, &pkt_list);
- skb_dequeue_tail(&pkt_list);
+ bcmerror = brcmf_sdio_buffrw(sdiodev, SDIO_FUNC_1, write,
+ sdaddr, pkt);
if (bcmerror) {
brcmf_err("membytes transfer failed\n");
break;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 08/12] brcmfmac: verify result of brcmf_sdio_addrprep() calls
2013-10-15 13:44 [PATCH 00/12] brcmfmac: fixes for MMC hosts without scatter-gather Arend van Spriel
` (6 preceding siblings ...)
2013-10-15 13:44 ` [PATCH 07/12] brcmfmac: rework single packet transfers Arend van Spriel
@ 2013-10-15 13:44 ` Arend van Spriel
2013-10-15 13:44 ` [PATCH 09/12] brcmfmac: remove stale code from brcmf_sdcard_recv_chain() Arend van Spriel
` (4 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
Not all calls to the function brcmf_sdio_addrprep() check
the return value, but it may fail so better verify it.
Reviewed-by: Franky Lin <frankyl@broadcom.com>
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index da02816..c88e267 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -238,7 +238,9 @@ brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
func_num = SDIO_FUNC_1;
reg_size = 4;
- brcmf_sdio_addrprep(sdiodev, reg_size, &addr);
+ ret = brcmf_sdio_addrprep(sdiodev, reg_size, &addr);
+ if (ret)
+ goto done;
}
do {
@@ -254,6 +256,7 @@ brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
func_num, addr, data, 4);
} while (ret != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
+done:
if (ret != 0)
brcmf_err("failed with %d\n", ret);
@@ -605,9 +608,10 @@ brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
memcpy(mypkt->data, buf, nbytes);
width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
- brcmf_sdio_addrprep(sdiodev, width, &addr);
+ err = brcmf_sdio_addrprep(sdiodev, width, &addr);
- err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, mypkt);
+ if (!err)
+ err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, mypkt);
brcmu_pkt_buf_free_skb(mypkt);
return err;
@@ -619,12 +623,15 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
uint flags, struct sk_buff_head *pktq)
{
uint width;
+ int err;
brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n",
fn, addr, pktq->qlen);
width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
- brcmf_sdio_addrprep(sdiodev, width, &addr);
+ err = brcmf_sdio_addrprep(sdiodev, width, &addr);
+ if (err)
+ return err;
if (pktq->qlen == 1)
return brcmf_sdio_buffrw(sdiodev, fn, true, addr, pktq->next);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 09/12] brcmfmac: remove stale code from brcmf_sdcard_recv_chain()
2013-10-15 13:44 [PATCH 00/12] brcmfmac: fixes for MMC hosts without scatter-gather Arend van Spriel
` (7 preceding siblings ...)
2013-10-15 13:44 ` [PATCH 08/12] brcmfmac: verify result of brcmf_sdio_addrprep() calls Arend van Spriel
@ 2013-10-15 13:44 ` Arend van Spriel
2013-10-15 13:44 ` [PATCH 10/12] brcmfmac: fix brcmf_sdcard_send_pkt() for host without sg support Arend van Spriel
` (3 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
The function brcmf_sdcard_recv_chain() has been reworked with
commit "brcmfmac: add sdio sg list support", but the incr_fix
variable is only assigned but not used so removing it now.
Reviewed-by: Franky Lin <frankyl@broadcom.com>
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index c88e267..92818d79 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -571,7 +571,6 @@ done:
int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
uint flags, struct sk_buff_head *pktq)
{
- uint incr_fix;
uint width;
int err = 0;
@@ -583,7 +582,6 @@ int brcmf_sdcard_recv_chain(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_sdio_sglist_rw(sdiodev, fn, false, addr, pktq);
done:
--
1.7.10.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 10/12] brcmfmac: fix brcmf_sdcard_send_pkt() for host without sg support
2013-10-15 13:44 [PATCH 00/12] brcmfmac: fixes for MMC hosts without scatter-gather Arend van Spriel
` (8 preceding siblings ...)
2013-10-15 13:44 ` [PATCH 09/12] brcmfmac: remove stale code from brcmf_sdcard_recv_chain() Arend van Spriel
@ 2013-10-15 13:44 ` Arend van Spriel
2013-10-15 13:44 ` [PATCH 11/12] brcmfmac: fix brcmf_sdio_txpkt_prep() " Arend van Spriel
` (2 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
If the host does not support scatter-gather transmit the packets
in the pktq individually using brcmf_sdio_buffrw().
Reviewed-by: Franky Lin <frankyl@broadcom.com>
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 92818d79..1103dc1 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -620,6 +620,7 @@ int
brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
uint flags, struct sk_buff_head *pktq)
{
+ struct sk_buff *skb;
uint width;
int err;
@@ -631,9 +632,16 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
if (err)
return err;
- if (pktq->qlen == 1)
- return brcmf_sdio_buffrw(sdiodev, fn, true, addr, pktq->next);
- return brcmf_sdio_sglist_rw(sdiodev, fn, true, addr, pktq);
+ if (pktq->qlen == 1 || !sdiodev->sg_support)
+ skb_queue_walk(pktq, skb) {
+ err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, skb);
+ if (err)
+ break;
+ }
+ else
+ err = brcmf_sdio_sglist_rw(sdiodev, fn, true, addr, pktq);
+
+ return err;
}
int
--
1.7.10.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 11/12] brcmfmac: fix brcmf_sdio_txpkt_prep() for host without sg support
2013-10-15 13:44 [PATCH 00/12] brcmfmac: fixes for MMC hosts without scatter-gather Arend van Spriel
` (9 preceding siblings ...)
2013-10-15 13:44 ` [PATCH 10/12] brcmfmac: fix brcmf_sdcard_send_pkt() for host without sg support Arend van Spriel
@ 2013-10-15 13:44 ` Arend van Spriel
2013-10-15 13:44 ` [PATCH 12/12] brcmfmac: fix brcmf_sdcard_recv_chain() " Arend van Spriel
2013-10-16 8:51 ` [PATCH 00/12] brcmfmac: fixes for MMC hosts without scatter-gather Arend van Spriel
12 siblings, 0 replies; 14+ messages in thread
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
When running on a host controller that does not support scatter-gather
transfers the function brcmf_sdio_txpkt_prep() should not add tail
padding buffers.
Reviewed-by: Franky Lin <frankyl@broadcom.com>
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 106 ++++++++++++--------
1 file changed, 64 insertions(+), 42 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index ab1c919..c927701 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -1880,6 +1880,56 @@ brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus)
/* bit mask of data length chopped from the previous packet */
#define ALIGN_SKB_CHOP_LEN_MASK 0x7fff
+static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio_dev *sdiodev,
+ struct sk_buff_head *pktq,
+ struct sk_buff *pkt, uint chan)
+{
+ struct sk_buff *pkt_pad;
+ u16 tail_pad, tail_chop, sg_align;
+ unsigned int blksize;
+ u8 *dat_buf;
+ int ntail;
+
+ blksize = sdiodev->func[SDIO_FUNC_2]->cur_blksize;
+ sg_align = 4;
+ if (sdiodev->pdata && sdiodev->pdata->sd_sgentry_align > 4)
+ sg_align = sdiodev->pdata->sd_sgentry_align;
+ /* sg entry alignment should be a divisor of block size */
+ WARN_ON(blksize % sg_align);
+
+ /* Check tail padding */
+ pkt_pad = NULL;
+ tail_chop = pkt->len % sg_align;
+ tail_pad = sg_align - tail_chop;
+ tail_pad += blksize - (pkt->len + tail_pad) % blksize;
+ if (skb_tailroom(pkt) < tail_pad && pkt->len > blksize) {
+ pkt_pad = brcmu_pkt_buf_get_skb(tail_pad + tail_chop);
+ if (pkt_pad == NULL)
+ return -ENOMEM;
+ memcpy(pkt_pad->data,
+ pkt->data + pkt->len - tail_chop,
+ tail_chop);
+ *(u32 *)(pkt_pad->cb) = ALIGN_SKB_FLAG + tail_chop;
+ skb_trim(pkt, pkt->len - tail_chop);
+ __skb_queue_after(pktq, pkt, pkt_pad);
+ } else {
+ ntail = pkt->data_len + tail_pad -
+ (pkt->end - pkt->tail);
+ if (skb_cloned(pkt) || ntail > 0)
+ if (pskb_expand_head(pkt, 0, ntail, GFP_ATOMIC))
+ return -ENOMEM;
+ if (skb_linearize(pkt))
+ return -ENOMEM;
+ dat_buf = (u8 *)(pkt->data);
+ __skb_put(pkt, tail_pad);
+ }
+
+ if (pkt_pad)
+ return pkt->len + tail_chop;
+ else
+ return pkt->len - tail_pad;
+}
+
/**
* brcmf_sdio_txpkt_prep - packet preparation for transmit
* @bus: brcmf_sdio structure pointer
@@ -1896,24 +1946,16 @@ static int
brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq,
uint chan)
{
- u16 head_pad, tail_pad, tail_chop, head_align, sg_align;
- int ntail;
- struct sk_buff *pkt_next, *pkt_new;
+ u16 head_pad, head_align;
+ struct sk_buff *pkt_next;
u8 *dat_buf;
- unsigned blksize = bus->sdiodev->func[SDIO_FUNC_2]->cur_blksize;
+ int err;
struct brcmf_sdio_hdrinfo hd_info = {0};
/* SDIO ADMA requires at least 32 bit alignment */
head_align = 4;
- sg_align = 4;
- if (bus->sdiodev->pdata) {
- head_align = bus->sdiodev->pdata->sd_head_align > 4 ?
- bus->sdiodev->pdata->sd_head_align : 4;
- sg_align = bus->sdiodev->pdata->sd_sgentry_align > 4 ?
- bus->sdiodev->pdata->sd_sgentry_align : 4;
- }
- /* sg entry alignment should be a divisor of block size */
- WARN_ON(blksize % sg_align);
+ if (bus->sdiodev->pdata && bus->sdiodev->pdata->sd_head_align > 4)
+ head_align = bus->sdiodev->pdata->sd_head_align;
pkt_next = pktq->next;
dat_buf = (u8 *)(pkt_next->data);
@@ -1932,40 +1974,20 @@ brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq,
memset(dat_buf, 0, head_pad + bus->tx_hdrlen);
}
- /* Check tail padding */
- pkt_new = NULL;
- tail_chop = pkt_next->len % sg_align;
- tail_pad = sg_align - tail_chop;
- tail_pad += blksize - (pkt_next->len + tail_pad) % blksize;
- if (skb_tailroom(pkt_next) < tail_pad && pkt_next->len > blksize) {
- pkt_new = brcmu_pkt_buf_get_skb(tail_pad + tail_chop);
- if (pkt_new == NULL)
- return -ENOMEM;
- memcpy(pkt_new->data,
- pkt_next->data + pkt_next->len - tail_chop,
- tail_chop);
- *(u32 *)(pkt_new->cb) = ALIGN_SKB_FLAG + tail_chop;
- skb_trim(pkt_next, pkt_next->len - tail_chop);
- __skb_queue_after(pktq, pkt_next, pkt_new);
+ if (bus->sdiodev->sg_support && pktq->qlen > 1) {
+ err = brcmf_sdio_txpkt_prep_sg(bus->sdiodev, pktq,
+ pkt_next, chan);
+ if (err < 0)
+ return err;
+ hd_info.len = (u16)err;
} else {
- ntail = pkt_next->data_len + tail_pad -
- (pkt_next->end - pkt_next->tail);
- if (skb_cloned(pkt_next) || ntail > 0)
- if (pskb_expand_head(pkt_next, 0, ntail, GFP_ATOMIC))
- return -ENOMEM;
- if (skb_linearize(pkt_next))
- return -ENOMEM;
- dat_buf = (u8 *)(pkt_next->data);
- __skb_put(pkt_next, tail_pad);
+ hd_info.len = pkt_next->len;
}
- /* Now prep the header */
- if (pkt_new)
- hd_info.len = pkt_next->len + tail_chop;
- else
- hd_info.len = pkt_next->len - tail_pad;
hd_info.channel = chan;
hd_info.dat_offset = head_pad + bus->tx_hdrlen;
+
+ /* Now fill the header */
brcmf_sdio_hdpack(bus, dat_buf, &hd_info);
if (BRCMF_BYTES_ON() &&
--
1.7.10.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 12/12] brcmfmac: fix brcmf_sdcard_recv_chain() for host without sg support
2013-10-15 13:44 [PATCH 00/12] brcmfmac: fixes for MMC hosts without scatter-gather Arend van Spriel
` (10 preceding siblings ...)
2013-10-15 13:44 ` [PATCH 11/12] brcmfmac: fix brcmf_sdio_txpkt_prep() " Arend van Spriel
@ 2013-10-15 13:44 ` Arend van Spriel
2013-10-16 8:51 ` [PATCH 00/12] brcmfmac: fixes for MMC hosts without scatter-gather Arend van Spriel
12 siblings, 0 replies; 14+ messages in thread
From: Arend van Spriel @ 2013-10-15 13:44 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
If the SDIO host controller does not support scatter-gather the glom
superframe must be transfered from the device and the data for each
packet in the queue must be extracted from it.
Reviewed-by: Franky Lin <frankyl@broadcom.com>
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 21 ++++++++++++++++++--
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 2 +-
.../net/wireless/brcm80211/brcmfmac/sdio_host.h | 2 +-
3 files changed, 21 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 1103dc1..3e10b80 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -569,8 +569,10 @@ done:
}
int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
- uint flags, struct sk_buff_head *pktq)
+ uint flags, struct sk_buff_head *pktq, uint totlen)
{
+ struct sk_buff *glom_skb;
+ struct sk_buff *skb;
uint width;
int err = 0;
@@ -582,7 +584,22 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
if (err)
goto done;
- err = brcmf_sdio_sglist_rw(sdiodev, fn, false, addr, pktq);
+ if (pktq->qlen == 1)
+ err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, pktq->next);
+ else if (!sdiodev->sg_support) {
+ glom_skb = brcmu_pkt_buf_get_skb(totlen);
+ if (!glom_skb)
+ return -ENOMEM;
+ err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, glom_skb);
+ if (err)
+ goto done;
+
+ skb_queue_walk(pktq, skb) {
+ memcpy(skb->data, glom_skb->data, skb->len);
+ skb_pull(glom_skb, skb->len);
+ }
+ } else
+ err = brcmf_sdio_sglist_rw(sdiodev, fn, false, addr, pktq);
done:
return err;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index c927701..b02953c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -1392,7 +1392,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
sdio_claim_host(bus->sdiodev->func[1]);
errcode = brcmf_sdcard_recv_chain(bus->sdiodev,
bus->sdiodev->sbwad,
- SDIO_FUNC_2, F2SYNC, &bus->glom);
+ SDIO_FUNC_2, F2SYNC, &bus->glom, dlen);
sdio_release_host(bus->sdiodev->func[1]);
bus->sdcnt.f2rxdata++;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
index 59c456f..1b034ea 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
@@ -225,7 +225,7 @@ brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
uint flags, u8 *buf, uint nbytes);
extern int
brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
- uint flags, struct sk_buff_head *pktq);
+ uint flags, struct sk_buff_head *pktq, uint totlen);
/* Flags bits */
--
1.7.10.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 00/12] brcmfmac: fixes for MMC hosts without scatter-gather
2013-10-15 13:44 [PATCH 00/12] brcmfmac: fixes for MMC hosts without scatter-gather Arend van Spriel
` (11 preceding siblings ...)
2013-10-15 13:44 ` [PATCH 12/12] brcmfmac: fix brcmf_sdcard_recv_chain() " Arend van Spriel
@ 2013-10-16 8:51 ` Arend van Spriel
12 siblings, 0 replies; 14+ messages in thread
From: Arend van Spriel @ 2013-10-16 8:51 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless
On 10/15/2013 03:44 PM, Arend van Spriel wrote:
> On our internal test setups it turned out that the MMC host controller
> did not support scatterlists (struct mmc_host::max_segs == 1). It took
> a number of patches to cleanup and support this. While at it some debug
> trace functions were modified and added.
Hi John,
Forgot to mention this series is intended for v3.13 and applies to the
master branch of the wireless-next repository.
Regards,
Arend
> Arend van Spriel (12):
> brcmfmac: store address in trace_brcmf_hexdump()
> brcmfmac: add tracepoint for capturing the SDPCM header
> brcmfmac: rename variable max_seg_sz to max_seg_cnt for clarity
> brcmfmac: determine host controller related variables during probe
> brcmfmac: rework scatter-gather code in brcmf_sdio_buffrw()
> brcmfmac: rename brcmf_sdio_buffrw()
> brcmfmac: rework single packet transfers
> brcmfmac: verify result of brcmf_sdio_addrprep() calls
> brcmfmac: remove stale code from brcmf_sdcard_recv_chain()
> brcmfmac: fix brcmf_sdcard_send_pkt() for host without sg support
> brcmfmac: fix brcmf_sdio_txpkt_prep() for host without sg support
> brcmfmac: fix brcmf_sdcard_recv_chain() for host without sg support
>
> drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 186 +++++++++++---------
> .../net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | 17 ++
> drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 111 +++++++-----
> .../net/wireless/brcm80211/brcmfmac/sdio_host.h | 6 +-
> .../net/wireless/brcm80211/brcmfmac/tracepoint.h | 21 ++-
> 5 files changed, 216 insertions(+), 125 deletions(-)
>
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2013-10-16 8:52 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-10-15 13:44 [PATCH 00/12] brcmfmac: fixes for MMC hosts without scatter-gather Arend van Spriel
2013-10-15 13:44 ` [PATCH 01/12] brcmfmac: store address in trace_brcmf_hexdump() Arend van Spriel
2013-10-15 13:44 ` [PATCH 02/12] brcmfmac: add tracepoint for capturing the SDPCM header Arend van Spriel
2013-10-15 13:44 ` [PATCH 03/12] brcmfmac: rename variable max_seg_sz to max_seg_cnt for clarity Arend van Spriel
2013-10-15 13:44 ` [PATCH 04/12] brcmfmac: determine host controller related variables during probe Arend van Spriel
2013-10-15 13:44 ` [PATCH 05/12] brcmfmac: rework scatter-gather code in brcmf_sdio_buffrw() Arend van Spriel
2013-10-15 13:44 ` [PATCH 06/12] brcmfmac: rename brcmf_sdio_buffrw() Arend van Spriel
2013-10-15 13:44 ` [PATCH 07/12] brcmfmac: rework single packet transfers Arend van Spriel
2013-10-15 13:44 ` [PATCH 08/12] brcmfmac: verify result of brcmf_sdio_addrprep() calls Arend van Spriel
2013-10-15 13:44 ` [PATCH 09/12] brcmfmac: remove stale code from brcmf_sdcard_recv_chain() Arend van Spriel
2013-10-15 13:44 ` [PATCH 10/12] brcmfmac: fix brcmf_sdcard_send_pkt() for host without sg support Arend van Spriel
2013-10-15 13:44 ` [PATCH 11/12] brcmfmac: fix brcmf_sdio_txpkt_prep() " Arend van Spriel
2013-10-15 13:44 ` [PATCH 12/12] brcmfmac: fix brcmf_sdcard_recv_chain() " Arend van Spriel
2013-10-16 8:51 ` [PATCH 00/12] brcmfmac: fixes for MMC hosts without scatter-gather Arend van Spriel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).