Disk blocks for long periods

Joakim Tjernlund joakim.tjernlund at lumentis.se
Tue Aug 6 06:06:34 EDT 2002


Hi Dave

This is interesting ...

> I've been working on what may be the same problem and I think I 
> finally understand it. I've seen it with 2.4.4, 2.4.18 and
> with 2.4.18 with the 2.4.19 jffs2 and mtd code. I am using an 
> AM29LV641, which uses cfi_cmdset_0002.c, but the code in 
> cfi_cmdset_0001.c is similar. I have a possible solution
> but I'd like some feedback on it.

Yes, cfi_cmdset_0001.c has the same problem and I think do_write_buffer() is
even more sensitive since is has an extra unlock,udelay,lock pair in it.

> 
> The problem occurs when do_erase_oneblock() tries to lock the 
> flash while cfi_amdstd_write() is writing a lot of data. The 
> erasing thread locks the chip mutex when do_write_oneword() does the
>     cfi_spin_unlock(chip->mutex);
>     cfi_udelay(chip->word_write_time);
>     cfi_spinlock(chip->mutex);
> sequence. It sees the state is FL_WRITING, so it puts itself 
> back on the wait queue. do_write_oneword() continues and eventually
> sets the state back to FL_READY and wakes up the queue, but the
> erasing thread doesn't actually run until the cfi_udelay() in 
> do_write_oneword() calls schedule() while writing the next word
> to the flash. The state is FL_WRITING, so the erasing thread goes
> back on the wait queue. This continues until the entire write is
> finished, then the erasing thread finally starts the erase.
> 
> The effect of all this sheduling is to write exactly one word
> to flash for each jiffie! My flash is 16 bits wide, so a single
> write of 2400 bytes was sometimes taking 1200 jiffies, or
> 12 seconds.
> 
> This patch to cfi_cmdset_0002.c 1.56 seems solve the problem, but
> I am not sure if this is right way to do it. Comments?

I am not sure this is the the rigth way either, but I will test and see what happens.

BTW, is it neccesary to use spin_lock_bh()? Can we not get away with just spin_lock()?
I am not very good at locking, but I think xxx_bh is only needed when interrupts can
can execute the locked code and currently there are no interrupts in this code path(I think).

Is it not true that xxx_bh() also disables interrupts? If so, there must be rather long
periods with interrupts turned off in cfi_cmdset_xxxx.c?

Have you tried to use cfi_udelay(chip->word_write_time) instead of udelay(chip->word_write_time)?
That will at least let other processes run, won't it? 

Perhaps David can comment?

> 
> Dave Ellis
> dge at sixnetio.com
> 
> BTW - If I make similar changes to 1.55 or before it solves this
> problem, but the write fails occasionally. I am guessing that
> with my change it gets to the write completion check faster and the
> old check fails, but the new write completion polling works better.
> 
> --- cfi_cmdset_0002.c	Mon Jul 15 11:13:25 2002
> +++ cfi_cmdset_0002.fixed.c	Mon Aug  5 14:28:40 2002
> @@ -386,9 +384,7 @@
>  
>  	cfi_write(map, datum, adr);
>  
> -	cfi_spin_unlock(chip->mutex);
> -	cfi_udelay(chip->word_write_time);
> -	cfi_spin_lock(chip->mutex);
> +	udelay(chip->word_write_time);
>  
>  
>  	/* Polling toggle bits instead of reading back many times
> @@ -447,6 +444,7 @@
>  	chip->state = FL_READY;
>  	wake_up(&chip->wq);
>  	cfi_spin_unlock(chip->mutex);
> +	cfi_udelay(1);	/* just a chance to schedule() */
>  	
>  	return ret;
>  }
> 
> 
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
> 





More information about the linux-mtd mailing list