From: David Woodhouse Date: Sat, 30 Oct 2010 11:35:11 +0000 (+0100) Subject: Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux... X-Git-Tag: v2.6.37-rc1~22^2~2 X-Git-Url: http://bbs.cooldavid.org/git/?a=commitdiff_plain;h=67577927e8d7a1f4b09b4992df640eadc6aacb36;hp=-c;p=net-next-2.6.git Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git Conflicts: drivers/mtd/mtd_blkdevs.c Merge Grant's device-tree bits so that we can apply the subsequent fixes. Signed-off-by: David Woodhouse --- 67577927e8d7a1f4b09b4992df640eadc6aacb36 diff --combined arch/powerpc/Kconfig index 44df1bac970,4b1e521d966..29158913a66 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@@ -138,6 -138,7 +138,7 @@@ config PP select HAVE_OPROFILE select HAVE_SYSCALL_WRAPPERS if PPC64 select GENERIC_ATOMIC64 if PPC32 + select HAVE_IRQ_WORK select HAVE_PERF_EVENTS select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_HW_BREAKPOINT if PERF_EVENTS && PPC_BOOK3S_64 @@@ -687,12 -688,9 +688,12 @@@ config 4xx_SO bool config FSL_LBC - bool + bool "Freescale Local Bus support" + depends on FSL_SOC help - Freescale Localbus support + Enables reporting of errors from the Freescale local bus + controller. Also contains some common code used by + drivers for specific local bus peripherals. config FSL_GTM bool diff --combined drivers/mtd/chips/cfi_cmdset_0002.c index 288fc2ea849,ba29d2f0ffd..3b8e32d8797 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@@ -291,23 -291,6 +291,23 @@@ static void fixup_sst39vf_rev_b(struct cfi->addr_unlock1 = 0x555; cfi->addr_unlock2 = 0x2AA; + + cfi->sector_erase_cmd = CMD(0x50); +} + +static void fixup_sst38vf640x_sectorsize(struct mtd_info *mtd, void *param) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + + fixup_sst39vf_rev_b(mtd, param); + + /* + * CFI reports 1024 sectors (0x03ff+1) of 64KBytes (0x0100*256) where + * it should report a size of 8KBytes (0x0020*256). + */ + cfi->cfiq->EraseRegionInfo[0] = 0x002003ff; + pr_warning("%s: Bad 38VF640x CFI data; adjusting sector size from 64 to 8KiB\n", mtd->name); } static void fixup_s29gl064n_sectors(struct mtd_info *mtd, void *param) @@@ -334,14 -317,14 +334,14 @@@ static void fixup_s29gl032n_sectors(str /* Used to fix CFI-Tables of chips without Extended Query Tables */ static struct cfi_fixup cfi_nopri_fixup_table[] = { - { CFI_MFR_SST, 0x234A, fixup_sst39vf, NULL, }, // SST39VF1602 - { CFI_MFR_SST, 0x234B, fixup_sst39vf, NULL, }, // SST39VF1601 - { CFI_MFR_SST, 0x235A, fixup_sst39vf, NULL, }, // SST39VF3202 - { CFI_MFR_SST, 0x235B, fixup_sst39vf, NULL, }, // SST39VF3201 - { CFI_MFR_SST, 0x235C, fixup_sst39vf_rev_b, NULL, }, // SST39VF3202B - { CFI_MFR_SST, 0x235D, fixup_sst39vf_rev_b, NULL, }, // SST39VF3201B - { CFI_MFR_SST, 0x236C, fixup_sst39vf_rev_b, NULL, }, // SST39VF6402B - { CFI_MFR_SST, 0x236D, fixup_sst39vf_rev_b, NULL, }, // SST39VF6401B + { CFI_MFR_SST, 0x234A, fixup_sst39vf, NULL, }, /* SST39VF1602 */ + { CFI_MFR_SST, 0x234B, fixup_sst39vf, NULL, }, /* SST39VF1601 */ + { CFI_MFR_SST, 0x235A, fixup_sst39vf, NULL, }, /* SST39VF3202 */ + { CFI_MFR_SST, 0x235B, fixup_sst39vf, NULL, }, /* SST39VF3201 */ + { CFI_MFR_SST, 0x235C, fixup_sst39vf_rev_b, NULL, }, /* SST39VF3202B */ + { CFI_MFR_SST, 0x235D, fixup_sst39vf_rev_b, NULL, }, /* SST39VF3201B */ + { CFI_MFR_SST, 0x236C, fixup_sst39vf_rev_b, NULL, }, /* SST39VF6402B */ + { CFI_MFR_SST, 0x236D, fixup_sst39vf_rev_b, NULL, }, /* SST39VF6401B */ { 0, 0, NULL, NULL } }; @@@ -361,10 -344,6 +361,10 @@@ static struct cfi_fixup cfi_fixup_table { CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors, NULL, }, { CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors, NULL, }, { CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors, NULL, }, + { CFI_MFR_SST, 0x536A, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6402 */ + { CFI_MFR_SST, 0x536B, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6401 */ + { CFI_MFR_SST, 0x536C, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6404 */ + { CFI_MFR_SST, 0x536D, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6403 */ #if !FORCE_WORD_WRITE { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, }, #endif @@@ -395,13 -374,6 +395,13 @@@ static void cfi_fixup_major_minor(struc if (cfi->mfr == CFI_MFR_SAMSUNG && cfi->id == 0x257e && extp->MajorVersion == '0') extp->MajorVersion = '1'; + /* + * SST 38VF640x chips report major=0xFF / minor=0xFF. + */ + if (cfi->mfr == CFI_MFR_SST && (cfi->id >> 4) == 0x0536) { + extp->MajorVersion = '1'; + extp->MinorVersion = '0'; + } } struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) @@@ -446,8 -418,8 +446,8 @@@ /* * Valid primary extension versions are: 1.0, 1.1, 1.2, 1.3, 1.4 - * see: http://www.amd.com/us-en/assets/content_type/DownloadableAssets/cfi_r20.pdf, page 19 - * http://www.amd.com/us-en/assets/content_type/DownloadableAssets/cfi_100_20011201.pdf + * see: http://cs.ozerki.net/zap/pub/axim-x5/docs/cfi_r20.pdf, page 19 + * http://www.spansion.com/Support/AppNotes/cfi_100_20011201.pdf * http://www.spansion.com/Support/Datasheets/s29ws-p_00_a12_e.pdf */ if (extp->MajorVersion != '1' || @@@ -573,6 -545,15 +573,6 @@@ static struct mtd_info *cfi_amdstd_setu printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize); goto setup_err; } -#if 0 - // debug - for (i=0; inumeraseregions;i++){ - printk("%d: offset=0x%x,size=0x%x,blocks=%d\n", - i,mtd->eraseregions[i].offset, - mtd->eraseregions[i].erasesize, - mtd->eraseregions[i].numblocks); - } -#endif __module_get(THIS_MODULE); register_reboot_notifier(&mtd->reboot_notifier); @@@ -693,7 -674,7 +693,7 @@@ static int get_chip(struct map_info *ma * there was an error (so leave the erase * routine to recover from it) or we trying to * use the erase-in-progress sector. */ - map_write(map, CMD(0x30), chip->in_progress_block_addr); + map_write(map, cfi->sector_erase_cmd, chip->in_progress_block_addr); chip->state = FL_ERASING; chip->oldstate = FL_READY; printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__); @@@ -746,7 -727,7 +746,7 @@@ static void put_chip(struct map_info *m switch(chip->oldstate) { case FL_ERASING: chip->state = chip->oldstate; - map_write(map, CMD(0x30), chip->in_progress_block_addr); + map_write(map, cfi->sector_erase_cmd, chip->in_progress_block_addr); chip->oldstate = FL_READY; chip->state = FL_ERASING; break; @@@ -889,7 -870,7 +889,7 @@@ static void __xipram xip_udelay(struct local_irq_disable(); /* Resume the write or erase operation */ - map_write(map, CMD(0x30), adr); + map_write(map, cfi->sector_erase_cmd, adr); chip->state = oldstate; start = xip_currtime(); } else if (usec >= 1000000/HZ) { @@@ -1044,6 -1025,9 +1044,6 @@@ static inline int do_read_secsi_onechip mutex_lock(&chip->mutex); if (chip->state != FL_READY){ -#if 0 - printk(KERN_DEBUG "Waiting for chip to read, status = %d\n", chip->state); -#endif set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(&chip->wq, &wait); @@@ -1051,6 -1035,10 +1051,6 @@@ schedule(); remove_wait_queue(&chip->wq, &wait); -#if 0 - if(signal_pending(current)) - return -EINTR; -#endif timeo = jiffies + HZ; goto retry; @@@ -1258,6 -1246,9 +1258,6 @@@ static int cfi_amdstd_write_words(struc mutex_lock(&cfi->chips[chipnum].mutex); if (cfi->chips[chipnum].state != FL_READY) { -#if 0 - printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state); -#endif set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(&cfi->chips[chipnum].wq, &wait); @@@ -1265,6 -1256,10 +1265,6 @@@ schedule(); remove_wait_queue(&cfi->chips[chipnum].wq, &wait); -#if 0 - if(signal_pending(current)) - return -EINTR; -#endif goto retry; } @@@ -1329,6 -1324,9 +1329,6 @@@ mutex_lock(&cfi->chips[chipnum].mutex); if (cfi->chips[chipnum].state != FL_READY) { -#if 0 - printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state); -#endif set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(&cfi->chips[chipnum].wq, &wait); @@@ -1336,6 -1334,10 +1336,6 @@@ schedule(); remove_wait_queue(&cfi->chips[chipnum].wq, &wait); -#if 0 - if(signal_pending(current)) - return -EINTR; -#endif goto retry1; } @@@ -1394,6 -1396,7 +1394,6 @@@ static int __xipram do_write_buffer(str cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); - //cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); /* Write Buffer Load */ map_write(map, CMD(0x25), cmd_adr); @@@ -1672,7 -1675,7 +1672,7 @@@ static int __xipram do_erase_oneblock(s cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); - map_write(map, CMD(0x30), adr); + map_write(map, cfi->sector_erase_cmd, adr); chip->state = FL_ERASING; chip->erase_suspended = 0; diff --combined drivers/mtd/devices/m25p80.c index 7e0edd40ad4,ea22520c040..669d2b7e36b --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@@ -661,14 -661,11 +661,14 @@@ static const struct spi_device_id m25p_ { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) }, { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) }, { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) }, + { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SECT_4K) }, { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) }, { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) }, { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, 0) }, + { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K) }, + { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, /* SST -- large erase sizes are "overlays", "sectors" are 4K */ { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K) }, @@@ -717,7 -714,6 +717,7 @@@ { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, + { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, /* Catalyst / On Semiconductor -- non-JEDEC */ { "cat25c11", CAT25_INFO( 16, 8, 16, 1) }, @@@ -928,6 -924,13 +928,13 @@@ static int __devinit m25p_probe(struct nr_parts = data->nr_parts; } + #ifdef CONFIG_OF + if (nr_parts <= 0 && spi->dev.of_node) { + nr_parts = of_mtd_parse_partitions(&spi->dev, + spi->dev.of_node, &parts); + } + #endif + if (nr_parts > 0) { for (i = 0; i < nr_parts; i++) { DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = " diff --combined drivers/mtd/maps/Kconfig index e5eb65cfb3e,962212628f6..a0dd7bba948 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@@ -172,7 -172,7 +172,7 @@@ config MTD_OCTAGO This provides a 'mapping' driver which supports the way in which the flash chips are connected in the Octagon-5066 Single Board Computer. More information on the board is available at - . + . config MTD_VMAX tristate "JEDEC Flash device mapped on Tempustech VMAX SBC301" @@@ -251,15 -251,6 +251,15 @@@ config MTD_NETte help Support for flash chips on NETtel/SecureEdge/SnapGear boards. +config MTD_BCM963XX + tristate "Map driver for Broadcom BCM963xx boards" + depends on BCM63XX + select MTD_MAP_BANK_WIDTH_2 + select MTD_CFI_I1 + help + Support for parsing CFE image tag and creating MTD partitions on + Broadcom BCM63xx boards. + config MTD_DILNETPC tristate "CFI Flash device mapped on DIL/Net PC" depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN @@@ -293,7 -284,7 +293,7 @@@ config MTD_TQM8XX chips, currently uses AMD one. This 'mapping' driver supports that arrangement, allowing the CFI probe and command set driver code to communicate with the chips on the TQM8xxL board. More at - . + . config MTD_RPXLITE tristate "CFI Flash device mapped on RPX Lite or CLLF" diff --combined drivers/mtd/maps/pcmciamtd.c index 86c74685eb7,57a1acfe22c..91702294839 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@@ -16,7 -16,6 +16,6 @@@ #include #include - #include #include #include @@@ -101,7 -100,7 +100,7 @@@ MODULE_PARM_DESC(mem_type, "Set Memory static caddr_t remap_window(struct map_info *map, unsigned long to) { struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; - window_handle_t win = (window_handle_t)map->map_priv_2; + struct resource *win = (struct resource *) map->map_priv_2; unsigned int offset; int ret; @@@ -316,30 -315,19 +315,19 @@@ static void pcmciamtd_set_vpp(struct ma { struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; struct pcmcia_device *link = dev->p_dev; - modconf_t mod; - int ret; - - mod.Attributes = CONF_VPP1_CHANGE_VALID | CONF_VPP2_CHANGE_VALID; - mod.Vcc = 0; - mod.Vpp1 = mod.Vpp2 = on ? dev->vpp : 0; DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp); - ret = pcmcia_modify_configuration(link, &mod); + pcmcia_fixup_vpp(link, on ? dev->vpp : 0); } - /* After a card is removed, pcmciamtd_release() will unregister the - * device, and release the PCMCIA configuration. If the device is - * still open, this will be postponed until it is closed. - */ - static void pcmciamtd_release(struct pcmcia_device *link) { struct pcmciamtd_dev *dev = link->priv; DEBUG(3, "link = 0x%p", link); - if (link->win) { + if (link->resource[2]->end) { if(dev->win_base) { iounmap(dev->win_base); dev->win_base = NULL; @@@ -482,18 -470,12 +470,12 @@@ static void card_settings(struct pcmcia } - /* pcmciamtd_config() is scheduled to run after a CARD_INSERTION event - * is received, to configure the PCMCIA socket, and to make the - * MTD device available to the system. - */ - static int pcmciamtd_config(struct pcmcia_device *link) { struct pcmciamtd_dev *dev = link->priv; struct mtd_info *mtd = NULL; - win_req_t req; int ret; - int i; + int i, j = 0; static char *probes[] = { "jedec_probe", "cfi_probe" }; int new_name = 0; @@@ -520,28 -502,34 +502,34 @@@ * smaller windows until we succeed */ - req.Attributes = WIN_MEMORY_TYPE_CM | WIN_ENABLE; - req.Attributes |= (dev->pcmcia_map.bankwidth == 1) ? WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16; - req.Base = 0; - req.AccessSpeed = mem_speed; - link->win = (window_handle_t)link; - req.Size = (force_size) ? force_size << 20 : MAX_PCMCIA_ADDR; + link->resource[2]->flags |= WIN_MEMORY_TYPE_CM | WIN_ENABLE; + link->resource[2]->flags |= (dev->pcmcia_map.bankwidth == 1) ? + WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16; + link->resource[2]->start = 0; + link->resource[2]->end = (force_size) ? force_size << 20 : + MAX_PCMCIA_ADDR; dev->win_size = 0; do { int ret; - DEBUG(2, "requesting window with size = %dKiB memspeed = %d", - req.Size >> 10, req.AccessSpeed); - ret = pcmcia_request_window(link, &req, &link->win); + DEBUG(2, "requesting window with size = %luKiB memspeed = %d", + (unsigned long) resource_size(link->resource[2]) >> 10, + mem_speed); + ret = pcmcia_request_window(link, link->resource[2], mem_speed); DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size); if(ret) { - req.Size >>= 1; + j++; + link->resource[2]->start = 0; + link->resource[2]->end = (force_size) ? + force_size << 20 : MAX_PCMCIA_ADDR; + link->resource[2]->end >>= j; } else { - DEBUG(2, "Got window of size %dKiB", req.Size >> 10); - dev->win_size = req.Size; + DEBUG(2, "Got window of size %luKiB", (unsigned long) + resource_size(link->resource[2]) >> 10); + dev->win_size = resource_size(link->resource[2]); break; } - } while(req.Size >= 0x1000); + } while (link->resource[2]->end >= 0x1000); DEBUG(2, "dev->win_size = %d", dev->win_size); @@@ -553,33 -541,31 +541,31 @@@ DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10); /* Get write protect status */ - DEBUG(2, "window handle = 0x%8.8lx", (unsigned long)link->win); - dev->win_base = ioremap(req.Base, req.Size); + dev->win_base = ioremap(link->resource[2]->start, + resource_size(link->resource[2])); if(!dev->win_base) { - dev_err(&dev->p_dev->dev, "ioremap(%lu, %u) failed\n", - req.Base, req.Size); + dev_err(&dev->p_dev->dev, "ioremap(%pR) failed\n", + link->resource[2]); pcmciamtd_release(link); return -ENODEV; } - DEBUG(1, "mapped window dev = %p req.base = 0x%lx base = %p size = 0x%x", - dev, req.Base, dev->win_base, req.Size); + DEBUG(1, "mapped window dev = %p @ %pR, base = %p", + dev, link->resource[2], dev->win_base); dev->offset = 0; dev->pcmcia_map.map_priv_1 = (unsigned long)dev; - dev->pcmcia_map.map_priv_2 = (unsigned long)link->win; + dev->pcmcia_map.map_priv_2 = (unsigned long)link->resource[2]; dev->vpp = (vpp) ? vpp : link->socket->socket.Vpp; - link->conf.Attributes = 0; if(setvpp == 2) { - link->conf.Vpp = dev->vpp; + link->vpp = dev->vpp; } else { - link->conf.Vpp = 0; + link->vpp = 0; } - link->conf.IntType = INT_MEMORY; - link->conf.ConfigIndex = 0; + link->config_index = 0; DEBUG(2, "Setting Configuration"); - ret = pcmcia_request_configuration(link, &link->conf); + ret = pcmcia_enable_device(link); if (ret != 0) { if (dev->win_base) { iounmap(dev->win_base); @@@ -654,6 -640,10 +640,6 @@@ } dev_info(&dev->p_dev->dev, "mtd%d: %s\n", mtd->index, mtd->name); return 0; - - dev_err(&dev->p_dev->dev, "CS Error, exiting\n"); - pcmciamtd_release(link); - return -ENODEV; } @@@ -676,12 -666,6 +662,6 @@@ static int pcmciamtd_resume(struct pcmc } - /* This deletes a driver "instance". The device is de-registered - * with Card Services. If it has been released, all local data - * structures are freed. Otherwise, the structures will be freed - * when the device is released. - */ - static void pcmciamtd_detach(struct pcmcia_device *link) { struct pcmciamtd_dev *dev = link->priv; @@@ -699,11 -683,6 +679,6 @@@ } - /* pcmciamtd_attach() creates an "instance" of the driver, allocating - * local data structures for one device. The device is registered - * with Card Services. - */ - static int pcmciamtd_probe(struct pcmcia_device *link) { struct pcmciamtd_dev *dev; @@@ -716,9 -695,6 +691,6 @@@ dev->p_dev = link; link->priv = dev; - link->conf.Attributes = 0; - link->conf.IntType = INT_MEMORY; - return pcmciamtd_config(link); } @@@ -753,9 -729,7 +725,7 @@@ static struct pcmcia_device_id pcmciamt MODULE_DEVICE_TABLE(pcmcia, pcmciamtd_ids); static struct pcmcia_driver pcmciamtd_driver = { - .drv = { - .name = "pcmciamtd" - }, + .name = "pcmciamtd", .probe = pcmciamtd_probe, .remove = pcmciamtd_detach, .owner = THIS_MODULE, @@@ -767,8 -741,6 +737,6 @@@ static int __init init_pcmciamtd(void) { - info(DRIVER_DESC); - if(bankwidth && bankwidth != 1 && bankwidth != 2) { info("bad bankwidth (%d), using default", bankwidth); bankwidth = 2; diff --combined drivers/mtd/mtd_blkdevs.c index 63790e975d2,50ab431b24e..f9329794f3b --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@@ -29,7 -29,6 +29,6 @@@ #include #include #include - #include #include #include #include @@@ -38,6 -37,7 +37,7 @@@ #include "mtdcore.h" + static DEFINE_MUTEX(mtd_blkdevs_mutex); static LIST_HEAD(blktrans_majors); static DEFINE_MUTEX(blktrans_ref_mutex); @@@ -133,10 -133,6 +133,10 @@@ static int mtd_blktrans_thread(void *ar if (!req && !(req = blk_fetch_request(rq))) { set_current_state(TASK_INTERRUPTIBLE); + + if (kthread_should_stop()) + set_current_state(TASK_RUNNING); + spin_unlock_irq(rq->queue_lock); schedule(); spin_lock_irq(rq->queue_lock); @@@ -180,53 -176,54 +180,57 @@@ static void mtd_blktrans_request(struc static int blktrans_open(struct block_device *bdev, fmode_t mode) { struct mtd_blktrans_dev *dev = blktrans_dev_get(bdev->bd_disk); - int ret; + int ret = 0; if (!dev) return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/ + mutex_lock(&mtd_blkdevs_mutex); mutex_lock(&dev->lock); - if (!dev->mtd) { - ret = -ENXIO; + if (dev->open++) goto unlock; - } - ret = !dev->open++ && dev->tr->open ? dev->tr->open(dev) : 0; + kref_get(&dev->ref); + __module_get(dev->tr->owner); + + if (dev->mtd) { + ret = dev->tr->open ? dev->tr->open(dev) : 0; + __get_mtd_device(dev->mtd); + } - /* Take another reference on the device so it won't go away till - last release */ - if (!ret) - kref_get(&dev->ref); unlock: mutex_unlock(&dev->lock); blktrans_dev_put(dev); + mutex_unlock(&mtd_blkdevs_mutex); return ret; } static int blktrans_release(struct gendisk *disk, fmode_t mode) { struct mtd_blktrans_dev *dev = blktrans_dev_get(disk); - int ret = -ENXIO; + int ret = 0; if (!dev) return ret; + mutex_lock(&mtd_blkdevs_mutex); mutex_lock(&dev->lock); - /* Release one reference, we sure its not the last one here*/ - kref_put(&dev->ref, blktrans_dev_release); - - if (!dev->mtd) + if (--dev->open) goto unlock; - ret = !--dev->open && dev->tr->release ? dev->tr->release(dev) : 0; + kref_put(&dev->ref, blktrans_dev_release); + module_put(dev->tr->owner); + + if (dev->mtd) { + ret = dev->tr->release ? dev->tr->release(dev) : 0; + __put_mtd_device(dev->mtd); + } unlock: mutex_unlock(&dev->lock); blktrans_dev_put(dev); + mutex_unlock(&mtd_blkdevs_mutex); return ret; } @@@ -259,6 -256,7 +263,7 @@@ static int blktrans_ioctl(struct block_ if (!dev) return ret; + mutex_lock(&mtd_blkdevs_mutex); mutex_lock(&dev->lock); if (!dev->mtd) @@@ -273,6 -271,7 +278,7 @@@ } unlock: mutex_unlock(&dev->lock); + mutex_unlock(&mtd_blkdevs_mutex); blktrans_dev_put(dev); return ret; } @@@ -386,6 -385,9 +392,6 @@@ int add_mtd_blktrans_dev(struct mtd_blk gd->queue = new->rq; - __get_mtd_device(new->mtd); - __module_get(tr->owner); - /* Create processing thread */ /* TODO: workqueue ? */ new->thread = kthread_run(mtd_blktrans_thread, new, @@@ -408,6 -410,8 +414,6 @@@ } return 0; error4: - module_put(tr->owner); - __put_mtd_device(new->mtd); blk_cleanup_queue(new->rq); error3: put_disk(new->disk); @@@ -444,15 -448,17 +450,15 @@@ int del_mtd_blktrans_dev(struct mtd_blk blk_start_queue(old->rq); spin_unlock_irqrestore(&old->queue_lock, flags); - /* Ask trans driver for release to the mtd device */ + /* If the device is currently open, tell trans driver to close it, + then put mtd device, and don't touch it again */ mutex_lock(&old->lock); - if (old->open && old->tr->release) { - old->tr->release(old); - old->open = 0; + if (old->open) { + if (old->tr->release) + old->tr->release(old); + __put_mtd_device(old->mtd); } - __put_mtd_device(old->mtd); - module_put(old->tr->owner); - - /* At that point, we don't touch the mtd anymore */ old->mtd = NULL; mutex_unlock(&old->lock); @@@ -502,16 -508,13 +508,16 @@@ int register_mtd_blktrans(struct mtd_bl mutex_lock(&mtd_table_mutex); ret = register_blkdev(tr->major, tr->name); - if (ret) { + if (ret < 0) { printk(KERN_WARNING "Unable to register %s block device on major %d: %d\n", tr->name, tr->major, ret); mutex_unlock(&mtd_table_mutex); return ret; } + if (ret) + tr->major = ret; + tr->blkshift = ffs(tr->blksize) - 1; INIT_LIST_HEAD(&tr->devs); diff --combined drivers/mtd/mtdchar.c index b7ed09c5790,5ef45487b65..3eff1e562ad --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@@ -26,18 -26,18 +26,19 @@@ #include #include #include - #include + #include #include #include #include - +#include #include +#include #include #include #define MTD_INODE_FS_MAGIC 0x11307854 + static DEFINE_MUTEX(mtd_mutex); static struct vfsmount *mtd_inode_mnt __read_mostly; /* @@@ -91,7 -91,7 +92,7 @@@ static int mtd_open(struct inode *inode if ((file->f_mode & FMODE_WRITE) && (minor & 1)) return -EACCES; - lock_kernel(); + mutex_lock(&mtd_mutex); mtd = get_mtd_device(NULL, devnum); if (IS_ERR(mtd)) { @@@ -139,7 -139,7 +140,7 @@@ file->private_data = mfi; out: - unlock_kernel(); + mutex_unlock(&mtd_mutex); return ret; } /* mtd_open */ @@@ -478,78 -478,6 +479,78 @@@ static int mtd_do_readoob(struct mtd_in return ret; } +/* + * Copies (and truncates, if necessary) data from the larger struct, + * nand_ecclayout, to the smaller, deprecated layout struct, + * nand_ecclayout_user. This is necessary only to suppport the deprecated + * API ioctl ECCGETLAYOUT while allowing all new functionality to use + * nand_ecclayout flexibly (i.e. the struct may change size in new + * releases without requiring major rewrites). + */ +static int shrink_ecclayout(const struct nand_ecclayout *from, + struct nand_ecclayout_user *to) +{ + int i; + + if (!from || !to) + return -EINVAL; + + memset(to, 0, sizeof(*to)); + + to->eccbytes = min((int)from->eccbytes, MTD_MAX_ECCPOS_ENTRIES); + for (i = 0; i < to->eccbytes; i++) + to->eccpos[i] = from->eccpos[i]; + + for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES; i++) { + if (from->oobfree[i].length == 0 && + from->oobfree[i].offset == 0) + break; + to->oobavail += from->oobfree[i].length; + to->oobfree[i] = from->oobfree[i]; + } + + return 0; +} + +#ifdef CONFIG_MTD_PARTITIONS +static int mtd_blkpg_ioctl(struct mtd_info *mtd, + struct blkpg_ioctl_arg __user *arg) +{ + struct blkpg_ioctl_arg a; + struct blkpg_partition p; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + /* Only master mtd device must be used to control partitions */ + if (!mtd_is_master(mtd)) + return -EINVAL; + + if (copy_from_user(&a, arg, sizeof(struct blkpg_ioctl_arg))) + return -EFAULT; + + if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition))) + return -EFAULT; + + switch (a.op) { + case BLKPG_ADD_PARTITION: + + return mtd_add_partition(mtd, p.devname, p.start, p.length); + + case BLKPG_DEL_PARTITION: + + if (p.pno < 0) + return -EINVAL; + + return mtd_del_partition(mtd, p.pno); + + default: + return -EINVAL; + } +} +#endif + + static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) { struct mtd_file_info *mfi = file->private_data; @@@ -586,9 -514,6 +587,9 @@@ if (get_user(ur_idx, &(ur->regionindex))) return -EFAULT; + if (ur_idx >= mtd->numeraseregions) + return -EINVAL; + kr = &(mtd->eraseregions[ur_idx]); if (put_user(kr->offset, &(ur->offset)) @@@ -888,23 -813,14 +889,23 @@@ } #endif + /* This ioctl is being deprecated - it truncates the ecc layout */ case ECCGETLAYOUT: { + struct nand_ecclayout_user *usrlay; + if (!mtd->ecclayout) return -EOPNOTSUPP; - if (copy_to_user(argp, mtd->ecclayout, - sizeof(struct nand_ecclayout))) - return -EFAULT; + usrlay = kmalloc(sizeof(*usrlay), GFP_KERNEL); + if (!usrlay) + return -ENOMEM; + + shrink_ecclayout(mtd->ecclayout, usrlay); + + if (copy_to_user(argp, usrlay, sizeof(*usrlay))) + ret = -EFAULT; + kfree(usrlay); break; } @@@ -940,22 -856,6 +941,22 @@@ break; } +#ifdef CONFIG_MTD_PARTITIONS + case BLKPG: + { + ret = mtd_blkpg_ioctl(mtd, + (struct blkpg_ioctl_arg __user *)arg); + break; + } + + case BLKRRPART: + { + /* No reread partition feature. Just return ok */ + ret = 0; + break; + } +#endif + default: ret = -ENOTTY; } @@@ -967,9 -867,9 +968,9 @@@ static long mtd_unlocked_ioctl(struct f { int ret; - lock_kernel(); + mutex_lock(&mtd_mutex); ret = mtd_ioctl(file, cmd, arg); - unlock_kernel(); + mutex_unlock(&mtd_mutex); return ret; } @@@ -993,7 -893,7 +994,7 @@@ static long mtd_compat_ioctl(struct fil void __user *argp = compat_ptr(arg); int ret = 0; - lock_kernel(); + mutex_lock(&mtd_mutex); switch (cmd) { case MEMWRITEOOB32: @@@ -1028,7 -928,7 +1029,7 @@@ ret = mtd_ioctl(file, cmd, (unsigned long)argp); } - unlock_kernel(); + mutex_unlock(&mtd_mutex); return ret; } @@@ -1134,7 -1034,7 +1135,7 @@@ static int mtd_inodefs_get_sb(struct fi const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC, + return get_sb_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC, mnt); } diff --combined drivers/mtd/nand/omap2.c index 439e80d78ed,513e0a76a4a..cd41c58b5bb --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@@ -111,11 -111,11 +111,11 @@@ static int use_dma = 1 module_param(use_dma, bool, 0); MODULE_PARM_DESC(use_dma, "enable/disable use of DMA"); #else -const int use_dma; +static const int use_dma; #endif #else const int use_prefetch; -const int use_dma; +static const int use_dma; #endif struct omap_nand_info { @@@ -413,7 -413,7 +413,7 @@@ static inline int omap_nand_dma_transfe prefetch_status = gpmc_read_status(GPMC_PREFETCH_COUNT); } while (prefetch_status); /* disable and stop the PFPW engine */ - gpmc_prefetch_reset(); + gpmc_prefetch_reset(info->gpmc_cs); dma_unmap_single(&info->pdev->dev, dma_addr, len, dir); return 0; diff --combined fs/jffs2/fs.c index 2701b372da7,d9beb06e6fc..e896e67767e --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@@ -21,7 -21,6 +21,6 @@@ #include #include #include - #include #include "nodelist.h" static int jffs2_flash_setup(struct jffs2_sb_info *c); @@@ -391,7 -390,6 +390,6 @@@ int jffs2_remount_fs (struct super_bloc This also catches the case where it was stopped and this is just a remount to restart it. Flush the writebuffer, if neccecary, else we loose it */ - lock_kernel(); if (!(sb->s_flags & MS_RDONLY)) { jffs2_stop_garbage_collect_thread(c); mutex_lock(&c->alloc_sem); @@@ -403,8 -401,6 +401,6 @@@ jffs2_start_garbage_collect_thread(c); *flags |= MS_NOATIME; - - unlock_kernel(); return 0; } @@@ -478,25 -474,6 +474,25 @@@ struct inode *jffs2_new_inode (struct i return inode; } +static int calculate_inocache_hashsize(uint32_t flash_size) +{ + /* + * Pick a inocache hash size based on the size of the medium. + * Count how many megabytes we're dealing with, apply a hashsize twice + * that size, but rounding down to the usual big powers of 2. And keep + * to sensible bounds. + */ + + int size_mb = flash_size / 1024 / 1024; + int hashsize = (size_mb * 2) & ~0x3f; + + if (hashsize < INOCACHE_HASHSIZE_MIN) + return INOCACHE_HASHSIZE_MIN; + if (hashsize > INOCACHE_HASHSIZE_MAX) + return INOCACHE_HASHSIZE_MAX; + + return hashsize; +} int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) { @@@ -543,8 -520,7 +539,8 @@@ if (ret) return ret; - c->inocache_list = kcalloc(INOCACHE_HASHSIZE, sizeof(struct jffs2_inode_cache *), GFP_KERNEL); + c->inocache_hashsize = calculate_inocache_hashsize(c->flash_size); + c->inocache_list = kcalloc(c->inocache_hashsize, sizeof(struct jffs2_inode_cache *), GFP_KERNEL); if (!c->inocache_list) { ret = -ENOMEM; goto out_wbuf;