Browse Source

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
Linus Torvalds 16 years ago
parent
commit
221be177e6

+ 8 - 0
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 int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
 static void maprom_nop (struct mtd_info *);
 static void maprom_nop (struct mtd_info *);
 static struct mtd_info *map_rom_probe(struct map_info *map);
 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 = {
 static struct mtd_chip_driver maprom_chipdrv = {
 	.probe	= map_rom_probe,
 	.probe	= map_rom_probe,
@@ -42,6 +43,7 @@ static struct mtd_info *map_rom_probe(struct map_info *map)
 	mtd->read = maprom_read;
 	mtd->read = maprom_read;
 	mtd->write = maprom_write;
 	mtd->write = maprom_write;
 	mtd->sync = maprom_nop;
 	mtd->sync = maprom_nop;
+	mtd->erase = maprom_erase;
 	mtd->flags = MTD_CAP_ROM;
 	mtd->flags = MTD_CAP_ROM;
 	mtd->erasesize = map->size;
 	mtd->erasesize = map->size;
 	mtd->writesize = 1;
 	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;
 	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)
 static int __init map_rom_init(void)
 {
 {
 	register_mtd_chip_driver(&maprom_chipdrv);
 	register_mtd_chip_driver(&maprom_chipdrv);

+ 10 - 4
drivers/mtd/devices/slram.c

@@ -267,22 +267,28 @@ 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) - devstart;
+		if (devlength < devstart)
+			goto err_out;
+
+		devlength -= devstart;
 	} else {
 	} else {
 		devlength = simple_strtoul(szlength + 1, &buffer, 0);
 		devlength = simple_strtoul(szlength + 1, &buffer, 0);
 		devlength = handle_unit(devlength, buffer);
 		devlength = handle_unit(devlength, buffer);
 	}
 	}
 	T("slram: devname=%s, devstart=0x%lx, devlength=0x%lx\n",
 	T("slram: devname=%s, devstart=0x%lx, devlength=0x%lx\n",
 			devname, devstart, devlength);
 			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))){
 	if ((devstart = register_device(devname, devstart, devlength))){
 		unregister_devices();
 		unregister_devices();
 		return((int)devstart);
 		return((int)devstart);
 	}
 	}
 	return(0);
 	return(0);
+
+err_out:
+	E("slram: Illegal length parameter.\n");
+	return(-EINVAL);
 }
 }
 
 
 #ifndef MODULE
 #ifndef MODULE

+ 1 - 0
drivers/mtd/lpddr/Kconfig

@@ -12,6 +12,7 @@ config MTD_LPDDR
 	  DDR memories, intended for battery-operated systems.
 	  DDR memories, intended for battery-operated systems.
 
 
 config MTD_QINFO_PROBE
 config MTD_QINFO_PROBE
+	depends on MTD_LPDDR
 	tristate "Detect flash chips by QINFO probe"
 	tristate "Detect flash chips by QINFO probe"
 	help
 	help
 	    Device Information for LPDDR chips is offered through the Overlay
 	    Device Information for LPDDR chips is offered through the Overlay

+ 1 - 1
drivers/mtd/maps/Kconfig

@@ -491,7 +491,7 @@ config MTD_PCMCIA_ANONYMOUS
 
 
 config MTD_BFIN_ASYNC
 config MTD_BFIN_ASYNC
 	tristate "Blackfin BF533-STAMP Flash Chip Support"
 	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
 	select MTD_PARTITIONS
 	default y
 	default y
 	help
 	help

+ 5 - 1
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)) {
 	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);
 		pr_devinit(KERN_ERR DRIVER_NAME ": Failed to request gpio %d\n", state->enet_flash_pin);
+		kfree(state);
 		return -EBUSY;
 		return -EBUSY;
 	}
 	}
 	gpio_direction_output(state->enet_flash_pin, 1);
 	gpio_direction_output(state->enet_flash_pin, 1);
 
 
 	pr_devinit(KERN_NOTICE DRIVER_NAME ": probing %d-bit flash bus\n", state->map.bankwidth * 8);
 	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);
 	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;
 		return -ENXIO;
