From: Kevin Hao <haokexin@gmail.com>
Date: Tue, 2 Oct 2007 20:56:04 +0000 (-0700)
Subject: [MTD] [NOR] fix ctrl-alt-del can't reboot for intel flash bug
X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=c4a9f88daf6c382fedde4cdddef0b30f1d0a20db;p=GitHub%2Fexynos8895%2Fandroid_kernel_samsung_universal8895.git

[MTD] [NOR] fix ctrl-alt-del can't reboot for intel flash bug

When we press ctrl-alt-del,kernel_restart_prepare will invoke
cfi_intelext_reboot which will set flash to read array mode, but later
when device_shutdown is invoked which may put current work queue to
sleep and other process may be scheduled to running and programming
flash in not FL_READY mode again. So we can't boot up if this flash is
used for bootloader.

Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
---

diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index c655e971c158..3aa3dca56ae6 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -653,7 +653,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
  resettime:
 	timeo = jiffies + HZ;
  retry:
-	if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING || mode == FL_OTP_WRITE)) {
+	if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING || mode == FL_OTP_WRITE || mode == FL_SHUTDOWN)) {
 		/*
 		 * OK. We have possibility for contension on the write/erase
 		 * operations which are global to the real chip and not per
@@ -798,6 +798,9 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
 		if (mode == FL_READY && chip->oldstate == FL_READY)
 			return 0;
 
+	case FL_SHUTDOWN:
+		/* The machine is rebooting now,so no one can get chip anymore */
+		return -EIO;
 	default:
 	sleep:
 		set_current_state(TASK_UNINTERRUPTIBLE);
@@ -2409,10 +2412,10 @@ static int cfi_intelext_reset(struct mtd_info *mtd)
 		   and switch to array mode so any bootloader in
 		   flash is accessible for soft reboot. */
 		spin_lock(chip->mutex);
-		ret = get_chip(map, chip, chip->start, FL_SYNCING);
+		ret = get_chip(map, chip, chip->start, FL_SHUTDOWN);
 		if (!ret) {
 			map_write(map, CMD(0xff), chip->start);
-			chip->state = FL_READY;
+			chip->state = FL_SHUTDOWN;
 		}
 		spin_unlock(chip->mutex);
 	}
diff --git a/include/linux/mtd/flashchip.h b/include/linux/mtd/flashchip.h
index a293a3b78e05..39e7d2a1be9a 100644
--- a/include/linux/mtd/flashchip.h
+++ b/include/linux/mtd/flashchip.h
@@ -40,6 +40,7 @@ typedef enum {
 	FL_POINT,
 	FL_XIP_WHILE_ERASING,
 	FL_XIP_WHILE_WRITING,
+	FL_SHUTDOWN,
 	FL_UNKNOWN
 } flstate_t;