[PATCH]Fixes of performance and stability issues in CFI driver.
Alexey Korolev
akorolev at pentafluge.infradead.org
Fri Jul 14 04:48:05 EDT 2006
David,
Could you please commit the changes into repository?
I've got mail from Nicolas he found it acceptable.
>
> > Could you please tell me what do you think about this patch? It is not
> > included yet.
>
> It is fine and you can add my sign-off for it.
>
> Sorry for the delay. I was on vacation last week and I am about to have
> some more really soon. In other words I won't have much time for MTD
> stuff until mid august. This includes committing your patch (someone
> else will have to do it).
>
>
> Nicolas
>
> Here is a comment for the patch:
>
> Fix of performance and stability issues on NOR chips. It fixes:
> 1. Very low write performance on Sibley (perf tests demonstrated write performance less than 100Kb/sec when it should be over 400Kb/sec).
> 2. Low erase performance. (perf tests on Sibleuy demonstrated erase performance 246Kb/sec when it should be over 300Kb/sec).
> 3. Error on JFFS2 tests with CPU loading application when MTD returns "block erase error: (status timeout)"
> To fix the issue it does the following:
> 1. Removes the timeout tuning from inval_cache_and_wait_for_operation.
> 2. Waiting conditions in inval_cache_and_wait_for_operation now is based on timer resolution
> If timeout is lower than timer resolution then we do in cycle
> "Checking the status"
> udelay(1);
> cond_resched();
> If timeout is greater than timer resolution (probably erase operation)
> We do the following
> sleep for half of operation timeout
> and do in cycle the following
> "Checking the status"
> sleep for timer resolution
>
> Thanks,
> Alexey
>
>
> Signed-off-by: Nicolas Pitre <nico at cam.org>
> Signed-off-by: Alexey Korolev <akorolev at infradead.org>
>
> diff -aur orig/drivers/mtd/chips/cfi_cmdset_0001.c latest/drivers/mtd/chips/cfi_cmdset_0001.c
> --- orig/drivers/mtd/chips/cfi_cmdset_0001.c 2006-06-26 13:20:00.000000000 +0400
> +++ latest/drivers/mtd/chips/cfi_cmdset_0001.c 2006-06-28 21:56:09.611390112 +0400
> @@ -908,7 +908,7 @@
>
> static int __xipram xip_wait_for_operation(
> struct map_info *map, struct flchip *chip,
> - unsigned long adr, int *chip_op_time )
> + unsigned long adr, unsigned int chip_op_time )
> {
> struct cfi_private *cfi = map->fldrv_priv;
> struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
> @@ -917,7 +917,7 @@
> flstate_t oldstate, newstate;
>
> start = xip_currtime();
> - usec = *chip_op_time * 8;
> + usec = chip_op_time * 8;
> if (usec == 0)
> usec = 500000;
> done = 0;
> @@ -1027,8 +1027,8 @@
> #define XIP_INVAL_CACHED_RANGE(map, from, size) \
> INVALIDATE_CACHED_RANGE(map, from, size)
>
> -#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, p_usec) \
> - xip_wait_for_operation(map, chip, cmd_adr, p_usec)
> +#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, usec) \
> + xip_wait_for_operation(map, chip, cmd_adr, usec)
>
> #else
>
> @@ -1040,64 +1040,64 @@
> static int inval_cache_and_wait_for_operation(
> struct map_info *map, struct flchip *chip,
> unsigned long cmd_adr, unsigned long inval_adr, int inval_len,
> - int *chip_op_time )
> + unsigned int chip_op_time)
> {
> struct cfi_private *cfi = map->fldrv_priv;
> map_word status, status_OK = CMD(0x80);
> - int z, chip_state = chip->state;
> - unsigned long timeo;
> + int chip_state = chip->state;
> + unsigned int timeo, sleep_time;
>
> spin_unlock(chip->mutex);
> if (inval_len)
> INVALIDATE_CACHED_RANGE(map, inval_adr, inval_len);
> - if (*chip_op_time)
> - cfi_udelay(*chip_op_time);
> spin_lock(chip->mutex);
>
> - timeo = *chip_op_time * 8 * HZ / 1000000;
> - if (timeo < HZ/2)
> - timeo = HZ/2;
> - timeo += jiffies;
> + /* set our timeout to 8 times the expected delay */
> + timeo = chip_op_time * 8;
> + if (!timeo)
> + timeo = 500000;
> + sleep_time = chip_op_time / 2;
>
> - z = 0;
> for (;;) {
> - if (chip->state != chip_state) {
> - /* Someone's suspended the operation: sleep */
> - DECLARE_WAITQUEUE(wait, current);
> -
> - set_current_state(TASK_UNINTERRUPTIBLE);
> - add_wait_queue(&chip->wq, &wait);
> - spin_unlock(chip->mutex);
> - schedule();
> - remove_wait_queue(&chip->wq, &wait);
> - timeo = jiffies + (HZ / 2); /* FIXME */
> - spin_lock(chip->mutex);
> - continue;
> - }
> -
> status = map_read(map, cmd_adr);
> if (map_word_andequal(map, status, status_OK, status_OK))
> break;
>
> - /* OK Still waiting */
> - if (time_after(jiffies, timeo)) {
> + if (!timeo) {
> map_write(map, CMD(0x70), cmd_adr);
> chip->state = FL_STATUS;
> return -ETIME;
> }
>
> - /* Latency issues. Drop the lock, wait a while and retry */
> - z++;
> + /* OK Still waiting. Drop the lock, wait a while and retry. */
> spin_unlock(chip->mutex);
> - cfi_udelay(1);
> + if (sleep_time >= 1000000/HZ) {
> + /*
> + * Half of the normal delay still remaining
> + * can be performed with a sleeping delay instead
> + * of busy waiting.
> + */
> + msleep(sleep_time/1000);
> + timeo -= sleep_time;
> + sleep_time = 1000000/HZ;
> + } else {
> + udelay(1);
> + cond_resched();
> + timeo--;
> + }
> spin_lock(chip->mutex);
> - }
>
> - if (!z) {
> - if (!--(*chip_op_time))
> - *chip_op_time = 1;
> - } else if (z > 1)
> - ++(*chip_op_time);
> + if (chip->state != chip_state) {
> + /* Someone's suspended the operation: sleep */
> + DECLARE_WAITQUEUE(wait, current);
> + set_current_state(TASK_UNINTERRUPTIBLE);
> + add_wait_queue(&chip->wq, &wait);
> + spin_unlock(chip->mutex);
> + schedule();
> + remove_wait_queue(&chip->wq, &wait);
> + spin_lock(chip->mutex);
> + }
> + }
>
> /* Done and happy. */
> chip->state = FL_STATUS;
> @@ -1107,8 +1107,7 @@
> #endif
>
> #define WAIT_TIMEOUT(map, chip, adr, udelay) \
> - ({ int __udelay = (udelay); \
> - INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, &__udelay); })
> + INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, udelay);
>
>
> static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len)
> @@ -1332,7 +1331,7 @@
>
> ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
> adr, map_bankwidth(map),
> - &chip->word_write_time);
> + chip->word_write_time);
> if (ret) {
> xip_enable(map, chip, adr);
> printk(KERN_ERR "%s: word write error (status timeout)\n", map->name);
> @@ -1569,7 +1568,7 @@
>
> ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr,
> adr, len,
> - &chip->buffer_write_time);
> + chip->buffer_write_time);
> if (ret) {
> map_write(map, CMD(0x70), cmd_adr);
> chip->state = FL_STATUS;
> @@ -1704,7 +1703,7 @@
>
> ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
> adr, len,
> - &chip->erase_time);
> + chip->erase_time);
> if (ret) {
> map_write(map, CMD(0x70), adr);
> chip->state = FL_STATUS;
>
Thanks,
Alexey
More information about the linux-mtd
mailing list