* [PATCH] [MTD] NAND: Add panic_write for NAND flashes
@ 2008-09-23 12:26 Edgar E. Iglesias
2009-08-18 8:42 ` ye janboe
0 siblings, 1 reply; 2+ messages in thread
From: Edgar E. Iglesias @ 2008-09-23 12:26 UTC (permalink / raw)
To: linux-mtd
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@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;
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] [MTD] NAND: Add panic_write for NAND flashes
2008-09-23 12:26 [PATCH] [MTD] NAND: Add panic_write for NAND flashes Edgar E. Iglesias
@ 2009-08-18 8:42 ` ye janboe
0 siblings, 0 replies; 2+ messages in thread
From: ye janboe @ 2009-08-18 8:42 UTC (permalink / raw)
To: Edgar E. Iglesias; +Cc: linux-mtd
why this patch is not accepted?
Thanks
Janboe Ye
2008/9/23 Edgar E. Iglesias <edgar.iglesias@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@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/
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2009-08-18 8:42 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-09-23 12:26 [PATCH] [MTD] NAND: Add panic_write for NAND flashes Edgar E. Iglesias
2009-08-18 8:42 ` ye janboe
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.