mtd/drivers/mtd/chips cfi_cmdset_0002.c,1.65,1.66

Thayne Harbaugh tharbaugh at lnxi.com
Fri Apr 11 18:25:20 EDT 2003


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

Modified Files:
	cfi_cmdset_0002.c 
Log Message:
Print error information when status bits can't be decoded.
Cleanup ugly if/else nesting with easier to read goto.

Index: cfi_cmdset_0002.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/chips/cfi_cmdset_0002.c,v
retrieving revision 1.65
retrieving revision 1.66
diff -u -r1.65 -r1.66
--- cfi_cmdset_0002.c	28 Mar 2003 19:47:42 -0000	1.65
+++ cfi_cmdset_0002.c	11 Apr 2003 22:25:17 -0000	1.66
@@ -457,7 +457,7 @@
 static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, __u32 datum, int fast)
 {
 	unsigned long timeo = jiffies + HZ;
-	unsigned int oldstatus, status;
+	unsigned int oldstatus, status, prev_oldstatus, prev_status;
 	unsigned int dq6, dq5;	
 	struct cfi_private *cfi = map->fldrv_priv;
     /* We use a 1ms + 1 jiffies generic timeout for writes (most devices have
@@ -500,6 +500,7 @@
 
 	adr += chip->start;
 	ENABLE_VPP(map);
+
 	if (fast) { /* Unlock bypass */
 		cfi_send_gen_cmd(0xA0, 0, chip->start, map, cfi, cfi->device_type, NULL);
 	}
@@ -521,24 +522,24 @@
 	 * This ensures that write operation is really completed,
 	 * or tells us why it failed.
 	 *
-	 * The polling and decoding of error state appears that it could
+	 * It appears tha the polling and decoding of error state might
 	 * be simplified.  Don't do it unless you really know what you
 	 * are doing.  You must remember that JESD21-C 3.5.3 states that
 	 * the status must be read back an _additional_ two times before
 	 * a failure is determined.  This is because these devices have
 	 * internal state machines that are asynchronous to the external
-	 * LPC bus.  During an erase or write the read-back status of the
-	 * polling bits might be internaling transitioning when the external
+	 * data bus.  During an erase or write the read-back status of the
+	 * polling bits might be transitioning internaly when the external
 	 * read-back occurs.  This means that the bits aren't in the final
 	 * state and they might appear to report an error as they transition
 	 * and are in a weird state.  This will produce infrequent errors
-	 * that will usually disappear then next time an erase or write
+	 * that will usually disappear the next time an erase or write
 	 * happens (Try tracking those errors down!).  To ensure that
 	 * the bits are not in transition the location must be read-back
 	 * two more times and compared against what was written - BOTH reads
 	 * MUST match what was written - don't think this can be simplified
-	 * to only the last read matching.  If the comparison fails error
-	 * state can then be decoded with certainty.
+	 * to only the last read matching.  If the comparison fails, error
+	 * state can then be decoded.
 	 *
 	 * - Thayne Harbaugh
 	 */
