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