GIT ea59830db01b6b3d6bda9f84e3d272a346115e8e git://git.infradead.org/mtd-2.6.git commit ea59830db01b6b3d6bda9f84e3d272a346115e8e Author: Josef 'Jeff' Sipek Date: Sat Sep 16 21:09:29 2006 -0400 [MTD] Use SEEK_{SET,CUR,END} instead of hardcoded values in mtdchar lseek() Signed-off-by: Josef 'Jeff' Sipek Signed-off-by: David Woodhouse commit de591dacf3034977b3fb94b61d08240c8b35c39d Author: Håvard Skinnemoen Date: Fri Sep 15 17:19:31 2006 +0200 MTD: Fix bug in fixup_convert_atmel_pri The memset() in fixup_convert_atmel_pri is supposed to zero out everything except the first 5 bytes in *extp, but it ends up zeroing out something way outside the struct instead. Fix this potentially dangerous code by casting the pointer to char * before doing arithmetic. Signed-off-by: Håvard Skinnemoen Signed-off-by: David Woodhouse commit d882687c51b52424a56992578ce7636b3f3c8d41 Author: Havasi Ferenc Date: Tue Sep 5 16:08:58 2006 +0200 [JFFS2][SUMMARY] Fix a summary collecting bug. In some special case (padding because of sync or umount) it can be possible that summary information is not fit to the end of the erase block. In these cases the collecting of summary is disabled for this erase block. The problem was that this was not respected by jffs2_sum_add_kvec(). This patch fix this bug. From: Zoltan Sogor Signed-off-by: Ferenc Havasi Signed-off-by: David Woodhouse commit fa6c220a7f01257b1c2c4203d48aaaedb0c4416f Author: Aubrey Lee Date: Tue Sep 5 05:55:07 2006 -0500 [PATCH] [MTD] DEVICES: Fill more device IDs in the structure of m25p80 The flash_info structure has a bunch of missing fields which causes problems when actually tryin to use some ST parts as it gets detected incorrectly. Signed-off-by: Aubrey L1 Signed-off-by: Josh Boyer commit 0165508c80a2b5d5268d9c5dfa9b30c534a33693 Author: Haavard Skinnemoen Date: Wed Aug 9 11:06:07 2006 +0200 MTD: Add lock/unlock operations for Atmel AT49BV6416 The AT49BV6416 is locked by default, so we really need to provide at least the unlock() operation for write and erase to work. This patch implements both ->lock() and ->unlock() and provides a fixup to install them when an AT49BV6416 chip is detected. These functions are probably valid on more Atmel chips, but I believe it's mostly obsolete ones. The AT49BV6416 is in fact obsolete, but it's used on all current AT32STK1000 development boards. Signed-off-by: Haavard Skinnemoen Signed-off-by: Josh Boyer commit 5b0c5c2c0d04c29f85abb485378ba5476c7aeec2 Author: Haavard Skinnemoen Date: Wed Aug 9 10:54:44 2006 +0200 MTD: Convert Atmel PRI information to AMD format Atmel flash chips don't have PRI information in the same format as AMD flash chips. This patch installs a fixup for all Atmel chips that converts the relevant PRI fields into AMD format. Only the fields that are actually used by the command set is actually converted. The rest are initialized to zero (which should be safe) Signed-off-by: Haavard Skinnemoen Signed-off-by: Josh Boyer commit 0b6c0bb3f9621b128011bcd5f65047c73afdde3b Author: Adrian Bunk Date: Tue Aug 15 02:42:25 2006 +0200 fs/jffs2/xattr.c: remove dead code This patch removes some obvious dead code spotted by the Coverity checker. Signed-off-by: Adrian Bunk Signed-off-by: Josh Boyer commit 79b9cd586f534f3f40ee66b6c27732149a5915ad Author: Takashi YOSHII Date: Tue Aug 15 07:26:32 2006 -0500 [PATCH] [MTD] Maps: Add dependency on alternate probe methods to physmap map/physmap.c tries to probe "cfi_probe", "jedec_probe" and "map_rom", but map/Kconfig says it depends on MTD_CFI only. This patch adds MTD_JEDECPROBE and MTD_ROM to the dependency condition. Signed-off-by: Takashi YOSHII Signed-off-by: Josh Boyer commit c4e6952ffd71b263a64d1a9d79812446130560a5 Author: Takashi YOSHI Date: Mon Aug 14 19:48:30 2006 -0500 [PATCH] MTD: Add Macronix MX29F040 to JEDEC Signed-off-by: Takashi YOSHII Signed-off-by: Josh Boyer commit 46a1652c28fc4f4e9d46ea12b0c36b5b6b600f58 Author: Alexey Korolev Date: Wed Jun 28 19:22:07 2006 +0100 [MTD] Fixes of performance and stability issues in CFI driver. Fix of performance and stability issues on Intel NOR chips. It fixes: 1. Very low write performance on Sibley (perf tests demonstrated write performance less than 100Kb/sec when it should be over 400Kb/sec). 2. Low erase performance. (perf tests on Sibleuy demonstrated erase performance 246Kb/sec when it should be over 300Kb/sec). 3. Error on JFFS2 tests with CPU loading application when MTD returns "block erase error: (status timeout)" To fix the issue it does the following: 1. Removes the timeout tuning from inval_cache_and_wait_for_operation. 2. Waiting conditions in inval_cache_and_wait_for_operation now is based on timer resolution If timeout is lower than timer resolution then we do in cycle "Checking the status" udelay(1); cond_resched(); If timeout is greater than timer resolution (probably erase operation) We do the following sleep for half of operation timeout and do in cycle the following "Checking the status" sleep for timer resolution Signed-off-by: Nicolas Pitre Signed-off-by: Alexey Korolev Signed-off-by: David Woodhouse commit c4e7fb313771ac03dfdca26d30e8b721731c562b Author: Ville Herva Date: Fri Jul 14 00:31:16 2006 +0300 block2mtd.c: Make kernel boot command line arguments work (try 4) Trying to pass kernel command line arguments to block2mtd at boot-time does not work currently. block2mtd_setup() is called so early that kmalloc() fails nevermind being able to do open_bdev_excl() (which requires rootfs to be mounted. This patch only saves the option string at the early boot stage, and parses them later when block2mtd_init() is called. If open_bdev_excl() fails, open_by_devnum(name_to_dev_t()) is tried instead, which makes it possible to initialize the driver before rootfs has been mounted. Also gets rid of the superfluous parse_name() that only checks if name is longer than 80 chars and copies it to a string that is not kfreed. With this patch, I can boot statically compiled block2mtd, and mount jffs2 as rootfs (without modules or initrd), with lilo config like this: root=/dev/mtdblock0 append="rootfstype=jffs2 block2mtd.block2mtd=/dev/hdc2,65536" (Note that rootfstype=jffs2 is required, since the kernel only tries filesystems without "nodev" attribute by default, and jffs is "nodev"). Compared to first version of this patch, this one does not copy the parameters to the global buffer if init has already been called, and the global array is marked as __initdata. Compared to the second version of this patch, module build is fixed. Compared to the third version of this patch, statically compiled block2mtd driver with no boot-time parameter no longer gives spurious error 'cannot open device ""' Signed-off-by: Ville Herva Acked-by: Jörn Engel Signed-off-by: David Woodhouse commit 9a909867d2eca7727d0d5884df96e791e3531f24 Author: David Woodhouse Date: Sat Jul 15 13:26:18 2006 +0100 [MTD NAND] Fix lookup error in nand_get_flash_type() Spotted by liyu Signed-off-by: David Woodhouse commit 9d05cd51780c3855976b26cbee265490a0a10be9 Author: Rolf Eike Beer Date: Fri Jul 14 14:39:06 2006 +0200 remove #error on !PCI from pmc551.c PMC551 depends on PCI in Kconfig so there is no need to #error in code if PCI is not set. Signed-off-by: Rolf Eike Beer Signed-off-by: David Woodhouse commit 6a5a297cf78e64ed68577f3e3480bc10abf0124b Author: Richard Purdie Date: Sat Jul 15 13:05:24 2006 +0100 MTD: [NAND] Fix the sharpsl driver after breakage from a core conversion The CNE bits are inverted on the device and writeb function is missing a NOT operation. Signed-off-by: Richard Purdie Signed-off-by: David Woodhouse commit 8b0036eefd7a96f23244b969417684c8627f5ad6 Author: Vitaly Wool Date: Tue Jul 11 09:11:25 2006 +0200 [MTD] NAND: OOB buffer offset fixups In the case of data-pad-ecc-pad-data... layout the oob start position has to be sizeof(data) in nand_write_oob_syndrom(). In nand_fill_oob() we need to copy to buf + buffer offset instead of buf + write offset. From: Vitaly Wool Signed-off-by: Thomas Gleixner commit 90a18fab4ae07b77bf053b75a4d1285cd94faa79 Author: Adrian Bunk Date: Thu Jul 6 22:37:43 2006 +0200 make fs/jffs2/nodelist.c:jffs2_obsolete_node_frag() static This patch makes the needlessly global jffs2_obsolete_node_frag() static. Signed-off-by: Adrian Bunk Signed-off-by: David Woodhouse commit 220b0f5755f86745e4e16d001fe6f46b448565fa Author: Artem B. Bityutskiy Date: Wed Jul 5 11:04:02 2006 +0400 [PATCH] [MTD] NAND: fix dead URL in Kconfig Signed-off-by: Artem B. Bityutskiy drivers/mtd/chips/cfi_cmdset_0001.c | 87 ++++++++++++++------------- drivers/mtd/chips/cfi_cmdset_0002.c | 111 +++++++++++++++++++++++++++++++++++ drivers/mtd/chips/jedec_probe.c | 14 ++++ drivers/mtd/devices/block2mtd.c | 93 ++++++++++++++++++++--------- drivers/mtd/devices/m25p80.c | 12 ++-- drivers/mtd/devices/pmc551.c | 4 - drivers/mtd/maps/Kconfig | 12 ++-- drivers/mtd/mtdchar.c | 9 +-- drivers/mtd/nand/Kconfig | 2 - drivers/mtd/nand/nand_base.c | 2 - drivers/mtd/nand/sharpsl.c | 7 ++ fs/jffs2/nodelist.c | 6 ++ fs/jffs2/nodelist.h | 1 fs/jffs2/xattr.c | 1 include/linux/mtd/cfi.h | 13 ++++ 15 files changed, 271 insertions(+), 103 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 39edb82..7ea49a0 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -908,7 +908,7 @@ static void __xipram xip_enable(struct m static int __xipram xip_wait_for_operation( struct map_info *map, struct flchip *chip, - unsigned long adr, int *chip_op_time ) + unsigned long adr, unsigned int chip_op_time ) { struct cfi_private *cfi = map->fldrv_priv; struct cfi_pri_intelext *cfip = cfi->cmdset_priv; @@ -917,7 +917,7 @@ static int __xipram xip_wait_for_operati flstate_t oldstate, newstate; start = xip_currtime(); - usec = *chip_op_time * 8; + usec = chip_op_time * 8; if (usec == 0) usec = 500000; done = 0; @@ -1027,8 +1027,8 @@ static int __xipram xip_wait_for_operati #define XIP_INVAL_CACHED_RANGE(map, from, size) \ INVALIDATE_CACHED_RANGE(map, from, size) -#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, p_usec) \ - xip_wait_for_operation(map, chip, cmd_adr, p_usec) +#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, usec) \ + xip_wait_for_operation(map, chip, cmd_adr, usec) #else @@ -1040,64 +1040,64 @@ #define INVAL_CACHE_AND_WAIT inval_cache static int inval_cache_and_wait_for_operation( struct map_info *map, struct flchip *chip, unsigned long cmd_adr, unsigned long inval_adr, int inval_len, - int *chip_op_time ) + unsigned int chip_op_time) { struct cfi_private *cfi = map->fldrv_priv; map_word status, status_OK = CMD(0x80); - int z, chip_state = chip->state; - unsigned long timeo; + int chip_state = chip->state; + unsigned int timeo, sleep_time; spin_unlock(chip->mutex); if (inval_len) INVALIDATE_CACHED_RANGE(map, inval_adr, inval_len); - if (*chip_op_time) - cfi_udelay(*chip_op_time); spin_lock(chip->mutex); - timeo = *chip_op_time * 8 * HZ / 1000000; - if (timeo < HZ/2) - timeo = HZ/2; - timeo += jiffies; + /* set our timeout to 8 times the expected delay */ + timeo = chip_op_time * 8; + if (!timeo) + timeo = 500000; + sleep_time = chip_op_time / 2; - z = 0; for (;;) { - if (chip->state != chip_state) { - /* Someone's suspended the operation: sleep */ - DECLARE_WAITQUEUE(wait, current); - - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); - spin_unlock(chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); - timeo = jiffies + (HZ / 2); /* FIXME */ - spin_lock(chip->mutex); - continue; - } - status = map_read(map, cmd_adr); if (map_word_andequal(map, status, status_OK, status_OK)) break; - /* OK Still waiting */ - if (time_after(jiffies, timeo)) { + if (!timeo) { map_write(map, CMD(0x70), cmd_adr); chip->state = FL_STATUS; return -ETIME; } - /* Latency issues. Drop the lock, wait a while and retry */ - z++; + /* OK Still waiting. Drop the lock, wait a while and retry. */ spin_unlock(chip->mutex); - cfi_udelay(1); + if (sleep_time >= 1000000/HZ) { + /* + * Half of the normal delay still remaining + * can be performed with a sleeping delay instead + * of busy waiting. + */ + msleep(sleep_time/1000); + timeo -= sleep_time; + sleep_time = 1000000/HZ; + } else { + udelay(1); + cond_resched(); + timeo--; + } spin_lock(chip->mutex); - } - if (!z) { - if (!--(*chip_op_time)) - *chip_op_time = 1; - } else if (z > 1) - ++(*chip_op_time); + if (chip->state != chip_state) { + /* Someone's suspended the operation: sleep */ + DECLARE_WAITQUEUE(wait, current); + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + spin_unlock(chip->mutex); + schedule(); + remove_wait_queue(&chip->wq, &wait); + spin_lock(chip->mutex); + } + } /* Done and happy. */ chip->state = FL_STATUS; @@ -1107,8 +1107,7 @@ static int inval_cache_and_wait_for_oper #endif #define WAIT_TIMEOUT(map, chip, adr, udelay) \ - ({ int __udelay = (udelay); \ - INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, &__udelay); }) + INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, udelay); static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len) @@ -1332,7 +1331,7 @@ static int __xipram do_write_oneword(str ret = INVAL_CACHE_AND_WAIT(map, chip, adr, adr, map_bankwidth(map), - &chip->word_write_time); + chip->word_write_time); if (ret) { xip_enable(map, chip, adr); printk(KERN_ERR "%s: word write error (status timeout)\n", map->name); @@ -1569,7 +1568,7 @@ static int __xipram do_write_buffer(stru ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, adr, len, - &chip->buffer_write_time); + chip->buffer_write_time); if (ret) { map_write(map, CMD(0x70), cmd_adr); chip->state = FL_STATUS; @@ -1704,7 +1703,7 @@ static int __xipram do_erase_oneblock(st ret = INVAL_CACHE_AND_WAIT(map, chip, adr, adr, len, - &chip->erase_time); + chip->erase_time); if (ret) { map_write(map, CMD(0x70), adr); chip->state = FL_STATUS; diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 9885726..a482e89 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -45,9 +45,11 @@ #define FORCE_WORD_WRITE 0 #define MAX_WORD_RETRIES 3 #define MANUFACTURER_AMD 0x0001 +#define MANUFACTURER_ATMEL 0x001F #define MANUFACTURER_SST 0x00BF #define SST49LF004B 0x0060 #define SST49LF008A 0x005a +#define AT49BV6416 0x00d6 static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); @@ -68,6 +70,9 @@ static int get_chip(struct map_info *map static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr); #include "fwh_lock.h" +static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, size_t len); +static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, size_t len); + static struct mtd_chip_driver cfi_amdstd_chipdrv = { .probe = NULL, /* Not usable directly */ .destroy = cfi_amdstd_destroy, @@ -161,6 +166,26 @@ static void fixup_use_write_buffers(stru } } +/* Atmel chips don't use the same PRI format as AMD chips */ +static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + struct cfi_pri_amdstd *extp = cfi->cmdset_priv; + struct cfi_pri_atmel atmel_pri; + + memcpy(&atmel_pri, extp, sizeof(atmel_pri)); + memset((char *)extp + 5, 0, sizeof(*extp) - 5); + + if (atmel_pri.Features & 0x02) + extp->EraseSuspend = 2; + + if (atmel_pri.BottomBoot) + extp->TopBottom = 2; + else + extp->TopBottom = 3; +} + static void fixup_use_secsi(struct mtd_info *mtd, void *param) { /* Setup for chips with a secsi area */ @@ -179,6 +204,16 @@ static void fixup_use_erase_chip(struct } +/* + * Some Atmel chips (e.g. the AT49BV6416) power-up with all sectors + * locked by default. + */ +static void fixup_use_atmel_lock(struct mtd_info *mtd, void *param) +{ + mtd->lock = cfi_atmel_lock; + mtd->unlock = cfi_atmel_unlock; +} + static struct cfi_fixup cfi_fixup_table[] = { #ifdef AMD_BOOTLOC_BUG { CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL }, @@ -192,6 +227,7 @@ #endif #if !FORCE_WORD_WRITE { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, }, #endif + { CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL }, { 0, 0, NULL, NULL } }; static struct cfi_fixup jedec_fixup_table[] = { @@ -207,6 +243,7 @@ static struct cfi_fixup fixup_table[] = * we know that is the case. */ { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_erase_chip, NULL }, + { CFI_MFR_ATMEL, AT49BV6416, fixup_use_atmel_lock, NULL }, { 0, 0, NULL, NULL } }; @@ -1607,6 +1644,80 @@ static int cfi_amdstd_erase_chip(struct return 0; } +static int do_atmel_lock(struct map_info *map, struct flchip *chip, + unsigned long adr, int len, void *thunk) +{ + struct cfi_private *cfi = map->fldrv_priv; + int ret; + + spin_lock(chip->mutex); + ret = get_chip(map, chip, adr + chip->start, FL_LOCKING); + if (ret) + goto out_unlock; + chip->state = FL_LOCKING; + + DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n", + __func__, adr, len); + + 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(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(0x40), chip->start + adr); + + chip->state = FL_READY; + put_chip(map, chip, adr + chip->start); + ret = 0; + +out_unlock: + spin_unlock(chip->mutex); + return ret; +} + +static int do_atmel_unlock(struct map_info *map, struct flchip *chip, + unsigned long adr, int len, void *thunk) +{ + struct cfi_private *cfi = map->fldrv_priv; + int ret; + + spin_lock(chip->mutex); + ret = get_chip(map, chip, adr + chip->start, FL_UNLOCKING); + if (ret) + goto out_unlock; + chip->state = FL_UNLOCKING; + + DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n", + __func__, adr, len); + + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, + cfi->device_type, NULL); + map_write(map, CMD(0x70), adr); + + chip->state = FL_READY; + put_chip(map, chip, adr + chip->start); + ret = 0; + +out_unlock: + spin_unlock(chip->mutex); + return ret; +} + +static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, size_t len) +{ + return cfi_varsize_frob(mtd, do_atmel_lock, ofs, len, NULL); +} + +static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) +{ + return cfi_varsize_frob(mtd, do_atmel_unlock, ofs, len, NULL); +} + static void cfi_amdstd_sync (struct mtd_info *mtd) { diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index 8f39d0a..1154dac 100644 --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c @@ -111,6 +111,7 @@ #define I82802AC 0x00ac #define MX29LV040C 0x004F #define MX29LV160T 0x22C4 #define MX29LV160B 0x2249 +#define MX29F040 0x00A4 #define MX29F016 0x00AD #define MX29F002T 0x00B0 #define MX29F004T 0x0045 @@ -1172,6 +1173,19 @@ static const struct amd_flash_info jedec } }, { .mfr_id = MANUFACTURER_MACRONIX, + .dev_id = MX29F040, + .name = "Macronix MX29F040", + .uaddr = { + [0] = MTD_UADDR_0x0555_0x02AA /* x8 */ + }, + .DevSize = SIZE_512KiB, + .CmdSet = P_ID_AMD_STD, + .NumEraseRegions= 1, + .regions = { + ERASEINFO(0x10000,8), + } + }, { + .mfr_id = MANUFACTURER_MACRONIX, .dev_id = MX29F016, .name = "Macronix MX29F016", .uaddr = { diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index ede3561..401c6a2 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c @@ -18,6 +18,7 @@ #include #include #include #include +#include #define VERSION "$Revision: 1.30 $" @@ -236,6 +237,8 @@ static int _block2mtd_write(struct block } return 0; } + + static int block2mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { @@ -299,6 +302,19 @@ static struct block2mtd_dev *add_device( /* Get a handle on the device */ bdev = open_bdev_excl(devname, O_RDWR, NULL); +#ifndef MODULE + if (IS_ERR(bdev)) { + + /* We might not have rootfs mounted at this point. Try + to resolve the device name by other means. */ + + dev_t dev = name_to_dev_t(devname); + if (dev != 0) { + bdev = open_by_devnum(dev, FMODE_WRITE | FMODE_READ); + } + } +#endif + if (IS_ERR(bdev)) { ERROR("error: cannot open device %s", devname); goto devinit_err; @@ -393,26 +409,6 @@ static int parse_num(size_t *num, const } -static int parse_name(char **pname, const char *token, size_t limit) -{ - size_t len; - char *name; - - len = strlen(token) + 1; - if (len > limit) - return -ENOSPC; - - name = kmalloc(len, GFP_KERNEL); - if (!name) - return -ENOMEM; - - strcpy(name, token); - - *pname = name; - return 0; -} - - static inline void kill_final_newline(char *str) { char *newline = strrchr(str, '\n'); @@ -426,9 +422,15 @@ #define parse_err(fmt, args...) do { \ return 0; \ } while (0) -static int block2mtd_setup(const char *val, struct kernel_param *kp) +#ifndef MODULE +static int block2mtd_init_called = 0; +static __initdata char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */ +#endif + + +static int block2mtd_setup2(const char *val) { - char buf[80+12]; /* 80 for device, 12 for erase size */ + char buf[80 + 12]; /* 80 for device, 12 for erase size */ char *str = buf; char *token[2]; char *name; @@ -450,13 +452,9 @@ static int block2mtd_setup(const char *v if (!token[0]) parse_err("no argument"); - ret = parse_name(&name, token[0], 80); - if (ret == -ENOMEM) - parse_err("out of memory"); - if (ret == -ENOSPC) - parse_err("name too long"); - if (ret) - return 0; + name = token[0]; + if (strlen(name) + 1 > 80) + parse_err("device name too long"); if (token[1]) { ret = parse_num(&erase_size, token[1]); @@ -472,13 +470,48 @@ static int block2mtd_setup(const char *v } +static int block2mtd_setup(const char *val, struct kernel_param *kp) +{ +#ifdef MODULE + return block2mtd_setup2(val); +#else + /* If more parameters are later passed in via + /sys/module/block2mtd/parameters/block2mtd + and block2mtd_init() has already been called, + we can parse the argument now. */ + + if (block2mtd_init_called) + return block2mtd_setup2(val); + + /* During early boot stage, we only save the parameters + here. We must parse them later: if the param passed + from kernel boot command line, block2mtd_setup() is + called so early that it is not possible to resolve + the device (even kmalloc() fails). Deter that work to + block2mtd_setup2(). */ + + strlcpy(block2mtd_paramline, val, sizeof(block2mtd_paramline)); + + return 0; +#endif +} + + module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200); MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=[,]\""); static int __init block2mtd_init(void) { + int ret = 0; INFO("version " VERSION); - return 0; + +#ifndef MODULE + if (strlen(block2mtd_paramline)) + ret = block2mtd_setup2(block2mtd_paramline); + block2mtd_init_called = 1; +#endif + + return ret; } diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index a846614..ef4a731 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -406,13 +406,13 @@ struct flash_info { static struct flash_info __devinitdata m25p_data [] = { /* REVISIT: fill in JEDEC ids, for parts that have them */ - { "m25p05", 0x05, 0x0000, 32 * 1024, 2 }, - { "m25p10", 0x10, 0x0000, 32 * 1024, 4 }, - { "m25p20", 0x11, 0x0000, 64 * 1024, 4 }, - { "m25p40", 0x12, 0x0000, 64 * 1024, 8 }, + { "m25p05", 0x05, 0x2010, 32 * 1024, 2 }, + { "m25p10", 0x10, 0x2011, 32 * 1024, 4 }, + { "m25p20", 0x11, 0x2012, 64 * 1024, 4 }, + { "m25p40", 0x12, 0x2013, 64 * 1024, 8 }, { "m25p80", 0x13, 0x0000, 64 * 1024, 16 }, - { "m25p16", 0x14, 0x0000, 64 * 1024, 32 }, - { "m25p32", 0x15, 0x0000, 64 * 1024, 64 }, + { "m25p16", 0x14, 0x2015, 64 * 1024, 32 }, + { "m25p32", 0x15, 0x2016, 64 * 1024, 64 }, { "m25p64", 0x16, 0x2017, 64 * 1024, 128 }, }; diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c index 6f9bbf6..2c01497 100644 --- a/drivers/mtd/devices/pmc551.c +++ b/drivers/mtd/devices/pmc551.c @@ -99,10 +99,6 @@ #include #include #include -#ifndef CONFIG_PCI -#error Enable PCI in your kernel config -#endif - #include #include #include diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 83d0b2a..64d1b6a 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -13,13 +13,13 @@ config MTD_COMPLEX_MAPPINGS config MTD_PHYSMAP tristate "CFI Flash device in physical memory map" - depends on MTD_CFI + depends on MTD_CFI || MTD_JEDECPROBE || MTD_ROM help - This provides a 'mapping' driver which allows the CFI probe and - command set driver code to communicate with flash chips which - are mapped physically into the CPU's memory. You will need to - configure the physical address and size of the flash chips on - your particular board as well as the bus width, either statically + This provides a 'mapping' driver which allows the NOR Flash and + ROM driver code to communicate with chips which are mapped + physically into the CPU's memory. You will need to configure + the physical address and size of the flash chips on your + particular board as well as the bus width, either statically with config options or at run-time. config MTD_PHYSMAP_START diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index fb8b4f7..5b6acfc 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -62,15 +62,12 @@ static loff_t mtd_lseek (struct file *fi struct mtd_info *mtd = mfi->mtd; switch (orig) { - case 0: - /* SEEK_SET */ + case SEEK_SET: break; - case 1: - /* SEEK_CUR */ + case SEEK_CUR: offset += file->f_pos; break; - case 2: - /* SEEK_END */ + case SEEK_END: offset += mtd->size; break; default: diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 3db77ee..c99302e 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -11,7 +11,7 @@ config MTD_NAND help This enables support for accessing all type of NAND flash devices. For further information see - . + . config MTD_NAND_VERIFY_WRITE bool "Verify NAND page writes" diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 0a54d00..975b2ef 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2224,7 +2224,7 @@ static struct nand_flash_dev *nand_get_f } /* Try to identify manufacturer */ - for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_id++) { + for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) { if (nand_manuf_ids[maf_idx].id == *maf_id) break; } diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c index fbeedc3..51c7288 100644 --- a/drivers/mtd/nand/sharpsl.c +++ b/drivers/mtd/nand/sharpsl.c @@ -78,7 +78,7 @@ static struct mtd_partition sharpsl_nand /* * hardware specific access to control-lines * ctrl: - * NAND_CNE: bit 0 -> bit 0 & 4 + * NAND_CNE: bit 0 -> ! bit 0 & 4 * NAND_CLE: bit 1 -> bit 1 * NAND_ALE: bit 2 -> bit 2 * @@ -92,7 +92,10 @@ static void sharpsl_nand_hwcontrol(struc unsigned char bits = ctrl & 0x07; bits |= (ctrl & 0x01) << 4; - writeb((readb(FLASHCTL) & 0x17) | bits, FLASHCTL); + + bits ^= 0x11; + + writeb((readb(FLASHCTL) & ~0x17) | bits, FLASHCTL); } if (cmd != NAND_CMD_NONE) diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index 7675b33..5a6b4d6 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -21,6 +21,9 @@ #include #include #include "nodelist.h" +static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, + struct jffs2_node_frag *this); + void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list) { struct jffs2_full_dirent **prev = list; @@ -87,7 +90,8 @@ void jffs2_truncate_fragtree(struct jffs } } -void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this) +static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, + struct jffs2_node_frag *this) { if (this->node) { this->node->frags--; diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index cae92c1..0ddfd70 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -334,7 +334,6 @@ void jffs2_kill_fragtree(struct rb_root struct rb_node *rb_next(struct rb_node *); struct rb_node *rb_prev(struct rb_node *); void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root); -void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this); int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn); diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index 25bc1ae..4da09ce 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c @@ -1215,7 +1215,6 @@ int jffs2_garbage_collect_xattr_datum(st rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE); if (rc) { JFFS2_WARNING("jffs2_reserve_space_gc()=%d, request=%u\n", rc, totlen); - rc = rc ? rc : -EBADFD; goto out; } rc = save_xattr_datum(c, xd); diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index 09bfae6..123948b 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h @@ -199,6 +199,18 @@ struct cfi_pri_amdstd { uint8_t TopBottom; } __attribute__((packed)); +/* Vendor-Specific PRI for Atmel chips (command set 0x0002) */ + +struct cfi_pri_atmel { + uint8_t pri[3]; + uint8_t MajorVersion; + uint8_t MinorVersion; + uint8_t Features; + uint8_t BottomBoot; + uint8_t BurstMode; + uint8_t PageMode; +} __attribute__((packed)); + struct cfi_pri_query { uint8_t NumFields; uint32_t ProtField[1]; /* Not host ordered */ @@ -464,6 +476,7 @@ #define CFI_MFR_ANY 0xffff #define CFI_ID_ANY 0xffff #define CFI_MFR_AMD 0x0001 +#define CFI_MFR_ATMEL 0x001F #define CFI_MFR_ST 0x0020 /* STMicroelectronics */ void cfi_fixup(struct mtd_info *mtd, struct cfi_fixup* fixups);