mtd/drivers/mtd/chips cfi_cmdset_0002.c,1.67,1.68
Thayne Harbaugh
tharbaugh at lnxi.com
Mon Apr 21 19:26:28 EDT 2003
- Previous message: mtd/drivers/mtd/maps h720x-flash.c,NONE,1.1 Config.in,1.46,1.47
Kconfig,1.5,1.6 Makefile,1.39,1.40
- Next message: mtd/drivers/mtd/devices lart.c,1.2,1.3
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /home/cvs/mtd/drivers/mtd/chips
In directory phoenix.infradead.org:/tmp/cvs-serv17616
Modified Files:
cfi_cmdset_0002.c
Log Message:
Remove dq5 check from erase/write status polling.
dq5 is now only used to decode failures - using dq5 to
check status _greatly_ complicates the logic and only
optimizes the error case (which should be infrequent at
best).
Added benefit - chips that do not use dq5 now work - they
might have strange error reports when they timeout.
Future fixes should select cmdset_0002 capabilities for
chips that support dq7, dq6, dq5, dq2, erase suspend/resume,
etc.
Index: cfi_cmdset_0002.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/chips/cfi_cmdset_0002.c,v
retrieving revision 1.67
retrieving revision 1.68
diff -u -r1.67 -r1.68
--- cfi_cmdset_0002.c 15 Apr 2003 22:32:13 -0000 1.67
+++ cfi_cmdset_0002.c 21 Apr 2003 23:26:25 -0000 1.68
@@ -472,6 +472,7 @@
static unsigned long uWriteTimeout = ( HZ / 1000 ) + 1;
DECLARE_WAITQUEUE(wait, current);
int ret = 0;
+ int ta = 0;
retry:
cfi_spin_lock(chip->mutex);
@@ -554,30 +555,23 @@
__func__, oldstatus, status );
/*
- * This assumes that dq5 == dq6 >> 1
- * It's done this way so that we only look for asserted dq5
- * on interleaved chips that are still toggling - we can
- * ignore chips that have already completed and might have
- * dq5 asserted. It is important to use oldstatus because
- * a completed state might look like it has toggled from
- * the previous read of status bits and it might trigger
- * an erroneous error.
+ * This only checks if dq6 is still toggling and that our
+ * timer hasn't expired. We purposefully ignore the chips
+ * internal timer that will assert dq5 and leave dq6 toggling.
+ * This is done for a variety of reasons:
+ * 1) Not all chips support dq5.
+ * 2) Dealing with asynchronous status bit and data updates
+ * and reading a device two more times creates _messy_
+ * logic when trying to deal with interleaved devices -
+ * some may be changing while others are still busy.
+ * 3) Checking dq5 only helps to optimize an error case that
+ * should at worst be infrequent and at best non-existent.
*
- * FIXME - this is rather complicated - trying to deal with
- * asynchronous transitions and cases where the toggle bit
- * appears to toggle when it has really just settled to true
- * data and having to read the locations an additional two
- * times to verify bits. It might be that we just need
- * to watch dq6 and our timeout and ignore dq5. If the
- * timeout is exceeded and we still have dq6 toggling we then
- * look for asserted dq5 for each toggling dq6. That would
- * be safer, easier to code and get correct, and marginally
- * less efficient. Who cares if the error case, which should
- * be very infrequent, is optimized.
+ * If our timeout occurs _then_ we will check dq5 to see
+ * if the device also had an internal timeout.
*/
while( ( ( status ^ oldstatus ) & dq6 )
- && ! ( oldstatus & ( ( status ^ oldstatus ) & dq6 ) >> 1 )
- && ! time_after(jiffies, timeo) ) {
+ && ! ( ta = time_after(jiffies, timeo) ) ) {
if (need_resched()) {
cfi_spin_unlock(chip->mutex);
@@ -592,35 +586,19 @@
__func__, oldstatus, status );
}
- if ( ( ( status ^ oldstatus ) & dq6 )
- && ! ( oldstatus & ( ( status ^ oldstatus ) & dq6 ) >> 1 ) ) {
- /* 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__ );
- 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.
+ * Something kicked us out of the read-back loop. We'll
+ * check success befor checking failure.
+ * Even though dq6 might be true data, it is unkown if
+ * all of the other bits have changed to true data due to
+ * the asynchronous nature of the internal state machine.
* 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 aren't still changing and that the status
* bits erroneously match the datum that was written.
*/
-
- /*
- * Be optimistic and check success first - then decode any
- * failures.
- */
prev_oldstatus = oldstatus;
prev_status = status;
oldstatus = cfi_read(map, adr);
@@ -633,24 +611,31 @@
goto write_done;
}
- /* something has failed */
- if ( ( ( status ^ oldstatus ) & dq6 )
- && ( status & ( ( status ^ oldstatus ) & dq6 >> 1 ) ) ) {
- printk(KERN_WARNING
- "MTD %s(): Internal flash device timeout occured.\n",
- __func__ );
- } else {
- /*
- * 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__ );
+ if ( ta ) {
+ int dq5mask = ( ( status ^ oldstatus ) & dq6 ) >> 1;
+ if ( status & dq5mask ) {
+ /* dq5 asserted - decode interleave chips */
+ printk( KERN_WARNING
+ "MTD %s(): FLASH internal timeout: 0x%.8x\n",
+ __func__,
+ status & dq5mask );
+ } else {
+ printk( KERN_WARNING
+ "MTD %s(): Software timed out during write.\n",
+ __func__ );
+ }
+ goto write_failed;
}
+ /*
+ * If we get to here then it means that something
+ * is wrong and it's not a timeout. 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%.8lx(0x%.8x): 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n",
__func__, adr, datum,
@@ -825,6 +810,7 @@
struct cfi_private *cfi = map->fldrv_priv;
DECLARE_WAITQUEUE(wait, current);
int ret = 0;
+ int ta = 0;
__u32 ones = 0;
retry:
@@ -882,8 +868,7 @@
__func__, oldstatus, status );
while( ( ( status ^ oldstatus ) & dq6 )
- && ! ( oldstatus & ( ( status ^ oldstatus ) & dq6 >> 1 ) )
- && ! time_after(jiffies, timeo) ) {
+ && ! ( ta = time_after(jiffies, timeo) ) ) {
int wait_reps;
/* an initial short sleep */
@@ -913,8 +898,7 @@
/* Busy wait for 1/10 of a milisecond */
for(wait_reps = 0;
(wait_reps < 100)
- && ( ( status ^ oldstatus ) & dq6 )
- && ! ( oldstatus & ( ( status ^ oldstatus ) & dq6 >> 1 ) );
+ && ( ( status ^ oldstatus ) & dq6 );
wait_reps++) {
/* Latency issues. Drop the lock, wait a while and retry */
@@ -934,62 +918,41 @@
__func__, oldstatus, status );
}
- if ( ( ( status ^ oldstatus ) & dq6 )
- && ! ( oldstatus & ( ( status ^ oldstatus ) & dq6 >> 1 ) ) ) {
- /* dq6 still toggling and dq5 still low - must be timeout */
- printk( KERN_WARNING
- "MTD %s(): Timed out while waiting for erase to complete.\n",
- __func__ );
- goto erase_failed;
- }
-
- /*
- * Be optimistic and check success first - then decode any
- * failures.
- */
prev_oldstatus = oldstatus;
prev_status = status;
oldstatus = cfi_read(map, adr);
status = cfi_read(map, adr);
DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n",
__func__, oldstatus, status );
-
- switch( CFIDEV_BUSWIDTH ) {
- case 1:
- ones = (__u8)~0;
- break;
- case 2:
- ones = (__u16)~0;
- break;
- case 4:
- ones = (__u32)~0;
- break;
- }
+
+ ones = CMD( (__u8)~0 );
if ( oldstatus == ones && status == ones ) {
/* success - do nothing */
goto erase_done;
}
- /* something has failed */
- if ( ( ( status ^ oldstatus ) & dq6 )
- && ( oldstatus & ( ( status ^ oldstatus ) & dq6 >> 1 ) ) ) {
- printk(KERN_WARNING
- "MTD %s(): Internal flash device timeout occured.\n",
- __func__ );
- } else {
- /*
- * This state means that the erase 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__ );
+ if ( ta ) {
+ int dq5mask = ( ( status ^ oldstatus ) & dq6 ) >> 1;
+ if ( status & dq5mask ) {
+ /* dq5 asserted - decode interleave chips */
+ printk( KERN_WARNING
+ "MTD %s(): FLASH internal timeout: 0x%.8x\n",
+ __func__,
+ status & dq5mask );
+ } else {
+ printk( KERN_WARNING
+ "MTD %s(): Software timed out during write.\n",
+ __func__ );
+ }
+ goto erase_failed;
}
printk(KERN_WARNING
+ "MTD %s(): Wacky! Unable to decode failure status\n",
+ __func__ );
+
+ printk(KERN_WARNING
"MTD %s(): 0x%.8lx(0x%.8x): 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n",
__func__, adr, ones,
prev_oldstatus, prev_status,
@@ -1017,6 +980,7 @@
struct cfi_private *cfi = map->fldrv_priv;
DECLARE_WAITQUEUE(wait, current);
int ret = 0;
+ int ta = 0;
__u32 ones = 0;
retry:
@@ -1074,8 +1038,7 @@
__func__, oldstatus, status );
while( ( ( status ^ oldstatus ) & dq6 )
- && ! ( oldstatus & ( ( status ^ oldstatus ) & dq6 >> 1 ) )
- && ! time_after(jiffies, timeo) ) {
+ && ! ( ta = time_after(jiffies, timeo) ) ) {
int wait_reps;
/* an initial short sleep */
@@ -1105,8 +1068,7 @@
/* Busy wait for 1/10 of a milisecond */
for(wait_reps = 0;
(wait_reps < 100)
- && ( ( status ^ oldstatus ) & dq6 )
- && ! ( oldstatus & ( ( status ^ oldstatus ) & dq6 >> 1 ) );
+ && ( ( status ^ oldstatus ) & dq6 );
wait_reps++) {
/* Latency issues. Drop the lock, wait a while and retry */
@@ -1126,19 +1088,6 @@
__func__, oldstatus, status );
}
- if ( ( ( status ^ oldstatus ) & dq6 )
- && ! ( oldstatus & ( ( status ^ oldstatus ) & dq6 >> 1 ) ) ) {
- /* dq6 still toggling and dq5 still low - must be timeout */
- printk( KERN_WARNING
- "MTD %s(): Timed out while waiting for erase to complete.\n",
- __func__ );
- goto erase_failed;
- }
-
- /*
- * Be optimistic and check success first - then decode any
- * failures.
- */
prev_oldstatus = oldstatus;
prev_status = status;
oldstatus = cfi_read(map, adr);
@@ -1146,40 +1095,32 @@
DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n",
__func__, oldstatus, status );
- switch( CFIDEV_BUSWIDTH ) {
- case 1:
- ones = (__u8)~0;
- break;
- case 2:
- ones = (__u16)~0;
- break;
- case 4:
- ones = (__u32)~0;
- break;
- }
-
+ ones = CMD( (__u8)~0 );
+
if ( oldstatus == ones && status == ones ) {
/* success - do nothing */
goto erase_done;
}
- /* something has failed */
- if ( ( ( status ^ oldstatus ) & dq6 )
- && ( oldstatus & ( ( status ^ oldstatus ) & dq6 >> 1 ) ) ) {
- printk(KERN_WARNING
- "MTD %s(): Internal flash device timeout occured.\n",
- __func__ );
- } else {
- /*
- * This state means that the erase 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__ );
+ if ( ta ) {
+ int dq5mask = ( ( status ^ oldstatus ) & dq6 ) >> 1;
+ if ( status & dq5mask ) {
+ /* dq5 asserted - decode interleave chips */
+ printk( KERN_WARNING
+ "MTD %s(): FLASH internal timeout: 0x%.8x\n",
+ __func__,
+ status & dq5mask );
+ } else {
+ printk( KERN_WARNING
+ "MTD %s(): Software timed out during write.\n",
+ __func__ );
+ }
+ goto erase_failed;
}
+
+ printk(KERN_WARNING
+ "MTD %s(): Wacky! Unable to decode failure status\n",
+ __func__ );
printk(KERN_WARNING
"MTD %s(): 0x%.8lx(0x%.8x): 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n",
- Previous message: mtd/drivers/mtd/maps h720x-flash.c,NONE,1.1 Config.in,1.46,1.47
Kconfig,1.5,1.6 Makefile,1.39,1.40
- Next message: mtd/drivers/mtd/devices lart.c,1.2,1.3
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the linux-mtd-cvs
mailing list