Most important part of this is that it fixes a regression in Samsung

NAND chip detection, introduced by some rework which went into 3.7. The
 initial fix wasn't quite complete, so it's in two parts. In fact the
 first part is committed twice (Artem committed his own copy of the same
 patch) and I've merged Artem's tree into mine which already had that fix.
 
 I'd have recommitted that to make it somewhat cleaner, but figured by
 this point in the release cycle it was better to merge *exactly* the
 commits which have been in linux-next.
 
 If I'd recommitted, I'd also omit the sparse warning fix. But it's there,
 and it's harmless — just marking one function as 'static' in onenand code.
 
 This also includes a couple more fixes for stable: an AB-BA deadlock in
 JFFS2, and an invalid range check in slram.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.12 (GNU/Linux)
 
 iEYEABECAAYFAlCwEIsACgkQdwG7hYl686NfZgCfSYFA2q8yp7jEMdDaxpFPuuDm
 FFMAoI3V27BpWxRab6GylYh8erHp9ful
 =Wo+T
 -----END PGP SIGNATURE-----

Merge tag 'for-linus-20121123' of git://git.infradead.org/mtd-2.6

Pull MTD fixes from David Woodhouse:
 "The most important part of this is that it fixes a regression in
  Samsung NAND chip detection, introduced by some rework which went into
  3.7.  The initial fix wasn't quite complete, so it's in two parts.  In
  fact the first part is committed twice (Artem committed his own copy
  of the same patch) and I've merged Artem's tree into mine which
  already had that fix.

  I'd have recommitted that to make it somewhat cleaner, but figured by
  this point in the release cycle it was better to merge *exactly* the
  commits which have been in linux-next.

  If I'd recommitted, I'd also omit the sparse warning fix.  But it's
  there, and it's harmless — just marking one function as 'static' in
  onenand code.

  This also includes a couple more fixes for stable: an AB-BA deadlock
  in JFFS2, and an invalid range check in slram."

* tag 'for-linus-20121123' of git://git.infradead.org/mtd-2.6:
  mtd: nand: fix Samsung SLC detection regression
  mtd: nand: fix Samsung SLC NAND identification regression
  jffs2: Fix lock acquisition order bug in jffs2_write_begin
  mtd: onenand: Make flexonenand_set_boundary static
  mtd: slram: invalid checking of absolute end address
  mtd: ofpart: Fix incorrect NULL check in parse_ofoldpart_partitions()
  mtd: nand: fix Samsung SLC NAND identification regression
This commit is contained in:
Linus Torvalds 2012-11-23 15:12:17 -10:00
commit 35f95d228e
5 changed files with 31 additions and 26 deletions

View File

