linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [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).