lkml.org 
[lkml]   [2004]   [Oct]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: MMC performance
Alan Cox wrote:

>Only on retries. You can try and blast the lot out the first time then
>on retries you write sector by sector.
>
>
>
Something like this? Gives more than double throughput here.

Index: linux-wbsd/drivers/mmc/mmc_block.c
===================================================================
--- linux-wbsd/drivers/mmc/mmc_block.c (revision 71)
+++ linux-wbsd/drivers/mmc/mmc_block.c (working copy)
@@ -166,9 +166,20 @@
struct mmc_blk_data *md = mq->data;
struct mmc_card *card = md->queue.card;
int ret;
+ int failsafe;

if (mmc_card_claim_host(card))
goto cmd_err;
+
+ /*
+ * We first try transfering multiple blocks. If this fails
+ * we fall back to single block transfers.
+ *
+ * This gives us good performance when all is well and the
+ * possibility to determine which sector fails when all
+ * is not well.
+ */
+ failsafe = 0;

do {
struct mmc_blk_request brq;
@@ -188,15 +199,24 @@
brq.stop.opcode = MMC_STOP_TRANSMISSION;
brq.stop.arg = 0;
brq.stop.flags = MMC_RSP_R1B;
+
+ /*
+ * A multi-block transfer failed. Falling back to single
+ * blocks.
+ */
+ if (failsafe)
+ brq.data.blocks = 1;
+
+ ret = 1;

if (rq_data_dir(req) == READ) {
brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK;
brq.data.flags |= MMC_DATA_READ;
} else {
- brq.cmd.opcode = MMC_WRITE_BLOCK;
+ brq.cmd.opcode = brq.data.blocks > 1 ? MMC_WRITE_MULTIPLE_BLOCK :
+ MMC_WRITE_BLOCK;
brq.cmd.flags = MMC_RSP_R1B;
brq.data.flags |= MMC_DATA_WRITE;
- brq.data.blocks = 1;
}
brq.mrq.stop = brq.data.blocks > 1 ? &brq.stop : NULL;

@@ -204,19 +224,34 @@
if (brq.cmd.error) {
printk(KERN_ERR "%s: error %d sending read/write command\n",
req->rq_disk->disk_name, brq.cmd.error);
- goto cmd_err;
+ if (failsafe)
+ goto cmd_err;
+ else {
+ failsafe = 1;
+ continue;
+ }
}

if (brq.data.error) {
printk(KERN_ERR "%s: error %d transferring data\n",
req->rq_disk->disk_name, brq.data.error);
- goto cmd_err;
+ if (failsafe)
+ goto cmd_err;
+ else {
+ failsafe = 1;
+ continue;
+ }
}

if (brq.stop.error) {
printk(KERN_ERR "%s: error %d sending stop command\n",
req->rq_disk->disk_name, brq.stop.error);
- goto cmd_err;
+ if (failsafe)
+ goto cmd_err;
+ else {
+ failsafe = 1;
+ continue;
+ }
}

do {
@@ -229,7 +264,12 @@
if (err) {
printk(KERN_ERR "%s: error %d requesting status\n",
req->rq_disk->disk_name, err);
- goto cmd_err;
+ if (failsafe)
+ goto cmd_err;
+ else {
+ failsafe = 1;
+ continue;
+ }
}
} while (!(cmd.resp[0] & R1_READY_FOR_DATA));

@@ -255,6 +295,11 @@
end_that_request_last(req);
}
spin_unlock_irq(&md->lock);
+
+ /*
+ * Go back to bulk mode if in failsafe mode.
+ */
+ failsafe = 0;
} while (ret);

mmc_card_release_host(card);
\
 
 \ /
  Last update: 2005-03-22 14:06    [from the cache]
©2003-2011 Jasper Spaans