Fix for CFI Flash Driver bug in 2.4 Kernel
Matsen, Dean (WA26)
Dean.Matsen at Honeywell.com
Fri Feb 24 08:33:37 EST 2006
All,
This patch applies to 2.4.22 from Monta Vista. We started seeing a
kernel panic due to the really SLOOOOW 29LV641MH-120 flash parts.
Interestingly, the same part with 90mS access time (29LV641MH-120) are
about 10 times faster erasing and programming.
Turns out there are two problems in the driver code:
1- the timeout is calculated incorrectly, based on HZ/100, which is zero
on my system 'cuz "HZ" is equal to 100
2- when the timeout occurs, the code erroneously releases a spinlock
twice.
I have not checked to see if there is a similar problem in the 2.6
kernel
Regards,
Dean Matsen
Software Architect
Alerton Honeywell
dean.matsen at honeywell.com
Patch follows:
------------------------------------------------------------------------
----------------------
diff --unified --recursive
ppc-linux-kernel.org/drivers/mtd/chips/cfi_cmdset_0002.c
ppc-linux-kernel/drivers/mtd/chips/cfi_cmdset_0002.c
--- ppc-linux-kernel.org/drivers/mtd/chips/cfi_cmdset_0002.c Sat
Jul 12 01:08:17 2003
+++ ppc-linux-kernel/drivers/mtd/chips/cfi_cmdset_0002.c Thu Feb 23
12:50:34 2006
@@ -10,6 +10,15 @@
*
* $Id: cfi_cmdset_0002.c,v 1.1.1.1 2003/07/12 08:08:17 dean Exp $
*
+ * - 2006/02/23 : Dean Matsen (dean.matsen at honeywell.com) Fixed write
+ * timeout bug: timeout was based on HZ/1000 before (which is equal
to
+ * zero in my system), also the exit path unlocked the spinlock
twice.
+ * Increased timeout from 1mS to 100mS, because new 100K write
flashes
+ * such as 29LV641MH say "TBD" in the data sheet for worst case
programming
+ * time. Problem was detected due to the really slow 29LV641MH-120
part,
+ * which erases and programs 10 times slower than any other flash
we've
+ * ever encountered (including the 29LV641MH-90, which is in the same
+ * 100K write family of parts!).
*/
#include <linux/module.h>
@@ -511,7 +520,7 @@
or tells us why it failed. */
dq6 = CMD(1<<6);
dq5 = CMD(1<<5);
- timeo = jiffies + (HZ/1000); /* setting timeout to 1ms for now */
+ timeo = jiffies + (HZ/10); /* setting timeout to 100ms for now */
oldstatus = cfi_read(map, adr);
status = cfi_read(map, adr);
@@ -532,10 +541,10 @@
}
if( (status & dq6) != (oldstatus & dq6) ) {
- /* The erasing didn't stop?? */
+ /* The writing didn't stop?? */
if( (status & dq5) == dq5 ) {
/* When DQ5 raises, we must check once again
- if DQ6 is toggling. If not, the erase has been
+ if DQ6 is toggling. If not, the write has been
completed OK. If not, reset chip. */
oldstatus = cfi_read(map, adr);
status = cfi_read(map, adr);
@@ -543,7 +552,7 @@
if ( (oldstatus & 0x00FF) == (status & 0x00FF) ) {
printk(KERN_WARNING "Warning: DQ5 raised while
program operation was in progress, however operation completed OK\n" );
} else {
- /* DQ5 is active so we can do a reset and stop
the erase */
+ /* DQ5 is active so we can do a reset and stop
the write */
cfi_write(map, CMD(0xF0), chip->start);
printk(KERN_WARNING "Internal flash device
timeout occurred or write operation was performed while flash was
programming.\n" );
}
@@ -554,7 +563,7 @@
wake_up(&chip->wq);
cfi_spin_unlock(chip->mutex);
DISABLE_VPP(map);
- ret = -EIO;
+ return -EIO;
}
}
------------------------------------------------------------------------
-----------------------------------
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ozlabs.org/pipermail/linuxppc-dev/attachments/20060223/4c35a0cc/attachment.htm>
More information about the Linuxppc-dev
mailing list