mtd/drivers/mtd/nand nand.c,1.80,1.81

gleixner at infradead.org gleixner at infradead.org
Fri Apr 16 00:12:02 EDT 2004


Update of /home/cvs/mtd/drivers/mtd/nand
In directory phoenix.infradead.org:/tmp/cvs-serv1657

Modified Files:
	nand.c 
Log Message:
read data from buffer if possible

Index: nand.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/nand/nand.c,v
retrieving revision 1.80
retrieving revision 1.81
diff -u -r1.80 -r1.81
--- nand.c	15 Apr 2004 11:58:53 -0000	1.80
+++ nand.c	16 Apr 2004 04:12:00 -0000	1.81
@@ -545,6 +545,10 @@
  * Erase can take up to 400ms and program up to 20ms according to 
  * general NAND and SmartMedia specs
  *
+ * @mtd:	MTD device structure
+ * @this:	NAND chip structure
+ * @state:	state to select the max. timeout value
+ *
 */
 static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
 {
@@ -806,7 +810,7 @@
 static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
 			  size_t * retlen, u_char * buf, u_char * oob_buf, struct nand_oobinfo *oobsel)
 {
-	int i, j, col, page, end, ecc, chipnr;
+	int i, j, col, realpage, page, end, ecc, chipnr, sndcmd = 1;
 	int erase_state = 0;
 	int read = 0, oob = 0, ecc_status = 0, ecc_failed = 0;
 	struct nand_chip *this = mtd->priv;
@@ -846,8 +850,8 @@
 	this->select_chip(mtd, chipnr);
 
 	/* First we calculate the starting page */
-	page = from >> this->page_shift;
-	page &= this->pagemask;
+	realpage = from >> this->page_shift;
+	page = realpage & this->pagemask;
 
 	/* Get raw starting column */
 	col = from & (mtd->oobblock - 1);
@@ -855,23 +859,36 @@
 	end = mtd->oobblock;
 	ecc = mtd->eccsize;
 
-	/* Send the read command 
-	 * If we read not page aligned we can start at ecc
-	 * boundary.
-	 * FIXME: Implement it
-	*/
-	this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page);
-	
 	/* Loop until all data read */
 	while (read < len) {
+		
+		int aligned = (!col && (len - read) >= end);
 		/* 
 		 * If the read is not page aligned, we have to read into data buffer
 		 * due to ecc, else we read into return buffer direct
 		 */
-		if (!col && (len - read) >= end)
+		if (aligned)
 			data_poi = &buf[read];
 		else 
 			data_poi = this->data_buf;
+		
+		/* Check, if we have this page in the buffer 
+		 *
+		 * FIXME: Make it work when we must provide oob data too,
+		 * check the usage of data_buf oob field
+		 */
+		if (realpage == this->pagebuf && !oob_buf) {
+			/* aligned read ? */
+			if (aligned)
+				memcpy (data_poi, this->data_buf, end);
+			goto readdata;
+		}
+
+		/* Check, if we must send the read command */
+		if (sndcmd) {
+			this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page);
+			sndcmd = 0;
+		}	
 
 		/* get oob area, if we have no oob buffer from fs-driver */
 		if (!oob_buf || oobsel->useecc == MTD_NANDECC_AUTOPLACE)
@@ -968,9 +985,10 @@
 		}
 readdata:
 		/* Partial page read, transfer data into fs buffer */
-		if (col || (len - read) < end) { 
+		if (!aligned) { 
 			for (j = col; j < end && read < len; j++)
 				buf[read++] = data_poi[j];
+			this->pagebuf = realpage;	
 		} else		
 			read += mtd->oobblock;
 
@@ -980,7 +998,7 @@
 		/* For subsequent reads align to page boundary. */
 		col = 0;
 		/* Increment page address */
-		page++;
+		realpage++;
 
 		/* Apply delay or wait for ready/busy pin 
 		 * Do this before the AUTOINCR check, so no problems
@@ -992,19 +1010,18 @@
 		else
 			while (!this->dev_ready(mtd));	
 			
-		page &= this->pagemask;
+		page = realpage & this->pagemask;
 		/* Check, if we cross a chip boundary */
 		if (!page) {
 			chipnr++;
 			this->select_chip(mtd, -1);
 			this->select_chip(mtd, chipnr);
 		}
-				
 		/* Check, if the chip supports auto page increment 
 		 * or if we have hit a block boundary. 
 		*/ 
 		if (!NAND_CANAUTOINCR(this) || !(page & blockcheck))
-			this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page);
+			sndcmd = 1;				
 	}
 
 	/* Deselect and wake up anyone waiting on the device */
@@ -1511,12 +1528,11 @@
 
 	/* Setup start page */
 	page = ((int) to) >> this->page_shift;
-	page &= this->pagemask;
+	startpage = page & this->pagemask;
 
 	/* Loop until all iovecs' data has been written */
 	len = 0;
 	while (count) {
-		startpage = page;
 		/* If the given tuple is >= pagesize then
 		 * write it out from the iov
 		 */
@@ -1536,8 +1552,8 @@
 				 * then use the real pageprogram command, else select 
 				 * cached programming if supported by the chip.
 				 */
-				ret = nand_write_page (mtd, this, page, &oobbuf[oob], oobsel, 
-					i != numpages);
+				ret = nand_write_page (mtd, this, page & this->pagemask, 
+					&oobbuf[oob], oobsel, i != numpages);
 				if (ret)
 					goto out;
 				this->data_poi += mtd->oobblock;
@@ -1566,11 +1582,13 @@
 					count--;
 				}
 			}
+			this->pagebuf = page;	
 			this->data_poi = this->data_buf;	
 			bufstart = this->data_poi;
 			numpages = 1;		
 			oobbuf = nand_prepare_oobbuf (mtd, NULL, oobsel, autoplace, numpages);
-			ret = nand_write_page (mtd, this, page, oobbuf, oobsel, 0);
+			ret = nand_write_page (mtd, this, page & this->pagemask,
+				oobbuf, oobsel, 0);
 			if (ret)
 				goto out;
 			page++;
@@ -1586,10 +1604,9 @@
 		if (!count)
 			break;
 
-		/* Make it relative to chip start */			
-		page &= this->pagemask;
+		startpage = page & this->pagemask;
 		/* Check, if we cross a chip boundary */
-		if (!page) {
+		if (!startpage) {
 			chipnr++;
 			this->select_chip(mtd, -1);
 			this->select_chip(mtd, chipnr);
@@ -2059,6 +2076,9 @@
 
 	/* De-select the device */
 	this->select_chip(mtd, -1);
+
+	/* Invalidate the pagebuffer reference */
+	this->pagebuf = -1;
 
 	/* Fill in remaining MTD driver data */
 	mtd->type = MTD_NANDFLASH;




More information about the linux-mtd-cvs mailing list