diff -urN mtd.orig/drivers/mtd/mtdchar.c mtd/drivers/mtd/mtdchar.c
--- mtd.orig/drivers/mtd/mtdchar.c	Tue Jul 16 20:28:45 2002
+++ mtd/drivers/mtd/mtdchar.c	Tue Aug 20 15:29:49 2002
@@ -442,6 +442,15 @@
 		break;
 	}
 
+	case MEMREVALIDATE:
+	{
+		if (revalidate_mtd_device(mtd))
+			return -EINVAL;
+
+		ret = 0;
+		break;
+	}
+
 		
 	default:
 		DEBUG(MTD_DEBUG_LEVEL0, "Invalid ioctl %x (MEMGETINFO = %x)\n", cmd, MEMGETINFO);
diff -urN mtd.orig/drivers/mtd/mtdcore.c mtd/drivers/mtd/mtdcore.c
--- mtd.orig/drivers/mtd/mtdcore.c	Thu Mar  7 21:38:10 2002
+++ mtd/drivers/mtd/mtdcore.c	Tue Aug 20 13:41:29 2002
@@ -105,6 +105,41 @@
 }
 
 /**
+ *	revalidate_mtd_device - revalidate an MTD device
+ *	@mtd: pointer to MTD device info structure
+ *
+ *	Notify each currently active MTD 'user' of device is changed. Returns
+ *	zero on success or 1 on failure, which currently will only happen
+ *	if the requested device does not appear to be present in the list. 
+ */
+
+int revalidate_mtd_device (struct mtd_info *mtd)
+{
+	struct mtd_notifier *not=mtd_notifiers;
+	int i;
+	
+	down(&mtd_table_mutex);
+
+	for (i=0; i < MAX_MTD_DEVICES; i++)
+	{
+		if (mtd_table[i] == mtd)
+		{
+			while (not)
+			{
+				if (not->revalidate)
+					(*(not->revalidate))(mtd);
+				not = not->next;
+			}
+			up (&mtd_table_mutex);
+			return 0;
+		}
+	}
+
+	up(&mtd_table_mutex);
+	return 1;
+}
+
+/**
  *	register_mtd_user - register a 'user' of MTD devices.
  *	@new: pointer to notifier info structure
  *
diff -urN mtd.orig/drivers/mtd/nftlcore.c mtd/drivers/mtd/nftlcore.c
--- mtd.orig/drivers/mtd/nftlcore.c	Wed Mar  6 17:38:17 2002
+++ mtd/drivers/mtd/nftlcore.c	Tue Aug 20 15:32:19 2002
@@ -87,33 +87,33 @@
 
 struct NFTLrecord *NFTLs[MAX_NFTLS];
 
-static void NFTL_setup(struct mtd_info *mtd)
+static void NFTL_setup(struct mtd_info *mtd, int firstfree, struct NFTLrecord *nftl)
 {
 	int i;
-	struct NFTLrecord *nftl;
 	unsigned long temp;
-	int firstfree = -1;
 
 	DEBUG(MTD_DEBUG_LEVEL1,"NFTL_setup\n");
 
-	for (i = 0; i < MAX_NFTLS; i++) {
-		if (!NFTLs[i] && firstfree == -1)
-			firstfree = i;
-		else if (NFTLs[i] && NFTLs[i]->mtd == mtd) {
-			/* This is a Spare Media Header for an NFTL we've already found */
-			DEBUG(MTD_DEBUG_LEVEL1, "MTD already mounted as NFTL\n");
+	if (nftl == NULL) {
+		for (i = 0; i < MAX_NFTLS; i++) {
+			if (!NFTLs[i] && firstfree == -1)
+				firstfree = i;
+			else if (NFTLs[i] && NFTLs[i]->mtd == mtd) {
+				/* This is a Spare Media Header for an NFTL we've already found */
+				DEBUG(MTD_DEBUG_LEVEL1, "MTD already mounted as NFTL\n");
+				return;
+			}
+		}
+		if (firstfree == -1) {
+			printk(KERN_WARNING "No more NFTL slot available\n");
 			return;
 		}
-	}
-        if (firstfree == -1) {
-		printk(KERN_WARNING "No more NFTL slot available\n");
-		return;
-        }
 
-	nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL);
-	if (!nftl) {
-		printk(KERN_WARNING "Out of memory for NFTL data structures\n");
-		return;
+		nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL);
+		if (!nftl) {
+			printk(KERN_WARNING "Out of memory for NFTL data structures\n");
+			return;
+		}
 	}
 
 	init_MUTEX(&nftl->mutex);
