Bulk transfers (round 2)
PATCH 1/1 Bulk transfers (round 2)
I didn't get any response for this one either ;)
This is only a performance boost so it is less critical. It is very nice to have though since the performance gain is substancial (>100%).
It should not pose any problems with data loss, which was your primary concern. It backs down to single block transfers when an error is detected.
This patch has been downloaded almost 500 times and there have been no errors reported that were related directly to the patch. The two errors reported from using this was in the driver and with a buggy card (the same one that needs the power cycle patch).
Kconfig default here is 'no' but 'yes' should be considered once it has been tested on some more controllers.
Rgds
Pierre
it might help if I include the actual patch...
drivers/mmc/mmc_block.c +61 -6
@@ -166,9 +166,25 @@struct mmc_blk_data *md = mq->data;struct mmc_card *card = md->queue.card;int ret; + +#ifdef CONFIG_MMC_BULKTRANSFER +int failsafe; +#endif if (mmc_card_claim_host (card)) goto cmd_err; + +#ifdef CONFIG_MMC_BULKTRANSFER +/* +* 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 ; +#endif do { struct mmc_blk_request brq;
@@ -189,14 +205,32 @@ brq.stop.arg =0 ; brq.stop.flags =MMC_RSP_R1B ; +#ifdef CONFIG_MMC_BULKTRANSFER +/* +* A multi-block transfer failed. Falling back to single +* blocks. +*/ +if (failsafe) + brq.data.blocks =1 ; + +#else +/* +* Writes are done one sector at a time. +*/ +if (rq_data_dir (req) !=READ ) + brq.data.blocks =1 ; +#endif + + 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 +238,19 @@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; + goto cmd_fail; }if (brq.data.error) {printk (KERN_ERR "%s: error %d transferring data\n" , req->rq_disk->disk_name, brq.data.error); - goto cmd_err; + goto cmd_fail; }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; + goto cmd_fail; } do {
@@ -229,7 +263,7 @@if (err) {printk (KERN_ERR "%s: error %d requesting status\n" , req->rq_disk->disk_name, err); - goto cmd_err; + goto cmd_fail; } }while (!(cmd.resp[0 ] &R1_READY_FOR_DATA ));
@@ -255,6 +289,27 @@end_that_request_last (req); }spin_unlock_irq (&md->lock); + +#ifdef CONFIG_MMC_BULKTRANSFER +/* +* Go back to bulk mode if in failsafe mode. +*/ + failsafe =0 ; +#endif + +continue ; + + cmd_fail: + +#ifdef CONFIG_MMC_BULKTRANSFER +if (failsafe) + goto cmd_err; +else + failsafe =1 ; +#else + goto cmd_err; +#endif + }while (ret);mmc_card_release_host (card);
drivers/mmc/Kconfig +9 -0
@@ -41,6 +41,15 @@ mount the filesystem. Almost everyone wishing MMC support should say Y or M here. +config MMC_BULKTRANSFER + bool "Multi-block writes (EXPERIMENTAL)" + depends on MMC_BLOCK != n && EXPERIMENTAL + default n + help + By default all writes are done one sector at a time. Enable + this option to transfer as large blocks as the host supports. + The transfer speed is in most cases doubled. + config MMC_ARMMMCI tristate "ARM AMBA Multimedia Card Interface support" depends on ARM_AMBA && MMC