Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=a8de85d557004d6d4e4cf79ecd6b97339b986fe9
Commit:     a8de85d557004d6d4e4cf79ecd6b97339b986fe9
Parent:     2fd32d4af83f4535d12d3f6dd23189352a9596fa
Author:     Adrian Hunter <[EMAIL PROTECTED]>
AuthorDate: Thu Jan 4 09:51:26 2007 +0200
Committer:  Artem Bityutskiy <[EMAIL PROTECTED]>
CommitDate: Wed Jan 10 14:58:42 2007 +0200

    [MTD] OneNAND: Implement read-while-load
    
    Read-while-load enables higher performance read operations.
    
    Signed-off-by: Adrian Hunter <[EMAIL PROTECTED]>
    Signed-off-by: Kyungmin Park <[EMAIL PROTECTED]>
---
 drivers/mtd/onenand/onenand_base.c |   74 ++++++++++++++++++++---------------
 include/linux/mtd/onenand.h        |    1 +
 2 files changed, 43 insertions(+), 32 deletions(-)

diff --git a/drivers/mtd/onenand/onenand_base.c 
b/drivers/mtd/onenand/onenand_base.c
index e80857b..abbe160 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -727,40 +727,47 @@ static int onenand_read(struct mtd_info *mtd, loff_t 
from, size_t len,
        /* TODO handling oob */
 
        stats = mtd->ecc_stats;
-       while (read < len) {
-               cond_resched();
-
-               thislen = min_t(int, mtd->writesize, len - read);
-
-               column = from & (mtd->writesize - 1);
-               if (column + thislen > mtd->writesize)
-                       thislen = mtd->writesize - column;
-
-               if (!onenand_check_bufferram(mtd, from)) {
-                       this->command(mtd, ONENAND_CMD_READ, from, 
mtd->writesize);
-
-                       ret = this->wait(mtd, FL_READING);
-                       /* First copy data and check return value for ECC 
handling */
-                       onenand_update_bufferram(mtd, from, !ret);
-               }
-
-               this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, 
thislen);
 
-               if (ret) {
-                       DEBUG(MTD_DEBUG_LEVEL0, "onenand_read: read failed = 
%d\n", ret);
-                       goto out;
-               }
+       /* Read-while-load method */
+
+       /* Do first load to bufferRAM */
+       if (read < len) {
+               if (!onenand_check_bufferram(mtd, from)) {
+                       this->command(mtd, ONENAND_CMD_READ, from, 
mtd->writesize);
+                       ret = this->wait(mtd, FL_READING);
+                       onenand_update_bufferram(mtd, from, !ret);
+               }
+       }
+
+       thislen = min_t(int, mtd->writesize, len - read);
+       column = from & (mtd->writesize - 1);
+       if (column + thislen > mtd->writesize)
+               thislen = mtd->writesize - column;
+
+       while (!ret) {
+               /* If there is more to load then start next load */
+               from += thislen;
+               if (read + thislen < len) {
+                       this->command(mtd, ONENAND_CMD_READ, from, 
mtd->writesize);
+                       ONENAND_SET_PREV_BUFFERRAM(this);
+               }
+               /* While load is going, read from last bufferRAM */
+               this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, 
thislen);
+               /* See if we are done */
+               read += thislen;
+               if (read == len)
+                       break;
+               /* Set up for next read from bufferRAM */
+               ONENAND_SET_NEXT_BUFFERRAM(this);
+               buf += thislen;
+               thislen = min_t(int, mtd->writesize, len - read);
+               column = 0;
+               cond_resched();
+               /* Now wait for load */
+               ret = this->wait(mtd, FL_READING);
+               onenand_update_bufferram(mtd, from, !ret);
+       }
 
-               read += thislen;
-
-               if (read == len)
-                       break;
-
-               from += thislen;
-               buf += thislen;
-       }
-
-out:
        /* Deselect and wake up anyone waiting on the device */
        onenand_release_device(mtd);
 
@@ -774,6 +781,9 @@ out:
        if (mtd->ecc_stats.failed - stats.failed)
                return -EBADMSG;
 
+       if (ret)
+               return ret;
+
        return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
 }
 
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index fe3500d..f775a7a 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -143,6 +143,7 @@ struct onenand_chip {
 #define ONENAND_CURRENT_BUFFERRAM(this)                (this->bufferram_index)
 #define ONENAND_NEXT_BUFFERRAM(this)           (this->bufferram_index ^ 1)
 #define ONENAND_SET_NEXT_BUFFERRAM(this)       (this->bufferram_index ^= 1)
+#define ONENAND_SET_PREV_BUFFERRAM(this)       (this->bufferram_index ^= 1)
 
 #define ONENAND_GET_SYS_CFG1(this)                                     \
        (this->read_word(this->base + ONENAND_REG_SYS_CFG1))
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to