Fix for CFI Flash Driver bug in 2.4 Kernel. Relates to 2.6 kernel too.

Matsen, Dean (WA26) Dean.Matsen at Honeywell.com
Thu Mar 2 20:28:38 EST 2006


Paul Mackerras recommended I forward this here

Regards,
Dean

OK, since it affects drivers/mtd, it should go to David Woodhouse
(dwmw2 at infradead.org) and the linux-mtd at lists.infradead.org mailing
list.

Paul.

-----Original Message-----
From: Matsen, Dean (WA26) 
Sent: Monday, February 27, 2006 10:49 AM
To: 'Paul Mackerras'
Subject: FW: Fix for CFI Flash Driver bug in 2.4 Kernel

Someone seems to have found out it also exists in the 2.6 kernel.

The original patch is at the end of this e-mail

Regards,
Dean


-----Original Message-----
From: Kelsey Dawes [mailto:kelsey at codemonkey.net] 
Sent: Friday, February 24, 2006 10:14 AM
To: Matsen, Dean (WA26)
Subject: Re: Fix for CFI Flash Driver bug in 2.4 Kernel

Hi Dean,

just FYI - I have hit this bug with a  2.6.13 tree.  

29LV640MH flash.  

Kelsey


On Thu, Feb 23, 2006 at 02:33:37PM -0700, Matsen, Dean (WA26) wrote:
> 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;
> 
>             }
> 
>       }
> 
>
------------------------------------------------------------------------
> -----------------------------------
> 
>  
> 
>  
> 
>  
> 
>  
> 
>  
> 

> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev at ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev




More information about the linux-mtd mailing list