aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi/build.c
diff options
context:
space:
mode:
authorKevin Cernekee <kpc.mtd@gmail.com>2009-06-09 13:59:19 -0400
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2009-06-10 09:50:50 -0400
commitd9dd0887cc5c6df0dbbe5a307284610607eea7ab (patch)
tree1b6dc1bf5e90c6cd49896196abda9369a50ab3b2 /drivers/mtd/ubi/build.c
parent6b5c94c6b4e1630a8e1ee7d30383d9396603749f (diff)
UBI: add reboot notifier
Terminate the UBI background thread prior to restarting the system. [Artem: amended comments a little] Signed-off-by: Kevin Cernekee <kpc.mtd@gmail.com> Tested-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'drivers/mtd/ubi/build.c')
-rw-r--r--drivers/mtd/ubi/build.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 964a99d48bc4..286ed594e5a0 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -41,6 +41,7 @@
41#include <linux/miscdevice.h> 41#include <linux/miscdevice.h>
42#include <linux/log2.h> 42#include <linux/log2.h>
43#include <linux/kthread.h> 43#include <linux/kthread.h>
44#include <linux/reboot.h>
44#include "ubi.h" 45#include "ubi.h"
45 46
46/* Maximum length of the 'mtd=' parameter */ 47/* Maximum length of the 'mtd=' parameter */
@@ -823,6 +824,34 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
823} 824}
824 825
825/** 826/**
827 * ubi_reboot_notifier - halt UBI transactions immediately prior to a reboot.
828 * @n: reboot notifier object
829 * @state: SYS_RESTART, SYS_HALT, or SYS_POWER_OFF
830 * @cmd: pointer to command string for RESTART2
831 *
832 * This function stops the UBI background thread so that the flash device
833 * remains quiescent when Linux restarts the system. Any queued work will be
834 * discarded, but this function will block until do_work() finishes if an
835 * operation is already in progress.
836 *
837 * This function solves a real-life problem observed on NOR flashes when an
838 * PEB erase operation starts, then the system is rebooted before the erase is
839 * finishes, and the boot loader gets confused and dies. So we prefer to finish
840 * the ongoing operation before rebooting.
841 */
842static int ubi_reboot_notifier(struct notifier_block *n, unsigned long state,
843 void *cmd)
844{
845 struct ubi_device *ubi;
846
847 ubi = container_of(n, struct ubi_device, reboot_notifier);
848 if (ubi->bgt_thread)
849 kthread_stop(ubi->bgt_thread);
850 ubi_sync(ubi->ubi_num);
851 return NOTIFY_DONE;
852}
853
854/**
826 * ubi_attach_mtd_dev - attach an MTD device. 855 * ubi_attach_mtd_dev - attach an MTD device.
827 * @mtd: MTD device description object 856 * @mtd: MTD device description object
828 * @ubi_num: number to assign to the new UBI device 857 * @ubi_num: number to assign to the new UBI device
@@ -978,6 +1007,11 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
978 wake_up_process(ubi->bgt_thread); 1007 wake_up_process(ubi->bgt_thread);
979 spin_unlock(&ubi->wl_lock); 1008 spin_unlock(&ubi->wl_lock);
980 1009
1010 /* Flash device priority is 0 - UBI needs to shut down first */
1011 ubi->reboot_notifier.priority = 1;
1012 ubi->reboot_notifier.notifier_call = ubi_reboot_notifier;
1013 register_reboot_notifier(&ubi->reboot_notifier);
1014
981 ubi_devices[ubi_num] = ubi; 1015 ubi_devices[ubi_num] = ubi;
982 ubi_notify_all(ubi, UBI_VOLUME_ADDED, NULL); 1016 ubi_notify_all(ubi, UBI_VOLUME_ADDED, NULL);
983 return ubi_num; 1017 return ubi_num;
@@ -1049,6 +1083,7 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
1049 * Before freeing anything, we have to stop the background thread to 1083 * Before freeing anything, we have to stop the background thread to
1050 * prevent it from doing anything on this device while we are freeing. 1084 * prevent it from doing anything on this device while we are freeing.
1051 */ 1085 */
1086 unregister_reboot_notifier(&ubi->reboot_notifier);
1052 if (ubi->bgt_thread) 1087 if (ubi->bgt_thread)
1053 kthread_stop(ubi->bgt_thread); 1088 kthread_stop(ubi->bgt_thread);
1054 1089