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    [W:0.059 / U:120.892 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site