linux-mtd.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* Very slow nor flash write
@ 2007-11-22 11:29 tike64
  2007-11-22 14:24 ` Alexey Korolev
  2007-11-22 18:12 ` Anders Grafström
  0 siblings, 2 replies; 7+ messages in thread
From: tike64 @ 2007-11-22 11:29 UTC (permalink / raw)
  To: linux-mtd

Dear List,

I have an LH7A400 board and there intel 28F160B3T nor flash chip. I managed to configure Linux 2.6.18 to access the chip as an MTD device. However, the write access was very slow, about 40ms per word or 0.00005 MB/s ;-)

I traced the problem to inval_cache_and_wait_for_operation() in cfi_cmdset_0001.c. In the for-loop, if the write access haven't finished when checked for the first time, a long "msleep(sleep_time/1000);" is triggered. The sleep duration is very long because chip_op_time value is 50000. The value comes from "cfi->chips[i].word_write_time = 50000;" in cfi_cmdset_0001(). That is wrong, I think. I changed it to 200 and now the writing is as fast as expected.

Now, the question is: How this should be fixed *correctly*? The 200 is the maximum word program time for this particular chip. Maybe it should have different value for different chips.

--

Timo

--

Note: Not everyone will face this problem. If the CPU is slow enough, so that the chip have finished before the first status check, then the problem doesn't occur. Also, when I placed one printk at the start of the inval_cache_and_wait_for_operation() function, the problem went away.





      ____________________________________________________________________________________
Be a better sports nut!  Let your teams follow you 
with Yahoo Mobile. Try it now.  http://mobile.yahoo.com/sports;_ylt=At9_qDKvtAbMuh1G1SQtBI7ntAcJ

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Very slow nor flash write
  2007-11-22 11:29 Very slow nor flash write tike64
@ 2007-11-22 14:24 ` Alexey Korolev
  2007-11-22 14:59   ` Jamie Lokier
  2007-11-22 15:12   ` Nicolas Pitre
  2007-11-22 18:12 ` Anders Grafström
  1 sibling, 2 replies; 7+ messages in thread
From: Alexey Korolev @ 2007-11-22 14:24 UTC (permalink / raw)
  To: tike64; +Cc: linux-mtd, nico

Hi Timo

> I have an LH7A400 board and there intel 28F160B3T nor flash chip. I managed to configure Linux 2.6.18 to access the chip as an MTD device. However, the write access was very slow, about 40ms per word or 0.00005 MB/s ;-)
> 
> I traced the problem to inval_cache_and_wait_for_operation() in cfi_cmdset_0001.c. In the for-loop, if the write access haven't finished when checked for the first time, a long "msleep(sleep_time/1000);" is triggered. The sleep duration is very long because chip_op_time value is 50000. The value comes from "cfi->chips[i].word_write_time = 50000;" in cfi_cmdset_0001(). That is wrong, I think. I changed it to 200 and now the writing is as fast as expected.
> 
> Now, the question is: How this should be fixed *correctly*? The 200 is the maximum word program time for this particular chip. Maybe it should have different value for different chips.

It seems the problem really exists and needs to be solved. The default value of word programming timeo is defined improperly 50000usec for one word is too much - but it is not good to set it very low because inval_cache_and_wait function could return with timeo out error. The best thing would be to set default word programming time for the slowest case. I think 10KB/s would be worst enough case.