@@ -175,7 +175,7 @@
 #endif
 }
 
-static void NFTL_unsetup(int i)
+static void NFTL_unsetup(int i, int keep)
 {
 	struct NFTLrecord *nftl = NFTLs[i];
 
@@ -189,7 +189,18 @@
 		kfree(nftl->EUNtable);
 		      
 	nftl_gendisk.nr_real--;
-	kfree(nftl);
+	if (!keep) kfree(nftl);
+}
+
+static void NFTL_resetup(int i)
+{
+	struct NFTLrecord *nftl = NFTLs[i];
+
+	DEBUG(MTD_DEBUG_LEVEL1, "NFTL_resetup %d\n", i);
+	
+	NFTL_unsetup(i, 1);
+
+	NFTL_setup(nftl->mtd, i, nftl);
 }
 
 /* Search the MTD device for NFTL partitions */
@@ -207,7 +218,7 @@
 		DEBUG(MTD_DEBUG_LEVEL3, "mtd->read = %p, size = %d, erasesize = %d\n", 
 		      mtd->read, mtd->size, mtd->erasesize);
 
-                NFTL_setup(mtd);
+                NFTL_setup(mtd, -1, NULL);
 	}
 }
 
@@ -217,7 +228,23 @@
 
 	for (i = 0; i < MAX_NFTLS; i++) {
 		if (NFTLs[i] && NFTLs[i]->mtd == mtd)
-			NFTL_unsetup(i);
+			NFTL_unsetup(i, 0);
+	}
+}
+
+static void NFTL_notify_revalidate(struct mtd_info *mtd)
+{
+	int i;
+
+	for (i = 0; i < MAX_NFTLS; i++) {
+		if (NFTLs[i] && NFTLs[i]->mtd == mtd) {
+			if (NFTLs[i]->usecount) {
+				printk(KERN_WARNING "Could not revalidate NFTL device\n");
+				continue;
+			}
+
+			NFTL_resetup(i);
+		}
 	}
 }
 
@@ -1048,8 +1075,9 @@
  ****************************************************************************/
 
 static struct mtd_notifier nftl_notifier = {
-	add:	NFTL_notify_add,
-	remove:	NFTL_notify_remove
+	add:		NFTL_notify_add,
+	remove:		NFTL_notify_remove,
+	revalidate: 	NFTL_notify_revalidate
 };
 
 extern char nftlmountrev[];
diff -urN mtd.orig/include/linux/mtd/mtd.h mtd/include/linux/mtd/mtd.h
--- mtd.orig/include/linux/mtd/mtd.h	Tue Nov 27 17:55:12 2001
+++ mtd/include/linux/mtd/mtd.h	Tue Aug 20 15:30:25 2002
@@ -93,6 +93,7 @@
 #define MEMUNLOCK               _IOW('M', 6, struct erase_info_user)
 #define MEMGETREGIONCOUNT	_IOR('M', 7, int)
 #define MEMGETREGIONINFO	_IOWR('M', 8, struct region_info_user)
+#define MEMREVALIDATE		_IO('M', 9)
 
 #ifndef __KERNEL__
 
@@ -219,6 +220,7 @@
 
 extern int add_mtd_device(struct mtd_info *mtd);
 extern int del_mtd_device (struct mtd_info *mtd);
+extern int revalidate_mtd_device(struct mtd_info *mtd);
 
 extern struct mtd_info *__get_mtd_device(struct mtd_info *mtd, int num);
 
@@ -244,6 +246,7 @@
 struct mtd_notifier {
 	void (*add)(struct mtd_info *mtd);
 	void (*remove)(struct mtd_info *mtd);
+	void (*revalidate)(struct mtd_info *mtd);
 	struct mtd_notifier *next;
 };
 
diff -urN mtd.orig/util/nftl_format.c mtd/util/nftl_format.c
--- mtd.orig/util/nftl_format.c	Wed May  1 14:59:04 2002
+++ mtd/util/nftl_format.c	Tue Aug 20 15:08:30 2002
@@ -333,5 +333,13 @@
 			printf("MEMWRITEOOB at %lx: %s\n", (unsigned long)oob.start, sys_errlist[errno]);
 	}
 
+	/* Phase 4. Revalidating the device */
+	printf("Phase 4. Revalidating the device\n");
+	if (ioctl(fd, MEMREVALIDATE, 0)) {
+		perror("ioctl(MEMREVALIDATE)");
+		close(fd);
+		return 1;
+	}
+
 	exit(0);
 }
