From c4a9f88daf6c382fedde4cdddef0b30f1d0a20db Mon Sep 17 00:00:00 2001 From: Kevin Hao Date: Tue, 2 Oct 2007 13:56:04 -0700 Subject: [PATCH] [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 Signed-off-by: David Woodhouse --- drivers/mtd/chips/cfi_cmdset_0001.c | 9 ++++++--- include/linux/mtd/flashchip.h | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index c655e971c1..3aa3dca56a 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 a293a3b78e..39e7d2a1be 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; -- 2.39.2