Thanks,
Alexey 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Very slow nor flash write
  2007-11-22 14:24 ` Alexey Korolev
@ 2007-11-22 14:59   ` Jamie Lokier
  2007-11-22 15:12   ` Nicolas Pitre
  1 sibling, 0 replies; 7+ messages in thread
From: Jamie Lokier @ 2007-11-22 14:59 UTC (permalink / raw)
  To: Alexey Korolev; +Cc: nico, linux-mtd, tike64

Alexey Korolev wrote:
> The best thing would be to set default word programming time for the
> slowest case. I think 10KB/s would be worst enough case.

I'm sure I've seen flash devices that program slower than 10KB/s.
However, I don't know if any CFI-1 devices would be that slow.

-- Jamie

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Very slow nor flash write
  2007-11-22 14:24 ` Alexey Korolev
  2007-11-22 14:59   ` Jamie Lokier
@ 2007-11-22 15:12   ` Nicolas Pitre
  2007-11-22 18:04     ` Alexey Korolev
  1 sibling, 1 reply; 7+ messages in thread
From: Nicolas Pitre @ 2007-11-22 15:12 UTC (permalink / raw)
  To: Alexey Korolev; +Cc: linux-mtd, tike64

On Thu, 22 Nov 2007, Alexey Korolev wrote:

> Hi Timo
> 
> > I have an LH7A400 board and there intel 28F160B3T nor flash chip. I managed to configure Linux 2.6.18 to access the chip as an MTD device. However, the write access was very slow, about 40ms per word or 0.00005 MB/s ;-)
> > 
> > I traced the problem to inval_cache_and_wait_for_operation() in cfi_cmdset_0001.c. In the for-loop, if the write access haven't finished when checked for the first time, a long "msleep(sleep_time/1000);" is triggered. The sleep duration is very long because chip_op_time value is 50000. The value comes from "cfi->chips[i].word_write_time = 50000;" in cfi_cmdset_0001(). That is wrong, I think. I changed it to 200 and now the writing is as fast as expected.
> > 
> > Now, the question is: How this should be fixed *correctly*? The 200 is the maximum word program time for this particular chip. Maybe it should have different value for different chips.
> 
> It seems the problem really exists and needs to be solved. The default 
> value of word programming timeo is defined improperly 50000usec for 
> one word is too much - but it is not good to set it very low because 
> inval_cache_and_wait function could return with timeo out error. The 
> best thing would be to set default word programming time for the 
> slowest case. I think 10KB/s would be worst enough case.

No.  You don't know if that is indeed the _absolute_ worst case, and 
doing so just moves the problem elsewhere.

Why not simply adding a fixup entry for this particular flash model to 
override word_write_time with the appropriate value instead?


Nicolas

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Very slow nor flash write
  2007-11-22 15:12   ` Nicolas Pitre
@ 2007-11-22 18:04     ` Alexey Korolev
  0 siblings, 0 replies; 7+ messages in thread
From: Alexey Korolev @ 2007-11-22 18:04 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: linux-mtd, tike64

Hi Nicolas,
> > It seems the problem really exists and needs to be solved. The default 
> > value of word programming timeo is defined improperly 50000usec for 
> > one word is too much - but it is not good to set it very low because 
> > inval_cache_and_wait function could return with timeo out error. The 
> > best thing would be to set default word programming time for the 
> > slowest case. I think 10KB/s would be worst enough case.
> 
> No.  You don't know if that is indeed the _absolute_ worst case, and 
> doing so just moves the problem elsewhere.
> 
> Why not simply adding a fixup entry for this particular flash model to 
> override word_write_time with the appropriate value instead?
> 
Fix up is not the best solution, because the problem will exist for every chip which do not have word programming time specified. Fixup will solve the problem for one particular part and will not fix other. 
You are right in point that setting default timeo to particular value suitable for particalur set of chips is not good as well. 
In current implementation we set up limit = timeo * 8. May be it would be better to make change here to solve the issue. If we would set up wait timeout _non less_ than some big value for chip but suitable for user it could solve the issue.If this will be  applied it won't be a problem to make default word programming time tiny. What do you think of it?
Thanks,
Alexey  

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Very slow nor flash write
  2007-11-22 11:29 Very slow nor flash write tike64
  2007-11-22 14:24 ` Alexey Korolev
