aboutsummaryrefslogtreecommitdiffstats
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 6d4e67f6c295..9e14a26ca4e8 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
836 int readcol = column; 836 int readcol = column;
837 int readend = column + thislen; 837 int readend = column + thislen;
838 int lastgap = 0; 838 int lastgap = 0;
839 uint8_t *oob_buf = this->page_buf + mtd->writesize; 839 uint8_t *oob_buf = this->oob_buf;
840 840
841 for (free = this->ecclayout->oobfree; free->length; ++free) { 841 for (free = this->ecclayout->oobfree; free->length; ++free) {
842 if (readcol >= lastgap) 842 if (readcol >= lastgap)
@@ -1356,7 +1356,7 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
1356 /* Grab the lock and see if the device is available */ 1356 /* Grab the lock and see if the device is available */
1357 onenand_get_device(mtd, FL_WRITING); 1357 onenand_get_device(mtd, FL_WRITING);
1358 1358
1359 oobbuf = this->page_buf + mtd->writesize; 1359 oobbuf = this->oob_buf;
1360 1360
1361 /* Loop until all data write */ 1361 /* Loop until all data write */
1362 while (written < len) { 1362 while (written < len) {
@@ -2332,15 +2332,25 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
2332 2332
2333 /* Allocate buffers, if necessary */ 2333 /* Allocate buffers, if necessary */
2334 if (!this->page_buf) { 2334 if (!this->page_buf) {
2335 size_t len; 2335 this->page_buf = kzalloc(mtd->writesize, GFP_KERNEL);
2336 len = mtd->writesize + mtd->oobsize;
2337 this->page_buf = kmalloc(len, GFP_KERNEL);
2338 if (!this->page_buf) { 2336 if (!this->page_buf) {
2339 printk(KERN_ERR "onenand_scan(): Can't allocate page_buf\n"); 2337 printk(KERN_ERR "onenand_scan(): Can't allocate page_buf\n");
2340 return -ENOMEM; 2338 return -ENOMEM;
2341 } 2339 }
2342 this->options |= ONENAND_PAGEBUF_ALLOC; 2340 this->options |= ONENAND_PAGEBUF_ALLOC;
2343 } 2341 }
2342 if (!this->oob_buf) {
2343 this->oob_buf = kzalloc(mtd->oobsize, GFP_KERNEL);
2344 if (!this->oob_buf) {
2345 printk(KERN_ERR "onenand_scan(): Can't allocate oob_buf\n");
2346 if (this->options & ONENAND_PAGEBUF_ALLOC) {
2347 this->options &= ~ONENAND_PAGEBUF_ALLOC;
2348 kfree(this->page_buf);
2349 }
2350 return -ENOMEM;
2351 }
2352 this->options |= ONENAND_OOBBUF_ALLOC;
2353 }
2344 2354
2345 this->state = FL_READY; 2355 this->state = FL_READY;
2346 init_waitqueue_head(&this->wq); 2356 init_waitqueue_head(&this->wq);
@@ -2437,9 +2447,11 @@ void onenand_release(struct mtd_info *mtd)
2437 kfree(bbm->bbt); 2447 kfree(bbm->bbt);
2438 kfree(this->bbm); 2448 kfree(this->bbm);
2439 } 2449 }
2440 /* Buffer allocated by onenand_scan */ 2450 /* Buffers allocated by onenand_scan */
2441 if (this->options & ONENAND_PAGEBUF_ALLOC) 2451 if (this->options & ONENAND_PAGEBUF_ALLOC)
2442 kfree(this->page_buf); 2452 kfree(this->page_buf);
2453 if (this->options & ONENAND_OOBBUF_ALLOC)
2454 kfree(this->oob_buf);
2443} 2455}
2444 2456
2445EXPORT_SYMBOL_GPL(onenand_scan); 2457EXPORT_SYMBOL_GPL(onenand_scan);
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index d8af8a95e58d..a56d24ada505 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -82,7 +82,8 @@ struct onenand_bufferram {
82 * @wq: [INTERN] wait queue to sleep on if a OneNAND 82 * @wq: [INTERN] wait queue to sleep on if a OneNAND
83 * operation is in progress 83 * operation is in progress
84 * @state: [INTERN] the current state of the OneNAND device 84 * @state: [INTERN] the current state of the OneNAND device
85 * @page_buf: data buffer 85 * @page_buf: [INTERN] page main data buffer
86 * @oob_buf: [INTERN] page oob data buffer
86 * @subpagesize: [INTERN] holds the subpagesize 87 * @subpagesize: [INTERN] holds the subpagesize
87 * @ecclayout: [REPLACEABLE] the default ecc placement scheme 88 * @ecclayout: [REPLACEABLE] the default ecc placement scheme
88 * @bbm: [REPLACEABLE] pointer to Bad Block Management 89 * @bbm: [REPLACEABLE] pointer to Bad Block Management
@@ -122,6 +123,7 @@ struct onenand_chip {
122 wait_queue_head_t wq; 123 wait_queue_head_t wq;
123 onenand_state_t state; 124 onenand_state_t state;
124 unsigned char *page_buf; 125 unsigned char *page_buf;
126 unsigned char *oob_buf;
125 127
126 int subpagesize; 128 int subpagesize;
127 struct nand_ecclayout *ecclayout; 129 struct nand_ecclayout *ecclayout;
@@ -156,6 +158,7 @@ struct onenand_chip {
156#define ONENAND_HAS_CONT_LOCK (0x0001) 158#define ONENAND_HAS_CONT_LOCK (0x0001)
157#define ONENAND_HAS_UNLOCK_ALL (0x0002) 159#define ONENAND_HAS_UNLOCK_ALL (0x0002)
158#define ONENAND_PAGEBUF_ALLOC (0x1000) 160#define ONENAND_PAGEBUF_ALLOC (0x1000)
161#define ONENAND_OOBBUF_ALLOC (0x2000)
159 162
160/* 163/*
161 * OneNAND Flash Manufacturer ID Codes 164 * OneNAND Flash Manufacturer ID Codes