+	}
 
 
 #ifdef CONFIG_MTD_PARTITIONS
 #ifdef CONFIG_MTD_PARTITIONS
 	ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0);
 	ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0);

+ 1 - 1
drivers/mtd/maps/ck804xrom.c

@@ -342,9 +342,9 @@ static struct pci_device_id ck804xrom_pci_tbl[] = {
 	{ 0, }
 	{ 0, }
 };
 };
 
 
+#if 0
 MODULE_DEVICE_TABLE(pci, ck804xrom_pci_tbl);
 MODULE_DEVICE_TABLE(pci, ck804xrom_pci_tbl);
 
 
-#if 0
 static struct pci_driver ck804xrom_driver = {
 static struct pci_driver ck804xrom_driver = {
 	.name =		MOD_NAME,
 	.name =		MOD_NAME,
 	.id_table =	ck804xrom_pci_tbl,
 	.id_table =	ck804xrom_pci_tbl,

+ 19 - 19
drivers/mtd/maps/physmap.c

@@ -29,6 +29,7 @@ struct physmap_flash_info {
 	struct map_info		map[MAX_RESOURCES];
 	struct map_info		map[MAX_RESOURCES];
 #ifdef CONFIG_MTD_PARTITIONS
 #ifdef CONFIG_MTD_PARTITIONS
 	int			nr_parts;
 	int			nr_parts;
+	struct mtd_partition	*parts;
 #endif
 #endif
 };
 };
 
 
@@ -45,25 +46,26 @@ static int physmap_flash_remove(struct platform_device *dev)
 
 
 	physmap_data = dev->dev.platform_data;
 	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);
 		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);
 		mtd_concat_destroy(info->cmtd);
-	}
 #endif
 #endif
 
 
 	for (i = 0; i < MAX_RESOURCES; i++) {
 	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]);
 			map_destroy(info->mtd[i]);
-		}
 	}
 	}
 	return 0;
 	return 0;
 }
 }
@@ -86,9 +88,6 @@ static int physmap_flash_probe(struct platform_device *dev)
 	int err = 0;
 	int err = 0;
 	int i;
 	int i;
 	int devices_found = 0;
 	int devices_found = 0;
-#ifdef CONFIG_MTD_PARTITIONS
-	struct mtd_partition *parts;
-#endif
 
 
 	physmap_data = dev->dev.platform_data;
 	physmap_data = dev->dev.platform_data;
 	if (physmap_data == NULL)
 	if (physmap_data == NULL)
@@ -167,10 +166,11 @@ static int physmap_flash_probe(struct platform_device *dev)
 		goto err_out;
 		goto err_out;
 
 
 #ifdef CONFIG_MTD_PARTITIONS
 #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) {
 	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;
 		return 0;
 	}
 	}
 
 

+ 11 - 7
fs/jffs2/background.c

@@ -95,13 +95,17 @@ static int jffs2_garbage_collect_thread(void *_c)
 			spin_unlock(&c->erase_completion_lock);
 			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.
 		/* Put_super will send a SIGKILL and then wait on the sem.
 		 */
 		 */

+ 33 - 9
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)
 				struct jffs2_tmp_dnode_info *tn)
 {
 {
 	uint32_t fn_end = tn->fn->ofs + tn->fn->size;
 	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));
 	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 (this) {
 		/* If the node is coincident with another at a lower address,
 		/* If the node is coincident with another at a lower address,
 		   back up until the other node is found. It may be relevant */
 		   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");
 		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)
 			if (!this->overlapped)
 				break;
 				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);
 		eat_last(&rii->tn_root, &last->rb);
 		ver_insert(&ver_root, last);
 		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
 		/* Now we have a bunch of nodes in reverse version
 		   order, in the tree at ver_root. Most of the time,
 		   order, in the tree at ver_root. Most of the time,