Commit 6e96783f authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.infradead.org/mtd-2.6

* git://git.infradead.org/mtd-2.6:
  [JFFS2] print a message when marking bad block
  [JFFS2] Check for all-zero node headers
  [MTD] [OneNAND] Classify the page data and oob buffer
  [MTD] [OneNAND] Exit the loop when transferring/filling of the oob is finished
  [MTD] [OneNAND] add Nokia Copyright and a credit
  [MTD] [OneNAND] Fix typo & wrong comments
  [MTD] [OneNAND] Use oob buffer instead of main one in oob functions
  [MTD] Correct partition failed erase address
  [JFFS2] Use yield() between GC passes in background thread.
  [MTD] [NAND] Correct misspelled preprocessor variable.
  [MTD] [MAPS] dilnetpc: Fix printk warning
  [MTD] [NOR] Fix oops in cfi_amdstd_sync
  [MTD] ESB2 check for closed ROM window
  [JFFS2] Fix writebuffer recovery in the first page of a block
  [MTD] [NAND] make oobavail public
parents 8466c833 0feba829
...@@ -359,6 +359,8 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) ...@@ -359,6 +359,8 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp; cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp; cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp; cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp;
cfi->chips[i].ref_point_counter = 0;
init_waitqueue_head(&(cfi->chips[i].wq));
} }
map->fldrv = &cfi_amdstd_chipdrv; map->fldrv = &cfi_amdstd_chipdrv;
......
...@@ -158,6 +158,8 @@ struct mtd_info *cfi_cmdset_0020(struct map_info *map, int primary) ...@@ -158,6 +158,8 @@ struct mtd_info *cfi_cmdset_0020(struct map_info *map, int primary)
cfi->chips[i].word_write_time = 128; cfi->chips[i].word_write_time = 128;
cfi->chips[i].buffer_write_time = 128; cfi->chips[i].buffer_write_time = 128;
cfi->chips[i].erase_time = 1024; cfi->chips[i].erase_time = 1024;
cfi->chips[i].ref_point_counter = 0;
init_waitqueue_head(&(cfi->chips[i].wq));
} }
return cfi_staa_setup(map); return cfi_staa_setup(map);
......
...@@ -402,8 +402,8 @@ static int __init init_dnpc(void) ...@@ -402,8 +402,8 @@ static int __init init_dnpc(void)
++higlvl_partition_info[i].name; ++higlvl_partition_info[i].name;
} }
printk(KERN_NOTICE "DIL/Net %s flash: 0x%lx at 0x%lx\n", printk(KERN_NOTICE "DIL/Net %s flash: 0x%lx at 0x%llx\n",
is_dnp ? "DNPC" : "ADNP", dnpc_map.size, dnpc_map.phys); is_dnp ? "DNPC" : "ADNP", dnpc_map.size, (unsigned long long)dnpc_map.phys);
dnpc_map.virt = ioremap_nocache(dnpc_map.phys, dnpc_map.size); dnpc_map.virt = ioremap_nocache(dnpc_map.phys, dnpc_map.size);
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */ #define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */
#define BIOS_CNTL 0xDC #define BIOS_CNTL 0xDC
#define BIOS_LOCK_ENABLE 0x02 #define BIOS_LOCK_ENABLE 0x02
#define BIOS_WRITE_ENABLE 0x01 #define BIOS_WRITE_ENABLE 0x01
...@@ -145,7 +145,7 @@ static void esb2rom_cleanup(struct esb2rom_window *window) ...@@ -145,7 +145,7 @@ static void esb2rom_cleanup(struct esb2rom_window *window)
} }
static int __devinit esb2rom_init_one(struct pci_dev *pdev, static int __devinit esb2rom_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
struct esb2rom_window *window = &esb2rom_window; struct esb2rom_window *window = &esb2rom_window;
...@@ -185,7 +185,7 @@ static int __devinit esb2rom_init_one(struct pci_dev *pdev, ...@@ -185,7 +185,7 @@ static int __devinit esb2rom_init_one(struct pci_dev *pdev,
/* Find a region continuous to the end of the ROM window */ /* Find a region continuous to the end of the ROM window */
window->phys = 0; window->phys = 0;
pci_read_config_word(pdev, FWH_DEC_EN1, &word); pci_read_config_word(pdev, FWH_DEC_EN1, &word);
printk(KERN_DEBUG "pci_read_config_byte : %x\n", word); printk(KERN_DEBUG "pci_read_config_word : %x\n", word);
if ((word & FWH_8MiB) == FWH_8MiB) if ((word & FWH_8MiB) == FWH_8MiB)
window->phys = 0xff400000; window->phys = 0xff400000;
...@@ -212,6 +212,11 @@ static int __devinit esb2rom_init_one(struct pci_dev *pdev, ...@@ -212,6 +212,11 @@ static int __devinit esb2rom_init_one(struct pci_dev *pdev,
else if ((word & FWH_0_5MiB) == FWH_0_5MiB) else if ((word & FWH_0_5MiB) == FWH_0_5MiB)
window->phys = 0xfff80000; window->phys = 0xfff80000;
if (window->phys == 0) {
printk(KERN_ERR MOD_NAME ": Rom window is closed\n");
goto out;
}
/* reserved 0x0020 and 0x0010 */ /* reserved 0x0020 and 0x0010 */
window->phys -= 0x400000UL; window->phys -= 0x400000UL;
window->size = (0xffffffffUL - window->phys) + 1UL; window->size = (0xffffffffUL - window->phys) + 1UL;
......
...@@ -727,6 +727,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c ...@@ -727,6 +727,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
concat->mtd.erasesize = subdev[0]->erasesize; concat->mtd.erasesize = subdev[0]->erasesize;
concat->mtd.writesize = subdev[0]->writesize; concat->mtd.writesize = subdev[0]->writesize;
concat->mtd.oobsize = subdev[0]->oobsize; concat->mtd.oobsize = subdev[0]->oobsize;
concat->mtd.oobavail = subdev[0]->oobavail;
if (subdev[0]->writev) if (subdev[0]->writev)
concat->mtd.writev = concat_writev; concat->mtd.writev = concat_writev;
if (subdev[0]->read_oob) if (subdev[0]->read_oob)
......
...@@ -200,6 +200,11 @@ static int part_erase (struct mtd_info *mtd, struct erase_info *instr) ...@@ -200,6 +200,11 @@ static int part_erase (struct mtd_info *mtd, struct erase_info *instr)
return -EINVAL; return -EINVAL;
instr->addr += part->offset; instr->addr += part->offset;
ret = part->master->erase(part->master, instr); ret = part->master->erase(part->master, instr);
if (ret) {
if (instr->fail_addr != 0xffffffff)
instr->fail_addr -= part->offset;
instr->addr -= part->offset;
}
return ret; return ret;
} }
...@@ -338,6 +343,7 @@ int add_mtd_partitions(struct mtd_info *master, ...@@ -338,6 +343,7 @@ int add_mtd_partitions(struct mtd_info *master,
slave->mtd.size = parts[i].size; slave->mtd.size = parts[i].size;
slave->mtd.writesize = master->writesize; slave->mtd.writesize = master->writesize;
slave->mtd.oobsize = master->oobsize; slave->mtd.oobsize = master->oobsize;
slave->mtd.oobavail = master->oobavail;
slave->mtd.subpage_sft = master->subpage_sft; slave->mtd.subpage_sft = master->subpage_sft;
slave->mtd.name = parts[i].name; slave->mtd.name = parts[i].name;
...@@ -559,4 +565,3 @@ EXPORT_SYMBOL_GPL(deregister_mtd_parser); ...@@ -559,4 +565,3 @@ EXPORT_SYMBOL_GPL(deregister_mtd_parser);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Nicolas Pitre <nico@cam.org>"); MODULE_AUTHOR("Nicolas Pitre <nico@cam.org>");
MODULE_DESCRIPTION("Generic support for partitioning of MTD devices"); MODULE_DESCRIPTION("Generic support for partitioning of MTD devices");
...@@ -114,7 +114,7 @@ module_param(no_autopart, int, 0); ...@@ -114,7 +114,7 @@ module_param(no_autopart, int, 0);
static int show_firmware_partition = 0; static int show_firmware_partition = 0;
module_param(show_firmware_partition, int, 0); module_param(show_firmware_partition, int, 0);
#ifdef MTD_NAND_DISKONCHIP_BBTWRITE #ifdef CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE
static int inftl_bbt_write = 1; static int inftl_bbt_write = 1;
#else #else
static int inftl_bbt_write = 0; static int inftl_bbt_write = 0;
......
...@@ -2524,6 +2524,7 @@ int nand_scan_tail(struct mtd_info *mtd) ...@@ -2524,6 +2524,7 @@ int nand_scan_tail(struct mtd_info *mtd)
for (i = 0; chip->ecc.layout->oobfree[i].length; i++) for (i = 0; chip->ecc.layout->oobfree[i].length; i++)
chip->ecc.layout->oobavail += chip->ecc.layout->oobavail +=
chip->ecc.layout->oobfree[i].length; chip->ecc.layout->oobfree[i].length;
mtd->oobavail = chip->ecc.layout->oobavail;
/* /*
* Set the number of read / write steps for one page depending on ECC * Set the number of read / write steps for one page depending on ECC
......
...@@ -4,6 +4,11 @@ ...@@ -4,6 +4,11 @@
* Copyright (C) 2005-2007 Samsung Electronics * Copyright (C) 2005-2007 Samsung Electronics
* Kyungmin Park <kyungmin.park@samsung.com> * Kyungmin Park <kyungmin.park@samsung.com>
* *
* Credits:
* Adrian Hunter <ext-adrian.hunter@nokia.com>:
* auto-placement support, read-while load support, various fixes
* Copyright (C) Nokia Corporation, 2007
*
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
...@@ -831,7 +836,7 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf, int col ...@@ -831,7 +836,7 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf, int col
int readcol = column; int readcol = column;
int readend = column + thislen; int readend = column + thislen;
int lastgap = 0; 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) { for (free = this->ecclayout->oobfree; free->length; ++free) {
if (readcol >= lastgap) if (readcol >= lastgap)
...@@ -849,7 +854,8 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf, int col ...@@ -849,7 +854,8 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf, int col
int n = ed - st; int n = ed - st;
memcpy(buf, oob_buf + st, n); memcpy(buf, oob_buf + st, n);
buf += n; buf += n;
} } else
break;
} }
return 0; return 0;
} }
...@@ -947,9 +953,9 @@ static int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len, ...@@ -947,9 +953,9 @@ static int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
/** /**
* onenand_read_oob - [MTD Interface] NAND write data and/or out-of-band * onenand_read_oob - [MTD Interface] NAND write data and/or out-of-band
* @mtd: MTD device structure * @param mtd: MTD device structure
* @from: offset to read from * @param from: offset to read from
* @ops: oob operation description structure * @param ops: oob operation description structure
*/ */
static int onenand_read_oob(struct mtd_info *mtd, loff_t from, static int onenand_read_oob(struct mtd_info *mtd, loff_t from,
struct mtd_oob_ops *ops) struct mtd_oob_ops *ops)
...@@ -1017,7 +1023,7 @@ static int onenand_bbt_wait(struct mtd_info *mtd, int state) ...@@ -1017,7 +1023,7 @@ static int onenand_bbt_wait(struct mtd_info *mtd, int state)
* onenand_bbt_read_oob - [MTD Interface] OneNAND read out-of-band for bbt scan * onenand_bbt_read_oob - [MTD Interface] OneNAND read out-of-band for bbt scan
* @param mtd MTD device structure * @param mtd MTD device structure
* @param from offset to read from * @param from offset to read from
* @param @ops oob operation description structure * @param ops oob operation description structure
* *
* OneNAND read out-of-band data from the spare area for bbt scan * OneNAND read out-of-band data from the spare area for bbt scan
*/ */
...@@ -1093,7 +1099,7 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from, ...@@ -1093,7 +1099,7 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to) static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to)
{ {
struct onenand_chip *this = mtd->priv; struct onenand_chip *this = mtd->priv;
char *readp = this->page_buf + mtd->writesize; char oobbuf[64];
int status, i; int status, i;
this->command(mtd, ONENAND_CMD_READOOB, to, mtd->oobsize); this->command(mtd, ONENAND_CMD_READOOB, to, mtd->oobsize);
...@@ -1102,9 +1108,9 @@ static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to ...@@ -1102,9 +1108,9 @@ static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to
if (status) if (status)
return status; return status;
this->read_bufferram(mtd, ONENAND_SPARERAM, readp, 0, mtd->oobsize); this->read_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize);
for(i = 0; i < mtd->oobsize; i++) for (i = 0; i < mtd->oobsize; i++)
if (buf[i] != 0xFF && buf[i] != readp[i]) if (buf[i] != 0xFF && buf[i] != oobbuf[i])
return -EBADMSG; return -EBADMSG;
return 0; return 0;
...@@ -1290,7 +1296,8 @@ static int onenand_fill_auto_oob(struct mtd_info *mtd, u_char *oob_buf, ...@@ -1290,7 +1296,8 @@ static int onenand_fill_auto_oob(struct mtd_info *mtd, u_char *oob_buf,
int n = ed - st; int n = ed - st;
memcpy(oob_buf + st, buf, n); memcpy(oob_buf + st, buf, n);
buf += n; buf += n;
} } else
break;
} }
return 0; return 0;
} }
...@@ -1312,6 +1319,7 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len, ...@@ -1312,6 +1319,7 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
struct onenand_chip *this = mtd->priv; struct onenand_chip *this = mtd->priv;
int column, ret = 0, oobsize; int column, ret = 0, oobsize;
int written = 0; int written = 0;
u_char *oobbuf;
DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
...@@ -1331,7 +1339,7 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len, ...@@ -1331,7 +1339,7 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
} }
/* For compatibility with NAND: Do not allow write past end of page */ /* For compatibility with NAND: Do not allow write past end of page */
if (column + len > oobsize) { if (unlikely(column + len > oobsize)) {
printk(KERN_ERR "onenand_write_oob: " printk(KERN_ERR "onenand_write_oob: "
"Attempt to write past end of page\n"); "Attempt to write past end of page\n");
return -EINVAL; return -EINVAL;
...@@ -1348,6 +1356,8 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len, ...@@ -1348,6 +1356,8 @@ 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 */ /* Grab the lock and see if the device is available */
onenand_get_device(mtd, FL_WRITING); onenand_get_device(mtd, FL_WRITING);
oobbuf = this->oob_buf;
/* Loop until all data write */ /* Loop until all data write */
while (written < len) { while (written < len) {
int thislen = min_t(int, oobsize, len - written); int thislen = min_t(int, oobsize, len - written);
...@@ -1358,12 +1368,12 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len, ...@@ -1358,12 +1368,12 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
/* We send data to spare ram with oobsize /* We send data to spare ram with oobsize
* to prevent byte access */ * to prevent byte access */
memset(this->page_buf, 0xff, mtd->oobsize); memset(oobbuf, 0xff, mtd->oobsize);
if (mode == MTD_OOB_AUTO) if (mode == MTD_OOB_AUTO)
onenand_fill_auto_oob(mtd, this->page_buf, buf, column, thislen); onenand_fill_auto_oob(mtd, oobbuf, buf, column, thislen);
else else
memcpy(this->page_buf + column, buf, thislen); memcpy(oobbuf + column, buf, thislen);
this->write_bufferram(mtd, ONENAND_SPARERAM, this->page_buf, 0, mtd->oobsize); this->write_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize);
this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize); this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize);
...@@ -1375,7 +1385,7 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len, ...@@ -1375,7 +1385,7 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
break; break;
} }
ret = onenand_verify_oob(mtd, this->page_buf, to); ret = onenand_verify_oob(mtd, oobbuf, to);
if (ret) { if (ret) {
printk(KERN_ERR "onenand_write_oob: verify failed %d\n", ret); printk(KERN_ERR "onenand_write_oob: verify failed %d\n", ret);
break; break;
...@@ -1400,9 +1410,9 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len, ...@@ -1400,9 +1410,9 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
/** /**
* onenand_write_oob - [MTD Interface] NAND write data and/or out-of-band * onenand_write_oob - [MTD Interface] NAND write data and/or out-of-band
* @mtd: MTD device structure * @param mtd: MTD device structure
* @from: offset to read from * @param to: offset to write
* @ops: oob operation description structure * @param ops: oob operation description structure
*/ */
static int onenand_write_oob(struct mtd_info *mtd, loff_t to, static int onenand_write_oob(struct mtd_info *mtd, loff_t to,
struct mtd_oob_ops *ops) struct mtd_oob_ops *ops)
...@@ -1616,6 +1626,7 @@ static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs) ...@@ -1616,6 +1626,7 @@ static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs)
* @param mtd MTD device structure * @param mtd MTD device structure
* @param ofs offset relative to mtd start * @param ofs offset relative to mtd start
* @param len number of bytes to lock or unlock * @param len number of bytes to lock or unlock
* @param cmd lock or unlock command
* *
* Lock or unlock one or more blocks * Lock or unlock one or more blocks
*/ */
...@@ -2117,10 +2128,11 @@ static void onenand_check_features(struct mtd_info *mtd) ...@@ -2117,10 +2128,11 @@ static void onenand_check_features(struct mtd_info *mtd)
} }
/** /**
* onenand_print_device_info - Print device ID * onenand_print_device_info - Print device & version ID
* @param device device ID * @param device device ID
* @param version version ID
* *
* Print device ID * Print device & version ID
*/ */
static void onenand_print_device_info(int device, int version) static void onenand_print_device_info(int device, int version)
{ {
...@@ -2320,15 +2332,25 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) ...@@ -2320,15 +2332,25 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
/* Allocate buffers, if necessary */ /* Allocate buffers, if necessary */
if (!this->page_buf) { if (!this->page_buf) {
size_t len; this->page_buf = kzalloc(mtd->writesize, GFP_KERNEL);
len = mtd->writesize + mtd->oobsize;
this->page_buf = kmalloc(len, GFP_KERNEL);
if (!this->page_buf) { if (!this->page_buf) {
printk(KERN_ERR "onenand_scan(): Can't allocate page_buf\n"); printk(KERN_ERR "onenand_scan(): Can't allocate page_buf\n");
return -ENOMEM; return -ENOMEM;
} }
this->options |= ONENAND_PAGEBUF_ALLOC; 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; this->state = FL_READY;
init_waitqueue_head(&this->wq); init_waitqueue_head(&this->wq);
...@@ -2367,6 +2389,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) ...@@ -2367,6 +2389,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
for (i = 0; this->ecclayout->oobfree[i].length; i++) for (i = 0; this->ecclayout->oobfree[i].length; i++)
this->ecclayout->oobavail += this->ecclayout->oobavail +=
this->ecclayout->oobfree[i].length; this->ecclayout->oobfree[i].length;
mtd->oobavail = this->ecclayout->oobavail;
mtd->ecclayout = this->ecclayout; mtd->ecclayout = this->ecclayout;
...@@ -2424,9 +2447,11 @@ void onenand_release(struct mtd_info *mtd) ...@@ -2424,9 +2447,11 @@ void onenand_release(struct mtd_info *mtd)
kfree(bbm->bbt); kfree(bbm->bbt);
kfree(this->bbm); kfree(this->bbm);
} }
/* Buffer allocated by onenand_scan */ /* Buffers allocated by onenand_scan */
if (this->options & ONENAND_PAGEBUF_ALLOC) if (this->options & ONENAND_PAGEBUF_ALLOC)
kfree(this->page_buf); kfree(this->page_buf);
if (this->options & ONENAND_OOBBUF_ALLOC)
kfree(this->oob_buf);
} }
EXPORT_SYMBOL_GPL(onenand_scan); EXPORT_SYMBOL_GPL(onenand_scan);
......
...@@ -99,7 +99,13 @@ static int jffs2_garbage_collect_thread(void *_c) ...@@ -99,7 +99,13 @@ static int jffs2_garbage_collect_thread(void *_c)
if (try_to_freeze()) if (try_to_freeze())
continue; continue;
cond_resched(); /* This thread is purely an optimisation. But if it runs when
other things could be running, it actually makes things a
lot worse. Use yield() and put it at the back of the runqueue
every time. Especially during boot, pulling an inode in
with read_inode() is much preferable to having the GC thread
get there first. */
yield();
/* Put_super will send a SIGKILL and then wait on the sem. /* Put_super will send a SIGKILL and then wait on the sem.
*/ */
......
...@@ -373,7 +373,14 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref ...@@ -373,7 +373,14 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, struct jffs2_unknown_node *un) static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, struct jffs2_unknown_node *un)
{ {
/* We don't mark unknown nodes as REF_UNCHECKED */ /* We don't mark unknown nodes as REF_UNCHECKED */
BUG_ON(ref_flags(ref) == REF_UNCHECKED); if (ref_flags(ref) == REF_UNCHECKED) {
JFFS2_ERROR("REF_UNCHECKED but unknown node at %#08x\n",
ref_offset(ref));
JFFS2_ERROR("Node is {%04x,%04x,%08x,%08x}. Please report this error.\n",
je16_to_cpu(un->magic), je16_to_cpu(un->nodetype),
je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc));
return 1;
}
un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype)); un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype));
...@@ -576,6 +583,13 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf ...@@ -576,6 +583,13 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
jffs2_mark_node_obsolete(c, ref); jffs2_mark_node_obsolete(c, ref);
goto cont; goto cont;
} }
/* Due to poor choice of crc32 seed, an all-zero node will have a correct CRC */
if (!je32_to_cpu(node->u.hdr_crc) && !je16_to_cpu(node->u.nodetype) &&
!je16_to_cpu(node->u.magic) && !je32_to_cpu(node->u.totlen)) {
JFFS2_NOTICE("All zero node header at %#08x.\n", ref_offset(ref));
jffs2_mark_node_obsolete(c, ref);
goto cont;
}
switch (je16_to_cpu(node->u.nodetype)) { switch (je16_to_cpu(node->u.nodetype)) {
......
...@@ -734,6 +734,15 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo ...@@ -734,6 +734,15 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
ofs += 4; ofs += 4;
continue; continue;
} }
/* Due to poor choice of crc32 seed, an all-zero node will have a correct CRC */
if (!je32_to_cpu(node->hdr_crc) && !je16_to_cpu(node->nodetype) &&
!je16_to_cpu(node->magic) && !je32_to_cpu(node->totlen)) {
noisy_printk(&noise, "jffs2_scan_eraseblock(): All zero node header at 0x%08x.\n", ofs);
if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
return err;
ofs += 4;
continue;
}
if (ofs + je32_to_cpu(node->totlen) > if (ofs + je32_to_cpu(node->totlen) >
jeb->offset + c->sector_size) { jeb->offset + c->sector_size) {
......
...@@ -238,7 +238,10 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) ...@@ -238,7 +238,10 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; jeb = &c->blocks[c->wbuf_ofs / c->sector_size];
spin_lock(&c->erase_completion_lock); spin_lock(&c->erase_completion_lock);
jffs2_block_refile(c, jeb, REFILE_NOTEMPTY); if (c->wbuf_ofs % c->mtd->erasesize)
jffs2_block_refile(c, jeb, REFILE_NOTEMPTY);
else
jffs2_block_refile(c, jeb, REFILE_ANYWAY);
spin_unlock(&c->erase_completion_lock); spin_unlock(&c->erase_completion_lock);
BUG_ON(!ref_obsolete(jeb->last_node)); BUG_ON(!ref_obsolete(jeb->last_node));
...@@ -1087,7 +1090,7 @@ int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock * ...@@ -1087,7 +1090,7 @@ int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *
if (!c->mtd->block_markbad) if (!c->mtd->block_markbad)
return 1; // What else can we do? return 1; // What else can we do?
D1(printk(KERN_WARNING "jffs2_write_nand_badblock(): Marking bad block at %08x\n", bad_offset)); printk(KERN_WARNING "JFFS2: marking eraseblock at %08x\n as bad", bad_offset);
ret = c->mtd->block_markbad(c->mtd, bad_offset); ret = c->mtd->block_markbad(c->mtd, bad_offset);
if (ret) { if (ret) {
......
...@@ -121,6 +121,7 @@ struct mtd_info { ...@@ -121,6 +121,7 @@ struct mtd_info {
u_int32_t writesize; u_int32_t writesize;
u_int32_t oobsize; // Amount of OOB data per block (e.g. 16) u_int32_t oobsize; // Amount of OOB data per block (e.g. 16)
u_int32_t oobavail; // Available OOB bytes per block
// Kernel-only stuff starts here. // Kernel-only stuff starts here.
char *name; char *name;
......
...@@ -82,7 +82,8 @@ struct onenand_bufferram { ...@@ -82,7 +82,8 @@ struct onenand_bufferram {
* @wq: [INTERN] wait queue to sleep on if a OneNAND * @wq: [INTERN] wait queue to sleep on if a OneNAND
* operation is in progress * operation is in progress
* @state: [INTERN] the current state of the OneNAND device * @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 * @subpagesize: [INTERN] holds the subpagesize
* @ecclayout: [REPLACEABLE] the default ecc placement scheme * @ecclayout: [REPLACEABLE] the default ecc placement scheme
* @bbm: [REPLACEABLE] pointer to Bad Block Management * @bbm: [REPLACEABLE] pointer to Bad Block Management
...@@ -122,6 +123,7 @@ struct onenand_chip { ...@@ -122,6 +123,7 @@ struct onenand_chip {
wait_queue_head_t wq; wait_queue_head_t wq;
onenand_state_t state; onenand_state_t state;
unsigned char *page_buf; unsigned char *page_buf;
unsigned char *oob_buf;
int subpagesize; int subpagesize;
struct nand_ecclayout *ecclayout; struct nand_ecclayout *ecclayout;
...@@ -156,6 +158,7 @@ struct onenand_chip { ...@@ -156,6 +158,7 @@ struct onenand_chip {
#define ONENAND_HAS_CONT_LOCK (0x0001) #define ONENAND_HAS_CONT_LOCK (0x0001)
#define ONENAND_HAS_UNLOCK_ALL (0x0002) #define ONENAND_HAS_UNLOCK_ALL (0x0002)
#define ONENAND_PAGEBUF_ALLOC (0x1000) #define ONENAND_PAGEBUF_ALLOC (0x1000)
#define ONENAND_OOBBUF_ALLOC (0x2000)
/* /*
* OneNAND Flash Manufacturer ID Codes * OneNAND Flash Manufacturer ID Codes
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment