[PATCH] [MTD] NAND: Add panic_write for NAND flashes

ye janboe janboe.ye at gmail.com
Tue Aug 18 04:42:05 EDT 2009


why this patch is not accepted?

Thanks

Janboe Ye

2008/9/23 Edgar E. Iglesias <edgar.iglesias at axis.com>:
> Hello,
>
> This is a quick and dirty patch to add panic_write for NAND flashes.
> The patch seems to work OK on my CRIS board running a 2.6.26 kernel
> with a ID: 0x20, Chip ID: 0xf1 (ST Micro NAND 128MiB 3,3V 8-bit).
> Also compile tested on a fresh x86 MTD git clone.
>
> If you find it useful feel free to apply it, otherwise >/dev/null.
>
> Thanks,
>
> Signed-off-by: Edgar E. Iglesias <edgar at axis.com>
>
>  drivers/mtd/nand/nand_base.c |  129 +++++++++++++++++++++++++++++++++++++++---
>  1 files changed, 121 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
> index 0a9c9cd..442a7de 100644
> --- a/drivers/mtd/nand/nand_base.c
> +++ b/drivers/mtd/nand/nand_base.c
> @@ -414,6 +414,28 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
>        return nand_isbad_bbt(mtd, ofs, allowbbt);
>  }
>
> +/**
> + * panic_nand_wait_ready - [GENERIC] Wait for the ready pin after commands.
> + * @mtd:       MTD device structure
> + * @timeo:     Timeout
> + *
> + * Helper function for nand_wait_ready used when needing to wait in interrupt
> + * context.
> + */
> +static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo)
> +{
> +       struct nand_chip *chip = mtd->priv;
> +       int i;
> +
> +       /* Give the device 400 ms to get ready?  */
> +       for (i = 0; i < timeo; i++) {
> +               if (chip->dev_ready(mtd))
> +                       break;
> +               touch_softlockup_watchdog();
> +               mdelay(1);
> +       }
> +}
> +
>  /*
>  * Wait for the ready pin, after a command
>  * The timeout is catched later.
> @@ -423,6 +445,10 @@ void nand_wait_ready(struct mtd_info *mtd)
>        struct nand_chip *chip = mtd->priv;
>        unsigned long timeo = jiffies + 2;
>
> +       /* 400ms timeout?  */
> +       if (in_interrupt())
> +               return panic_nand_wait_ready(mtd, 400);
> +
>        led_trigger_event(nand_led_trigger, LED_FULL);
>        /* wait until command is processed or timeout occures */
>        do {
> @@ -658,6 +684,23 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
>  }
>
>  /**
> + * panic_nand_get_device - [GENERIC] Get chip for selected access
> + * @chip:      the nand chip descriptor
> + * @mtd:       MTD device structure
> + * @new_state: the state which is requested
> + *
> + * Used when in panic, no locks are taken.
> + */
> +static void
> +panic_nand_get_device(struct nand_chip *chip,
> +                     struct mtd_info *mtd, int new_state)
> +{
> +       /* Hardware controller shared among independend devices */
> +       chip->controller->active = chip;
> +       chip->state = new_state;
> +}
> +
> +/**
>  * nand_get_device - [GENERIC] Get chip for selected access
>  * @chip:      the nand chip descriptor
>  * @mtd:       MTD device structure
> @@ -697,6 +740,32 @@ nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state)
>  }
>
>  /**
> + * panic_nand_wait - [GENERIC]  wait until the command is done
> + * @mtd:       MTD device structure
> + * @chip:      NAND chip structure
> + * @timeo:     Timeout
> + *
> + * Wait for command done. This is a helper function for nand_wait used when
> + * we are in interrupt context. May happen when in panic and trying to write
> + * an oops trough mtdoops.
> + */
> +static void panic_nand_wait(struct mtd_info *mtd, struct nand_chip *chip,
> +                           unsigned long timeo)
> +{
> +       int i;
> +       for (i = 0; i < timeo; i++) {
> +               if (chip->dev_ready) {
> +                       if (chip->dev_ready(mtd))
> +                               break;
> +               } else {
> +                       if (chip->read_byte(mtd) & NAND_STATUS_READY)
> +                               break;
> +               }
> +               mdelay(1);
> +        }
> +}
> +
> +/**
>  * nand_wait - [DEFAULT]  wait until the command is done
>  * @mtd:       MTD device structure
>  * @chip:      NAND chip structure
> @@ -727,15 +796,19 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
>        else
>                chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
>
> -       while (time_before(jiffies, timeo)) {
> -               if (chip->dev_ready) {
> -                       if (chip->dev_ready(mtd))
> -                               break;
> -               } else {
> -                       if (chip->read_byte(mtd) & NAND_STATUS_READY)
> -                               break;
> +       if (in_interrupt())
> +               panic_nand_wait(mtd, chip, timeo);
> +       else {
> +               while (time_before(jiffies, timeo)) {
> +                       if (chip->dev_ready) {
> +                               if (chip->dev_ready(mtd))
> +                                       break;
> +                       } else {
> +                               if (chip->read_byte(mtd) & NAND_STATUS_READY)
> +                                       break;
> +                       }
> +                       cond_resched();
>                }
> -               cond_resched();
>        }
>        led_trigger_event(nand_led_trigger, LED_OFF);
>
> @@ -1797,6 +1870,45 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
>  }
>
>  /**
> + * panic_nand_write - [MTD Interface] NAND write with ECC
> + * @mtd:       MTD device structure
> + * @to:                offset to write to
> + * @len:       number of bytes to write
> + * @retlen:    pointer to variable to store the number of written bytes
> + * @buf:       the data to write
> + *
> + * NAND write with ECC. Used when performing writes in interrupt context, this
> + * may for example be called by mtdoops when writing an oops while in panic.
> + */
> +static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
> +                           size_t *retlen, const uint8_t *buf)
> +{
> +       struct nand_chip *chip = mtd->priv;
> +       int ret;
> +
> +       /* Do not allow reads past end of device */
> +       if ((to + len) > mtd->size)
> +               return -EINVAL;
> +       if (!len)
> +               return 0;
> +
> +       /* Wait for the device to get ready.  */
> +       panic_nand_wait(mtd, chip, 400);
> +
> +       /* Grab the device.  */
> +       panic_nand_get_device(chip, mtd, FL_WRITING);
> +
> +       chip->ops.len = len;
> +       chip->ops.datbuf = (uint8_t *)buf;
> +       chip->ops.oobbuf = NULL;
> +
> +       ret = nand_do_write_ops(mtd, to, &chip->ops);
> +
> +       *retlen = chip->ops.retlen;
> +       return ret;
> +}
> +
> +/**
>  * nand_write - [MTD Interface] NAND write with ECC
>  * @mtd:       MTD device structure
>  * @to:                offset to write to
> @@ -2694,6 +2806,7 @@ int nand_scan_tail(struct mtd_info *mtd)
>        mtd->unpoint = NULL;
>        mtd->read = nand_read;
>        mtd->write = nand_write;
> +       mtd->panic_write = panic_nand_write;
>        mtd->read_oob = nand_read_oob;
>        mtd->write_oob = nand_write_oob;
>        mtd->sync = nand_sync;
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>



More information about the linux-mtd mailing list