@ -240,7 +240,7 @@ static int parse_cmdline(char *devname, char *szstart, char *szlength)
if (*(szlength) != '+') { if (*(szlength) != '+') {
devlength = simple_strtoul(szlength, &buffer, 0); devlength = simple_strtoul(szlength, &buffer, 0);
devlength = handle_unit(devlength, buffer) - devstart; devlength = handle_unit(devlength, buffer);
if (devlength < devstart) if (devlength < devstart)
goto err_out; goto err_out;

View File

@ -2983,13 +2983,15 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
/* /*
* Field definitions are in the following datasheets: * Field definitions are in the following datasheets:
* Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32) * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32)
* New style (6 byte ID): Samsung K9GAG08U0F (p.44) * New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44)
* Hynix MLC (6 byte ID): Hynix H27UBG8T2B (p.22) * Hynix MLC (6 byte ID): Hynix H27UBG8T2B (p.22)
* *
* Check for ID length, cell type, and Hynix/Samsung ID to decide what * Check for ID length, non-zero 6th byte, cell type, and Hynix/Samsung
* to do. * ID to decide what to do.
*/ */
if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG) { if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG &&
(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
id_data[5] != 0x00) {
/* Calc pagesize */ /* Calc pagesize */
mtd->writesize = 2048 << (extid & 0x03); mtd->writesize = 2048 << (extid & 0x03);
extid >>= 2; extid >>= 2;

View File

@ -121,7 +121,7 @@ static int parse_ofoldpart_partitions(struct mtd_info *master,
nr_parts = plen / sizeof(part[0]); nr_parts = plen / sizeof(part[0]);
*pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL); *pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL);
if (!pparts) if (!*pparts)
return -ENOMEM; return -ENOMEM;
names = of_get_property(dp, "partition-names", &plen); names = of_get_property(dp, "partition-names", &plen);

View File

@ -3694,7 +3694,7 @@ static int flexonenand_check_blocks_erased(struct mtd_info *mtd, int start, int
* flexonenand_set_boundary - Writes the SLC boundary * flexonenand_set_boundary - Writes the SLC boundary
* @param mtd - mtd info structure * @param mtd - mtd info structure
*/ */
int flexonenand_set_boundary(struct mtd_info *mtd, int die, static int flexonenand_set_boundary(struct mtd_info *mtd, int die,
int boundary, int lock) int boundary, int lock)
{ {
struct onenand_chip *this = mtd->priv; struct onenand_chip *this = mtd->priv;

View File

@ -138,33 +138,39 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
struct page *pg; struct page *pg;
struct inode *inode = mapping->host; struct inode *inode = mapping->host;
struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
struct jffs2_raw_inode ri;
uint32_t alloc_len = 0;
pgoff_t index = pos >> PAGE_CACHE_SHIFT; pgoff_t index = pos >> PAGE_CACHE_SHIFT;
uint32_t pageofs = index << PAGE_CACHE_SHIFT; uint32_t pageofs = index << PAGE_CACHE_SHIFT;
int ret = 0; int ret = 0;
pg = grab_cache_page_write_begin(mapping, index, flags);
if (!pg)
return -ENOMEM;
*pagep = pg;
jffs2_dbg(1, "%s()\n", __func__); jffs2_dbg(1, "%s()\n", __func__);
if (pageofs > inode->i_size) { if (pageofs > inode->i_size) {
ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
if (ret)
return ret;
}
mutex_lock(&f->sem);
pg = grab_cache_page_write_begin(mapping, index, flags);
if (!pg) {
if (alloc_len)
jffs2_complete_reservation(c);
mutex_unlock(&f->sem);
return -ENOMEM;
}
*pagep = pg;
if (alloc_len) {
/* Make new hole frag from old EOF to new page */ /* Make new hole frag from old EOF to new page */
struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
struct jffs2_raw_inode ri;
struct jffs2_full_dnode *fn; struct jffs2_full_dnode *fn;
uint32_t alloc_len;
jffs2_dbg(1, "Writing new hole frag 0x%x-0x%x between current EOF and new page\n", jffs2_dbg(1, "Writing new hole frag 0x%x-0x%x between current EOF and new page\n",
(unsigned int)inode->i_size, pageofs); (unsigned int)inode->i_size, pageofs);
ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
if (ret)
goto out_page;
mutex_lock(&f->sem);
memset(&ri, 0, sizeof(ri)); memset(&ri, 0, sizeof(ri));
ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@ -191,7 +197,6 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
if (IS_ERR(fn)) { if (IS_ERR(fn)) {
ret = PTR_ERR(fn); ret = PTR_ERR(fn);
jffs2_complete_reservation(c); jffs2_complete_reservation(c);
mutex_unlock(&f->sem);
goto out_page; goto out_page;
} }
ret = jffs2_add_full_dnode_to_inode(c, f, fn); ret = jffs2_add_full_dnode_to_inode(c, f, fn);
@ -206,12 +211,10 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
jffs2_mark_node_obsolete(c, fn->raw); jffs2_mark_node_obsolete(c, fn->raw);
jffs2_free_full_dnode(fn); jffs2_free_full_dnode(fn);
jffs2_complete_reservation(c); jffs2_complete_reservation(c);
mutex_unlock(&f->sem);
goto out_page; goto out_page;
} }
jffs2_complete_reservation(c); jffs2_complete_reservation(c);
inode->i_size = pageofs; inode->i_size = pageofs;
mutex_unlock(&f->sem);
} }
/* /*
@ -220,18 +223,18 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
* case of a short-copy. * case of a short-copy.
*/ */
if (!PageUptodate(pg)) { if (!PageUptodate(pg)) {
mutex_lock(&f->sem);
ret = jffs2_do_readpage_nolock(inode, pg); ret = jffs2_do_readpage_nolock(inode, pg);
mutex_unlock(&f->sem);
if (ret) if (ret)
goto out_page; goto out_page;
} }
mutex_unlock(&f->sem);
jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags); jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags);
return ret; return ret;
out_page: out_page:
unlock_page(pg); unlock_page(pg);
page_cache_release(pg); page_cache_release(pg);
mutex_unlock(&f->sem);
return ret; return ret;
} }