summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-02-26 23:45:57 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2009-02-26 23:45:57 +0100
commit221be177e68e197a946bb991c8b91468e960be4e (patch)
treef77313df6358700d58cc7921551400170a8f6700
parentMerge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/gi... (diff)
parent[MTD] [MAPS] Remove MODULE_DEVICE_TABLE() from ck804rom driver. (diff)
downloadlinux-221be177e68e197a946bb991c8b91468e960be4e.tar.xz
linux-221be177e68e197a946bb991c8b91468e960be4e.zip
Merge git://git.infradead.org/mtd-2.6
* git://git.infradead.org/mtd-2.6: [MTD] [MAPS] Remove MODULE_DEVICE_TABLE() from ck804rom driver. [JFFS2] fix mount crash caused by removed nodes [JFFS2] force the jffs2 GC daemon to behave a bit better [MTD] [MAPS] blackfin async requires complex mappings [MTD] [MAPS] blackfin: fix memory leak in error path [MTD] [MAPS] physmap: fix wrong free and del_mtd_{partition,device} [MTD] slram: Handle negative devlength correctly [MTD] map_rom has NULL erase pointer [MTD] [LPDDR] qinfo_probe depends on lpddr
-rw-r--r--drivers/mtd/chips/map_rom.c8
-rw-r--r--drivers/mtd/devices/slram.c14
-rw-r--r--drivers/mtd/lpddr/Kconfig1
-rw-r--r--drivers/mtd/maps/Kconfig2
-rw-r--r--drivers/mtd/maps/bfin-async-flash.c6
-rw-r--r--drivers/mtd/maps/ck804xrom.c2
-rw-r--r--drivers/mtd/maps/physmap.c38
-rw-r--r--fs/jffs2/background.c18
-rw-r--r--fs/jffs2/readinode.c42
9 files changed, 89 insertions, 42 deletions
diff --git a/drivers/mtd/chips/map_rom.c b/drivers/mtd/chips/map_rom.c
index 821d0ed6bae3..c76d6e5f47ee 100644
--- a/drivers/mtd/chips/map_rom.c
+++ b/drivers/mtd/chips/map_rom.c
@@ -19,6 +19,7 @@ static int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
static void maprom_nop (struct mtd_info *);
static struct mtd_info *map_rom_probe(struct map_info *map);
+static int maprom_erase (struct mtd_info *mtd, struct erase_info *info);
static struct mtd_chip_driver maprom_chipdrv = {
.probe = map_rom_probe,
@@ -42,6 +43,7 @@ static struct mtd_info *map_rom_probe(struct map_info *map)
mtd->read = maprom_read;
mtd->write = maprom_write;
mtd->sync = maprom_nop;
+ mtd->erase = maprom_erase;
mtd->flags = MTD_CAP_ROM;
mtd->erasesize = map->size;
mtd->writesize = 1;
@@ -71,6 +73,12 @@ static int maprom_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *re
return -EIO;
}
+static int maprom_erase (struct mtd_info *mtd, struct erase_info *info)
+{
+ /* We do our best 8) */
+ return -EROFS;
+}
+
static int __init map_rom_init(void)
{
register_mtd_chip_driver(&maprom_chipdrv);
diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c
index a425d09f35a0..00248e81ecd5 100644
--- a/drivers/mtd/devices/slram.c
+++ b/drivers/mtd/devices/slram.c
@@ -267,22 +267,28 @@ static int parse_cmdline(char *devname, char *szstart, char *szlength)
if (*(szlength) != '+') {
devlength = simple_strtoul(szlength, &buffer, 0);
devlength = handle_unit(devlength, buffer) - devstart;
+ if (devlength < devstart)
+ goto err_out;
+
+ devlength -= devstart;
} else {
devlength = simple_strtoul(szlength + 1, &buffer, 0);
devlength = handle_unit(devlength, buffer);
}
T("slram: devname=%s, devstart=0x%lx, devlength=0x%lx\n",
devname, devstart, devlength);
- if ((devstart < 0) || (devlength < 0) || (devlength % SLRAM_BLK_SZ != 0)) {
- E("slram: Illegal start / length parameter.\n");
- return(-EINVAL);
- }
+ if (devlength % SLRAM_BLK_SZ != 0)
+ goto err_out;
if ((devstart = register_device(devname, devstart, devlength))){
unregister_devices();
return((int)devstart);
}
return(0);
+
+err_out:
+ E("slram: Illegal length parameter.\n");
+ return(-EINVAL);
}
#ifndef MODULE
diff --git a/drivers/mtd/lpddr/Kconfig b/drivers/mtd/lpddr/Kconfig
index acd4ea9b2278..5a401d8047ab 100644
--- a/drivers/mtd/lpddr/Kconfig
+++ b/drivers/mtd/lpddr/Kconfig
@@ -12,6 +12,7 @@ config MTD_LPDDR
DDR memories, intended for battery-operated systems.
config MTD_QINFO_PROBE
+ depends on MTD_LPDDR
tristate "Detect flash chips by QINFO probe"
help
Device Information for LPDDR chips is offered through the Overlay
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 0225cbbf22de..043d50fb6ef6 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -491,7 +491,7 @@ config MTD_PCMCIA_ANONYMOUS
config MTD_BFIN_ASYNC
tristate "Blackfin BF533-STAMP Flash Chip Support"
- depends on BFIN533_STAMP && MTD_CFI
+ depends on BFIN533_STAMP && MTD_CFI && MTD_COMPLEX_MAPPINGS
select MTD_PARTITIONS
default y
help
diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c
index 6fec86aaed7e..576611f605db 100644
--- a/drivers/mtd/maps/bfin-async-flash.c
+++ b/drivers/mtd/maps/bfin-async-flash.c
@@ -152,14 +152,18 @@ static int __devinit bfin_flash_probe(struct platform_device *pdev)
if (gpio_request(state->enet_flash_pin, DRIVER_NAME)) {
pr_devinit(KERN_ERR DRIVER_NAME ": Failed to request gpio %d\n", state->enet_flash_pin);
+ kfree(state);
return -EBUSY;
}
gpio_direction_output(state->enet_flash_pin, 1);
pr_devinit(KERN_NOTICE DRIVER_NAME ": probing %d-bit flash bus\n", state->map.bankwidth * 8);
state->mtd = do_map_probe(memory->name, &state->map);
- if (!state->mtd)
+ if (!state->mtd) {
+ gpio_free(state->enet_flash_pin);
+ kfree(state);
return -ENXIO;
+ }
#ifdef CONFIG_MTD_PARTITIONS
ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0);
diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c
index 5f7a245ed132..424f17d6ffd1 100644
--- a/drivers/mtd/maps/ck804xrom.c
+++ b/drivers/mtd/maps/ck804xrom.c
@@ -342,9 +342,9 @@ static struct pci_device_id ck804xrom_pci_tbl[] = {
{ 0, }
};
+#if 0
MODULE_DEVICE_TABLE(pci, ck804xrom_pci_tbl);
-#if 0
static struct pci_driver ck804xrom_driver = {
.name = MOD_NAME,
.id_table = ck804xrom_pci_tbl,
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index 87743661d48e..4b122e7ab4b3 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -29,6 +29,7 @@ struct physmap_flash_info {
struct map_info map[MAX_RESOURCES];
#ifdef CONFIG_MTD_PARTITIONS
int nr_parts;
+ struct mtd_partition *parts;
#endif
};
@@ -45,25 +46,26 @@ static int physmap_flash_remove(struct platform_device *dev)
physmap_data = dev->dev.platform_data;
-#ifdef CONFIG_MTD_CONCAT
- if (info->cmtd != info->mtd[0]) {
+#ifdef CONFIG_MTD_PARTITIONS
+ if (info->nr_parts) {
+ del_mtd_partitions(info->cmtd);
+ kfree(info->parts);
+ } else if (physmap_data->nr_parts)
+ del_mtd_partitions(info->cmtd);
+ else
del_mtd_device(info->cmtd);
+#else
+ del_mtd_device(info->cmtd);
+#endif
+
+#ifdef CONFIG_MTD_CONCAT
+ if (info->cmtd != info->mtd[0])
mtd_concat_destroy(info->cmtd);
- }
#endif
for (i = 0; i < MAX_RESOURCES; i++) {
- if (info->mtd[i] != NULL) {
-#ifdef CONFIG_MTD_PARTITIONS
- if (info->nr_parts || physmap_data->nr_parts)
- del_mtd_partitions(info->mtd[i]);
- else
- del_mtd_device(info->mtd[i]);
-#else
- del_mtd_device(info->mtd[i]);
-#endif
+ if (info->mtd[i] != NULL)
map_destroy(info->mtd[i]);
- }
}
return 0;
}
@@ -86,9 +88,6 @@ static int physmap_flash_probe(struct platform_device *dev)
int err = 0;
int i;
int devices_found = 0;
-#ifdef CONFIG_MTD_PARTITIONS
- struct mtd_partition *parts;
-#endif
physmap_data = dev->dev.platform_data;
if (physmap_data == NULL)
@@ -167,10 +166,11 @@ static int physmap_flash_probe(struct platform_device *dev)
goto err_out;
#ifdef CONFIG_MTD_PARTITIONS
- err = parse_mtd_partitions(info->cmtd, part_probe_types, &parts, 0);
+ err = parse_mtd_partitions(info->cmtd, part_probe_types,
+ &info->parts, 0);
if (err > 0) {
- add_mtd_partitions(info->cmtd, parts, err);
- kfree(parts);
+ add_mtd_partitions(info->cmtd, info->parts, err);
+ info->nr_parts = err;
return 0;
}
diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c
index 3cceef4ad2b7..e9580104b6ba 100644
--- a/fs/jffs2/background.c
+++ b/fs/jffs2/background.c
@@ -95,13 +95,17 @@ static int jffs2_garbage_collect_thread(void *_c)
spin_unlock(&c->erase_completion_lock);
- /* 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();
+ /* Problem - immediately after bootup, the GCD spends a lot
+ * of time in places like jffs2_kill_fragtree(); so much so
+ * that userspace processes (like gdm and X) are starved
+ * despite plenty of cond_resched()s and renicing. Yield()
+ * doesn't help, either (presumably because userspace and GCD
+ * are generally competing for a higher latency resource -
+ * disk).
+ * This forces the GCD to slow the hell down. Pulling an
+ * inode in with read_inode() is much preferable to having
+ * the GC thread get there first. */
+ schedule_timeout_interruptible(msecs_to_jiffies(50));
/* Put_super will send a SIGKILL and then wait on the sem.
*/
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 6ca08ad887c0..1fc1e92356ee 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -220,7 +220,7 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
struct jffs2_tmp_dnode_info *tn)
{
uint32_t fn_end = tn->fn->ofs + tn->fn->size;
- struct jffs2_tmp_dnode_info *this;
+ struct jffs2_tmp_dnode_info *this, *ptn;
dbg_readinode("insert fragment %#04x-%#04x, ver %u at %08x\n", tn->fn->ofs, fn_end, tn->version, ref_offset(tn->fn->raw));
@@ -251,11 +251,18 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
if (this) {
/* If the node is coincident with another at a lower address,
back up until the other node is found. It may be relevant */
- while (this->overlapped)
- this = tn_prev(this);
-
- /* First node should never be marked overlapped */
- BUG_ON(!this);
+ while (this->overlapped) {
+ ptn = tn_prev(this);
+ if (!ptn) {
+ /*
+ * We killed a node which set the overlapped
+ * flags during the scan. Fix it up.
+ */
+ this->overlapped = 0;
+ break;
+ }
+ this = ptn;
+ }
dbg_readinode("'this' found %#04x-%#04x (%s)\n", this->fn->ofs, this->fn->ofs + this->fn->size, this->fn ? "data" : "hole");
}
@@ -360,7 +367,17 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
}
if (!this->overlapped)
break;
- this = tn_prev(this);
+
+ ptn = tn_prev(this);
+ if (!ptn) {
+ /*
+ * We killed a node which set the overlapped
+ * flags during the scan. Fix it up.
+ */
+ this->overlapped = 0;
+ break;
+ }
+ this = ptn;
}
}
@@ -456,8 +473,15 @@ static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c,
eat_last(&rii->tn_root, &last->rb);
ver_insert(&ver_root, last);
- if (unlikely(last->overlapped))
- continue;
+ if (unlikely(last->overlapped)) {
+ if (pen)
+ continue;
+ /*
+ * We killed a node which set the overlapped
+ * flags during the scan. Fix it up.
+ */
+ last->overlapped = 0;
+ }
/* Now we have a bunch of nodes in reverse version
order, in the tree at ver_root. Most of the time,