[1/2] MTD: cfi_cmdset_0002: Add reboot notifier for AMD flashes

Submitted by Kevin Cernekee on April 13, 2010, 8:30 p.m.

Details

Message ID bb2e763d69a8cc1576fd58fbde424ff5f688c409@localhost.localdomain
State New, archived
Headers show

Commit Message

Kevin Cernekee April 13, 2010, 8:30 p.m.
Ensure that the flash device is in a quiescent state before rebooting.
The implementation is closely modeled after the cfe_cmdset_0001 reboot
notifier, commit 963a6fb0a0d336d0513083b7e4b5c3ff9d6d2061 .

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
---
 drivers/mtd/chips/cfi_cmdset_0002.c |   50 +++++++++++++++++++++++++++++++++++
 1 files changed, 50 insertions(+), 0 deletions(-)

Comments

Artem Bityutskiy April 14, 2010, 4:57 a.m.
On Tue, 2010-04-13 at 13:30 -0700, Kevin Cernekee wrote:
> +static int cfi_amdstd_reset(struct mtd_info *mtd)
> +{
> +	struct map_info *map = mtd->priv;
> +	struct cfi_private *cfi = map->fldrv_priv;
> +	int i, ret;
> +	struct flchip *chip;
> +
> +	for (i = 0; i < cfi->numchips; i++) {
> +
> +		chip = &cfi->chips[i];
> +
> +		spin_lock(chip->mutex);
> +
> +		ret = get_chip(map, chip, chip->start, FL_SHUTDOWN);
> +		if (!ret) {
> +			map_write(map, CMD(0xF0), chip->start);
> +			chip->state = FL_SHUTDOWN;
> +			put_chip(map, chip, chip->start);
> +		}
> +
> +		spin_unlock(chip->mutex);
> +	}
> +
> +	return 0;
> +}

Kevin, I'd suggest to document why you do this in the code, just for the
next generation, or for the archaeologists who will dig MTD code in the
future.
Fabio Giovagnini April 14, 2010, 5:33 a.m.
Exactly!!!!
Why this is requested?
Is it necessary for the best proper woring mode?

Thanks a lot


In data mercoledì 14 aprile 2010 06:57:58, Artem Bityutskiy ha scritto:
: > On Tue, 2010-04-13 at 13:30 -0700, Kevin Cernekee wrote:
> > +static int cfi_amdstd_reset(struct mtd_info *mtd)
> > +{
> > +	struct map_info *map = mtd->priv;
> > +	struct cfi_private *cfi = map->fldrv_priv;
> > +	int i, ret;
> > +	struct flchip *chip;
> > +
> > +	for (i = 0; i < cfi->numchips; i++) {
> > +
> > +		chip = &cfi->chips[i];
> > +
> > +		spin_lock(chip->mutex);
> > +
> > +		ret = get_chip(map, chip, chip->start, FL_SHUTDOWN);
> > +		if (!ret) {
> > +			map_write(map, CMD(0xF0), chip->start);
> > +			chip->state = FL_SHUTDOWN;
> > +			put_chip(map, chip, chip->start);
> > +		}
> > +
> > +		spin_unlock(chip->mutex);
> > +	}
> > +
> > +	return 0;
> > +}
> 
> Kevin, I'd suggest to document why you do this in the code, just for the
> next generation, or for the archaeologists who will dig MTD code in the
> future.
>

Patch hide | download patch | download mbox

diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index ea2a7f6..4b10072 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -32,6 +32,7 @@ 
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/reboot.h>
 #include <linux/mtd/compatmac.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/mtd.h>
@@ -56,6 +57,7 @@  static int cfi_amdstd_erase_varsize(struct mtd_info *, struct erase_info *);
 static void cfi_amdstd_sync (struct mtd_info *);
 static int cfi_amdstd_suspend (struct mtd_info *);
 static void cfi_amdstd_resume (struct mtd_info *);
+static int cfi_amdstd_reboot(struct notifier_block *, unsigned long, void *);
 static int cfi_amdstd_secsi_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
 
 static void cfi_amdstd_destroy(struct mtd_info *);
@@ -351,6 +353,8 @@  struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
 	mtd->name    = map->name;
 	mtd->writesize = 1;
 
+	mtd->reboot_notifier.notifier_call = cfi_amdstd_reboot;
+
 	if (cfi->cfi_mode==CFI_MODE_CFI){
 		unsigned char bootloc;
 		/*
@@ -487,6 +491,7 @@  static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd)
 #endif
 
 	__module_get(THIS_MODULE);
+	register_reboot_notifier(&mtd->reboot_notifier);
 	return mtd;
 
  setup_err:
@@ -628,6 +633,10 @@  static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
 		chip->state = FL_READY;
 		return 0;
 
+	case FL_SHUTDOWN:
+		/* The machine is rebooting */
+		return -EIO;
+
 	case FL_POINT:
 		/* Only if there's no operation suspended... */
 		if (mode == FL_READY && chip->oldstate == FL_READY)
@@ -1918,11 +1927,52 @@  static void cfi_amdstd_resume(struct mtd_info *mtd)
 	}
 }
 
+
+static int cfi_amdstd_reset(struct mtd_info *mtd)
+{
+	struct map_info *map = mtd->priv;
+	struct cfi_private *cfi = map->fldrv_priv;
+	int i, ret;
+	struct flchip *chip;
+
+	for (i = 0; i < cfi->numchips; i++) {
+
+		chip = &cfi->chips[i];
+
+		spin_lock(chip->mutex);
+
+		ret = get_chip(map, chip, chip->start, FL_SHUTDOWN);
+		if (!ret) {
+			map_write(map, CMD(0xF0), chip->start);
+			chip->state = FL_SHUTDOWN;
+			put_chip(map, chip, chip->start);
+		}
+
+		spin_unlock(chip->mutex);
+	}
+
+	return 0;
+}
+
+
+static int cfi_amdstd_reboot(struct notifier_block *nb, unsigned long val,
+			       void *v)
+{
+	struct mtd_info *mtd;
+
+	mtd = container_of(nb, struct mtd_info, reboot_notifier);
+	cfi_amdstd_reset(mtd);
+	return NOTIFY_DONE;
+}
+
+
 static void cfi_amdstd_destroy(struct mtd_info *mtd)
 {
 	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
 
+	cfi_amdstd_reset(mtd);
+	unregister_reboot_notifier(&mtd->reboot_notifier);
 	kfree(cfi->cmdset_priv);
 	kfree(cfi->cfiq);
 	kfree(cfi);