@@ -572,55 +573,82 @@
 		/* dq6 still toggling and dq5 still low - must be timeout */
 		printk( KERN_WARNING
 			"MTD %s(): Timed out while waiting for write to complete.\n",
-			__func__ );        
-		/* reset */
-		cfi_write( map, CMD(0xF0), chip->start );
-		ret = -EIO;
-	} else {
-		/*
-		 * Either dq5 went high or dq6 finish toggling.  For
-		 * the correct completion of certain types of writes
-		 * dq5 might _appear_ to go high while dq6 might
-		 * _appear_ to still be toggling - it depends on the
-		 * last state of the toggle was in and what the final
-		 * state will be with true data.  We alread know that
-		 * something changed state with the last set of reads.
-		 * We will read two more times and use this to either
-		 * verify that the write completed successfully or
-		 * that something really went wrong.  BOTH reads
-		 * must match what was written - this certifies that
-		 * the dq6 is not still toggling and have the status
-		 * bits erroneously match the datum that was written.
-		 */
-		/*
-		 * Be optimistic and check success first - then decode any
-		 * failures.
-		 */
-		oldstatus = cfi_read(map, adr);
-		status = cfi_read(map, adr);
-
-		if ( oldstatus == datum && status == datum ) {
-			/* success - do nothing */
-		} else {
-			/* something has failed */
-			if ( ( ( status ^ oldstatus ) & dq6 )
-			     && ( status & dq5 ) ) {
-				printk(KERN_WARNING "MTD %s(): Internal flash device timeout occured.\n", __func__ );
-			} else {
-				/*
-				 * This state means that the write did not succeed
-				 * and that the usual error state of toggling dq6
-				 * while dq5 goes high did not happen.  Something
-				 * is seriously wacky!
-				 */
-				printk(KERN_WARNING "MTD %s(): Wacky!  Unable to decode failure status\n", __func__ );
-			}
-			ret = -EIO;
-			/* reset on all failures. */
-			cfi_write( map, CMD(0xF0), chip->start );
-		}
+			__func__ );
+		goto write_failed;
 	}
 
+	/*
+	 * Either dq5 went high or dq6 finish toggling.  For
+	 * the correct completion of certain types of writes
+	 * dq5 might _appear_ to go high while dq6 might
+	 * _appear_ to still be toggling - it depends on the
+	 * last toggle-state dq6 was in and what the final
+	 * state will be with true data.  We alread know that
+	 * something changed state with the last set of reads.
+	 * We will read two more times and use this to either
+	 * verify that the write completed successfully or
+	 * that something really went wrong.  BOTH reads
+	 * must match what was written - this certifies that
+	 * dq6 is not still toggling  and that the status
+	 * bits erroneously match the datum that was written.
+	 */
+	prev_oldstatus = oldstatus;
+	prev_status = status;
+
+	/*
+	 * Be optimistic and check success first - then decode any
+	 * failures.
+	 */
+	oldstatus = cfi_read(map, adr);
+	status = cfi_read(map, adr);
+
+	if ( oldstatus == datum && status == datum ) {
+		/* success - do nothing */
+		goto write_done;
+	}
+
+	/* something has failed */
+	if ( ( ( status ^ oldstatus ) & dq6 )
+	     && ( status & dq5 ) ) {
+		printk(KERN_WARNING
+		       "MTD %s(): Internal flash device timeout occured.\n",
+		       __func__ );
+		goto write_failed;
+	}
+
+	/*
+	 * If we get to here then it means that something failed
+	 * and that the usual error state of toggling dq6
+	 * while dq5 goes high did not happen.  Something
+	 * is seriously wacky!  Dump some debug info.
+	 */
+	printk(KERN_WARNING "MTD %s(): Wacky!  Unable to decode failure status\n", __func__ );
+	printk(KERN_WARNING
+	       "MTD %s(): 0x%.2x: 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n",
+	       __func__, datum,
+	       prev_oldstatus, prev_status,
+	       oldstatus, status);
+
+	printk(KERN_WARNING "MTD %s(): dq6: %d %d %d %d\n",
+	       __func__,
+	       prev_oldstatus & dq6 ? 1 : 0,
+	       prev_status & dq6 ? 1 : 0,
+	       oldstatus & dq6 ? 1 : 0,
+	       status & dq6 ? 1 : 0);
+
+	printk(KERN_WARNING "MTD %s(): dq5: %d %d %d %d\n",
+	       __func__,
+	       prev_oldstatus & dq5 ? 1 : 0,
+	       prev_status & dq5 ? 1 : 0,
+	       oldstatus & dq5 ? 1 : 0,
+	       status & dq5 ? 1 : 0);
+
+ write_failed:
+	ret = -EIO;
+	/* reset on all failures. */
+	cfi_write( map, CMD(0xF0), chip->start );
+
+ write_done:
 	DISABLE_VPP(map);
 	chip->state = FL_READY;
 	wake_up(&chip->wq);




More information about the linux-mtd-cvs mailing list