mtd: cfi_cmdset_0002: fix do_write_buffer() timeout error

Linux-MTD Mailing List linux-mtd at lists.infradead.org
Fri Aug 8 09:59:03 PDT 2014


Gitweb:     http://git.infradead.org/?p=mtd-2.6.git;a=commit;h=6534e6809e6c9d48114b537afe03bee3fd33bf01
Commit:     6534e6809e6c9d48114b537afe03bee3fd33bf01
Parent:     d68a5c3d2db408a83e69f12b57b8e19c086d1aee
Author:     Bean Huo <beanhuo at outlook.com>
AuthorDate: Wed Jul 16 09:05:26 2014 -0700
Committer:  Brian Norris <computersforpeace at gmail.com>
CommitDate: Wed Jul 16 11:03:38 2014 -0700

    mtd: cfi_cmdset_0002: fix do_write_buffer() timeout error
    
    For some NOR flashes, the size of the buffer program has been increased
    from 256 bytes to 512 bytes, and so 2ms maximum timeout can may not be
    sufficient for all different vendor's NOR flash. There is maximum
    timeout information in the CFI area, so we instead of picking a fixed
    value, we can calculate this according to the standard CFI parameters
    parsed at probe time. If we haven't probed this information, or it is
    smaller than 2000us, then specify a minimum value 2000us.
    
    Tested with Micron JS28F512M29EWx and Micron MT28EW512ABA flash devices.
    
    Signed-off-by: Bean Huo <beanhuo at outlook.com>
    [Brian: fix up comments, use 'max()']
    Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 drivers/mtd/chips/cfi_cmdset_0002.c | 25 +++++++++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index bf313be6..5a4bfe3 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -645,6 +645,23 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
 		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 = 1<<cfi->cfiq->BlockEraseTimeoutTyp;
+		/*
+		 * First calculate the timeout max according to timeout field
+		 * of struct cfi_ident that probed from chip's CFI aera, if
+		 * available. Specify a minimum of 2000us, in case the CFI data
+		 * is wrong.
+		 */
+		if (cfi->cfiq->BufWriteTimeoutTyp &&
+		    cfi->cfiq->BufWriteTimeoutMax)
+			cfi->chips[i].buffer_write_time_max =
+				1 << (cfi->cfiq->BufWriteTimeoutTyp +
+				      cfi->cfiq->BufWriteTimeoutMax);
+		else
+			cfi->chips[i].buffer_write_time_max = 0;
+
+		cfi->chips[i].buffer_write_time_max =
+			max(cfi->chips[i].buffer_write_time_max, 2000);
+
 		cfi->chips[i].ref_point_counter = 0;
 		init_waitqueue_head(&(cfi->chips[i].wq));
 	}
@@ -1774,8 +1791,12 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
 {
 	struct cfi_private *cfi = map->fldrv_priv;
 	unsigned long timeo = jiffies + HZ;
-	/* see comments in do_write_oneword() regarding uWriteTimeo. */
-	unsigned long uWriteTimeout = ( HZ / 1000 ) + 1;
+	/*
+	 * Timeout is calculated according to CFI data, if available.
+	 * See more comments in cfi_cmdset_0002().
+	 */
+	unsigned long uWriteTimeout =
+				usecs_to_jiffies(chip->buffer_write_time_max);
 	int ret = -EIO;
 	unsigned long cmd_adr;
 	int z, words;



More information about the linux-mtd-cvs mailing list