mtd/drivers/mtd/chips cfi_cmdset_0001.c,1.165,1.166

Nicolas Pitre nico at infradead.org
Fri Feb 4 21:35:29 EST 2005


Update of /home/cvs/mtd/drivers/mtd/chips
In directory phoenix.infradead.org:/tmp/cvs-serv17087/drivers/mtd/chips

Modified Files:
	cfi_cmdset_0001.c 
Log Message:
Another fix to the put_chip() concurrency logic.

Problem was occurring when:

1) one thread was erasing a block in partition x;
2) another thread suspended the erase in order to write to
   partition y;
3) a third thread came along to read a different block from
   partition x and, when it called put_chip(), chip->oldstate was
   FL_ERASING and the erase (mistakenly) resumed;
4) the write in partition y obviously failed.

Incidentally, the fix for this problem also fixed the case where
suspending writes for MTD XIP usage was not working properly.


Index: cfi_cmdset_0001.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/chips/cfi_cmdset_0001.c,v
retrieving revision 1.165
retrieving revision 1.166
diff -u -r1.165 -r1.166
--- cfi_cmdset_0001.c	5 Feb 2005 02:06:15 -0000	1.165
+++ cfi_cmdset_0001.c	5 Feb 2005 02:35:26 -0000	1.166
@@ -36,10 +36,7 @@
 #include <linux/mtd/cfi.h>
 
 /* #define CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE */
-
-#ifdef CONFIG_MTD_XIP
-#define CMDSET0001_DISABLE_WRITE_SUSPEND
-#endif
+/* #define CMDSET0001_DISABLE_WRITE_SUSPEND */
 
 // debugging, turns off buffer write mode if set to 1
 #define FORCE_WORD_WRITE 0
@@ -152,7 +149,6 @@
 #endif
 
 #ifdef CMDSET0001_DISABLE_WRITE_SUSPEND
-/* The XIP config appears to have problems using write suspend at the moment */ 
 static void fixup_no_write_suspend(struct mtd_info *mtd, void* param)
 {
 	struct map_info *map = mtd->priv;
@@ -735,7 +731,7 @@
 	if (chip->priv) {
 		struct flchip_shared *shared = chip->priv;
 		spin_lock(&shared->lock);
-		if (shared->writing == chip) {
+		if (shared->writing == chip && chip->oldstate == FL_READY) {
 			/* We own the ability to write, but we're done */
 			shared->writing = shared->erasing;
 			if (shared->writing && shared->writing != chip) {
@@ -747,17 +743,24 @@
 				put_chip(map, loaner, loaner->start);
 				spin_lock(chip->mutex);
 				spin_unlock(loaner->mutex);
-			} else {
-				if (chip->oldstate != FL_ERASING) {
-					shared->erasing = NULL;
-					if (chip->oldstate != FL_WRITING)
-						shared->writing = NULL;
-				}
-				spin_unlock(&shared->lock);
+				wake_up(&chip->wq);
+				return;
 			}
-		} else {
+			shared->erasing = NULL;
+			shared->writing = NULL;
+		} else if (shared->erasing == chip && shared->writing != chip) {
+			/*
+			 * We own the ability to erase without the ability
+			 * to write, which means the erase was suspended
+			 * and some other partition is currently writing.
+			 * Don't let the switch below mess things up since
+			 * we don't have ownership to resume anything.
+			 */
 			spin_unlock(&shared->lock);
+			wake_up(&chip->wq);
+			return;
 		}
+		spin_unlock(&shared->lock);
 	}
 
 	switch(chip->oldstate) {





More information about the linux-mtd-cvs mailing list