From: David Vrabel <david.vrabel@csr.com>
To: Pierre Ossman <drzeus-list@drzeus.cx>
Cc: linux-kernel@vger.kernel.org
Subject: [patch 3/3] sdio: extend sdio_readsb() and friends to handle any length of buffer
Date: Wed, 08 Aug 2007 14:24:21 +0100 [thread overview]
Message-ID: <46B9C405.2070003@csr.com> (raw)
In-Reply-To: <46B9C38C.1030708@csr.com>
[-- Attachment #1: Type: text/plain, Size: 152 bytes --]
--
David Vrabel, Software Engineer, Drivers group Tel: +44 (0)1223 692562
CSR plc, Churchill House, Cambridge Business Park, Cowley Road, CB4 0WZ
.
[-- Attachment #2: sdio-extend-sdio-readsb-and-friends-to-handle-any-length-of-buffer.patch --]
[-- Type: text/x-patch, Size: 7004 bytes --]
sdio: extend sdio_readsb() and friends to handle any length of buffer
Extend sdio_readsb(), sdio_writesb(), sdio_memcpy_fromio(), and
sdio_memcpy_toio() to handle any length of buffer by splitting the transfer
into several IO_RW_EXTENDED commands. Typically, a transfer would be split
into a single block mode transfer followed by a byte mode transfer for the
remainder but we also handle lack of block mode support and the block size
being greater than 512 (the maximum byte mode transfer size).
host->max_seg_size <= host->max_req_size so there's no need to check both
when determining the maximum data size for a single command.
Signed-off-by: David Vrabel <david.vrabel@csr.com>
---
Index: mmc/drivers/mmc/core/sdio_io.c
===================================================================
--- mmc.orig/drivers/mmc/core/sdio_io.c 2007-08-08 13:34:09.000000000 +0100
+++ mmc/drivers/mmc/core/sdio_io.c 2007-08-08 13:34:17.000000000 +0100
@@ -193,6 +193,69 @@
EXPORT_SYMBOL_GPL(sdio_set_block_size);
+/* Split an arbitrarily sized data transfer into several
+ * IO_RW_EXTENDED commands. */
+static int sdio_io_rw_ext_helper(struct sdio_func *func, int write,
+ unsigned addr, int incr_addr, u8 *buf, unsigned size)
+{
+ unsigned remainder = size;
+ unsigned max_blocks;
+ int ret;
+
+ /* Do the bulk of the transfer using block mode (if supported). */
+ if (func->card->cccr.multi_block) {
+ unsigned max_blocks;
+
+ /* Blocks per command is limited by host count, host transfer
+ * size (we only use a single sg entry) and the maximum for
+ * IO_RW_EXTENDED of 511 blocks. */
+ max_blocks = min(min(
+ func->card->host->max_blk_count,
+ func->card->host->max_seg_size / func->cur_blksize),
+ 511u);
+
+ while (remainder > func->cur_blksize) {
+ unsigned blocks;
+
+ blocks = remainder % func->cur_blksize;
+ if (blocks > max_blocks)
+ blocks = max_blocks;
+ size = blocks * func->cur_blksize;
+
+ ret = mmc_io_rw_extended(func->card, write,
+ func->num, addr, incr_addr, buf,
+ blocks, func->cur_blksize);
+ if (ret)
+ return ret;
+
+ remainder -= size;
+ buf += size;
+ if (incr_addr)
+ addr += size;
+ }
+ }
+
+ /* Write the remainder using byte mode. */
+ while (remainder > 0) {
+ size = remainder;
+ if (size > func->cur_blksize)
+ size = func->cur_blksize;
+ if (size > 512)
+ size = 512; /* maximum size for byte mode */
+
+ ret = mmc_io_rw_extended(func->card, write, func->num, addr,
+ incr_addr, buf, 1, size);
+ if (ret)
+ return ret;
+
+ remainder -= size;
+ buf += size;
+ if (incr_addr)
+ addr += size;
+ }
+ return 0;
+}
+
/**
* sdio_readb - read a single byte from a SDIO function
* @func: SDIO function to access
@@ -258,15 +321,13 @@
* @addr: address to begin reading from
* @count: number of bytes to read
*
- * Reads up to 512 bytes from the address space of a given SDIO
- * function. Return value indicates if the transfer succeeded or
- * not.
+ * Reads from the address space of a given SDIO function. Return
+ * value indicates if the transfer succeeded or not.
*/
int sdio_memcpy_fromio(struct sdio_func *func, void *dst,
unsigned int addr, int count)
{
- return mmc_io_rw_extended(func->card, 0, func->num, addr, 0, dst,
- count);
+ return sdio_io_rw_ext_helper(func, 0, addr, 1, dst, count);
}
EXPORT_SYMBOL_GPL(sdio_memcpy_fromio);
@@ -278,15 +339,13 @@
* @src: buffer that contains the data to write
* @count: number of bytes to write
*
- * Writes up to 512 bytes to the address space of a given SDIO
- * function. Return value indicates if the transfer succeeded or
- * not.
+ * Writes to the address space of a given SDIO function. Return
+ * value indicates if the transfer succeeded or not.
*/
int sdio_memcpy_toio(struct sdio_func *func, unsigned int addr,
void *src, int count)
{
- return mmc_io_rw_extended(func->card, 1, func->num, addr, 0, src,
- count);
+ return sdio_io_rw_ext_helper(func, 1, addr, 1, src, count);
}
/**
@@ -296,15 +355,13 @@
* @addr: address of (single byte) FIFO
* @count: number of bytes to read
*
- * Reads up to 512 bytes from the specified FIFO of a given SDIO
- * function. Return value indicates if the transfer succeeded or
- * not.
+ * Reads from the specified FIFO of a given SDIO function. Return
+ * value indicates if the transfer succeeded or not.
*/
int sdio_readsb(struct sdio_func *func, void *dst, unsigned int addr,
int count)
{
- return mmc_io_rw_extended(func->card, 0, func->num, addr, 1, dst,
- count);
+ return sdio_io_rw_ext_helper(func, 0, addr, 0, dst, count);
}
EXPORT_SYMBOL_GPL(sdio_readsb);
@@ -323,8 +380,7 @@
int sdio_writesb(struct sdio_func *func, unsigned int addr, void *src,
int count)
{
- return mmc_io_rw_extended(func->card, 1, func->num, addr, 1, src,
- count);
+ return sdio_io_rw_ext_helper(func, 1, addr, 0, src, count);
}
EXPORT_SYMBOL_GPL(sdio_writesb);
Index: mmc/drivers/mmc/core/sdio_ops.c
===================================================================
--- mmc.orig/drivers/mmc/core/sdio_ops.c 2007-08-08 13:29:47.000000000 +0100
+++ mmc/drivers/mmc/core/sdio_ops.c 2007-08-08 13:34:17.000000000 +0100
@@ -88,7 +88,7 @@
}
int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
- unsigned addr, int bang, u8 *buf, unsigned size)
+ unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz)
{
struct mmc_request mrq;
struct mmc_command cmd;
@@ -97,7 +97,7 @@
BUG_ON(!card);
BUG_ON(fn > 7);
- BUG_ON(size > 512);
+ BUG_ON(blocks == 1 && blksz > 512);
memset(&mrq, 0, sizeof(struct mmc_request));
memset(&cmd, 0, sizeof(struct mmc_command));
@@ -109,18 +109,21 @@
cmd.opcode = SD_IO_RW_EXTENDED;
cmd.arg = write ? 0x80000000 : 0x00000000;
cmd.arg |= fn << 28;
- cmd.arg |= bang ? 0x00000000 : 0x04000000;
+ cmd.arg |= incr_addr ? 0x04000000 : 0x00000000;
cmd.arg |= addr << 9;
- cmd.arg |= (size == 512) ? 0 : size;
+ if (blocks == 1 && blksz <= 512)
+ cmd.arg |= (blksz == 512) ? 0 : blksz; /* byte mode */
+ else
+ cmd.arg |= 0x08000000 | blocks; /* block mode */
cmd.flags = MMC_RSP_R5 | MMC_CMD_ADTC;
- data.blksz = size;
- data.blocks = 1;
+ data.blksz = blksz;
+ data.blocks = blocks;
data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
data.sg = &sg;
data.sg_len = 1;
- sg_init_one(&sg, buf, size);
+ sg_init_one(&sg, buf, blksz * blocks);
mmc_set_data_timeout(&data, card, 0);
Index: mmc/drivers/mmc/core/sdio_ops.h
===================================================================
--- mmc.orig/drivers/mmc/core/sdio_ops.h 2007-08-08 13:29:47.000000000 +0100
+++ mmc/drivers/mmc/core/sdio_ops.h 2007-08-08 13:34:17.000000000 +0100
@@ -16,7 +16,7 @@
int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
unsigned addr, u8 in, u8* out);
int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
- unsigned addr, int bang, u8 *data, unsigned size);
+ unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz);
#endif
next prev parent reply other threads:[~2007-08-08 13:25 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-07-31 15:36 sdio: enhance IO_RW_EXTENDED support David Vrabel
2007-07-31 15:36 ` sdio: parameterize SDIO FBR register defines David Vrabel
2007-08-04 13:26 ` Pierre Ossman
2007-08-06 10:14 ` David Vrabel
2007-08-06 14:58 ` Pierre Ossman
2007-07-31 15:36 ` sdio: set the functions' block size David Vrabel
2007-08-04 13:30 ` Pierre Ossman
2007-08-06 10:04 ` David Vrabel
2007-07-31 15:36 ` sdio: extend sdio_readsb() and friends to handle any length of buffer David Vrabel
2007-08-04 13:35 ` Pierre Ossman
2007-08-04 13:23 ` sdio: enhance IO_RW_EXTENDED support Pierre Ossman
2007-08-06 10:31 ` David Vrabel
2007-08-06 15:12 ` Pierre Ossman
2007-08-06 15:32 ` David Vrabel
2007-08-06 18:06 ` Pierre Ossman
2007-08-06 20:01 ` Pierre Ossman
2007-08-07 12:51 ` David Vrabel
2007-08-07 12:53 ` [patch 1/4] sdio: parameterize SDIO FBR register defines David Vrabel
2007-08-07 12:54 ` [patch 2/4] sdio: set the functions' block size David Vrabel
2007-08-07 13:38 ` Pierre Ossman
2007-08-07 17:20 ` David Vrabel
2007-08-07 17:54 ` Pierre Ossman
2007-08-08 9:46 ` David Vrabel
2007-08-08 10:06 ` Pierre Ossman
2007-08-08 10:19 ` David Vrabel
2007-08-07 12:55 ` [patch 3/4] sdio: extend sdio_readsb() and friends to handle any length of buffer David Vrabel
2007-08-07 13:42 ` Pierre Ossman
2007-08-07 20:17 ` Pierre Ossman
2007-08-08 10:19 ` David Vrabel
2007-08-08 10:37 ` Pierre Ossman
2007-08-08 13:22 ` David Vrabel
2007-08-08 13:23 ` [patch 1/3] sdio: add SDIO_FBR_BASE(f) macro David Vrabel
2007-08-08 13:23 ` [patch 2/3] sdio: set the functions' block size David Vrabel
2007-08-08 13:24 ` David Vrabel [this message]
2007-08-08 16:55 ` [patch 3/4] sdio: extend sdio_readsb() and friends to handle any length of buffer Pierre Ossman
2007-08-07 12:55 ` [patch 4/4] sdio: disable CD resistor David Vrabel
2007-08-07 13:43 ` Pierre Ossman
2007-08-07 14:46 ` David Vrabel
2007-08-07 15:08 ` Pierre Ossman
2007-08-07 13:33 ` sdio: enhance IO_RW_EXTENDED support Pierre Ossman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=46B9C405.2070003@csr.com \
--to=david.vrabel@csr.com \
--cc=drzeus-list@drzeus.cx \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.