@ 2007-11-22 18:12 ` Anders Grafström
  1 sibling, 0 replies; 7+ messages in thread
From: Anders Grafström @ 2007-11-22 18:12 UTC (permalink / raw)
  To: tike64; +Cc: linux-mtd

tike64 wrote:
> Dear List,
> 
> I have an LH7A400 board and there intel 28F160B3T nor flash chip. I managed to configure Linux 2.6.18 to access the chip as an MTD device. However, the write access was very slow, about 40ms per word or 0.00005 MB/s ;-)
> 
> I traced the problem to inval_cache_and_wait_for_operation() in cfi_cmdset_0001.c. In the for-loop, if the write access haven't finished when checked for the first time, a long "msleep(sleep_time/1000);" is triggered. The sleep duration is very long because chip_op_time value is 50000. The value comes from "cfi->chips[i].word_write_time = 50000;" in cfi_cmdset_0001(). That is wrong, I think. I changed it to 200 and now the writing is as fast as expected.
> 
> Now, the question is: How this should be fixed *correctly*? The 200 is the maximum word program time for this particular chip. Maybe it should have different value for different chips.

There is actually a more serious problem in this code area. It is falsely assumed
that chip_op_time * 8 is long enough for the timeout. On aging and failing flash chips
this is not enough. The max value that the datasheet specifies is required. Otherwise
you will get a timeout while the chip is still trying to perform the operation.
After a timeout the mtd driver proceeds like nothing happened and the chip will be
in a different state than the driver expects it to be in and you get lots of errors
when subsequent operations fail.

This patch applies to linux kernel 2.6.18. It might help for your problem and hopefully
gives an idea of the problem I described. It still exists in current git. I had hoped
to update this patch for current git before posting it but haven't had time for it yet.

/Anders


diff -urpN linux-2.6.18.orig/drivers/mtd/chips/cfi_cmdset_0001.c 
linux-2.6.18/drivers/mtd/chips/cfi_cmdset_0001.c
--- linux-2.6.18.orig/drivers/mtd/chips/cfi_cmdset_0001.c	2006-09-20 05:42:06.000000000 +0200
+++ linux-2.6.18/drivers/mtd/chips/cfi_cmdset_0001.c	2007-11-22 18:08:24.000000000 +0100
@@ -401,6 +401,12 @@ struct mtd_info *cfi_cmdset_0001(struct
  		cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
  		cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
  		cfi->chips[i].erase_time = 1000<<cfi->cfiq->BlockEraseTimeoutTyp;
+		cfi->chips[i].word_write_timeout = 1<<(cfi->cfiq->WordWriteTimeoutTyp +
+		                                       cfi->cfiq->WordWriteTimeoutMax);
+		cfi->chips[i].buffer_write_timeout = 1<<(cfi->cfiq->BufWriteTimeoutTyp +
+		                                         cfi->cfiq->BufWriteTimeoutMax);
+		cfi->chips[i].erase_timeout = 1000<<(cfi->cfiq->BlockEraseTimeoutTyp +
+		                                     cfi->cfiq->BlockEraseTimeoutMax);
  		cfi->chips[i].ref_point_counter = 0;
  		init_waitqueue_head(&(cfi->chips[i].wq));
  	}
@@ -908,7 +914,7 @@ static void __xipram xip_enable(struct m

  static int __xipram xip_wait_for_operation(
  		struct map_info *map, struct flchip *chip,
-		unsigned long adr, unsigned int chip_op_time )
+		unsigned long adr, unsigned int chip_op_time, unsigned int chip_op_timeout)
  {
  	struct cfi_private *cfi = map->fldrv_priv;
  	struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
@@ -917,7 +923,7 @@ static int __xipram xip_wait_for_operati
  	flstate_t oldstate, newstate;

         	start = xip_currtime();
-	usec = chip_op_time * 8;
+	usec = chip_op_timeout;
  	if (usec == 0)
  		usec = 500000;
  	done = 0;
@@ -1027,8 +1033,8 @@ static int __xipram xip_wait_for_operati
  #define XIP_INVAL_CACHED_RANGE(map, from, size)  \
  	INVALIDATE_CACHED_RANGE(map, from, size)

-#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, usec) \
-	xip_wait_for_operation(map, chip, cmd_adr, usec)
+#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, usec, usec_max) \
+	xip_wait_for_operation(map, chip, cmd_adr, usec, usec_max)

  #else

@@ -1040,7 +1046,7 @@ static int __xipram xip_wait_for_operati
  static int inval_cache_and_wait_for_operation(
  		struct map_info *map, struct flchip *chip,
  		unsigned long cmd_adr, unsigned long inval_adr, int inval_len,
-		unsigned int chip_op_time)
+		unsigned int chip_op_time, unsigned int chip_op_timeout)
  {
  	struct cfi_private *cfi = map->fldrv_priv;
  	map_word status, status_OK = CMD(0x80);
@@ -1052,8 +1058,7 @@ static int inval_cache_and_wait_for_oper
  		INVALIDATE_CACHED_RANGE(map, inval_adr, inval_len);
  	spin_lock(chip->mutex);

-	/* set our timeout to 8 times the expected delay */
-	timeo = chip_op_time * 8;
+	timeo = chip_op_timeout;
  	if (!timeo)
  		timeo = 500000;
  	sleep_time = chip_op_time / 2;
@@ -1107,7 +1112,7 @@ static int inval_cache_and_wait_for_oper
  #endif

  #define WAIT_TIMEOUT(map, chip, adr, udelay) \
-	INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, udelay);
+	INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, udelay, udelay * 8);


  static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len)
@@ -1331,7 +1336,8 @@ static int __xipram do_write_oneword(str

  	ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
  				   adr, map_bankwidth(map),
-				   chip->word_write_time);
+				   chip->word_write_time,
+				   chip->word_write_timeout);
  	if (ret) {
  		xip_enable(map, chip, adr);
  		printk(KERN_ERR "%s: word write error (status timeout)\n", map->name);
@@ -1568,7 +1574,8 @@ static int __xipram do_write_buffer(stru

  	ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr,
  				   adr, len,
-				   chip->buffer_write_time);
+				   chip->buffer_write_time,
+				   chip->buffer_write_timeout);
  	if (ret) {
  		map_write(map, CMD(0x70), cmd_adr);
  		chip->state = FL_STATUS;
@@ -1703,7 +1710,8 @@ static int __xipram do_erase_oneblock(st

  	ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
  				   adr, len,
-				   chip->erase_time);
+				   chip->erase_time,
+				   chip->erase_timeout);
  	if (ret) {
  		map_write(map, CMD(0x70), adr);
  		chip->state = FL_STATUS;
diff -urpN linux-2.6.18.orig/include/linux/mtd/flashchip.h linux-2.6.18/include/linux/mtd/flashchip.h
--- linux-2.6.18.orig/include/linux/mtd/flashchip.h	2006-09-20 05:42:06.000000000 +0200
+++ linux-2.6.18/include/linux/mtd/flashchip.h	2007-09-11 20:46:03.000000000 +0200
@@ -75,6 +75,10 @@ struct flchip {
  	int buffer_write_time;
  	int erase_time;

+	int word_write_timeout;
+	int buffer_write_timeout;
+	int erase_timeout;
+
  	void *priv;
  };

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Very slow nor flash write
       [not found] <214802.55189.qm@web59211.mail.re1.yahoo.com>
@ 2007-11-23 22:36 ` Anders Grafström
  0 siblings, 0 replies; 7+ messages in thread
