Commit 35f95d22 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 5e351cdc 85146244
...@@ -240,7 +240,7 @@ static int parse_cmdline(char *devname, char *szstart, char *szlength) ...@@ -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;
......
...@@ -2983,13 +2983,15 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -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;
......
...@@ -121,7 +121,7 @@ static int parse_ofoldpart_partitions(struct mtd_info *master, ...@@ -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);
......
...@@ -3694,7 +3694,7 @@ static int flexonenand_check_blocks_erased(struct mtd_info *mtd, int start, int ...@@ -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;
......
...@@ -138,33 +138,39 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, ...@@ -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;
jffs2_dbg(1, "%s()\n", __func__);
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); pg = grab_cache_page_write_begin(mapping, index, flags);
if (!pg) if (!pg) {
if (alloc_len)
jffs2_complete_reservation(c);
mutex_unlock(&f->sem);
return -ENOMEM; return -ENOMEM;
}
*pagep = pg; *pagep = pg;
jffs2_dbg(1, "%s()\n", __func__); if (alloc_len) {
if (pageofs > inode->i_size) {
/* 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, ...@@ -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, ...@@ -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, ...@@ -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;
} }
......
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