Commit 221be177 authored by Linus Torvalds's avatar Linus Torvalds

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
parents d4998115 b50be33e
...@@ -19,6 +19,7 @@ static int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); ...@@ -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) ...@@ -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 ...@@ -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);
......
...@@ -267,22 +267,28 @@ static int parse_cmdline(char *devname, char *szstart, char *szlength) ...@@ -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)) { if (devlength % SLRAM_BLK_SZ != 0)
E("slram: Illegal start / length parameter.\n"); goto err_out;
return(-EINVAL);
}
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
......
...@@ -12,6 +12,7 @@ config MTD_LPDDR ...@@ -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
......
...@@ -491,7 +491,7 @@ config MTD_PCMCIA_ANONYMOUS ...@@ -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
......
...@@ -152,14 +152,18 @@ static int __devinit bfin_flash_probe(struct platform_device *pdev) ...@@ -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);
......
...@@ -342,9 +342,9 @@ static struct pci_device_id ck804xrom_pci_tbl[] = { ...@@ -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,
......
...@@ -29,6 +29,7 @@ struct physmap_flash_info { ...@@ -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) ...@@ -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 #ifdef CONFIG_MTD_PARTITIONS
if (info->cmtd != info->mtd[0]) { 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) { 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
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) ...@@ -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) ...@@ -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); add_mtd_partitions(info->cmtd, info->parts, err);
kfree(parts); info->nr_parts = err;
return 0; return 0;
} }
......
...@@ -95,13 +95,17 @@ static int jffs2_garbage_collect_thread(void *_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 /* Problem - immediately after bootup, the GCD spends a lot
other things could be running, it actually makes things a * of time in places like jffs2_kill_fragtree(); so much so
lot worse. Use yield() and put it at the back of the runqueue * that userspace processes (like gdm and X) are starved
every time. Especially during boot, pulling an inode in * despite plenty of cond_resched()s and renicing. Yield()
with read_inode() is much preferable to having the GC thread * doesn't help, either (presumably because userspace and GCD
get there first. */ * are generally competing for a higher latency resource -
yield(); * 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.
*/ */
......
...@@ -220,7 +220,7 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *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, ...@@ -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) while (this->overlapped) {
this = tn_prev(this); ptn = tn_prev(this);
if (!ptn) {
/* First node should never be marked overlapped */ /*
BUG_ON(!this); * 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, ...@@ -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, ...@@ -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)) if (unlikely(last->overlapped)) {
continue; 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,
......
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