aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-04-27 18:34:57 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-04-27 18:34:57 -0400
commitf00546363fff1576ceddc2690d47e5f9c1dd2e05 (patch)
treef6cb8965b6754fc6ce7570cf1471ebe9874e509a
parent50f732ee63b91eb08a29974b36bd63e1150bb642 (diff)
parent28b57cddb3ed4f7999e4b76ef36ebaaf6e2e0c37 (diff)
Merge git://git.infradead.org/mtd-2.6
* git://git.infradead.org/mtd-2.6: (46 commits) [MTD] [MAPS] drivers/mtd/maps/ck804xrom.c: convert pci_module_init() [MTD] [NAND] CM-x270 MTD driver [MTD] [NAND] Wrong calculation of page number in nand_block_bad() [MTD] [MAPS] fix plat-ram printk format [JFFS2] Fix compr_rubin.c build after include file elimination. [JFFS2] Handle inodes with only a single metadata node with non-zero isize [JFFS2] Tidy up licensing/copyright boilerplate. [MTD] [OneNAND] Exit loop only when column start with 0 [MTD] [OneNAND] Fix access the past of the real oobfree array [MTD] [OneNAND] Update Samsung OneNAND official URL [JFFS2] Better fix for all-zero node headers [JFFS2] Improve read_inode memory usage, v2. [JFFS2] Improve failure mode if inode checking leaves unchecked space. [JFFS2] Fix cross-endian build. [MTD] Finish conversion mtd_blkdevs to use the kthread API [JFFS2] Obsolete dirent nodes immediately on unlink, where possible. Use menuconfig objects: MTD [MTD] mtd_blkdevs: Convert to use the kthread API [MTD] Fix fwh_lock locking [JFFS2] Speed up mount for directly-mapped NOR flash ...
-rw-r--r--drivers/mtd/Kconfig30
-rw-r--r--drivers/mtd/chips/Kconfig12
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c93
-rw-r--r--drivers/mtd/chips/fwh_lock.h3
-rw-r--r--drivers/mtd/devices/Kconfig26
-rw-r--r--drivers/mtd/devices/Makefile1
-rw-r--r--drivers/mtd/devices/at91_dataflash26.c485
-rw-r--r--drivers/mtd/devices/block2mtd.c67
-rw-r--r--drivers/mtd/maps/Kconfig47
-rw-r--r--drivers/mtd/maps/Makefile2
-rw-r--r--drivers/mtd/maps/alchemy-flash.c9
-rw-r--r--drivers/mtd/maps/ck804xrom.c2
-rw-r--r--drivers/mtd/maps/plat-ram.c3
-rw-r--r--drivers/mtd/maps/pmcmsp-flash.c184
-rw-r--r--drivers/mtd/maps/pmcmsp-ramroot.c105
-rw-r--r--drivers/mtd/mtd_blkdevs.c43
-rw-r--r--drivers/mtd/mtdchar.c2
-rw-r--r--drivers/mtd/nand/Kconfig63
-rw-r--r--drivers/mtd/nand/Makefile1
-rw-r--r--drivers/mtd/nand/cafe.c25
-rw-r--r--drivers/mtd/nand/cmx270_nand.c267
-rw-r--r--drivers/mtd/nand/nand_base.c8
-rw-r--r--drivers/mtd/nand/nand_ids.c4
-rw-r--r--drivers/mtd/nand/nandsim.c518
-rw-r--r--drivers/mtd/onenand/Kconfig15
-rw-r--r--drivers/mtd/onenand/onenand_base.c21
-rw-r--r--fs/jffs2/LICENCE7
-rw-r--r--fs/jffs2/Makefile1
-rw-r--r--fs/jffs2/README.Locking1
-rw-r--r--fs/jffs2/TODO3
-rw-r--r--fs/jffs2/acl.c3
-rw-r--r--fs/jffs2/acl.h3
-rw-r--r--fs/jffs2/background.c4
-rw-r--r--fs/jffs2/build.c4
-rw-r--r--fs/jffs2/compr.c144
-rw-r--r--fs/jffs2/compr.h17
-rw-r--r--fs/jffs2/compr_rtime.c3
-rw-r--r--fs/jffs2/compr_rubin.c81
-rw-r--r--fs/jffs2/compr_rubin.h21
-rw-r--r--fs/jffs2/compr_zlib.c4
-rw-r--r--fs/jffs2/comprtest.c307
-rw-r--r--fs/jffs2/debug.c5
-rw-r--r--fs/jffs2/debug.h5
-rw-r--r--fs/jffs2/dir.c4
-rw-r--r--fs/jffs2/erase.c6
-rw-r--r--fs/jffs2/file.c4
-rw-r--r--fs/jffs2/fs.c4
-rw-r--r--fs/jffs2/gc.c7
-rw-r--r--fs/jffs2/ioctl.c4
-rw-r--r--fs/jffs2/jffs2_fs_i.h11
-rw-r--r--fs/jffs2/jffs2_fs_sb.h11
-rw-r--r--fs/jffs2/malloc.c4
-rw-r--r--fs/jffs2/nodelist.c482
-rw-r--r--fs/jffs2/nodelist.h40
-rw-r--r--fs/jffs2/nodemgmt.c9
-rw-r--r--fs/jffs2/os-linux.h4
-rw-r--r--fs/jffs2/pushpull.h72
-rw-r--r--fs/jffs2/read.c4
-rw-r--r--fs/jffs2/readinode.c851
-rw-r--r--fs/jffs2/scan.c62
-rw-r--r--fs/jffs2/security.c3
-rw-r--r--fs/jffs2/summary.c12
-rw-r--r--fs/jffs2/summary.h10
-rw-r--r--fs/jffs2/super.c6
-rw-r--r--fs/jffs2/symlink.c5
-rw-r--r--fs/jffs2/wbuf.c15
-rw-r--r--fs/jffs2/write.c7
-rw-r--r--fs/jffs2/writev.c4
-rw-r--r--fs/jffs2/xattr.c3
-rw-r--r--fs/jffs2/xattr.h3
-rw-r--r--fs/jffs2/xattr_trusted.c3
-rw-r--r--fs/jffs2/xattr_user.c3
-rw-r--r--include/linux/mtd/iflash.h98
-rw-r--r--include/linux/mtd/mtd.h1
-rw-r--r--include/linux/mtd/nand.h1
75 files changed, 2678 insertions, 1724 deletions
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 6d1b91bf7ad5..c1b47db29bd2 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -1,8 +1,6 @@
1# $Id: Kconfig,v 1.11 2005/11/07 11:14:19 gleixner Exp $ 1# $Id: Kconfig,v 1.11 2005/11/07 11:14:19 gleixner Exp $
2 2
3menu "Memory Technology Devices (MTD)" 3menuconfig MTD
4
5config MTD
6 tristate "Memory Technology Device (MTD) support" 4 tristate "Memory Technology Device (MTD) support"
7 help 5 help
8 Memory Technology Devices are flash, RAM and similar chips, often 6 Memory Technology Devices are flash, RAM and similar chips, often
@@ -13,9 +11,10 @@ config MTD
13 them. It will also allow you to select individual drivers for 11 them. It will also allow you to select individual drivers for
14 particular hardware and users of MTD devices. If unsure, say N. 12 particular hardware and users of MTD devices. If unsure, say N.
15 13
14if MTD
15
16config MTD_DEBUG 16config MTD_DEBUG
17 bool "Debugging" 17 bool "Debugging"
18 depends on MTD
19 help 18 help
20 This turns on low-level debugging for the entire MTD sub-system. 19 This turns on low-level debugging for the entire MTD sub-system.
21 Normally, you should say 'N'. 20 Normally, you should say 'N'.
@@ -29,7 +28,6 @@ config MTD_DEBUG_VERBOSE
29 28
30config MTD_CONCAT 29config MTD_CONCAT
31 tristate "MTD concatenating support" 30 tristate "MTD concatenating support"
32 depends on MTD
33 help 31 help
34 Support for concatenating several MTD devices into a single 32 Support for concatenating several MTD devices into a single
35 (virtual) one. This allows you to have -for example- a JFFS(2) 33 (virtual) one. This allows you to have -for example- a JFFS(2)
@@ -38,7 +36,6 @@ config MTD_CONCAT
38 36
39config MTD_PARTITIONS 37config MTD_PARTITIONS
40 bool "MTD partitioning support" 38 bool "MTD partitioning support"
41 depends on MTD
42 help 39 help
43 If you have a device which needs to divide its flash chip(s) up 40 If you have a device which needs to divide its flash chip(s) up
44 into multiple 'partitions', each of which appears to the user as 41 into multiple 'partitions', each of which appears to the user as
@@ -153,11 +150,9 @@ config MTD_AFS_PARTS
153 'armflash' map driver (CONFIG_MTD_ARMFLASH) does this, for example. 150 'armflash' map driver (CONFIG_MTD_ARMFLASH) does this, for example.
154 151
155comment "User Modules And Translation Layers" 152comment "User Modules And Translation Layers"
156 depends on MTD
157 153
158config MTD_CHAR 154config MTD_CHAR
159 tristate "Direct char device access to MTD devices" 155 tristate "Direct char device access to MTD devices"
160 depends on MTD
161 help 156 help
162 This provides a character device for each MTD device present in 157 This provides a character device for each MTD device present in
163 the system, allowing the user to read and write directly to the 158 the system, allowing the user to read and write directly to the
@@ -166,12 +161,12 @@ config MTD_CHAR
166 161
167config MTD_BLKDEVS 162config MTD_BLKDEVS
168 tristate "Common interface to block layer for MTD 'translation layers'" 163 tristate "Common interface to block layer for MTD 'translation layers'"
169 depends on MTD && BLOCK 164 depends on BLOCK
170 default n 165 default n
171 166
172config MTD_BLOCK 167config MTD_BLOCK
173 tristate "Caching block device access to MTD devices" 168 tristate "Caching block device access to MTD devices"
174 depends on MTD && BLOCK 169 depends on BLOCK
175 select MTD_BLKDEVS 170 select MTD_BLKDEVS
176 ---help--- 171 ---help---
177 Although most flash chips have an erase size too large to be useful 172 Although most flash chips have an erase size too large to be useful
@@ -194,7 +189,7 @@ config MTD_BLOCK
194 189
195config MTD_BLOCK_RO 190config MTD_BLOCK_RO
196 tristate "Readonly block device access to MTD devices" 191 tristate "Readonly block device access to MTD devices"
197 depends on MTD_BLOCK!=y && MTD && BLOCK 192 depends on MTD_BLOCK!=y && BLOCK
198 select MTD_BLKDEVS 193 select MTD_BLKDEVS
199 help 194 help
200 This allows you to mount read-only file systems (such as cramfs) 195 This allows you to mount read-only file systems (such as cramfs)
@@ -206,7 +201,7 @@ config MTD_BLOCK_RO
206 201
207config FTL 202config FTL
208 tristate "FTL (Flash Translation Layer) support" 203 tristate "FTL (Flash Translation Layer) support"
209 depends on MTD && BLOCK 204 depends on BLOCK
210 select MTD_BLKDEVS 205 select MTD_BLKDEVS
211 ---help--- 206 ---help---
212 This provides support for the original Flash Translation Layer which 207 This provides support for the original Flash Translation Layer which
@@ -223,7 +218,7 @@ config FTL
223 218
224config NFTL 219config NFTL
225 tristate "NFTL (NAND Flash Translation Layer) support" 220 tristate "NFTL (NAND Flash Translation Layer) support"
226 depends on MTD && BLOCK 221 depends on BLOCK
227 select MTD_BLKDEVS 222 select MTD_BLKDEVS
228 ---help--- 223 ---help---
229 This provides support for the NAND Flash Translation Layer which is 224 This provides support for the NAND Flash Translation Layer which is
@@ -247,7 +242,7 @@ config NFTL_RW
247 242
248config INFTL 243config INFTL
249 tristate "INFTL (Inverse NAND Flash Translation Layer) support" 244 tristate "INFTL (Inverse NAND Flash Translation Layer) support"
250 depends on MTD && BLOCK 245 depends on BLOCK
251 select MTD_BLKDEVS 246 select MTD_BLKDEVS
252 ---help--- 247 ---help---
253 This provides support for the Inverse NAND Flash Translation 248 This provides support for the Inverse NAND Flash Translation
@@ -265,7 +260,7 @@ config INFTL
265 260
266config RFD_FTL 261config RFD_FTL
267 tristate "Resident Flash Disk (Flash Translation Layer) support" 262 tristate "Resident Flash Disk (Flash Translation Layer) support"
268 depends on MTD && BLOCK 263 depends on BLOCK
269 select MTD_BLKDEVS 264 select MTD_BLKDEVS
270 ---help--- 265 ---help---
271 This provides support for the flash translation layer known 266 This provides support for the flash translation layer known
@@ -276,7 +271,7 @@ config RFD_FTL
276 271
277config SSFDC 272config SSFDC
278 tristate "NAND SSFDC (SmartMedia) read only translation layer" 273 tristate "NAND SSFDC (SmartMedia) read only translation layer"
279 depends on MTD && BLOCK 274 depends on BLOCK
280 select MTD_BLKDEVS 275 select MTD_BLKDEVS
281 help 276 help
282 This enables read only access to SmartMedia formatted NAND 277 This enables read only access to SmartMedia formatted NAND
@@ -294,5 +289,4 @@ source "drivers/mtd/onenand/Kconfig"
294 289
295source "drivers/mtd/ubi/Kconfig" 290source "drivers/mtd/ubi/Kconfig"
296 291
297endmenu 292endif # MTD
298
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig
index 72e6d73beb40..d28e0fc85e12 100644
--- a/drivers/mtd/chips/Kconfig
+++ b/drivers/mtd/chips/Kconfig
@@ -6,7 +6,6 @@ menu "RAM/ROM/Flash chip drivers"
6 6
7config MTD_CFI 7config MTD_CFI
8 tristate "Detect flash chips by Common Flash Interface (CFI) probe" 8 tristate "Detect flash chips by Common Flash Interface (CFI) probe"
9 depends on MTD
10 select MTD_GEN_PROBE 9 select MTD_GEN_PROBE
11 help 10 help
12 The Common Flash Interface specification was developed by Intel, 11 The Common Flash Interface specification was developed by Intel,
@@ -18,7 +17,6 @@ config MTD_CFI
18 17
19config MTD_JEDECPROBE 18config MTD_JEDECPROBE
20 tristate "Detect non-CFI AMD/JEDEC-compatible flash chips" 19 tristate "Detect non-CFI AMD/JEDEC-compatible flash chips"
21 depends on MTD
22 select MTD_GEN_PROBE 20 select MTD_GEN_PROBE
23 help 21 help
24 This option enables JEDEC-style probing of flash chips which are not 22 This option enables JEDEC-style probing of flash chips which are not
@@ -213,21 +211,18 @@ config MTD_CFI_UTIL
213 211
214config MTD_RAM 212config MTD_RAM
215 tristate "Support for RAM chips in bus mapping" 213 tristate "Support for RAM chips in bus mapping"
216 depends on MTD
217 help 214 help
218 This option enables basic support for RAM chips accessed through 215 This option enables basic support for RAM chips accessed through
219 a bus mapping driver. 216 a bus mapping driver.
220 217
221config MTD_ROM 218config MTD_ROM
222 tristate "Support for ROM chips in bus mapping" 219 tristate "Support for ROM chips in bus mapping"
223 depends on MTD
224 help 220 help
225 This option enables basic support for ROM chips accessed through 221 This option enables basic support for ROM chips accessed through
226 a bus mapping driver. 222 a bus mapping driver.
227 223
228config MTD_ABSENT 224config MTD_ABSENT
229 tristate "Support for absent chips in bus mapping" 225 tristate "Support for absent chips in bus mapping"
230 depends on MTD
231 help 226 help
232 This option enables support for a dummy probing driver used to 227 This option enables support for a dummy probing driver used to
233 allocated placeholder MTD devices on systems that have socketed 228 allocated placeholder MTD devices on systems that have socketed
@@ -237,7 +232,6 @@ config MTD_ABSENT
237 with this driver will return -ENODEV upon access. 232 with this driver will return -ENODEV upon access.
238 233
239config MTD_OBSOLETE_CHIPS 234config MTD_OBSOLETE_CHIPS
240 depends on MTD
241 bool "Older (theoretically obsoleted now) drivers for non-CFI chips" 235 bool "Older (theoretically obsoleted now) drivers for non-CFI chips"
242 help 236 help
243 This option does not enable any code directly, but will allow you to 237 This option does not enable any code directly, but will allow you to
@@ -250,7 +244,7 @@ config MTD_OBSOLETE_CHIPS
250 244
251config MTD_AMDSTD 245config MTD_AMDSTD
252 tristate "AMD compatible flash chip support (non-CFI)" 246 tristate "AMD compatible flash chip support (non-CFI)"
253 depends on MTD && MTD_OBSOLETE_CHIPS && BROKEN 247 depends on MTD_OBSOLETE_CHIPS && BROKEN
254 help 248 help
255 This option enables support for flash chips using AMD-compatible 249 This option enables support for flash chips using AMD-compatible
256 commands, including some which are not CFI-compatible and hence 250 commands, including some which are not CFI-compatible and hence
@@ -260,7 +254,7 @@ config MTD_AMDSTD
260 254
261config MTD_SHARP 255config MTD_SHARP
262 tristate "pre-CFI Sharp chip support" 256 tristate "pre-CFI Sharp chip support"
263 depends on MTD && MTD_OBSOLETE_CHIPS 257 depends on MTD_OBSOLETE_CHIPS
264 help 258 help
265 This option enables support for flash chips using Sharp-compatible 259 This option enables support for flash chips using Sharp-compatible
266 commands, including some which are not CFI-compatible and hence 260 commands, including some which are not CFI-compatible and hence
@@ -268,7 +262,7 @@ config MTD_SHARP
268 262
269config MTD_JEDEC 263config MTD_JEDEC
270 tristate "JEDEC device support" 264 tristate "JEDEC device support"
271 depends on MTD && MTD_OBSOLETE_CHIPS && BROKEN 265 depends on MTD_OBSOLETE_CHIPS && BROKEN
272 help 266 help
273 Enable older JEDEC flash interface devices for self 267 Enable older JEDEC flash interface devices for self
274 programming flash. It is commonly used in older AMD chips. It is 268 programming flash. It is commonly used in older AMD chips. It is
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index f334959a335b..2f19fa78d24a 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -15,6 +15,8 @@
15 * - optimized write buffer method 15 * - optimized write buffer method
16 * 02/05/2002 Christopher Hoover <ch@hpl.hp.com>/<ch@murgatroid.com> 16 * 02/05/2002 Christopher Hoover <ch@hpl.hp.com>/<ch@murgatroid.com>
17 * - reworked lock/unlock/erase support for var size flash 17 * - reworked lock/unlock/erase support for var size flash
18 * 21/03/2007 Rodolfo Giometti <giometti@linux.it>
19 * - auto unlock sectors on resume for auto locking flash on power up
18 */ 20 */
19 21
20#include <linux/module.h> 22#include <linux/module.h>
@@ -30,6 +32,7 @@
30#include <linux/delay.h> 32#include <linux/delay.h>
31#include <linux/interrupt.h> 33#include <linux/interrupt.h>
32#include <linux/reboot.h> 34#include <linux/reboot.h>
35#include <linux/bitmap.h>
33#include <linux/mtd/xip.h> 36#include <linux/mtd/xip.h>
34#include <linux/mtd/map.h> 37#include <linux/mtd/map.h>
35#include <linux/mtd/mtd.h> 38#include <linux/mtd/mtd.h>
@@ -220,6 +223,15 @@ static void fixup_use_write_buffers(struct mtd_info *mtd, void *param)
220 } 223 }
221} 224}
222 225
226/*
227 * Some chips power-up with all sectors locked by default.
228 */
229static void fixup_use_powerup_lock(struct mtd_info *mtd, void *param)
230{
231 printk(KERN_INFO "Using auto-unlock on power-up/resume\n" );
232 mtd->flags |= MTD_STUPID_LOCK;
233}
234
223static struct cfi_fixup cfi_fixup_table[] = { 235static struct cfi_fixup cfi_fixup_table[] = {
224#ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE 236#ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
225 { CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash, NULL }, 237 { CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash, NULL },
@@ -232,6 +244,7 @@ static struct cfi_fixup cfi_fixup_table[] = {
232#endif 244#endif
233 { CFI_MFR_ST, 0x00ba, /* M28W320CT */ fixup_st_m28w320ct, NULL }, 245 { CFI_MFR_ST, 0x00ba, /* M28W320CT */ fixup_st_m28w320ct, NULL },
234 { CFI_MFR_ST, 0x00bb, /* M28W320CB */ fixup_st_m28w320cb, NULL }, 246 { CFI_MFR_ST, 0x00bb, /* M28W320CB */ fixup_st_m28w320cb, NULL },
247 { MANUFACTURER_INTEL, 0x891c, fixup_use_powerup_lock, NULL, },
235 { 0, 0, NULL, NULL } 248 { 0, 0, NULL, NULL }
236}; 249};
237 250
@@ -460,6 +473,7 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd)
460 mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].offset = (j*devsize)+offset; 473 mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].offset = (j*devsize)+offset;
461 mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].erasesize = ersize; 474 mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].erasesize = ersize;
462 mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].numblocks = ernum; 475 mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].numblocks = ernum;
476 mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].lockmap = kmalloc(ernum / 8 + 1, GFP_KERNEL);
463 } 477 }
464 offset += (ersize * ernum); 478 offset += (ersize * ernum);
465 } 479 }
@@ -1825,8 +1839,7 @@ static void cfi_intelext_sync (struct mtd_info *mtd)
1825 } 1839 }
1826} 1840}
1827 1841
1828#ifdef DEBUG_LOCK_BITS 1842static int __xipram do_getlockstatus_oneblock(struct map_info *map,
1829static int __xipram do_printlockstatus_oneblock(struct map_info *map,
1830 struct flchip *chip, 1843 struct flchip *chip,
1831 unsigned long adr, 1844 unsigned long adr,
1832 int len, void *thunk) 1845 int len, void *thunk)
@@ -1840,8 +1853,17 @@ static int __xipram do_printlockstatus_oneblock(struct map_info *map,
1840 chip->state = FL_JEDEC_QUERY; 1853 chip->state = FL_JEDEC_QUERY;
1841 status = cfi_read_query(map, adr+(2*ofs_factor)); 1854 status = cfi_read_query(map, adr+(2*ofs_factor));
1842 xip_enable(map, chip, 0); 1855 xip_enable(map, chip, 0);
1856 return status;
1857}
1858
1859#ifdef DEBUG_LOCK_BITS
1860static int __xipram do_printlockstatus_oneblock(struct map_info *map,
1861 struct flchip *chip,
1862 unsigned long adr,
1863 int len, void *thunk)
1864{
1843 printk(KERN_DEBUG "block status register for 0x%08lx is %x\n", 1865 printk(KERN_DEBUG "block status register for 0x%08lx is %x\n",
1844 adr, status); 1866 adr, do_getlockstatus_oneblock(map, chip, adr, len, thunk));
1845 return 0; 1867 return 0;
1846} 1868}
1847#endif 1869#endif
@@ -2216,14 +2238,45 @@ static int cfi_intelext_get_user_prot_info(struct mtd_info *mtd,
2216 2238
2217#endif 2239#endif
2218 2240
2241static void cfi_intelext_save_locks(struct mtd_info *mtd)
2242{
2243 struct mtd_erase_region_info *region;
2244 int block, status, i;
2245 unsigned long adr;
2246 size_t len;
2247
2248 for (i = 0; i < mtd->numeraseregions; i++) {
2249 region = &mtd->eraseregions[i];
2250 if (!region->lockmap)
2251 continue;
2252
2253 for (block = 0; block < region->numblocks; block++){
2254 len = region->erasesize;
2255 adr = region->offset + block * len;
2256
2257 status = cfi_varsize_frob(mtd,
2258 do_getlockstatus_oneblock, adr, len, 0);
2259 if (status)
2260 set_bit(block, region->lockmap);
2261 else
2262 clear_bit(block, region->lockmap);
2263 }
2264 }
2265}
2266
2219static int cfi_intelext_suspend(struct mtd_info *mtd) 2267static int cfi_intelext_suspend(struct mtd_info *mtd)
2220{ 2268{
2221 struct map_info *map = mtd->priv; 2269 struct map_info *map = mtd->priv;
2222 struct cfi_private *cfi = map->fldrv_priv; 2270 struct cfi_private *cfi = map->fldrv_priv;
2271 struct cfi_pri_intelext *extp = cfi->cmdset_priv;
2223 int i; 2272 int i;
2224 struct flchip *chip; 2273 struct flchip *chip;
2225 int ret = 0; 2274 int ret = 0;
2226 2275
2276 if ((mtd->flags & MTD_STUPID_LOCK)
2277 && extp && (extp->FeatureSupport & (1 << 5)))
2278 cfi_intelext_save_locks(mtd);
2279
2227 for (i=0; !ret && i<cfi->numchips; i++) { 2280 for (i=0; !ret && i<cfi->numchips; i++) {
2228 chip = &cfi->chips[i]; 2281 chip = &cfi->chips[i];
2229 2282
@@ -2285,10 +2338,33 @@ static int cfi_intelext_suspend(struct mtd_info *mtd)
2285 return ret; 2338 return ret;
2286} 2339}
2287 2340
2341static void cfi_intelext_restore_locks(struct mtd_info *mtd)
2342{
2343 struct mtd_erase_region_info *region;
2344 int block, i;
2345 unsigned long adr;
2346 size_t len;
2347
2348 for (i = 0; i < mtd->numeraseregions; i++) {
2349 region = &mtd->eraseregions[i];
2350 if (!region->lockmap)
2351 continue;
2352
2353 for (block = 0; block < region->numblocks; block++) {
2354 len = region->erasesize;
2355 adr = region->offset + block * len;
2356
2357 if (!test_bit(block, region->lockmap))
2358 cfi_intelext_unlock(mtd, adr, len);
2359 }
2360 }
2361}
2362
2288static void cfi_intelext_resume(struct mtd_info *mtd) 2363static void cfi_intelext_resume(struct mtd_info *mtd)
2289{ 2364{
2290 struct map_info *map = mtd->priv; 2365 struct map_info *map = mtd->priv;
2291 struct cfi_private *cfi = map->fldrv_priv; 2366 struct cfi_private *cfi = map->fldrv_priv;
2367 struct cfi_pri_intelext *extp = cfi->cmdset_priv;
2292 int i; 2368 int i;
2293 struct flchip *chip; 2369 struct flchip *chip;
2294 2370
@@ -2307,6 +2383,10 @@ static void cfi_intelext_resume(struct mtd_info *mtd)
2307 2383
2308 spin_unlock(chip->mutex); 2384 spin_unlock(chip->mutex);
2309 } 2385 }
2386
2387 if ((mtd->flags & MTD_STUPID_LOCK)
2388 && extp && (extp->FeatureSupport & (1 << 5)))
2389 cfi_intelext_restore_locks(mtd);
2310} 2390}
2311 2391
2312static int cfi_intelext_reset(struct mtd_info *mtd) 2392static int cfi_intelext_reset(struct mtd_info *mtd)
@@ -2347,12 +2427,19 @@ static void cfi_intelext_destroy(struct mtd_info *mtd)
2347{ 2427{
2348 struct map_info *map = mtd->priv; 2428 struct map_info *map = mtd->priv;
2349 struct cfi_private *cfi = map->fldrv_priv; 2429 struct cfi_private *cfi = map->fldrv_priv;
2430 struct mtd_erase_region_info *region;
2431 int i;
2350 cfi_intelext_reset(mtd); 2432 cfi_intelext_reset(mtd);
2351 unregister_reboot_notifier(&mtd->reboot_notifier); 2433 unregister_reboot_notifier(&mtd->reboot_notifier);
2352 kfree(cfi->cmdset_priv); 2434 kfree(cfi->cmdset_priv);
2353 kfree(cfi->cfiq); 2435 kfree(cfi->cfiq);
2354 kfree(cfi->chips[0].priv); 2436 kfree(cfi->chips[0].priv);
2355 kfree(cfi); 2437 kfree(cfi);
2438 for (i = 0; i < mtd->numeraseregions; i++) {
2439 region = &mtd->eraseregions[i];
2440 if (region->lockmap)
2441 kfree(region->lockmap);
2442 }
2356 kfree(mtd->eraseregions); 2443 kfree(mtd->eraseregions);
2357} 2444}
2358 2445
diff --git a/drivers/mtd/chips/fwh_lock.h b/drivers/mtd/chips/fwh_lock.h
index 77303ce5dcf1..ab44f2b996f8 100644
--- a/drivers/mtd/chips/fwh_lock.h
+++ b/drivers/mtd/chips/fwh_lock.h
@@ -65,11 +65,12 @@ static int fwh_xxlock_oneblock(struct map_info *map, struct flchip *chip,
65 return ret; 65 return ret;
66 } 66 }
67 67
68 chip->oldstate = chip->state;
68 chip->state = xxlt->state; 69 chip->state = xxlt->state;
69 map_write(map, CMD(xxlt->val), adr); 70 map_write(map, CMD(xxlt->val), adr);
70 71
71 /* Done and happy. */ 72 /* Done and happy. */
72 chip->state = FL_READY; 73 chip->state = chip->oldstate;
73 put_chip(map, chip, adr); 74 put_chip(map, chip, adr);
74 spin_unlock(chip->mutex); 75 spin_unlock(chip->mutex);
75 return 0; 76 return 0;
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 440f6851da69..690c94236d7f 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -6,7 +6,7 @@ menu "Self-contained MTD device drivers"
6 6
7config MTD_PMC551 7config MTD_PMC551
8 tristate "Ramix PMC551 PCI Mezzanine RAM card support" 8 tristate "Ramix PMC551 PCI Mezzanine RAM card support"
9 depends on MTD && PCI 9 depends on PCI
10 ---help--- 10 ---help---
11 This provides a MTD device driver for the Ramix PMC551 RAM PCI card 11 This provides a MTD device driver for the Ramix PMC551 RAM PCI card
12 from Ramix Inc. <http://www.ramix.com/products/memory/pmc551.html>. 12 from Ramix Inc. <http://www.ramix.com/products/memory/pmc551.html>.
@@ -40,7 +40,7 @@ config MTD_PMC551_DEBUG
40 40
41config MTD_MS02NV 41config MTD_MS02NV
42 tristate "DEC MS02-NV NVRAM module support" 42 tristate "DEC MS02-NV NVRAM module support"
43 depends on MTD && MACH_DECSTATION 43 depends on MACH_DECSTATION
44 help 44 help
45 This is an MTD driver for the DEC's MS02-NV (54-20948-01) battery 45 This is an MTD driver for the DEC's MS02-NV (54-20948-01) battery
46 backed-up NVRAM module. The module was originally meant as an NFS 46 backed-up NVRAM module. The module was originally meant as an NFS
@@ -54,15 +54,23 @@ config MTD_MS02NV
54 54
55config MTD_DATAFLASH 55config MTD_DATAFLASH
56 tristate "Support for AT45xxx DataFlash" 56 tristate "Support for AT45xxx DataFlash"
57 depends on MTD && SPI_MASTER && EXPERIMENTAL 57 depends on SPI_MASTER && EXPERIMENTAL
58 help 58 help
59 This enables access to AT45xxx DataFlash chips, using SPI. 59 This enables access to AT45xxx DataFlash chips, using SPI.
60 Sometimes DataFlash chips are packaged inside MMC-format 60 Sometimes DataFlash chips are packaged inside MMC-format
61 cards; at this writing, the MMC stack won't handle those. 61 cards; at this writing, the MMC stack won't handle those.
62 62
63config MTD_DATAFLASH26
64 tristate "AT91RM9200 DataFlash AT26xxx"
65 depends on MTD && ARCH_AT91RM9200 && AT91_SPI
66 help
67 This enables access to the DataFlash chip (AT26xxx) on an
68 AT91RM9200-based board.
69 If you have such a board and such a DataFlash, say 'Y'.
70
63config MTD_M25P80 71config MTD_M25P80
64 tristate "Support for M25 SPI Flash" 72 tristate "Support for M25 SPI Flash"
65 depends on MTD && SPI_MASTER && EXPERIMENTAL 73 depends on SPI_MASTER && EXPERIMENTAL
66 help 74 help
67 This enables access to ST M25P80 and similar SPI flash chips, 75 This enables access to ST M25P80 and similar SPI flash chips,
68 used for program and data storage. Set up your spi devices 76 used for program and data storage. Set up your spi devices
@@ -70,7 +78,6 @@ config MTD_M25P80
70 78
71config MTD_SLRAM 79config MTD_SLRAM
72 tristate "Uncached system RAM" 80 tristate "Uncached system RAM"
73 depends on MTD
74 help 81 help
75 If your CPU cannot cache all of the physical memory in your machine, 82 If your CPU cannot cache all of the physical memory in your machine,
76 you can still use it for storage or swap by using this driver to 83 you can still use it for storage or swap by using this driver to
@@ -78,7 +85,6 @@ config MTD_SLRAM
78 85
79config MTD_PHRAM 86config MTD_PHRAM
80 tristate "Physical system RAM" 87 tristate "Physical system RAM"
81 depends on MTD
82 help 88 help
83 This is a re-implementation of the slram driver above. 89 This is a re-implementation of the slram driver above.
84 90
@@ -88,7 +94,7 @@ config MTD_PHRAM
88 94
89config MTD_LART 95config MTD_LART
90 tristate "28F160xx flash driver for LART" 96 tristate "28F160xx flash driver for LART"
91 depends on SA1100_LART && MTD 97 depends on SA1100_LART
92 help 98 help
93 This enables the flash driver for LART. Please note that you do 99 This enables the flash driver for LART. Please note that you do
94 not need any mapping/chip driver for LART. This one does it all 100 not need any mapping/chip driver for LART. This one does it all
@@ -96,7 +102,6 @@ config MTD_LART
96 102
97config MTD_MTDRAM 103config MTD_MTDRAM
98 tristate "Test driver using RAM" 104 tristate "Test driver using RAM"
99 depends on MTD
100 help 105 help
101 This enables a test MTD device driver which uses vmalloc() to 106 This enables a test MTD device driver which uses vmalloc() to
102 provide storage. You probably want to say 'N' unless you're 107 provide storage. You probably want to say 'N' unless you're
@@ -136,7 +141,7 @@ config MTDRAM_ABS_POS
136 141
137config MTD_BLOCK2MTD 142config MTD_BLOCK2MTD
138 tristate "MTD using block device" 143 tristate "MTD using block device"
139 depends on MTD && BLOCK 144 depends on BLOCK
140 help 145 help
141 This driver allows a block device to appear as an MTD. It would 146 This driver allows a block device to appear as an MTD. It would
142 generally be used in the following cases: 147 generally be used in the following cases:
@@ -150,7 +155,6 @@ comment "Disk-On-Chip Device Drivers"
150 155
151config MTD_DOC2000 156config MTD_DOC2000
152 tristate "M-Systems Disk-On-Chip 2000 and Millennium (DEPRECATED)" 157 tristate "M-Systems Disk-On-Chip 2000 and Millennium (DEPRECATED)"
153 depends on MTD
154 select MTD_DOCPROBE 158 select MTD_DOCPROBE
155 select MTD_NAND_IDS 159 select MTD_NAND_IDS
156 ---help--- 160 ---help---
@@ -173,7 +177,6 @@ config MTD_DOC2000
173 177
174config MTD_DOC2001 178config MTD_DOC2001
175 tristate "M-Systems Disk-On-Chip Millennium-only alternative driver (DEPRECATED)" 179 tristate "M-Systems Disk-On-Chip Millennium-only alternative driver (DEPRECATED)"
176 depends on MTD
177 select MTD_DOCPROBE 180 select MTD_DOCPROBE
178 select MTD_NAND_IDS 181 select MTD_NAND_IDS
179 ---help--- 182 ---help---
@@ -195,7 +198,6 @@ config MTD_DOC2001
195 198
196config MTD_DOC2001PLUS 199config MTD_DOC2001PLUS
197 tristate "M-Systems Disk-On-Chip Millennium Plus" 200 tristate "M-Systems Disk-On-Chip Millennium Plus"
198 depends on MTD
199 select MTD_DOCPROBE 201 select MTD_DOCPROBE
200 select MTD_NAND_IDS 202 select MTD_NAND_IDS
201 ---help--- 203 ---help---
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index 0f788d5c4bf8..8ab568b3f533 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -16,4 +16,5 @@ obj-$(CONFIG_MTD_MTDRAM) += mtdram.o
16obj-$(CONFIG_MTD_LART) += lart.o 16obj-$(CONFIG_MTD_LART) += lart.o
17obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o 17obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o
18obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o 18obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o
19obj-$(CONFIG_MTD_DATAFLASH26) += at91_dataflash26.o
19obj-$(CONFIG_MTD_M25P80) += m25p80.o 20obj-$(CONFIG_MTD_M25P80) += m25p80.o
diff --git a/drivers/mtd/devices/at91_dataflash26.c b/drivers/mtd/devices/at91_dataflash26.c
new file mode 100644
index 000000000000..64ce37f986fc
--- /dev/null
+++ b/drivers/mtd/devices/at91_dataflash26.c
@@ -0,0 +1,485 @@
1/*
2 * Atmel DataFlash driver for Atmel AT91RM9200 (Thunder)
3 * This is a largely modified version of at91_dataflash.c that
4 * supports AT26xxx dataflash chips. The original driver supports
5 * AT45xxx chips.
6 *
7 * Note: This driver was only tested with an AT26F004. It should be
8 * easy to make it work with other AT26xxx dataflash devices, though.
9 *
10 * Copyright (C) 2007 Hans J. Koch <hjk@linutronix.de>
11 * original Copyright (C) SAN People (Pty) Ltd
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * version 2 as published by the Free Software Foundation.
16*/
17
18#include <linux/config.h>
19#include <linux/module.h>
20#include <linux/init.h>
21#include <linux/mtd/mtd.h>
22
23#include <asm/arch/at91_spi.h>
24
25#define DATAFLASH_MAX_DEVICES 4 /* max number of dataflash devices */
26
27#define MANUFACTURER_ID_ATMEL 0x1F
28
29/* command codes */
30
31#define AT26_OP_READ_STATUS 0x05
32#define AT26_OP_READ_DEV_ID 0x9F
33#define AT26_OP_ERASE_PAGE_4K 0x20
34#define AT26_OP_READ_ARRAY_FAST 0x0B
35#define AT26_OP_SEQUENTIAL_WRITE 0xAF
36#define AT26_OP_WRITE_ENABLE 0x06
37#define AT26_OP_WRITE_DISABLE 0x04
38#define AT26_OP_SECTOR_PROTECT 0x36
39#define AT26_OP_SECTOR_UNPROTECT 0x39
40
41/* status register bits */
42
43#define AT26_STATUS_BUSY 0x01
44#define AT26_STATUS_WRITE_ENABLE 0x02
45
46struct dataflash_local
47{
48 int spi; /* SPI chip-select number */
49 unsigned int page_size; /* number of bytes per page */
50};
51
52
53/* Detected DataFlash devices */
54static struct mtd_info* mtd_devices[DATAFLASH_MAX_DEVICES];
55static int nr_devices = 0;
56
57/* Allocate a single SPI transfer descriptor. We're assuming that if multiple
58 SPI transfers occur at the same time, spi_access_bus() will serialize them.
59 If this is not valid, then either (i) each dataflash 'priv' structure
60 needs it's own transfer descriptor, (ii) we lock this one, or (iii) use
61 another mechanism. */
62static struct spi_transfer_list* spi_transfer_desc;
63
64/*
65 * Perform a SPI transfer to access the DataFlash device.
66 */
67static int do_spi_transfer(int nr, char* tx, int tx_len, char* rx, int rx_len,
68 char* txnext, int txnext_len, char* rxnext, int rxnext_len)
69{
70 struct spi_transfer_list* list = spi_transfer_desc;
71
72 list->tx[0] = tx; list->txlen[0] = tx_len;
73 list->rx[0] = rx; list->rxlen[0] = rx_len;
74
75 list->tx[1] = txnext; list->txlen[1] = txnext_len;
76 list->rx[1] = rxnext; list->rxlen[1] = rxnext_len;
77
78 list->nr_transfers = nr;
79 /* Note: spi_transfer() always returns 0, there are no error checks */
80 return spi_transfer(list);
81}
82
83/*
84 * Return the status of the DataFlash device.
85 */
86static unsigned char at91_dataflash26_status(void)
87{
88 unsigned char command[2];
89
90 command[0] = AT26_OP_READ_STATUS;
91 command[1] = 0;
92
93 do_spi_transfer(1, command, 2, command, 2, NULL, 0, NULL, 0);
94
95 return command[1];
96}
97
98/*
99 * Poll the DataFlash device until it is READY.
100 */
101static unsigned char at91_dataflash26_waitready(void)
102{
103 unsigned char status;
104
105 while (1) {
106 status = at91_dataflash26_status();
107 if (!(status & AT26_STATUS_BUSY))
108 return status;
109 }
110}
111
112/*
113 * Enable/disable write access
114 */
115 static void at91_dataflash26_write_enable(int enable)
116{
117 unsigned char cmd[2];
118
119 DEBUG(MTD_DEBUG_LEVEL3, "write_enable: enable=%i\n", enable);
120
121 if (enable)
122 cmd[0] = AT26_OP_WRITE_ENABLE;
123 else
124 cmd[0] = AT26_OP_WRITE_DISABLE;
125 cmd[1] = 0;
126
127 do_spi_transfer(1, cmd, 2, cmd, 2, NULL, 0, NULL, 0);
128}
129
130/*
131 * Protect/unprotect sector
132 */
133 static void at91_dataflash26_sector_protect(loff_t addr, int protect)
134{
135 unsigned char cmd[4];
136
137 DEBUG(MTD_DEBUG_LEVEL3, "sector_protect: addr=0x%06x prot=%d\n",
138 addr, protect);
139
140 if (protect)
141 cmd[0] = AT26_OP_SECTOR_PROTECT;
142 else
143 cmd[0] = AT26_OP_SECTOR_UNPROTECT;
144 cmd[1] = (addr & 0x00FF0000) >> 16;
145 cmd[2] = (addr & 0x0000FF00) >> 8;
146 cmd[3] = (addr & 0x000000FF);
147
148 do_spi_transfer(1, cmd, 4, cmd, 4, NULL, 0, NULL, 0);
149}
150
151/*
152 * Erase blocks of flash.
153 */
154static int at91_dataflash26_erase(struct mtd_info *mtd,
155 struct erase_info *instr)
156{
157 struct dataflash_local *priv = (struct dataflash_local *) mtd->priv;
158 unsigned char cmd[4];
159
160 DEBUG(MTD_DEBUG_LEVEL1, "dataflash_erase: addr=0x%06x len=%i\n",
161 instr->addr, instr->len);
162
163 /* Sanity checks */
164 if (priv->page_size != 4096)
165 return -EINVAL; /* Can't handle other sizes at the moment */
166
167 if ( ((instr->len % mtd->erasesize) != 0)
168 || ((instr->len % priv->page_size) != 0)
169 || ((instr->addr % priv->page_size) != 0)
170 || ((instr->addr + instr->len) > mtd->size))
171 return -EINVAL;
172
173 spi_access_bus(priv->spi);
174
175 while (instr->len > 0) {
176 at91_dataflash26_write_enable(1);
177 at91_dataflash26_sector_protect(instr->addr, 0);
178 at91_dataflash26_write_enable(1);
179 cmd[0] = AT26_OP_ERASE_PAGE_4K;
180 cmd[1] = (instr->addr & 0x00FF0000) >> 16;
181 cmd[2] = (instr->addr & 0x0000FF00) >> 8;
182 cmd[3] = (instr->addr & 0x000000FF);
183
184 DEBUG(MTD_DEBUG_LEVEL3, "ERASE: (0x%02x) 0x%02x 0x%02x"
185 "0x%02x\n",
186 cmd[0], cmd[1], cmd[2], cmd[3]);
187
188 do_spi_transfer(1, cmd, 4, cmd, 4, NULL, 0, NULL, 0);
189 at91_dataflash26_waitready();
190
191 instr->addr += priv->page_size; /* next page */
192 instr->len -= priv->page_size;
193 }
194
195 at91_dataflash26_write_enable(0);
196 spi_release_bus(priv->spi);
197
198 /* Inform MTD subsystem that erase is complete */
199 instr->state = MTD_ERASE_DONE;
200 if (instr->callback)
201 instr->callback(instr);
202
203 return 0;
204}
205
206/*
207 * Read from the DataFlash device.
208 * from : Start offset in flash device
209 * len : Number of bytes to read
210 * retlen : Number of bytes actually read
211 * buf : Buffer that will receive data
212 */
213static int at91_dataflash26_read(struct mtd_info *mtd, loff_t from, size_t len,
214 size_t *retlen, u_char *buf)
215{
216 struct dataflash_local *priv = (struct dataflash_local *) mtd->priv;
217 unsigned char cmd[5];
218
219 DEBUG(MTD_DEBUG_LEVEL1, "dataflash_read: %lli .. %lli\n",
220 from, from+len);
221
222 *retlen = 0;
223
224 /* Sanity checks */
225 if (!len)
226 return 0;
227 if (from + len > mtd->size)
228 return -EINVAL;
229
230 cmd[0] = AT26_OP_READ_ARRAY_FAST;
231 cmd[1] = (from & 0x00FF0000) >> 16;
232 cmd[2] = (from & 0x0000FF00) >> 8;
233 cmd[3] = (from & 0x000000FF);
234 /* cmd[4] is a "Don't care" byte */
235
236 DEBUG(MTD_DEBUG_LEVEL3, "READ: (0x%02x) 0x%02x 0x%02x 0x%02x\n",
237 cmd[0], cmd[1], cmd[2], cmd[3]);
238
239 spi_access_bus(priv->spi);
240 do_spi_transfer(2, cmd, 5, cmd, 5, buf, len, buf, len);
241 spi_release_bus(priv->spi);
242
243 *retlen = len;
244 return 0;
245}
246
247/*
248 * Write to the DataFlash device.
249 * to : Start offset in flash device
250 * len : Number of bytes to write
251 * retlen : Number of bytes actually written
252 * buf : Buffer containing the data
253 */
254static int at91_dataflash26_write(struct mtd_info *mtd, loff_t to, size_t len,
255 size_t *retlen, const u_char *buf)
256{
257 struct dataflash_local *priv = (struct dataflash_local *) mtd->priv;
258 unsigned int addr, buf_index = 0;
259 int ret = -EIO, sector, last_sector;
260 unsigned char status, cmd[5];
261
262 DEBUG(MTD_DEBUG_LEVEL1, "dataflash_write: %lli .. %lli\n", to, to+len);
263
264 *retlen = 0;
265
266 /* Sanity checks */
267 if (!len)
268 return 0;
269 if (to + len > mtd->size)
270 return -EINVAL;
271
272 spi_access_bus(priv->spi);
273
274 addr = to;
275 last_sector = -1;
276
277 while (buf_index < len) {
278 sector = addr / priv->page_size;
279 /* Write first byte if a new sector begins */
280 if (sector != last_sector) {
281 at91_dataflash26_write_enable(1);
282 at91_dataflash26_sector_protect(addr, 0);
283 at91_dataflash26_write_enable(1);
284
285 /* Program first byte of a new sector */
286 cmd[0] = AT26_OP_SEQUENTIAL_WRITE;
287 cmd[1] = (addr & 0x00FF0000) >> 16;
288 cmd[2] = (addr & 0x0000FF00) >> 8;
289 cmd[3] = (addr & 0x000000FF);
290 cmd[4] = buf[buf_index++];
291 do_spi_transfer(1, cmd, 5, cmd, 5, NULL, 0, NULL, 0);
292 status = at91_dataflash26_waitready();
293 addr++;
294 /* On write errors, the chip resets the write enable
295 flag. This also happens after the last byte of a
296 sector is successfully programmed. */
297 if ( ( !(status & AT26_STATUS_WRITE_ENABLE))
298 && ((addr % priv->page_size) != 0) ) {
299 DEBUG(MTD_DEBUG_LEVEL1,
300 "write error1: addr=0x%06x, "
301 "status=0x%02x\n", addr, status);
302 goto write_err;
303 }
304 (*retlen)++;
305 last_sector = sector;
306 }
307
308 /* Write subsequent bytes in the same sector */
309 cmd[0] = AT26_OP_SEQUENTIAL_WRITE;
310 cmd[1] = buf[buf_index++];
311 do_spi_transfer(1, cmd, 2, cmd, 2, NULL, 0, NULL, 0);
312 status = at91_dataflash26_waitready();
313 addr++;
314
315 if ( ( !(status & AT26_STATUS_WRITE_ENABLE))
316 && ((addr % priv->page_size) != 0) ) {
317 DEBUG(MTD_DEBUG_LEVEL1, "write error2: addr=0x%06x, "
318 "status=0x%02x\n", addr, status);
319 goto write_err;
320 }
321
322 (*retlen)++;
323 }
324
325 ret = 0;
326 at91_dataflash26_write_enable(0);
327write_err:
328 spi_release_bus(priv->spi);
329 return ret;
330}
331
332/*
333 * Initialize and register DataFlash device with MTD subsystem.
334 */
335static int __init add_dataflash(int channel, char *name, int nr_pages,
336 int pagesize)
337{
338 struct mtd_info *device;
339 struct dataflash_local *priv;
340
341 if (nr_devices >= DATAFLASH_MAX_DEVICES) {
342 printk(KERN_ERR "at91_dataflash26: Too many devices "
343 "detected\n");
344 return 0;
345 }
346
347 device = kzalloc(sizeof(struct mtd_info) + strlen(name) + 8,
348 GFP_KERNEL);
349 if (!device)
350 return -ENOMEM;
351
352 device->name = (char *)&device[1];
353 sprintf(device->name, "%s.spi%d", name, channel);
354 device->size = nr_pages * pagesize;
355 device->erasesize = pagesize;
356 device->owner = THIS_MODULE;
357 device->type = MTD_DATAFLASH;
358 device->flags = MTD_CAP_NORFLASH;
359 device->erase = at91_dataflash26_erase;
360 device->read = at91_dataflash26_read;
361 device->write = at91_dataflash26_write;
362
363 priv = (struct dataflash_local *)kzalloc(sizeof(struct dataflash_local),
364 GFP_KERNEL);
365 if (!priv) {
366 kfree(device);
367 return -ENOMEM;
368 }
369
370 priv->spi = channel;
371 priv->page_size = pagesize;
372 device->priv = priv;
373
374 mtd_devices[nr_devices] = device;
375 nr_devices++;
376 printk(KERN_INFO "at91_dataflash26: %s detected [spi%i] (%i bytes)\n",
377 name, channel, device->size);
378
379 return add_mtd_device(device);
380}
381
382/*
383 * Detect and initialize DataFlash device connected to specified SPI channel.
384 *
385 */
386
387struct dataflash26_types {
388 unsigned char id0;
389 unsigned char id1;
390 char *name;
391 int pagesize;
392 int nr_pages;
393};
394
395struct dataflash26_types df26_types[] = {
396 {
397 .id0 = 0x04,
398 .id1 = 0x00,
399 .name = "AT26F004",
400 .pagesize = 4096,
401 .nr_pages = 128,
402 },
403 {
404 .id0 = 0x45,
405 .id1 = 0x01,
406 .name = "AT26DF081A", /* Not tested ! */
407 .pagesize = 4096,
408 .nr_pages = 256,
409 },
410};
411
412static int __init at91_dataflash26_detect(int channel)
413{
414 unsigned char status, cmd[5];
415 int i;
416
417 spi_access_bus(channel);
418 status = at91_dataflash26_status();
419
420 if (status == 0 || status == 0xff) {
421 printk(KERN_ERR "at91_dataflash26_detect: status error %d\n",
422 status);
423 spi_release_bus(channel);
424 return -ENODEV;
425 }
426
427 cmd[0] = AT26_OP_READ_DEV_ID;
428 do_spi_transfer(1, cmd, 5, cmd, 5, NULL, 0, NULL, 0);
429 spi_release_bus(channel);
430
431 if (cmd[1] != MANUFACTURER_ID_ATMEL)
432 return -ENODEV;
433
434 for (i = 0; i < ARRAY_SIZE(df26_types); i++) {
435 if ( cmd[2] == df26_types[i].id0
436 && cmd[3] == df26_types[i].id1)
437 return add_dataflash(channel,
438 df26_types[i].name,
439 df26_types[i].nr_pages,
440 df26_types[i].pagesize);
441 }
442
443 printk(KERN_ERR "at91_dataflash26_detect: Unsupported device "
444 "(0x%02x/0x%02x)\n", cmd[2], cmd[3]);
445 return -ENODEV;
446}
447
448static int __init at91_dataflash26_init(void)
449{
450 spi_transfer_desc = kmalloc(sizeof(struct spi_transfer_list),
451 GFP_KERNEL);
452 if (!spi_transfer_desc)
453 return -ENOMEM;
454
455 /* DataFlash (SPI chip select 0) */
456 at91_dataflash26_detect(0);
457
458#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
459 /* DataFlash card (SPI chip select 3) */
460 at91_dataflash26_detect(3);
461#endif
462 return 0;
463}
464
465static void __exit at91_dataflash26_exit(void)
466{
467 int i;
468
469 for (i = 0; i < DATAFLASH_MAX_DEVICES; i++) {
470 if (mtd_devices[i]) {
471 del_mtd_device(mtd_devices[i]);
472 kfree(mtd_devices[i]->priv);
473 kfree(mtd_devices[i]);
474 }
475 }
476 nr_devices = 0;
477 kfree(spi_transfer_desc);
478}
479
480module_init(at91_dataflash26_init);
481module_exit(at91_dataflash26_exit);
482
483MODULE_LICENSE("GPL");
484MODULE_AUTHOR("Hans J. Koch");
485MODULE_DESCRIPTION("DataFlash AT26xxx driver for Atmel AT91RM9200");
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index f9f2ce7806b0..ce47544dc120 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -40,56 +40,9 @@ struct block2mtd_dev {
40static LIST_HEAD(blkmtd_device_list); 40static LIST_HEAD(blkmtd_device_list);
41 41
42 42
43#define PAGE_READAHEAD 64 43static struct page* page_read(struct address_space *mapping, int index)
44static void cache_readahead(struct address_space *mapping, int index)
45{ 44{
46 filler_t *filler = (filler_t*)mapping->a_ops->readpage; 45 filler_t *filler = (filler_t*)mapping->a_ops->readpage;
47 int i, pagei;
48 unsigned ret = 0;
49 unsigned long end_index;
50 struct page *page;
51 LIST_HEAD(page_pool);
52 struct inode *inode = mapping->host;
53 loff_t isize = i_size_read(inode);
54
55 if (!isize) {
56 INFO("iSize=0 in cache_readahead\n");
57 return;
58 }
59
60 end_index = ((isize - 1) >> PAGE_CACHE_SHIFT);
61
62 read_lock_irq(&mapping->tree_lock);
63 for (i = 0; i < PAGE_READAHEAD; i++) {
64 pagei = index + i;
65 if (pagei > end_index) {
66 INFO("Overrun end of disk in cache readahead\n");
67 break;
68 }
69 page = radix_tree_lookup(&mapping->page_tree, pagei);
70 if (page && (!i))
71 break;
72 if (page)
73 continue;
74 read_unlock_irq(&mapping->tree_lock);
75 page = page_cache_alloc_cold(mapping);
76 read_lock_irq(&mapping->tree_lock);
77 if (!page)
78 break;
79 page->index = pagei;
80 list_add(&page->lru, &page_pool);
81 ret++;
82 }
83 read_unlock_irq(&mapping->tree_lock);
84 if (ret)
85 read_cache_pages(mapping, &page_pool, filler, NULL);
86}
87
88
89static struct page* page_readahead(struct address_space *mapping, int index)
90{
91 filler_t *filler = (filler_t*)mapping->a_ops->readpage;
92 cache_readahead(mapping, index);
93 return read_cache_page(mapping, index, filler, NULL); 46 return read_cache_page(mapping, index, filler, NULL);
94} 47}
95 48
@@ -105,14 +58,14 @@ static int _block2mtd_erase(struct block2mtd_dev *dev, loff_t to, size_t len)
105 u_long *max; 58 u_long *max;
106 59
107 while (pages) { 60 while (pages) {
108 page = page_readahead(mapping, index); 61 page = page_read(mapping, index);
109 if (!page) 62 if (!page)
110 return -ENOMEM; 63 return -ENOMEM;
111 if (IS_ERR(page)) 64 if (IS_ERR(page))
112 return PTR_ERR(page); 65 return PTR_ERR(page);
113 66
114 max = (u_long*)page_address(page) + PAGE_SIZE; 67 max = page_address(page) + PAGE_SIZE;
115 for (p=(u_long*)page_address(page); p<max; p++) 68 for (p=page_address(page); p<max; p++)
116 if (*p != -1UL) { 69 if (*p != -1UL) {
117 lock_page(page); 70 lock_page(page);
118 memset(page_address(page), 0xff, PAGE_SIZE); 71 memset(page_address(page), 0xff, PAGE_SIZE);
@@ -174,8 +127,7 @@ static int block2mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
174 cpylen = len; // this page 127 cpylen = len; // this page
175 len = len - cpylen; 128 len = len - cpylen;
176 129
177 // Get page 130 page = page_read(dev->blkdev->bd_inode->i_mapping, index);
178 page = page_readahead(dev->blkdev->bd_inode->i_mapping, index);
179 if (!page) 131 if (!page)
180 return -ENOMEM; 132 return -ENOMEM;
181 if (IS_ERR(page)) 133 if (IS_ERR(page))
@@ -213,8 +165,7 @@ static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf,
213 cpylen = len; // this page 165 cpylen = len; // this page
214 len = len - cpylen; 166 len = len - cpylen;
215 167
216 // Get page 168 page = page_read(mapping, index);
217 page = page_readahead(mapping, index);
218 if (!page) 169 if (!page)
219 return -ENOMEM; 170 return -ENOMEM;
220 if (IS_ERR(page)) 171 if (IS_ERR(page))
@@ -308,9 +259,9 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
308 /* We might not have rootfs mounted at this point. Try 259 /* We might not have rootfs mounted at this point. Try
309 to resolve the device name by other means. */ 260 to resolve the device name by other means. */
310 261
311 dev_t dev = name_to_dev_t(devname); 262 dev_t devt = name_to_dev_t(devname);
312 if (dev != 0) { 263 if (devt) {
313 bdev = open_by_devnum(dev, FMODE_WRITE | FMODE_READ); 264 bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ);
314 } 265 }
315 } 266 }
316#endif 267#endif
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index bbf0553bdb2e..d990d8141ef5 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -6,7 +6,6 @@ menu "Mapping drivers for chip access"
6 6
7config MTD_COMPLEX_MAPPINGS 7config MTD_COMPLEX_MAPPINGS
8 bool "Support non-linear mappings of flash chips" 8 bool "Support non-linear mappings of flash chips"
9 depends on MTD
10 help 9 help
11 This causes the chip drivers to allow for complicated 10 This causes the chip drivers to allow for complicated
12 paged mappings of flash chips. 11 paged mappings of flash chips.
@@ -69,6 +68,39 @@ config MTD_PHYSMAP_OF
69 physically into the CPU's memory. The mapping description here is 68 physically into the CPU's memory. The mapping description here is
70 taken from OF device tree. 69 taken from OF device tree.
71 70
71config MTD_PMC_MSP_EVM
72 tristate "CFI Flash device mapped on PMC-Sierra MSP"
73 depends on PMC_MSP && MTD_CFI
74 select MTD_PARTITIONS
75 help
76 This provides a 'mapping' driver which support the way
77 in which user-programmable flash chips are connected on the
78 PMC-Sierra MSP eval/demo boards
79
80choice
81 prompt "Maximum mappable memory avialable for flash IO"
82 depends on MTD_PMC_MSP_EVM
83 default MSP_FLASH_MAP_LIMIT_32M
84
85config MSP_FLASH_MAP_LIMIT_32M
86 bool "32M"
87
88endchoice
89
90config MSP_FLASH_MAP_LIMIT
91 hex
92 default "0x02000000"
93 depends on MSP_FLASH_MAP_LIMIT_32M
94
95config MTD_PMC_MSP_RAMROOT
96 tristate "Embedded RAM block device for root on PMC-Sierra MSP"
97 depends on PMC_MSP_EMBEDDED_ROOTFS && \
98 (MTD_BLOCK || MTD_BLOCK_RO) && \
99 MTD_RAM
100 help
101 This provides support for the embedded root file system
102 on PMC MSP devices. This memory is mapped as a MTD block device.
103
72config MTD_SUN_UFLASH 104config MTD_SUN_UFLASH
73 tristate "Sun Microsystems userflash support" 105 tristate "Sun Microsystems userflash support"
74 depends on SPARC && MTD_CFI 106 depends on SPARC && MTD_CFI
@@ -240,13 +272,13 @@ config MTD_NETtel
240 272
241config MTD_ALCHEMY 273config MTD_ALCHEMY
242 tristate "AMD Alchemy Pb1xxx/Db1xxx/RDK MTD support" 274 tristate "AMD Alchemy Pb1xxx/Db1xxx/RDK MTD support"
243 depends on SOC_AU1X00 275 depends on SOC_AU1X00 && MTD_PARTITIONS && MTD_CFI
244 help 276 help
245 Flash memory access on AMD Alchemy Pb/Db/RDK Reference Boards 277 Flash memory access on AMD Alchemy Pb/Db/RDK Reference Boards
246 278
247config MTD_MTX1 279config MTD_MTX1
248 tristate "4G Systems MTX-1 Flash device" 280 tristate "4G Systems MTX-1 Flash device"
249 depends on MIPS && MIPS_MTX1 281 depends on MIPS_MTX1 && MTD_CFI
250 help 282 help
251 Flash memory access on 4G Systems MTX-1 Board. If you have one of 283 Flash memory access on 4G Systems MTX-1 Board. If you have one of
252 these boards and would like to use the flash chips on it, say 'Y'. 284 these boards and would like to use the flash chips on it, say 'Y'.
@@ -384,7 +416,7 @@ config MTD_TQM834x
384 416
385config MTD_OCELOT 417config MTD_OCELOT
386 tristate "Momenco Ocelot boot flash device" 418 tristate "Momenco Ocelot boot flash device"
387 depends on MIPS && MOMENCO_OCELOT 419 depends on MOMENCO_OCELOT
388 help 420 help
389 This enables access routines for the boot flash device and for the 421 This enables access routines for the boot flash device and for the
390 NVRAM on the Momenco Ocelot board. If you have one of these boards 422 NVRAM on the Momenco Ocelot board. If you have one of these boards
@@ -517,7 +549,7 @@ config MTD_OMAP_NOR
517# This needs CFI or JEDEC, depending on the cards found. 549# This needs CFI or JEDEC, depending on the cards found.
518config MTD_PCI 550config MTD_PCI
519 tristate "PCI MTD driver" 551 tristate "PCI MTD driver"
520 depends on MTD && PCI && MTD_COMPLEX_MAPPINGS 552 depends on PCI && MTD_COMPLEX_MAPPINGS
521 help 553 help
522 Mapping for accessing flash devices on add-in cards like the Intel XScale 554 Mapping for accessing flash devices on add-in cards like the Intel XScale
523 IQ80310 card, and the Intel EBSA285 card in blank ROM programming mode 555 IQ80310 card, and the Intel EBSA285 card in blank ROM programming mode
@@ -527,7 +559,7 @@ config MTD_PCI
527 559
528config MTD_PCMCIA 560config MTD_PCMCIA
529 tristate "PCMCIA MTD driver" 561 tristate "PCMCIA MTD driver"
530 depends on MTD && PCMCIA && MTD_COMPLEX_MAPPINGS && BROKEN 562 depends on PCMCIA && MTD_COMPLEX_MAPPINGS && BROKEN
531 help 563 help
532 Map driver for accessing PCMCIA linear flash memory cards. These 564 Map driver for accessing PCMCIA linear flash memory cards. These
533 cards are usually around 4-16MiB in size. This does not include 565 cards are usually around 4-16MiB in size. This does not include
@@ -591,13 +623,12 @@ config MTD_BAST_MAXSIZE
591 623
592config MTD_SHARP_SL 624config MTD_SHARP_SL
593 bool "ROM mapped on Sharp SL Series" 625 bool "ROM mapped on Sharp SL Series"
594 depends on MTD && ARCH_PXA 626 depends on ARCH_PXA
595 help 627 help
596 This enables access to the flash chip on the Sharp SL Series of PDAs. 628 This enables access to the flash chip on the Sharp SL Series of PDAs.
597 629
598config MTD_PLATRAM 630config MTD_PLATRAM
599 tristate "Map driver for platform device RAM (mtd-ram)" 631 tristate "Map driver for platform device RAM (mtd-ram)"
600 depends on MTD
601 select MTD_RAM 632 select MTD_RAM
602 help 633 help
603 Map driver for RAM areas described via the platform device 634 Map driver for RAM areas described via the platform device
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 071d0bf922b6..de036c5e6139 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -27,6 +27,8 @@ obj-$(CONFIG_MTD_CEIVA) += ceiva.o
27obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o 27obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o
28obj-$(CONFIG_MTD_PHYSMAP) += physmap.o 28obj-$(CONFIG_MTD_PHYSMAP) += physmap.o
29obj-$(CONFIG_MTD_PHYSMAP_OF) += physmap_of.o 29obj-$(CONFIG_MTD_PHYSMAP_OF) += physmap_of.o
30obj-$(CONFIG_MTD_PMC_MSP_EVM) += pmcmsp-flash.o
31obj-$(CONFIG_MTD_PMC_MSP_RAMROOT)+= pmcmsp-ramroot.o
30obj-$(CONFIG_MTD_PNC2000) += pnc2000.o 32obj-$(CONFIG_MTD_PNC2000) += pnc2000.o
31obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o 33obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o
32obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o 34obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o
diff --git a/drivers/mtd/maps/alchemy-flash.c b/drivers/mtd/maps/alchemy-flash.c
index 7fc8097e41d2..84fbe0e8c47e 100644
--- a/drivers/mtd/maps/alchemy-flash.c
+++ b/drivers/mtd/maps/alchemy-flash.c
@@ -1,10 +1,7 @@
1/* 1/*
2 * Flash memory access on AMD Alchemy evaluation boards 2 * Flash memory access on AMD Alchemy evaluation boards
3 * 3 *
4 * $Id: alchemy-flash.c,v 1.2 2005/11/07 11:14:26 gleixner Exp $
5 *
6 * (C) 2003, 2004 Pete Popov <ppopov@embeddedalley.com> 4 * (C) 2003, 2004 Pete Popov <ppopov@embeddedalley.com>
7 *
8 */ 5 */
9 6
10#include <linux/init.h> 7#include <linux/init.h>
@@ -18,12 +15,6 @@
18 15
19#include <asm/io.h> 16#include <asm/io.h>
20 17
21#ifdef DEBUG_RW
22#define DBG(x...) printk(x)
23#else
24#define DBG(x...)
25#endif
26
27#ifdef CONFIG_MIPS_PB1000 18#ifdef CONFIG_MIPS_PB1000
28#define BOARD_MAP_NAME "Pb1000 Flash" 19#define BOARD_MAP_NAME "Pb1000 Flash"
29#define BOARD_FLASH_SIZE 0x00800000 /* 8MB */ 20#define BOARD_FLASH_SIZE 0x00800000 /* 8MB */
diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c
index 3d4a4d8ac789..688ef495888a 100644
--- a/drivers/mtd/maps/ck804xrom.c
+++ b/drivers/mtd/maps/ck804xrom.c
@@ -338,7 +338,7 @@ static int __init init_ck804xrom(void)
338 } 338 }
339 return -ENXIO; 339 return -ENXIO;
340#if 0 340#if 0
341 return pci_module_init(&ck804xrom_driver); 341 return pci_register_driver(&ck804xrom_driver);
342#endif 342#endif
343} 343}
344 344
diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c
index 2b6504ecbbd1..894c0b271289 100644
--- a/drivers/mtd/maps/plat-ram.c
+++ b/drivers/mtd/maps/plat-ram.c
@@ -169,7 +169,8 @@ static int platram_probe(struct platform_device *pdev)
169 goto exit_free; 169 goto exit_free;
170 } 170 }
171 171
172 dev_dbg(&pdev->dev, "got platform resource %p (0x%lx)\n", res, res->start); 172 dev_dbg(&pdev->dev, "got platform resource %p (0x%llx)\n", res,
173 (unsigned long long)res->start);
173 174
174 /* setup map parameters */ 175 /* setup map parameters */
175 176
diff --git a/drivers/mtd/maps/pmcmsp-flash.c b/drivers/mtd/maps/pmcmsp-flash.c
new file mode 100644
index 000000000000..7e0377ec1c40
--- /dev/null
+++ b/drivers/mtd/maps/pmcmsp-flash.c
@@ -0,0 +1,184 @@
1/*
2 * Mapping of a custom board with both AMD CFI and JEDEC flash in partitions.
3 * Config with both CFI and JEDEC device support.
4 *
5 * Basically physmap.c with the addition of partitions and
6 * an array of mapping info to accomodate more than one flash type per board.
7 *
8 * Copyright 2005-2007 PMC-Sierra, Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
18 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
21 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, write to the Free Software Foundation, Inc.,
28 * 675 Mass Ave, Cambridge, MA 02139, USA.
29 */
30
31#include <linux/module.h>
32#include <linux/types.h>
33#include <linux/kernel.h>
34#include <linux/mtd/mtd.h>
35#include <linux/mtd/map.h>
36#include <linux/mtd/partitions.h>
37
38#include <asm/io.h>
39
40#include <msp_prom.h>
41#include <msp_regs.h>
42
43
44static struct mtd_info **msp_flash;
45static struct mtd_partition **msp_parts;
46static struct map_info *msp_maps;
47static int fcnt;
48
49#define DEBUG_MARKER printk(KERN_NOTICE "%s[%d]\n",__FUNCTION__,__LINE__)
50
51int __init init_msp_flash(void)
52{
53 int i, j;
54 int offset, coff;
55 char *env;
56 int pcnt;
57 char flash_name[] = "flash0";
58 char part_name[] = "flash0_0";
59 unsigned addr, size;
60
61 /* If ELB is disabled by "ful-mux" mode, we can't get at flash */
62 if ((*DEV_ID_REG & DEV_ID_SINGLE_PC) &&
63 (*ELB_1PC_EN_REG & SINGLE_PCCARD)) {
64 printk(KERN_NOTICE "Single PC Card mode: no flash access\n");
65 return -ENXIO;
66 }
67
68 /* examine the prom environment for flash devices */
69 for (fcnt = 0; (env = prom_getenv(flash_name)); fcnt++)
70 flash_name[5] = '0' + fcnt + 1;
71
72 if (fcnt < 1)
73 return -ENXIO;
74
75 printk(KERN_NOTICE "Found %d PMC flash devices\n", fcnt);
76 msp_flash = (struct mtd_info **)kmalloc(
77 fcnt * sizeof(struct map_info *), GFP_KERNEL);
78 msp_parts = (struct mtd_partition **)kmalloc(
79 fcnt * sizeof(struct mtd_partition *), GFP_KERNEL);
80 msp_maps = (struct map_info *)kmalloc(
81 fcnt * sizeof(struct mtd_info), GFP_KERNEL);
82 memset(msp_maps, 0, fcnt * sizeof(struct mtd_info));
83
84 /* loop over the flash devices, initializing each */
85 for (i = 0; i < fcnt; i++) {
86 /* examine the prom environment for flash partititions */
87 part_name[5] = '0' + i;
88 part_name[7] = '0';
89 for (pcnt = 0; (env = prom_getenv(part_name)); pcnt++)
90 part_name[7] = '0' + pcnt + 1;
91
92 if (pcnt == 0) {
93 printk(KERN_NOTICE "Skipping flash device %d "
94 "(no partitions defined)\n", i);
95 continue;
96 }
97
98 msp_parts[i] = (struct mtd_partition *)kmalloc(
99 pcnt * sizeof(struct mtd_partition), GFP_KERNEL);
100 memset(msp_parts[i], 0, pcnt * sizeof(struct mtd_partition));
101
102 /* now initialize the devices proper */
103 flash_name[5] = '0' + i;
104 env = prom_getenv(flash_name);
105
106 if (sscanf(env, "%x:%x", &addr, &size) < 2)
107 return -ENXIO;
108 addr = CPHYSADDR(addr);
109
110 printk(KERN_NOTICE
111 "MSP flash device \"%s\": 0x%08x at 0x%08x\n",
112 flash_name, size, addr);
113 /* This must matchs the actual size of the flash chip */
114 msp_maps[i].size = size;
115 msp_maps[i].phys = addr;
116
117 /*
118 * Platforms have a specific limit of the size of memory
119 * which may be mapped for flash:
120 */
121 if (size > CONFIG_MSP_FLASH_MAP_LIMIT)
122 size = CONFIG_MSP_FLASH_MAP_LIMIT;
123 msp_maps[i].virt = ioremap(addr, size);
124 msp_maps[i].bankwidth = 1;
125 msp_maps[i].name = strncpy(kmalloc(7, GFP_KERNEL),
126 flash_name, 7);
127
128 if (msp_maps[i].virt == NULL)
129 return -ENXIO;
130
131 for (j = 0; j < pcnt; j++) {
132 part_name[5] = '0' + i;
133 part_name[7] = '0' + j;
134
135 env = prom_getenv(part_name);
136
137 if (sscanf(env, "%x:%x:%n", &offset, &size, &coff) < 2)
138 return -ENXIO;
139
140 msp_parts[i][j].size = size;
141 msp_parts[i][j].offset = offset;
142 msp_parts[i][j].name = env + coff;
143 }
144
145 /* now probe and add the device */
146 simple_map_init(&msp_maps[i]);
147 msp_flash[i] = do_map_probe("cfi_probe", &msp_maps[i]);
148 if (msp_flash[i]) {
149 msp_flash[i]->owner = THIS_MODULE;
150 add_mtd_partitions(msp_flash[i], msp_parts[i], pcnt);
151 } else {
152 printk(KERN_ERR "map probe failed for flash\n");
153 return -ENXIO;
154 }
155 }
156
157 return 0;
158}
159
160static void __exit cleanup_msp_flash(void)
161{
162 int i;
163
164 for (i = 0; i < sizeof(msp_flash) / sizeof(struct mtd_info **); i++) {
165 del_mtd_partitions(msp_flash[i]);
166 map_destroy(msp_flash[i]);
167 iounmap((void *)msp_maps[i].virt);
168
169 /* free the memory */
170 kfree(msp_maps[i].name);
171 kfree(msp_parts[i]);
172 }
173
174 kfree(msp_flash);
175 kfree(msp_parts);
176 kfree(msp_maps);
177}
178
179MODULE_AUTHOR("PMC-Sierra, Inc");
180MODULE_DESCRIPTION("MTD map driver for PMC-Sierra MSP boards");
181MODULE_LICENSE("GPL");
182
183module_init(init_msp_flash);
184module_exit(cleanup_msp_flash);
diff --git a/drivers/mtd/maps/pmcmsp-ramroot.c b/drivers/mtd/maps/pmcmsp-ramroot.c
new file mode 100644
index 000000000000..18049bceba8d
--- /dev/null
+++ b/drivers/mtd/maps/pmcmsp-ramroot.c
@@ -0,0 +1,105 @@
1/*
2 * Mapping of the rootfs in a physical region of memory
3 *
4 * Copyright (C) 2005-2007 PMC-Sierra Inc.
5 * Author: Andrew Hughes, Andrew_Hughes@pmc-sierra.com
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
13 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
15 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
16 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
17 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
18 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
21 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 *
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 675 Mass Ave, Cambridge, MA 02139, USA.
26 */
27
28#include <linux/module.h>
29#include <linux/types.h>
30#include <linux/kernel.h>
31#include <linux/init.h>
32#include <linux/slab.h>
33#include <linux/fs.h>
34#include <linux/root_dev.h>
35#include <linux/mtd/mtd.h>
36#include <linux/mtd/map.h>
37
38#include <asm/io.h>
39
40#include <msp_prom.h>
41
42static struct mtd_info *rr_mtd;
43
44struct map_info rr_map = {
45 .name = "ramroot",
46 .bankwidth = 4,
47};
48
49static int __init init_rrmap(void)
50{
51 void *ramroot_start;
52 unsigned long ramroot_size;
53
54 /* Check for supported rootfs types */
55 if (get_ramroot(&ramroot_start, &ramroot_size)) {
56 rr_map.phys = CPHYSADDR(ramroot_start);
57 rr_map.size = ramroot_size;
58
59 printk(KERN_NOTICE
60 "PMC embedded root device: 0x%08lx @ 0x%08lx\n",
61 rr_map.size, (unsigned long)rr_map.phys);
62 } else {
63 printk(KERN_ERR
64 "init_rrmap: no supported embedded rootfs detected!\n");
65 return -ENXIO;
66 }
67
68 /* Map rootfs to I/O space for block device driver */
69 rr_map.virt = ioremap(rr_map.phys, rr_map.size);
70 if (!rr_map.virt) {
71 printk(KERN_ERR "Failed to ioremap\n");
72 return -EIO;
73 }
74
75 simple_map_init(&rr_map);
76
77 rr_mtd = do_map_probe("map_ram", &rr_map);
78 if (rr_mtd) {
79 rr_mtd->owner = THIS_MODULE;
80
81 add_mtd_device(rr_mtd);
82 ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, rr_mtd->index);
83
84 return 0;
85 }
86
87 iounmap(rr_map.virt);
88 return -ENXIO;
89}
90
91static void __exit cleanup_rrmap(void)
92{
93 del_mtd_device(rr_mtd);
94 map_destroy(rr_mtd);
95
96 iounmap(rr_map.virt);
97 rr_map.virt = NULL;
98}
99
100MODULE_AUTHOR("PMC-Sierra, Inc");
101MODULE_DESCRIPTION("MTD map driver for embedded PMC-Sierra MSP filesystem");
102MODULE_LICENSE("GPL");
103
104module_init(init_rrmap);
105module_exit(cleanup_rrmap);
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index b879a66daa9e..524b83b5ebf5 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -20,6 +20,7 @@
20#include <linux/hdreg.h> 20#include <linux/hdreg.h>
21#include <linux/init.h> 21#include <linux/init.h>
22#include <linux/mutex.h> 22#include <linux/mutex.h>
23#include <linux/kthread.h>
23#include <asm/uaccess.h> 24#include <asm/uaccess.h>
24 25
25static LIST_HEAD(blktrans_majors); 26static LIST_HEAD(blktrans_majors);
@@ -28,9 +29,7 @@ extern struct mutex mtd_table_mutex;
28extern struct mtd_info *mtd_table[]; 29extern struct mtd_info *mtd_table[];
29 30
30struct mtd_blkcore_priv { 31struct mtd_blkcore_priv {
31 struct completion thread_dead; 32 struct task_struct *thread;
32 int exiting;
33 wait_queue_head_t thread_wq;
34 struct request_queue *rq; 33 struct request_queue *rq;
35 spinlock_t queue_lock; 34 spinlock_t queue_lock;
36}; 35};
@@ -83,38 +82,19 @@ static int mtd_blktrans_thread(void *arg)
83 /* we might get involved when memory gets low, so use PF_MEMALLOC */ 82 /* we might get involved when memory gets low, so use PF_MEMALLOC */
84 current->flags |= PF_MEMALLOC | PF_NOFREEZE; 83 current->flags |= PF_MEMALLOC | PF_NOFREEZE;
85 84
86 daemonize("%sd", tr->name);
87
88 /* daemonize() doesn't do this for us since some kernel threads
89 actually want to deal with signals. We can't just call
90 exit_sighand() since that'll cause an oops when we finally
91 do exit. */
92 spin_lock_irq(&current->sighand->siglock);
93 sigfillset(&current->blocked);
94 recalc_sigpending();
95 spin_unlock_irq(&current->sighand->siglock);
96
97 spin_lock_irq(rq->queue_lock); 85 spin_lock_irq(rq->queue_lock);
98 86 while (!kthread_should_stop()) {
99 while (!tr->blkcore_priv->exiting) {
100 struct request *req; 87 struct request *req;
101 struct mtd_blktrans_dev *dev; 88 struct mtd_blktrans_dev *dev;
102 int res = 0; 89 int res = 0;
103 DECLARE_WAITQUEUE(wait, current);
104 90
105 req = elv_next_request(rq); 91 req = elv_next_request(rq);
106 92
107 if (!req) { 93 if (!req) {
108 add_wait_queue(&tr->blkcore_priv->thread_wq, &wait);
109 set_current_state(TASK_INTERRUPTIBLE); 94 set_current_state(TASK_INTERRUPTIBLE);
110
111 spin_unlock_irq(rq->queue_lock); 95 spin_unlock_irq(rq->queue_lock);
112
113 schedule(); 96 schedule();
114 remove_wait_queue(&tr->blkcore_priv->thread_wq, &wait);
115
116 spin_lock_irq(rq->queue_lock); 97 spin_lock_irq(rq->queue_lock);
117
118 continue; 98 continue;
119 } 99 }
120 100
@@ -133,13 +113,13 @@ static int mtd_blktrans_thread(void *arg)
133 } 113 }
134 spin_unlock_irq(rq->queue_lock); 114 spin_unlock_irq(rq->queue_lock);
135 115
136 complete_and_exit(&tr->blkcore_priv->thread_dead, 0); 116 return 0;
137} 117}
138 118
139static void mtd_blktrans_request(struct request_queue *rq) 119static void mtd_blktrans_request(struct request_queue *rq)
140{ 120{
141 struct mtd_blktrans_ops *tr = rq->queuedata; 121 struct mtd_blktrans_ops *tr = rq->queuedata;
142 wake_up(&tr->blkcore_priv->thread_wq); 122 wake_up_process(tr->blkcore_priv->thread);
143} 123}
144 124
145 125
@@ -388,8 +368,6 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
388 return ret; 368 return ret;
389 } 369 }
390 spin_lock_init(&tr->blkcore_priv->queue_lock); 370 spin_lock_init(&tr->blkcore_priv->queue_lock);
391 init_completion(&tr->blkcore_priv->thread_dead);
392 init_waitqueue_head(&tr->blkcore_priv->thread_wq);
393 371
394 tr->blkcore_priv->rq = blk_init_queue(mtd_blktrans_request, &tr->blkcore_priv->queue_lock); 372 tr->blkcore_priv->rq = blk_init_queue(mtd_blktrans_request, &tr->blkcore_priv->queue_lock);
395 if (!tr->blkcore_priv->rq) { 373 if (!tr->blkcore_priv->rq) {
@@ -403,13 +381,14 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
403 blk_queue_hardsect_size(tr->blkcore_priv->rq, tr->blksize); 381 blk_queue_hardsect_size(tr->blkcore_priv->rq, tr->blksize);
404 tr->blkshift = ffs(tr->blksize) - 1; 382 tr->blkshift = ffs(tr->blksize) - 1;
405 383
406 ret = kernel_thread(mtd_blktrans_thread, tr, CLONE_KERNEL); 384 tr->blkcore_priv->thread = kthread_run(mtd_blktrans_thread, tr,
407 if (ret < 0) { 385 "%sd", tr->name);
386 if (IS_ERR(tr->blkcore_priv->thread)) {
408 blk_cleanup_queue(tr->blkcore_priv->rq); 387 blk_cleanup_queue(tr->blkcore_priv->rq);
409 unregister_blkdev(tr->major, tr->name); 388 unregister_blkdev(tr->major, tr->name);
410 kfree(tr->blkcore_priv); 389 kfree(tr->blkcore_priv);
411 mutex_unlock(&mtd_table_mutex); 390 mutex_unlock(&mtd_table_mutex);
412 return ret; 391 return PTR_ERR(tr->blkcore_priv->thread);
413 } 392 }
414 393
415 INIT_LIST_HEAD(&tr->devs); 394 INIT_LIST_HEAD(&tr->devs);
@@ -432,9 +411,7 @@ int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr)
432 mutex_lock(&mtd_table_mutex); 411 mutex_lock(&mtd_table_mutex);
433 412
434 /* Clean up the kernel thread */ 413 /* Clean up the kernel thread */
435 tr->blkcore_priv->exiting = 1; 414 kthread_stop(tr->blkcore_priv->thread);
436 wake_up(&tr->blkcore_priv->thread_wq);
437 wait_for_completion(&tr->blkcore_priv->thread_dead);
438 415
439 /* Remove it from the list of active majors */ 416 /* Remove it from the list of active majors */
440 list_del(&tr->list); 417 list_del(&tr->list);
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 1592eac64e57..8c86b802f212 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -553,7 +553,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
553 ops.datbuf = NULL; 553 ops.datbuf = NULL;
554 ops.mode = MTD_OOB_PLACE; 554 ops.mode = MTD_OOB_PLACE;
555 555
556 if (ops.ooboffs && ops.len > (mtd->oobsize - ops.ooboffs)) 556 if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))
557 return -EINVAL; 557 return -EINVAL;
558 558
559 ops.oobbuf = kmalloc(buf.length, GFP_KERNEL); 559 ops.oobbuf = kmalloc(buf.length, GFP_KERNEL);
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 2d12dcdd740c..d05873b8c155 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -1,10 +1,7 @@
1# drivers/mtd/nand/Kconfig 1# drivers/mtd/nand/Kconfig
2# $Id: Kconfig,v 1.35 2005/11/07 11:14:30 gleixner Exp $ 2# $Id: Kconfig,v 1.35 2005/11/07 11:14:30 gleixner Exp $
3 3
4menu "NAND Flash Device Drivers" 4menuconfig MTD_NAND
5 depends on MTD!=n
6
7config MTD_NAND
8 tristate "NAND Device Support" 5 tristate "NAND Device Support"
9 depends on MTD 6 depends on MTD
10 select MTD_NAND_IDS 7 select MTD_NAND_IDS
@@ -13,9 +10,10 @@ config MTD_NAND
13 devices. For further information see 10 devices. For further information see
14 <http://www.linux-mtd.infradead.org/doc/nand.html>. 11 <http://www.linux-mtd.infradead.org/doc/nand.html>.
15 12
13if MTD_NAND
14
16config MTD_NAND_VERIFY_WRITE 15config MTD_NAND_VERIFY_WRITE
17 bool "Verify NAND page writes" 16 bool "Verify NAND page writes"
18 depends on MTD_NAND
19 help 17 help
20 This adds an extra check when data is written to the flash. The 18 This adds an extra check when data is written to the flash. The
21 NAND flash device internally checks only bits transitioning 19 NAND flash device internally checks only bits transitioning
@@ -25,53 +23,61 @@ config MTD_NAND_VERIFY_WRITE
25 23
26config MTD_NAND_ECC_SMC 24config MTD_NAND_ECC_SMC
27 bool "NAND ECC Smart Media byte order" 25 bool "NAND ECC Smart Media byte order"
28 depends on MTD_NAND
29 default n 26 default n
30 help 27 help
31 Software ECC according to the Smart Media Specification. 28 Software ECC according to the Smart Media Specification.
32 The original Linux implementation had byte 0 and 1 swapped. 29 The original Linux implementation had byte 0 and 1 swapped.
33 30
31config MTD_NAND_MUSEUM_IDS
32 bool "Enable chip ids for obsolete ancient NAND devices"
33 depends on MTD_NAND
34 default n
35 help
36 Enable this option only when your board has first generation
37 NAND chips (page size 256 byte, erase size 4-8KiB). The IDs
38 of these chips were reused by later, larger chips.
39
34config MTD_NAND_AUTCPU12 40config MTD_NAND_AUTCPU12
35 tristate "SmartMediaCard on autronix autcpu12 board" 41 tristate "SmartMediaCard on autronix autcpu12 board"
36 depends on MTD_NAND && ARCH_AUTCPU12 42 depends on ARCH_AUTCPU12
37 help 43 help
38 This enables the driver for the autronix autcpu12 board to 44 This enables the driver for the autronix autcpu12 board to
39 access the SmartMediaCard. 45 access the SmartMediaCard.
40 46
41config MTD_NAND_EDB7312 47config MTD_NAND_EDB7312
42 tristate "Support for Cirrus Logic EBD7312 evaluation board" 48 tristate "Support for Cirrus Logic EBD7312 evaluation board"
43 depends on MTD_NAND && ARCH_EDB7312 49 depends on ARCH_EDB7312
44 help 50 help
45 This enables the driver for the Cirrus Logic EBD7312 evaluation 51 This enables the driver for the Cirrus Logic EBD7312 evaluation
46 board to access the onboard NAND Flash. 52 board to access the onboard NAND Flash.
47 53
48config MTD_NAND_H1900 54config MTD_NAND_H1900
49 tristate "iPAQ H1900 flash" 55 tristate "iPAQ H1900 flash"
50 depends on MTD_NAND && ARCH_PXA && MTD_PARTITIONS 56 depends on ARCH_PXA && MTD_PARTITIONS
51 help 57 help
52 This enables the driver for the iPAQ h1900 flash. 58 This enables the driver for the iPAQ h1900 flash.
53 59
54config MTD_NAND_SPIA 60config MTD_NAND_SPIA
55 tristate "NAND Flash device on SPIA board" 61 tristate "NAND Flash device on SPIA board"
56 depends on ARCH_P720T && MTD_NAND 62 depends on ARCH_P720T
57 help 63 help
58 If you had to ask, you don't have one. Say 'N'. 64 If you had to ask, you don't have one. Say 'N'.
59 65
60config MTD_NAND_AMS_DELTA 66config MTD_NAND_AMS_DELTA
61 tristate "NAND Flash device on Amstrad E3" 67 tristate "NAND Flash device on Amstrad E3"
62 depends on MACH_AMS_DELTA && MTD_NAND 68 depends on MACH_AMS_DELTA
63 help 69 help
64 Support for NAND flash on Amstrad E3 (Delta). 70 Support for NAND flash on Amstrad E3 (Delta).
65 71
66config MTD_NAND_TOTO 72config MTD_NAND_TOTO
67 tristate "NAND Flash device on TOTO board" 73 tristate "NAND Flash device on TOTO board"
68 depends on ARCH_OMAP && MTD_NAND && BROKEN 74 depends on ARCH_OMAP && BROKEN
69 help 75 help
70 Support for NAND flash on Texas Instruments Toto platform. 76 Support for NAND flash on Texas Instruments Toto platform.
71 77
72config MTD_NAND_TS7250 78config MTD_NAND_TS7250
73 tristate "NAND Flash device on TS-7250 board" 79 tristate "NAND Flash device on TS-7250 board"
74 depends on MACH_TS72XX && MTD_NAND 80 depends on MACH_TS72XX
75 help 81 help
76 Support for NAND flash on Technologic Systems TS-7250 platform. 82 Support for NAND flash on Technologic Systems TS-7250 platform.
77 83
@@ -80,14 +86,14 @@ config MTD_NAND_IDS
80 86
81config MTD_NAND_AU1550 87config MTD_NAND_AU1550
82 tristate "Au1550/1200 NAND support" 88 tristate "Au1550/1200 NAND support"
83 depends on (SOC_AU1200 || SOC_AU1550) && MTD_NAND 89 depends on SOC_AU1200 || SOC_AU1550
84 help 90 help
85 This enables the driver for the NAND flash controller on the 91 This enables the driver for the NAND flash controller on the
86 AMD/Alchemy 1550 SOC. 92 AMD/Alchemy 1550 SOC.
87 93
88config MTD_NAND_RTC_FROM4 94config MTD_NAND_RTC_FROM4
89 tristate "Renesas Flash ROM 4-slot interface board (FROM_BOARD4)" 95 tristate "Renesas Flash ROM 4-slot interface board (FROM_BOARD4)"
90 depends on MTD_NAND && SH_SOLUTION_ENGINE 96 depends on SH_SOLUTION_ENGINE
91 select REED_SOLOMON 97 select REED_SOLOMON
92 select REED_SOLOMON_DEC8 98 select REED_SOLOMON_DEC8
93 select BITREVERSE 99 select BITREVERSE
@@ -97,13 +103,13 @@ config MTD_NAND_RTC_FROM4
97 103
98config MTD_NAND_PPCHAMELEONEVB 104config MTD_NAND_PPCHAMELEONEVB
99 tristate "NAND Flash device on PPChameleonEVB board" 105 tristate "NAND Flash device on PPChameleonEVB board"
100 depends on PPCHAMELEONEVB && MTD_NAND && BROKEN 106 depends on PPCHAMELEONEVB && BROKEN
101 help 107 help
102 This enables the NAND flash driver on the PPChameleon EVB Board. 108 This enables the NAND flash driver on the PPChameleon EVB Board.
103 109
104config MTD_NAND_S3C2410 110config MTD_NAND_S3C2410
105 tristate "NAND Flash support for S3C2410/S3C2440 SoC" 111 tristate "NAND Flash support for S3C2410/S3C2440 SoC"
106 depends on ARCH_S3C2410 && MTD_NAND 112 depends on ARCH_S3C2410
107 help 113 help
108 This enables the NAND flash controller on the S3C2410 and S3C2440 114 This enables the NAND flash controller on the S3C2410 and S3C2440
109 SoCs 115 SoCs
@@ -128,7 +134,7 @@ config MTD_NAND_S3C2410_HWECC
128 134
129config MTD_NAND_NDFC 135config MTD_NAND_NDFC
130 tristate "NDFC NanD Flash Controller" 136 tristate "NDFC NanD Flash Controller"
131 depends on MTD_NAND && 44x 137 depends on 44x
132 select MTD_NAND_ECC_SMC 138 select MTD_NAND_ECC_SMC
133 help 139 help
134 NDFC Nand Flash Controllers are integrated in EP44x SoCs 140 NDFC Nand Flash Controllers are integrated in EP44x SoCs
@@ -145,7 +151,7 @@ config MTD_NAND_S3C2410_CLKSTOP
145 151
146config MTD_NAND_DISKONCHIP 152config MTD_NAND_DISKONCHIP
147 tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)" 153 tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)"
148 depends on MTD_NAND && EXPERIMENTAL 154 depends on EXPERIMENTAL
149 select REED_SOLOMON 155 select REED_SOLOMON
150 select REED_SOLOMON_DEC16 156 select REED_SOLOMON_DEC16
151 help 157 help
@@ -215,11 +221,11 @@ config MTD_NAND_DISKONCHIP_BBTWRITE
215 221
216config MTD_NAND_SHARPSL 222config MTD_NAND_SHARPSL
217 tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)" 223 tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)"
218 depends on MTD_NAND && ARCH_PXA 224 depends on ARCH_PXA
219 225
220config MTD_NAND_BASLER_EXCITE 226config MTD_NAND_BASLER_EXCITE
221 tristate "Support for NAND Flash on Basler eXcite" 227 tristate "Support for NAND Flash on Basler eXcite"
222 depends on MTD_NAND && BASLER_EXCITE 228 depends on BASLER_EXCITE
223 help 229 help
224 This enables the driver for the NAND flash device found on the 230 This enables the driver for the NAND flash device found on the
225 Basler eXcite Smart Camera. If built as a module, the driver 231 Basler eXcite Smart Camera. If built as a module, the driver
@@ -227,14 +233,14 @@ config MTD_NAND_BASLER_EXCITE
227 233
228config MTD_NAND_CAFE 234config MTD_NAND_CAFE
229 tristate "NAND support for OLPC CAFÉ chip" 235 tristate "NAND support for OLPC CAFÉ chip"
230 depends on MTD_NAND && PCI 236 depends on PCI
231 help 237 help
232 Use NAND flash attached to the CAFÉ chip designed for the $100 238 Use NAND flash attached to the CAFÉ chip designed for the $100
233 laptop. 239 laptop.
234 240
235config MTD_NAND_CS553X 241config MTD_NAND_CS553X
236 tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)" 242 tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)"
237 depends on MTD_NAND && X86_32 && (X86_PC || X86_GENERICARCH) 243 depends on X86_32 && (X86_PC || X86_GENERICARCH)
238 help 244 help
239 The CS553x companion chips for the AMD Geode processor 245 The CS553x companion chips for the AMD Geode processor
240 include NAND flash controllers with built-in hardware ECC 246 include NAND flash controllers with built-in hardware ECC
@@ -247,16 +253,21 @@ config MTD_NAND_CS553X
247 253
248config MTD_NAND_AT91 254config MTD_NAND_AT91
249 bool "Support for NAND Flash / SmartMedia on AT91" 255 bool "Support for NAND Flash / SmartMedia on AT91"
250 depends on MTD_NAND && ARCH_AT91 256 depends on ARCH_AT91
251 help 257 help
252 Enables support for NAND Flash / Smart Media Card interface 258 Enables support for NAND Flash / Smart Media Card interface
253 on Atmel AT91 processors. 259 on Atmel AT91 processors.
254 260
261config MTD_NAND_CM_X270
262 tristate "Support for NAND Flash on CM-X270 modules"
263 depends on MTD_NAND && MACH_ARMCORE
264
265
255config MTD_NAND_NANDSIM 266config MTD_NAND_NANDSIM
256 tristate "Support for NAND Flash Simulator" 267 tristate "Support for NAND Flash Simulator"
257 depends on MTD_NAND && MTD_PARTITIONS 268 depends on MTD_PARTITIONS
258 help 269 help
259 The simulator may simulate various NAND flash chips for the 270 The simulator may simulate various NAND flash chips for the
260 MTD nand layer. 271 MTD nand layer.
261 272
262endmenu 273endif # MTD_NAND
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 80f1dfc77949..6872031a3fb2 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o
24obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o 24obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o
25obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o 25obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o
26obj-$(CONFIG_MTD_NAND_AT91) += at91_nand.o 26obj-$(CONFIG_MTD_NAND_AT91) += at91_nand.o
27obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o
27obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o 28obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o
28 29
29nand-objs := nand_base.o nand_bbt.o 30nand-objs := nand_base.o nand_bbt.o
diff --git a/drivers/mtd/nand/cafe.c b/drivers/mtd/nand/cafe.c
index fd6bb3ed40df..c328a7514510 100644
--- a/drivers/mtd/nand/cafe.c
+++ b/drivers/mtd/nand/cafe.c
@@ -530,7 +530,6 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
530{ 530{
531 struct mtd_info *mtd; 531 struct mtd_info *mtd;
532 struct cafe_priv *cafe; 532 struct cafe_priv *cafe;
533 uint32_t timing1, timing2, timing3;
534 uint32_t ctrl; 533 uint32_t ctrl;
535 int err = 0; 534 int err = 0;
536 535
@@ -587,21 +586,19 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
587 } 586 }
588 587
589 if (numtimings == 3) { 588 if (numtimings == 3) {
590 timing1 = timing[0];
591 timing2 = timing[1];
592 timing3 = timing[2];
593 cafe_dev_dbg(&cafe->pdev->dev, "Using provided timings (%08x %08x %08x)\n", 589 cafe_dev_dbg(&cafe->pdev->dev, "Using provided timings (%08x %08x %08x)\n",
594 timing1, timing2, timing3); 590 timing[0], timing[1], timing[2]);
595 } else { 591 } else {
596 timing1 = cafe_readl(cafe, NAND_TIMING1); 592 timing[0] = cafe_readl(cafe, NAND_TIMING1);
597 timing2 = cafe_readl(cafe, NAND_TIMING2); 593 timing[1] = cafe_readl(cafe, NAND_TIMING2);
598 timing3 = cafe_readl(cafe, NAND_TIMING3); 594 timing[2] = cafe_readl(cafe, NAND_TIMING3);
599 595
600 if (timing1 | timing2 | timing3) { 596 if (timing[0] | timing[1] | timing[2]) {
601 cafe_dev_dbg(&cafe->pdev->dev, "Timing registers already set (%08x %08x %08x)\n", timing1, timing2, timing3); 597 cafe_dev_dbg(&cafe->pdev->dev, "Timing registers already set (%08x %08x %08x)\n",
598 timing[0], timing[1], timing[2]);
602 } else { 599 } else {
603 dev_warn(&cafe->pdev->dev, "Timing registers unset; using most conservative defaults\n"); 600 dev_warn(&cafe->pdev->dev, "Timing registers unset; using most conservative defaults\n");
604 timing1 = timing2 = timing3 = 0xffffffff; 601 timing[0] = timing[1] = timing[2] = 0xffffffff;
605 } 602 }
606 } 603 }
607 604
@@ -609,9 +606,9 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
609 cafe_writel(cafe, 1, NAND_RESET); 606 cafe_writel(cafe, 1, NAND_RESET);
610 cafe_writel(cafe, 0, NAND_RESET); 607 cafe_writel(cafe, 0, NAND_RESET);
611 608
612 cafe_writel(cafe, timing1, NAND_TIMING1); 609 cafe_writel(cafe, timing[0], NAND_TIMING1);
613 cafe_writel(cafe, timing2, NAND_TIMING2); 610 cafe_writel(cafe, timing[1], NAND_TIMING2);
614 cafe_writel(cafe, timing3, NAND_TIMING3); 611 cafe_writel(cafe, timing[2], NAND_TIMING3);
615 612
616 cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK); 613 cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
617 err = request_irq(pdev->irq, &cafe_nand_interrupt, IRQF_SHARED, 614 err = request_irq(pdev->irq, &cafe_nand_interrupt, IRQF_SHARED,
diff --git a/drivers/mtd/nand/cmx270_nand.c b/drivers/mtd/nand/cmx270_nand.c
new file mode 100644
index 000000000000..cb663ef245d5
--- /dev/null
+++ b/drivers/mtd/nand/cmx270_nand.c
@@ -0,0 +1,267 @@
1/*
2 * linux/drivers/mtd/nand/cmx270-nand.c
3 *
4 * Copyright (C) 2006 Compulab, Ltd.
5 * Mike Rapoport <mike@compulab.co.il>
6 *
7 * Derived from drivers/mtd/nand/h1910.c
8 * Copyright (C) 2002 Marius Gröger (mag@sysgo.de)
9 * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
10 *
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 * Overview:
17 * This is a device driver for the NAND flash device found on the
18 * CM-X270 board.
19 */
20
21#include <linux/mtd/nand.h>
22#include <linux/mtd/partitions.h>
23
24#include <asm/io.h>
25#include <asm/irq.h>
26
27#include <asm/arch/hardware.h>
28#include <asm/arch/pxa-regs.h>
29
30#define GPIO_NAND_CS (11)
31#define GPIO_NAND_RB (89)
32
33/* This macro needed to ensure in-order operation of GPIO and local
34 * bus. Without both asm command and dummy uncached read there're
35 * states when NAND access is broken. I've looked for such macro(s) in
36 * include/asm-arm but found nothing approptiate.
37 * dmac_clean_range is close, but is makes cache invalidation
38 * unnecessary here and it cannot be used in module
39 */
40#define DRAIN_WB() \
41 do { \
42 unsigned char dummy; \
43 asm volatile ("mcr p15, 0, r0, c7, c10, 4":::"r0"); \
44 dummy=*((unsigned char*)UNCACHED_ADDR); \
45 } while(0)
46
47/* MTD structure for CM-X270 board */
48static struct mtd_info *cmx270_nand_mtd;
49
50/* remaped IO address of the device */
51static void __iomem *cmx270_nand_io;
52
53/*
54 * Define static partitions for flash device
55 */
56static struct mtd_partition partition_info[] = {
57 [0] = {
58 .name = "cmx270-0",
59 .offset = 0,
60 .size = MTDPART_SIZ_FULL
61 }
62};
63#define NUM_PARTITIONS (ARRAY_SIZE(partition_info))
64
65const char *part_probes[] = { "cmdlinepart", NULL };
66
67static u_char cmx270_read_byte(struct mtd_info *mtd)
68{
69 struct nand_chip *this = mtd->priv;
70
71 return (readl(this->IO_ADDR_R) >> 16);
72}
73
74static void cmx270_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
75{
76 int i;
77 struct nand_chip *this = mtd->priv;
78
79 for (i=0; i<len; i++)
80 writel((*buf++ << 16), this->IO_ADDR_W);
81}
82
83static void cmx270_read_buf(struct mtd_info *mtd, u_char *buf, int len)
84{
85 int i;
86 struct nand_chip *this = mtd->priv;
87
88 for (i=0; i<len; i++)
89 *buf++ = readl(this->IO_ADDR_R) >> 16;
90}
91
92static int cmx270_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
93{
94 int i;
95 struct nand_chip *this = mtd->priv;
96
97 for (i=0; i<len; i++)
98 if (buf[i] != (u_char)(readl(this->IO_ADDR_R) >> 16))
99 return -EFAULT;
100
101 return 0;
102}
103
104static inline void nand_cs_on(void)
105{
106 GPCR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS);
107}
108
109static void nand_cs_off(void)
110{
111 DRAIN_WB();
112
113 GPSR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS);
114}
115
116/*
117 * hardware specific access to control-lines
118 */
119static void cmx270_hwcontrol(struct mtd_info *mtd, int dat,
120 unsigned int ctrl)
121{
122 struct nand_chip* this = mtd->priv;
123 unsigned int nandaddr = (unsigned int)this->IO_ADDR_W;
124
125 DRAIN_WB();
126
127 if (ctrl & NAND_CTRL_CHANGE) {
128 if ( ctrl & NAND_ALE )
129 nandaddr |= (1 << 3);
130 else
131 nandaddr &= ~(1 << 3);
132 if ( ctrl & NAND_CLE )
133 nandaddr |= (1 << 2);
134 else
135 nandaddr &= ~(1 << 2);
136 if ( ctrl & NAND_NCE )
137 nand_cs_on();
138 else
139 nand_cs_off();
140 }
141
142 DRAIN_WB();
143 this->IO_ADDR_W = (void __iomem*)nandaddr;
144 if (dat != NAND_CMD_NONE)
145 writel((dat << 16), this->IO_ADDR_W);
146
147 DRAIN_WB();
148}
149
150/*
151 * read device ready pin
152 */
153static int cmx270_device_ready(struct mtd_info *mtd)
154{
155 DRAIN_WB();
156
157 return (GPLR(GPIO_NAND_RB) & GPIO_bit(GPIO_NAND_RB));
158}
159
160/*
161 * Main initialization routine
162 */
163static int cmx270_init(void)
164{
165 struct nand_chip *this;
166 const char *part_type;
167 struct mtd_partition *mtd_parts;
168 int mtd_parts_nb = 0;
169 int ret;
170
171 /* Allocate memory for MTD device structure and private data */
172 cmx270_nand_mtd = kzalloc(sizeof(struct mtd_info) +
173 sizeof(struct nand_chip),
174 GFP_KERNEL);
175 if (!cmx270_nand_mtd) {
176 printk("Unable to allocate CM-X270 NAND MTD device structure.\n");
177 return -ENOMEM;
178 }
179
180 cmx270_nand_io = ioremap(PXA_CS1_PHYS, 12);
181 if (!cmx270_nand_io) {
182 printk("Unable to ioremap NAND device\n");
183 ret = -EINVAL;
184 goto err1;
185 }
186
187 /* Get pointer to private data */
188 this = (struct nand_chip *)(&cmx270_nand_mtd[1]);
189
190 /* Link the private data with the MTD structure */
191 cmx270_nand_mtd->owner = THIS_MODULE;
192 cmx270_nand_mtd->priv = this;
193
194 /* insert callbacks */
195 this->IO_ADDR_R = cmx270_nand_io;
196 this->IO_ADDR_W = cmx270_nand_io;
197 this->cmd_ctrl = cmx270_hwcontrol;
198 this->dev_ready = cmx270_device_ready;
199
200 /* 15 us command delay time */
201 this->chip_delay = 20;
202 this->ecc.mode = NAND_ECC_SOFT;
203
204 /* read/write functions */
205 this->read_byte = cmx270_read_byte;
206 this->read_buf = cmx270_read_buf;
207 this->write_buf = cmx270_write_buf;
208 this->verify_buf = cmx270_verify_buf;
209
210 /* Scan to find existence of the device */
211 if (nand_scan (cmx270_nand_mtd, 1)) {
212 printk(KERN_NOTICE "No NAND device\n");
213 ret = -ENXIO;
214 goto err2;
215 }
216
217#ifdef CONFIG_MTD_CMDLINE_PARTS
218 mtd_parts_nb = parse_mtd_partitions(cmx270_nand_mtd, part_probes,
219 &mtd_parts, 0);
220 if (mtd_parts_nb > 0)
221 part_type = "command line";
222 else
223 mtd_parts_nb = 0;
224#endif
225 if (!mtd_parts_nb) {
226 mtd_parts = partition_info;
227 mtd_parts_nb = NUM_PARTITIONS;
228 part_type = "static";
229 }
230
231 /* Register the partitions */
232 printk(KERN_NOTICE "Using %s partition definition\n", part_type);
233 ret = add_mtd_partitions(cmx270_nand_mtd, mtd_parts, mtd_parts_nb);
234 if (ret)
235 goto err2;
236
237 /* Return happy */
238 return 0;
239
240err2:
241 iounmap(cmx270_nand_io);
242err1:
243 kfree(cmx270_nand_mtd);
244
245 return ret;
246
247}
248module_init(cmx270_init);
249
250/*
251 * Clean up routine
252 */
253static void cmx270_cleanup(void)
254{
255 /* Release resources, unregister device */
256 nand_release(cmx270_nand_mtd);
257
258 iounmap(cmx270_nand_io);
259
260 /* Free the MTD device structure */
261 kfree (cmx270_nand_mtd);
262}
263module_exit(cmx270_cleanup);
264
265MODULE_LICENSE("GPL");
266MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
267MODULE_DESCRIPTION("NAND flash driver for Compulab CM-X270 Module");
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 6af37b8cff65..04de315e4937 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -312,7 +312,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
312 /* Select the NAND device */ 312 /* Select the NAND device */
313 chip->select_chip(mtd, chipnr); 313 chip->select_chip(mtd, chipnr);
314 } else 314 } else
315 page = (int)ofs; 315 page = (int)(ofs >> chip->page_shift);
316 316
317 if (chip->options & NAND_BUSWIDTH_16) { 317 if (chip->options & NAND_BUSWIDTH_16) {
318 chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos & 0xFE, 318 chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos & 0xFE,
@@ -350,7 +350,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
350 int block, ret; 350 int block, ret;
351 351
352 /* Get block number */ 352 /* Get block number */
353 block = ((int)ofs) >> chip->bbt_erase_shift; 353 block = (int)(ofs >> chip->bbt_erase_shift);
354 if (chip->bbt) 354 if (chip->bbt)
355 chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); 355 chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
356 356
@@ -771,7 +771,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
771 uint8_t *ecc_code = chip->buffers->ecccode; 771 uint8_t *ecc_code = chip->buffers->ecccode;
772 int *eccpos = chip->ecc.layout->eccpos; 772 int *eccpos = chip->ecc.layout->eccpos;
773 773
774 nand_read_page_raw(mtd, chip, buf); 774 chip->ecc.read_page_raw(mtd, chip, buf);
775 775
776 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) 776 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
777 chip->ecc.calculate(mtd, p, &ecc_calc[i]); 777 chip->ecc.calculate(mtd, p, &ecc_calc[i]);
@@ -1426,7 +1426,7 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
1426 for (i = 0; i < chip->ecc.total; i++) 1426 for (i = 0; i < chip->ecc.total; i++)
1427 chip->oob_poi[eccpos[i]] = ecc_calc[i]; 1427 chip->oob_poi[eccpos[i]] = ecc_calc[i];
1428 1428
1429 nand_write_page_raw(mtd, chip, buf); 1429 chip->ecc.write_page_raw(mtd, chip, buf);
1430} 1430}
1431 1431
1432/** 1432/**
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index 2e2cdf2fc91d..2fc674a190cf 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -24,6 +24,8 @@
24* 512 512 Byte page size 24* 512 512 Byte page size
25*/ 25*/
26struct nand_flash_dev nand_flash_ids[] = { 26struct nand_flash_dev nand_flash_ids[] = {
27
28#ifdef CONFIG_MTD_NAND_MUSEUM_IDS
27 {"NAND 1MiB 5V 8-bit", 0x6e, 256, 1, 0x1000, 0}, 29 {"NAND 1MiB 5V 8-bit", 0x6e, 256, 1, 0x1000, 0},
28 {"NAND 2MiB 5V 8-bit", 0x64, 256, 2, 0x1000, 0}, 30 {"NAND 2MiB 5V 8-bit", 0x64, 256, 2, 0x1000, 0},
29 {"NAND 4MiB 5V 8-bit", 0x6b, 512, 4, 0x2000, 0}, 31 {"NAND 4MiB 5V 8-bit", 0x6b, 512, 4, 0x2000, 0},
@@ -39,6 +41,7 @@ struct nand_flash_dev nand_flash_ids[] = {
39 {"NAND 8MiB 3,3V 8-bit", 0xe6, 512, 8, 0x2000, 0}, 41 {"NAND 8MiB 3,3V 8-bit", 0xe6, 512, 8, 0x2000, 0},
40 {"NAND 8MiB 1,8V 16-bit", 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16}, 42 {"NAND 8MiB 1,8V 16-bit", 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16},
41 {"NAND 8MiB 3,3V 16-bit", 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16}, 43 {"NAND 8MiB 3,3V 16-bit", 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16},
44#endif
42 45
43 {"NAND 16MiB 1,8V 8-bit", 0x33, 512, 16, 0x4000, 0}, 46 {"NAND 16MiB 1,8V 8-bit", 0x33, 512, 16, 0x4000, 0},
44 {"NAND 16MiB 3,3V 8-bit", 0x73, 512, 16, 0x4000, 0}, 47 {"NAND 16MiB 3,3V 8-bit", 0x73, 512, 16, 0x4000, 0},
@@ -137,6 +140,7 @@ struct nand_manufacturers nand_manuf_ids[] = {
137 {NAND_MFR_RENESAS, "Renesas"}, 140 {NAND_MFR_RENESAS, "Renesas"},
138 {NAND_MFR_STMICRO, "ST Micro"}, 141 {NAND_MFR_STMICRO, "ST Micro"},
139 {NAND_MFR_HYNIX, "Hynix"}, 142 {NAND_MFR_HYNIX, "Hynix"},
143 {NAND_MFR_MICRON, "Micron"},
140 {0x0, "Unknown"} 144 {0x0, "Unknown"}
141}; 145};
142 146
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index c3bca9590ad2..205df0f771fe 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -37,6 +37,8 @@
37#include <linux/mtd/nand.h> 37#include <linux/mtd/nand.h>
38#include <linux/mtd/partitions.h> 38#include <linux/mtd/partitions.h>
39#include <linux/delay.h> 39#include <linux/delay.h>
40#include <linux/list.h>
41#include <linux/random.h>
40 42
41/* Default simulator parameters values */ 43/* Default simulator parameters values */
42#if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \ 44#if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \
@@ -90,6 +92,15 @@ static uint bus_width = CONFIG_NANDSIM_BUS_WIDTH;
90static uint do_delays = CONFIG_NANDSIM_DO_DELAYS; 92static uint do_delays = CONFIG_NANDSIM_DO_DELAYS;
91static uint log = CONFIG_NANDSIM_LOG; 93static uint log = CONFIG_NANDSIM_LOG;
92static uint dbg = CONFIG_NANDSIM_DBG; 94static uint dbg = CONFIG_NANDSIM_DBG;
95static unsigned long parts[MAX_MTD_DEVICES];
96static unsigned int parts_num;
97static char *badblocks = NULL;
98static char *weakblocks = NULL;
99static char *weakpages = NULL;
100static unsigned int bitflips = 0;
101static char *gravepages = NULL;
102static unsigned int rptwear = 0;
103static unsigned int overridesize = 0;
93 104
94module_param(first_id_byte, uint, 0400); 105module_param(first_id_byte, uint, 0400);
95module_param(second_id_byte, uint, 0400); 106module_param(second_id_byte, uint, 0400);
@@ -104,8 +115,16 @@ module_param(bus_width, uint, 0400);
104module_param(do_delays, uint, 0400); 115module_param(do_delays, uint, 0400);
105module_param(log, uint, 0400); 116module_param(log, uint, 0400);
106module_param(dbg, uint, 0400); 117module_param(dbg, uint, 0400);
107 118module_param_array(parts, ulong, &parts_num, 0400);
108MODULE_PARM_DESC(first_id_byte, "The fist byte returned by NAND Flash 'read ID' command (manufaturer ID)"); 119module_param(badblocks, charp, 0400);
120module_param(weakblocks, charp, 0400);
121module_param(weakpages, charp, 0400);
122module_param(bitflips, uint, 0400);
123module_param(gravepages, charp, 0400);
124module_param(rptwear, uint, 0400);
125module_param(overridesize, uint, 0400);
126
127MODULE_PARM_DESC(first_id_byte, "The first byte returned by NAND Flash 'read ID' command (manufacturer ID)");
109MODULE_PARM_DESC(second_id_byte, "The second byte returned by NAND Flash 'read ID' command (chip ID)"); 128MODULE_PARM_DESC(second_id_byte, "The second byte returned by NAND Flash 'read ID' command (chip ID)");
110MODULE_PARM_DESC(third_id_byte, "The third byte returned by NAND Flash 'read ID' command"); 129MODULE_PARM_DESC(third_id_byte, "The third byte returned by NAND Flash 'read ID' command");
111MODULE_PARM_DESC(fourth_id_byte, "The fourth byte returned by NAND Flash 'read ID' command"); 130MODULE_PARM_DESC(fourth_id_byte, "The fourth byte returned by NAND Flash 'read ID' command");
@@ -118,6 +137,23 @@ MODULE_PARM_DESC(bus_width, "Chip's bus width (8- or 16-bit)");
118MODULE_PARM_DESC(do_delays, "Simulate NAND delays using busy-waits if not zero"); 137MODULE_PARM_DESC(do_delays, "Simulate NAND delays using busy-waits if not zero");
119MODULE_PARM_DESC(log, "Perform logging if not zero"); 138MODULE_PARM_DESC(log, "Perform logging if not zero");
120MODULE_PARM_DESC(dbg, "Output debug information if not zero"); 139MODULE_PARM_DESC(dbg, "Output debug information if not zero");
140MODULE_PARM_DESC(parts, "Partition sizes (in erase blocks) separated by commas");
141/* Page and erase block positions for the following parameters are independent of any partitions */
142MODULE_PARM_DESC(badblocks, "Erase blocks that are initially marked bad, separated by commas");
143MODULE_PARM_DESC(weakblocks, "Weak erase blocks [: remaining erase cycles (defaults to 3)]"
144 " separated by commas e.g. 113:2 means eb 113"
145 " can be erased only twice before failing");
146MODULE_PARM_DESC(weakpages, "Weak pages [: maximum writes (defaults to 3)]"
147 " separated by commas e.g. 1401:2 means page 1401"
148 " can be written only twice before failing");
149MODULE_PARM_DESC(bitflips, "Maximum number of random bit flips per page (zero by default)");
150MODULE_PARM_DESC(gravepages, "Pages that lose data [: maximum reads (defaults to 3)]"
151 " separated by commas e.g. 1401:2 means page 1401"
152 " can be read only twice before failing");
153MODULE_PARM_DESC(rptwear, "Number of erases inbetween reporting wear, if not zero");
154MODULE_PARM_DESC(overridesize, "Specifies the NAND Flash size overriding the ID bytes. "
155 "The size is specified in erase blocks and as the exponent of a power of two"
156 " e.g. 5 means a size of 32 erase blocks");
121 157
122/* The largest possible page size */ 158/* The largest possible page size */
123#define NS_LARGEST_PAGE_SIZE 2048 159#define NS_LARGEST_PAGE_SIZE 2048
@@ -131,9 +167,11 @@ MODULE_PARM_DESC(dbg, "Output debug information if not zero");
131#define NS_DBG(args...) \ 167#define NS_DBG(args...) \
132 do { if (dbg) printk(KERN_DEBUG NS_OUTPUT_PREFIX " debug: " args); } while(0) 168 do { if (dbg) printk(KERN_DEBUG NS_OUTPUT_PREFIX " debug: " args); } while(0)
133#define NS_WARN(args...) \ 169#define NS_WARN(args...) \
134 do { printk(KERN_WARNING NS_OUTPUT_PREFIX " warnig: " args); } while(0) 170 do { printk(KERN_WARNING NS_OUTPUT_PREFIX " warning: " args); } while(0)
135#define NS_ERR(args...) \ 171#define NS_ERR(args...) \
136 do { printk(KERN_ERR NS_OUTPUT_PREFIX " errorr: " args); } while(0) 172 do { printk(KERN_ERR NS_OUTPUT_PREFIX " error: " args); } while(0)
173#define NS_INFO(args...) \
174 do { printk(KERN_INFO NS_OUTPUT_PREFIX " " args); } while(0)
137 175
138/* Busy-wait delay macros (microseconds, milliseconds) */ 176/* Busy-wait delay macros (microseconds, milliseconds) */
139#define NS_UDELAY(us) \ 177#define NS_UDELAY(us) \
@@ -238,7 +276,8 @@ union ns_mem {
238 * The structure which describes all the internal simulator data. 276 * The structure which describes all the internal simulator data.
239 */ 277 */
240struct nandsim { 278struct nandsim {
241 struct mtd_partition part; 279 struct mtd_partition partitions[MAX_MTD_DEVICES];
280 unsigned int nbparts;
242 281
243 uint busw; /* flash chip bus width (8 or 16) */ 282 uint busw; /* flash chip bus width (8 or 16) */
244 u_char ids[4]; /* chip's ID bytes */ 283 u_char ids[4]; /* chip's ID bytes */
@@ -338,6 +377,38 @@ static struct nandsim_operations {
338 STATE_DATAOUT, STATE_READY}} 377 STATE_DATAOUT, STATE_READY}}
339}; 378};
340 379
380struct weak_block {
381 struct list_head list;
382 unsigned int erase_block_no;
383 unsigned int max_erases;
384 unsigned int erases_done;
385};
386
387static LIST_HEAD(weak_blocks);
388
389struct weak_page {
390 struct list_head list;
391 unsigned int page_no;
392 unsigned int max_writes;
393 unsigned int writes_done;
394};
395
396static LIST_HEAD(weak_pages);
397
398struct grave_page {
399 struct list_head list;
400 unsigned int page_no;
401 unsigned int max_reads;
402 unsigned int reads_done;
403};
404
405static LIST_HEAD(grave_pages);
406
407static unsigned long *erase_block_wear = NULL;
408static unsigned int wear_eb_count = 0;
409static unsigned long total_wear = 0;
410static unsigned int rptwear_cnt = 0;
411
341/* MTD structure for NAND controller */ 412/* MTD structure for NAND controller */
342static struct mtd_info *nsmtd; 413static struct mtd_info *nsmtd;
343 414
@@ -381,6 +452,13 @@ static void free_device(struct nandsim *ns)
381 } 452 }
382} 453}
383 454
455static char *get_partition_name(int i)
456{
457 char buf[64];
458 sprintf(buf, "NAND simulator partition %d", i);
459 return kstrdup(buf, GFP_KERNEL);
460}
461
384/* 462/*
385 * Initialize the nandsim structure. 463 * Initialize the nandsim structure.
386 * 464 *
@@ -390,7 +468,9 @@ static int init_nandsim(struct mtd_info *mtd)
390{ 468{
391 struct nand_chip *chip = (struct nand_chip *)mtd->priv; 469 struct nand_chip *chip = (struct nand_chip *)mtd->priv;
392 struct nandsim *ns = (struct nandsim *)(chip->priv); 470 struct nandsim *ns = (struct nandsim *)(chip->priv);
393 int i; 471 int i, ret = 0;
472 u_int32_t remains;
473 u_int32_t next_offset;
394 474
395 if (NS_IS_INITIALIZED(ns)) { 475 if (NS_IS_INITIALIZED(ns)) {
396 NS_ERR("init_nandsim: nandsim is already initialized\n"); 476 NS_ERR("init_nandsim: nandsim is already initialized\n");
@@ -448,6 +528,40 @@ static int init_nandsim(struct mtd_info *mtd)
448 } 528 }
449 } 529 }
450 530
531 /* Fill the partition_info structure */
532 if (parts_num > ARRAY_SIZE(ns->partitions)) {
533 NS_ERR("too many partitions.\n");
534 ret = -EINVAL;
535 goto error;
536 }
537 remains = ns->geom.totsz;
538 next_offset = 0;
539 for (i = 0; i < parts_num; ++i) {
540 unsigned long part = parts[i];
541 if (!part || part > remains / ns->geom.secsz) {
542 NS_ERR("bad partition size.\n");
543 ret = -EINVAL;
544 goto error;
545 }
546 ns->partitions[i].name = get_partition_name(i);
547 ns->partitions[i].offset = next_offset;
548 ns->partitions[i].size = part * ns->geom.secsz;
549 next_offset += ns->partitions[i].size;
550 remains -= ns->partitions[i].size;
551 }
552 ns->nbparts = parts_num;
553 if (remains) {
554 if (parts_num + 1 > ARRAY_SIZE(ns->partitions)) {
555 NS_ERR("too many partitions.\n");
556 ret = -EINVAL;
557 goto error;
558 }
559 ns->partitions[i].name = get_partition_name(i);
560 ns->partitions[i].offset = next_offset;
561 ns->partitions[i].size = remains;
562 ns->nbparts += 1;
563 }
564
451 /* Detect how many ID bytes the NAND chip outputs */ 565 /* Detect how many ID bytes the NAND chip outputs */
452 for (i = 0; nand_flash_ids[i].name != NULL; i++) { 566 for (i = 0; nand_flash_ids[i].name != NULL; i++) {
453 if (second_id_byte != nand_flash_ids[i].id) 567 if (second_id_byte != nand_flash_ids[i].id)
@@ -474,7 +588,7 @@ static int init_nandsim(struct mtd_info *mtd)
474 printk("sector address bytes: %u\n", ns->geom.secaddrbytes); 588 printk("sector address bytes: %u\n", ns->geom.secaddrbytes);
475 printk("options: %#x\n", ns->options); 589 printk("options: %#x\n", ns->options);
476 590
477 if (alloc_device(ns) != 0) 591 if ((ret = alloc_device(ns)) != 0)
478 goto error; 592 goto error;
479 593
480 /* Allocate / initialize the internal buffer */ 594 /* Allocate / initialize the internal buffer */
@@ -482,21 +596,17 @@ static int init_nandsim(struct mtd_info *mtd)
482 if (!ns->buf.byte) { 596 if (!ns->buf.byte) {
483 NS_ERR("init_nandsim: unable to allocate %u bytes for the internal buffer\n", 597 NS_ERR("init_nandsim: unable to allocate %u bytes for the internal buffer\n",
484 ns->geom.pgszoob); 598 ns->geom.pgszoob);
599 ret = -ENOMEM;
485 goto error; 600 goto error;
486 } 601 }
487 memset(ns->buf.byte, 0xFF, ns->geom.pgszoob); 602 memset(ns->buf.byte, 0xFF, ns->geom.pgszoob);
488 603
489 /* Fill the partition_info structure */
490 ns->part.name = "NAND simulator partition";
491 ns->part.offset = 0;
492 ns->part.size = ns->geom.totsz;
493
494 return 0; 604 return 0;
495 605
496error: 606error:
497 free_device(ns); 607 free_device(ns);
498 608
499 return -ENOMEM; 609 return ret;
500} 610}
501 611
502/* 612/*
@@ -510,6 +620,287 @@ static void free_nandsim(struct nandsim *ns)
510 return; 620 return;
511} 621}
512 622
623static int parse_badblocks(struct nandsim *ns, struct mtd_info *mtd)
624{
625 char *w;
626 int zero_ok;
627 unsigned int erase_block_no;
628 loff_t offset;
629
630 if (!badblocks)
631 return 0;
632 w = badblocks;
633 do {
634 zero_ok = (*w == '0' ? 1 : 0);
635 erase_block_no = simple_strtoul(w, &w, 0);
636 if (!zero_ok && !erase_block_no) {
637 NS_ERR("invalid badblocks.\n");
638 return -EINVAL;
639 }
640 offset = erase_block_no * ns->geom.secsz;
641 if (mtd->block_markbad(mtd, offset)) {
642 NS_ERR("invalid badblocks.\n");
643 return -EINVAL;
644 }
645 if (*w == ',')
646 w += 1;
647 } while (*w);
648 return 0;
649}
650
651static int parse_weakblocks(void)
652{
653 char *w;
654 int zero_ok;
655 unsigned int erase_block_no;
656 unsigned int max_erases;
657 struct weak_block *wb;
658
659 if (!weakblocks)
660 return 0;
661 w = weakblocks;
662 do {
663 zero_ok = (*w == '0' ? 1 : 0);
664 erase_block_no = simple_strtoul(w, &w, 0);
665 if (!zero_ok && !erase_block_no) {
666 NS_ERR("invalid weakblocks.\n");
667 return -EINVAL;
668 }
669 max_erases = 3;
670 if (*w == ':') {
671 w += 1;
672 max_erases = simple_strtoul(w, &w, 0);
673 }
674 if (*w == ',')
675 w += 1;
676 wb = kzalloc(sizeof(*wb), GFP_KERNEL);
677 if (!wb) {
678 NS_ERR("unable to allocate memory.\n");
679 return -ENOMEM;
680 }
681 wb->erase_block_no = erase_block_no;
682 wb->max_erases = max_erases;
683 list_add(&wb->list, &weak_blocks);
684 } while (*w);
685 return 0;
686}
687
688static int erase_error(unsigned int erase_block_no)
689{
690 struct weak_block *wb;
691
692 list_for_each_entry(wb, &weak_blocks, list)
693 if (wb->erase_block_no == erase_block_no) {
694 if (wb->erases_done >= wb->max_erases)
695 return 1;
696 wb->erases_done += 1;
697 return 0;
698 }
699 return 0;
700}
701
702static int parse_weakpages(void)
703{
704 char *w;
705 int zero_ok;
706 unsigned int page_no;
707 unsigned int max_writes;
708 struct weak_page *wp;
709
710 if (!weakpages)
711 return 0;
712 w = weakpages;
713 do {
714 zero_ok = (*w == '0' ? 1 : 0);
715 page_no = simple_strtoul(w, &w, 0);
716 if (!zero_ok && !page_no) {
717 NS_ERR("invalid weakpagess.\n");
718 return -EINVAL;
719 }
720 max_writes = 3;
721 if (*w == ':') {
722 w += 1;
723 max_writes = simple_strtoul(w, &w, 0);
724 }
725 if (*w == ',')
726 w += 1;
727 wp = kzalloc(sizeof(*wp), GFP_KERNEL);
728 if (!wp) {
729 NS_ERR("unable to allocate memory.\n");
730 return -ENOMEM;
731 }
732 wp->page_no = page_no;
733 wp->max_writes = max_writes;
734 list_add(&wp->list, &weak_pages);
735 } while (*w);
736 return 0;
737}
738
739static int write_error(unsigned int page_no)
740{
741 struct weak_page *wp;
742
743 list_for_each_entry(wp, &weak_pages, list)
744 if (wp->page_no == page_no) {
745 if (wp->writes_done >= wp->max_writes)
746 return 1;
747 wp->writes_done += 1;
748 return 0;
749 }
750 return 0;
751}
752
753static int parse_gravepages(void)
754{
755 char *g;
756 int zero_ok;
757 unsigned int page_no;
758 unsigned int max_reads;
759 struct grave_page *gp;
760
761 if (!gravepages)
762 return 0;
763 g = gravepages;
764 do {
765 zero_ok = (*g == '0' ? 1 : 0);
766 page_no = simple_strtoul(g, &g, 0);
767 if (!zero_ok && !page_no) {
768 NS_ERR("invalid gravepagess.\n");
769 return -EINVAL;
770 }
771 max_reads = 3;
772 if (*g == ':') {
773 g += 1;
774 max_reads = simple_strtoul(g, &g, 0);
775 }
776 if (*g == ',')
777 g += 1;
778 gp = kzalloc(sizeof(*gp), GFP_KERNEL);
779 if (!gp) {
780 NS_ERR("unable to allocate memory.\n");
781 return -ENOMEM;
782 }
783 gp->page_no = page_no;
784 gp->max_reads = max_reads;
785 list_add(&gp->list, &grave_pages);
786 } while (*g);
787 return 0;
788}
789
790static int read_error(unsigned int page_no)
791{
792 struct grave_page *gp;
793
794 list_for_each_entry(gp, &grave_pages, list)
795 if (gp->page_no == page_no) {
796 if (gp->reads_done >= gp->max_reads)
797 return 1;
798 gp->reads_done += 1;
799 return 0;
800 }
801 return 0;
802}
803
804static void free_lists(void)
805{
806 struct list_head *pos, *n;
807 list_for_each_safe(pos, n, &weak_blocks) {
808 list_del(pos);
809 kfree(list_entry(pos, struct weak_block, list));
810 }
811 list_for_each_safe(pos, n, &weak_pages) {
812 list_del(pos);
813 kfree(list_entry(pos, struct weak_page, list));
814 }
815 list_for_each_safe(pos, n, &grave_pages) {
816 list_del(pos);
817 kfree(list_entry(pos, struct grave_page, list));
818 }
819 kfree(erase_block_wear);
820}
821
822static int setup_wear_reporting(struct mtd_info *mtd)
823{
824 size_t mem;
825
826 if (!rptwear)
827 return 0;
828 wear_eb_count = mtd->size / mtd->erasesize;
829 mem = wear_eb_count * sizeof(unsigned long);
830 if (mem / sizeof(unsigned long) != wear_eb_count) {
831 NS_ERR("Too many erase blocks for wear reporting\n");
832 return -ENOMEM;
833 }
834 erase_block_wear = kzalloc(mem, GFP_KERNEL);
835 if (!erase_block_wear) {
836 NS_ERR("Too many erase blocks for wear reporting\n");
837 return -ENOMEM;
838 }
839 return 0;
840}
841
842static void update_wear(unsigned int erase_block_no)
843{
844 unsigned long wmin = -1, wmax = 0, avg;
845 unsigned long deciles[10], decile_max[10], tot = 0;
846 unsigned int i;
847
848 if (!erase_block_wear)
849 return;
850 total_wear += 1;
851 if (total_wear == 0)
852 NS_ERR("Erase counter total overflow\n");
853 erase_block_wear[erase_block_no] += 1;
854 if (erase_block_wear[erase_block_no] == 0)
855 NS_ERR("Erase counter overflow for erase block %u\n", erase_block_no);
856 rptwear_cnt += 1;
857 if (rptwear_cnt < rptwear)
858 return;
859 rptwear_cnt = 0;
860 /* Calc wear stats */
861 for (i = 0; i < wear_eb_count; ++i) {
862 unsigned long wear = erase_block_wear[i];
863 if (wear < wmin)
864 wmin = wear;
865 if (wear > wmax)
866 wmax = wear;
867 tot += wear;
868 }
869 for (i = 0; i < 9; ++i) {
870 deciles[i] = 0;
871 decile_max[i] = (wmax * (i + 1) + 5) / 10;
872 }
873 deciles[9] = 0;
874 decile_max[9] = wmax;
875 for (i = 0; i < wear_eb_count; ++i) {
876 int d;
877 unsigned long wear = erase_block_wear[i];
878 for (d = 0; d < 10; ++d)
879 if (wear <= decile_max[d]) {
880 deciles[d] += 1;
881 break;
882 }
883 }
884 avg = tot / wear_eb_count;
885 /* Output wear report */
886 NS_INFO("*** Wear Report ***\n");
887 NS_INFO("Total numbers of erases: %lu\n", tot);
888 NS_INFO("Number of erase blocks: %u\n", wear_eb_count);
889 NS_INFO("Average number of erases: %lu\n", avg);
890 NS_INFO("Maximum number of erases: %lu\n", wmax);
891 NS_INFO("Minimum number of erases: %lu\n", wmin);
892 for (i = 0; i < 10; ++i) {
893 unsigned long from = (i ? decile_max[i - 1] + 1 : 0);
894 if (from > decile_max[i])
895 continue;
896 NS_INFO("Number of ebs with erase counts from %lu to %lu : %lu\n",
897 from,
898 decile_max[i],
899 deciles[i]);
900 }
901 NS_INFO("*** End of Wear Report ***\n");
902}
903
513/* 904/*
514 * Returns the string representation of 'state' state. 905 * Returns the string representation of 'state' state.
515 */ 906 */
@@ -822,9 +1213,31 @@ static void read_page(struct nandsim *ns, int num)
822 NS_DBG("read_page: page %d not allocated\n", ns->regs.row); 1213 NS_DBG("read_page: page %d not allocated\n", ns->regs.row);
823 memset(ns->buf.byte, 0xFF, num); 1214 memset(ns->buf.byte, 0xFF, num);
824 } else { 1215 } else {
1216 unsigned int page_no = ns->regs.row;
825 NS_DBG("read_page: page %d allocated, reading from %d\n", 1217 NS_DBG("read_page: page %d allocated, reading from %d\n",
826 ns->regs.row, ns->regs.column + ns->regs.off); 1218 ns->regs.row, ns->regs.column + ns->regs.off);
1219 if (read_error(page_no)) {
1220 int i;
1221 memset(ns->buf.byte, 0xFF, num);
1222 for (i = 0; i < num; ++i)
1223 ns->buf.byte[i] = random32();
1224 NS_WARN("simulating read error in page %u\n", page_no);
1225 return;
1226 }
827 memcpy(ns->buf.byte, NS_PAGE_BYTE_OFF(ns), num); 1227 memcpy(ns->buf.byte, NS_PAGE_BYTE_OFF(ns), num);
1228 if (bitflips && random32() < (1 << 22)) {
1229 int flips = 1;
1230 if (bitflips > 1)
1231 flips = (random32() % (int) bitflips) + 1;
1232 while (flips--) {
1233 int pos = random32() % (num * 8);
1234 ns->buf.byte[pos / 8] ^= (1 << (pos % 8));
1235 NS_WARN("read_page: flipping bit %d in page %d "
1236 "reading from %d ecc: corrected=%u failed=%u\n",
1237 pos, ns->regs.row, ns->regs.column + ns->regs.off,
1238 nsmtd->ecc_stats.corrected, nsmtd->ecc_stats.failed);
1239 }
1240 }
828 } 1241 }
829} 1242}
830 1243
@@ -883,6 +1296,7 @@ static int do_state_action(struct nandsim *ns, uint32_t action)
883{ 1296{
884 int num; 1297 int num;
885 int busdiv = ns->busw == 8 ? 1 : 2; 1298 int busdiv = ns->busw == 8 ? 1 : 2;
1299 unsigned int erase_block_no, page_no;
886 1300
887 action &= ACTION_MASK; 1301 action &= ACTION_MASK;
888 1302
@@ -942,14 +1356,24 @@ static int do_state_action(struct nandsim *ns, uint32_t action)
942 8 * (ns->geom.pgaddrbytes - ns->geom.secaddrbytes)) | ns->regs.column; 1356 8 * (ns->geom.pgaddrbytes - ns->geom.secaddrbytes)) | ns->regs.column;
943 ns->regs.column = 0; 1357 ns->regs.column = 0;
944 1358
1359 erase_block_no = ns->regs.row >> (ns->geom.secshift - ns->geom.pgshift);
1360
945 NS_DBG("do_state_action: erase sector at address %#x, off = %d\n", 1361 NS_DBG("do_state_action: erase sector at address %#x, off = %d\n",
946 ns->regs.row, NS_RAW_OFFSET(ns)); 1362 ns->regs.row, NS_RAW_OFFSET(ns));
947 NS_LOG("erase sector %d\n", ns->regs.row >> (ns->geom.secshift - ns->geom.pgshift)); 1363 NS_LOG("erase sector %u\n", erase_block_no);
948 1364
949 erase_sector(ns); 1365 erase_sector(ns);
950 1366
951 NS_MDELAY(erase_delay); 1367 NS_MDELAY(erase_delay);
952 1368
1369 if (erase_block_wear)
1370 update_wear(erase_block_no);
1371
1372 if (erase_error(erase_block_no)) {
1373 NS_WARN("simulating erase failure in erase block %u\n", erase_block_no);
1374 return -1;
1375 }
1376
953 break; 1377 break;
954 1378
955 case ACTION_PRGPAGE: 1379 case ACTION_PRGPAGE:
@@ -972,6 +1396,8 @@ static int do_state_action(struct nandsim *ns, uint32_t action)
972 if (prog_page(ns, num) == -1) 1396 if (prog_page(ns, num) == -1)
973 return -1; 1397 return -1;
974 1398
1399 page_no = ns->regs.row;
1400
975 NS_DBG("do_state_action: copy %d bytes from int buf to (%#x, %#x), raw off = %d\n", 1401 NS_DBG("do_state_action: copy %d bytes from int buf to (%#x, %#x), raw off = %d\n",
976 num, ns->regs.row, ns->regs.column, NS_RAW_OFFSET(ns) + ns->regs.off); 1402 num, ns->regs.row, ns->regs.column, NS_RAW_OFFSET(ns) + ns->regs.off);
977 NS_LOG("programm page %d\n", ns->regs.row); 1403 NS_LOG("programm page %d\n", ns->regs.row);
@@ -979,6 +1405,11 @@ static int do_state_action(struct nandsim *ns, uint32_t action)
979 NS_UDELAY(programm_delay); 1405 NS_UDELAY(programm_delay);
980 NS_UDELAY(output_cycle * ns->geom.pgsz / 1000 / busdiv); 1406 NS_UDELAY(output_cycle * ns->geom.pgsz / 1000 / busdiv);
981 1407
1408 if (write_error(page_no)) {
1409 NS_WARN("simulating write failure in page %u\n", page_no);
1410 return -1;
1411 }
1412
982 break; 1413 break;
983 1414
984 case ACTION_ZEROOFF: 1415 case ACTION_ZEROOFF:
@@ -1503,7 +1934,7 @@ static int __init ns_init_module(void)
1503{ 1934{
1504 struct nand_chip *chip; 1935 struct nand_chip *chip;
1505 struct nandsim *nand; 1936 struct nandsim *nand;
1506 int retval = -ENOMEM; 1937 int retval = -ENOMEM, i;
1507 1938
1508 if (bus_width != 8 && bus_width != 16) { 1939 if (bus_width != 8 && bus_width != 16) {
1509 NS_ERR("wrong bus width (%d), use only 8 or 16\n", bus_width); 1940 NS_ERR("wrong bus width (%d), use only 8 or 16\n", bus_width);
@@ -1533,6 +1964,8 @@ static int __init ns_init_module(void)
1533 chip->verify_buf = ns_nand_verify_buf; 1964 chip->verify_buf = ns_nand_verify_buf;
1534 chip->read_word = ns_nand_read_word; 1965 chip->read_word = ns_nand_read_word;
1535 chip->ecc.mode = NAND_ECC_SOFT; 1966 chip->ecc.mode = NAND_ECC_SOFT;
1967 /* The NAND_SKIP_BBTSCAN option is necessary for 'overridesize' */
1968 /* and 'badblocks' parameters to work */
1536 chip->options |= NAND_SKIP_BBTSCAN; 1969 chip->options |= NAND_SKIP_BBTSCAN;
1537 1970
1538 /* 1971 /*
@@ -1557,6 +1990,15 @@ static int __init ns_init_module(void)
1557 1990
1558 nsmtd->owner = THIS_MODULE; 1991 nsmtd->owner = THIS_MODULE;
1559 1992
1993 if ((retval = parse_weakblocks()) != 0)
1994 goto error;
1995
1996 if ((retval = parse_weakpages()) != 0)
1997 goto error;
1998
1999 if ((retval = parse_gravepages()) != 0)
2000 goto error;
2001
1560 if ((retval = nand_scan(nsmtd, 1)) != 0) { 2002 if ((retval = nand_scan(nsmtd, 1)) != 0) {
1561 NS_ERR("can't register NAND Simulator\n"); 2003 NS_ERR("can't register NAND Simulator\n");
1562 if (retval > 0) 2004 if (retval > 0)
@@ -1564,23 +2006,44 @@ static int __init ns_init_module(void)
1564 goto error; 2006 goto error;
1565 } 2007 }
1566 2008
1567 if ((retval = init_nandsim(nsmtd)) != 0) { 2009 if (overridesize) {
1568 NS_ERR("scan_bbt: can't initialize the nandsim structure\n"); 2010 u_int32_t new_size = nsmtd->erasesize << overridesize;
1569 goto error; 2011 if (new_size >> overridesize != nsmtd->erasesize) {
2012 NS_ERR("overridesize is too big\n");
2013 goto err_exit;
2014 }
2015 /* N.B. This relies on nand_scan not doing anything with the size before we change it */
2016 nsmtd->size = new_size;
2017 chip->chipsize = new_size;
2018 chip->chip_shift = ffs(new_size) - 1;
1570 } 2019 }
1571 2020
1572 if ((retval = nand_default_bbt(nsmtd)) != 0) { 2021 if ((retval = setup_wear_reporting(nsmtd)) != 0)
1573 free_nandsim(nand); 2022 goto err_exit;
1574 goto error; 2023
1575 } 2024 if ((retval = init_nandsim(nsmtd)) != 0)
2025 goto err_exit;
1576 2026
1577 /* Register NAND as one big partition */ 2027 if ((retval = parse_badblocks(nand, nsmtd)) != 0)
1578 add_mtd_partitions(nsmtd, &nand->part, 1); 2028 goto err_exit;
2029
2030 if ((retval = nand_default_bbt(nsmtd)) != 0)
2031 goto err_exit;
2032
2033 /* Register NAND partitions */
2034 if ((retval = add_mtd_partitions(nsmtd, &nand->partitions[0], nand->nbparts)) != 0)
2035 goto err_exit;
1579 2036
1580 return 0; 2037 return 0;
1581 2038
2039err_exit:
2040 free_nandsim(nand);
2041 nand_release(nsmtd);
2042 for (i = 0;i < ARRAY_SIZE(nand->partitions); ++i)
2043 kfree(nand->partitions[i].name);
1582error: 2044error:
1583 kfree(nsmtd); 2045 kfree(nsmtd);
2046 free_lists();
1584 2047
1585 return retval; 2048 return retval;
1586} 2049}
@@ -1593,10 +2056,14 @@ module_init(ns_init_module);
1593static void __exit ns_cleanup_module(void) 2056static void __exit ns_cleanup_module(void)
1594{ 2057{
1595 struct nandsim *ns = (struct nandsim *)(((struct nand_chip *)nsmtd->priv)->priv); 2058 struct nandsim *ns = (struct nandsim *)(((struct nand_chip *)nsmtd->priv)->priv);
2059 int i;
1596 2060
1597 free_nandsim(ns); /* Free nandsim private resources */ 2061 free_nandsim(ns); /* Free nandsim private resources */
1598 nand_release(nsmtd); /* Unregisterd drived */ 2062 nand_release(nsmtd); /* Unregister driver */
2063 for (i = 0;i < ARRAY_SIZE(ns->partitions); ++i)
2064 kfree(ns->partitions[i].name);
1599 kfree(nsmtd); /* Free other structures */ 2065 kfree(nsmtd); /* Free other structures */
2066 free_lists();
1600} 2067}
1601 2068
1602module_exit(ns_cleanup_module); 2069module_exit(ns_cleanup_module);
@@ -1604,4 +2071,3 @@ module_exit(ns_cleanup_module);
1604MODULE_LICENSE ("GPL"); 2071MODULE_LICENSE ("GPL");
1605MODULE_AUTHOR ("Artem B. Bityuckiy"); 2072MODULE_AUTHOR ("Artem B. Bityuckiy");
1606MODULE_DESCRIPTION ("The NAND flash simulator"); 2073MODULE_DESCRIPTION ("The NAND flash simulator");
1607
diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig
index 373bddce8f1c..c257d397d08a 100644
--- a/drivers/mtd/onenand/Kconfig
+++ b/drivers/mtd/onenand/Kconfig
@@ -2,20 +2,18 @@
2# linux/drivers/mtd/onenand/Kconfig 2# linux/drivers/mtd/onenand/Kconfig
3# 3#
4 4
5menu "OneNAND Flash Device Drivers" 5menuconfig MTD_ONENAND
6 depends on MTD != n
7
8config MTD_ONENAND
9 tristate "OneNAND Device Support" 6 tristate "OneNAND Device Support"
10 depends on MTD 7 depends on MTD
11 help 8 help
12 This enables support for accessing all type of OneNAND flash 9 This enables support for accessing all type of OneNAND flash
13 devices. For further information see 10 devices. For further information see
14 <http://www.samsung.com/Products/Semiconductor/Flash/OneNAND_TM/index.htm>. 11 <http://www.samsung.com/Products/Semiconductor/OneNAND/index.htm>
12
13if MTD_ONENAND
15 14
16config MTD_ONENAND_VERIFY_WRITE 15config MTD_ONENAND_VERIFY_WRITE
17 bool "Verify OneNAND page writes" 16 bool "Verify OneNAND page writes"
18 depends on MTD_ONENAND
19 help 17 help
20 This adds an extra check when data is written to the flash. The 18 This adds an extra check when data is written to the flash. The
21 OneNAND flash device internally checks only bits transitioning 19 OneNAND flash device internally checks only bits transitioning
@@ -25,13 +23,12 @@ config MTD_ONENAND_VERIFY_WRITE
25 23
26config MTD_ONENAND_GENERIC 24config MTD_ONENAND_GENERIC
27 tristate "OneNAND Flash device via platform device driver" 25 tristate "OneNAND Flash device via platform device driver"
28 depends on MTD_ONENAND && ARM 26 depends on ARM
29 help 27 help
30 Support for OneNAND flash via platform device driver. 28 Support for OneNAND flash via platform device driver.
31 29
32config MTD_ONENAND_OTP 30config MTD_ONENAND_OTP
33 bool "OneNAND OTP Support" 31 bool "OneNAND OTP Support"
34 depends on MTD_ONENAND
35 help 32 help
36 One Block of the NAND Flash Array memory is reserved as 33 One Block of the NAND Flash Array memory is reserved as
37 a One-Time Programmable Block memory area. 34 a One-Time Programmable Block memory area.
@@ -43,4 +40,4 @@ config MTD_ONENAND_OTP
43 40
44 OTP block is fully-guaranteed to be a valid block. 41 OTP block is fully-guaranteed to be a valid block.
45 42
46endmenu 43endif # MTD_ONENAND
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 9e14a26ca4e8..000794c6caf5 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -836,9 +836,11 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf, int col
836 int readcol = column; 836 int readcol = column;
837 int readend = column + thislen; 837 int readend = column + thislen;
838 int lastgap = 0; 838 int lastgap = 0;
839 unsigned int i;
839 uint8_t *oob_buf = this->oob_buf; 840 uint8_t *oob_buf = this->oob_buf;
840 841
841 for (free = this->ecclayout->oobfree; free->length; ++free) { 842 free = this->ecclayout->oobfree;
843 for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
842 if (readcol >= lastgap) 844 if (readcol >= lastgap)
843 readcol += free->offset - lastgap; 845 readcol += free->offset - lastgap;
844 if (readend >= lastgap) 846 if (readend >= lastgap)
@@ -846,7 +848,8 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf, int col
846 lastgap = free->offset + free->length; 848 lastgap = free->offset + free->length;
847 } 849 }
848 this->read_bufferram(mtd, ONENAND_SPARERAM, oob_buf, 0, mtd->oobsize); 850 this->read_bufferram(mtd, ONENAND_SPARERAM, oob_buf, 0, mtd->oobsize);
849 for (free = this->ecclayout->oobfree; free->length; ++free) { 851 free = this->ecclayout->oobfree;
852 for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
850 int free_end = free->offset + free->length; 853 int free_end = free->offset + free->length;
851 if (free->offset < readend && free_end > readcol) { 854 if (free->offset < readend && free_end > readcol) {
852 int st = max_t(int,free->offset,readcol); 855 int st = max_t(int,free->offset,readcol);
@@ -854,7 +857,7 @@ static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf, int col
854 int n = ed - st; 857 int n = ed - st;
855 memcpy(buf, oob_buf + st, n); 858 memcpy(buf, oob_buf + st, n);
856 buf += n; 859 buf += n;
857 } else 860 } else if (column == 0)
858 break; 861 break;
859 } 862 }
860 return 0; 863 return 0;
@@ -1280,15 +1283,18 @@ static int onenand_fill_auto_oob(struct mtd_info *mtd, u_char *oob_buf,
1280 int writecol = column; 1283 int writecol = column;
1281 int writeend = column + thislen; 1284 int writeend = column + thislen;
1282 int lastgap = 0; 1285 int lastgap = 0;
1286 unsigned int i;
1283 1287
1284 for (free = this->ecclayout->oobfree; free->length; ++free) { 1288 free = this->ecclayout->oobfree;
1289 for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
1285 if (writecol >= lastgap) 1290 if (writecol >= lastgap)
1286 writecol += free->offset - lastgap; 1291 writecol += free->offset - lastgap;
1287 if (writeend >= lastgap) 1292 if (writeend >= lastgap)
1288 writeend += free->offset - lastgap; 1293 writeend += free->offset - lastgap;
1289 lastgap = free->offset + free->length; 1294 lastgap = free->offset + free->length;
1290 } 1295 }
1291 for (free = this->ecclayout->oobfree; free->length; ++free) { 1296 free = this->ecclayout->oobfree;
1297 for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
1292 int free_end = free->offset + free->length; 1298 int free_end = free->offset + free->length;
1293 if (free->offset < writeend && free_end > writecol) { 1299 if (free->offset < writeend && free_end > writecol) {
1294 int st = max_t(int,free->offset,writecol); 1300 int st = max_t(int,free->offset,writecol);
@@ -1296,7 +1302,7 @@ static int onenand_fill_auto_oob(struct mtd_info *mtd, u_char *oob_buf,
1296 int n = ed - st; 1302 int n = ed - st;
1297 memcpy(oob_buf + st, buf, n); 1303 memcpy(oob_buf + st, buf, n);
1298 buf += n; 1304 buf += n;
1299 } else 1305 } else if (column == 0)
1300 break; 1306 break;
1301 } 1307 }
1302 return 0; 1308 return 0;
@@ -2386,7 +2392,8 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
2386 * the out of band area 2392 * the out of band area
2387 */ 2393 */
2388 this->ecclayout->oobavail = 0; 2394 this->ecclayout->oobavail = 0;
2389 for (i = 0; this->ecclayout->oobfree[i].length; i++) 2395 for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES &&
2396 this->ecclayout->oobfree[i].length; i++)
2390 this->ecclayout->oobavail += 2397 this->ecclayout->oobavail +=
2391 this->ecclayout->oobfree[i].length; 2398 this->ecclayout->oobfree[i].length;
2392 mtd->oobavail = this->ecclayout->oobavail; 2399 mtd->oobavail = this->ecclayout->oobavail;
diff --git a/fs/jffs2/LICENCE b/fs/jffs2/LICENCE
index cd81d83e4ad2..562885908135 100644
--- a/fs/jffs2/LICENCE
+++ b/fs/jffs2/LICENCE
@@ -1,7 +1,7 @@
1The files in this directory and elsewhere which refer to this LICENCE 1The files in this directory and elsewhere which refer to this LICENCE
2file are part of JFFS2, the Journalling Flash File System v2. 2file are part of JFFS2, the Journalling Flash File System v2.
3 3
4 Copyright (C) 2001, 2002 Red Hat, Inc. 4 Copyright © 2001-2007 Red Hat, Inc. and others
5 5
6JFFS2 is free software; you can redistribute it and/or modify it under 6JFFS2 is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free 7the terms of the GNU General Public License as published by the Free
@@ -28,8 +28,3 @@ of the GNU General Public License.
28This exception does not invalidate any other reasons why a work based on 28This exception does not invalidate any other reasons why a work based on
29this file might be covered by the GNU General Public License. 29this file might be covered by the GNU General Public License.
30 30
31For information on obtaining alternative licences for JFFS2, see
32http://sources.redhat.com/jffs2/jffs2-licence.html
33
34
35 $Id: LICENCE,v 1.1 2002/05/20 14:56:37 dwmw2 Exp $
diff --git a/fs/jffs2/Makefile b/fs/jffs2/Makefile
index 7f28ee0bd132..c32b241e3d91 100644
--- a/fs/jffs2/Makefile
+++ b/fs/jffs2/Makefile
@@ -1,7 +1,6 @@
1# 1#
2# Makefile for the Linux Journalling Flash File System v2 (JFFS2) 2# Makefile for the Linux Journalling Flash File System v2 (JFFS2)
3# 3#
4# $Id: Makefile.common,v 1.11 2005/09/07 08:34:53 havasi Exp $
5# 4#
6 5
7obj-$(CONFIG_JFFS2_FS) += jffs2.o 6obj-$(CONFIG_JFFS2_FS) += jffs2.o
diff --git a/fs/jffs2/README.Locking b/fs/jffs2/README.Locking
index c8f0bd64e53e..d14d5a4dc5ac 100644
--- a/fs/jffs2/README.Locking
+++ b/fs/jffs2/README.Locking
@@ -1,4 +1,3 @@
1 $Id: README.Locking,v 1.12 2005/04/13 13:22:35 dwmw2 Exp $
2 1
3 JFFS2 LOCKING DOCUMENTATION 2 JFFS2 LOCKING DOCUMENTATION
4 --------------------------- 3 ---------------------------
diff --git a/fs/jffs2/TODO b/fs/jffs2/TODO
index d0e23b26fa50..5d3ea4070f01 100644
--- a/fs/jffs2/TODO
+++ b/fs/jffs2/TODO
@@ -1,4 +1,3 @@
1$Id: TODO,v 1.18 2005/09/22 11:24:56 dedekind Exp $
2 1
3 - support asynchronous operation -- add a per-fs 'reserved_space' count, 2 - support asynchronous operation -- add a per-fs 'reserved_space' count,
4 let each outstanding write reserve the _maximum_ amount of physical 3 let each outstanding write reserve the _maximum_ amount of physical
@@ -30,8 +29,6 @@ $Id: TODO,v 1.18 2005/09/22 11:24:56 dedekind Exp $
30 the full dirent, we only need to go to the flash in lookup() when we think we've 29 the full dirent, we only need to go to the flash in lookup() when we think we've
31 got a match, and in readdir(). 30 got a match, and in readdir().
32 - Doubly-linked next_in_ino list to allow us to free obsoleted raw_node_refs immediately? 31 - Doubly-linked next_in_ino list to allow us to free obsoleted raw_node_refs immediately?
33 - Remove totlen from jffs2_raw_node_ref? Need to have totlen passed into
34 jffs2_mark_node_obsolete(). Can all callers work it out?
35 - Remove size from jffs2_raw_node_frag. 32 - Remove size from jffs2_raw_node_frag.
36 33
37dedekind: 34dedekind:
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
index 73f0d60f73a5..a46101ee867a 100644
--- a/fs/jffs2/acl.c
+++ b/fs/jffs2/acl.c
@@ -1,13 +1,14 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2006 NEC Corporation 4 * Copyright © 2006 NEC Corporation
5 * 5 *
6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> 6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 */ 10 */
11
11#include <linux/kernel.h> 12#include <linux/kernel.h>
12#include <linux/slab.h> 13#include <linux/slab.h>
13#include <linux/fs.h> 14#include <linux/fs.h>
diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h
index fa327dbd3171..c84378cee82a 100644
--- a/fs/jffs2/acl.h
+++ b/fs/jffs2/acl.h
@@ -1,13 +1,14 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2006 NEC Corporation 4 * Copyright © 2006 NEC Corporation
5 * 5 *
6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> 6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 */ 10 */
11
11struct jffs2_acl_entry { 12struct jffs2_acl_entry {
12 jint16_t e_tag; 13 jint16_t e_tag;
13 jint16_t e_perm; 14 jint16_t e_perm;
diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c
index 888f236e5494..0c82dfcfd246 100644
--- a/fs/jffs2/background.c
+++ b/fs/jffs2/background.c
@@ -1,14 +1,12 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by David Woodhouse <dwmw2@infradead.org> 6 * Created by David Woodhouse <dwmw2@infradead.org>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: background.c,v 1.54 2005/05/20 21:37:12 gleixner Exp $
11 *
12 */ 10 */
13 11
14#include <linux/kernel.h> 12#include <linux/kernel.h>
diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c
index 07119c42a861..0ca2fff2617f 100644
--- a/fs/jffs2/build.c
+++ b/fs/jffs2/build.c
@@ -1,14 +1,12 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by David Woodhouse <dwmw2@infradead.org> 6 * Created by David Woodhouse <dwmw2@infradead.org>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: build.c,v 1.85 2005/11/07 11:14:38 gleixner Exp $
11 *
12 */ 10 */
13 11
14#include <linux/kernel.h> 12#include <linux/kernel.h>
diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c
index 7001ba26c067..485d065de41f 100644
--- a/fs/jffs2/compr.c
+++ b/fs/jffs2/compr.c
@@ -1,16 +1,14 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * Created by Arjan van de Ven <arjanv@redhat.com> 5 * Created by Arjan van de Ven <arjanv@redhat.com>
6 * 6 *
7 * Copyright (C) 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>, 7 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
8 * University of Szeged, Hungary 8 * University of Szeged, Hungary
9 * 9 *
10 * For licensing information, see the file 'LICENCE' in this directory. 10 * For licensing information, see the file 'LICENCE' in this directory.
11 * 11 *
12 * $Id: compr.c,v 1.46 2005/11/07 11:14:38 gleixner Exp $
13 *
14 */ 12 */
15 13
16#include "compr.h" 14#include "compr.h"
@@ -268,144 +266,6 @@ int jffs2_unregister_compressor(struct jffs2_compressor *comp)
268 return 0; 266 return 0;
269} 267}
270 268
271#ifdef CONFIG_JFFS2_PROC
272
273#define JFFS2_STAT_BUF_SIZE 16000
274
275char *jffs2_list_compressors(void)
276{
277 struct jffs2_compressor *this;
278 char *buf, *act_buf;
279
280 act_buf = buf = kmalloc(JFFS2_STAT_BUF_SIZE,GFP_KERNEL);
281 list_for_each_entry(this, &jffs2_compressor_list, list) {
282 act_buf += sprintf(act_buf, "%10s priority:%d ", this->name, this->priority);
283 if ((this->disabled)||(!this->compress))
284 act_buf += sprintf(act_buf,"disabled");
285 else
286 act_buf += sprintf(act_buf,"enabled");
287 act_buf += sprintf(act_buf,"\n");
288 }
289 return buf;
290}
291
292char *jffs2_stats(void)
293{
294 struct jffs2_compressor *this;
295 char *buf, *act_buf;
296
297 act_buf = buf = kmalloc(JFFS2_STAT_BUF_SIZE,GFP_KERNEL);
298
299 act_buf += sprintf(act_buf,"JFFS2 compressor statistics:\n");
300 act_buf += sprintf(act_buf,"%10s ","none");
301 act_buf += sprintf(act_buf,"compr: %d blocks (%d) decompr: %d blocks\n", none_stat_compr_blocks,
302 none_stat_compr_size, none_stat_decompr_blocks);
303 spin_lock(&jffs2_compressor_list_lock);
304 list_for_each_entry(this, &jffs2_compressor_list, list) {
305 act_buf += sprintf(act_buf,"%10s ",this->name);
306 if ((this->disabled)||(!this->compress))
307 act_buf += sprintf(act_buf,"- ");
308 else
309 act_buf += sprintf(act_buf,"+ ");
310 act_buf += sprintf(act_buf,"compr: %d blocks (%d/%d) decompr: %d blocks ", this->stat_compr_blocks,
311 this->stat_compr_new_size, this->stat_compr_orig_size,
312 this->stat_decompr_blocks);
313 act_buf += sprintf(act_buf,"\n");
314 }
315 spin_unlock(&jffs2_compressor_list_lock);
316
317 return buf;
318}
319
320char *jffs2_get_compression_mode_name(void)
321{
322 switch (jffs2_compression_mode) {
323 case JFFS2_COMPR_MODE_NONE:
324 return "none";
325 case JFFS2_COMPR_MODE_PRIORITY:
326 return "priority";
327 case JFFS2_COMPR_MODE_SIZE:
328 return "size";
329 }
330 return "unkown";
331}
332
333int jffs2_set_compression_mode_name(const char *name)
334{
335 if (!strcmp("none",name)) {
336 jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
337 return 0;
338 }
339 if (!strcmp("priority",name)) {
340 jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY;
341 return 0;
342 }
343 if (!strcmp("size",name)) {
344 jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE;
345 return 0;
346 }
347 return 1;
348}
349
350static int jffs2_compressor_Xable(const char *name, int disabled)
351{
352 struct jffs2_compressor *this;
353 spin_lock(&jffs2_compressor_list_lock);
354 list_for_each_entry(this, &jffs2_compressor_list, list) {
355 if (!strcmp(this->name, name)) {
356 this->disabled = disabled;
357 spin_unlock(&jffs2_compressor_list_lock);
358 return 0;
359 }
360 }
361 spin_unlock(&jffs2_compressor_list_lock);
362 printk(KERN_WARNING "JFFS2: compressor %s not found.\n",name);
363 return 1;
364}
365
366int jffs2_enable_compressor_name(const char *name)
367{
368 return jffs2_compressor_Xable(name, 0);
369}
370
371int jffs2_disable_compressor_name(const char *name)
372{
373 return jffs2_compressor_Xable(name, 1);
374}
375
376int jffs2_set_compressor_priority(const char *name, int priority)
377{
378 struct jffs2_compressor *this,*comp;
379 spin_lock(&jffs2_compressor_list_lock);
380 list_for_each_entry(this, &jffs2_compressor_list, list) {
381 if (!strcmp(this->name, name)) {
382 this->priority = priority;
383 comp = this;
384 goto reinsert;
385 }
386 }
387 spin_unlock(&jffs2_compressor_list_lock);
388 printk(KERN_WARNING "JFFS2: compressor %s not found.\n",name);
389 return 1;
390reinsert:
391 /* list is sorted in the order of priority, so if
392 we change it we have to reinsert it into the
393 good place */
394 list_del(&comp->list);
395 list_for_each_entry(this, &jffs2_compressor_list, list) {
396 if (this->priority < comp->priority) {
397 list_add(&comp->list, this->list.prev);
398 spin_unlock(&jffs2_compressor_list_lock);
399 return 0;
400 }
401 }
402 list_add_tail(&comp->list, &jffs2_compressor_list);
403 spin_unlock(&jffs2_compressor_list_lock);
404 return 0;
405}
406
407#endif
408
409void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig) 269void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig)
410{ 270{
411 if (orig != comprbuf) 271 if (orig != comprbuf)
diff --git a/fs/jffs2/compr.h b/fs/jffs2/compr.h
index 509b8b1c0811..68cc7010dbdf 100644
--- a/fs/jffs2/compr.h
+++ b/fs/jffs2/compr.h
@@ -1,13 +1,10 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>, 4 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
5 * University of Szeged, Hungary 5 * University of Szeged, Hungary
6 * 6 *
7 * For licensing information, see the file 'LICENCE' in the 7 * For licensing information, see the file 'LICENCE' in this directory.
8 * jffs2 directory.
9 *
10 * $Id: compr.h,v 1.9 2005/11/07 11:14:38 gleixner Exp $
11 * 8 *
12 */ 9 */
13 10
@@ -76,16 +73,6 @@ int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
76 73
77void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig); 74void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig);
78 75
79#ifdef CONFIG_JFFS2_PROC
80int jffs2_enable_compressor_name(const char *name);
81int jffs2_disable_compressor_name(const char *name);
82int jffs2_set_compression_mode_name(const char *mode_name);
83char *jffs2_get_compression_mode_name(void);
84int jffs2_set_compressor_priority(const char *mode_name, int priority);
85char *jffs2_list_compressors(void);
86char *jffs2_stats(void);
87#endif
88
89/* Compressor modules */ 76/* Compressor modules */
90/* These functions will be called by jffs2_compressors_init/exit */ 77/* These functions will be called by jffs2_compressors_init/exit */
91 78
diff --git a/fs/jffs2/compr_rtime.c b/fs/jffs2/compr_rtime.c
index 2eb1b7428d16..0d0bfd2e4e0d 100644
--- a/fs/jffs2/compr_rtime.c
+++ b/fs/jffs2/compr_rtime.c
@@ -1,13 +1,12 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by Arjan van de Ven <arjanv@redhat.com> 6 * Created by Arjan van de Ven <arjanv@redhat.com>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: compr_rtime.c,v 1.14 2004/06/23 16:34:40 havasi Exp $
11 * 10 *
12 * 11 *
13 * Very simple lz77-ish encoder. 12 * Very simple lz77-ish encoder.
diff --git a/fs/jffs2/compr_rubin.c b/fs/jffs2/compr_rubin.c
index e792e675d624..ea0431e047d5 100644
--- a/fs/jffs2/compr_rubin.c
+++ b/fs/jffs2/compr_rubin.c
@@ -1,23 +1,94 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001, 2002 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by Arjan van de Ven <arjanv@redhat.com> 6 * Created by Arjan van de Ven <arjanv@redhat.com>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: compr_rubin.c,v 1.20 2004/06/23 16:34:40 havasi Exp $
11 *
12 */ 10 */
13 11
14#include <linux/string.h> 12#include <linux/string.h>
15#include <linux/types.h> 13#include <linux/types.h>
16#include <linux/jffs2.h> 14#include <linux/jffs2.h>
17#include "compr_rubin.h" 15#include <linux/errno.h>
18#include "histo_mips.h"
19#include "compr.h" 16#include "compr.h"
20 17
18
19#define RUBIN_REG_SIZE 16
20#define UPPER_BIT_RUBIN (((long) 1)<<(RUBIN_REG_SIZE-1))
21#define LOWER_BITS_RUBIN ((((long) 1)<<(RUBIN_REG_SIZE-1))-1)
22
23
24#define BIT_DIVIDER_MIPS 1043
25static int bits_mips[8] = { 277,249,290,267,229,341,212,241}; /* mips32 */
26
27#include <linux/errno.h>
28
29struct pushpull {
30 unsigned char *buf;
31 unsigned int buflen;
32 unsigned int ofs;
33 unsigned int reserve;
34};
35
36struct rubin_state {
37 unsigned long p;
38 unsigned long q;
39 unsigned long rec_q;
40 long bit_number;
41 struct pushpull pp;
42 int bit_divider;
43 int bits[8];
44};
45
46static inline void init_pushpull(struct pushpull *pp, char *buf, unsigned buflen, unsigned ofs, unsigned reserve)
47{
48 pp->buf = buf;
49 pp->buflen = buflen;
50 pp->ofs = ofs;
51 pp->reserve = reserve;
52}
53
54static inline int pushbit(struct pushpull *pp, int bit, int use_reserved)
55{
56 if (pp->ofs >= pp->buflen - (use_reserved?0:pp->reserve)) {
57 return -ENOSPC;
58 }
59
60 if (bit) {
61 pp->buf[pp->ofs >> 3] |= (1<<(7-(pp->ofs &7)));
62 }
63 else {
64 pp->buf[pp->ofs >> 3] &= ~(1<<(7-(pp->ofs &7)));
65 }
66 pp->ofs++;
67
68 return 0;
69}
70
71static inline int pushedbits(struct pushpull *pp)
72{
73 return pp->ofs;
74}
75
76static inline int pullbit(struct pushpull *pp)
77{
78 int bit;
79
80 bit = (pp->buf[pp->ofs >> 3] >> (7-(pp->ofs & 7))) & 1;
81
82 pp->ofs++;
83 return bit;
84}
85
86static inline int pulledbits(struct pushpull *pp)
87{
88 return pp->ofs;
89}
90
91
21static void init_rubin(struct rubin_state *rs, int div, int *bits) 92static void init_rubin(struct rubin_state *rs, int div, int *bits)
22{ 93{
23 int c; 94 int c;
diff --git a/fs/jffs2/compr_rubin.h b/fs/jffs2/compr_rubin.h
deleted file mode 100644
index bf1a93451621..000000000000
--- a/fs/jffs2/compr_rubin.h
+++ /dev/null
@@ -1,21 +0,0 @@
1/* Rubin encoder/decoder header */
2/* work started at : aug 3, 1994 */
3/* last modification : aug 15, 1994 */
4/* $Id: compr_rubin.h,v 1.7 2005/11/07 11:14:38 gleixner Exp $ */
5
6#include "pushpull.h"
7
8#define RUBIN_REG_SIZE 16
9#define UPPER_BIT_RUBIN (((long) 1)<<(RUBIN_REG_SIZE-1))
10#define LOWER_BITS_RUBIN ((((long) 1)<<(RUBIN_REG_SIZE-1))-1)
11
12
13struct rubin_state {
14 unsigned long p;
15 unsigned long q;
16 unsigned long rec_q;
17 long bit_number;
18 struct pushpull pp;
19 int bit_divider;
20 int bits[8];
21};
diff --git a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c
index 0c1fc6e20b43..2b87fccc1557 100644
--- a/fs/jffs2/compr_zlib.c
+++ b/fs/jffs2/compr_zlib.c
@@ -1,14 +1,12 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by David Woodhouse <dwmw2@infradead.org> 6 * Created by David Woodhouse <dwmw2@infradead.org>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: compr_zlib.c,v 1.32 2005/11/07 11:14:38 gleixner Exp $
11 *
12 */ 10 */
13 11
14#if !defined(__KERNEL__) && !defined(__ECOS) 12#if !defined(__KERNEL__) && !defined(__ECOS)
diff --git a/fs/jffs2/comprtest.c b/fs/jffs2/comprtest.c
deleted file mode 100644
index f0fb8be7740c..000000000000
--- a/fs/jffs2/comprtest.c
+++ /dev/null
@@ -1,307 +0,0 @@
1/* $Id: comprtest.c,v 1.6 2005/11/07 11:14:38 gleixner Exp $ */
2
3#include <linux/kernel.h>
4#include <linux/string.h>
5#include <linux/module.h>
6#include <asm/types.h>
7#if 0
8#define TESTDATA_LEN 512
9static unsigned char testdata[TESTDATA_LEN] = {
10 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x83, 0x04, 0x08, 0x34, 0x00, 0x00, 0x00,
12 0xb0, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x20, 0x00, 0x06, 0x00, 0x28, 0x00,
13 0x1e, 0x00, 0x1b, 0x00, 0x06, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x80, 0x04, 0x08,
14 0x34, 0x80, 0x04, 0x08, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
15 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0xf4, 0x80, 0x04, 0x08,
16 0xf4, 0x80, 0x04, 0x08, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
17 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x08,
18 0x00, 0x80, 0x04, 0x08, 0x0d, 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
19 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0x00, 0x10, 0x95, 0x04, 0x08,
20 0x10, 0x95, 0x04, 0x08, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
21 0x00, 0x10, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x58, 0x05, 0x00, 0x00, 0x58, 0x95, 0x04, 0x08,
22 0x58, 0x95, 0x04, 0x08, 0xa0, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
23 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x08, 0x81, 0x04, 0x08,
24 0x08, 0x81, 0x04, 0x08, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
25 0x04, 0x00, 0x00, 0x00, 0x2f, 0x6c, 0x69, 0x62, 0x2f, 0x6c, 0x64, 0x2d, 0x6c, 0x69, 0x6e, 0x75,
26 0x78, 0x2e, 0x73, 0x6f, 0x2e, 0x32, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
27 0x01, 0x00, 0x00, 0x00, 0x47, 0x4e, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
28 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
29 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
30 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
32 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00,
33 0x0c, 0x83, 0x04, 0x08, 0x81, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
34 0x1c, 0x83, 0x04, 0x08, 0xac, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00,
35 0x2c, 0x83, 0x04, 0x08, 0xdd, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
36 0x3c, 0x83, 0x04, 0x08, 0x2e, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
37 0x4c, 0x83, 0x04, 0x08, 0x7d, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
38 0x00, 0x85, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x00, 0x00,
39 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x67,
40 0x6d, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x5f, 0x00, 0x6c, 0x69, 0x62, 0x63,
41 0x2e, 0x73, 0x6f, 0x2e, 0x36, 0x00, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x00, 0x5f, 0x5f, 0x63};
42#else
43#define TESTDATA_LEN 3481
44static unsigned char testdata[TESTDATA_LEN] = {
45 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x22, 0x64, 0x62, 0x65, 0x6e, 0x63, 0x68,
46 0x2e, 0x68, 0x22, 0x0a, 0x0a, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x4d, 0x41, 0x58,
47 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x20, 0x31, 0x30, 0x30, 0x30, 0x0a, 0x0a, 0x73, 0x74, 0x61,
48 0x74, 0x69, 0x63, 0x20, 0x63, 0x68, 0x61, 0x72, 0x20, 0x62, 0x75, 0x66, 0x5b, 0x37, 0x30, 0x30,
49 0x30, 0x30, 0x5d, 0x3b, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x20,
50 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x61,
51 0x74, 0x69, 0x63, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x7b, 0x0a, 0x09, 0x69, 0x6e,
52 0x74, 0x20, 0x66, 0x64, 0x3b, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c,
53 0x65, 0x3b, 0x0a, 0x7d, 0x20, 0x66, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x4d, 0x41, 0x58, 0x5f,
54 0x46, 0x49, 0x4c, 0x45, 0x53, 0x5d, 0x3b, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f,
55 0x5f, 0x75, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x28, 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x66, 0x6e,
56 0x61, 0x6d, 0x65, 0x29, 0x0a, 0x7b, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x75, 0x70, 0x70, 0x65, 0x72,
57 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x3b, 0x0a, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x75,
58 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x20, 0x21, 0x3d, 0x20,
59 0x30, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x28,
60 0x25, 0x64, 0x29, 0x20, 0x75, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x25, 0x73, 0x20, 0x66, 0x61,
61 0x69, 0x6c, 0x65, 0x64, 0x20, 0x28, 0x25, 0x73, 0x29, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09,
62 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75,
63 0x6e, 0x74, 0x2c, 0x20, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x65, 0x72,
64 0x72, 0x6f, 0x72, 0x28, 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x29, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a,
65 0x7d, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x5f, 0x66,
66 0x69, 0x6c, 0x65, 0x28, 0x69, 0x6e, 0x74, 0x20, 0x66, 0x64, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20,
67 0x73, 0x69, 0x7a, 0x65, 0x29, 0x0a, 0x7b, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x73, 0x3b, 0x0a,
68 0x09, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x28, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x20, 0x7b, 0x0a,
69 0x09, 0x09, 0x73, 0x20, 0x3d, 0x20, 0x4d, 0x49, 0x4e, 0x28, 0x73, 0x69, 0x7a, 0x65, 0x6f, 0x66,
70 0x28, 0x62, 0x75, 0x66, 0x29, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x09,
71 0x77, 0x72, 0x69, 0x74, 0x65, 0x28, 0x66, 0x64, 0x2c, 0x20, 0x62, 0x75, 0x66, 0x2c, 0x20, 0x73,
72 0x29, 0x3b, 0x0a, 0x09, 0x09, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x2d, 0x3d, 0x20, 0x73, 0x3b, 0x0a,
73 0x09, 0x7d, 0x0a, 0x7d, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x6f, 0x70,
74 0x65, 0x6e, 0x28, 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20,
75 0x69, 0x6e, 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20,
76 0x73, 0x69, 0x7a, 0x65, 0x29, 0x0a, 0x7b, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x66, 0x64, 0x2c,
77 0x20, 0x69, 0x3b, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x3d,
78 0x20, 0x4f, 0x5f, 0x52, 0x44, 0x57, 0x52, 0x7c, 0x4f, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x3b,
79 0x0a, 0x09, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x73, 0x74, 0x61, 0x74, 0x20, 0x73, 0x74,
80 0x3b, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x63, 0x6f,
81 0x75, 0x6e, 0x74, 0x3b, 0x0a, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x75, 0x70, 0x70, 0x65, 0x72, 0x28,
82 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x3b, 0x0a, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x73, 0x69,
83 0x7a, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x7c,
84 0x3d, 0x20, 0x4f, 0x5f, 0x54, 0x52, 0x55, 0x4e, 0x43, 0x3b, 0x0a, 0x0a, 0x09, 0x66, 0x64, 0x20,
85 0x3d, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x66, 0x6c,
86 0x61, 0x67, 0x73, 0x2c, 0x20, 0x30, 0x36, 0x30, 0x30, 0x29, 0x3b, 0x0a, 0x09, 0x69, 0x66, 0x20,
87 0x28, 0x66, 0x64, 0x20, 0x3d, 0x3d, 0x20, 0x2d, 0x31, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70,
88 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x28, 0x25, 0x64, 0x29, 0x20, 0x6f, 0x70, 0x65, 0x6e,
89 0x20, 0x25, 0x73, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x68,
90 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x25, 0x64, 0x20, 0x28, 0x25, 0x73, 0x29, 0x5c, 0x6e, 0x22,
91 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65,
92 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2c, 0x20, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x68,
93 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28,
94 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x29, 0x29, 0x3b, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72,
95 0x6e, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x66, 0x73, 0x74, 0x61, 0x74, 0x28, 0x66, 0x64, 0x2c,
96 0x20, 0x26, 0x73, 0x74, 0x29, 0x3b, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x73, 0x69, 0x7a, 0x65,
97 0x20, 0x3e, 0x20, 0x73, 0x74, 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x20, 0x7b,
98 0x0a, 0x23, 0x69, 0x66, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69,
99 0x6e, 0x74, 0x66, 0x28, 0x22, 0x28, 0x25, 0x64, 0x29, 0x20, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64,
100 0x69, 0x6e, 0x67, 0x20, 0x25, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x25, 0x64, 0x20, 0x66, 0x72, 0x6f,
101 0x6d, 0x20, 0x25, 0x64, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20,
102 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2c, 0x20, 0x66,
103 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2c, 0x20, 0x28, 0x69, 0x6e, 0x74,
104 0x29, 0x73, 0x74, 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x23, 0x65,
105 0x6e, 0x64, 0x69, 0x66, 0x0a, 0x09, 0x09, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x5f, 0x66, 0x69,
106 0x6c, 0x65, 0x28, 0x66, 0x64, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x2d, 0x20, 0x73, 0x74,
107 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x20, 0x65, 0x6c,
108 0x73, 0x65, 0x20, 0x69, 0x66, 0x20, 0x28, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x3c, 0x20, 0x73, 0x74,
109 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72,
110 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x69, 0x6e, 0x67,
111 0x20, 0x25, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x25, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x25,
112 0x64, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
113 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2c, 0x20, 0x28, 0x69, 0x6e,
114 0x74, 0x29, 0x73, 0x74, 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x09,
115 0x09, 0x66, 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x28, 0x66, 0x64, 0x2c, 0x20, 0x73,
116 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x69,
117 0x3d, 0x30, 0x3b, 0x69, 0x3c, 0x4d, 0x41, 0x58, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x3b, 0x69,
118 0x2b, 0x2b, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x66, 0x74, 0x61, 0x62,
119 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x3d, 0x3d, 0x20,
120 0x30, 0x29, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x69, 0x66,
121 0x20, 0x28, 0x69, 0x20, 0x3d, 0x3d, 0x20, 0x4d, 0x41, 0x58, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53,
122 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x66, 0x69,
123 0x6c, 0x65, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20, 0x66, 0x6f,
124 0x72, 0x20, 0x25, 0x73, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x3b,
125 0x0a, 0x09, 0x09, 0x65, 0x78, 0x69, 0x74, 0x28, 0x31, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09,
126 0x66, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65,
127 0x20, 0x3d, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x3b, 0x0a, 0x09, 0x66, 0x74, 0x61, 0x62,
128 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x66, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x64, 0x3b, 0x0a, 0x09,
129 0x69, 0x66, 0x20, 0x28, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2b, 0x2b, 0x20, 0x25, 0x20, 0x31, 0x30,
130 0x30, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e,
131 0x74, 0x66, 0x28, 0x22, 0x2e, 0x22, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x7d, 0x0a, 0x0a, 0x76,
132 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x28, 0x69, 0x6e, 0x74,
133 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x7a,
134 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x29, 0x0a, 0x7b,
135 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x69, 0x3b, 0x0a, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x62,
136 0x75, 0x66, 0x5b, 0x30, 0x5d, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x6d, 0x65, 0x6d, 0x73,
137 0x65, 0x74, 0x28, 0x62, 0x75, 0x66, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x6f,
138 0x66, 0x28, 0x62, 0x75, 0x66, 0x29, 0x29, 0x3b, 0x0a, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28,
139 0x69, 0x3d, 0x30, 0x3b, 0x69, 0x3c, 0x4d, 0x41, 0x58, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x3b,
140 0x69, 0x2b, 0x2b, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x66, 0x74, 0x61,
141 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x3d, 0x3d,
142 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x29, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a,
143 0x09, 0x7d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x69, 0x20, 0x3d, 0x3d, 0x20, 0x4d, 0x41, 0x58,
144 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x29, 0x20, 0x7b, 0x0a, 0x23, 0x69, 0x66, 0x20, 0x31, 0x0a,
145 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x28, 0x25, 0x64, 0x29, 0x20, 0x64,
146 0x6f, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x3a, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20,
147 0x25, 0x64, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20,
148 0x73, 0x69, 0x7a, 0x65, 0x3d, 0x25, 0x64, 0x20, 0x6f, 0x66, 0x73, 0x3d, 0x25, 0x64, 0x5c, 0x6e,
149 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e,
150 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2c, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x2c,
151 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2c, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x29, 0x3b, 0x0a,
152 0x23, 0x65, 0x6e, 0x64, 0x69, 0x66, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x3b,
153 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x6c, 0x73, 0x65, 0x65, 0x6b, 0x28, 0x66, 0x74, 0x61, 0x62, 0x6c,
154 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x66, 0x64, 0x2c, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c,
155 0x20, 0x53, 0x45, 0x45, 0x4b, 0x5f, 0x53, 0x45, 0x54, 0x29, 0x3b, 0x0a, 0x09, 0x69, 0x66, 0x20,
156 0x28, 0x77, 0x72, 0x69, 0x74, 0x65, 0x28, 0x66, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d,
157 0x2e, 0x66, 0x64, 0x2c, 0x20, 0x62, 0x75, 0x66, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x20,
158 0x21, 0x3d, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69,
159 0x6e, 0x74, 0x66, 0x28, 0x22, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65,
160 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x25, 0x64, 0x5c, 0x6e,
161 0x22, 0x2c, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x7d,
162 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x28, 0x69,
163 0x6e, 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x73,
164 0x69, 0x7a, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x29,
165 0x0a, 0x7b, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x69, 0x3b, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x20,
166 0x28, 0x69, 0x3d, 0x30, 0x3b, 0x69, 0x3c, 0x4d, 0x41, 0x58, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53,
167 0x3b, 0x69, 0x2b, 0x2b, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x66, 0x74,
168 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x3d,
169 0x3d, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x29, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b,
170 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x69, 0x20, 0x3d, 0x3d, 0x20, 0x4d, 0x41,
171 0x58, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69,
172 0x6e, 0x74, 0x66, 0x28, 0x22, 0x28, 0x25, 0x64, 0x29, 0x20, 0x64, 0x6f, 0x5f, 0x72, 0x65, 0x61,
173 0x64, 0x3a, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x25, 0x64, 0x20, 0x77, 0x61, 0x73,
174 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x3d, 0x25,
175 0x64, 0x20, 0x6f, 0x66, 0x73, 0x3d, 0x25, 0x64, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09,
176 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e,
177 0x74, 0x2c, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2c,
178 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x29, 0x3b, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75,
179 0x72, 0x6e, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x6c, 0x73, 0x65, 0x65, 0x6b, 0x28, 0x66, 0x74,
180 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x66, 0x64, 0x2c, 0x20, 0x6f, 0x66, 0x66, 0x73,
181 0x65, 0x74, 0x2c, 0x20, 0x53, 0x45, 0x45, 0x4b, 0x5f, 0x53, 0x45, 0x54, 0x29, 0x3b, 0x0a, 0x09,
182 0x72, 0x65, 0x61, 0x64, 0x28, 0x66, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x66,
183 0x64, 0x2c, 0x20, 0x62, 0x75, 0x66, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x7d,
184 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x28,
185 0x69, 0x6e, 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x29, 0x0a, 0x7b, 0x0a, 0x09, 0x69,
186 0x6e, 0x74, 0x20, 0x69, 0x3b, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x69, 0x3d, 0x30, 0x3b,
187 0x69, 0x3c, 0x4d, 0x41, 0x58, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x3b, 0x69, 0x2b, 0x2b, 0x29,
188 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x66, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b,
189 0x69, 0x5d, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x68, 0x61, 0x6e,
190 0x64, 0x6c, 0x65, 0x29, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09,
191 0x69, 0x66, 0x20, 0x28, 0x69, 0x20, 0x3d, 0x3d, 0x20, 0x4d, 0x41, 0x58, 0x5f, 0x46, 0x49, 0x4c,
192 0x45, 0x53, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22,
193 0x28, 0x25, 0x64, 0x29, 0x20, 0x64, 0x6f, 0x5f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x3a, 0x20, 0x68,
194 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x25, 0x64, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x74,
195 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20,
196 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2c, 0x20,
197 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72,
198 0x6e, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x28, 0x66, 0x74, 0x61,
199 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x66, 0x64, 0x29, 0x3b, 0x0a, 0x09, 0x66, 0x74, 0x61,
200 0x62, 0x6c, 0x65, 0x5b, 0x69, 0x5d, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x3d, 0x20,
201 0x30, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x6d, 0x6b,
202 0x64, 0x69, 0x72, 0x28, 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29,
203 0x0a, 0x7b, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x75, 0x70, 0x70, 0x65, 0x72, 0x28, 0x66, 0x6e, 0x61,
204 0x6d, 0x65, 0x29, 0x3b, 0x0a, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x6d, 0x6b, 0x64, 0x69, 0x72,
205 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x30, 0x37, 0x30, 0x30, 0x29, 0x20, 0x21, 0x3d,
206 0x20, 0x30, 0x29, 0x20, 0x7b, 0x0a, 0x23, 0x69, 0x66, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x0a,
207 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x6d, 0x6b, 0x64, 0x69, 0x72, 0x20,
208 0x25, 0x73, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x28, 0x25, 0x73, 0x29, 0x5c, 0x6e,
209 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6e, 0x61,
210 0x6d, 0x65, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x65, 0x72, 0x72,
211 0x6e, 0x6f, 0x29, 0x29, 0x3b, 0x0a, 0x23, 0x65, 0x6e, 0x64, 0x69, 0x66, 0x0a, 0x09, 0x7d, 0x0a,
212 0x7d, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x72, 0x6d, 0x64, 0x69, 0x72,
213 0x28, 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x0a, 0x7b, 0x0a,
214 0x09, 0x73, 0x74, 0x72, 0x75, 0x70, 0x70, 0x65, 0x72, 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29,
215 0x3b, 0x0a, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x72, 0x6d, 0x64, 0x69, 0x72, 0x28, 0x66, 0x6e,
216 0x61, 0x6d, 0x65, 0x29, 0x20, 0x21, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70,
217 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x72, 0x6d, 0x64, 0x69, 0x72, 0x20, 0x25, 0x73, 0x20,
218 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x28, 0x25, 0x73, 0x29, 0x5c, 0x6e, 0x22, 0x2c, 0x20,
219 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c,
220 0x20, 0x73, 0x74, 0x72, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x29,
221 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x7d, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f,
222 0x5f, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x28, 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x6f, 0x6c,
223 0x64, 0x2c, 0x20, 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x6e, 0x65, 0x77, 0x29, 0x0a, 0x7b, 0x0a,
224 0x09, 0x73, 0x74, 0x72, 0x75, 0x70, 0x70, 0x65, 0x72, 0x28, 0x6f, 0x6c, 0x64, 0x29, 0x3b, 0x0a,
225 0x09, 0x73, 0x74, 0x72, 0x75, 0x70, 0x70, 0x65, 0x72, 0x28, 0x6e, 0x65, 0x77, 0x29, 0x3b, 0x0a,
226 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x28, 0x6f, 0x6c, 0x64,
227 0x2c, 0x20, 0x6e, 0x65, 0x77, 0x29, 0x20, 0x21, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x7b, 0x0a, 0x09,
228 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x20,
229 0x25, 0x73, 0x20, 0x25, 0x73, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x28, 0x25, 0x73,
230 0x29, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
231 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x6e, 0x65, 0x77, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x65, 0x72, 0x72,
232 0x6f, 0x72, 0x28, 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x29, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x7d,
233 0x0a, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x28,
234 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74,
235 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x0a, 0x7b, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74,
236 0x20, 0x73, 0x74, 0x61, 0x74, 0x20, 0x73, 0x74, 0x3b, 0x0a, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x75,
237 0x70, 0x70, 0x65, 0x72, 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x3b, 0x0a, 0x0a, 0x09, 0x69,
238 0x66, 0x20, 0x28, 0x73, 0x74, 0x61, 0x74, 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x26,
239 0x73, 0x74, 0x29, 0x20, 0x21, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72,
240 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x28, 0x25, 0x64, 0x29, 0x20, 0x64, 0x6f, 0x5f, 0x73, 0x74,
241 0x61, 0x74, 0x3a, 0x20, 0x25, 0x73, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x3d, 0x25, 0x64, 0x20, 0x25,
242 0x73, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
243 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2c, 0x20, 0x66, 0x6e, 0x61, 0x6d,
244 0x65, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x65, 0x72, 0x72, 0x6f,
245 0x72, 0x28, 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x29, 0x29, 0x3b, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74,
246 0x75, 0x72, 0x6e, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x53, 0x5f, 0x49,
247 0x53, 0x44, 0x49, 0x52, 0x28, 0x73, 0x74, 0x2e, 0x73, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x29,
248 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x3b, 0x0a, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28,
249 0x73, 0x74, 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x21, 0x3d, 0x20, 0x73, 0x69,
250 0x7a, 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22,
251 0x28, 0x25, 0x64, 0x29, 0x20, 0x64, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x3a, 0x20, 0x25, 0x73,
252 0x20, 0x77, 0x72, 0x6f, 0x6e, 0x67, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x25, 0x64, 0x20, 0x25,
253 0x64, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
254 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2c, 0x20, 0x66, 0x6e, 0x61, 0x6d,
255 0x65, 0x2c, 0x20, 0x28, 0x69, 0x6e, 0x74, 0x29, 0x73, 0x74, 0x2e, 0x73, 0x74, 0x5f, 0x73, 0x69,
256 0x7a, 0x65, 0x2c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x7d, 0x0a, 0x7d, 0x0a,
257 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x6f, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x28,
258 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x74,
259 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x0a, 0x7b, 0x0a, 0x09, 0x64, 0x6f, 0x5f, 0x6f, 0x70, 0x65,
260 0x6e, 0x28, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x35, 0x30, 0x30, 0x30, 0x2c, 0x20, 0x73,
261 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0a, 0x09, 0x64, 0x6f, 0x5f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x28,
262 0x35, 0x30, 0x30, 0x30, 0x29, 0x3b, 0x0a, 0x7d, 0x0a
263};
264#endif
265static unsigned char comprbuf[TESTDATA_LEN];
266static unsigned char decomprbuf[TESTDATA_LEN];
267
268int jffs2_decompress(unsigned char comprtype, unsigned char *cdata_in,
269 unsigned char *data_out, uint32_t cdatalen, uint32_t datalen);
270unsigned char jffs2_compress(unsigned char *data_in, unsigned char *cpage_out,
271 uint32_t *datalen, uint32_t *cdatalen);
272
273int init_module(void ) {
274 unsigned char comprtype;
275 uint32_t c, d;
276 int ret;
277
278 printk("Original data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
279 testdata[0],testdata[1],testdata[2],testdata[3],
280 testdata[4],testdata[5],testdata[6],testdata[7],
281 testdata[8],testdata[9],testdata[10],testdata[11],
282 testdata[12],testdata[13],testdata[14],testdata[15]);
283 d = TESTDATA_LEN;
284 c = TESTDATA_LEN;
285 comprtype = jffs2_compress(testdata, comprbuf, &d, &c);
286
287 printk("jffs2_compress used compression type %d. Compressed size %d, uncompressed size %d\n",
288 comprtype, c, d);
289 printk("Compressed data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
290 comprbuf[0],comprbuf[1],comprbuf[2],comprbuf[3],
291 comprbuf[4],comprbuf[5],comprbuf[6],comprbuf[7],
292 comprbuf[8],comprbuf[9],comprbuf[10],comprbuf[11],
293 comprbuf[12],comprbuf[13],comprbuf[14],comprbuf[15]);
294
295 ret = jffs2_decompress(comprtype, comprbuf, decomprbuf, c, d);
296 printk("jffs2_decompress returned %d\n", ret);
297 printk("Decompressed data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
298 decomprbuf[0],decomprbuf[1],decomprbuf[2],decomprbuf[3],
299 decomprbuf[4],decomprbuf[5],decomprbuf[6],decomprbuf[7],
300 decomprbuf[8],decomprbuf[9],decomprbuf[10],decomprbuf[11],
301 decomprbuf[12],decomprbuf[13],decomprbuf[14],decomprbuf[15]);
302 if (memcmp(decomprbuf, testdata, d))
303 printk("Compression and decompression corrupted data\n");
304 else
305 printk("Compression good for %d bytes\n", d);
306 return 1;
307}
diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c
index 4189e4a36050..3a32c64ed497 100644
--- a/fs/jffs2/debug.c
+++ b/fs/jffs2/debug.c
@@ -1,15 +1,14 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by David Woodhouse <dwmw2@infradead.org> 6 * Created by David Woodhouse <dwmw2@infradead.org>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: debug.c,v 1.12 2005/11/07 11:14:39 gleixner Exp $
11 *
12 */ 10 */
11
13#include <linux/kernel.h> 12#include <linux/kernel.h>
14#include <linux/types.h> 13#include <linux/types.h>
15#include <linux/pagemap.h> 14#include <linux/pagemap.h>
diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h
index f89c85d5a3f8..2a49f2c51a9f 100644
--- a/fs/jffs2/debug.h
+++ b/fs/jffs2/debug.h
@@ -1,15 +1,14 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by David Woodhouse <dwmw2@infradead.org> 6 * Created by David Woodhouse <dwmw2@infradead.org>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: debug.h,v 1.21 2005/11/07 11:14:39 gleixner Exp $
11 *
12 */ 10 */
11
13#ifndef _JFFS2_DEBUG_H_ 12#ifndef _JFFS2_DEBUG_H_
14#define _JFFS2_DEBUG_H_ 13#define _JFFS2_DEBUG_H_
15 14
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 9fa2e27f0641..c1dfca310dd6 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -1,14 +1,12 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by David Woodhouse <dwmw2@infradead.org> 6 * Created by David Woodhouse <dwmw2@infradead.org>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: dir.c,v 1.90 2005/11/07 11:14:39 gleixner Exp $
11 *
12 */ 10 */
13 11
14#include <linux/kernel.h> 12#include <linux/kernel.h>
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index ad0121088dde..66e7c2f1e644 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -1,14 +1,12 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by David Woodhouse <dwmw2@infradead.org> 6 * Created by David Woodhouse <dwmw2@infradead.org>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: erase.c,v 1.85 2005/09/20 14:53:15 dedekind Exp $
11 *
12 */ 10 */
13 11
14#include <linux/kernel.h> 12#include <linux/kernel.h>
@@ -333,7 +331,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
333 331
334 *bad_offset = ofs; 332 *bad_offset = ofs;
335 333
336 ret = jffs2_flash_read(c, ofs, readlen, &retlen, ebuf); 334 ret = c->mtd->read(c->mtd, ofs, readlen, &retlen, ebuf);
337 if (ret) { 335 if (ret) {
338 printk(KERN_WARNING "Read of newly-erased block at 0x%08x failed: %d. Putting on bad_list\n", ofs, ret); 336 printk(KERN_WARNING "Read of newly-erased block at 0x%08x failed: %d. Putting on bad_list\n", ofs, ret);
339 goto fail; 337 goto fail;
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index e82eeaf7590d..99871279a1ed 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -1,14 +1,12 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by David Woodhouse <dwmw2@infradead.org> 6 * Created by David Woodhouse <dwmw2@infradead.org>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: file.c,v 1.104 2005/10/18 23:29:35 tpoynor Exp $
11 *
12 */ 10 */
13 11
14#include <linux/kernel.h> 12#include <linux/kernel.h>
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 8a649f602767..1d3b7a9fc828 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -1,14 +1,12 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by David Woodhouse <dwmw2@infradead.org> 6 * Created by David Woodhouse <dwmw2@infradead.org>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: fs.c,v 1.66 2005/09/27 13:17:29 dedekind Exp $
11 *
12 */ 10 */
13 11
14#include <linux/capability.h> 12#include <linux/capability.h>
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index 3a3cf225981f..2d99e06ab223 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -1,14 +1,12 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by David Woodhouse <dwmw2@infradead.org> 6 * Created by David Woodhouse <dwmw2@infradead.org>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: gc.c,v 1.155 2005/11/07 11:14:39 gleixner Exp $
11 *
12 */ 10 */
13 11
14#include <linux/kernel.h> 12#include <linux/kernel.h>
@@ -144,7 +142,8 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
144 c->unchecked_size); 142 c->unchecked_size);
145 jffs2_dbg_dump_block_lists_nolock(c); 143 jffs2_dbg_dump_block_lists_nolock(c);
146 spin_unlock(&c->erase_completion_lock); 144 spin_unlock(&c->erase_completion_lock);
147 BUG(); 145 up(&c->alloc_sem);
146 return -ENOSPC;
148 } 147 }
149 148
150 spin_unlock(&c->erase_completion_lock); 149 spin_unlock(&c->erase_completion_lock);
diff --git a/fs/jffs2/ioctl.c b/fs/jffs2/ioctl.c
index 69099835de1c..f4d525b0ea53 100644
--- a/fs/jffs2/ioctl.c
+++ b/fs/jffs2/ioctl.c
@@ -1,14 +1,12 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by David Woodhouse <dwmw2@infradead.org> 6 * Created by David Woodhouse <dwmw2@infradead.org>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: ioctl.c,v 1.10 2005/11/07 11:14:40 gleixner Exp $
11 *
12 */ 10 */
13 11
14#include <linux/fs.h> 12#include <linux/fs.h>
diff --git a/fs/jffs2/jffs2_fs_i.h b/fs/jffs2/jffs2_fs_i.h
index 3a566077ac95..0b78fdc9773b 100644
--- a/fs/jffs2/jffs2_fs_i.h
+++ b/fs/jffs2/jffs2_fs_i.h
@@ -1,4 +1,13 @@
1/* $Id: jffs2_fs_i.h,v 1.19 2005/11/07 11:14:52 gleixner Exp $ */ 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright © 2001-2007 Red Hat, Inc.
5 *
6 * Created by David Woodhouse <dwmw2@infradead.org>
7 *
8 * For licensing information, see the file 'LICENCE' in this directory.
9 *
10 */
2 11
3#ifndef _JFFS2_FS_I 12#ifndef _JFFS2_FS_I
4#define _JFFS2_FS_I 13#define _JFFS2_FS_I
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
index ea88f69af130..b13298a824ed 100644
--- a/fs/jffs2/jffs2_fs_sb.h
+++ b/fs/jffs2/jffs2_fs_sb.h
@@ -1,4 +1,13 @@
1/* $Id: jffs2_fs_sb.h,v 1.54 2005/09/21 13:37:34 dedekind Exp $ */ 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright © 2001-2007 Red Hat, Inc.
5 *
6 * Created by David Woodhouse <dwmw2@infradead.org>
7 *
8 * For licensing information, see the file 'LICENCE' in this directory.
9 *
10 */
2 11
3#ifndef _JFFS2_FS_SB 12#ifndef _JFFS2_FS_SB
4#define _JFFS2_FS_SB 13#define _JFFS2_FS_SB
diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c
index 83f9881ec4cc..35c1a5e30ba1 100644
--- a/fs/jffs2/malloc.c
+++ b/fs/jffs2/malloc.c
@@ -1,14 +1,12 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by David Woodhouse <dwmw2@infradead.org> 6 * Created by David Woodhouse <dwmw2@infradead.org>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: malloc.c,v 1.31 2005/11/07 11:14:40 gleixner Exp $
11 *
12 */ 10 */
13 11
14#include <linux/kernel.h> 12#include <linux/kernel.h>
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
index 5a6b4d64206c..4bf86088b3ae 100644
--- a/fs/jffs2/nodelist.c
+++ b/fs/jffs2/nodelist.c
@@ -1,14 +1,12 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by David Woodhouse <dwmw2@infradead.org> 6 * Created by David Woodhouse <dwmw2@infradead.org>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: nodelist.c,v 1.115 2005/11/07 11:14:40 gleixner Exp $
11 *
12 */ 10 */
13 11
14#include <linux/kernel.h> 12#include <linux/kernel.h>
@@ -54,7 +52,7 @@ void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new
54 *prev = new; 52 *prev = new;
55} 53}
56 54
57void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint32_t size) 55uint32_t jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint32_t size)
58{ 56{
59 struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size); 57 struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size);
60 58
@@ -76,18 +74,24 @@ void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint
76 } 74 }
77 75
78 if (size == 0) 76 if (size == 0)
79 return; 77 return 0;
80 78
81 /*
82 * If the last fragment starts at the RAM page boundary, it is
83 * REF_PRISTINE irrespective of its size.
84 */
85 frag = frag_last(list); 79 frag = frag_last(list);
80
81 /* Sanity check for truncation to longer than we started with... */
82 if (!frag)
83 return 0;
84 if (frag->ofs + frag->size < size)
85 return frag->ofs + frag->size;
86
87 /* If the last fragment starts at the RAM page boundary, it is
88 * REF_PRISTINE irrespective of its size. */
86 if (frag->node && (frag->ofs & (PAGE_CACHE_SIZE - 1)) == 0) { 89 if (frag->node && (frag->ofs & (PAGE_CACHE_SIZE - 1)) == 0) {
87 dbg_fragtree2("marking the last fragment 0x%08x-0x%08x REF_PRISTINE.\n", 90 dbg_fragtree2("marking the last fragment 0x%08x-0x%08x REF_PRISTINE.\n",
88 frag->ofs, frag->ofs + frag->size); 91 frag->ofs, frag->ofs + frag->size);
89 frag->node->raw->flash_offset = ref_offset(frag->node->raw) | REF_PRISTINE; 92 frag->node->raw->flash_offset = ref_offset(frag->node->raw) | REF_PRISTINE;
90 } 93 }
94 return size;
91} 95}
92 96
93static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, 97static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c,
@@ -397,466 +401,6 @@ int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_in
397 return 0; 401 return 0;
398} 402}
399 403
400/*
401 * Check the data CRC of the node.
402 *
403 * Returns: 0 if the data CRC is correct;
404 * 1 - if incorrect;
405 * error code if an error occured.
406 */
407static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn)
408{
409 struct jffs2_raw_node_ref *ref = tn->fn->raw;
410 int err = 0, pointed = 0;
411 struct jffs2_eraseblock *jeb;
412 unsigned char *buffer;
413 uint32_t crc, ofs, len;
414 size_t retlen;
415
416 BUG_ON(tn->csize == 0);
417
418 if (!jffs2_is_writebuffered(c))
419 goto adj_acc;
420
421 /* Calculate how many bytes were already checked */
422 ofs = ref_offset(ref) + sizeof(struct jffs2_raw_inode);
423 len = ofs % c->wbuf_pagesize;
424 if (likely(len))
425 len = c->wbuf_pagesize - len;
426
427 if (len >= tn->csize) {
428 dbg_readinode("no need to check node at %#08x, data length %u, data starts at %#08x - it has already been checked.\n",
429 ref_offset(ref), tn->csize, ofs);
430 goto adj_acc;
431 }
432
433 ofs += len;
434 len = tn->csize - len;
435
436 dbg_readinode("check node at %#08x, data length %u, partial CRC %#08x, correct CRC %#08x, data starts at %#08x, start checking from %#08x - %u bytes.\n",
437 ref_offset(ref), tn->csize, tn->partial_crc, tn->data_crc, ofs - len, ofs, len);
438
439#ifndef __ECOS
440 /* TODO: instead, incapsulate point() stuff to jffs2_flash_read(),
441 * adding and jffs2_flash_read_end() interface. */
442 if (c->mtd->point) {
443 err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer);
444 if (!err && retlen < tn->csize) {
445 JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize);
446 c->mtd->unpoint(c->mtd, buffer, ofs, len);
447 } else if (err)
448 JFFS2_WARNING("MTD point failed: error code %d.\n", err);
449 else
450 pointed = 1; /* succefully pointed to device */
451 }
452#endif
453
454 if (!pointed) {
455 buffer = kmalloc(len, GFP_KERNEL);
456 if (unlikely(!buffer))
457 return -ENOMEM;
458
459 /* TODO: this is very frequent pattern, make it a separate
460 * routine */
461 err = jffs2_flash_read(c, ofs, len, &retlen, buffer);
462 if (err) {
463 JFFS2_ERROR("can not read %d bytes from 0x%08x, error code: %d.\n", len, ofs, err);
464 goto free_out;
465 }
466
467 if (retlen != len) {
468 JFFS2_ERROR("short read at %#08x: %zd instead of %d.\n", ofs, retlen, len);
469 err = -EIO;
470 goto free_out;
471 }
472 }
473
474 /* Continue calculating CRC */
475 crc = crc32(tn->partial_crc, buffer, len);
476 if(!pointed)
477 kfree(buffer);
478#ifndef __ECOS
479 else
480 c->mtd->unpoint(c->mtd, buffer, ofs, len);
481#endif
482
483 if (crc != tn->data_crc) {
484 JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n",
485 ofs, tn->data_crc, crc);
486 return 1;
487 }
488
489adj_acc:
490 jeb = &c->blocks[ref->flash_offset / c->sector_size];
491 len = ref_totlen(c, jeb, ref);
492
493 /*
494 * Mark the node as having been checked and fix the
495 * accounting accordingly.
496 */
497 spin_lock(&c->erase_completion_lock);
498 jeb->used_size += len;
499 jeb->unchecked_size -= len;
500 c->used_size += len;
501 c->unchecked_size -= len;
502 spin_unlock(&c->erase_completion_lock);
503
504 return 0;
505
506free_out:
507 if(!pointed)
508 kfree(buffer);
509#ifndef __ECOS
510 else
511 c->mtd->unpoint(c->mtd, buffer, ofs, len);
512#endif
513 return err;
514}
515
516/*
517 * Helper function for jffs2_add_older_frag_to_fragtree().
518 *
519 * Checks the node if we are in the checking stage.
520 */
521static int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn)
522{
523 int ret;
524
525 BUG_ON(ref_obsolete(tn->fn->raw));
526
527 /* We only check the data CRC of unchecked nodes */
528 if (ref_flags(tn->fn->raw) != REF_UNCHECKED)
529 return 0;
530
531 dbg_fragtree2("check node %#04x-%#04x, phys offs %#08x.\n",
532 tn->fn->ofs, tn->fn->ofs + tn->fn->size, ref_offset(tn->fn->raw));
533
534 ret = check_node_data(c, tn);
535 if (unlikely(ret < 0)) {
536 JFFS2_ERROR("check_node_data() returned error: %d.\n",
537 ret);
538 } else if (unlikely(ret > 0)) {
539 dbg_fragtree2("CRC error, mark it obsolete.\n");
540 jffs2_mark_node_obsolete(c, tn->fn->raw);
541 }
542
543 return ret;
544}
545
546/*
547 * Helper function for jffs2_add_older_frag_to_fragtree().
548 *
549 * Called when the new fragment that is being inserted
550 * splits a hole fragment.
551 */
552static int split_hole(struct jffs2_sb_info *c, struct rb_root *root,
553 struct jffs2_node_frag *newfrag, struct jffs2_node_frag *hole)
554{
555 dbg_fragtree2("fragment %#04x-%#04x splits the hole %#04x-%#04x\n",
556 newfrag->ofs, newfrag->ofs + newfrag->size, hole->ofs, hole->ofs + hole->size);
557
558 if (hole->ofs == newfrag->ofs) {
559 /*
560 * Well, the new fragment actually starts at the same offset as
561 * the hole.
562 */
563 if (hole->ofs + hole->size > newfrag->ofs + newfrag->size) {
564 /*
565 * We replace the overlapped left part of the hole by
566 * the new node.
567 */
568
569 dbg_fragtree2("insert fragment %#04x-%#04x and cut the left part of the hole\n",
570 newfrag->ofs, newfrag->ofs + newfrag->size);
571 rb_replace_node(&hole->rb, &newfrag->rb, root);
572
573 hole->ofs += newfrag->size;
574 hole->size -= newfrag->size;
575
576 /*
577 * We know that 'hole' should be the right hand
578 * fragment.
579 */
580 jffs2_fragtree_insert(hole, newfrag);
581 rb_insert_color(&hole->rb, root);
582 } else {
583 /*
584 * Ah, the new fragment is of the same size as the hole.
585 * Relace the hole by it.
586 */
587 dbg_fragtree2("insert fragment %#04x-%#04x and overwrite hole\n",
588 newfrag->ofs, newfrag->ofs + newfrag->size);
589 rb_replace_node(&hole->rb, &newfrag->rb, root);
590 jffs2_free_node_frag(hole);
591 }
592 } else {
593 /* The new fragment lefts some hole space at the left */
594
595 struct jffs2_node_frag * newfrag2 = NULL;
596
597 if (hole->ofs + hole->size > newfrag->ofs + newfrag->size) {
598 /* The new frag also lefts some space at the right */
599 newfrag2 = new_fragment(NULL, newfrag->ofs +
600 newfrag->size, hole->ofs + hole->size
601 - newfrag->ofs - newfrag->size);
602 if (unlikely(!newfrag2)) {
603 jffs2_free_node_frag(newfrag);
604 return -ENOMEM;
605 }
606 }
607
608 hole->size = newfrag->ofs - hole->ofs;
609 dbg_fragtree2("left the hole %#04x-%#04x at the left and inserd fragment %#04x-%#04x\n",
610 hole->ofs, hole->ofs + hole->size, newfrag->ofs, newfrag->ofs + newfrag->size);
611
612 jffs2_fragtree_insert(newfrag, hole);
613 rb_insert_color(&newfrag->rb, root);
614
615 if (newfrag2) {
616 dbg_fragtree2("left the hole %#04x-%#04x at the right\n",
617 newfrag2->ofs, newfrag2->ofs + newfrag2->size);
618 jffs2_fragtree_insert(newfrag2, newfrag);
619 rb_insert_color(&newfrag2->rb, root);
620 }
621 }
622
623 return 0;
624}
625
626/*
627 * This function is used when we build inode. It expects the nodes are passed
628 * in the decreasing version order. The whole point of this is to improve the
629 * inodes checking on NAND: we check the nodes' data CRC only when they are not
630 * obsoleted. Previously, add_frag_to_fragtree() function was used and
631 * nodes were passed to it in the increasing version ordes and CRCs of all
632 * nodes were checked.
633 *
634 * Note: tn->fn->size shouldn't be zero.
635 *
636 * Returns 0 if the node was inserted
637 * 1 if it wasn't inserted (since it is obsolete)
638 * < 0 an if error occured
639 */
640int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
641 struct jffs2_tmp_dnode_info *tn)
642{
643 struct jffs2_node_frag *this, *newfrag;
644 uint32_t lastend;
645 struct jffs2_full_dnode *fn = tn->fn;
646 struct rb_root *root = &f->fragtree;
647 uint32_t fn_size = fn->size, fn_ofs = fn->ofs;
648 int err, checked = 0;
649 int ref_flag;
650
651 dbg_fragtree("insert fragment %#04x-%#04x, ver %u\n", fn_ofs, fn_ofs + fn_size, tn->version);
652
653 /* Skip all the nodes which are completed before this one starts */
654 this = jffs2_lookup_node_frag(root, fn_ofs);
655 if (this)
656 dbg_fragtree2("'this' found %#04x-%#04x (%s)\n", this->ofs, this->ofs + this->size, this->node ? "data" : "hole");
657
658 if (this)
659 lastend = this->ofs + this->size;
660 else
661 lastend = 0;
662
663 /* Detect the preliminary type of node */
664 if (fn->size >= PAGE_CACHE_SIZE)
665 ref_flag = REF_PRISTINE;
666 else
667 ref_flag = REF_NORMAL;
668
669 /* See if we ran off the end of the root */
670 if (lastend <= fn_ofs) {
671 /* We did */
672
673 /*
674 * We are going to insert the new node into the
675 * fragment tree, so check it.
676 */
677 err = check_node(c, f, tn);
678 if (err != 0)
679 return err;
680
681 fn->frags = 1;
682
683 newfrag = new_fragment(fn, fn_ofs, fn_size);
684 if (unlikely(!newfrag))
685 return -ENOMEM;
686
687 err = no_overlapping_node(c, root, newfrag, this, lastend);
688 if (unlikely(err != 0)) {
689 jffs2_free_node_frag(newfrag);
690 return err;
691 }
692
693 goto out_ok;
694 }
695
696 fn->frags = 0;
697
698 while (1) {
699 /*
700 * Here we have:
701 * fn_ofs < this->ofs + this->size && fn_ofs >= this->ofs.
702 *
703 * Remember, 'this' has higher version, any non-hole node
704 * which is already in the fragtree is newer then the newly
705 * inserted.
706 */
707 if (!this->node) {
708 /*
709 * 'this' is the hole fragment, so at least the
710 * beginning of the new fragment is valid.
711 */
712
713 /*
714 * We are going to insert the new node into the
715 * fragment tree, so check it.
716 */
717 if (!checked) {
718 err = check_node(c, f, tn);
719 if (unlikely(err != 0))
720 return err;
721 checked = 1;
722 }
723
724 if (this->ofs + this->size >= fn_ofs + fn_size) {
725 /* We split the hole on two parts */
726
727 fn->frags += 1;
728 newfrag = new_fragment(fn, fn_ofs, fn_size);
729 if (unlikely(!newfrag))
730 return -ENOMEM;
731
732 err = split_hole(c, root, newfrag, this);
733 if (unlikely(err))
734 return err;
735 goto out_ok;
736 }
737
738 /*
739 * The beginning of the new fragment is valid since it
740 * overlaps the hole node.
741 */
742
743 ref_flag = REF_NORMAL;
744
745 fn->frags += 1;
746 newfrag = new_fragment(fn, fn_ofs,
747 this->ofs + this->size - fn_ofs);
748 if (unlikely(!newfrag))
749 return -ENOMEM;
750
751 if (fn_ofs == this->ofs) {
752 /*
753 * The new node starts at the same offset as
754 * the hole and supersieds the hole.
755 */
756 dbg_fragtree2("add the new fragment instead of hole %#04x-%#04x, refcnt %d\n",
757 fn_ofs, fn_ofs + this->ofs + this->size - fn_ofs, fn->frags);
758
759 rb_replace_node(&this->rb, &newfrag->rb, root);
760 jffs2_free_node_frag(this);
761 } else {
762 /*
763 * The hole becomes shorter as its right part
764 * is supersieded by the new fragment.
765 */
766 dbg_fragtree2("reduce size of hole %#04x-%#04x to %#04x-%#04x\n",
767 this->ofs, this->ofs + this->size, this->ofs, this->ofs + this->size - newfrag->size);
768
769 dbg_fragtree2("add new fragment %#04x-%#04x, refcnt %d\n", fn_ofs,
770 fn_ofs + this->ofs + this->size - fn_ofs, fn->frags);
771
772 this->size -= newfrag->size;
773 jffs2_fragtree_insert(newfrag, this);
774 rb_insert_color(&newfrag->rb, root);
775 }
776
777 fn_ofs += newfrag->size;
778 fn_size -= newfrag->size;
779 this = rb_entry(rb_next(&newfrag->rb),
780 struct jffs2_node_frag, rb);
781
782 dbg_fragtree2("switch to the next 'this' fragment: %#04x-%#04x %s\n",
783 this->ofs, this->ofs + this->size, this->node ? "(data)" : "(hole)");
784 }
785
786 /*
787 * 'This' node is not the hole so it obsoletes the new fragment
788 * either fully or partially.
789 */
790 if (this->ofs + this->size >= fn_ofs + fn_size) {
791 /* The new node is obsolete, drop it */
792 if (fn->frags == 0) {
793 dbg_fragtree2("%#04x-%#04x is obsolete, mark it obsolete\n", fn_ofs, fn_ofs + fn_size);
794 ref_flag = REF_OBSOLETE;
795 }
796 goto out_ok;
797 } else {
798 struct jffs2_node_frag *new_this;
799
800 /* 'This' node obsoletes the beginning of the new node */
801 dbg_fragtree2("the beginning %#04x-%#04x is obsolete\n", fn_ofs, this->ofs + this->size);
802
803 ref_flag = REF_NORMAL;
804
805 fn_size -= this->ofs + this->size - fn_ofs;
806 fn_ofs = this->ofs + this->size;
807 dbg_fragtree2("now considering %#04x-%#04x\n", fn_ofs, fn_ofs + fn_size);
808
809 new_this = rb_entry(rb_next(&this->rb), struct jffs2_node_frag, rb);
810 if (!new_this) {
811 /*
812 * There is no next fragment. Add the rest of
813 * the new node as the right-hand child.
814 */
815 if (!checked) {
816 err = check_node(c, f, tn);
817 if (unlikely(err != 0))
818 return err;
819 checked = 1;
820 }
821
822 fn->frags += 1;
823 newfrag = new_fragment(fn, fn_ofs, fn_size);
824 if (unlikely(!newfrag))
825 return -ENOMEM;
826
827 dbg_fragtree2("there are no more fragments, insert %#04x-%#04x\n",
828 newfrag->ofs, newfrag->ofs + newfrag->size);
829 rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right);
830 rb_insert_color(&newfrag->rb, root);
831 goto out_ok;
832 } else {
833 this = new_this;
834 dbg_fragtree2("switch to the next 'this' fragment: %#04x-%#04x %s\n",
835 this->ofs, this->ofs + this->size, this->node ? "(data)" : "(hole)");
836 }
837 }
838 }
839
840out_ok:
841 BUG_ON(fn->size < PAGE_CACHE_SIZE && ref_flag == REF_PRISTINE);
842
843 if (ref_flag == REF_OBSOLETE) {
844 dbg_fragtree2("the node is obsolete now\n");
845 /* jffs2_mark_node_obsolete() will adjust space accounting */
846 jffs2_mark_node_obsolete(c, fn->raw);
847 return 1;
848 }
849
850 dbg_fragtree2("the node is \"%s\" now\n", ref_flag == REF_NORMAL ? "REF_NORMAL" : "REF_PRISTINE");
851
852 /* Space accounting was adjusted at check_node_data() */
853 spin_lock(&c->erase_completion_lock);
854 fn->raw->flash_offset = ref_offset(fn->raw) | ref_flag;
855 spin_unlock(&c->erase_completion_lock);
856
857 return 0;
858}
859
860void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, int state) 404void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, int state)
861{ 405{
862 spin_lock(&c->inocache_lock); 406 spin_lock(&c->inocache_lock);
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index 4178b4b55948..25126a062cae 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -1,14 +1,12 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by David Woodhouse <dwmw2@infradead.org> 6 * Created by David Woodhouse <dwmw2@infradead.org>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: nodelist.h,v 1.140 2005/09/07 08:34:54 havasi Exp $
11 *
12 */ 10 */
13 11
14#ifndef __JFFS2_NODELIST_H__ 12#ifndef __JFFS2_NODELIST_H__
@@ -40,6 +38,9 @@
40#define cpu_to_je32(x) ((jint32_t){x}) 38#define cpu_to_je32(x) ((jint32_t){x})
41#define cpu_to_jemode(x) ((jmode_t){os_to_jffs2_mode(x)}) 39#define cpu_to_jemode(x) ((jmode_t){os_to_jffs2_mode(x)})
42 40
41#define constant_cpu_to_je16(x) ((jint16_t){x})
42#define constant_cpu_to_je32(x) ((jint32_t){x})
43
43#define je16_to_cpu(x) ((x).v16) 44#define je16_to_cpu(x) ((x).v16)
44#define je32_to_cpu(x) ((x).v32) 45#define je32_to_cpu(x) ((x).v32)
45#define jemode_to_cpu(x) (jffs2_to_os_mode((x).m)) 46#define jemode_to_cpu(x) (jffs2_to_os_mode((x).m))
@@ -48,6 +49,9 @@
48#define cpu_to_je32(x) ((jint32_t){cpu_to_be32(x)}) 49#define cpu_to_je32(x) ((jint32_t){cpu_to_be32(x)})
49#define cpu_to_jemode(x) ((jmode_t){cpu_to_be32(os_to_jffs2_mode(x))}) 50#define cpu_to_jemode(x) ((jmode_t){cpu_to_be32(os_to_jffs2_mode(x))})
50 51
52#define constant_cpu_to_je16(x) ((jint16_t){__constant_cpu_to_be16(x)})
53#define constant_cpu_to_je32(x) ((jint32_t){__constant_cpu_to_be32(x)})
54
51#define je16_to_cpu(x) (be16_to_cpu(x.v16)) 55#define je16_to_cpu(x) (be16_to_cpu(x.v16))
52#define je32_to_cpu(x) (be32_to_cpu(x.v32)) 56#define je32_to_cpu(x) (be32_to_cpu(x.v32))
53#define jemode_to_cpu(x) (be32_to_cpu(jffs2_to_os_mode((x).m))) 57#define jemode_to_cpu(x) (be32_to_cpu(jffs2_to_os_mode((x).m)))
@@ -56,6 +60,9 @@
56#define cpu_to_je32(x) ((jint32_t){cpu_to_le32(x)}) 60#define cpu_to_je32(x) ((jint32_t){cpu_to_le32(x)})
57#define cpu_to_jemode(x) ((jmode_t){cpu_to_le32(os_to_jffs2_mode(x))}) 61#define cpu_to_jemode(x) ((jmode_t){cpu_to_le32(os_to_jffs2_mode(x))})
58 62
63#define constant_cpu_to_je16(x) ((jint16_t){__constant_cpu_to_le16(x)})
64#define constant_cpu_to_je32(x) ((jint32_t){__constant_cpu_to_le32(x)})
65
59#define je16_to_cpu(x) (le16_to_cpu(x.v16)) 66#define je16_to_cpu(x) (le16_to_cpu(x.v16))
60#define je32_to_cpu(x) (le32_to_cpu(x.v32)) 67#define je32_to_cpu(x) (le32_to_cpu(x.v32))
61#define jemode_to_cpu(x) (le32_to_cpu(jffs2_to_os_mode((x).m))) 68#define jemode_to_cpu(x) (le32_to_cpu(jffs2_to_os_mode((x).m)))
@@ -216,7 +223,20 @@ struct jffs2_tmp_dnode_info
216 uint32_t version; 223 uint32_t version;
217 uint32_t data_crc; 224 uint32_t data_crc;
218 uint32_t partial_crc; 225 uint32_t partial_crc;
219 uint32_t csize; 226 uint16_t csize;
227 uint16_t overlapped;
228};
229
230/* Temporary data structure used during readinode. */
231struct jffs2_readinode_info
232{
233 struct rb_root tn_root;
234 struct jffs2_tmp_dnode_info *mdata_tn;
235 uint32_t highest_version;
236 uint32_t latest_mctime;
237 uint32_t mctime_ver;
238 struct jffs2_full_dirent *fds;
239 struct jffs2_raw_node_ref *latest_ref;
220}; 240};
221 241
222struct jffs2_full_dirent 242struct jffs2_full_dirent
@@ -319,6 +339,15 @@ static inline struct jffs2_node_frag *frag_last(struct rb_root *root)
319#define frag_right(frag) rb_entry((frag)->rb.rb_right, struct jffs2_node_frag, rb) 339#define frag_right(frag) rb_entry((frag)->rb.rb_right, struct jffs2_node_frag, rb)
320#define frag_erase(frag, list) rb_erase(&frag->rb, list); 340#define frag_erase(frag, list) rb_erase(&frag->rb, list);
321 341
342#define tn_next(tn) rb_entry(rb_next(&(tn)->rb), struct jffs2_tmp_dnode_info, rb)
343#define tn_prev(tn) rb_entry(rb_prev(&(tn)->rb), struct jffs2_tmp_dnode_info, rb)
344#define tn_parent(tn) rb_entry(rb_parent(&(tn)->rb), struct jffs2_tmp_dnode_info, rb)
345#define tn_left(tn) rb_entry((tn)->rb.rb_left, struct jffs2_tmp_dnode_info, rb)
346#define tn_right(tn) rb_entry((tn)->rb.rb_right, struct jffs2_tmp_dnode_info, rb)
347#define tn_erase(tn, list) rb_erase(&tn->rb, list);
348#define tn_last(list) rb_entry(rb_last(list), struct jffs2_tmp_dnode_info, rb)
349#define tn_first(list) rb_entry(rb_first(list), struct jffs2_tmp_dnode_info, rb)
350
322/* nodelist.c */ 351/* nodelist.c */
323void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list); 352void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list);
324void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, int state); 353void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, int state);
@@ -333,8 +362,7 @@ struct rb_node *rb_next(struct rb_node *);
333struct rb_node *rb_prev(struct rb_node *); 362struct rb_node *rb_prev(struct rb_node *);
334void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root); 363void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root);
335int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); 364int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn);
336void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); 365uint32_t jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size);
337int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn);
338struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c, 366struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c,
339 struct jffs2_eraseblock *jeb, 367 struct jffs2_eraseblock *jeb,
340 uint32_t ofs, uint32_t len, 368 uint32_t ofs, uint32_t len,
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
index d88376992ed9..dbc908ad622b 100644
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -1,14 +1,12 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by David Woodhouse <dwmw2@infradead.org> 6 * Created by David Woodhouse <dwmw2@infradead.org>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: nodemgmt.c,v 1.127 2005/09/20 15:49:12 dedekind Exp $
11 *
12 */ 10 */
13 11
14#include <linux/kernel.h> 12#include <linux/kernel.h>
@@ -172,6 +170,11 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
172static void jffs2_close_nextblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) 170static void jffs2_close_nextblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
173{ 171{
174 172
173 if (c->nextblock == NULL) {
174 D1(printk(KERN_DEBUG "jffs2_close_nextblock: Erase block at 0x%08x has already been placed in a list\n",
175 jeb->offset));
176 return;
177 }
175 /* Check, if we have a dirty block now, or if it was dirty already */ 178 /* Check, if we have a dirty block now, or if it was dirty already */
176 if (ISDIRTY (jeb->wasted_size + jeb->dirty_size)) { 179 if (ISDIRTY (jeb->wasted_size + jeb->dirty_size)) {
177 c->dirty_size += jeb->wasted_size; 180 c->dirty_size += jeb->wasted_size;
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index 8d92e45168ca..80daea96bbc2 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -1,14 +1,12 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2002-2003 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by David Woodhouse <dwmw2@infradead.org> 6 * Created by David Woodhouse <dwmw2@infradead.org>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: os-linux.h,v 1.64 2005/09/30 13:59:13 dedekind Exp $
11 *
12 */ 10 */
13 11
14#ifndef __JFFS2_OS_LINUX_H__ 12#ifndef __JFFS2_OS_LINUX_H__
diff --git a/fs/jffs2/pushpull.h b/fs/jffs2/pushpull.h
deleted file mode 100644
index c0c2a9158dff..000000000000
--- a/fs/jffs2/pushpull.h
+++ /dev/null
@@ -1,72 +0,0 @@
1/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright (C) 2001, 2002 Red Hat, Inc.
5 *
6 * Created by David Woodhouse <dwmw2@infradead.org>
7 *
8 * For licensing information, see the file 'LICENCE' in this directory.
9 *
10 * $Id: pushpull.h,v 1.10 2004/11/16 20:36:11 dwmw2 Exp $
11 *
12 */
13
14#ifndef __PUSHPULL_H__
15#define __PUSHPULL_H__
16
17#include <linux/errno.h>
18
19struct pushpull {
20 unsigned char *buf;
21 unsigned int buflen;
22 unsigned int ofs;
23 unsigned int reserve;
24};
25
26
27static inline void init_pushpull(struct pushpull *pp, char *buf, unsigned buflen, unsigned ofs, unsigned reserve)
28{
29 pp->buf = buf;
30 pp->buflen = buflen;
31 pp->ofs = ofs;
32 pp->reserve = reserve;
33}
34
35static inline int pushbit(struct pushpull *pp, int bit, int use_reserved)
36{
37 if (pp->ofs >= pp->buflen - (use_reserved?0:pp->reserve)) {
38 return -ENOSPC;
39 }
40
41 if (bit) {
42 pp->buf[pp->ofs >> 3] |= (1<<(7-(pp->ofs &7)));
43 }
44 else {
45 pp->buf[pp->ofs >> 3] &= ~(1<<(7-(pp->ofs &7)));
46 }
47 pp->ofs++;
48
49 return 0;
50}
51
52static inline int pushedbits(struct pushpull *pp)
53{
54 return pp->ofs;
55}
56
57static inline int pullbit(struct pushpull *pp)
58{
59 int bit;
60
61 bit = (pp->buf[pp->ofs >> 3] >> (7-(pp->ofs & 7))) & 1;
62
63 pp->ofs++;
64 return bit;
65}
66
67static inline int pulledbits(struct pushpull *pp)
68{
69 return pp->ofs;
70}
71
72#endif /* __PUSHPULL_H__ */
diff --git a/fs/jffs2/read.c b/fs/jffs2/read.c
index f3b86da833ba..cfe05c1966a5 100644
--- a/fs/jffs2/read.c
+++ b/fs/jffs2/read.c
@@ -1,14 +1,12 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by David Woodhouse <dwmw2@infradead.org> 6 * Created by David Woodhouse <dwmw2@infradead.org>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: read.c,v 1.42 2005/11/07 11:14:41 gleixner Exp $
11 *
12 */ 10 */
13 11
14#include <linux/kernel.h> 12#include <linux/kernel.h>
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 717a48cf7df2..6aff38930b50 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -1,14 +1,12 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by David Woodhouse <dwmw2@infradead.org> 6 * Created by David Woodhouse <dwmw2@infradead.org>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: readinode.c,v 1.143 2005/11/07 11:14:41 gleixner Exp $
11 *
12 */ 10 */
13 11
14#include <linux/kernel.h> 12#include <linux/kernel.h>
@@ -22,30 +20,510 @@
22#include "nodelist.h" 20#include "nodelist.h"
23 21
24/* 22/*
25 * Put a new tmp_dnode_info into the temporaty RB-tree, keeping the list in 23 * Check the data CRC of the node.
26 * order of increasing version. 24 *
25 * Returns: 0 if the data CRC is correct;
26 * 1 - if incorrect;
27 * error code if an error occured.
27 */ 28 */
28static void jffs2_add_tn_to_tree(struct jffs2_tmp_dnode_info *tn, struct rb_root *list) 29static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn)
29{ 30{
30 struct rb_node **p = &list->rb_node; 31 struct jffs2_raw_node_ref *ref = tn->fn->raw;
31 struct rb_node * parent = NULL; 32 int err = 0, pointed = 0;
32 struct jffs2_tmp_dnode_info *this; 33 struct jffs2_eraseblock *jeb;
33 34 unsigned char *buffer;
34 while (*p) { 35 uint32_t crc, ofs, len;
35 parent = *p; 36 size_t retlen;
36 this = rb_entry(parent, struct jffs2_tmp_dnode_info, rb); 37
37 38 BUG_ON(tn->csize == 0);
38 /* There may actually be a collision here, but it doesn't 39
39 actually matter. As long as the two nodes with the same 40 if (!jffs2_is_writebuffered(c))
40 version are together, it's all fine. */ 41 goto adj_acc;
41 if (tn->version > this->version) 42
42 p = &(*p)->rb_left; 43 /* Calculate how many bytes were already checked */
44 ofs = ref_offset(ref) + sizeof(struct jffs2_raw_inode);
45 len = ofs % c->wbuf_pagesize;
46 if (likely(len))
47 len = c->wbuf_pagesize - len;
48
49 if (len >= tn->csize) {
50 dbg_readinode("no need to check node at %#08x, data length %u, data starts at %#08x - it has already been checked.\n",
51 ref_offset(ref), tn->csize, ofs);
52 goto adj_acc;
53 }
54
55 ofs += len;
56 len = tn->csize - len;
57
58 dbg_readinode("check node at %#08x, data length %u, partial CRC %#08x, correct CRC %#08x, data starts at %#08x, start checking from %#08x - %u bytes.\n",
59 ref_offset(ref), tn->csize, tn->partial_crc, tn->data_crc, ofs - len, ofs, len);
60
61#ifndef __ECOS
62 /* TODO: instead, incapsulate point() stuff to jffs2_flash_read(),
63 * adding and jffs2_flash_read_end() interface. */
64 if (c->mtd->point) {
65 err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer);
66 if (!err && retlen < tn->csize) {
67 JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize);
68 c->mtd->unpoint(c->mtd, buffer, ofs, len);
69 } else if (err)
70 JFFS2_WARNING("MTD point failed: error code %d.\n", err);
43 else 71 else
44 p = &(*p)->rb_right; 72 pointed = 1; /* succefully pointed to device */
73 }
74#endif
75
76 if (!pointed) {
77 buffer = kmalloc(len, GFP_KERNEL);
78 if (unlikely(!buffer))
79 return -ENOMEM;
80
81 /* TODO: this is very frequent pattern, make it a separate
82 * routine */
83 err = jffs2_flash_read(c, ofs, len, &retlen, buffer);
84 if (err) {
85 JFFS2_ERROR("can not read %d bytes from 0x%08x, error code: %d.\n", len, ofs, err);
86 goto free_out;
87 }
88
89 if (retlen != len) {
90 JFFS2_ERROR("short read at %#08x: %zd instead of %d.\n", ofs, retlen, len);
91 err = -EIO;
92 goto free_out;
93 }
94 }
95
96 /* Continue calculating CRC */
97 crc = crc32(tn->partial_crc, buffer, len);
98 if(!pointed)
99 kfree(buffer);
100#ifndef __ECOS
101 else
102 c->mtd->unpoint(c->mtd, buffer, ofs, len);
103#endif
104
105 if (crc != tn->data_crc) {
106 JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n",
107 ofs, tn->data_crc, crc);
108 return 1;
45 } 109 }
46 110
47 rb_link_node(&tn->rb, parent, p); 111adj_acc:
48 rb_insert_color(&tn->rb, list); 112 jeb = &c->blocks[ref->flash_offset / c->sector_size];
113 len = ref_totlen(c, jeb, ref);
114 /* If it should be REF_NORMAL, it'll get marked as such when
115 we build the fragtree, shortly. No need to worry about GC
116 moving it while it's marked REF_PRISTINE -- GC won't happen
117 till we've finished checking every inode anyway. */
118 ref->flash_offset |= REF_PRISTINE;
119 /*
120 * Mark the node as having been checked and fix the
121 * accounting accordingly.
122 */
123 spin_lock(&c->erase_completion_lock);
124 jeb->used_size += len;
125 jeb->unchecked_size -= len;
126 c->used_size += len;
127 c->unchecked_size -= len;
128 jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
129 spin_unlock(&c->erase_completion_lock);
130
131 return 0;
132
133free_out:
134 if(!pointed)
135 kfree(buffer);
136#ifndef __ECOS
137 else
138 c->mtd->unpoint(c->mtd, buffer, ofs, len);
139#endif
140 return err;
141}
142
143/*
144 * Helper function for jffs2_add_older_frag_to_fragtree().
145 *
146 * Checks the node if we are in the checking stage.
147 */
148static int check_tn_node(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn)
149{
150 int ret;
151
152 BUG_ON(ref_obsolete(tn->fn->raw));
153
154 /* We only check the data CRC of unchecked nodes */
155 if (ref_flags(tn->fn->raw) != REF_UNCHECKED)
156 return 0;
157
158 dbg_readinode("check node %#04x-%#04x, phys offs %#08x\n",
159 tn->fn->ofs, tn->fn->ofs + tn->fn->size, ref_offset(tn->fn->raw));
160
161 ret = check_node_data(c, tn);
162 if (unlikely(ret < 0)) {
163 JFFS2_ERROR("check_node_data() returned error: %d.\n",
164 ret);
165 } else if (unlikely(ret > 0)) {
166 dbg_readinode("CRC error, mark it obsolete.\n");
167 jffs2_mark_node_obsolete(c, tn->fn->raw);
168 }
169
170 return ret;
171}
172
173static struct jffs2_tmp_dnode_info *jffs2_lookup_tn(struct rb_root *tn_root, uint32_t offset)
174{
175 struct rb_node *next;
176 struct jffs2_tmp_dnode_info *tn = NULL;
177
178 dbg_readinode("root %p, offset %d\n", tn_root, offset);
179
180 next = tn_root->rb_node;
181
182 while (next) {
183 tn = rb_entry(next, struct jffs2_tmp_dnode_info, rb);
184
185 if (tn->fn->ofs < offset)
186 next = tn->rb.rb_right;
187 else if (tn->fn->ofs >= offset)
188 next = tn->rb.rb_left;
189 else
190 break;
191 }
192
193 return tn;
194}
195
196
197static void jffs2_kill_tn(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn)
198{
199 jffs2_mark_node_obsolete(c, tn->fn->raw);
200 jffs2_free_full_dnode(tn->fn);
201 jffs2_free_tmp_dnode_info(tn);
202}
203/*
204 * This function is used when we read an inode. Data nodes arrive in
205 * arbitrary order -- they may be older or newer than the nodes which
206 * are already in the tree. Where overlaps occur, the older node can
207 * be discarded as long as the newer passes the CRC check. We don't
208 * bother to keep track of holes in this rbtree, and neither do we deal
209 * with frags -- we can have multiple entries starting at the same
210 * offset, and the one with the smallest length will come first in the
211 * ordering.
212 *
213 * Returns 0 if the node was inserted
214 * 1 if the node is obsolete (because we can't mark it so yet)
215 * < 0 an if error occurred
216 */
217static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
218 struct jffs2_readinode_info *rii,
219 struct jffs2_tmp_dnode_info *tn)
220{
221 uint32_t fn_end = tn->fn->ofs + tn->fn->size;
222 struct jffs2_tmp_dnode_info *insert_point = NULL, *this;
223
224 dbg_readinode("insert fragment %#04x-%#04x, ver %u\n", tn->fn->ofs, fn_end, tn->version);
225
226 /* If a node has zero dsize, we only have to keep if it if it might be the
227 node with highest version -- i.e. the one which will end up as f->metadata.
228 Note that such nodes won't be REF_UNCHECKED since there are no data to
229 check anyway. */
230 if (!tn->fn->size) {
231 if (rii->mdata_tn) {
232 /* We had a candidate mdata node already */
233 dbg_readinode("kill old mdata with ver %d\n", rii->mdata_tn->version);
234 jffs2_kill_tn(c, rii->mdata_tn);
235 }
236 rii->mdata_tn = tn;
237 dbg_readinode("keep new mdata with ver %d\n", tn->version);
238 return 0;
239 }
240
241 /* Find the earliest node which _may_ be relevant to this one */
242 this = jffs2_lookup_tn(&rii->tn_root, tn->fn->ofs);
243 if (!this) {
244 /* First addition to empty tree. $DEITY how I love the easy cases */
245 rb_link_node(&tn->rb, NULL, &rii->tn_root.rb_node);
246 rb_insert_color(&tn->rb, &rii->tn_root);
247 dbg_readinode("keep new frag\n");
248 return 0;
249 }
250
251 /* If we add a new node it'll be somewhere under here. */
252 insert_point = this;
253
254 /* If the node is coincident with another at a lower address,
255 back up until the other node is found. It may be relevant */
256 while (tn->overlapped)
257 tn = tn_prev(tn);
258
259 dbg_readinode("'this' found %#04x-%#04x (%s)\n", this->fn->ofs, this->fn->ofs + this->fn->size, this->fn ? "data" : "hole");
260
261 while (this) {
262 if (this->fn->ofs > fn_end)
263 break;
264 dbg_readinode("Ponder this ver %d, 0x%x-0x%x\n",
265 this->version, this->fn->ofs, this->fn->size);
266
267 if (this->version == tn->version) {
268 /* Version number collision means REF_PRISTINE GC. Accept either of them
269 as long as the CRC is correct. Check the one we have already... */
270 if (!check_tn_node(c, this)) {
271 /* The one we already had was OK. Keep it and throw away the new one */
272 dbg_readinode("Like old node. Throw away new\n");
273 jffs2_kill_tn(c, tn);
274 return 0;
275 } else {
276 /* Who cares if the new one is good; keep it for now anyway. */
277 rb_replace_node(&this->rb, &tn->rb, &rii->tn_root);
278 /* Same overlapping from in front and behind */
279 tn->overlapped = this->overlapped;
280 jffs2_kill_tn(c, this);
281 dbg_readinode("Like new node. Throw away old\n");
282 return 0;
283 }
284 }
285 if (this->version < tn->version &&
286 this->fn->ofs >= tn->fn->ofs &&
287 this->fn->ofs + this->fn->size <= fn_end) {
288 /* New node entirely overlaps 'this' */
289 if (check_tn_node(c, tn)) {
290 dbg_readinode("new node bad CRC\n");
291 jffs2_kill_tn(c, tn);
292 return 0;
293 }
294 /* ... and is good. Kill 'this'... */
295 rb_replace_node(&this->rb, &tn->rb, &rii->tn_root);
296 tn->overlapped = this->overlapped;
297 jffs2_kill_tn(c, this);
298 /* ... and any subsequent nodes which are also overlapped */
299 this = tn_next(tn);
300 while (this && this->fn->ofs + this->fn->size < fn_end) {
301 struct jffs2_tmp_dnode_info *next = tn_next(this);
302 if (this->version < tn->version) {
303 tn_erase(this, &rii->tn_root);
304 dbg_readinode("Kill overlapped ver %d, 0x%x-0x%x\n",
305 this->version, this->fn->ofs,
306 this->fn->ofs+this->fn->size);
307 jffs2_kill_tn(c, this);
308 }
309 this = next;
310 }
311 dbg_readinode("Done inserting new\n");
312 return 0;
313 }
314 if (this->version > tn->version &&
315 this->fn->ofs <= tn->fn->ofs &&
316 this->fn->ofs+this->fn->size >= fn_end) {
317 /* New node entirely overlapped by 'this' */
318 if (!check_tn_node(c, this)) {
319 dbg_readinode("Good CRC on old node. Kill new\n");
320 jffs2_kill_tn(c, tn);
321 return 0;
322 }
323 /* ... but 'this' was bad. Replace it... */
324 rb_replace_node(&this->rb, &tn->rb, &rii->tn_root);
325 dbg_readinode("Bad CRC on old overlapping node. Kill it\n");
326 jffs2_kill_tn(c, this);
327 return 0;
328 }
329 /* We want to be inserted under the last node which is
330 either at a lower offset _or_ has a smaller range */
331 if (this->fn->ofs < tn->fn->ofs ||
332 (this->fn->ofs == tn->fn->ofs &&
333 this->fn->size <= tn->fn->size))
334 insert_point = this;
335
336 this = tn_next(this);
337 }
338 dbg_readinode("insert_point %p, ver %d, 0x%x-0x%x, ov %d\n",
339 insert_point, insert_point->version, insert_point->fn->ofs,
340 insert_point->fn->ofs+insert_point->fn->size,
341 insert_point->overlapped);
342 /* We neither completely obsoleted nor were completely
343 obsoleted by an earlier node. Insert under insert_point */
344 {
345 struct rb_node *parent = &insert_point->rb;
346 struct rb_node **link = &parent;
347
348 while (*link) {
349 parent = *link;
350 insert_point = rb_entry(parent, struct jffs2_tmp_dnode_info, rb);
351 if (tn->fn->ofs > insert_point->fn->ofs)
352 link = &insert_point->rb.rb_right;
353 else if (tn->fn->ofs < insert_point->fn->ofs ||
354 tn->fn->size < insert_point->fn->size)
355 link = &insert_point->rb.rb_left;
356 else
357 link = &insert_point->rb.rb_right;
358 }
359 rb_link_node(&tn->rb, &insert_point->rb, link);
360 rb_insert_color(&tn->rb, &rii->tn_root);
361 }
362 /* If there's anything behind that overlaps us, note it */
363 this = tn_prev(tn);
364 if (this) {
365 while (1) {
366 if (this->fn->ofs + this->fn->size > tn->fn->ofs) {
367 dbg_readinode("Node is overlapped by %p (v %d, 0x%x-0x%x)\n",
368 this, this->version, this->fn->ofs,
369 this->fn->ofs+this->fn->size);
370 tn->overlapped = 1;
371 break;
372 }
373 if (!this->overlapped)
374 break;
375 this = tn_prev(this);
376 }
377 }
378
379 /* If the new node overlaps anything ahead, note it */
380 this = tn_next(tn);
381 while (this && this->fn->ofs < fn_end) {
382 this->overlapped = 1;
383 dbg_readinode("Node ver %d, 0x%x-0x%x is overlapped\n",
384 this->version, this->fn->ofs,
385 this->fn->ofs+this->fn->size);
386 this = tn_next(this);
387 }
388 return 0;
389}
390
391/* Trivial function to remove the last node in the tree. Which by definition
392 has no right-hand -- so can be removed just by making its only child (if
393 any) take its place under its parent. */
394static void eat_last(struct rb_root *root, struct rb_node *node)
395{
396 struct rb_node *parent = rb_parent(node);
397 struct rb_node **link;
398
399 /* LAST! */
400 BUG_ON(node->rb_right);
401
402 if (!parent)
403 link = &root->rb_node;
404 else if (node == parent->rb_left)
405 link = &parent->rb_left;
406 else
407 link = &parent->rb_right;
408
409 *link = node->rb_left;
410 /* Colour doesn't matter now. Only the parent pointer. */
411 if (node->rb_left)
412 node->rb_left->rb_parent_color = node->rb_parent_color;
413}
414
415/* We put this in reverse order, so we can just use eat_last */
416static void ver_insert(struct rb_root *ver_root, struct jffs2_tmp_dnode_info *tn)
417{
418 struct rb_node **link = &ver_root->rb_node;
419 struct rb_node *parent = NULL;
420 struct jffs2_tmp_dnode_info *this_tn;
421
422 while (*link) {
423 parent = *link;
424 this_tn = rb_entry(parent, struct jffs2_tmp_dnode_info, rb);
425
426 if (tn->version > this_tn->version)
427 link = &parent->rb_left;
428 else
429 link = &parent->rb_right;
430 }
431 dbg_readinode("Link new node at %p (root is %p)\n", link, ver_root);
432 rb_link_node(&tn->rb, parent, link);
433 rb_insert_color(&tn->rb, ver_root);
434}
435
436/* Build final, normal fragtree from tn tree. It doesn't matter which order
437 we add nodes to the real fragtree, as long as they don't overlap. And
438 having thrown away the majority of overlapped nodes as we went, there
439 really shouldn't be many sets of nodes which do overlap. If we start at
440 the end, we can use the overlap markers -- we can just eat nodes which
441 aren't overlapped, and when we encounter nodes which _do_ overlap we
442 sort them all into a temporary tree in version order before replaying them. */
443static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c,
444 struct jffs2_inode_info *f,
445 struct jffs2_readinode_info *rii)
446{
447 struct jffs2_tmp_dnode_info *pen, *last, *this;
448 struct rb_root ver_root = RB_ROOT;
449 uint32_t high_ver = 0;
450
451 if (rii->mdata_tn) {
452 dbg_readinode("potential mdata is ver %d at %p\n", rii->mdata_tn->version, rii->mdata_tn);
453 high_ver = rii->mdata_tn->version;
454 rii->latest_ref = rii->mdata_tn->fn->raw;
455 }
456#ifdef JFFS2_DBG_READINODE_MESSAGES
457 this = tn_last(&rii->tn_root);
458 while (this) {
459 dbg_readinode("tn %p ver %d range 0x%x-0x%x ov %d\n", this, this->version, this->fn->ofs,
460 this->fn->ofs+this->fn->size, this->overlapped);
461 this = tn_prev(this);
462 }
463#endif
464 pen = tn_last(&rii->tn_root);
465 while ((last = pen)) {
466 pen = tn_prev(last);
467
468 eat_last(&rii->tn_root, &last->rb);
469 ver_insert(&ver_root, last);
470
471 if (unlikely(last->overlapped))
472 continue;
473
474 /* Now we have a bunch of nodes in reverse version
475 order, in the tree at ver_root. Most of the time,
476 there'll actually be only one node in the 'tree',
477 in fact. */
478 this = tn_last(&ver_root);
479
480 while (this) {
481 struct jffs2_tmp_dnode_info *vers_next;
482 int ret;
483 vers_next = tn_prev(this);
484 eat_last(&ver_root, &this->rb);
485 if (check_tn_node(c, this)) {
486 dbg_readinode("node ver %x, 0x%x-0x%x failed CRC\n",
487 this->version, this->fn->ofs,
488 this->fn->ofs+this->fn->size);
489 jffs2_kill_tn(c, this);
490 } else {
491 if (this->version > high_ver) {
492 /* Note that this is different from the other
493 highest_version, because this one is only
494 counting _valid_ nodes which could give the
495 latest inode metadata */
496 high_ver = this->version;
497 rii->latest_ref = this->fn->raw;
498 }
499 dbg_readinode("Add %p (v %x, 0x%x-0x%x, ov %d) to fragtree\n",
500 this, this->version, this->fn->ofs,
501 this->fn->ofs+this->fn->size, this->overlapped);
502
503 ret = jffs2_add_full_dnode_to_inode(c, f, this->fn);
504 if (ret) {
505 /* Free the nodes in vers_root; let the caller
506 deal with the rest */
507 JFFS2_ERROR("Add node to tree failed %d\n", ret);
508 while (1) {
509 vers_next = tn_prev(this);
510 if (check_tn_node(c, this))
511 jffs2_mark_node_obsolete(c, this->fn->raw);
512 jffs2_free_full_dnode(this->fn);
513 jffs2_free_tmp_dnode_info(this);
514 this = vers_next;
515 if (!this)
516 break;
517 eat_last(&ver_root, &vers_next->rb);
518 }
519 return ret;
520 }
521 jffs2_free_tmp_dnode_info(this);
522 }
523 this = vers_next;
524 }
525 }
526 return 0;
49} 527}
50 528
51static void jffs2_free_tmp_dnode_info_list(struct rb_root *list) 529static void jffs2_free_tmp_dnode_info_list(struct rb_root *list)
@@ -112,8 +590,8 @@ static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_r
112 * negative error code on failure. 590 * negative error code on failure.
113 */ 591 */
114static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, 592static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
115 struct jffs2_raw_dirent *rd, size_t read, struct jffs2_full_dirent **fdp, 593 struct jffs2_raw_dirent *rd, size_t read,
116 uint32_t *latest_mctime, uint32_t *mctime_ver) 594 struct jffs2_readinode_info *rii)
117{ 595{
118 struct jffs2_full_dirent *fd; 596 struct jffs2_full_dirent *fd;
119 uint32_t crc; 597 uint32_t crc;
@@ -125,7 +603,8 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r
125 if (unlikely(crc != je32_to_cpu(rd->node_crc))) { 603 if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
126 JFFS2_NOTICE("header CRC failed on dirent node at %#08x: read %#08x, calculated %#08x\n", 604 JFFS2_NOTICE("header CRC failed on dirent node at %#08x: read %#08x, calculated %#08x\n",
127 ref_offset(ref), je32_to_cpu(rd->node_crc), crc); 605 ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
128 return 1; 606 jffs2_mark_node_obsolete(c, ref);
607 return 0;
129 } 608 }
130 609
131 /* If we've never checked the CRCs on this node, check them now */ 610 /* If we've never checked the CRCs on this node, check them now */
@@ -137,7 +616,8 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r
137 if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) { 616 if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) {
138 JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n", 617 JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n",
139 ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen)); 618 ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen));
140 return 1; 619 jffs2_mark_node_obsolete(c, ref);
620 return 0;
141 } 621 }
142 622
143 jeb = &c->blocks[ref->flash_offset / c->sector_size]; 623 jeb = &c->blocks[ref->flash_offset / c->sector_size];
@@ -161,10 +641,13 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r
161 fd->ino = je32_to_cpu(rd->ino); 641 fd->ino = je32_to_cpu(rd->ino);
162 fd->type = rd->type; 642 fd->type = rd->type;
163 643
644 if (fd->version > rii->highest_version)
645 rii->highest_version = fd->version;
646
164 /* Pick out the mctime of the latest dirent */ 647 /* Pick out the mctime of the latest dirent */
165 if(fd->version > *mctime_ver && je32_to_cpu(rd->mctime)) { 648 if(fd->version > rii->mctime_ver && je32_to_cpu(rd->mctime)) {
166 *mctime_ver = fd->version; 649 rii->mctime_ver = fd->version;
167 *latest_mctime = je32_to_cpu(rd->mctime); 650 rii->latest_mctime = je32_to_cpu(rd->mctime);
168 } 651 }
169 652
170 /* 653 /*
@@ -201,7 +684,7 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r
201 * Wheee. We now have a complete jffs2_full_dirent structure, with 684 * Wheee. We now have a complete jffs2_full_dirent structure, with
202 * the name in it and everything. Link it into the list 685 * the name in it and everything. Link it into the list
203 */ 686 */
204 jffs2_add_fd_to_list(c, fd, fdp); 687 jffs2_add_fd_to_list(c, fd, &rii->fds);
205 688
206 return 0; 689 return 0;
207} 690}
@@ -210,13 +693,13 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r
210 * Helper function for jffs2_get_inode_nodes(). 693 * Helper function for jffs2_get_inode_nodes().
211 * It is called every time an inode node is found. 694 * It is called every time an inode node is found.
212 * 695 *
213 * Returns: 0 on succes; 696 * Returns: 0 on success;
214 * 1 if the node should be marked obsolete; 697 * 1 if the node should be marked obsolete;
215 * negative error code on failure. 698 * negative error code on failure.
216 */ 699 */
217static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, 700static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
218 struct jffs2_raw_inode *rd, struct rb_root *tnp, int rdlen, 701 struct jffs2_raw_inode *rd, int rdlen,
219 uint32_t *latest_mctime, uint32_t *mctime_ver) 702 struct jffs2_readinode_info *rii)
220{ 703{
221 struct jffs2_tmp_dnode_info *tn; 704 struct jffs2_tmp_dnode_info *tn;
222 uint32_t len, csize; 705 uint32_t len, csize;
@@ -230,7 +713,8 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
230 if (unlikely(crc != je32_to_cpu(rd->node_crc))) { 713 if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
231 JFFS2_NOTICE("node CRC failed on dnode at %#08x: read %#08x, calculated %#08x\n", 714 JFFS2_NOTICE("node CRC failed on dnode at %#08x: read %#08x, calculated %#08x\n",
232 ref_offset(ref), je32_to_cpu(rd->node_crc), crc); 715 ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
233 return 1; 716 jffs2_mark_node_obsolete(c, ref);
717 return 0;
234 } 718 }
235 719
236 tn = jffs2_alloc_tmp_dnode_info(); 720 tn = jffs2_alloc_tmp_dnode_info();
@@ -342,6 +826,10 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
342 tn->data_crc = je32_to_cpu(rd->data_crc); 826 tn->data_crc = je32_to_cpu(rd->data_crc);
343 tn->csize = csize; 827 tn->csize = csize;
344 tn->fn->raw = ref; 828 tn->fn->raw = ref;
829 tn->overlapped = 0;
830
831 if (tn->version > rii->highest_version)
832 rii->highest_version = tn->version;
345 833
346 /* There was a bug where we wrote hole nodes out with 834 /* There was a bug where we wrote hole nodes out with
347 csize/dsize swapped. Deal with it */ 835 csize/dsize swapped. Deal with it */
@@ -353,13 +841,25 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
353 dbg_readinode("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n", 841 dbg_readinode("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n",
354 ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize); 842 ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize);
355 843
356 jffs2_add_tn_to_tree(tn, tnp); 844 ret = jffs2_add_tn_to_tree(c, rii, tn);
357 845
846 if (ret) {
847 jffs2_free_full_dnode(tn->fn);
848 free_out:
849 jffs2_free_tmp_dnode_info(tn);
850 return ret;
851 }
852#ifdef JFFS2_DBG_READINODE_MESSAGES
853 dbg_readinode("After adding ver %d:\n", tn->version);
854 tn = tn_first(&rii->tn_root);
855 while (tn) {
856 dbg_readinode("%p: v %d r 0x%x-0x%x ov %d\n",
857 tn, tn->version, tn->fn->ofs,
858 tn->fn->ofs+tn->fn->size, tn->overlapped);
859 tn = tn_next(tn);
860 }
861#endif
358 return 0; 862 return 0;
359
360free_out:
361 jffs2_free_tmp_dnode_info(tn);
362 return ret;
363} 863}
364 864
365/* 865/*
@@ -379,7 +879,8 @@ static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_re
379 JFFS2_ERROR("Node is {%04x,%04x,%08x,%08x}. Please report this error.\n", 879 JFFS2_ERROR("Node is {%04x,%04x,%08x,%08x}. Please report this error.\n",
380 je16_to_cpu(un->magic), je16_to_cpu(un->nodetype), 880 je16_to_cpu(un->magic), je16_to_cpu(un->nodetype),
381 je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc)); 881 je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc));
382 return 1; 882 jffs2_mark_node_obsolete(c, ref);
883 return 0;
383 } 884 }
384 885
385 un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype)); 886 un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype));
@@ -407,7 +908,8 @@ static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_re
407 case JFFS2_FEATURE_RWCOMPAT_DELETE: 908 case JFFS2_FEATURE_RWCOMPAT_DELETE:
408 JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n", 909 JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n",
409 je16_to_cpu(un->nodetype), ref_offset(ref)); 910 je16_to_cpu(un->nodetype), ref_offset(ref));
410 return 1; 911 jffs2_mark_node_obsolete(c, ref);
912 return 0;
411 } 913 }
412 914
413 return 0; 915 return 0;
@@ -421,92 +923,62 @@ static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_re
421 * negative error code on failure. 923 * negative error code on failure.
422 */ 924 */
423static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, 925static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
424 int right_size, int *rdlen, unsigned char *buf, unsigned char *bufstart) 926 int needed_len, int *rdlen, unsigned char *buf)
425{ 927{
426 int right_len, err, len; 928 int err, to_read = needed_len - *rdlen;
427 size_t retlen; 929 size_t retlen;
428 uint32_t offs; 930 uint32_t offs;
429 931
430 if (jffs2_is_writebuffered(c)) { 932 if (jffs2_is_writebuffered(c)) {
431 right_len = c->wbuf_pagesize - (bufstart - buf); 933 int rem = to_read % c->wbuf_pagesize;
432 if (right_size + (int)(bufstart - buf) > c->wbuf_pagesize)
433 right_len += c->wbuf_pagesize;
434 } else
435 right_len = right_size;
436 934
437 if (*rdlen == right_len) 935 if (rem)
438 return 0; 936 to_read += c->wbuf_pagesize - rem;
937 }
439 938
440 /* We need to read more data */ 939 /* We need to read more data */
441 offs = ref_offset(ref) + *rdlen; 940 offs = ref_offset(ref) + *rdlen;
442 if (jffs2_is_writebuffered(c)) {
443 bufstart = buf + c->wbuf_pagesize;
444 len = c->wbuf_pagesize;
445 } else {
446 bufstart = buf + *rdlen;
447 len = right_size - *rdlen;
448 }
449 941
450 dbg_readinode("read more %d bytes\n", len); 942 dbg_readinode("read more %d bytes\n", to_read);
451 943
452 err = jffs2_flash_read(c, offs, len, &retlen, bufstart); 944 err = jffs2_flash_read(c, offs, to_read, &retlen, buf + *rdlen);
453 if (err) { 945 if (err) {
454 JFFS2_ERROR("can not read %d bytes from 0x%08x, " 946 JFFS2_ERROR("can not read %d bytes from 0x%08x, "
455 "error code: %d.\n", len, offs, err); 947 "error code: %d.\n", to_read, offs, err);
456 return err; 948 return err;
457 } 949 }
458 950
459 if (retlen < len) { 951 if (retlen < to_read) {
460 JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n", 952 JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n",
461 offs, retlen, len); 953 offs, retlen, to_read);
462 return -EIO; 954 return -EIO;
463 } 955 }
464 956
465 *rdlen = right_len; 957 *rdlen += to_read;
466
467 return 0; 958 return 0;
468} 959}
469 960
470/* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated 961/* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated
471 with this ino, returning the former in order of version */ 962 with this ino. Perform a preliminary ordering on data nodes, throwing away
963 those which are completely obsoleted by newer ones. The naïve approach we
964 use to take of just returning them _all_ in version order will cause us to
965 run out of memory in certain degenerate cases. */
472static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f, 966static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
473 struct rb_root *tnp, struct jffs2_full_dirent **fdp, 967 struct jffs2_readinode_info *rii)
474 uint32_t *highest_version, uint32_t *latest_mctime,
475 uint32_t *mctime_ver)
476{ 968{
477 struct jffs2_raw_node_ref *ref, *valid_ref; 969 struct jffs2_raw_node_ref *ref, *valid_ref;
478 struct rb_root ret_tn = RB_ROOT;
479 struct jffs2_full_dirent *ret_fd = NULL;
480 unsigned char *buf = NULL; 970 unsigned char *buf = NULL;
481 union jffs2_node_union *node; 971 union jffs2_node_union *node;
482 size_t retlen; 972 size_t retlen;
483 int len, err; 973 int len, err;
484 974
485 *mctime_ver = 0; 975 rii->mctime_ver = 0;
486 976
487 dbg_readinode("ino #%u\n", f->inocache->ino); 977 dbg_readinode("ino #%u\n", f->inocache->ino);
488 978
489 if (jffs2_is_writebuffered(c)) {
490 /*
491 * If we have the write buffer, we assume the minimal I/O unit
492 * is c->wbuf_pagesize. We implement some optimizations which in
493 * this case and we need a temporary buffer of size =
494 * 2*c->wbuf_pagesize bytes (see comments in read_dnode()).
495 * Basically, we want to read not only the node header, but the
496 * whole wbuf (NAND page in case of NAND) or 2, if the node
497 * header overlaps the border between the 2 wbufs.
498 */
499 len = 2*c->wbuf_pagesize;
500 } else {
501 /*
502 * When there is no write buffer, the size of the temporary
503 * buffer is the size of the larges node header.
504 */
505 len = sizeof(union jffs2_node_union);
506 }
507
508 /* FIXME: in case of NOR and available ->point() this 979 /* FIXME: in case of NOR and available ->point() this
509 * needs to be fixed. */ 980 * needs to be fixed. */
981 len = sizeof(union jffs2_node_union) + c->wbuf_pagesize;
510 buf = kmalloc(len, GFP_KERNEL); 982 buf = kmalloc(len, GFP_KERNEL);
511 if (!buf) 983 if (!buf)
512 return -ENOMEM; 984 return -ENOMEM;
@@ -516,8 +988,6 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
516 if (!valid_ref && f->inocache->ino != 1) 988 if (!valid_ref && f->inocache->ino != 1)
517 JFFS2_WARNING("Eep. No valid nodes for ino #%u.\n", f->inocache->ino); 989 JFFS2_WARNING("Eep. No valid nodes for ino #%u.\n", f->inocache->ino);
518 while (valid_ref) { 990 while (valid_ref) {
519 unsigned char *bufstart;
520
521 /* We can hold a pointer to a non-obsolete node without the spinlock, 991 /* We can hold a pointer to a non-obsolete node without the spinlock,
522 but _obsolete_ nodes may disappear at any time, if the block 992 but _obsolete_ nodes may disappear at any time, if the block
523 they're in gets erased. So if we mark 'ref' obsolete while we're 993 they're in gets erased. So if we mark 'ref' obsolete while we're
@@ -533,32 +1003,31 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
533 /* 1003 /*
534 * At this point we don't know the type of the node we're going 1004 * At this point we don't know the type of the node we're going
535 * to read, so we do not know the size of its header. In order 1005 * to read, so we do not know the size of its header. In order
536 * to minimize the amount of flash IO we assume the node has 1006 * to minimize the amount of flash IO we assume the header is
537 * size = JFFS2_MIN_NODE_HEADER. 1007 * of size = JFFS2_MIN_NODE_HEADER.
538 */ 1008 */
1009 len = JFFS2_MIN_NODE_HEADER;
539 if (jffs2_is_writebuffered(c)) { 1010 if (jffs2_is_writebuffered(c)) {
1011 int end, rem;
1012
540 /* 1013 /*
541 * We treat 'buf' as 2 adjacent wbufs. We want to 1014 * We are about to read JFFS2_MIN_NODE_HEADER bytes,
542 * adjust bufstart such as it points to the 1015 * but this flash has some minimal I/O unit. It is
543 * beginning of the node within this wbuf. 1016 * possible that we'll need to read more soon, so read
1017 * up to the next min. I/O unit, in order not to
1018 * re-read the same min. I/O unit twice.
544 */ 1019 */
545 bufstart = buf + (ref_offset(ref) % c->wbuf_pagesize); 1020 end = ref_offset(ref) + len;
546 /* We will read either one wbuf or 2 wbufs. */ 1021 rem = end % c->wbuf_pagesize;
547 len = c->wbuf_pagesize - (bufstart - buf); 1022 if (rem)
548 if (JFFS2_MIN_NODE_HEADER + (int)(bufstart - buf) > c->wbuf_pagesize) { 1023 end += c->wbuf_pagesize - rem;
549 /* The header spans the border of the first wbuf */ 1024 len = end - ref_offset(ref);
550 len += c->wbuf_pagesize;
551 }
552 } else {
553 bufstart = buf;
554 len = JFFS2_MIN_NODE_HEADER;
555 } 1025 }
556 1026
557 dbg_readinode("read %d bytes at %#08x(%d).\n", len, ref_offset(ref), ref_flags(ref)); 1027 dbg_readinode("read %d bytes at %#08x(%d).\n", len, ref_offset(ref), ref_flags(ref));
558 1028
559 /* FIXME: point() */ 1029 /* FIXME: point() */
560 err = jffs2_flash_read(c, ref_offset(ref), len, 1030 err = jffs2_flash_read(c, ref_offset(ref), len, &retlen, buf);
561 &retlen, bufstart);
562 if (err) { 1031 if (err) {
563 JFFS2_ERROR("can not read %d bytes from 0x%08x, " "error code: %d.\n", len, ref_offset(ref), err); 1032 JFFS2_ERROR("can not read %d bytes from 0x%08x, " "error code: %d.\n", len, ref_offset(ref), err);
564 goto free_out; 1033 goto free_out;
@@ -570,7 +1039,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
570 goto free_out; 1039 goto free_out;
571 } 1040 }
572 1041
573 node = (union jffs2_node_union *)bufstart; 1042 node = (union jffs2_node_union *)buf;
574 1043
575 /* No need to mask in the valid bit; it shouldn't be invalid */ 1044 /* No need to mask in the valid bit; it shouldn't be invalid */
576 if (je32_to_cpu(node->u.hdr_crc) != crc32(0, node, sizeof(node->u)-4)) { 1045 if (je32_to_cpu(node->u.hdr_crc) != crc32(0, node, sizeof(node->u)-4)) {
@@ -583,10 +1052,10 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
583 jffs2_mark_node_obsolete(c, ref); 1052 jffs2_mark_node_obsolete(c, ref);
584 goto cont; 1053 goto cont;
585 } 1054 }
586 /* Due to poor choice of crc32 seed, an all-zero node will have a correct CRC */ 1055 if (je16_to_cpu(node->u.magic) != JFFS2_MAGIC_BITMASK) {
587 if (!je32_to_cpu(node->u.hdr_crc) && !je16_to_cpu(node->u.nodetype) && 1056 /* Not a JFFS2 node, whinge and move on */
588 !je16_to_cpu(node->u.magic) && !je32_to_cpu(node->u.totlen)) { 1057 JFFS2_NOTICE("Wrong magic bitmask 0x%04x in node header at %#08x.\n",
589 JFFS2_NOTICE("All zero node header at %#08x.\n", ref_offset(ref)); 1058 je16_to_cpu(node->u.magic), ref_offset(ref));
590 jffs2_mark_node_obsolete(c, ref); 1059 jffs2_mark_node_obsolete(c, ref);
591 goto cont; 1060 goto cont;
592 } 1061 }
@@ -596,46 +1065,34 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
596 case JFFS2_NODETYPE_DIRENT: 1065 case JFFS2_NODETYPE_DIRENT:
597 1066
598 if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent)) { 1067 if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent)) {
599 err = read_more(c, ref, sizeof(struct jffs2_raw_dirent), &len, buf, bufstart); 1068 err = read_more(c, ref, sizeof(struct jffs2_raw_dirent), &len, buf);
600 if (unlikely(err)) 1069 if (unlikely(err))
601 goto free_out; 1070 goto free_out;
602 } 1071 }
603 1072
604 err = read_direntry(c, ref, &node->d, retlen, &ret_fd, latest_mctime, mctime_ver); 1073 err = read_direntry(c, ref, &node->d, retlen, rii);
605 if (err == 1) { 1074 if (unlikely(err))
606 jffs2_mark_node_obsolete(c, ref);
607 break;
608 } else if (unlikely(err))
609 goto free_out; 1075 goto free_out;
610 1076
611 if (je32_to_cpu(node->d.version) > *highest_version)
612 *highest_version = je32_to_cpu(node->d.version);
613
614 break; 1077 break;
615 1078
616 case JFFS2_NODETYPE_INODE: 1079 case JFFS2_NODETYPE_INODE:
617 1080
618 if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode)) { 1081 if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode)) {
619 err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf, bufstart); 1082 err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf);
620 if (unlikely(err)) 1083 if (unlikely(err))
621 goto free_out; 1084 goto free_out;
622 } 1085 }
623 1086
624 err = read_dnode(c, ref, &node->i, &ret_tn, len, latest_mctime, mctime_ver); 1087 err = read_dnode(c, ref, &node->i, len, rii);
625 if (err == 1) { 1088 if (unlikely(err))
626 jffs2_mark_node_obsolete(c, ref);
627 break;
628 } else if (unlikely(err))
629 goto free_out; 1089 goto free_out;
630 1090
631 if (je32_to_cpu(node->i.version) > *highest_version)
632 *highest_version = je32_to_cpu(node->i.version);
633
634 break; 1091 break;
635 1092
636 default: 1093 default:
637 if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_unknown_node)) { 1094 if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_unknown_node)) {
638 err = read_more(c, ref, sizeof(struct jffs2_unknown_node), &len, buf, bufstart); 1095 err = read_more(c, ref, sizeof(struct jffs2_unknown_node), &len, buf);
639 if (unlikely(err)) 1096 if (unlikely(err))
640 goto free_out; 1097 goto free_out;
641 } 1098 }
@@ -653,17 +1110,19 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
653 } 1110 }
654 1111
655 spin_unlock(&c->erase_completion_lock); 1112 spin_unlock(&c->erase_completion_lock);
656 *tnp = ret_tn;
657 *fdp = ret_fd;
658 kfree(buf); 1113 kfree(buf);
659 1114
1115 f->highest_version = rii->highest_version;
1116
660 dbg_readinode("nodes of inode #%u were read, the highest version is %u, latest_mctime %u, mctime_ver %u.\n", 1117 dbg_readinode("nodes of inode #%u were read, the highest version is %u, latest_mctime %u, mctime_ver %u.\n",
661 f->inocache->ino, *highest_version, *latest_mctime, *mctime_ver); 1118 f->inocache->ino, rii->highest_version, rii->latest_mctime,
1119 rii->mctime_ver);
662 return 0; 1120 return 0;
663 1121
664 free_out: 1122 free_out:
665 jffs2_free_tmp_dnode_info_list(&ret_tn); 1123 jffs2_free_tmp_dnode_info_list(&rii->tn_root);
666 jffs2_free_full_dirent_list(ret_fd); 1124 jffs2_free_full_dirent_list(rii->fds);
1125 rii->fds = NULL;
667 kfree(buf); 1126 kfree(buf);
668 return err; 1127 return err;
669} 1128}
@@ -672,20 +1131,17 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
672 struct jffs2_inode_info *f, 1131 struct jffs2_inode_info *f,
673 struct jffs2_raw_inode *latest_node) 1132 struct jffs2_raw_inode *latest_node)
674{ 1133{
675 struct jffs2_tmp_dnode_info *tn; 1134 struct jffs2_readinode_info rii;
676 struct rb_root tn_list; 1135 uint32_t crc, new_size;
677 struct rb_node *rb, *repl_rb;
678 struct jffs2_full_dirent *fd_list;
679 struct jffs2_full_dnode *fn, *first_fn = NULL;
680 uint32_t crc;
681 uint32_t latest_mctime, mctime_ver;
682 size_t retlen; 1136 size_t retlen;
683 int ret; 1137 int ret;
684 1138
685 dbg_readinode("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink); 1139 dbg_readinode("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink);
686 1140
1141 memset(&rii, 0, sizeof(rii));
1142
687 /* Grab all nodes relevant to this ino */ 1143 /* Grab all nodes relevant to this ino */
688 ret = jffs2_get_inode_nodes(c, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver); 1144 ret = jffs2_get_inode_nodes(c, f, &rii);
689 1145
690 if (ret) { 1146 if (ret) {
691 JFFS2_ERROR("cannot read nodes for ino %u, returned error is %d\n", f->inocache->ino, ret); 1147 JFFS2_ERROR("cannot read nodes for ino %u, returned error is %d\n", f->inocache->ino, ret);
@@ -693,74 +1149,42 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
693 jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); 1149 jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
694 return ret; 1150 return ret;
695 } 1151 }
696 f->dents = fd_list;
697
698 rb = rb_first(&tn_list);
699 1152
700 while (rb) { 1153 ret = jffs2_build_inode_fragtree(c, f, &rii);
701 cond_resched(); 1154 if (ret) {
702 tn = rb_entry(rb, struct jffs2_tmp_dnode_info, rb); 1155 JFFS2_ERROR("Failed to build final fragtree for inode #%u: error %d\n",
703 fn = tn->fn; 1156 f->inocache->ino, ret);
704 ret = 1; 1157 if (f->inocache->state == INO_STATE_READING)
705 dbg_readinode("consider node ver %u, phys offset " 1158 jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
706 "%#08x(%d), range %u-%u.\n", tn->version, 1159 jffs2_free_tmp_dnode_info_list(&rii.tn_root);
707 ref_offset(fn->raw), ref_flags(fn->raw), 1160 /* FIXME: We could at least crc-check them all */
708 fn->ofs, fn->ofs + fn->size); 1161 if (rii.mdata_tn) {
709 1162 jffs2_free_full_dnode(rii.mdata_tn->fn);
710 if (fn->size) { 1163 jffs2_free_tmp_dnode_info(rii.mdata_tn);
711 ret = jffs2_add_older_frag_to_fragtree(c, f, tn); 1164 rii.mdata_tn = NULL;
712 /* TODO: the error code isn't checked, check it */ 1165 }
713 jffs2_dbg_fragtree_paranoia_check_nolock(f); 1166 return ret;
714 BUG_ON(ret < 0); 1167 }
715 if (!first_fn && ret == 0)
716 first_fn = fn;
717 } else if (!first_fn) {
718 first_fn = fn;
719 f->metadata = fn;
720 ret = 0; /* Prevent freeing the metadata update node */
721 } else
722 jffs2_mark_node_obsolete(c, fn->raw);
723
724 BUG_ON(rb->rb_left);
725 if (rb_parent(rb) && rb_parent(rb)->rb_left == rb) {
726 /* We were then left-hand child of our parent. We need
727 * to move our own right-hand child into our place. */
728 repl_rb = rb->rb_right;
729 if (repl_rb)
730 rb_set_parent(repl_rb, rb_parent(rb));
731 } else
732 repl_rb = NULL;
733
734 rb = rb_next(rb);
735
736 /* Remove the spent tn from the tree; don't bother rebalancing
737 * but put our right-hand child in our own place. */
738 if (rb_parent(&tn->rb)) {
739 if (rb_parent(&tn->rb)->rb_left == &tn->rb)
740 rb_parent(&tn->rb)->rb_left = repl_rb;
741 else if (rb_parent(&tn->rb)->rb_right == &tn->rb)
742 rb_parent(&tn->rb)->rb_right = repl_rb;
743 else BUG();
744 } else if (tn->rb.rb_right)
745 rb_set_parent(tn->rb.rb_right, NULL);
746 1168
747 jffs2_free_tmp_dnode_info(tn); 1169 if (rii.mdata_tn) {
748 if (ret) { 1170 if (rii.mdata_tn->fn->raw == rii.latest_ref) {
749 dbg_readinode("delete dnode %u-%u.\n", 1171 f->metadata = rii.mdata_tn->fn;
750 fn->ofs, fn->ofs + fn->size); 1172 jffs2_free_tmp_dnode_info(rii.mdata_tn);
751 jffs2_free_full_dnode(fn); 1173 } else {
1174 jffs2_kill_tn(c, rii.mdata_tn);
752 } 1175 }
1176 rii.mdata_tn = NULL;
753 } 1177 }
754 jffs2_dbg_fragtree_paranoia_check_nolock(f);
755 1178
756 BUG_ON(first_fn && ref_obsolete(first_fn->raw)); 1179 f->dents = rii.fds;
757 1180
758 fn = first_fn; 1181 jffs2_dbg_fragtree_paranoia_check_nolock(f);
759 if (unlikely(!first_fn)) { 1182
1183 if (unlikely(!rii.latest_ref)) {
760 /* No data nodes for this inode. */ 1184 /* No data nodes for this inode. */
761 if (f->inocache->ino != 1) { 1185 if (f->inocache->ino != 1) {
762 JFFS2_WARNING("no data nodes found for ino #%u\n", f->inocache->ino); 1186 JFFS2_WARNING("no data nodes found for ino #%u\n", f->inocache->ino);
763 if (!fd_list) { 1187 if (!rii.fds) {
764 if (f->inocache->state == INO_STATE_READING) 1188 if (f->inocache->state == INO_STATE_READING)
765 jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); 1189 jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT);
766 return -EIO; 1190 return -EIO;
@@ -778,7 +1202,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
778 return 0; 1202 return 0;
779 } 1203 }
780 1204
781 ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(*latest_node), &retlen, (void *)latest_node); 1205 ret = jffs2_flash_read(c, ref_offset(rii.latest_ref), sizeof(*latest_node), &retlen, (void *)latest_node);
782 if (ret || retlen != sizeof(*latest_node)) { 1206 if (ret || retlen != sizeof(*latest_node)) {
783 JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n", 1207 JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n",
784 ret, retlen, sizeof(*latest_node)); 1208 ret, retlen, sizeof(*latest_node));
@@ -791,7 +1215,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
791 crc = crc32(0, latest_node, sizeof(*latest_node)-8); 1215 crc = crc32(0, latest_node, sizeof(*latest_node)-8);
792 if (crc != je32_to_cpu(latest_node->node_crc)) { 1216 if (crc != je32_to_cpu(latest_node->node_crc)) {
793 JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n", 1217 JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n",
794 f->inocache->ino, ref_offset(fn->raw)); 1218 f->inocache->ino, ref_offset(rii.latest_ref));
795 up(&f->sem); 1219 up(&f->sem);
796 jffs2_do_clear_inode(c, f); 1220 jffs2_do_clear_inode(c, f);
797 return -EIO; 1221 return -EIO;
@@ -799,17 +1223,22 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
799 1223
800 switch(jemode_to_cpu(latest_node->mode) & S_IFMT) { 1224 switch(jemode_to_cpu(latest_node->mode) & S_IFMT) {
801 case S_IFDIR: 1225 case S_IFDIR:
802 if (mctime_ver > je32_to_cpu(latest_node->version)) { 1226 if (rii.mctime_ver > je32_to_cpu(latest_node->version)) {
803 /* The times in the latest_node are actually older than 1227 /* The times in the latest_node are actually older than
804 mctime in the latest dirent. Cheat. */ 1228 mctime in the latest dirent. Cheat. */
805 latest_node->ctime = latest_node->mtime = cpu_to_je32(latest_mctime); 1229 latest_node->ctime = latest_node->mtime = cpu_to_je32(rii.latest_mctime);
806 } 1230 }
807 break; 1231 break;
808 1232
809 1233
810 case S_IFREG: 1234 case S_IFREG:
811 /* If it was a regular file, truncate it to the latest node's isize */ 1235 /* If it was a regular file, truncate it to the latest node's isize */
812 jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize)); 1236 new_size = jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize));
1237 if (new_size != je32_to_cpu(latest_node->isize)) {
1238 JFFS2_WARNING("Truncating ino #%u to %d bytes failed because it only had %d bytes to start with!\n",
1239 f->inocache->ino, je32_to_cpu(latest_node->isize), new_size);
1240 latest_node->isize = cpu_to_je32(new_size);
1241 }
813 break; 1242 break;
814 1243
815 case S_IFLNK: 1244 case S_IFLNK:
@@ -832,7 +1261,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
832 return -ENOMEM; 1261 return -ENOMEM;
833 } 1262 }
834 1263
835 ret = jffs2_flash_read(c, ref_offset(fn->raw) + sizeof(*latest_node), 1264 ret = jffs2_flash_read(c, ref_offset(rii.latest_ref) + sizeof(*latest_node),
836 je32_to_cpu(latest_node->csize), &retlen, (char *)f->target); 1265 je32_to_cpu(latest_node->csize), &retlen, (char *)f->target);
837 1266
838 if (ret || retlen != je32_to_cpu(latest_node->csize)) { 1267 if (ret || retlen != je32_to_cpu(latest_node->csize)) {
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 7fb45bd4915c..2a1c976c7924 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -1,15 +1,14 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by David Woodhouse <dwmw2@infradead.org> 6 * Created by David Woodhouse <dwmw2@infradead.org>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: scan.c,v 1.125 2005/09/30 13:59:13 dedekind Exp $
11 *
12 */ 10 */
11
13#include <linux/kernel.h> 12#include <linux/kernel.h>
14#include <linux/sched.h> 13#include <linux/sched.h>
15#include <linux/slab.h> 14#include <linux/slab.h>
@@ -636,16 +635,17 @@ scan_more:
636 635
637 if (*(uint32_t *)(&buf[ofs-buf_ofs]) == 0xffffffff) { 636 if (*(uint32_t *)(&buf[ofs-buf_ofs]) == 0xffffffff) {
638 uint32_t inbuf_ofs; 637 uint32_t inbuf_ofs;
639 uint32_t empty_start; 638 uint32_t empty_start, scan_end;
640 639
641 empty_start = ofs; 640 empty_start = ofs;
642 ofs += 4; 641 ofs += 4;
642 scan_end = min_t(uint32_t, EMPTY_SCAN_SIZE(c->sector_size)/8, buf_len);
643 643
644 D1(printk(KERN_DEBUG "Found empty flash at 0x%08x\n", ofs)); 644 D1(printk(KERN_DEBUG "Found empty flash at 0x%08x\n", ofs));
645 more_empty: 645 more_empty:
646 inbuf_ofs = ofs - buf_ofs; 646 inbuf_ofs = ofs - buf_ofs;
647 while (inbuf_ofs < buf_len) { 647 while (inbuf_ofs < scan_end) {
648 if (*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff) { 648 if (unlikely(*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff)) {
649 printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x\n", 649 printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x\n",
650 empty_start, ofs); 650 empty_start, ofs);
651 if ((err = jffs2_scan_dirty_space(c, jeb, ofs-empty_start))) 651 if ((err = jffs2_scan_dirty_space(c, jeb, ofs-empty_start)))
@@ -666,7 +666,11 @@ scan_more:
666 D1(printk(KERN_DEBUG "%d bytes at start of block seems clean... assuming all clean\n", EMPTY_SCAN_SIZE(c->sector_size))); 666 D1(printk(KERN_DEBUG "%d bytes at start of block seems clean... assuming all clean\n", EMPTY_SCAN_SIZE(c->sector_size)));
667 return BLK_STATE_CLEANMARKER; 667 return BLK_STATE_CLEANMARKER;
668 } 668 }
669 669 if (!buf_size && (scan_end != buf_len)) {/* XIP/point case */
670 scan_end = buf_len;
671 goto more_empty;
672 }
673
670 /* See how much more there is to read in this eraseblock... */ 674 /* See how much more there is to read in this eraseblock... */
671 buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); 675 buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
672 if (!buf_len) { 676 if (!buf_len) {
@@ -676,6 +680,8 @@ scan_more:
676 empty_start)); 680 empty_start));
677 break; 681 break;
678 } 682 }
683 /* point never reaches here */
684 scan_end = buf_len;
679 D1(printk(KERN_DEBUG "Reading another 0x%x at 0x%08x\n", buf_len, ofs)); 685 D1(printk(KERN_DEBUG "Reading another 0x%x at 0x%08x\n", buf_len, ofs));
680 err = jffs2_fill_scan_buf(c, buf, ofs, buf_len); 686 err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
681 if (err) 687 if (err)
@@ -734,18 +740,8 @@ scan_more:
734 ofs += 4; 740 ofs += 4;
735 continue; 741 continue;
736 } 742 }
737 /* Due to poor choice of crc32 seed, an all-zero node will have a correct CRC */
738 if (!je32_to_cpu(node->hdr_crc) && !je16_to_cpu(node->nodetype) &&
739 !je16_to_cpu(node->magic) && !je32_to_cpu(node->totlen)) {
740 noisy_printk(&noise, "jffs2_scan_eraseblock(): All zero node header at 0x%08x.\n", ofs);
741 if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
742 return err;
743 ofs += 4;
744 continue;
745 }
746 743
747 if (ofs + je32_to_cpu(node->totlen) > 744 if (ofs + je32_to_cpu(node->totlen) > jeb->offset + c->sector_size) {
748 jeb->offset + c->sector_size) {
749 /* Eep. Node goes over the end of the erase block. */ 745 /* Eep. Node goes over the end of the erase block. */
750 printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n", 746 printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n",
751 ofs, je32_to_cpu(node->totlen)); 747 ofs, je32_to_cpu(node->totlen));
@@ -952,8 +948,7 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
952 struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s) 948 struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s)
953{ 949{
954 struct jffs2_inode_cache *ic; 950 struct jffs2_inode_cache *ic;
955 uint32_t ino = je32_to_cpu(ri->ino); 951 uint32_t crc, ino = je32_to_cpu(ri->ino);
956 int err;
957 952
958 D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", ofs)); 953 D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", ofs));
959 954
@@ -966,21 +961,22 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
966 Which means that the _full_ amount of time to get to proper write mode with GC 961 Which means that the _full_ amount of time to get to proper write mode with GC
967 operational may actually be _longer_ than before. Sucks to be me. */ 962 operational may actually be _longer_ than before. Sucks to be me. */
968 963
964 /* Check the node CRC in any case. */
965 crc = crc32(0, ri, sizeof(*ri)-8);
966 if (crc != je32_to_cpu(ri->node_crc)) {
967 printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on "
968 "node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
969 ofs, je32_to_cpu(ri->node_crc), crc);
970 /*
971 * We believe totlen because the CRC on the node
972 * _header_ was OK, just the node itself failed.
973 */
974 return jffs2_scan_dirty_space(c, jeb,
975 PAD(je32_to_cpu(ri->totlen)));
976 }
977
969 ic = jffs2_get_ino_cache(c, ino); 978 ic = jffs2_get_ino_cache(c, ino);
970 if (!ic) { 979 if (!ic) {
971 /* Inocache get failed. Either we read a bogus ino# or it's just genuinely the
972 first node we found for this inode. Do a CRC check to protect against the former
973 case */
974 uint32_t crc = crc32(0, ri, sizeof(*ri)-8);
975
976 if (crc != je32_to_cpu(ri->node_crc)) {
977 printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
978 ofs, je32_to_cpu(ri->node_crc), crc);
979 /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */
980 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(ri->totlen)))))
981 return err;
982 return 0;
983 }
984 ic = jffs2_scan_make_ino_cache(c, ino); 980 ic = jffs2_scan_make_ino_cache(c, ino);
985 if (!ic) 981 if (!ic)
986 return -ENOMEM; 982 return -ENOMEM;
diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c
index 52a9894a6364..bc9f6ba10823 100644
--- a/fs/jffs2/security.c
+++ b/fs/jffs2/security.c
@@ -1,13 +1,14 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2006 NEC Corporation 4 * Copyright © 2006 NEC Corporation
5 * 5 *
6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> 6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 */ 10 */
11
11#include <linux/kernel.h> 12#include <linux/kernel.h>
12#include <linux/slab.h> 13#include <linux/slab.h>
13#include <linux/fs.h> 14#include <linux/fs.h>
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index 30f888414ce7..d828b296392a 100644
--- a/fs/jffs2/summary.c
+++ b/fs/jffs2/summary.c
@@ -1,16 +1,14 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>, 4 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
5 * Zoltan Sogor <weth@inf.u-szeged.hu>, 5 * Zoltan Sogor <weth@inf.u-szeged.hu>,
6 * Patrik Kluba <pajko@halom.u-szeged.hu>, 6 * Patrik Kluba <pajko@halom.u-szeged.hu>,
7 * University of Szeged, Hungary 7 * University of Szeged, Hungary
8 * 2006 KaiGai Kohei <kaigai@ak.jp.nec.com> 8 * 2006 KaiGai Kohei <kaigai@ak.jp.nec.com>
9 * 9 *
10 * For licensing information, see the file 'LICENCE' in this directory. 10 * For licensing information, see the file 'LICENCE' in this directory.
11 * 11 *
12 * $Id: summary.c,v 1.4 2005/09/26 11:37:21 havasi Exp $
13 *
14 */ 12 */
15 13
16#include <linux/kernel.h> 14#include <linux/kernel.h>
diff --git a/fs/jffs2/summary.h b/fs/jffs2/summary.h
index 6bf1f6aa4552..0c6669e21390 100644
--- a/fs/jffs2/summary.h
+++ b/fs/jffs2/summary.h
@@ -1,15 +1,13 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>, 4 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
5 * Zoltan Sogor <weth@inf.u-szeged.hu>, 5 * Zoltan Sogor <weth@inf.u-szeged.hu>,
6 * Patrik Kluba <pajko@halom.u-szeged.hu>, 6 * Patrik Kluba <pajko@halom.u-szeged.hu>,
7 * University of Szeged, Hungary 7 * University of Szeged, Hungary
8 * 8 *
9 * For licensing information, see the file 'LICENCE' in this directory. 9 * For licensing information, see the file 'LICENCE' in this directory.
10 * 10 *
11 * $Id: summary.h,v 1.2 2005/09/26 11:37:21 havasi Exp $
12 *
13 */ 11 */
14 12
15#ifndef JFFS2_SUMMARY_H 13#ifndef JFFS2_SUMMARY_H
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index cc7e8e71ad46..e51164a8a8d4 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -1,14 +1,12 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by David Woodhouse <dwmw2@infradead.org> 6 * Created by David Woodhouse <dwmw2@infradead.org>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: super.c,v 1.110 2005/11/07 11:14:42 gleixner Exp $
11 *
12 */ 10 */
13 11
14#include <linux/kernel.h> 12#include <linux/kernel.h>
@@ -347,7 +345,7 @@ static int __init init_jffs2_fs(void)
347#ifdef CONFIG_JFFS2_SUMMARY 345#ifdef CONFIG_JFFS2_SUMMARY
348 " (SUMMARY) " 346 " (SUMMARY) "
349#endif 347#endif
350 " (C) 2001-2006 Red Hat, Inc.\n"); 348 " © 2001-2006 Red Hat, Inc.\n");
351 349
352 jffs2_inode_cachep = kmem_cache_create("jffs2_i", 350 jffs2_inode_cachep = kmem_cache_create("jffs2_i",
353 sizeof(struct jffs2_inode_info), 351 sizeof(struct jffs2_inode_info),
diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c
index 7e4882c8a7ed..b7339c3b6ad9 100644
--- a/fs/jffs2/symlink.c
+++ b/fs/jffs2/symlink.c
@@ -1,17 +1,14 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001, 2002 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by David Woodhouse <dwmw2@infradead.org> 6 * Created by David Woodhouse <dwmw2@infradead.org>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: symlink.c,v 1.19 2005/11/07 11:14:42 gleixner Exp $
11 *
12 */ 10 */
13 11
14
15#include <linux/kernel.h> 12#include <linux/kernel.h>
16#include <linux/slab.h> 13#include <linux/slab.h>
17#include <linux/fs.h> 14#include <linux/fs.h>
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index ab86031b3c07..c556e85a565c 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -1,16 +1,14 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * Copyright (C) 2004 Thomas Gleixner <tglx@linutronix.de> 5 * Copyright © 2004 Thomas Gleixner <tglx@linutronix.de>
6 * 6 *
7 * Created by David Woodhouse <dwmw2@infradead.org> 7 * Created by David Woodhouse <dwmw2@infradead.org>
8 * Modified debugged and enhanced by Thomas Gleixner <tglx@linutronix.de> 8 * Modified debugged and enhanced by Thomas Gleixner <tglx@linutronix.de>
9 * 9 *
10 * For licensing information, see the file 'LICENCE' in this directory. 10 * For licensing information, see the file 'LICENCE' in this directory.
11 * 11 *
12 * $Id: wbuf.c,v 1.100 2005/09/30 13:59:13 dedekind Exp $
13 *
14 */ 12 */
15 13
16#include <linux/kernel.h> 14#include <linux/kernel.h>
@@ -345,6 +343,9 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
345 return; 343 return;
346 } 344 }
347 345
346 /* The summary is not recovered, so it must be disabled for this erase block */
347 jffs2_sum_disable_collecting(c->summary);
348
348 ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, nr_refile); 349 ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, nr_refile);
349 if (ret) { 350 if (ret) {
350 printk(KERN_WARNING "Failed to allocate node refs for wbuf recovery. Data loss ensues.\n"); 351 printk(KERN_WARNING "Failed to allocate node refs for wbuf recovery. Data loss ensues.\n");
@@ -967,9 +968,9 @@ exit:
967 968
968static const struct jffs2_unknown_node oob_cleanmarker = 969static const struct jffs2_unknown_node oob_cleanmarker =
969{ 970{
970 .magic = cpu_to_je16(JFFS2_MAGIC_BITMASK), 971 .magic = constant_cpu_to_je16(JFFS2_MAGIC_BITMASK),
971 .nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER), 972 .nodetype = constant_cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER),
972 .totlen = cpu_to_je32(8) 973 .totlen = constant_cpu_to_je32(8)
973}; 974};
974 975
975/* 976/*
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c
index 67176792e138..c9fe0ab3a329 100644
--- a/fs/jffs2/write.c
+++ b/fs/jffs2/write.c
@@ -1,14 +1,12 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by David Woodhouse <dwmw2@infradead.org> 6 * Created by David Woodhouse <dwmw2@infradead.org>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: write.c,v 1.97 2005/11/07 11:14:42 gleixner Exp $
11 *
12 */ 10 */
13 11
14#include <linux/kernel.h> 12#include <linux/kernel.h>
@@ -507,8 +505,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
507 uint32_t alloclen; 505 uint32_t alloclen;
508 int ret; 506 int ret;
509 507
510 if (1 /* alternative branch needs testing */ || 508 if (!jffs2_can_mark_obsolete(c)) {
511 !jffs2_can_mark_obsolete(c)) {
512 /* We can't mark stuff obsolete on the medium. We need to write a deletion dirent */ 509 /* We can't mark stuff obsolete on the medium. We need to write a deletion dirent */
513 510
514 rd = jffs2_alloc_raw_dirent(); 511 rd = jffs2_alloc_raw_dirent();
diff --git a/fs/jffs2/writev.c b/fs/jffs2/writev.c
index c638ae1008de..b9276b11bac6 100644
--- a/fs/jffs2/writev.c
+++ b/fs/jffs2/writev.c
@@ -1,14 +1,12 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2001, 2002 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by David Woodhouse <dwmw2@infradead.org> 6 * Created by David Woodhouse <dwmw2@infradead.org>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: writev.c,v 1.8 2005/09/09 15:11:58 havasi Exp $
11 *
12 */ 10 */
13 11
14#include <linux/kernel.h> 12#include <linux/kernel.h>
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
index 4bb3f1897330..78fc08893a6c 100644
--- a/fs/jffs2/xattr.c
+++ b/fs/jffs2/xattr.c
@@ -1,13 +1,14 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2006 NEC Corporation 4 * Copyright © 2006 NEC Corporation
5 * 5 *
6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> 6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 */ 10 */
11
11#include <linux/kernel.h> 12#include <linux/kernel.h>
12#include <linux/slab.h> 13#include <linux/slab.h>
13#include <linux/fs.h> 14#include <linux/fs.h>
diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h
index 06a5c69dcf8b..3b0ff2925937 100644
--- a/fs/jffs2/xattr.h
+++ b/fs/jffs2/xattr.h
@@ -1,13 +1,14 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2006 NEC Corporation 4 * Copyright © 2006 NEC Corporation
5 * 5 *
6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> 6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 */ 10 */
11
11#ifndef _JFFS2_FS_XATTR_H_ 12#ifndef _JFFS2_FS_XATTR_H_
12#define _JFFS2_FS_XATTR_H_ 13#define _JFFS2_FS_XATTR_H_
13 14
diff --git a/fs/jffs2/xattr_trusted.c b/fs/jffs2/xattr_trusted.c
index ed046e19dbfa..8ec5765ef348 100644
--- a/fs/jffs2/xattr_trusted.c
+++ b/fs/jffs2/xattr_trusted.c
@@ -1,13 +1,14 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2006 NEC Corporation 4 * Copyright © 2006 NEC Corporation
5 * 5 *
6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> 6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 */ 10 */
11
11#include <linux/kernel.h> 12#include <linux/kernel.h>
12#include <linux/fs.h> 13#include <linux/fs.h>
13#include <linux/jffs2.h> 14#include <linux/jffs2.h>
diff --git a/fs/jffs2/xattr_user.c b/fs/jffs2/xattr_user.c
index 2f8e9aa01ea0..40942bc516bb 100644
--- a/fs/jffs2/xattr_user.c
+++ b/fs/jffs2/xattr_user.c
@@ -1,13 +1,14 @@
1/* 1/*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright (C) 2006 NEC Corporation 4 * Copyright © 2006 NEC Corporation
5 * 5 *
6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> 6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 */ 10 */
11
11#include <linux/kernel.h> 12#include <linux/kernel.h>
12#include <linux/fs.h> 13#include <linux/fs.h>
13#include <linux/jffs2.h> 14#include <linux/jffs2.h>
diff --git a/include/linux/mtd/iflash.h b/include/linux/mtd/iflash.h
deleted file mode 100644
index 9aa5b4f02666..000000000000
--- a/include/linux/mtd/iflash.h
+++ /dev/null
@@ -1,98 +0,0 @@
1/* $Id: iflash.h,v 1.2 2000/11/13 18:01:54 dwmw2 Exp $ */
2
3#ifndef __MTD_IFLASH_H__
4#define __MTD_IFLASH_H__
5
6/* Extended CIS registers for Series 2 and 2+ cards */
7/* The registers are all offsets from 0x4000 */
8#define CISREG_CSR 0x0100
9#define CISREG_WP 0x0104
10#define CISREG_RDYBSY 0x0140
11
12/* Extended CIS registers for Series 2 cards */
13#define CISREG_SLEEP 0x0118
14#define CISREG_RDY_MASK 0x0120
15#define CISREG_RDY_STATUS 0x0130
16
17/* Extended CIS registers for Series 2+ cards */
18#define CISREG_VCR 0x010c
19
20/* Card Status Register */
21#define CSR_SRESET 0x20 /* Soft reset */
22#define CSR_CMWP 0x10 /* Common memory write protect */
23#define CSR_PWRDOWN 0x08 /* Power down status */
24#define CSR_CISWP 0x04 /* Common memory CIS WP */
25#define CSR_WP 0x02 /* Mechanical write protect */
26#define CSR_READY 0x01 /* Ready/busy status */
27
28/* Write Protection Register */
29#define WP_BLKEN 0x04 /* Enable block locking */
30#define WP_CMWP 0x02 /* Common memory write protect */
31#define WP_CISWP 0x01 /* Common memory CIS WP */
32
33/* Voltage Control Register */
34#define VCR_VCC_LEVEL 0x80 /* 0 = 5V, 1 = 3.3V */
35#define VCR_VPP_VALID 0x02 /* Vpp Valid */
36#define VCR_VPP_GEN 0x01 /* Integrated Vpp generator */
37
38/* Ready/Busy Mode Register */
39#define RDYBSY_RACK 0x02 /* Ready acknowledge */
40#define RDYBSY_MODE 0x01 /* 1 = high performance */
41
42#define LOW(x) ((x) & 0xff)
43
44/* 28F008SA-Compatible Command Set */
45#define IF_READ_ARRAY 0xffff
46#define IF_INTEL_ID 0x9090
47#define IF_READ_CSR 0x7070
48#define IF_CLEAR_CSR 0x5050
49#define IF_WRITE 0x4040
50#define IF_BLOCK_ERASE 0x2020
51#define IF_ERASE_SUSPEND 0xb0b0
52#define IF_CONFIRM 0xd0d0
53
54/* 28F016SA Performance Enhancement Commands */
55#define IF_READ_PAGE 0x7575
56#define IF_PAGE_SWAP 0x7272
57#define IF_SINGLE_LOAD 0x7474
58#define IF_SEQ_LOAD 0xe0e0
59#define IF_PAGE_WRITE 0x0c0c
60#define IF_RDY_MODE 0x9696
61#define IF_RDY_LEVEL 0x0101
62#define IF_RDY_PULSE_WRITE 0x0202
63#define IF_RDY_PULSE_ERASE 0x0303
64#define IF_RDY_DISABLE 0x0404
65#define IF_LOCK_BLOCK 0x7777
66#define IF_UPLOAD_STATUS 0x9797
67#define IF_READ_ESR 0x7171
68#define IF_ERASE_UNLOCKED 0xa7a7
69#define IF_SLEEP 0xf0f0
70#define IF_ABORT 0x8080
71#define IF_UPLOAD_DEVINFO 0x9999
72
73/* Definitions for Compatible Status Register */
74#define CSR_WR_READY 0x8080 /* Write state machine status */
75#define CSR_ERA_SUSPEND 0x4040 /* Erase suspend status */
76#define CSR_ERA_ERR 0x2020 /* Erase status */
77#define CSR_WR_ERR 0x1010 /* Data write status */
78#define CSR_VPP_LOW 0x0808 /* Vpp status */
79
80/* Definitions for Global Status Register */
81#define GSR_WR_READY 0x8080 /* Write state machine status */
82#define GSR_OP_SUSPEND 0x4040 /* Operation suspend status */
83#define GSR_OP_ERR 0x2020 /* Device operation status */
84#define GSR_SLEEP 0x1010 /* Device sleep status */
85#define GSR_QUEUE_FULL 0x0808 /* Queue status */
86#define GSR_PAGE_AVAIL 0x0404 /* Page buffer available status */
87#define GSR_PAGE_READY 0x0202 /* Page buffer status */
88#define GSR_PAGE_SELECT 0x0101 /* Page buffer select status */
89
90/* Definitions for Block Status Register */
91#define BSR_READY 0x8080 /* Block status */
92#define BSR_UNLOCK 0x4040 /* Block lock status */
93#define BSR_FAILED 0x2020 /* Block operation status */
94#define BSR_ABORTED 0x1010 /* Operation abort status */
95#define BSR_QUEUE_FULL 0x0808 /* Queue status */
96#define BSR_VPP_LOW 0x0404 /* Vpp status */
97
98#endif /* __MTD_IFLASH_H__ */
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 3d956c3abb31..45d482ce8397 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -53,6 +53,7 @@ struct mtd_erase_region_info {
53 u_int32_t offset; /* At which this region starts, from the beginning of the MTD */ 53 u_int32_t offset; /* At which this region starts, from the beginning of the MTD */
54 u_int32_t erasesize; /* For this region */ 54 u_int32_t erasesize; /* For this region */
55 u_int32_t numblocks; /* Number of blocks of erasesize in this region */ 55 u_int32_t numblocks; /* Number of blocks of erasesize in this region */
56 unsigned long *lockmap; /* If keeping bitmap of locks */
56}; 57};
57 58
58/* 59/*
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 97523887fe5d..cf197ad62da6 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -431,6 +431,7 @@ struct nand_chip {
431#define NAND_MFR_RENESAS 0x07 431#define NAND_MFR_RENESAS 0x07
432#define NAND_MFR_STMICRO 0x20 432#define NAND_MFR_STMICRO 0x20
433#define NAND_MFR_HYNIX 0xad 433#define NAND_MFR_HYNIX 0xad
434#define NAND_MFR_MICRON 0x2c
434 435
435/** 436/**
436 * struct nand_flash_dev - NAND Flash Device ID Structure 437 * struct nand_flash_dev - NAND Flash Device ID Structure