From: Anders Grafström @ 2007-11-23 22:36 UTC (permalink / raw)
  To: tike64; +Cc: jamie, nico, linux-mtd, akorolev

tike64 wrote:
> Of course the code must always allow for possible timeouts.But wouldn't the
> cfi_cmdset_0001.c code take care of that:
>
>         if (!timeo) {
>             map_write(map, CMD(0x70), cmd_adr);
>             chip->state = FL_STATUS;
>             return -ETIME;

This is where the state is lost. chip->state is changed to FL_STATUS
but the hardware remains in FL_ERASING or FL_WRITING state until it
completes the operation or times out after the max erase or write time.

What then happens is get_chip() timing out saying
"Waiting for chip to be ready timed out. Status xxxx"
and jffs2 complaining about not being able to read or write.
But this is probably only an issue for erase operations.

For me this resulted in failure to read the file system at boot time
and thus a system that could not be booted.

I guess there is something wrong with the timeout error path.
Should chip->state be left unchanged?

> I think I understand the principle of the patch and it seems fine to me. But
> it seems to solve the problem only for the CFI parts. I think there should be
> respective timing fields in the jedec_table in jedec_probe.c.

Yes, it only solves it for parts that have timing values specified. There is
more to do. Quick version could be to set the timeouts to the old defaults and
the write and erase time to short values.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2007-11-23 23:01 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-11-22 11:29 Very slow nor flash write tike64
2007-11-22 14:24 ` Alexey Korolev
2007-11-22 14:59   ` Jamie Lokier
2007-11-22 15:12   ` Nicolas Pitre
2007-11-22 18:04     ` Alexey Korolev
2007-11-22 18:12 ` Anders Grafström
     [not found] <214802.55189.qm@web59211.mail.re1.yahoo.com>
2007-11-23 22:36 ` Anders Grafström

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).