mtd/drivers/mtd/chips cfi_cmdset_0002.c,1.93,1.94

dvrabel at infradead.org dvrabel at infradead.org
Tue Jan 27 05:16:22 EST 2004


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

Modified Files:
	cfi_cmdset_0002.c 
Log Message:
Fixes erase-suspend on AMD command set chips:
  - Erase suspend resume command must be written to the block to be resumed.
  - When erasing DQ2 must a) be read from the erase in progress block
    b) doesn't indicate that an erase has been suspended.  DQ6 is the toggle
    bit to check.
  - Currently erase-suspend-program does work.  It sometimes fails to erase
    the block completely.  So erase-suspend-program has been disabled for now.
    Note that this severly reduces write performance when used with (for
    example) JFFS2 but at least it works.


Index: cfi_cmdset_0002.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/chips/cfi_cmdset_0002.c,v
retrieving revision 1.93
retrieving revision 1.94
diff -u -r1.93 -r1.94
--- cfi_cmdset_0002.c	20 Nov 2003 08:39:35 -0000	1.93
+++ cfi_cmdset_0002.c	27 Jan 2004 10:16:20 -0000	1.94
@@ -375,6 +375,9 @@
 		printk(KERN_NOTICE "cfi_cmdset_0002: Disabling fast programming due to code brokenness.\n");
 		cfi->fast_prog = 0;
 	}
+        /* FIXME: erase-suspend-program is broken.  See
+           http://lists.infradead.org/pipermail/linux-mtd/2003-December/009001.html */
+        printk(KERN_NOTICE "cfi_cmdset_0002: Disabling erase-suspend-program due to code brokenness.\n");
 
 
         /* does this chip have a secsi area? */
@@ -499,27 +502,37 @@
 		return 0;
 
 	case FL_ERASING:
+                if (mode == FL_WRITING) /* FIXME: Erase-suspend-program appears broken. */
+                        goto sleep;
+
 		if (!(mode == FL_READY || mode == FL_POINT
 		      || (mode == FL_WRITING && (cfip->EraseSuspend & 0x2))
 		      || (mode == FL_WRITING && (cfip->EraseSuspend & 0x1))))
 			goto sleep;
 
+                oldstatus = cfi_read(map, adr);
+                status = cfi_read(map, adr);
+                if ((oldstatus ^ status) & dq2) {
+                        printk(KERN_ERR "Can't suspend erase -- block in progress\n");
+                        goto sleep;
+                }
+
 		/* Erase suspend */
 		/* FIXME - is there a way to verify suspend? */
-		cfi_write(map, CMD(0xB0), adr);
+		cfi_write(map, CMD(0xB0), chip->in_progress_block_addr);
 		chip->oldstate = FL_ERASING;
 		chip->state = FL_ERASE_SUSPENDING;
 		chip->erase_suspended = 1;
 		for (;;) {
-			oldstatus = cfi_read(map, adr);
-			status = cfi_read(map, adr);
-			if (((oldstatus ^ status) & dq2) == dq2)
+			oldstatus = cfi_read(map, chip->in_progress_block_addr);
+			status = cfi_read(map, chip->in_progress_block_addr);
+			if (((oldstatus ^ status) & dq6) == 0)
 			        break;
 
 			if (time_after(jiffies, timeo)) {
 				/* Urgh. Resume and pretend we weren't here. */
 				/* FIXME - is there a way to verify resume? */
-				cfi_write(map, CMD(0x30), adr);
+				cfi_write(map, CMD(0x30), chip->in_progress_block_addr);
 				chip->state = FL_ERASING;
 				chip->oldstate = FL_READY;
 				printk(KERN_ERR "Chip not ready after erase "
@@ -533,7 +546,7 @@
 			/* Nobody will touch it while it's in state FL_ERASE_SUSPENDING.
 			   So we can just loop here. */
 		}
-		chip->state = FL_STATUS;
+		chip->state = FL_READY;
 		return 0;
 
 	case FL_POINT:
@@ -561,7 +574,7 @@
 	switch(chip->oldstate) {
 	case FL_ERASING:
 		chip->state = chip->oldstate;
-		cfi_write(map, CMD(0x30), adr);
+		cfi_write(map, CMD(0x30), chip->in_progress_block_addr);
 		chip->oldstate = FL_READY;
 		chip->state = FL_ERASING;
 		break;
@@ -1506,7 +1519,8 @@
 
 	chip->state = FL_ERASING;
 	chip->erase_suspended = 0;
-	
+	chip->in_progress_block_addr = adr;
+
 	cfi_spin_unlock(chip->mutex);
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout((chip->erase_time*HZ)/(2*1000));
@@ -1738,6 +1752,7 @@
 
 	chip->state = FL_ERASING;
 	chip->erase_suspended = 0;
+	chip->in_progress_block_addr = adr;
 	
 	cfi_spin_unlock(chip->mutex);
 	set_current_state(TASK_UNINTERRUPTIBLE);




More information about the linux-mtd-cvs mailing list