diff options
-rw-r--r-- | drivers/mtd/onenand/onenand_base.c | 24 | ||||
-rw-r--r-- | include/linux/mtd/onenand.h | 5 |
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 | ||
2445 | EXPORT_SYMBOL_GPL(onenand_scan); | 2457 | EXPORT_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 |