From: David Vrabel <david.vrabel@csr.com>
To: Pierre Ossman <drzeus-list@drzeus.cx>
Cc: linux-kernel@vger.kernel.org
Subject: [patch 3/4] sdio: extend sdio_readsb() and friends to handle any length of buffer
Date: Tue, 07 Aug 2007 13:55:12 +0100 [thread overview]
Message-ID: <46B86BB0.4000100@csr.com> (raw)
In-Reply-To: <46B86ADB.90000@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: 6864 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.
For this to work the block size must be limited to the maximum size of a
byte mode transfer (512 bytes). This limitation could be revisited if
there are any cards out there that require a block size > 512.
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-07 07:27:31.000000000 +0100
+++ mmc/drivers/mmc/core/sdio_io.c 2007-08-07 07:35:02.000000000 +0100
@@ -153,6 +153,13 @@
{
int ret;
+ /* The standard permits block sizes up to 2048 bytes, but
+ * sdio_readsb() etc. can only work with block size <= 512. */
+ if (blksz > 512) {
+ blksz = 512;
+ dev_warn(&func->dev, "block size limited to 512 bytes\n");
+ }
+
ret = mmc_io_rw_direct(func->card, 1, 0,
SDIO_FBR_BASE(func->num) + SDIO_FBR_BLKSIZE,
blksz & 0xff, NULL);
@@ -227,6 +234,48 @@
EXPORT_SYMBOL_GPL(sdio_writeb);
+/* 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 fn, unsigned addr, int incr_addr, u8 *buf, unsigned size)
+{
+ unsigned remainder = size;
+ unsigned max_blocks;
+ int ret;
+
+ /* 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, fn, addr,
+ incr_addr, buf, blocks, func->cur_blksize);
+ if (ret)
+ return ret;
+
+ remainder -= size;
+ buf += size;
+ if (incr_addr)
+ addr += size;
+ }
+
+ if (remainder)
+ ret = mmc_io_rw_extended(func->card, write, fn, addr,
+ incr_addr, buf, 1, remainder);
+ return ret;
+}
+
/**
* sdio_memcpy_fromio - read a chunk of memory from a SDIO function
* @func: SDIO function to access
@@ -234,14 +283,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,
+ return sdio_io_rw_ext_helper(func, 0, func->num, addr, 1, dst,
count);
}
@@ -254,14 +302,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,
+ return sdio_io_rw_ext_helper(func, 1, func->num, addr, 1, src,
count);
}
@@ -272,14 +319,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,
+ return sdio_io_rw_ext_helper(func, 0, func->num, addr, 0, dst,
count);
}
@@ -299,7 +345,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,
+ return sdio_io_rw_ext_helper(func, 1, func->num, addr, 0, src,
count);
}
Index: mmc/drivers/mmc/core/sdio_ops.c
===================================================================
--- mmc.orig/drivers/mmc/core/sdio_ops.c 2007-08-07 07:27:27.000000000 +0100
+++ mmc/drivers/mmc/core/sdio_ops.c 2007-08-07 07:27:31.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,22 @@
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) {
+ cmd.arg |= 0x08000000;
+ cmd.arg |= blocks;
+ } else
+ cmd.arg |= (blksz == 512) ? 0 : blksz;
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-07 07:27:27.000000000 +0100
+++ mmc/drivers/mmc/core/sdio_ops.h 2007-08-07 07:27:31.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-07 12:56 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 ` David Vrabel [this message]
2007-08-07 13:42 ` [patch 3/4] sdio: extend sdio_readsb() and friends to handle any length of buffer 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 ` [patch 3/3] sdio: extend sdio_readsb() and friends to handle any length of buffer David Vrabel
2007-08-08 16:55 ` [patch 3/4] " 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=46B86BB0.4000100@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.