summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/onenand/onenand_base.c24
-rw-r--r--include/linux/mtd/onenand.h5
2 files changed, 22 insertions, 7 deletions
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 6d4e67f6c29..9e14a26ca4e 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -836,7 +836,7 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf, int col
int readcol = column;
int readend = column + thislen;
int lastgap = 0;
- uint8_t *oob_buf = this->page_buf + mtd->writesize;
+ uint8_t *oob_buf = this->oob_buf;
for (free = this->ecclayout->oobfree; free->length; ++free) {
if (readcol >= lastgap)
@@ -1356,7 +1356,7 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
/* Grab the lock and see if the device is available */
onenand_get_device(mtd, FL_WRITING);
- oobbuf = this->page_buf + mtd->writesize;
+ oobbuf = this->oob_buf;
/* Loop until all data write */
while (written < len) {
@@ -2332,15 +2332,25 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
/* Allocate buffers, if necessary */
if (!this->page_buf) {
- size_t len;
- len = mtd->writesize + mtd->oobsize;
- this->page_buf = kmalloc(len, GFP_KERNEL);
+ this->page_buf = kzalloc(mtd->writesize, GFP_KERNEL);
if (!this->page_buf) {
printk(KERN_ERR "onenand_scan(): Can't allocate page_buf\n");
return -ENOMEM;
}
this->options |= ONENAND_PAGEBUF_ALLOC;
}
+ if (!this->oob_buf) {
+ this->oob_buf = kzalloc(mtd->oobsize, GFP_KERNEL);
+ if (!this->oob_buf) {
+ printk(KERN_ERR "onenand_scan(): Can't allocate oob_buf\n");
+ if (this->options & ONENAND_PAGEBUF_ALLOC) {
+ this->options &= ~ONENAND_PAGEBUF_ALLOC;
+ kfree(this->page_buf);
+ }
+ return -ENOMEM;
+ }
+ this->options |= ONENAND_OOBBUF_ALLOC;
+ }
this->state = FL_READY;
init_waitqueue_head(&this->wq);
@@ -2437,9 +2447,11 @@ void onenand_release(struct mtd_info *mtd)
kfree(bbm->bbt);
kfree(this->bbm);
}
- /* Buffer allocated by onenand_scan */
+ /* Buffers allocated by onenand_scan */
if (this->options & ONENAND_PAGEBUF_ALLOC)
kfree(this->page_buf);
+ if (this->options & ONENAND_OOBBUF_ALLOC)
+ kfree(this->oob_buf);
}
EXPORT_SYMBOL_GPL(onenand_scan);
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index d8af8a95e58..a56d24ada50 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -82,7 +82,8 @@ struct onenand_bufferram {
* @wq: [INTERN] wait queue to sleep on if a OneNAND
* operation is in progress
* @state: [INTERN] the current state of the OneNAND device
- * @page_buf: data buffer
+ * @page_buf: [INTERN] page main data buffer
+ * @oob_buf: [INTERN] page oob data buffer
* @subpagesize: [INTERN] holds the subpagesize
* @ecclayout: [REPLACEABLE] the default ecc placement scheme
* @bbm: [REPLACEABLE] pointer to Bad Block Management
@@ -122,6 +123,7 @@ struct onenand_chip {
wait_queue_head_t wq;
onenand_state_t state;
unsigned char *page_buf;
+ unsigned char *oob_buf;
int subpagesize;
struct nand_ecclayout *ecclayout;
@@ -156,6 +158,7 @@ struct onenand_chip {
#define ONENAND_HAS_CONT_LOCK (0x0001)
#define ONENAND_HAS_UNLOCK_ALL (0x0002)
#define ONENAND_PAGEBUF_ALLOC (0x1000)
+#define ONENAND_OOBBUF_ALLOC (0x2000)
/*
* OneNAND Flash Manufacturer ID Codes