Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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
...

+2677 -1723
+12 -18
drivers/mtd/Kconfig
··· 1 1 # $Id: Kconfig,v 1.11 2005/11/07 11:14:19 gleixner Exp $ 2 2 3 - menu "Memory Technology Devices (MTD)" 4 - 5 - config MTD 3 + menuconfig MTD 6 4 tristate "Memory Technology Device (MTD) support" 7 5 help 8 6 Memory Technology Devices are flash, RAM and similar chips, often ··· 11 13 them. It will also allow you to select individual drivers for 12 14 particular hardware and users of MTD devices. If unsure, say N. 13 15 16 + if MTD 17 + 14 18 config MTD_DEBUG 15 19 bool "Debugging" 16 - depends on MTD 17 20 help 18 21 This turns on low-level debugging for the entire MTD sub-system. 19 22 Normally, you should say 'N'. ··· 28 29 29 30 config MTD_CONCAT 30 31 tristate "MTD concatenating support" 31 - depends on MTD 32 32 help 33 33 Support for concatenating several MTD devices into a single 34 34 (virtual) one. This allows you to have -for example- a JFFS(2) ··· 36 38 37 39 config MTD_PARTITIONS 38 40 bool "MTD partitioning support" 39 - depends on MTD 40 41 help 41 42 If you have a device which needs to divide its flash chip(s) up 42 43 into multiple 'partitions', each of which appears to the user as ··· 150 153 'armflash' map driver (CONFIG_MTD_ARMFLASH) does this, for example. 151 154 152 155 comment "User Modules And Translation Layers" 153 - depends on MTD 154 156 155 157 config MTD_CHAR 156 158 tristate "Direct char device access to MTD devices" 157 - depends on MTD 158 159 help 159 160 This provides a character device for each MTD device present in 160 161 the system, allowing the user to read and write directly to the ··· 161 166 162 167 config MTD_BLKDEVS 163 168 tristate "Common interface to block layer for MTD 'translation layers'" 164 - depends on MTD && BLOCK 169 + depends on BLOCK 165 170 default n 166 171 167 172 config MTD_BLOCK 168 173 tristate "Caching block device access to MTD devices" 169 - depends on MTD && BLOCK 174 + depends on BLOCK 170 175 select MTD_BLKDEVS 171 176 ---help--- 172 177 Although most flash chips have an erase size too large to be useful ··· 189 194 190 195 config MTD_BLOCK_RO 191 196 tristate "Readonly block device access to MTD devices" 192 - depends on MTD_BLOCK!=y && MTD && BLOCK 197 + depends on MTD_BLOCK!=y && BLOCK 193 198 select MTD_BLKDEVS 194 199 help 195 200 This allows you to mount read-only file systems (such as cramfs) ··· 201 206 202 207 config FTL 203 208 tristate "FTL (Flash Translation Layer) support" 204 - depends on MTD && BLOCK 209 + depends on BLOCK 205 210 select MTD_BLKDEVS 206 211 ---help--- 207 212 This provides support for the original Flash Translation Layer which ··· 218 223 219 224 config NFTL 220 225 tristate "NFTL (NAND Flash Translation Layer) support" 221 - depends on MTD && BLOCK 226 + depends on BLOCK 222 227 select MTD_BLKDEVS 223 228 ---help--- 224 229 This provides support for the NAND Flash Translation Layer which is ··· 242 247 243 248 config INFTL 244 249 tristate "INFTL (Inverse NAND Flash Translation Layer) support" 245 - depends on MTD && BLOCK 250 + depends on BLOCK 246 251 select MTD_BLKDEVS 247 252 ---help--- 248 253 This provides support for the Inverse NAND Flash Translation ··· 260 265 261 266 config RFD_FTL 262 267 tristate "Resident Flash Disk (Flash Translation Layer) support" 263 - depends on MTD && BLOCK 268 + depends on BLOCK 264 269 select MTD_BLKDEVS 265 270 ---help--- 266 271 This provides support for the flash translation layer known ··· 271 276 272 277 config SSFDC 273 278 tristate "NAND SSFDC (SmartMedia) read only translation layer" 274 - depends on MTD && BLOCK 279 + depends on BLOCK 275 280 select MTD_BLKDEVS 276 281 help 277 282 This enables read only access to SmartMedia formatted NAND ··· 289 294 290 295 source "drivers/mtd/ubi/Kconfig" 291 296 292 - endmenu 293 - 297 + endif # MTD
+3 -9
drivers/mtd/chips/Kconfig
··· 6 6 7 7 config MTD_CFI 8 8 tristate "Detect flash chips by Common Flash Interface (CFI) probe" 9 - depends on MTD 10 9 select MTD_GEN_PROBE 11 10 help 12 11 The Common Flash Interface specification was developed by Intel, ··· 17 18 18 19 config MTD_JEDECPROBE 19 20 tristate "Detect non-CFI AMD/JEDEC-compatible flash chips" 20 - depends on MTD 21 21 select MTD_GEN_PROBE 22 22 help 23 23 This option enables JEDEC-style probing of flash chips which are not ··· 211 213 212 214 config MTD_RAM 213 215 tristate "Support for RAM chips in bus mapping" 214 - depends on MTD 215 216 help 216 217 This option enables basic support for RAM chips accessed through 217 218 a bus mapping driver. 218 219 219 220 config MTD_ROM 220 221 tristate "Support for ROM chips in bus mapping" 221 - depends on MTD 222 222 help 223 223 This option enables basic support for ROM chips accessed through 224 224 a bus mapping driver. 225 225 226 226 config MTD_ABSENT 227 227 tristate "Support for absent chips in bus mapping" 228 - depends on MTD 229 228 help 230 229 This option enables support for a dummy probing driver used to 231 230 allocated placeholder MTD devices on systems that have socketed ··· 232 237 with this driver will return -ENODEV upon access. 233 238 234 239 config MTD_OBSOLETE_CHIPS 235 - depends on MTD 236 240 bool "Older (theoretically obsoleted now) drivers for non-CFI chips" 237 241 help 238 242 This option does not enable any code directly, but will allow you to ··· 244 250 245 251 config MTD_AMDSTD 246 252 tristate "AMD compatible flash chip support (non-CFI)" 247 - depends on MTD && MTD_OBSOLETE_CHIPS && BROKEN 253 + depends on MTD_OBSOLETE_CHIPS && BROKEN 248 254 help 249 255 This option enables support for flash chips using AMD-compatible 250 256 commands, including some which are not CFI-compatible and hence ··· 254 260 255 261 config MTD_SHARP 256 262 tristate "pre-CFI Sharp chip support" 257 - depends on MTD && MTD_OBSOLETE_CHIPS 263 + depends on MTD_OBSOLETE_CHIPS 258 264 help 259 265 This option enables support for flash chips using Sharp-compatible 260 266 commands, including some which are not CFI-compatible and hence ··· 262 268 263 269 config MTD_JEDEC 264 270 tristate "JEDEC device support" 265 - depends on MTD && MTD_OBSOLETE_CHIPS && BROKEN 271 + depends on MTD_OBSOLETE_CHIPS && BROKEN 266 272 help 267 273 Enable older JEDEC flash interface devices for self 268 274 programming flash. It is commonly used in older AMD chips. It is
+90 -3
drivers/mtd/chips/cfi_cmdset_0001.c
··· 15 15 * - optimized write buffer method 16 16 * 02/05/2002 Christopher Hoover <ch@hpl.hp.com>/<ch@murgatroid.com> 17 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 22 #include <linux/module.h> ··· 32 30 #include <linux/delay.h> 33 31 #include <linux/interrupt.h> 34 32 #include <linux/reboot.h> 33 + #include <linux/bitmap.h> 35 34 #include <linux/mtd/xip.h> 36 35 #include <linux/mtd/map.h> 37 36 #include <linux/mtd/mtd.h> ··· 223 220 } 224 221 } 225 222 223 + /* 224 + * Some chips power-up with all sectors locked by default. 225 + */ 226 + static void fixup_use_powerup_lock(struct mtd_info *mtd, void *param) 227 + { 228 + printk(KERN_INFO "Using auto-unlock on power-up/resume\n" ); 229 + mtd->flags |= MTD_STUPID_LOCK; 230 + } 231 + 226 232 static struct cfi_fixup cfi_fixup_table[] = { 227 233 #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE 228 234 { CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash, NULL }, ··· 244 232 #endif 245 233 { CFI_MFR_ST, 0x00ba, /* M28W320CT */ fixup_st_m28w320ct, NULL }, 246 234 { CFI_MFR_ST, 0x00bb, /* M28W320CB */ fixup_st_m28w320cb, NULL }, 235 + { MANUFACTURER_INTEL, 0x891c, fixup_use_powerup_lock, NULL, }, 247 236 { 0, 0, NULL, NULL } 248 237 }; 249 238 ··· 473 460 mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].offset = (j*devsize)+offset; 474 461 mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].erasesize = ersize; 475 462 mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].numblocks = ernum; 463 + mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].lockmap = kmalloc(ernum / 8 + 1, GFP_KERNEL); 476 464 } 477 465 offset += (ersize * ernum); 478 466 } ··· 1839 1825 } 1840 1826 } 1841 1827 1842 - #ifdef DEBUG_LOCK_BITS 1843 - static int __xipram do_printlockstatus_oneblock(struct map_info *map, 1828 + static int __xipram do_getlockstatus_oneblock(struct map_info *map, 1844 1829 struct flchip *chip, 1845 1830 unsigned long adr, 1846 1831 int len, void *thunk) ··· 1853 1840 chip->state = FL_JEDEC_QUERY; 1854 1841 status = cfi_read_query(map, adr+(2*ofs_factor)); 1855 1842 xip_enable(map, chip, 0); 1843 + return status; 1844 + } 1845 + 1846 + #ifdef DEBUG_LOCK_BITS 1847 + static int __xipram do_printlockstatus_oneblock(struct map_info *map, 1848 + struct flchip *chip, 1849 + unsigned long adr, 1850 + int len, void *thunk) 1851 + { 1856 1852 printk(KERN_DEBUG "block status register for 0x%08lx is %x\n", 1857 - adr, status); 1853 + adr, do_getlockstatus_oneblock(map, chip, adr, len, thunk)); 1858 1854 return 0; 1859 1855 } 1860 1856 #endif ··· 2238 2216 2239 2217 #endif 2240 2218 2219 + static void cfi_intelext_save_locks(struct mtd_info *mtd) 2220 + { 2221 + struct mtd_erase_region_info *region; 2222 + int block, status, i; 2223 + unsigned long adr; 2224 + size_t len; 2225 + 2226 + for (i = 0; i < mtd->numeraseregions; i++) { 2227 + region = &mtd->eraseregions[i]; 2228 + if (!region->lockmap) 2229 + continue; 2230 + 2231 + for (block = 0; block < region->numblocks; block++){ 2232 + len = region->erasesize; 2233 + adr = region->offset + block * len; 2234 + 2235 + status = cfi_varsize_frob(mtd, 2236 + do_getlockstatus_oneblock, adr, len, 0); 2237 + if (status) 2238 + set_bit(block, region->lockmap); 2239 + else 2240 + clear_bit(block, region->lockmap); 2241 + } 2242 + } 2243 + } 2244 + 2241 2245 static int cfi_intelext_suspend(struct mtd_info *mtd) 2242 2246 { 2243 2247 struct map_info *map = mtd->priv; 2244 2248 struct cfi_private *cfi = map->fldrv_priv; 2249 + struct cfi_pri_intelext *extp = cfi->cmdset_priv; 2245 2250 int i; 2246 2251 struct flchip *chip; 2247 2252 int ret = 0; 2253 + 2254 + if ((mtd->flags & MTD_STUPID_LOCK) 2255 + && extp && (extp->FeatureSupport & (1 << 5))) 2256 + cfi_intelext_save_locks(mtd); 2248 2257 2249 2258 for (i=0; !ret && i<cfi->numchips; i++) { 2250 2259 chip = &cfi->chips[i]; ··· 2338 2285 return ret; 2339 2286 } 2340 2287 2288 + static void cfi_intelext_restore_locks(struct mtd_info *mtd) 2289 + { 2290 + struct mtd_erase_region_info *region; 2291 + int block, i; 2292 + unsigned long adr; 2293 + size_t len; 2294 + 2295 + for (i = 0; i < mtd->numeraseregions; i++) { 2296 + region = &mtd->eraseregions[i]; 2297 + if (!region->lockmap) 2298 + continue; 2299 + 2300 + for (block = 0; block < region->numblocks; block++) { 2301 + len = region->erasesize; 2302 + adr = region->offset + block * len; 2303 + 2304 + if (!test_bit(block, region->lockmap)) 2305 + cfi_intelext_unlock(mtd, adr, len); 2306 + } 2307 + } 2308 + } 2309 + 2341 2310 static void cfi_intelext_resume(struct mtd_info *mtd) 2342 2311 { 2343 2312 struct map_info *map = mtd->priv; 2344 2313 struct cfi_private *cfi = map->fldrv_priv; 2314 + struct cfi_pri_intelext *extp = cfi->cmdset_priv; 2345 2315 int i; 2346 2316 struct flchip *chip; 2347 2317 ··· 2383 2307 2384 2308 spin_unlock(chip->mutex); 2385 2309 } 2310 + 2311 + if ((mtd->flags & MTD_STUPID_LOCK) 2312 + && extp && (extp->FeatureSupport & (1 << 5))) 2313 + cfi_intelext_restore_locks(mtd); 2386 2314 } 2387 2315 2388 2316 static int cfi_intelext_reset(struct mtd_info *mtd) ··· 2427 2347 { 2428 2348 struct map_info *map = mtd->priv; 2429 2349 struct cfi_private *cfi = map->fldrv_priv; 2350 + struct mtd_erase_region_info *region; 2351 + int i; 2430 2352 cfi_intelext_reset(mtd); 2431 2353 unregister_reboot_notifier(&mtd->reboot_notifier); 2432 2354 kfree(cfi->cmdset_priv); 2433 2355 kfree(cfi->cfiq); 2434 2356 kfree(cfi->chips[0].priv); 2435 2357 kfree(cfi); 2358 + for (i = 0; i < mtd->numeraseregions; i++) { 2359 + region = &mtd->eraseregions[i]; 2360 + if (region->lockmap) 2361 + kfree(region->lockmap); 2362 + } 2436 2363 kfree(mtd->eraseregions); 2437 2364 } 2438 2365
+2 -1
drivers/mtd/chips/fwh_lock.h
··· 65 65 return ret; 66 66 } 67 67 68 + chip->oldstate = chip->state; 68 69 chip->state = xxlt->state; 69 70 map_write(map, CMD(xxlt->val), adr); 70 71 71 72 /* Done and happy. */ 72 - chip->state = FL_READY; 73 + chip->state = chip->oldstate; 73 74 put_chip(map, chip, adr); 74 75 spin_unlock(chip->mutex); 75 76 return 0;
+14 -12
drivers/mtd/devices/Kconfig
··· 6 6 7 7 config MTD_PMC551 8 8 tristate "Ramix PMC551 PCI Mezzanine RAM card support" 9 - depends on MTD && PCI 9 + depends on PCI 10 10 ---help--- 11 11 This provides a MTD device driver for the Ramix PMC551 RAM PCI card 12 12 from Ramix Inc. <http://www.ramix.com/products/memory/pmc551.html>. ··· 40 40 41 41 config MTD_MS02NV 42 42 tristate "DEC MS02-NV NVRAM module support" 43 - depends on MTD && MACH_DECSTATION 43 + depends on MACH_DECSTATION 44 44 help 45 45 This is an MTD driver for the DEC's MS02-NV (54-20948-01) battery 46 46 backed-up NVRAM module. The module was originally meant as an NFS ··· 54 54 55 55 config MTD_DATAFLASH 56 56 tristate "Support for AT45xxx DataFlash" 57 - depends on MTD && SPI_MASTER && EXPERIMENTAL 57 + depends on SPI_MASTER && EXPERIMENTAL 58 58 help 59 59 This enables access to AT45xxx DataFlash chips, using SPI. 60 60 Sometimes DataFlash chips are packaged inside MMC-format 61 61 cards; at this writing, the MMC stack won't handle those. 62 62 63 + config 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 + 63 71 config MTD_M25P80 64 72 tristate "Support for M25 SPI Flash" 65 - depends on MTD && SPI_MASTER && EXPERIMENTAL 73 + depends on SPI_MASTER && EXPERIMENTAL 66 74 help 67 75 This enables access to ST M25P80 and similar SPI flash chips, 68 76 used for program and data storage. Set up your spi devices ··· 78 70 79 71 config MTD_SLRAM 80 72 tristate "Uncached system RAM" 81 - depends on MTD 82 73 help 83 74 If your CPU cannot cache all of the physical memory in your machine, 84 75 you can still use it for storage or swap by using this driver to ··· 85 78 86 79 config MTD_PHRAM 87 80 tristate "Physical system RAM" 88 - depends on MTD 89 81 help 90 82 This is a re-implementation of the slram driver above. 91 83 ··· 94 88 95 89 config MTD_LART 96 90 tristate "28F160xx flash driver for LART" 97 - depends on SA1100_LART && MTD 91 + depends on SA1100_LART 98 92 help 99 93 This enables the flash driver for LART. Please note that you do 100 94 not need any mapping/chip driver for LART. This one does it all ··· 102 96 103 97 config MTD_MTDRAM 104 98 tristate "Test driver using RAM" 105 - depends on MTD 106 99 help 107 100 This enables a test MTD device driver which uses vmalloc() to 108 101 provide storage. You probably want to say 'N' unless you're ··· 141 136 142 137 config MTD_BLOCK2MTD 143 138 tristate "MTD using block device" 144 - depends on MTD && BLOCK 139 + depends on BLOCK 145 140 help 146 141 This driver allows a block device to appear as an MTD. It would 147 142 generally be used in the following cases: ··· 155 150 156 151 config MTD_DOC2000 157 152 tristate "M-Systems Disk-On-Chip 2000 and Millennium (DEPRECATED)" 158 - depends on MTD 159 153 select MTD_DOCPROBE 160 154 select MTD_NAND_IDS 161 155 ---help--- ··· 177 173 178 174 config MTD_DOC2001 179 175 tristate "M-Systems Disk-On-Chip Millennium-only alternative driver (DEPRECATED)" 180 - depends on MTD 181 176 select MTD_DOCPROBE 182 177 select MTD_NAND_IDS 183 178 ---help--- ··· 198 195 199 196 config MTD_DOC2001PLUS 200 197 tristate "M-Systems Disk-On-Chip Millennium Plus" 201 - depends on MTD 202 198 select MTD_DOCPROBE 203 199 select MTD_NAND_IDS 204 200 ---help---
+1
drivers/mtd/devices/Makefile
··· 16 16 obj-$(CONFIG_MTD_LART) += lart.o 17 17 obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o 18 18 obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o 19 + obj-$(CONFIG_MTD_DATAFLASH26) += at91_dataflash26.o 19 20 obj-$(CONFIG_MTD_M25P80) += m25p80.o
+485
drivers/mtd/devices/at91_dataflash26.c
··· 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 + 46 + struct 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 */ 54 + static struct mtd_info* mtd_devices[DATAFLASH_MAX_DEVICES]; 55 + static 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. */ 62 + static struct spi_transfer_list* spi_transfer_desc; 63 + 64 + /* 65 + * Perform a SPI transfer to access the DataFlash device. 66 + */ 67 + static 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 + */ 86 + static 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 + */ 101 + static 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 + */ 154 + static 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 + */ 213 + static 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 + */ 254 + static 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); 327 + write_err: 328 + spi_release_bus(priv->spi); 329 + return ret; 330 + } 331 + 332 + /* 333 + * Initialize and register DataFlash device with MTD subsystem. 334 + */ 335 + static 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 + 387 + struct dataflash26_types { 388 + unsigned char id0; 389 + unsigned char id1; 390 + char *name; 391 + int pagesize; 392 + int nr_pages; 393 + }; 394 + 395 + struct 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 + 412 + static 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 + 448 + static 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 + 465 + static 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 + 480 + module_init(at91_dataflash26_init); 481 + module_exit(at91_dataflash26_exit); 482 + 483 + MODULE_LICENSE("GPL"); 484 + MODULE_AUTHOR("Hans J. Koch"); 485 + MODULE_DESCRIPTION("DataFlash AT26xxx driver for Atmel AT91RM9200");
+9 -58
drivers/mtd/devices/block2mtd.c
··· 40 40 static LIST_HEAD(blkmtd_device_list); 41 41 42 42 43 - #define PAGE_READAHEAD 64 44 - static void cache_readahead(struct address_space *mapping, int index) 43 + static struct page* page_read(struct address_space *mapping, int index) 45 44 { 46 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 - 89 - static 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 46 return read_cache_page(mapping, index, filler, NULL); 94 47 } 95 48 ··· 58 105 u_long *max; 59 106 60 107 while (pages) { 61 - page = page_readahead(mapping, index); 108 + page = page_read(mapping, index); 62 109 if (!page) 63 110 return -ENOMEM; 64 111 if (IS_ERR(page)) 65 112 return PTR_ERR(page); 66 113 67 - max = (u_long*)page_address(page) + PAGE_SIZE; 68 - for (p=(u_long*)page_address(page); p<max; p++) 114 + max = page_address(page) + PAGE_SIZE; 115 + for (p=page_address(page); p<max; p++) 69 116 if (*p != -1UL) { 70 117 lock_page(page); 71 118 memset(page_address(page), 0xff, PAGE_SIZE); ··· 127 174 cpylen = len; // this page 128 175 len = len - cpylen; 129 176 130 - // Get page 131 - page = page_readahead(dev->blkdev->bd_inode->i_mapping, index); 177 + page = page_read(dev->blkdev->bd_inode->i_mapping, index); 132 178 if (!page) 133 179 return -ENOMEM; 134 180 if (IS_ERR(page)) ··· 165 213 cpylen = len; // this page 166 214 len = len - cpylen; 167 215 168 - // Get page 169 - page = page_readahead(mapping, index); 216 + page = page_read(mapping, index); 170 217 if (!page) 171 218 return -ENOMEM; 172 219 if (IS_ERR(page)) ··· 259 308 /* We might not have rootfs mounted at this point. Try 260 309 to resolve the device name by other means. */ 261 310 262 - dev_t dev = name_to_dev_t(devname); 263 - if (dev != 0) { 264 - bdev = open_by_devnum(dev, FMODE_WRITE | FMODE_READ); 311 + dev_t devt = name_to_dev_t(devname); 312 + if (devt) { 313 + bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ); 265 314 } 266 315 } 267 316 #endif
+39 -8
drivers/mtd/maps/Kconfig
··· 6 6 7 7 config MTD_COMPLEX_MAPPINGS 8 8 bool "Support non-linear mappings of flash chips" 9 - depends on MTD 10 9 help 11 10 This causes the chip drivers to allow for complicated 12 11 paged mappings of flash chips. ··· 67 68 ROM driver code to communicate with chips which are mapped 68 69 physically into the CPU's memory. The mapping description here is 69 70 taken from OF device tree. 71 + 72 + config MTD_PMC_MSP_EVM 73 + tristate "CFI Flash device mapped on PMC-Sierra MSP" 74 + depends on PMC_MSP && MTD_CFI 75 + select MTD_PARTITIONS 76 + help 77 + This provides a 'mapping' driver which support the way 78 + in which user-programmable flash chips are connected on the 79 + PMC-Sierra MSP eval/demo boards 80 + 81 + choice 82 + prompt "Maximum mappable memory avialable for flash IO" 83 + depends on MTD_PMC_MSP_EVM 84 + default MSP_FLASH_MAP_LIMIT_32M 85 + 86 + config MSP_FLASH_MAP_LIMIT_32M 87 + bool "32M" 88 + 89 + endchoice 90 + 91 + config MSP_FLASH_MAP_LIMIT 92 + hex 93 + default "0x02000000" 94 + depends on MSP_FLASH_MAP_LIMIT_32M 95 + 96 + config MTD_PMC_MSP_RAMROOT 97 + tristate "Embedded RAM block device for root on PMC-Sierra MSP" 98 + depends on PMC_MSP_EMBEDDED_ROOTFS && \ 99 + (MTD_BLOCK || MTD_BLOCK_RO) && \ 100 + MTD_RAM 101 + help 102 + This provides support for the embedded root file system 103 + on PMC MSP devices. This memory is mapped as a MTD block device. 70 104 71 105 config MTD_SUN_UFLASH 72 106 tristate "Sun Microsystems userflash support" ··· 272 240 273 241 config MTD_ALCHEMY 274 242 tristate "AMD Alchemy Pb1xxx/Db1xxx/RDK MTD support" 275 - depends on SOC_AU1X00 243 + depends on SOC_AU1X00 && MTD_PARTITIONS && MTD_CFI 276 244 help 277 245 Flash memory access on AMD Alchemy Pb/Db/RDK Reference Boards 278 246 279 247 config MTD_MTX1 280 248 tristate "4G Systems MTX-1 Flash device" 281 - depends on MIPS && MIPS_MTX1 249 + depends on MIPS_MTX1 && MTD_CFI 282 250 help 283 251 Flash memory access on 4G Systems MTX-1 Board. If you have one of 284 252 these boards and would like to use the flash chips on it, say 'Y'. ··· 416 384 417 385 config MTD_OCELOT 418 386 tristate "Momenco Ocelot boot flash device" 419 - depends on MIPS && MOMENCO_OCELOT 387 + depends on MOMENCO_OCELOT 420 388 help 421 389 This enables access routines for the boot flash device and for the 422 390 NVRAM on the Momenco Ocelot board. If you have one of these boards ··· 549 517 # This needs CFI or JEDEC, depending on the cards found. 550 518 config MTD_PCI 551 519 tristate "PCI MTD driver" 552 - depends on MTD && PCI && MTD_COMPLEX_MAPPINGS 520 + depends on PCI && MTD_COMPLEX_MAPPINGS 553 521 help 554 522 Mapping for accessing flash devices on add-in cards like the Intel XScale 555 523 IQ80310 card, and the Intel EBSA285 card in blank ROM programming mode ··· 559 527 560 528 config MTD_PCMCIA 561 529 tristate "PCMCIA MTD driver" 562 - depends on MTD && PCMCIA && MTD_COMPLEX_MAPPINGS && BROKEN 530 + depends on PCMCIA && MTD_COMPLEX_MAPPINGS && BROKEN 563 531 help 564 532 Map driver for accessing PCMCIA linear flash memory cards. These 565 533 cards are usually around 4-16MiB in size. This does not include ··· 623 591 624 592 config MTD_SHARP_SL 625 593 bool "ROM mapped on Sharp SL Series" 626 - depends on MTD && ARCH_PXA 594 + depends on ARCH_PXA 627 595 help 628 596 This enables access to the flash chip on the Sharp SL Series of PDAs. 629 597 630 598 config MTD_PLATRAM 631 599 tristate "Map driver for platform device RAM (mtd-ram)" 632 - depends on MTD 633 600 select MTD_RAM 634 601 help 635 602 Map driver for RAM areas described via the platform device
+2
drivers/mtd/maps/Makefile
··· 27 27 obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o 28 28 obj-$(CONFIG_MTD_PHYSMAP) += physmap.o 29 29 obj-$(CONFIG_MTD_PHYSMAP_OF) += physmap_of.o 30 + obj-$(CONFIG_MTD_PMC_MSP_EVM) += pmcmsp-flash.o 31 + obj-$(CONFIG_MTD_PMC_MSP_RAMROOT)+= pmcmsp-ramroot.o 30 32 obj-$(CONFIG_MTD_PNC2000) += pnc2000.o 31 33 obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o 32 34 obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o
-9
drivers/mtd/maps/alchemy-flash.c
··· 1 1 /* 2 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 4 * (C) 2003, 2004 Pete Popov <ppopov@embeddedalley.com> 7 - * 8 5 */ 9 6 10 7 #include <linux/init.h> ··· 14 17 #include <linux/mtd/partitions.h> 15 18 16 19 #include <asm/io.h> 17 - 18 - #ifdef DEBUG_RW 19 - #define DBG(x...) printk(x) 20 - #else 21 - #define DBG(x...) 22 - #endif 23 20 24 21 #ifdef CONFIG_MIPS_PB1000 25 22 #define BOARD_MAP_NAME "Pb1000 Flash"
+1 -1
drivers/mtd/maps/ck804xrom.c
··· 338 338 } 339 339 return -ENXIO; 340 340 #if 0 341 - return pci_module_init(&ck804xrom_driver); 341 + return pci_register_driver(&ck804xrom_driver); 342 342 #endif 343 343 } 344 344
+2 -1
drivers/mtd/maps/plat-ram.c
··· 169 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 175 /* setup map parameters */ 175 176
+184
drivers/mtd/maps/pmcmsp-flash.c
··· 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 + 44 + static struct mtd_info **msp_flash; 45 + static struct mtd_partition **msp_parts; 46 + static struct map_info *msp_maps; 47 + static int fcnt; 48 + 49 + #define DEBUG_MARKER printk(KERN_NOTICE "%s[%d]\n",__FUNCTION__,__LINE__) 50 + 51 + int __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 + 160 + static 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 + 179 + MODULE_AUTHOR("PMC-Sierra, Inc"); 180 + MODULE_DESCRIPTION("MTD map driver for PMC-Sierra MSP boards"); 181 + MODULE_LICENSE("GPL"); 182 + 183 + module_init(init_msp_flash); 184 + module_exit(cleanup_msp_flash);
+105
drivers/mtd/maps/pmcmsp-ramroot.c
··· 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 + 42 + static struct mtd_info *rr_mtd; 43 + 44 + struct map_info rr_map = { 45 + .name = "ramroot", 46 + .bankwidth = 4, 47 + }; 48 + 49 + static 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 + 91 + static 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 + 100 + MODULE_AUTHOR("PMC-Sierra, Inc"); 101 + MODULE_DESCRIPTION("MTD map driver for embedded PMC-Sierra MSP filesystem"); 102 + MODULE_LICENSE("GPL"); 103 + 104 + module_init(init_rrmap); 105 + module_exit(cleanup_rrmap);
+10 -33
drivers/mtd/mtd_blkdevs.c
··· 20 20 #include <linux/hdreg.h> 21 21 #include <linux/init.h> 22 22 #include <linux/mutex.h> 23 + #include <linux/kthread.h> 23 24 #include <asm/uaccess.h> 24 25 25 26 static LIST_HEAD(blktrans_majors); ··· 29 28 extern struct mtd_info *mtd_table[]; 30 29 31 30 struct mtd_blkcore_priv { 32 - struct completion thread_dead; 33 - int exiting; 34 - wait_queue_head_t thread_wq; 31 + struct task_struct *thread; 35 32 struct request_queue *rq; 36 33 spinlock_t queue_lock; 37 34 }; ··· 82 83 /* we might get involved when memory gets low, so use PF_MEMALLOC */ 83 84 current->flags |= PF_MEMALLOC | PF_NOFREEZE; 84 85 85 - daemonize("%sd", tr->name); 86 - 87 - /* daemonize() doesn't do this for us since some kernel threads 88 - actually want to deal with signals. We can't just call 89 - exit_sighand() since that'll cause an oops when we finally 90 - do exit. */ 91 - spin_lock_irq(&current->sighand->siglock); 92 - sigfillset(&current->blocked); 93 - recalc_sigpending(); 94 - spin_unlock_irq(&current->sighand->siglock); 95 - 96 86 spin_lock_irq(rq->queue_lock); 97 - 98 - while (!tr->blkcore_priv->exiting) { 87 + while (!kthread_should_stop()) { 99 88 struct request *req; 100 89 struct mtd_blktrans_dev *dev; 101 90 int res = 0; 102 - DECLARE_WAITQUEUE(wait, current); 103 91 104 92 req = elv_next_request(rq); 105 93 106 94 if (!req) { 107 - add_wait_queue(&tr->blkcore_priv->thread_wq, &wait); 108 95 set_current_state(TASK_INTERRUPTIBLE); 109 - 110 96 spin_unlock_irq(rq->queue_lock); 111 - 112 97 schedule(); 113 - remove_wait_queue(&tr->blkcore_priv->thread_wq, &wait); 114 - 115 98 spin_lock_irq(rq->queue_lock); 116 - 117 99 continue; 118 100 } 119 101 ··· 113 133 } 114 134 spin_unlock_irq(rq->queue_lock); 115 135 116 - complete_and_exit(&tr->blkcore_priv->thread_dead, 0); 136 + return 0; 117 137 } 118 138 119 139 static void mtd_blktrans_request(struct request_queue *rq) 120 140 { 121 141 struct mtd_blktrans_ops *tr = rq->queuedata; 122 - wake_up(&tr->blkcore_priv->thread_wq); 142 + wake_up_process(tr->blkcore_priv->thread); 123 143 } 124 144 125 145 ··· 368 388 return ret; 369 389 } 370 390 spin_lock_init(&tr->blkcore_priv->queue_lock); 371 - init_completion(&tr->blkcore_priv->thread_dead); 372 - init_waitqueue_head(&tr->blkcore_priv->thread_wq); 373 391 374 392 tr->blkcore_priv->rq = blk_init_queue(mtd_blktrans_request, &tr->blkcore_priv->queue_lock); 375 393 if (!tr->blkcore_priv->rq) { ··· 381 403 blk_queue_hardsect_size(tr->blkcore_priv->rq, tr->blksize); 382 404 tr->blkshift = ffs(tr->blksize) - 1; 383 405 384 - ret = kernel_thread(mtd_blktrans_thread, tr, CLONE_KERNEL); 385 - if (ret < 0) { 406 + tr->blkcore_priv->thread = kthread_run(mtd_blktrans_thread, tr, 407 + "%sd", tr->name); 408 + if (IS_ERR(tr->blkcore_priv->thread)) { 386 409 blk_cleanup_queue(tr->blkcore_priv->rq); 387 410 unregister_blkdev(tr->major, tr->name); 388 411 kfree(tr->blkcore_priv); 389 412 mutex_unlock(&mtd_table_mutex); 390 - return ret; 413 + return PTR_ERR(tr->blkcore_priv->thread); 391 414 } 392 415 393 416 INIT_LIST_HEAD(&tr->devs); ··· 411 432 mutex_lock(&mtd_table_mutex); 412 433 413 434 /* Clean up the kernel thread */ 414 - tr->blkcore_priv->exiting = 1; 415 - wake_up(&tr->blkcore_priv->thread_wq); 416 - wait_for_completion(&tr->blkcore_priv->thread_dead); 435 + kthread_stop(tr->blkcore_priv->thread); 417 436 418 437 /* Remove it from the list of active majors */ 419 438 list_del(&tr->list);
+1 -1
drivers/mtd/mtdchar.c
··· 553 553 ops.datbuf = NULL; 554 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 557 return -EINVAL; 558 558 559 559 ops.oobbuf = kmalloc(buf.length, GFP_KERNEL);
+37 -26
drivers/mtd/nand/Kconfig
··· 1 1 # drivers/mtd/nand/Kconfig 2 2 # $Id: Kconfig,v 1.35 2005/11/07 11:14:30 gleixner Exp $ 3 3 4 - menu "NAND Flash Device Drivers" 5 - depends on MTD!=n 6 - 7 - config MTD_NAND 4 + menuconfig MTD_NAND 8 5 tristate "NAND Device Support" 9 6 depends on MTD 10 7 select MTD_NAND_IDS ··· 10 13 devices. For further information see 11 14 <http://www.linux-mtd.infradead.org/doc/nand.html>. 12 15 16 + if MTD_NAND 17 + 13 18 config MTD_NAND_VERIFY_WRITE 14 19 bool "Verify NAND page writes" 15 - depends on MTD_NAND 16 20 help 17 21 This adds an extra check when data is written to the flash. The 18 22 NAND flash device internally checks only bits transitioning ··· 23 25 24 26 config MTD_NAND_ECC_SMC 25 27 bool "NAND ECC Smart Media byte order" 26 - depends on MTD_NAND 27 28 default n 28 29 help 29 30 Software ECC according to the Smart Media Specification. 30 31 The original Linux implementation had byte 0 and 1 swapped. 31 32 33 + config MTD_NAND_MUSEUM_IDS 34 + bool "Enable chip ids for obsolete ancient NAND devices" 35 + depends on MTD_NAND 36 + default n 37 + help 38 + Enable this option only when your board has first generation 39 + NAND chips (page size 256 byte, erase size 4-8KiB). The IDs 40 + of these chips were reused by later, larger chips. 41 + 32 42 config MTD_NAND_AUTCPU12 33 43 tristate "SmartMediaCard on autronix autcpu12 board" 34 - depends on MTD_NAND && ARCH_AUTCPU12 44 + depends on ARCH_AUTCPU12 35 45 help 36 46 This enables the driver for the autronix autcpu12 board to 37 47 access the SmartMediaCard. 38 48 39 49 config MTD_NAND_EDB7312 40 50 tristate "Support for Cirrus Logic EBD7312 evaluation board" 41 - depends on MTD_NAND && ARCH_EDB7312 51 + depends on ARCH_EDB7312 42 52 help 43 53 This enables the driver for the Cirrus Logic EBD7312 evaluation 44 54 board to access the onboard NAND Flash. 45 55 46 56 config MTD_NAND_H1900 47 57 tristate "iPAQ H1900 flash" 48 - depends on MTD_NAND && ARCH_PXA && MTD_PARTITIONS 58 + depends on ARCH_PXA && MTD_PARTITIONS 49 59 help 50 60 This enables the driver for the iPAQ h1900 flash. 51 61 52 62 config MTD_NAND_SPIA 53 63 tristate "NAND Flash device on SPIA board" 54 - depends on ARCH_P720T && MTD_NAND 64 + depends on ARCH_P720T 55 65 help 56 66 If you had to ask, you don't have one. Say 'N'. 57 67 58 68 config MTD_NAND_AMS_DELTA 59 69 tristate "NAND Flash device on Amstrad E3" 60 - depends on MACH_AMS_DELTA && MTD_NAND 70 + depends on MACH_AMS_DELTA 61 71 help 62 72 Support for NAND flash on Amstrad E3 (Delta). 63 73 64 74 config MTD_NAND_TOTO 65 75 tristate "NAND Flash device on TOTO board" 66 - depends on ARCH_OMAP && MTD_NAND && BROKEN 76 + depends on ARCH_OMAP && BROKEN 67 77 help 68 78 Support for NAND flash on Texas Instruments Toto platform. 69 79 70 80 config MTD_NAND_TS7250 71 81 tristate "NAND Flash device on TS-7250 board" 72 - depends on MACH_TS72XX && MTD_NAND 82 + depends on MACH_TS72XX 73 83 help 74 84 Support for NAND flash on Technologic Systems TS-7250 platform. 75 85 ··· 86 80 87 81 config MTD_NAND_AU1550 88 82 tristate "Au1550/1200 NAND support" 89 - depends on (SOC_AU1200 || SOC_AU1550) && MTD_NAND 83 + depends on SOC_AU1200 || SOC_AU1550 90 84 help 91 85 This enables the driver for the NAND flash controller on the 92 86 AMD/Alchemy 1550 SOC. 93 87 94 88 config MTD_NAND_RTC_FROM4 95 89 tristate "Renesas Flash ROM 4-slot interface board (FROM_BOARD4)" 96 - depends on MTD_NAND && SH_SOLUTION_ENGINE 90 + depends on SH_SOLUTION_ENGINE 97 91 select REED_SOLOMON 98 92 select REED_SOLOMON_DEC8 99 93 select BITREVERSE ··· 103 97 104 98 config MTD_NAND_PPCHAMELEONEVB 105 99 tristate "NAND Flash device on PPChameleonEVB board" 106 - depends on PPCHAMELEONEVB && MTD_NAND && BROKEN 100 + depends on PPCHAMELEONEVB && BROKEN 107 101 help 108 102 This enables the NAND flash driver on the PPChameleon EVB Board. 109 103 110 104 config MTD_NAND_S3C2410 111 105 tristate "NAND Flash support for S3C2410/S3C2440 SoC" 112 - depends on ARCH_S3C2410 && MTD_NAND 106 + depends on ARCH_S3C2410 113 107 help 114 108 This enables the NAND flash controller on the S3C2410 and S3C2440 115 109 SoCs ··· 134 128 135 129 config MTD_NAND_NDFC 136 130 tristate "NDFC NanD Flash Controller" 137 - depends on MTD_NAND && 44x 131 + depends on 44x 138 132 select MTD_NAND_ECC_SMC 139 133 help 140 134 NDFC Nand Flash Controllers are integrated in EP44x SoCs ··· 151 145 152 146 config MTD_NAND_DISKONCHIP 153 147 tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)" 154 - depends on MTD_NAND && EXPERIMENTAL 148 + depends on EXPERIMENTAL 155 149 select REED_SOLOMON 156 150 select REED_SOLOMON_DEC16 157 151 help ··· 221 215 222 216 config MTD_NAND_SHARPSL 223 217 tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)" 224 - depends on MTD_NAND && ARCH_PXA 218 + depends on ARCH_PXA 225 219 226 220 config MTD_NAND_BASLER_EXCITE 227 221 tristate "Support for NAND Flash on Basler eXcite" 228 - depends on MTD_NAND && BASLER_EXCITE 222 + depends on BASLER_EXCITE 229 223 help 230 224 This enables the driver for the NAND flash device found on the 231 225 Basler eXcite Smart Camera. If built as a module, the driver ··· 233 227 234 228 config MTD_NAND_CAFE 235 229 tristate "NAND support for OLPC CAFÉ chip" 236 - depends on MTD_NAND && PCI 230 + depends on PCI 237 231 help 238 232 Use NAND flash attached to the CAFÉ chip designed for the $100 239 233 laptop. 240 234 241 235 config MTD_NAND_CS553X 242 236 tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)" 243 - depends on MTD_NAND && X86_32 && (X86_PC || X86_GENERICARCH) 237 + depends on X86_32 && (X86_PC || X86_GENERICARCH) 244 238 help 245 239 The CS553x companion chips for the AMD Geode processor 246 240 include NAND flash controllers with built-in hardware ECC ··· 253 247 254 248 config MTD_NAND_AT91 255 249 bool "Support for NAND Flash / SmartMedia on AT91" 256 - depends on MTD_NAND && ARCH_AT91 250 + depends on ARCH_AT91 257 251 help 258 252 Enables support for NAND Flash / Smart Media Card interface 259 253 on Atmel AT91 processors. 260 254 255 + config MTD_NAND_CM_X270 256 + tristate "Support for NAND Flash on CM-X270 modules" 257 + depends on MTD_NAND && MACH_ARMCORE 258 + 259 + 261 260 config MTD_NAND_NANDSIM 262 261 tristate "Support for NAND Flash Simulator" 263 - depends on MTD_NAND && MTD_PARTITIONS 262 + depends on MTD_PARTITIONS 264 263 help 265 264 The simulator may simulate various NAND flash chips for the 266 265 MTD nand layer. 267 266 268 - endmenu 267 + endif # MTD_NAND
+1
drivers/mtd/nand/Makefile
··· 24 24 obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o 25 25 obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o 26 26 obj-$(CONFIG_MTD_NAND_AT91) += at91_nand.o 27 + obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o 27 28 obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o 28 29 29 30 nand-objs := nand_base.o nand_bbt.o
+11 -14
drivers/mtd/nand/cafe.c
··· 530 530 { 531 531 struct mtd_info *mtd; 532 532 struct cafe_priv *cafe; 533 - uint32_t timing1, timing2, timing3; 534 533 uint32_t ctrl; 535 534 int err = 0; 536 535 ··· 586 587 } 587 588 588 589 if (numtimings == 3) { 589 - timing1 = timing[0]; 590 - timing2 = timing[1]; 591 - timing3 = timing[2]; 592 590 cafe_dev_dbg(&cafe->pdev->dev, "Using provided timings (%08x %08x %08x)\n", 593 - timing1, timing2, timing3); 591 + timing[0], timing[1], timing[2]); 594 592 } else { 595 - timing1 = cafe_readl(cafe, NAND_TIMING1); 596 - timing2 = cafe_readl(cafe, NAND_TIMING2); 597 - timing3 = cafe_readl(cafe, NAND_TIMING3); 593 + timing[0] = cafe_readl(cafe, NAND_TIMING1); 594 + timing[1] = cafe_readl(cafe, NAND_TIMING2); 595 + timing[2] = cafe_readl(cafe, NAND_TIMING3); 598 596 599 - if (timing1 | timing2 | timing3) { 600 - cafe_dev_dbg(&cafe->pdev->dev, "Timing registers already set (%08x %08x %08x)\n", timing1, timing2, timing3); 597 + if (timing[0] | timing[1] | timing[2]) { 598 + cafe_dev_dbg(&cafe->pdev->dev, "Timing registers already set (%08x %08x %08x)\n", 599 + timing[0], timing[1], timing[2]); 601 600 } else { 602 601 dev_warn(&cafe->pdev->dev, "Timing registers unset; using most conservative defaults\n"); 603 - timing1 = timing2 = timing3 = 0xffffffff; 602 + timing[0] = timing[1] = timing[2] = 0xffffffff; 604 603 } 605 604 } 606 605 ··· 606 609 cafe_writel(cafe, 1, NAND_RESET); 607 610 cafe_writel(cafe, 0, NAND_RESET); 608 611 609 - cafe_writel(cafe, timing1, NAND_TIMING1); 610 - cafe_writel(cafe, timing2, NAND_TIMING2); 611 - cafe_writel(cafe, timing3, NAND_TIMING3); 612 + cafe_writel(cafe, timing[0], NAND_TIMING1); 613 + cafe_writel(cafe, timing[1], NAND_TIMING2); 614 + cafe_writel(cafe, timing[2], NAND_TIMING3); 612 615 613 616 cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK); 614 617 err = request_irq(pdev->irq, &cafe_nand_interrupt, IRQF_SHARED,
+267
drivers/mtd/nand/cmx270_nand.c
··· 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 */ 48 + static struct mtd_info *cmx270_nand_mtd; 49 + 50 + /* remaped IO address of the device */ 51 + static void __iomem *cmx270_nand_io; 52 + 53 + /* 54 + * Define static partitions for flash device 55 + */ 56 + static 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 + 65 + const char *part_probes[] = { "cmdlinepart", NULL }; 66 + 67 + static 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 + 74 + static 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 + 83 + static 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 + 92 + static 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 + 104 + static inline void nand_cs_on(void) 105 + { 106 + GPCR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS); 107 + } 108 + 109 + static 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 + */ 119 + static 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 + */ 153 + static 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 + */ 163 + static 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 + 240 + err2: 241 + iounmap(cmx270_nand_io); 242 + err1: 243 + kfree(cmx270_nand_mtd); 244 + 245 + return ret; 246 + 247 + } 248 + module_init(cmx270_init); 249 + 250 + /* 251 + * Clean up routine 252 + */ 253 + static 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 + } 263 + module_exit(cmx270_cleanup); 264 + 265 + MODULE_LICENSE("GPL"); 266 + MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>"); 267 + MODULE_DESCRIPTION("NAND flash driver for Compulab CM-X270 Module");
+4 -4
drivers/mtd/nand/nand_base.c
··· 312 312 /* Select the NAND device */ 313 313 chip->select_chip(mtd, chipnr); 314 314 } else 315 - page = (int)ofs; 315 + page = (int)(ofs >> chip->page_shift); 316 316 317 317 if (chip->options & NAND_BUSWIDTH_16) { 318 318 chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos & 0xFE, ··· 350 350 int block, ret; 351 351 352 352 /* Get block number */ 353 - block = ((int)ofs) >> chip->bbt_erase_shift; 353 + block = (int)(ofs >> chip->bbt_erase_shift); 354 354 if (chip->bbt) 355 355 chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); 356 356 ··· 771 771 uint8_t *ecc_code = chip->buffers->ecccode; 772 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 776 for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) 777 777 chip->ecc.calculate(mtd, p, &ecc_calc[i]); ··· 1426 1426 for (i = 0; i < chip->ecc.total; i++) 1427 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 /**
+4
drivers/mtd/nand/nand_ids.c
··· 24 24 * 512 512 Byte page size 25 25 */ 26 26 struct nand_flash_dev nand_flash_ids[] = { 27 + 28 + #ifdef CONFIG_MTD_NAND_MUSEUM_IDS 27 29 {"NAND 1MiB 5V 8-bit", 0x6e, 256, 1, 0x1000, 0}, 28 30 {"NAND 2MiB 5V 8-bit", 0x64, 256, 2, 0x1000, 0}, 29 31 {"NAND 4MiB 5V 8-bit", 0x6b, 512, 4, 0x2000, 0}, ··· 41 39 {"NAND 8MiB 3,3V 8-bit", 0xe6, 512, 8, 0x2000, 0}, 42 40 {"NAND 8MiB 1,8V 16-bit", 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16}, 43 41 {"NAND 8MiB 3,3V 16-bit", 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16}, 42 + #endif 44 43 45 44 {"NAND 16MiB 1,8V 8-bit", 0x33, 512, 16, 0x4000, 0}, 46 45 {"NAND 16MiB 3,3V 8-bit", 0x73, 512, 16, 0x4000, 0}, ··· 140 137 {NAND_MFR_RENESAS, "Renesas"}, 141 138 {NAND_MFR_STMICRO, "ST Micro"}, 142 139 {NAND_MFR_HYNIX, "Hynix"}, 140 + {NAND_MFR_MICRON, "Micron"}, 143 141 {0x0, "Unknown"} 144 142 }; 145 143
+491 -25
drivers/mtd/nand/nandsim.c
··· 37 37 #include <linux/mtd/nand.h> 38 38 #include <linux/mtd/partitions.h> 39 39 #include <linux/delay.h> 40 + #include <linux/list.h> 41 + #include <linux/random.h> 40 42 41 43 /* Default simulator parameters values */ 42 44 #if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \ ··· 92 90 static uint do_delays = CONFIG_NANDSIM_DO_DELAYS; 93 91 static uint log = CONFIG_NANDSIM_LOG; 94 92 static uint dbg = CONFIG_NANDSIM_DBG; 93 + static unsigned long parts[MAX_MTD_DEVICES]; 94 + static unsigned int parts_num; 95 + static char *badblocks = NULL; 96 + static char *weakblocks = NULL; 97 + static char *weakpages = NULL; 98 + static unsigned int bitflips = 0; 99 + static char *gravepages = NULL; 100 + static unsigned int rptwear = 0; 101 + static unsigned int overridesize = 0; 95 102 96 103 module_param(first_id_byte, uint, 0400); 97 104 module_param(second_id_byte, uint, 0400); ··· 115 104 module_param(do_delays, uint, 0400); 116 105 module_param(log, uint, 0400); 117 106 module_param(dbg, uint, 0400); 107 + module_param_array(parts, ulong, &parts_num, 0400); 108 + module_param(badblocks, charp, 0400); 109 + module_param(weakblocks, charp, 0400); 110 + module_param(weakpages, charp, 0400); 111 + module_param(bitflips, uint, 0400); 112 + module_param(gravepages, charp, 0400); 113 + module_param(rptwear, uint, 0400); 114 + module_param(overridesize, uint, 0400); 118 115 119 - MODULE_PARM_DESC(first_id_byte, "The fist byte returned by NAND Flash 'read ID' command (manufaturer ID)"); 116 + MODULE_PARM_DESC(first_id_byte, "The first byte returned by NAND Flash 'read ID' command (manufacturer ID)"); 120 117 MODULE_PARM_DESC(second_id_byte, "The second byte returned by NAND Flash 'read ID' command (chip ID)"); 121 118 MODULE_PARM_DESC(third_id_byte, "The third byte returned by NAND Flash 'read ID' command"); 122 119 MODULE_PARM_DESC(fourth_id_byte, "The fourth byte returned by NAND Flash 'read ID' command"); ··· 137 118 MODULE_PARM_DESC(do_delays, "Simulate NAND delays using busy-waits if not zero"); 138 119 MODULE_PARM_DESC(log, "Perform logging if not zero"); 139 120 MODULE_PARM_DESC(dbg, "Output debug information if not zero"); 121 + MODULE_PARM_DESC(parts, "Partition sizes (in erase blocks) separated by commas"); 122 + /* Page and erase block positions for the following parameters are independent of any partitions */ 123 + MODULE_PARM_DESC(badblocks, "Erase blocks that are initially marked bad, separated by commas"); 124 + MODULE_PARM_DESC(weakblocks, "Weak erase blocks [: remaining erase cycles (defaults to 3)]" 125 + " separated by commas e.g. 113:2 means eb 113" 126 + " can be erased only twice before failing"); 127 + MODULE_PARM_DESC(weakpages, "Weak pages [: maximum writes (defaults to 3)]" 128 + " separated by commas e.g. 1401:2 means page 1401" 129 + " can be written only twice before failing"); 130 + MODULE_PARM_DESC(bitflips, "Maximum number of random bit flips per page (zero by default)"); 131 + MODULE_PARM_DESC(gravepages, "Pages that lose data [: maximum reads (defaults to 3)]" 132 + " separated by commas e.g. 1401:2 means page 1401" 133 + " can be read only twice before failing"); 134 + MODULE_PARM_DESC(rptwear, "Number of erases inbetween reporting wear, if not zero"); 135 + MODULE_PARM_DESC(overridesize, "Specifies the NAND Flash size overriding the ID bytes. " 136 + "The size is specified in erase blocks and as the exponent of a power of two" 137 + " e.g. 5 means a size of 32 erase blocks"); 140 138 141 139 /* The largest possible page size */ 142 140 #define NS_LARGEST_PAGE_SIZE 2048 ··· 167 131 #define NS_DBG(args...) \ 168 132 do { if (dbg) printk(KERN_DEBUG NS_OUTPUT_PREFIX " debug: " args); } while(0) 169 133 #define NS_WARN(args...) \ 170 - do { printk(KERN_WARNING NS_OUTPUT_PREFIX " warnig: " args); } while(0) 134 + do { printk(KERN_WARNING NS_OUTPUT_PREFIX " warning: " args); } while(0) 171 135 #define NS_ERR(args...) \ 172 - do { printk(KERN_ERR NS_OUTPUT_PREFIX " errorr: " args); } while(0) 136 + do { printk(KERN_ERR NS_OUTPUT_PREFIX " error: " args); } while(0) 137 + #define NS_INFO(args...) \ 138 + do { printk(KERN_INFO NS_OUTPUT_PREFIX " " args); } while(0) 173 139 174 140 /* Busy-wait delay macros (microseconds, milliseconds) */ 175 141 #define NS_UDELAY(us) \ ··· 276 238 * The structure which describes all the internal simulator data. 277 239 */ 278 240 struct nandsim { 279 - struct mtd_partition part; 241 + struct mtd_partition partitions[MAX_MTD_DEVICES]; 242 + unsigned int nbparts; 280 243 281 244 uint busw; /* flash chip bus width (8 or 16) */ 282 245 u_char ids[4]; /* chip's ID bytes */ ··· 377 338 STATE_DATAOUT, STATE_READY}} 378 339 }; 379 340 341 + struct weak_block { 342 + struct list_head list; 343 + unsigned int erase_block_no; 344 + unsigned int max_erases; 345 + unsigned int erases_done; 346 + }; 347 + 348 + static LIST_HEAD(weak_blocks); 349 + 350 + struct weak_page { 351 + struct list_head list; 352 + unsigned int page_no; 353 + unsigned int max_writes; 354 + unsigned int writes_done; 355 + }; 356 + 357 + static LIST_HEAD(weak_pages); 358 + 359 + struct grave_page { 360 + struct list_head list; 361 + unsigned int page_no; 362 + unsigned int max_reads; 363 + unsigned int reads_done; 364 + }; 365 + 366 + static LIST_HEAD(grave_pages); 367 + 368 + static unsigned long *erase_block_wear = NULL; 369 + static unsigned int wear_eb_count = 0; 370 + static unsigned long total_wear = 0; 371 + static unsigned int rptwear_cnt = 0; 372 + 380 373 /* MTD structure for NAND controller */ 381 374 static struct mtd_info *nsmtd; 382 375 ··· 452 381 } 453 382 } 454 383 384 + static char *get_partition_name(int i) 385 + { 386 + char buf[64]; 387 + sprintf(buf, "NAND simulator partition %d", i); 388 + return kstrdup(buf, GFP_KERNEL); 389 + } 390 + 455 391 /* 456 392 * Initialize the nandsim structure. 457 393 * ··· 468 390 { 469 391 struct nand_chip *chip = (struct nand_chip *)mtd->priv; 470 392 struct nandsim *ns = (struct nandsim *)(chip->priv); 471 - int i; 393 + int i, ret = 0; 394 + u_int32_t remains; 395 + u_int32_t next_offset; 472 396 473 397 if (NS_IS_INITIALIZED(ns)) { 474 398 NS_ERR("init_nandsim: nandsim is already initialized\n"); ··· 528 448 } 529 449 } 530 450 451 + /* Fill the partition_info structure */ 452 + if (parts_num > ARRAY_SIZE(ns->partitions)) { 453 + NS_ERR("too many partitions.\n"); 454 + ret = -EINVAL; 455 + goto error; 456 + } 457 + remains = ns->geom.totsz; 458 + next_offset = 0; 459 + for (i = 0; i < parts_num; ++i) { 460 + unsigned long part = parts[i]; 461 + if (!part || part > remains / ns->geom.secsz) { 462 + NS_ERR("bad partition size.\n"); 463 + ret = -EINVAL; 464 + goto error; 465 + } 466 + ns->partitions[i].name = get_partition_name(i); 467 + ns->partitions[i].offset = next_offset; 468 + ns->partitions[i].size = part * ns->geom.secsz; 469 + next_offset += ns->partitions[i].size; 470 + remains -= ns->partitions[i].size; 471 + } 472 + ns->nbparts = parts_num; 473 + if (remains) { 474 + if (parts_num + 1 > ARRAY_SIZE(ns->partitions)) { 475 + NS_ERR("too many partitions.\n"); 476 + ret = -EINVAL; 477 + goto error; 478 + } 479 + ns->partitions[i].name = get_partition_name(i); 480 + ns->partitions[i].offset = next_offset; 481 + ns->partitions[i].size = remains; 482 + ns->nbparts += 1; 483 + } 484 + 531 485 /* Detect how many ID bytes the NAND chip outputs */ 532 486 for (i = 0; nand_flash_ids[i].name != NULL; i++) { 533 487 if (second_id_byte != nand_flash_ids[i].id) ··· 588 474 printk("sector address bytes: %u\n", ns->geom.secaddrbytes); 589 475 printk("options: %#x\n", ns->options); 590 476 591 - if (alloc_device(ns) != 0) 477 + if ((ret = alloc_device(ns)) != 0) 592 478 goto error; 593 479 594 480 /* Allocate / initialize the internal buffer */ ··· 596 482 if (!ns->buf.byte) { 597 483 NS_ERR("init_nandsim: unable to allocate %u bytes for the internal buffer\n", 598 484 ns->geom.pgszoob); 485 + ret = -ENOMEM; 599 486 goto error; 600 487 } 601 488 memset(ns->buf.byte, 0xFF, ns->geom.pgszoob); 602 - 603 - /* Fill the partition_info structure */ 604 - ns->part.name = "NAND simulator partition"; 605 - ns->part.offset = 0; 606 - ns->part.size = ns->geom.totsz; 607 489 608 490 return 0; 609 491 610 492 error: 611 493 free_device(ns); 612 494 613 - return -ENOMEM; 495 + return ret; 614 496 } 615 497 616 498 /* ··· 618 508 free_device(ns); 619 509 620 510 return; 511 + } 512 + 513 + static int parse_badblocks(struct nandsim *ns, struct mtd_info *mtd) 514 + { 515 + char *w; 516 + int zero_ok; 517 + unsigned int erase_block_no; 518 + loff_t offset; 519 + 520 + if (!badblocks) 521 + return 0; 522 + w = badblocks; 523 + do { 524 + zero_ok = (*w == '0' ? 1 : 0); 525 + erase_block_no = simple_strtoul(w, &w, 0); 526 + if (!zero_ok && !erase_block_no) { 527 + NS_ERR("invalid badblocks.\n"); 528 + return -EINVAL; 529 + } 530 + offset = erase_block_no * ns->geom.secsz; 531 + if (mtd->block_markbad(mtd, offset)) { 532 + NS_ERR("invalid badblocks.\n"); 533 + return -EINVAL; 534 + } 535 + if (*w == ',') 536 + w += 1; 537 + } while (*w); 538 + return 0; 539 + } 540 + 541 + static int parse_weakblocks(void) 542 + { 543 + char *w; 544 + int zero_ok; 545 + unsigned int erase_block_no; 546 + unsigned int max_erases; 547 + struct weak_block *wb; 548 + 549 + if (!weakblocks) 550 + return 0; 551 + w = weakblocks; 552 + do { 553 + zero_ok = (*w == '0' ? 1 : 0); 554 + erase_block_no = simple_strtoul(w, &w, 0); 555 + if (!zero_ok && !erase_block_no) { 556 + NS_ERR("invalid weakblocks.\n"); 557 + return -EINVAL; 558 + } 559 + max_erases = 3; 560 + if (*w == ':') { 561 + w += 1; 562 + max_erases = simple_strtoul(w, &w, 0); 563 + } 564 + if (*w == ',') 565 + w += 1; 566 + wb = kzalloc(sizeof(*wb), GFP_KERNEL); 567 + if (!wb) { 568 + NS_ERR("unable to allocate memory.\n"); 569 + return -ENOMEM; 570 + } 571 + wb->erase_block_no = erase_block_no; 572 + wb->max_erases = max_erases; 573 + list_add(&wb->list, &weak_blocks); 574 + } while (*w); 575 + return 0; 576 + } 577 + 578 + static int erase_error(unsigned int erase_block_no) 579 + { 580 + struct weak_block *wb; 581 + 582 + list_for_each_entry(wb, &weak_blocks, list) 583 + if (wb->erase_block_no == erase_block_no) { 584 + if (wb->erases_done >= wb->max_erases) 585 + return 1; 586 + wb->erases_done += 1; 587 + return 0; 588 + } 589 + return 0; 590 + } 591 + 592 + static int parse_weakpages(void) 593 + { 594 + char *w; 595 + int zero_ok; 596 + unsigned int page_no; 597 + unsigned int max_writes; 598 + struct weak_page *wp; 599 + 600 + if (!weakpages) 601 + return 0; 602 + w = weakpages; 603 + do { 604 + zero_ok = (*w == '0' ? 1 : 0); 605 + page_no = simple_strtoul(w, &w, 0); 606 + if (!zero_ok && !page_no) { 607 + NS_ERR("invalid weakpagess.\n"); 608 + return -EINVAL; 609 + } 610 + max_writes = 3; 611 + if (*w == ':') { 612 + w += 1; 613 + max_writes = simple_strtoul(w, &w, 0); 614 + } 615 + if (*w == ',') 616 + w += 1; 617 + wp = kzalloc(sizeof(*wp), GFP_KERNEL); 618 + if (!wp) { 619 + NS_ERR("unable to allocate memory.\n"); 620 + return -ENOMEM; 621 + } 622 + wp->page_no = page_no; 623 + wp->max_writes = max_writes; 624 + list_add(&wp->list, &weak_pages); 625 + } while (*w); 626 + return 0; 627 + } 628 + 629 + static int write_error(unsigned int page_no) 630 + { 631 + struct weak_page *wp; 632 + 633 + list_for_each_entry(wp, &weak_pages, list) 634 + if (wp->page_no == page_no) { 635 + if (wp->writes_done >= wp->max_writes) 636 + return 1; 637 + wp->writes_done += 1; 638 + return 0; 639 + } 640 + return 0; 641 + } 642 + 643 + static int parse_gravepages(void) 644 + { 645 + char *g; 646 + int zero_ok; 647 + unsigned int page_no; 648 + unsigned int max_reads; 649 + struct grave_page *gp; 650 + 651 + if (!gravepages) 652 + return 0; 653 + g = gravepages; 654 + do { 655 + zero_ok = (*g == '0' ? 1 : 0); 656 + page_no = simple_strtoul(g, &g, 0); 657 + if (!zero_ok && !page_no) { 658 + NS_ERR("invalid gravepagess.\n"); 659 + return -EINVAL; 660 + } 661 + max_reads = 3; 662 + if (*g == ':') { 663 + g += 1; 664 + max_reads = simple_strtoul(g, &g, 0); 665 + } 666 + if (*g == ',') 667 + g += 1; 668 + gp = kzalloc(sizeof(*gp), GFP_KERNEL); 669 + if (!gp) { 670 + NS_ERR("unable to allocate memory.\n"); 671 + return -ENOMEM; 672 + } 673 + gp->page_no = page_no; 674 + gp->max_reads = max_reads; 675 + list_add(&gp->list, &grave_pages); 676 + } while (*g); 677 + return 0; 678 + } 679 + 680 + static int read_error(unsigned int page_no) 681 + { 682 + struct grave_page *gp; 683 + 684 + list_for_each_entry(gp, &grave_pages, list) 685 + if (gp->page_no == page_no) { 686 + if (gp->reads_done >= gp->max_reads) 687 + return 1; 688 + gp->reads_done += 1; 689 + return 0; 690 + } 691 + return 0; 692 + } 693 + 694 + static void free_lists(void) 695 + { 696 + struct list_head *pos, *n; 697 + list_for_each_safe(pos, n, &weak_blocks) { 698 + list_del(pos); 699 + kfree(list_entry(pos, struct weak_block, list)); 700 + } 701 + list_for_each_safe(pos, n, &weak_pages) { 702 + list_del(pos); 703 + kfree(list_entry(pos, struct weak_page, list)); 704 + } 705 + list_for_each_safe(pos, n, &grave_pages) { 706 + list_del(pos); 707 + kfree(list_entry(pos, struct grave_page, list)); 708 + } 709 + kfree(erase_block_wear); 710 + } 711 + 712 + static int setup_wear_reporting(struct mtd_info *mtd) 713 + { 714 + size_t mem; 715 + 716 + if (!rptwear) 717 + return 0; 718 + wear_eb_count = mtd->size / mtd->erasesize; 719 + mem = wear_eb_count * sizeof(unsigned long); 720 + if (mem / sizeof(unsigned long) != wear_eb_count) { 721 + NS_ERR("Too many erase blocks for wear reporting\n"); 722 + return -ENOMEM; 723 + } 724 + erase_block_wear = kzalloc(mem, GFP_KERNEL); 725 + if (!erase_block_wear) { 726 + NS_ERR("Too many erase blocks for wear reporting\n"); 727 + return -ENOMEM; 728 + } 729 + return 0; 730 + } 731 + 732 + static void update_wear(unsigned int erase_block_no) 733 + { 734 + unsigned long wmin = -1, wmax = 0, avg; 735 + unsigned long deciles[10], decile_max[10], tot = 0; 736 + unsigned int i; 737 + 738 + if (!erase_block_wear) 739 + return; 740 + total_wear += 1; 741 + if (total_wear == 0) 742 + NS_ERR("Erase counter total overflow\n"); 743 + erase_block_wear[erase_block_no] += 1; 744 + if (erase_block_wear[erase_block_no] == 0) 745 + NS_ERR("Erase counter overflow for erase block %u\n", erase_block_no); 746 + rptwear_cnt += 1; 747 + if (rptwear_cnt < rptwear) 748 + return; 749 + rptwear_cnt = 0; 750 + /* Calc wear stats */ 751 + for (i = 0; i < wear_eb_count; ++i) { 752 + unsigned long wear = erase_block_wear[i]; 753 + if (wear < wmin) 754 + wmin = wear; 755 + if (wear > wmax) 756 + wmax = wear; 757 + tot += wear; 758 + } 759 + for (i = 0; i < 9; ++i) { 760 + deciles[i] = 0; 761 + decile_max[i] = (wmax * (i + 1) + 5) / 10; 762 + } 763 + deciles[9] = 0; 764 + decile_max[9] = wmax; 765 + for (i = 0; i < wear_eb_count; ++i) { 766 + int d; 767 + unsigned long wear = erase_block_wear[i]; 768 + for (d = 0; d < 10; ++d) 769 + if (wear <= decile_max[d]) { 770 + deciles[d] += 1; 771 + break; 772 + } 773 + } 774 + avg = tot / wear_eb_count; 775 + /* Output wear report */ 776 + NS_INFO("*** Wear Report ***\n"); 777 + NS_INFO("Total numbers of erases: %lu\n", tot); 778 + NS_INFO("Number of erase blocks: %u\n", wear_eb_count); 779 + NS_INFO("Average number of erases: %lu\n", avg); 780 + NS_INFO("Maximum number of erases: %lu\n", wmax); 781 + NS_INFO("Minimum number of erases: %lu\n", wmin); 782 + for (i = 0; i < 10; ++i) { 783 + unsigned long from = (i ? decile_max[i - 1] + 1 : 0); 784 + if (from > decile_max[i]) 785 + continue; 786 + NS_INFO("Number of ebs with erase counts from %lu to %lu : %lu\n", 787 + from, 788 + decile_max[i], 789 + deciles[i]); 790 + } 791 + NS_INFO("*** End of Wear Report ***\n"); 621 792 } 622 793 623 794 /* ··· 1213 822 NS_DBG("read_page: page %d not allocated\n", ns->regs.row); 1214 823 memset(ns->buf.byte, 0xFF, num); 1215 824 } else { 825 + unsigned int page_no = ns->regs.row; 1216 826 NS_DBG("read_page: page %d allocated, reading from %d\n", 1217 827 ns->regs.row, ns->regs.column + ns->regs.off); 828 + if (read_error(page_no)) { 829 + int i; 830 + memset(ns->buf.byte, 0xFF, num); 831 + for (i = 0; i < num; ++i) 832 + ns->buf.byte[i] = random32(); 833 + NS_WARN("simulating read error in page %u\n", page_no); 834 + return; 835 + } 1218 836 memcpy(ns->buf.byte, NS_PAGE_BYTE_OFF(ns), num); 837 + if (bitflips && random32() < (1 << 22)) { 838 + int flips = 1; 839 + if (bitflips > 1) 840 + flips = (random32() % (int) bitflips) + 1; 841 + while (flips--) { 842 + int pos = random32() % (num * 8); 843 + ns->buf.byte[pos / 8] ^= (1 << (pos % 8)); 844 + NS_WARN("read_page: flipping bit %d in page %d " 845 + "reading from %d ecc: corrected=%u failed=%u\n", 846 + pos, ns->regs.row, ns->regs.column + ns->regs.off, 847 + nsmtd->ecc_stats.corrected, nsmtd->ecc_stats.failed); 848 + } 849 + } 1219 850 } 1220 851 } 1221 852 ··· 1296 883 { 1297 884 int num; 1298 885 int busdiv = ns->busw == 8 ? 1 : 2; 886 + unsigned int erase_block_no, page_no; 1299 887 1300 888 action &= ACTION_MASK; 1301 889 ··· 1356 942 8 * (ns->geom.pgaddrbytes - ns->geom.secaddrbytes)) | ns->regs.column; 1357 943 ns->regs.column = 0; 1358 944 945 + erase_block_no = ns->regs.row >> (ns->geom.secshift - ns->geom.pgshift); 946 + 1359 947 NS_DBG("do_state_action: erase sector at address %#x, off = %d\n", 1360 948 ns->regs.row, NS_RAW_OFFSET(ns)); 1361 - NS_LOG("erase sector %d\n", ns->regs.row >> (ns->geom.secshift - ns->geom.pgshift)); 949 + NS_LOG("erase sector %u\n", erase_block_no); 1362 950 1363 951 erase_sector(ns); 1364 952 1365 953 NS_MDELAY(erase_delay); 954 + 955 + if (erase_block_wear) 956 + update_wear(erase_block_no); 957 + 958 + if (erase_error(erase_block_no)) { 959 + NS_WARN("simulating erase failure in erase block %u\n", erase_block_no); 960 + return -1; 961 + } 1366 962 1367 963 break; 1368 964 ··· 1396 972 if (prog_page(ns, num) == -1) 1397 973 return -1; 1398 974 975 + page_no = ns->regs.row; 976 + 1399 977 NS_DBG("do_state_action: copy %d bytes from int buf to (%#x, %#x), raw off = %d\n", 1400 978 num, ns->regs.row, ns->regs.column, NS_RAW_OFFSET(ns) + ns->regs.off); 1401 979 NS_LOG("programm page %d\n", ns->regs.row); 1402 980 1403 981 NS_UDELAY(programm_delay); 1404 982 NS_UDELAY(output_cycle * ns->geom.pgsz / 1000 / busdiv); 983 + 984 + if (write_error(page_no)) { 985 + NS_WARN("simulating write failure in page %u\n", page_no); 986 + return -1; 987 + } 1405 988 1406 989 break; 1407 990 ··· 1934 1503 { 1935 1504 struct nand_chip *chip; 1936 1505 struct nandsim *nand; 1937 - int retval = -ENOMEM; 1506 + int retval = -ENOMEM, i; 1938 1507 1939 1508 if (bus_width != 8 && bus_width != 16) { 1940 1509 NS_ERR("wrong bus width (%d), use only 8 or 16\n", bus_width); ··· 1964 1533 chip->verify_buf = ns_nand_verify_buf; 1965 1534 chip->read_word = ns_nand_read_word; 1966 1535 chip->ecc.mode = NAND_ECC_SOFT; 1536 + /* The NAND_SKIP_BBTSCAN option is necessary for 'overridesize' */ 1537 + /* and 'badblocks' parameters to work */ 1967 1538 chip->options |= NAND_SKIP_BBTSCAN; 1968 1539 1969 1540 /* ··· 1990 1557 1991 1558 nsmtd->owner = THIS_MODULE; 1992 1559 1560 + if ((retval = parse_weakblocks()) != 0) 1561 + goto error; 1562 + 1563 + if ((retval = parse_weakpages()) != 0) 1564 + goto error; 1565 + 1566 + if ((retval = parse_gravepages()) != 0) 1567 + goto error; 1568 + 1993 1569 if ((retval = nand_scan(nsmtd, 1)) != 0) { 1994 1570 NS_ERR("can't register NAND Simulator\n"); 1995 1571 if (retval > 0) ··· 2006 1564 goto error; 2007 1565 } 2008 1566 2009 - if ((retval = init_nandsim(nsmtd)) != 0) { 2010 - NS_ERR("scan_bbt: can't initialize the nandsim structure\n"); 2011 - goto error; 1567 + if (overridesize) { 1568 + u_int32_t new_size = nsmtd->erasesize << overridesize; 1569 + if (new_size >> overridesize != nsmtd->erasesize) { 1570 + NS_ERR("overridesize is too big\n"); 1571 + goto err_exit; 1572 + } 1573 + /* N.B. This relies on nand_scan not doing anything with the size before we change it */ 1574 + nsmtd->size = new_size; 1575 + chip->chipsize = new_size; 1576 + chip->chip_shift = ffs(new_size) - 1; 2012 1577 } 2013 1578 2014 - if ((retval = nand_default_bbt(nsmtd)) != 0) { 2015 - free_nandsim(nand); 2016 - goto error; 2017 - } 1579 + if ((retval = setup_wear_reporting(nsmtd)) != 0) 1580 + goto err_exit; 2018 1581 2019 - /* Register NAND as one big partition */ 2020 - add_mtd_partitions(nsmtd, &nand->part, 1); 1582 + if ((retval = init_nandsim(nsmtd)) != 0) 1583 + goto err_exit; 1584 + 1585 + if ((retval = parse_badblocks(nand, nsmtd)) != 0) 1586 + goto err_exit; 1587 + 1588 + if ((retval = nand_default_bbt(nsmtd)) != 0) 1589 + goto err_exit; 1590 + 1591 + /* Register NAND partitions */ 1592 + if ((retval = add_mtd_partitions(nsmtd, &nand->partitions[0], nand->nbparts)) != 0) 1593 + goto err_exit; 2021 1594 2022 1595 return 0; 2023 1596 1597 + err_exit: 1598 + free_nandsim(nand); 1599 + nand_release(nsmtd); 1600 + for (i = 0;i < ARRAY_SIZE(nand->partitions); ++i) 1601 + kfree(nand->partitions[i].name); 2024 1602 error: 2025 1603 kfree(nsmtd); 1604 + free_lists(); 2026 1605 2027 1606 return retval; 2028 1607 } ··· 2056 1593 static void __exit ns_cleanup_module(void) 2057 1594 { 2058 1595 struct nandsim *ns = (struct nandsim *)(((struct nand_chip *)nsmtd->priv)->priv); 1596 + int i; 2059 1597 2060 1598 free_nandsim(ns); /* Free nandsim private resources */ 2061 - nand_release(nsmtd); /* Unregisterd drived */ 1599 + nand_release(nsmtd); /* Unregister driver */ 1600 + for (i = 0;i < ARRAY_SIZE(ns->partitions); ++i) 1601 + kfree(ns->partitions[i].name); 2062 1602 kfree(nsmtd); /* Free other structures */ 1603 + free_lists(); 2063 1604 } 2064 1605 2065 1606 module_exit(ns_cleanup_module); ··· 2071 1604 MODULE_LICENSE ("GPL"); 2072 1605 MODULE_AUTHOR ("Artem B. Bityuckiy"); 2073 1606 MODULE_DESCRIPTION ("The NAND flash simulator"); 2074 -
+6 -9
drivers/mtd/onenand/Kconfig
··· 2 2 # linux/drivers/mtd/onenand/Kconfig 3 3 # 4 4 5 - menu "OneNAND Flash Device Drivers" 6 - depends on MTD != n 7 - 8 - config MTD_ONENAND 5 + menuconfig MTD_ONENAND 9 6 tristate "OneNAND Device Support" 10 7 depends on MTD 11 8 help 12 9 This enables support for accessing all type of OneNAND flash 13 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 + 13 + if MTD_ONENAND 15 14 16 15 config MTD_ONENAND_VERIFY_WRITE 17 16 bool "Verify OneNAND page writes" 18 - depends on MTD_ONENAND 19 17 help 20 18 This adds an extra check when data is written to the flash. The 21 19 OneNAND flash device internally checks only bits transitioning ··· 23 25 24 26 config MTD_ONENAND_GENERIC 25 27 tristate "OneNAND Flash device via platform device driver" 26 - depends on MTD_ONENAND && ARM 28 + depends on ARM 27 29 help 28 30 Support for OneNAND flash via platform device driver. 29 31 30 32 config MTD_ONENAND_OTP 31 33 bool "OneNAND OTP Support" 32 - depends on MTD_ONENAND 33 34 help 34 35 One Block of the NAND Flash Array memory is reserved as 35 36 a One-Time Programmable Block memory area. ··· 40 43 41 44 OTP block is fully-guaranteed to be a valid block. 42 45 43 - endmenu 46 + endif # MTD_ONENAND
+14 -7
drivers/mtd/onenand/onenand_base.c
··· 836 836 int readcol = column; 837 837 int readend = column + thislen; 838 838 int lastgap = 0; 839 + unsigned int i; 839 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 844 if (readcol >= lastgap) 843 845 readcol += free->offset - lastgap; 844 846 if (readend >= lastgap) ··· 848 846 lastgap = free->offset + free->length; 849 847 } 850 848 this->read_bufferram(mtd, ONENAND_SPARERAM, oob_buf, 0, mtd->oobsize); 851 - for (free = this->ecclayout->oobfree; free->length; ++free) { 849 + free = this->ecclayout->oobfree; 850 + for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) { 852 851 int free_end = free->offset + free->length; 853 852 if (free->offset < readend && free_end > readcol) { 854 853 int st = max_t(int,free->offset,readcol); ··· 857 854 int n = ed - st; 858 855 memcpy(buf, oob_buf + st, n); 859 856 buf += n; 860 - } else 857 + } else if (column == 0) 861 858 break; 862 859 } 863 860 return 0; ··· 1283 1280 int writecol = column; 1284 1281 int writeend = column + thislen; 1285 1282 int lastgap = 0; 1283 + unsigned int i; 1286 1284 1287 - for (free = this->ecclayout->oobfree; free->length; ++free) { 1285 + free = this->ecclayout->oobfree; 1286 + for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) { 1288 1287 if (writecol >= lastgap) 1289 1288 writecol += free->offset - lastgap; 1290 1289 if (writeend >= lastgap) 1291 1290 writeend += free->offset - lastgap; 1292 1291 lastgap = free->offset + free->length; 1293 1292 } 1294 - for (free = this->ecclayout->oobfree; free->length; ++free) { 1293 + free = this->ecclayout->oobfree; 1294 + for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) { 1295 1295 int free_end = free->offset + free->length; 1296 1296 if (free->offset < writeend && free_end > writecol) { 1297 1297 int st = max_t(int,free->offset,writecol); ··· 1302 1296 int n = ed - st; 1303 1297 memcpy(oob_buf + st, buf, n); 1304 1298 buf += n; 1305 - } else 1299 + } else if (column == 0) 1306 1300 break; 1307 1301 } 1308 1302 return 0; ··· 2392 2386 * the out of band area 2393 2387 */ 2394 2388 this->ecclayout->oobavail = 0; 2395 - for (i = 0; this->ecclayout->oobfree[i].length; i++) 2389 + for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && 2390 + this->ecclayout->oobfree[i].length; i++) 2396 2391 this->ecclayout->oobavail += 2397 2392 this->ecclayout->oobfree[i].length; 2398 2393 mtd->oobavail = this->ecclayout->oobavail;
+1 -6
fs/jffs2/LICENCE
··· 1 1 The files in this directory and elsewhere which refer to this LICENCE 2 2 file 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 6 6 JFFS2 is free software; you can redistribute it and/or modify it under 7 7 the terms of the GNU General Public License as published by the Free ··· 28 28 This exception does not invalidate any other reasons why a work based on 29 29 this file might be covered by the GNU General Public License. 30 30 31 - For information on obtaining alternative licences for JFFS2, see 32 - http://sources.redhat.com/jffs2/jffs2-licence.html 33 - 34 - 35 - $Id: LICENCE,v 1.1 2002/05/20 14:56:37 dwmw2 Exp $
-1
fs/jffs2/Makefile
··· 1 1 # 2 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 7 6 obj-$(CONFIG_JFFS2_FS) += jffs2.o
-1
fs/jffs2/README.Locking
··· 1 - $Id: README.Locking,v 1.12 2005/04/13 13:22:35 dwmw2 Exp $ 2 1 3 2 JFFS2 LOCKING DOCUMENTATION 4 3 ---------------------------
-3
fs/jffs2/TODO
··· 1 - $Id: TODO,v 1.18 2005/09/22 11:24:56 dedekind Exp $ 2 1 3 2 - support asynchronous operation -- add a per-fs 'reserved_space' count, 4 3 let each outstanding write reserve the _maximum_ amount of physical ··· 29 30 the full dirent, we only need to go to the flash in lookup() when we think we've 30 31 got a match, and in readdir(). 31 32 - Doubly-linked next_in_ino list to allow us to free obsoleted raw_node_refs immediately? 32 - - Remove totlen from jffs2_raw_node_ref? Need to have totlen passed into 33 - jffs2_mark_node_obsolete(). Can all callers work it out? 34 33 - Remove size from jffs2_raw_node_frag. 35 34 36 35 dedekind:
+2 -1
fs/jffs2/acl.c
··· 1 1 /* 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 6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 9 * 10 10 */ 11 + 11 12 #include <linux/kernel.h> 12 13 #include <linux/slab.h> 13 14 #include <linux/fs.h>
+2 -1
fs/jffs2/acl.h
··· 1 1 /* 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 6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 9 * 10 10 */ 11 + 11 12 struct jffs2_acl_entry { 12 13 jint16_t e_tag; 13 14 jint16_t e_perm;
+1 -3
fs/jffs2/background.c
··· 1 1 /* 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 6 * Created by David Woodhouse <dwmw2@infradead.org> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 - * 10 - * $Id: background.c,v 1.54 2005/05/20 21:37:12 gleixner Exp $ 11 9 * 12 10 */ 13 11
+1 -3
fs/jffs2/build.c
··· 1 1 /* 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 6 * Created by David Woodhouse <dwmw2@infradead.org> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 - * 10 - * $Id: build.c,v 1.85 2005/11/07 11:14:38 gleixner Exp $ 11 9 * 12 10 */ 13 11
+2 -142
fs/jffs2/compr.c
··· 1 1 /* 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 * 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 8 * University of Szeged, Hungary 9 9 * 10 10 * For licensing information, see the file 'LICENCE' in this directory. 11 - * 12 - * $Id: compr.c,v 1.46 2005/11/07 11:14:38 gleixner Exp $ 13 11 * 14 12 */ 15 13 ··· 265 267 spin_unlock(&jffs2_compressor_list_lock); 266 268 return 0; 267 269 } 268 - 269 - #ifdef CONFIG_JFFS2_PROC 270 - 271 - #define JFFS2_STAT_BUF_SIZE 16000 272 - 273 - char *jffs2_list_compressors(void) 274 - { 275 - struct jffs2_compressor *this; 276 - char *buf, *act_buf; 277 - 278 - act_buf = buf = kmalloc(JFFS2_STAT_BUF_SIZE,GFP_KERNEL); 279 - list_for_each_entry(this, &jffs2_compressor_list, list) { 280 - act_buf += sprintf(act_buf, "%10s priority:%d ", this->name, this->priority); 281 - if ((this->disabled)||(!this->compress)) 282 - act_buf += sprintf(act_buf,"disabled"); 283 - else 284 - act_buf += sprintf(act_buf,"enabled"); 285 - act_buf += sprintf(act_buf,"\n"); 286 - } 287 - return buf; 288 - } 289 - 290 - char *jffs2_stats(void) 291 - { 292 - struct jffs2_compressor *this; 293 - char *buf, *act_buf; 294 - 295 - act_buf = buf = kmalloc(JFFS2_STAT_BUF_SIZE,GFP_KERNEL); 296 - 297 - act_buf += sprintf(act_buf,"JFFS2 compressor statistics:\n"); 298 - act_buf += sprintf(act_buf,"%10s ","none"); 299 - act_buf += sprintf(act_buf,"compr: %d blocks (%d) decompr: %d blocks\n", none_stat_compr_blocks, 300 - none_stat_compr_size, none_stat_decompr_blocks); 301 - spin_lock(&jffs2_compressor_list_lock); 302 - list_for_each_entry(this, &jffs2_compressor_list, list) { 303 - act_buf += sprintf(act_buf,"%10s ",this->name); 304 - if ((this->disabled)||(!this->compress)) 305 - act_buf += sprintf(act_buf,"- "); 306 - else 307 - act_buf += sprintf(act_buf,"+ "); 308 - act_buf += sprintf(act_buf,"compr: %d blocks (%d/%d) decompr: %d blocks ", this->stat_compr_blocks, 309 - this->stat_compr_new_size, this->stat_compr_orig_size, 310 - this->stat_decompr_blocks); 311 - act_buf += sprintf(act_buf,"\n"); 312 - } 313 - spin_unlock(&jffs2_compressor_list_lock); 314 - 315 - return buf; 316 - } 317 - 318 - char *jffs2_get_compression_mode_name(void) 319 - { 320 - switch (jffs2_compression_mode) { 321 - case JFFS2_COMPR_MODE_NONE: 322 - return "none"; 323 - case JFFS2_COMPR_MODE_PRIORITY: 324 - return "priority"; 325 - case JFFS2_COMPR_MODE_SIZE: 326 - return "size"; 327 - } 328 - return "unkown"; 329 - } 330 - 331 - int jffs2_set_compression_mode_name(const char *name) 332 - { 333 - if (!strcmp("none",name)) { 334 - jffs2_compression_mode = JFFS2_COMPR_MODE_NONE; 335 - return 0; 336 - } 337 - if (!strcmp("priority",name)) { 338 - jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY; 339 - return 0; 340 - } 341 - if (!strcmp("size",name)) { 342 - jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE; 343 - return 0; 344 - } 345 - return 1; 346 - } 347 - 348 - static int jffs2_compressor_Xable(const char *name, int disabled) 349 - { 350 - struct jffs2_compressor *this; 351 - spin_lock(&jffs2_compressor_list_lock); 352 - list_for_each_entry(this, &jffs2_compressor_list, list) { 353 - if (!strcmp(this->name, name)) { 354 - this->disabled = disabled; 355 - spin_unlock(&jffs2_compressor_list_lock); 356 - return 0; 357 - } 358 - } 359 - spin_unlock(&jffs2_compressor_list_lock); 360 - printk(KERN_WARNING "JFFS2: compressor %s not found.\n",name); 361 - return 1; 362 - } 363 - 364 - int jffs2_enable_compressor_name(const char *name) 365 - { 366 - return jffs2_compressor_Xable(name, 0); 367 - } 368 - 369 - int jffs2_disable_compressor_name(const char *name) 370 - { 371 - return jffs2_compressor_Xable(name, 1); 372 - } 373 - 374 - int jffs2_set_compressor_priority(const char *name, int priority) 375 - { 376 - struct jffs2_compressor *this,*comp; 377 - spin_lock(&jffs2_compressor_list_lock); 378 - list_for_each_entry(this, &jffs2_compressor_list, list) { 379 - if (!strcmp(this->name, name)) { 380 - this->priority = priority; 381 - comp = this; 382 - goto reinsert; 383 - } 384 - } 385 - spin_unlock(&jffs2_compressor_list_lock); 386 - printk(KERN_WARNING "JFFS2: compressor %s not found.\n",name); 387 - return 1; 388 - reinsert: 389 - /* list is sorted in the order of priority, so if 390 - we change it we have to reinsert it into the 391 - good place */ 392 - list_del(&comp->list); 393 - list_for_each_entry(this, &jffs2_compressor_list, list) { 394 - if (this->priority < comp->priority) { 395 - list_add(&comp->list, this->list.prev); 396 - spin_unlock(&jffs2_compressor_list_lock); 397 - return 0; 398 - } 399 - } 400 - list_add_tail(&comp->list, &jffs2_compressor_list); 401 - spin_unlock(&jffs2_compressor_list_lock); 402 - return 0; 403 - } 404 - 405 - #endif 406 270 407 271 void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig) 408 272 {
+2 -15
fs/jffs2/compr.h
··· 1 1 /* 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 5 * University of Szeged, Hungary 6 6 * 7 - * For licensing information, see the file 'LICENCE' in the 8 - * jffs2 directory. 9 - * 10 - * $Id: compr.h,v 1.9 2005/11/07 11:14:38 gleixner Exp $ 7 + * For licensing information, see the file 'LICENCE' in this directory. 11 8 * 12 9 */ 13 10 ··· 72 75 unsigned char *data_out, uint32_t cdatalen, uint32_t datalen); 73 76 74 77 void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig); 75 - 76 - #ifdef CONFIG_JFFS2_PROC 77 - int jffs2_enable_compressor_name(const char *name); 78 - int jffs2_disable_compressor_name(const char *name); 79 - int jffs2_set_compression_mode_name(const char *mode_name); 80 - char *jffs2_get_compression_mode_name(void); 81 - int jffs2_set_compressor_priority(const char *mode_name, int priority); 82 - char *jffs2_list_compressors(void); 83 - char *jffs2_stats(void); 84 - #endif 85 78 86 79 /* Compressor modules */ 87 80 /* These functions will be called by jffs2_compressors_init/exit */
+1 -2
fs/jffs2/compr_rtime.c
··· 1 1 /* 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 6 * Created by Arjan van de Ven <arjanv@redhat.com> 7 7 * 8 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 12 * Very simple lz77-ish encoder.
+76 -5
fs/jffs2/compr_rubin.c
··· 1 1 /* 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 6 * Created by Arjan van de Ven <arjanv@redhat.com> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 - * 10 - * $Id: compr_rubin.c,v 1.20 2004/06/23 16:34:40 havasi Exp $ 11 9 * 12 10 */ 13 11 14 12 #include <linux/string.h> 15 13 #include <linux/types.h> 16 14 #include <linux/jffs2.h> 17 - #include "compr_rubin.h" 18 - #include "histo_mips.h" 15 + #include <linux/errno.h> 19 16 #include "compr.h" 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 25 + static int bits_mips[8] = { 277,249,290,267,229,341,212,241}; /* mips32 */ 26 + 27 + #include <linux/errno.h> 28 + 29 + struct pushpull { 30 + unsigned char *buf; 31 + unsigned int buflen; 32 + unsigned int ofs; 33 + unsigned int reserve; 34 + }; 35 + 36 + struct 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 + 46 + static 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 + 54 + static 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 + 71 + static inline int pushedbits(struct pushpull *pp) 72 + { 73 + return pp->ofs; 74 + } 75 + 76 + static 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 + 86 + static inline int pulledbits(struct pushpull *pp) 87 + { 88 + return pp->ofs; 89 + } 90 + 20 91 21 92 static void init_rubin(struct rubin_state *rs, int div, int *bits) 22 93 {
-21
fs/jffs2/compr_rubin.h
··· 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 - 13 - struct 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 - };
+1 -3
fs/jffs2/compr_zlib.c
··· 1 1 /* 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 6 * Created by David Woodhouse <dwmw2@infradead.org> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 - * 10 - * $Id: compr_zlib.c,v 1.32 2005/11/07 11:14:38 gleixner Exp $ 11 9 * 12 10 */ 13 11
-307
fs/jffs2/comprtest.c
··· 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 9 - static 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 44 - static 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 265 - static unsigned char comprbuf[TESTDATA_LEN]; 266 - static unsigned char decomprbuf[TESTDATA_LEN]; 267 - 268 - int jffs2_decompress(unsigned char comprtype, unsigned char *cdata_in, 269 - unsigned char *data_out, uint32_t cdatalen, uint32_t datalen); 270 - unsigned char jffs2_compress(unsigned char *data_in, unsigned char *cpage_out, 271 - uint32_t *datalen, uint32_t *cdatalen); 272 - 273 - int 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 - }
+2 -3
fs/jffs2/debug.c
··· 1 1 /* 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 6 * Created by David Woodhouse <dwmw2@infradead.org> 7 7 * 8 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 12 #include <linux/kernel.h> 14 13 #include <linux/types.h> 15 14 #include <linux/pagemap.h>
+2 -3
fs/jffs2/debug.h
··· 1 1 /* 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 6 * Created by David Woodhouse <dwmw2@infradead.org> 7 7 * 8 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 12 #ifndef _JFFS2_DEBUG_H_ 14 13 #define _JFFS2_DEBUG_H_ 15 14
+1 -3
fs/jffs2/dir.c
··· 1 1 /* 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 6 * Created by David Woodhouse <dwmw2@infradead.org> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 - * 10 - * $Id: dir.c,v 1.90 2005/11/07 11:14:39 gleixner Exp $ 11 9 * 12 10 */ 13 11
+2 -4
fs/jffs2/erase.c
··· 1 1 /* 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 6 * Created by David Woodhouse <dwmw2@infradead.org> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 - * 10 - * $Id: erase.c,v 1.85 2005/09/20 14:53:15 dedekind Exp $ 11 9 * 12 10 */ 13 11 ··· 331 333 332 334 *bad_offset = ofs; 333 335 334 - ret = jffs2_flash_read(c, ofs, readlen, &retlen, ebuf); 336 + ret = c->mtd->read(c->mtd, ofs, readlen, &retlen, ebuf); 335 337 if (ret) { 336 338 printk(KERN_WARNING "Read of newly-erased block at 0x%08x failed: %d. Putting on bad_list\n", ofs, ret); 337 339 goto fail;
+1 -3
fs/jffs2/file.c
··· 1 1 /* 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 6 * Created by David Woodhouse <dwmw2@infradead.org> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 - * 10 - * $Id: file.c,v 1.104 2005/10/18 23:29:35 tpoynor Exp $ 11 9 * 12 10 */ 13 11
+1 -3
fs/jffs2/fs.c
··· 1 1 /* 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 6 * Created by David Woodhouse <dwmw2@infradead.org> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 - * 10 - * $Id: fs.c,v 1.66 2005/09/27 13:17:29 dedekind Exp $ 11 9 * 12 10 */ 13 11
+3 -4
fs/jffs2/gc.c
··· 1 1 /* 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 6 * Created by David Woodhouse <dwmw2@infradead.org> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 - * 10 - * $Id: gc.c,v 1.155 2005/11/07 11:14:39 gleixner Exp $ 11 9 * 12 10 */ 13 11 ··· 142 144 c->unchecked_size); 143 145 jffs2_dbg_dump_block_lists_nolock(c); 144 146 spin_unlock(&c->erase_completion_lock); 145 - BUG(); 147 + up(&c->alloc_sem); 148 + return -ENOSPC; 146 149 } 147 150 148 151 spin_unlock(&c->erase_completion_lock);
+1 -3
fs/jffs2/ioctl.c
··· 1 1 /* 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 6 * Created by David Woodhouse <dwmw2@infradead.org> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 - * 10 - * $Id: ioctl.c,v 1.10 2005/11/07 11:14:40 gleixner Exp $ 11 9 * 12 10 */ 13 11
+10 -1
fs/jffs2/jffs2_fs_i.h
··· 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 12 #ifndef _JFFS2_FS_I 4 13 #define _JFFS2_FS_I
+10 -1
fs/jffs2/jffs2_fs_sb.h
··· 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 12 #ifndef _JFFS2_FS_SB 4 13 #define _JFFS2_FS_SB
+1 -3
fs/jffs2/malloc.c
··· 1 1 /* 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 6 * Created by David Woodhouse <dwmw2@infradead.org> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 - * 10 - * $Id: malloc.c,v 1.31 2005/11/07 11:14:40 gleixner Exp $ 11 9 * 12 10 */ 13 11
+13 -469
fs/jffs2/nodelist.c
··· 1 1 /* 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 6 * Created by David Woodhouse <dwmw2@infradead.org> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 - * 10 - * $Id: nodelist.c,v 1.115 2005/11/07 11:14:40 gleixner Exp $ 11 9 * 12 10 */ 13 11 ··· 52 54 *prev = new; 53 55 } 54 56 55 - void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint32_t size) 57 + uint32_t jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint32_t size) 56 58 { 57 59 struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size); 58 60 ··· 74 76 } 75 77 76 78 if (size == 0) 77 - return; 79 + return 0; 78 80 79 - /* 80 - * If the last fragment starts at the RAM page boundary, it is 81 - * REF_PRISTINE irrespective of its size. 82 - */ 83 81 frag = frag_last(list); 82 + 83 + /* Sanity check for truncation to longer than we started with... */ 84 + if (!frag) 85 + return 0; 86 + if (frag->ofs + frag->size < size) 87 + return frag->ofs + frag->size; 88 + 89 + /* If the last fragment starts at the RAM page boundary, it is 90 + * REF_PRISTINE irrespective of its size. */ 84 91 if (frag->node && (frag->ofs & (PAGE_CACHE_SIZE - 1)) == 0) { 85 92 dbg_fragtree2("marking the last fragment 0x%08x-0x%08x REF_PRISTINE.\n", 86 93 frag->ofs, frag->ofs + frag->size); 87 94 frag->node->raw->flash_offset = ref_offset(frag->node->raw) | REF_PRISTINE; 88 95 } 96 + return size; 89 97 } 90 98 91 99 static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, ··· 397 393 } 398 394 } 399 395 jffs2_dbg_fragtree_paranoia_check_nolock(f); 400 - 401 - return 0; 402 - } 403 - 404 - /* 405 - * Check the data CRC of the node. 406 - * 407 - * Returns: 0 if the data CRC is correct; 408 - * 1 - if incorrect; 409 - * error code if an error occured. 410 - */ 411 - static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn) 412 - { 413 - struct jffs2_raw_node_ref *ref = tn->fn->raw; 414 - int err = 0, pointed = 0; 415 - struct jffs2_eraseblock *jeb; 416 - unsigned char *buffer; 417 - uint32_t crc, ofs, len; 418 - size_t retlen; 419 - 420 - BUG_ON(tn->csize == 0); 421 - 422 - if (!jffs2_is_writebuffered(c)) 423 - goto adj_acc; 424 - 425 - /* Calculate how many bytes were already checked */ 426 - ofs = ref_offset(ref) + sizeof(struct jffs2_raw_inode); 427 - len = ofs % c->wbuf_pagesize; 428 - if (likely(len)) 429 - len = c->wbuf_pagesize - len; 430 - 431 - if (len >= tn->csize) { 432 - dbg_readinode("no need to check node at %#08x, data length %u, data starts at %#08x - it has already been checked.\n", 433 - ref_offset(ref), tn->csize, ofs); 434 - goto adj_acc; 435 - } 436 - 437 - ofs += len; 438 - len = tn->csize - len; 439 - 440 - 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", 441 - ref_offset(ref), tn->csize, tn->partial_crc, tn->data_crc, ofs - len, ofs, len); 442 - 443 - #ifndef __ECOS 444 - /* TODO: instead, incapsulate point() stuff to jffs2_flash_read(), 445 - * adding and jffs2_flash_read_end() interface. */ 446 - if (c->mtd->point) { 447 - err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer); 448 - if (!err && retlen < tn->csize) { 449 - JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize); 450 - c->mtd->unpoint(c->mtd, buffer, ofs, len); 451 - } else if (err) 452 - JFFS2_WARNING("MTD point failed: error code %d.\n", err); 453 - else 454 - pointed = 1; /* succefully pointed to device */ 455 - } 456 - #endif 457 - 458 - if (!pointed) { 459 - buffer = kmalloc(len, GFP_KERNEL); 460 - if (unlikely(!buffer)) 461 - return -ENOMEM; 462 - 463 - /* TODO: this is very frequent pattern, make it a separate 464 - * routine */ 465 - err = jffs2_flash_read(c, ofs, len, &retlen, buffer); 466 - if (err) { 467 - JFFS2_ERROR("can not read %d bytes from 0x%08x, error code: %d.\n", len, ofs, err); 468 - goto free_out; 469 - } 470 - 471 - if (retlen != len) { 472 - JFFS2_ERROR("short read at %#08x: %zd instead of %d.\n", ofs, retlen, len); 473 - err = -EIO; 474 - goto free_out; 475 - } 476 - } 477 - 478 - /* Continue calculating CRC */ 479 - crc = crc32(tn->partial_crc, buffer, len); 480 - if(!pointed) 481 - kfree(buffer); 482 - #ifndef __ECOS 483 - else 484 - c->mtd->unpoint(c->mtd, buffer, ofs, len); 485 - #endif 486 - 487 - if (crc != tn->data_crc) { 488 - JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n", 489 - ofs, tn->data_crc, crc); 490 - return 1; 491 - } 492 - 493 - adj_acc: 494 - jeb = &c->blocks[ref->flash_offset / c->sector_size]; 495 - len = ref_totlen(c, jeb, ref); 496 - 497 - /* 498 - * Mark the node as having been checked and fix the 499 - * accounting accordingly. 500 - */ 501 - spin_lock(&c->erase_completion_lock); 502 - jeb->used_size += len; 503 - jeb->unchecked_size -= len; 504 - c->used_size += len; 505 - c->unchecked_size -= len; 506 - spin_unlock(&c->erase_completion_lock); 507 - 508 - return 0; 509 - 510 - free_out: 511 - if(!pointed) 512 - kfree(buffer); 513 - #ifndef __ECOS 514 - else 515 - c->mtd->unpoint(c->mtd, buffer, ofs, len); 516 - #endif 517 - return err; 518 - } 519 - 520 - /* 521 - * Helper function for jffs2_add_older_frag_to_fragtree(). 522 - * 523 - * Checks the node if we are in the checking stage. 524 - */ 525 - static int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn) 526 - { 527 - int ret; 528 - 529 - BUG_ON(ref_obsolete(tn->fn->raw)); 530 - 531 - /* We only check the data CRC of unchecked nodes */ 532 - if (ref_flags(tn->fn->raw) != REF_UNCHECKED) 533 - return 0; 534 - 535 - dbg_fragtree2("check node %#04x-%#04x, phys offs %#08x.\n", 536 - tn->fn->ofs, tn->fn->ofs + tn->fn->size, ref_offset(tn->fn->raw)); 537 - 538 - ret = check_node_data(c, tn); 539 - if (unlikely(ret < 0)) { 540 - JFFS2_ERROR("check_node_data() returned error: %d.\n", 541 - ret); 542 - } else if (unlikely(ret > 0)) { 543 - dbg_fragtree2("CRC error, mark it obsolete.\n"); 544 - jffs2_mark_node_obsolete(c, tn->fn->raw); 545 - } 546 - 547 - return ret; 548 - } 549 - 550 - /* 551 - * Helper function for jffs2_add_older_frag_to_fragtree(). 552 - * 553 - * Called when the new fragment that is being inserted 554 - * splits a hole fragment. 555 - */ 556 - static int split_hole(struct jffs2_sb_info *c, struct rb_root *root, 557 - struct jffs2_node_frag *newfrag, struct jffs2_node_frag *hole) 558 - { 559 - dbg_fragtree2("fragment %#04x-%#04x splits the hole %#04x-%#04x\n", 560 - newfrag->ofs, newfrag->ofs + newfrag->size, hole->ofs, hole->ofs + hole->size); 561 - 562 - if (hole->ofs == newfrag->ofs) { 563 - /* 564 - * Well, the new fragment actually starts at the same offset as 565 - * the hole. 566 - */ 567 - if (hole->ofs + hole->size > newfrag->ofs + newfrag->size) { 568 - /* 569 - * We replace the overlapped left part of the hole by 570 - * the new node. 571 - */ 572 - 573 - dbg_fragtree2("insert fragment %#04x-%#04x and cut the left part of the hole\n", 574 - newfrag->ofs, newfrag->ofs + newfrag->size); 575 - rb_replace_node(&hole->rb, &newfrag->rb, root); 576 - 577 - hole->ofs += newfrag->size; 578 - hole->size -= newfrag->size; 579 - 580 - /* 581 - * We know that 'hole' should be the right hand 582 - * fragment. 583 - */ 584 - jffs2_fragtree_insert(hole, newfrag); 585 - rb_insert_color(&hole->rb, root); 586 - } else { 587 - /* 588 - * Ah, the new fragment is of the same size as the hole. 589 - * Relace the hole by it. 590 - */ 591 - dbg_fragtree2("insert fragment %#04x-%#04x and overwrite hole\n", 592 - newfrag->ofs, newfrag->ofs + newfrag->size); 593 - rb_replace_node(&hole->rb, &newfrag->rb, root); 594 - jffs2_free_node_frag(hole); 595 - } 596 - } else { 597 - /* The new fragment lefts some hole space at the left */ 598 - 599 - struct jffs2_node_frag * newfrag2 = NULL; 600 - 601 - if (hole->ofs + hole->size > newfrag->ofs + newfrag->size) { 602 - /* The new frag also lefts some space at the right */ 603 - newfrag2 = new_fragment(NULL, newfrag->ofs + 604 - newfrag->size, hole->ofs + hole->size 605 - - newfrag->ofs - newfrag->size); 606 - if (unlikely(!newfrag2)) { 607 - jffs2_free_node_frag(newfrag); 608 - return -ENOMEM; 609 - } 610 - } 611 - 612 - hole->size = newfrag->ofs - hole->ofs; 613 - dbg_fragtree2("left the hole %#04x-%#04x at the left and inserd fragment %#04x-%#04x\n", 614 - hole->ofs, hole->ofs + hole->size, newfrag->ofs, newfrag->ofs + newfrag->size); 615 - 616 - jffs2_fragtree_insert(newfrag, hole); 617 - rb_insert_color(&newfrag->rb, root); 618 - 619 - if (newfrag2) { 620 - dbg_fragtree2("left the hole %#04x-%#04x at the right\n", 621 - newfrag2->ofs, newfrag2->ofs + newfrag2->size); 622 - jffs2_fragtree_insert(newfrag2, newfrag); 623 - rb_insert_color(&newfrag2->rb, root); 624 - } 625 - } 626 - 627 - return 0; 628 - } 629 - 630 - /* 631 - * This function is used when we build inode. It expects the nodes are passed 632 - * in the decreasing version order. The whole point of this is to improve the 633 - * inodes checking on NAND: we check the nodes' data CRC only when they are not 634 - * obsoleted. Previously, add_frag_to_fragtree() function was used and 635 - * nodes were passed to it in the increasing version ordes and CRCs of all 636 - * nodes were checked. 637 - * 638 - * Note: tn->fn->size shouldn't be zero. 639 - * 640 - * Returns 0 if the node was inserted 641 - * 1 if it wasn't inserted (since it is obsolete) 642 - * < 0 an if error occured 643 - */ 644 - int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, 645 - struct jffs2_tmp_dnode_info *tn) 646 - { 647 - struct jffs2_node_frag *this, *newfrag; 648 - uint32_t lastend; 649 - struct jffs2_full_dnode *fn = tn->fn; 650 - struct rb_root *root = &f->fragtree; 651 - uint32_t fn_size = fn->size, fn_ofs = fn->ofs; 652 - int err, checked = 0; 653 - int ref_flag; 654 - 655 - dbg_fragtree("insert fragment %#04x-%#04x, ver %u\n", fn_ofs, fn_ofs + fn_size, tn->version); 656 - 657 - /* Skip all the nodes which are completed before this one starts */ 658 - this = jffs2_lookup_node_frag(root, fn_ofs); 659 - if (this) 660 - dbg_fragtree2("'this' found %#04x-%#04x (%s)\n", this->ofs, this->ofs + this->size, this->node ? "data" : "hole"); 661 - 662 - if (this) 663 - lastend = this->ofs + this->size; 664 - else 665 - lastend = 0; 666 - 667 - /* Detect the preliminary type of node */ 668 - if (fn->size >= PAGE_CACHE_SIZE) 669 - ref_flag = REF_PRISTINE; 670 - else 671 - ref_flag = REF_NORMAL; 672 - 673 - /* See if we ran off the end of the root */ 674 - if (lastend <= fn_ofs) { 675 - /* We did */ 676 - 677 - /* 678 - * We are going to insert the new node into the 679 - * fragment tree, so check it. 680 - */ 681 - err = check_node(c, f, tn); 682 - if (err != 0) 683 - return err; 684 - 685 - fn->frags = 1; 686 - 687 - newfrag = new_fragment(fn, fn_ofs, fn_size); 688 - if (unlikely(!newfrag)) 689 - return -ENOMEM; 690 - 691 - err = no_overlapping_node(c, root, newfrag, this, lastend); 692 - if (unlikely(err != 0)) { 693 - jffs2_free_node_frag(newfrag); 694 - return err; 695 - } 696 - 697 - goto out_ok; 698 - } 699 - 700 - fn->frags = 0; 701 - 702 - while (1) { 703 - /* 704 - * Here we have: 705 - * fn_ofs < this->ofs + this->size && fn_ofs >= this->ofs. 706 - * 707 - * Remember, 'this' has higher version, any non-hole node 708 - * which is already in the fragtree is newer then the newly 709 - * inserted. 710 - */ 711 - if (!this->node) { 712 - /* 713 - * 'this' is the hole fragment, so at least the 714 - * beginning of the new fragment is valid. 715 - */ 716 - 717 - /* 718 - * We are going to insert the new node into the 719 - * fragment tree, so check it. 720 - */ 721 - if (!checked) { 722 - err = check_node(c, f, tn); 723 - if (unlikely(err != 0)) 724 - return err; 725 - checked = 1; 726 - } 727 - 728 - if (this->ofs + this->size >= fn_ofs + fn_size) { 729 - /* We split the hole on two parts */ 730 - 731 - fn->frags += 1; 732 - newfrag = new_fragment(fn, fn_ofs, fn_size); 733 - if (unlikely(!newfrag)) 734 - return -ENOMEM; 735 - 736 - err = split_hole(c, root, newfrag, this); 737 - if (unlikely(err)) 738 - return err; 739 - goto out_ok; 740 - } 741 - 742 - /* 743 - * The beginning of the new fragment is valid since it 744 - * overlaps the hole node. 745 - */ 746 - 747 - ref_flag = REF_NORMAL; 748 - 749 - fn->frags += 1; 750 - newfrag = new_fragment(fn, fn_ofs, 751 - this->ofs + this->size - fn_ofs); 752 - if (unlikely(!newfrag)) 753 - return -ENOMEM; 754 - 755 - if (fn_ofs == this->ofs) { 756 - /* 757 - * The new node starts at the same offset as 758 - * the hole and supersieds the hole. 759 - */ 760 - dbg_fragtree2("add the new fragment instead of hole %#04x-%#04x, refcnt %d\n", 761 - fn_ofs, fn_ofs + this->ofs + this->size - fn_ofs, fn->frags); 762 - 763 - rb_replace_node(&this->rb, &newfrag->rb, root); 764 - jffs2_free_node_frag(this); 765 - } else { 766 - /* 767 - * The hole becomes shorter as its right part 768 - * is supersieded by the new fragment. 769 - */ 770 - dbg_fragtree2("reduce size of hole %#04x-%#04x to %#04x-%#04x\n", 771 - this->ofs, this->ofs + this->size, this->ofs, this->ofs + this->size - newfrag->size); 772 - 773 - dbg_fragtree2("add new fragment %#04x-%#04x, refcnt %d\n", fn_ofs, 774 - fn_ofs + this->ofs + this->size - fn_ofs, fn->frags); 775 - 776 - this->size -= newfrag->size; 777 - jffs2_fragtree_insert(newfrag, this); 778 - rb_insert_color(&newfrag->rb, root); 779 - } 780 - 781 - fn_ofs += newfrag->size; 782 - fn_size -= newfrag->size; 783 - this = rb_entry(rb_next(&newfrag->rb), 784 - struct jffs2_node_frag, rb); 785 - 786 - dbg_fragtree2("switch to the next 'this' fragment: %#04x-%#04x %s\n", 787 - this->ofs, this->ofs + this->size, this->node ? "(data)" : "(hole)"); 788 - } 789 - 790 - /* 791 - * 'This' node is not the hole so it obsoletes the new fragment 792 - * either fully or partially. 793 - */ 794 - if (this->ofs + this->size >= fn_ofs + fn_size) { 795 - /* The new node is obsolete, drop it */ 796 - if (fn->frags == 0) { 797 - dbg_fragtree2("%#04x-%#04x is obsolete, mark it obsolete\n", fn_ofs, fn_ofs + fn_size); 798 - ref_flag = REF_OBSOLETE; 799 - } 800 - goto out_ok; 801 - } else { 802 - struct jffs2_node_frag *new_this; 803 - 804 - /* 'This' node obsoletes the beginning of the new node */ 805 - dbg_fragtree2("the beginning %#04x-%#04x is obsolete\n", fn_ofs, this->ofs + this->size); 806 - 807 - ref_flag = REF_NORMAL; 808 - 809 - fn_size -= this->ofs + this->size - fn_ofs; 810 - fn_ofs = this->ofs + this->size; 811 - dbg_fragtree2("now considering %#04x-%#04x\n", fn_ofs, fn_ofs + fn_size); 812 - 813 - new_this = rb_entry(rb_next(&this->rb), struct jffs2_node_frag, rb); 814 - if (!new_this) { 815 - /* 816 - * There is no next fragment. Add the rest of 817 - * the new node as the right-hand child. 818 - */ 819 - if (!checked) { 820 - err = check_node(c, f, tn); 821 - if (unlikely(err != 0)) 822 - return err; 823 - checked = 1; 824 - } 825 - 826 - fn->frags += 1; 827 - newfrag = new_fragment(fn, fn_ofs, fn_size); 828 - if (unlikely(!newfrag)) 829 - return -ENOMEM; 830 - 831 - dbg_fragtree2("there are no more fragments, insert %#04x-%#04x\n", 832 - newfrag->ofs, newfrag->ofs + newfrag->size); 833 - rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); 834 - rb_insert_color(&newfrag->rb, root); 835 - goto out_ok; 836 - } else { 837 - this = new_this; 838 - dbg_fragtree2("switch to the next 'this' fragment: %#04x-%#04x %s\n", 839 - this->ofs, this->ofs + this->size, this->node ? "(data)" : "(hole)"); 840 - } 841 - } 842 - } 843 - 844 - out_ok: 845 - BUG_ON(fn->size < PAGE_CACHE_SIZE && ref_flag == REF_PRISTINE); 846 - 847 - if (ref_flag == REF_OBSOLETE) { 848 - dbg_fragtree2("the node is obsolete now\n"); 849 - /* jffs2_mark_node_obsolete() will adjust space accounting */ 850 - jffs2_mark_node_obsolete(c, fn->raw); 851 - return 1; 852 - } 853 - 854 - dbg_fragtree2("the node is \"%s\" now\n", ref_flag == REF_NORMAL ? "REF_NORMAL" : "REF_PRISTINE"); 855 - 856 - /* Space accounting was adjusted at check_node_data() */ 857 - spin_lock(&c->erase_completion_lock); 858 - fn->raw->flash_offset = ref_offset(fn->raw) | ref_flag; 859 - spin_unlock(&c->erase_completion_lock); 860 396 861 397 return 0; 862 398 }
+34 -6
fs/jffs2/nodelist.h
··· 1 1 /* 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 6 * Created by David Woodhouse <dwmw2@infradead.org> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 - * 10 - * $Id: nodelist.h,v 1.140 2005/09/07 08:34:54 havasi Exp $ 11 9 * 12 10 */ 13 11 ··· 38 40 #define cpu_to_je32(x) ((jint32_t){x}) 39 41 #define cpu_to_jemode(x) ((jmode_t){os_to_jffs2_mode(x)}) 40 42 43 + #define constant_cpu_to_je16(x) ((jint16_t){x}) 44 + #define constant_cpu_to_je32(x) ((jint32_t){x}) 45 + 41 46 #define je16_to_cpu(x) ((x).v16) 42 47 #define je32_to_cpu(x) ((x).v32) 43 48 #define jemode_to_cpu(x) (jffs2_to_os_mode((x).m)) ··· 49 48 #define cpu_to_je32(x) ((jint32_t){cpu_to_be32(x)}) 50 49 #define cpu_to_jemode(x) ((jmode_t){cpu_to_be32(os_to_jffs2_mode(x))}) 51 50 51 + #define constant_cpu_to_je16(x) ((jint16_t){__constant_cpu_to_be16(x)}) 52 + #define constant_cpu_to_je32(x) ((jint32_t){__constant_cpu_to_be32(x)}) 53 + 52 54 #define je16_to_cpu(x) (be16_to_cpu(x.v16)) 53 55 #define je32_to_cpu(x) (be32_to_cpu(x.v32)) 54 56 #define jemode_to_cpu(x) (be32_to_cpu(jffs2_to_os_mode((x).m))) ··· 59 55 #define cpu_to_je16(x) ((jint16_t){cpu_to_le16(x)}) 60 56 #define cpu_to_je32(x) ((jint32_t){cpu_to_le32(x)}) 61 57 #define cpu_to_jemode(x) ((jmode_t){cpu_to_le32(os_to_jffs2_mode(x))}) 58 + 59 + #define constant_cpu_to_je16(x) ((jint16_t){__constant_cpu_to_le16(x)}) 60 + #define constant_cpu_to_je32(x) ((jint32_t){__constant_cpu_to_le32(x)}) 62 61 63 62 #define je16_to_cpu(x) (le16_to_cpu(x.v16)) 64 63 #define je32_to_cpu(x) (le32_to_cpu(x.v32)) ··· 223 216 uint32_t version; 224 217 uint32_t data_crc; 225 218 uint32_t partial_crc; 226 - uint32_t csize; 219 + uint16_t csize; 220 + uint16_t overlapped; 221 + }; 222 + 223 + /* Temporary data structure used during readinode. */ 224 + struct jffs2_readinode_info 225 + { 226 + struct rb_root tn_root; 227 + struct jffs2_tmp_dnode_info *mdata_tn; 228 + uint32_t highest_version; 229 + uint32_t latest_mctime; 230 + uint32_t mctime_ver; 231 + struct jffs2_full_dirent *fds; 232 + struct jffs2_raw_node_ref *latest_ref; 227 233 }; 228 234 229 235 struct jffs2_full_dirent ··· 339 319 #define frag_right(frag) rb_entry((frag)->rb.rb_right, struct jffs2_node_frag, rb) 340 320 #define frag_erase(frag, list) rb_erase(&frag->rb, list); 341 321 322 + #define tn_next(tn) rb_entry(rb_next(&(tn)->rb), struct jffs2_tmp_dnode_info, rb) 323 + #define tn_prev(tn) rb_entry(rb_prev(&(tn)->rb), struct jffs2_tmp_dnode_info, rb) 324 + #define tn_parent(tn) rb_entry(rb_parent(&(tn)->rb), struct jffs2_tmp_dnode_info, rb) 325 + #define tn_left(tn) rb_entry((tn)->rb.rb_left, struct jffs2_tmp_dnode_info, rb) 326 + #define tn_right(tn) rb_entry((tn)->rb.rb_right, struct jffs2_tmp_dnode_info, rb) 327 + #define tn_erase(tn, list) rb_erase(&tn->rb, list); 328 + #define tn_last(list) rb_entry(rb_last(list), struct jffs2_tmp_dnode_info, rb) 329 + #define tn_first(list) rb_entry(rb_first(list), struct jffs2_tmp_dnode_info, rb) 330 + 342 331 /* nodelist.c */ 343 332 void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list); 344 333 void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, int state); ··· 362 333 struct rb_node *rb_prev(struct rb_node *); 363 334 void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root); 364 335 int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); 365 - void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); 366 - int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn); 336 + uint32_t jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); 367 337 struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c, 368 338 struct jffs2_eraseblock *jeb, 369 339 uint32_t ofs, uint32_t len,
+6 -3
fs/jffs2/nodemgmt.c
··· 1 1 /* 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 6 * Created by David Woodhouse <dwmw2@infradead.org> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 - * 10 - * $Id: nodemgmt.c,v 1.127 2005/09/20 15:49:12 dedekind Exp $ 11 9 * 12 10 */ 13 11 ··· 170 172 static void jffs2_close_nextblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) 171 173 { 172 174 175 + if (c->nextblock == NULL) { 176 + D1(printk(KERN_DEBUG "jffs2_close_nextblock: Erase block at 0x%08x has already been placed in a list\n", 177 + jeb->offset)); 178 + return; 179 + } 173 180 /* Check, if we have a dirty block now, or if it was dirty already */ 174 181 if (ISDIRTY (jeb->wasted_size + jeb->dirty_size)) { 175 182 c->dirty_size += jeb->wasted_size;
+1 -3
fs/jffs2/os-linux.h
··· 1 1 /* 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 6 * Created by David Woodhouse <dwmw2@infradead.org> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 - * 10 - * $Id: os-linux.h,v 1.64 2005/09/30 13:59:13 dedekind Exp $ 11 9 * 12 10 */ 13 11
-72
fs/jffs2/pushpull.h
··· 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 - 19 - struct pushpull { 20 - unsigned char *buf; 21 - unsigned int buflen; 22 - unsigned int ofs; 23 - unsigned int reserve; 24 - }; 25 - 26 - 27 - static 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 - 35 - static 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 - 52 - static inline int pushedbits(struct pushpull *pp) 53 - { 54 - return pp->ofs; 55 - } 56 - 57 - static 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 - 67 - static inline int pulledbits(struct pushpull *pp) 68 - { 69 - return pp->ofs; 70 - } 71 - 72 - #endif /* __PUSHPULL_H__ */
+1 -3
fs/jffs2/read.c
··· 1 1 /* 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 6 * Created by David Woodhouse <dwmw2@infradead.org> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 - * 10 - * $Id: read.c,v 1.42 2005/11/07 11:14:41 gleixner Exp $ 11 9 * 12 10 */ 13 11
+640 -211
fs/jffs2/readinode.c
··· 1 1 /* 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 6 * Created by David Woodhouse <dwmw2@infradead.org> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 - * 10 - * $Id: readinode.c,v 1.143 2005/11/07 11:14:41 gleixner Exp $ 11 9 * 12 10 */ 13 11 ··· 20 22 #include "nodelist.h" 21 23 22 24 /* 23 - * Put a new tmp_dnode_info into the temporaty RB-tree, keeping the list in 24 - * order of increasing version. 25 + * Check the data CRC of the node. 26 + * 27 + * Returns: 0 if the data CRC is correct; 28 + * 1 - if incorrect; 29 + * error code if an error occured. 25 30 */ 26 - static void jffs2_add_tn_to_tree(struct jffs2_tmp_dnode_info *tn, struct rb_root *list) 31 + static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn) 27 32 { 28 - struct rb_node **p = &list->rb_node; 29 - struct rb_node * parent = NULL; 30 - struct jffs2_tmp_dnode_info *this; 33 + struct jffs2_raw_node_ref *ref = tn->fn->raw; 34 + int err = 0, pointed = 0; 35 + struct jffs2_eraseblock *jeb; 36 + unsigned char *buffer; 37 + uint32_t crc, ofs, len; 38 + size_t retlen; 31 39 32 - while (*p) { 33 - parent = *p; 34 - this = rb_entry(parent, struct jffs2_tmp_dnode_info, rb); 40 + BUG_ON(tn->csize == 0); 35 41 36 - /* There may actually be a collision here, but it doesn't 37 - actually matter. As long as the two nodes with the same 38 - version are together, it's all fine. */ 39 - if (tn->version > this->version) 40 - p = &(*p)->rb_left; 41 - else 42 - p = &(*p)->rb_right; 42 + if (!jffs2_is_writebuffered(c)) 43 + goto adj_acc; 44 + 45 + /* Calculate how many bytes were already checked */ 46 + ofs = ref_offset(ref) + sizeof(struct jffs2_raw_inode); 47 + len = ofs % c->wbuf_pagesize; 48 + if (likely(len)) 49 + len = c->wbuf_pagesize - len; 50 + 51 + if (len >= tn->csize) { 52 + dbg_readinode("no need to check node at %#08x, data length %u, data starts at %#08x - it has already been checked.\n", 53 + ref_offset(ref), tn->csize, ofs); 54 + goto adj_acc; 43 55 } 44 56 45 - rb_link_node(&tn->rb, parent, p); 46 - rb_insert_color(&tn->rb, list); 57 + ofs += len; 58 + len = tn->csize - len; 59 + 60 + 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", 61 + ref_offset(ref), tn->csize, tn->partial_crc, tn->data_crc, ofs - len, ofs, len); 62 + 63 + #ifndef __ECOS 64 + /* TODO: instead, incapsulate point() stuff to jffs2_flash_read(), 65 + * adding and jffs2_flash_read_end() interface. */ 66 + if (c->mtd->point) { 67 + err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer); 68 + if (!err && retlen < tn->csize) { 69 + JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize); 70 + c->mtd->unpoint(c->mtd, buffer, ofs, len); 71 + } else if (err) 72 + JFFS2_WARNING("MTD point failed: error code %d.\n", err); 73 + else 74 + pointed = 1; /* succefully pointed to device */ 75 + } 76 + #endif 77 + 78 + if (!pointed) { 79 + buffer = kmalloc(len, GFP_KERNEL); 80 + if (unlikely(!buffer)) 81 + return -ENOMEM; 82 + 83 + /* TODO: this is very frequent pattern, make it a separate 84 + * routine */ 85 + err = jffs2_flash_read(c, ofs, len, &retlen, buffer); 86 + if (err) { 87 + JFFS2_ERROR("can not read %d bytes from 0x%08x, error code: %d.\n", len, ofs, err); 88 + goto free_out; 89 + } 90 + 91 + if (retlen != len) { 92 + JFFS2_ERROR("short read at %#08x: %zd instead of %d.\n", ofs, retlen, len); 93 + err = -EIO; 94 + goto free_out; 95 + } 96 + } 97 + 98 + /* Continue calculating CRC */ 99 + crc = crc32(tn->partial_crc, buffer, len); 100 + if(!pointed) 101 + kfree(buffer); 102 + #ifndef __ECOS 103 + else 104 + c->mtd->unpoint(c->mtd, buffer, ofs, len); 105 + #endif 106 + 107 + if (crc != tn->data_crc) { 108 + JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n", 109 + ofs, tn->data_crc, crc); 110 + return 1; 111 + } 112 + 113 + adj_acc: 114 + jeb = &c->blocks[ref->flash_offset / c->sector_size]; 115 + len = ref_totlen(c, jeb, ref); 116 + /* If it should be REF_NORMAL, it'll get marked as such when 117 + we build the fragtree, shortly. No need to worry about GC 118 + moving it while it's marked REF_PRISTINE -- GC won't happen 119 + till we've finished checking every inode anyway. */ 120 + ref->flash_offset |= REF_PRISTINE; 121 + /* 122 + * Mark the node as having been checked and fix the 123 + * accounting accordingly. 124 + */ 125 + spin_lock(&c->erase_completion_lock); 126 + jeb->used_size += len; 127 + jeb->unchecked_size -= len; 128 + c->used_size += len; 129 + c->unchecked_size -= len; 130 + jffs2_dbg_acct_paranoia_check_nolock(c, jeb); 131 + spin_unlock(&c->erase_completion_lock); 132 + 133 + return 0; 134 + 135 + free_out: 136 + if(!pointed) 137 + kfree(buffer); 138 + #ifndef __ECOS 139 + else 140 + c->mtd->unpoint(c->mtd, buffer, ofs, len); 141 + #endif 142 + return err; 143 + } 144 + 145 + /* 146 + * Helper function for jffs2_add_older_frag_to_fragtree(). 147 + * 148 + * Checks the node if we are in the checking stage. 149 + */ 150 + static int check_tn_node(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn) 151 + { 152 + int ret; 153 + 154 + BUG_ON(ref_obsolete(tn->fn->raw)); 155 + 156 + /* We only check the data CRC of unchecked nodes */ 157 + if (ref_flags(tn->fn->raw) != REF_UNCHECKED) 158 + return 0; 159 + 160 + dbg_readinode("check node %#04x-%#04x, phys offs %#08x\n", 161 + tn->fn->ofs, tn->fn->ofs + tn->fn->size, ref_offset(tn->fn->raw)); 162 + 163 + ret = check_node_data(c, tn); 164 + if (unlikely(ret < 0)) { 165 + JFFS2_ERROR("check_node_data() returned error: %d.\n", 166 + ret); 167 + } else if (unlikely(ret > 0)) { 168 + dbg_readinode("CRC error, mark it obsolete.\n"); 169 + jffs2_mark_node_obsolete(c, tn->fn->raw); 170 + } 171 + 172 + return ret; 173 + } 174 + 175 + static struct jffs2_tmp_dnode_info *jffs2_lookup_tn(struct rb_root *tn_root, uint32_t offset) 176 + { 177 + struct rb_node *next; 178 + struct jffs2_tmp_dnode_info *tn = NULL; 179 + 180 + dbg_readinode("root %p, offset %d\n", tn_root, offset); 181 + 182 + next = tn_root->rb_node; 183 + 184 + while (next) { 185 + tn = rb_entry(next, struct jffs2_tmp_dnode_info, rb); 186 + 187 + if (tn->fn->ofs < offset) 188 + next = tn->rb.rb_right; 189 + else if (tn->fn->ofs >= offset) 190 + next = tn->rb.rb_left; 191 + else 192 + break; 193 + } 194 + 195 + return tn; 196 + } 197 + 198 + 199 + static void jffs2_kill_tn(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn) 200 + { 201 + jffs2_mark_node_obsolete(c, tn->fn->raw); 202 + jffs2_free_full_dnode(tn->fn); 203 + jffs2_free_tmp_dnode_info(tn); 204 + } 205 + /* 206 + * This function is used when we read an inode. Data nodes arrive in 207 + * arbitrary order -- they may be older or newer than the nodes which 208 + * are already in the tree. Where overlaps occur, the older node can 209 + * be discarded as long as the newer passes the CRC check. We don't 210 + * bother to keep track of holes in this rbtree, and neither do we deal 211 + * with frags -- we can have multiple entries starting at the same 212 + * offset, and the one with the smallest length will come first in the 213 + * ordering. 214 + * 215 + * Returns 0 if the node was inserted 216 + * 1 if the node is obsolete (because we can't mark it so yet) 217 + * < 0 an if error occurred 218 + */ 219 + static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, 220 + struct jffs2_readinode_info *rii, 221 + struct jffs2_tmp_dnode_info *tn) 222 + { 223 + uint32_t fn_end = tn->fn->ofs + tn->fn->size; 224 + struct jffs2_tmp_dnode_info *insert_point = NULL, *this; 225 + 226 + dbg_readinode("insert fragment %#04x-%#04x, ver %u\n", tn->fn->ofs, fn_end, tn->version); 227 + 228 + /* If a node has zero dsize, we only have to keep if it if it might be the 229 + node with highest version -- i.e. the one which will end up as f->metadata. 230 + Note that such nodes won't be REF_UNCHECKED since there are no data to 231 + check anyway. */ 232 + if (!tn->fn->size) { 233 + if (rii->mdata_tn) { 234 + /* We had a candidate mdata node already */ 235 + dbg_readinode("kill old mdata with ver %d\n", rii->mdata_tn->version); 236 + jffs2_kill_tn(c, rii->mdata_tn); 237 + } 238 + rii->mdata_tn = tn; 239 + dbg_readinode("keep new mdata with ver %d\n", tn->version); 240 + return 0; 241 + } 242 + 243 + /* Find the earliest node which _may_ be relevant to this one */ 244 + this = jffs2_lookup_tn(&rii->tn_root, tn->fn->ofs); 245 + if (!this) { 246 + /* First addition to empty tree. $DEITY how I love the easy cases */ 247 + rb_link_node(&tn->rb, NULL, &rii->tn_root.rb_node); 248 + rb_insert_color(&tn->rb, &rii->tn_root); 249 + dbg_readinode("keep new frag\n"); 250 + return 0; 251 + } 252 + 253 + /* If we add a new node it'll be somewhere under here. */ 254 + insert_point = this; 255 + 256 + /* If the node is coincident with another at a lower address, 257 + back up until the other node is found. It may be relevant */ 258 + while (tn->overlapped) 259 + tn = tn_prev(tn); 260 + 261 + dbg_readinode("'this' found %#04x-%#04x (%s)\n", this->fn->ofs, this->fn->ofs + this->fn->size, this->fn ? "data" : "hole"); 262 + 263 + while (this) { 264 + if (this->fn->ofs > fn_end) 265 + break; 266 + dbg_readinode("Ponder this ver %d, 0x%x-0x%x\n", 267 + this->version, this->fn->ofs, this->fn->size); 268 + 269 + if (this->version == tn->version) { 270 + /* Version number collision means REF_PRISTINE GC. Accept either of them 271 + as long as the CRC is correct. Check the one we have already... */ 272 + if (!check_tn_node(c, this)) { 273 + /* The one we already had was OK. Keep it and throw away the new one */ 274 + dbg_readinode("Like old node. Throw away new\n"); 275 + jffs2_kill_tn(c, tn); 276 + return 0; 277 + } else { 278 + /* Who cares if the new one is good; keep it for now anyway. */ 279 + rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); 280 + /* Same overlapping from in front and behind */ 281 + tn->overlapped = this->overlapped; 282 + jffs2_kill_tn(c, this); 283 + dbg_readinode("Like new node. Throw away old\n"); 284 + return 0; 285 + } 286 + } 287 + if (this->version < tn->version && 288 + this->fn->ofs >= tn->fn->ofs && 289 + this->fn->ofs + this->fn->size <= fn_end) { 290 + /* New node entirely overlaps 'this' */ 291 + if (check_tn_node(c, tn)) { 292 + dbg_readinode("new node bad CRC\n"); 293 + jffs2_kill_tn(c, tn); 294 + return 0; 295 + } 296 + /* ... and is good. Kill 'this'... */ 297 + rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); 298 + tn->overlapped = this->overlapped; 299 + jffs2_kill_tn(c, this); 300 + /* ... and any subsequent nodes which are also overlapped */ 301 + this = tn_next(tn); 302 + while (this && this->fn->ofs + this->fn->size < fn_end) { 303 + struct jffs2_tmp_dnode_info *next = tn_next(this); 304 + if (this->version < tn->version) { 305 + tn_erase(this, &rii->tn_root); 306 + dbg_readinode("Kill overlapped ver %d, 0x%x-0x%x\n", 307 + this->version, this->fn->ofs, 308 + this->fn->ofs+this->fn->size); 309 + jffs2_kill_tn(c, this); 310 + } 311 + this = next; 312 + } 313 + dbg_readinode("Done inserting new\n"); 314 + return 0; 315 + } 316 + if (this->version > tn->version && 317 + this->fn->ofs <= tn->fn->ofs && 318 + this->fn->ofs+this->fn->size >= fn_end) { 319 + /* New node entirely overlapped by 'this' */ 320 + if (!check_tn_node(c, this)) { 321 + dbg_readinode("Good CRC on old node. Kill new\n"); 322 + jffs2_kill_tn(c, tn); 323 + return 0; 324 + } 325 + /* ... but 'this' was bad. Replace it... */ 326 + rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); 327 + dbg_readinode("Bad CRC on old overlapping node. Kill it\n"); 328 + jffs2_kill_tn(c, this); 329 + return 0; 330 + } 331 + /* We want to be inserted under the last node which is 332 + either at a lower offset _or_ has a smaller range */ 333 + if (this->fn->ofs < tn->fn->ofs || 334 + (this->fn->ofs == tn->fn->ofs && 335 + this->fn->size <= tn->fn->size)) 336 + insert_point = this; 337 + 338 + this = tn_next(this); 339 + } 340 + dbg_readinode("insert_point %p, ver %d, 0x%x-0x%x, ov %d\n", 341 + insert_point, insert_point->version, insert_point->fn->ofs, 342 + insert_point->fn->ofs+insert_point->fn->size, 343 + insert_point->overlapped); 344 + /* We neither completely obsoleted nor were completely 345 + obsoleted by an earlier node. Insert under insert_point */ 346 + { 347 + struct rb_node *parent = &insert_point->rb; 348 + struct rb_node **link = &parent; 349 + 350 + while (*link) { 351 + parent = *link; 352 + insert_point = rb_entry(parent, struct jffs2_tmp_dnode_info, rb); 353 + if (tn->fn->ofs > insert_point->fn->ofs) 354 + link = &insert_point->rb.rb_right; 355 + else if (tn->fn->ofs < insert_point->fn->ofs || 356 + tn->fn->size < insert_point->fn->size) 357 + link = &insert_point->rb.rb_left; 358 + else 359 + link = &insert_point->rb.rb_right; 360 + } 361 + rb_link_node(&tn->rb, &insert_point->rb, link); 362 + rb_insert_color(&tn->rb, &rii->tn_root); 363 + } 364 + /* If there's anything behind that overlaps us, note it */ 365 + this = tn_prev(tn); 366 + if (this) { 367 + while (1) { 368 + if (this->fn->ofs + this->fn->size > tn->fn->ofs) { 369 + dbg_readinode("Node is overlapped by %p (v %d, 0x%x-0x%x)\n", 370 + this, this->version, this->fn->ofs, 371 + this->fn->ofs+this->fn->size); 372 + tn->overlapped = 1; 373 + break; 374 + } 375 + if (!this->overlapped) 376 + break; 377 + this = tn_prev(this); 378 + } 379 + } 380 + 381 + /* If the new node overlaps anything ahead, note it */ 382 + this = tn_next(tn); 383 + while (this && this->fn->ofs < fn_end) { 384 + this->overlapped = 1; 385 + dbg_readinode("Node ver %d, 0x%x-0x%x is overlapped\n", 386 + this->version, this->fn->ofs, 387 + this->fn->ofs+this->fn->size); 388 + this = tn_next(this); 389 + } 390 + return 0; 391 + } 392 + 393 + /* Trivial function to remove the last node in the tree. Which by definition 394 + has no right-hand -- so can be removed just by making its only child (if 395 + any) take its place under its parent. */ 396 + static void eat_last(struct rb_root *root, struct rb_node *node) 397 + { 398 + struct rb_node *parent = rb_parent(node); 399 + struct rb_node **link; 400 + 401 + /* LAST! */ 402 + BUG_ON(node->rb_right); 403 + 404 + if (!parent) 405 + link = &root->rb_node; 406 + else if (node == parent->rb_left) 407 + link = &parent->rb_left; 408 + else 409 + link = &parent->rb_right; 410 + 411 + *link = node->rb_left; 412 + /* Colour doesn't matter now. Only the parent pointer. */ 413 + if (node->rb_left) 414 + node->rb_left->rb_parent_color = node->rb_parent_color; 415 + } 416 + 417 + /* We put this in reverse order, so we can just use eat_last */ 418 + static void ver_insert(struct rb_root *ver_root, struct jffs2_tmp_dnode_info *tn) 419 + { 420 + struct rb_node **link = &ver_root->rb_node; 421 + struct rb_node *parent = NULL; 422 + struct jffs2_tmp_dnode_info *this_tn; 423 + 424 + while (*link) { 425 + parent = *link; 426 + this_tn = rb_entry(parent, struct jffs2_tmp_dnode_info, rb); 427 + 428 + if (tn->version > this_tn->version) 429 + link = &parent->rb_left; 430 + else 431 + link = &parent->rb_right; 432 + } 433 + dbg_readinode("Link new node at %p (root is %p)\n", link, ver_root); 434 + rb_link_node(&tn->rb, parent, link); 435 + rb_insert_color(&tn->rb, ver_root); 436 + } 437 + 438 + /* Build final, normal fragtree from tn tree. It doesn't matter which order 439 + we add nodes to the real fragtree, as long as they don't overlap. And 440 + having thrown away the majority of overlapped nodes as we went, there 441 + really shouldn't be many sets of nodes which do overlap. If we start at 442 + the end, we can use the overlap markers -- we can just eat nodes which 443 + aren't overlapped, and when we encounter nodes which _do_ overlap we 444 + sort them all into a temporary tree in version order before replaying them. */ 445 + static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c, 446 + struct jffs2_inode_info *f, 447 + struct jffs2_readinode_info *rii) 448 + { 449 + struct jffs2_tmp_dnode_info *pen, *last, *this; 450 + struct rb_root ver_root = RB_ROOT; 451 + uint32_t high_ver = 0; 452 + 453 + if (rii->mdata_tn) { 454 + dbg_readinode("potential mdata is ver %d at %p\n", rii->mdata_tn->version, rii->mdata_tn); 455 + high_ver = rii->mdata_tn->version; 456 + rii->latest_ref = rii->mdata_tn->fn->raw; 457 + } 458 + #ifdef JFFS2_DBG_READINODE_MESSAGES 459 + this = tn_last(&rii->tn_root); 460 + while (this) { 461 + dbg_readinode("tn %p ver %d range 0x%x-0x%x ov %d\n", this, this->version, this->fn->ofs, 462 + this->fn->ofs+this->fn->size, this->overlapped); 463 + this = tn_prev(this); 464 + } 465 + #endif 466 + pen = tn_last(&rii->tn_root); 467 + while ((last = pen)) { 468 + pen = tn_prev(last); 469 + 470 + eat_last(&rii->tn_root, &last->rb); 471 + ver_insert(&ver_root, last); 472 + 473 + if (unlikely(last->overlapped)) 474 + continue; 475 + 476 + /* Now we have a bunch of nodes in reverse version 477 + order, in the tree at ver_root. Most of the time, 478 + there'll actually be only one node in the 'tree', 479 + in fact. */ 480 + this = tn_last(&ver_root); 481 + 482 + while (this) { 483 + struct jffs2_tmp_dnode_info *vers_next; 484 + int ret; 485 + vers_next = tn_prev(this); 486 + eat_last(&ver_root, &this->rb); 487 + if (check_tn_node(c, this)) { 488 + dbg_readinode("node ver %x, 0x%x-0x%x failed CRC\n", 489 + this->version, this->fn->ofs, 490 + this->fn->ofs+this->fn->size); 491 + jffs2_kill_tn(c, this); 492 + } else { 493 + if (this->version > high_ver) { 494 + /* Note that this is different from the other 495 + highest_version, because this one is only 496 + counting _valid_ nodes which could give the 497 + latest inode metadata */ 498 + high_ver = this->version; 499 + rii->latest_ref = this->fn->raw; 500 + } 501 + dbg_readinode("Add %p (v %x, 0x%x-0x%x, ov %d) to fragtree\n", 502 + this, this->version, this->fn->ofs, 503 + this->fn->ofs+this->fn->size, this->overlapped); 504 + 505 + ret = jffs2_add_full_dnode_to_inode(c, f, this->fn); 506 + if (ret) { 507 + /* Free the nodes in vers_root; let the caller 508 + deal with the rest */ 509 + JFFS2_ERROR("Add node to tree failed %d\n", ret); 510 + while (1) { 511 + vers_next = tn_prev(this); 512 + if (check_tn_node(c, this)) 513 + jffs2_mark_node_obsolete(c, this->fn->raw); 514 + jffs2_free_full_dnode(this->fn); 515 + jffs2_free_tmp_dnode_info(this); 516 + this = vers_next; 517 + if (!this) 518 + break; 519 + eat_last(&ver_root, &vers_next->rb); 520 + } 521 + return ret; 522 + } 523 + jffs2_free_tmp_dnode_info(this); 524 + } 525 + this = vers_next; 526 + } 527 + } 528 + return 0; 47 529 } 48 530 49 531 static void jffs2_free_tmp_dnode_info_list(struct rb_root *list) ··· 590 112 * negative error code on failure. 591 113 */ 592 114 static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, 593 - struct jffs2_raw_dirent *rd, size_t read, struct jffs2_full_dirent **fdp, 594 - uint32_t *latest_mctime, uint32_t *mctime_ver) 115 + struct jffs2_raw_dirent *rd, size_t read, 116 + struct jffs2_readinode_info *rii) 595 117 { 596 118 struct jffs2_full_dirent *fd; 597 119 uint32_t crc; ··· 603 125 if (unlikely(crc != je32_to_cpu(rd->node_crc))) { 604 126 JFFS2_NOTICE("header CRC failed on dirent node at %#08x: read %#08x, calculated %#08x\n", 605 127 ref_offset(ref), je32_to_cpu(rd->node_crc), crc); 606 - return 1; 128 + jffs2_mark_node_obsolete(c, ref); 129 + return 0; 607 130 } 608 131 609 132 /* If we've never checked the CRCs on this node, check them now */ ··· 616 137 if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) { 617 138 JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n", 618 139 ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen)); 619 - return 1; 140 + jffs2_mark_node_obsolete(c, ref); 141 + return 0; 620 142 } 621 143 622 144 jeb = &c->blocks[ref->flash_offset / c->sector_size]; ··· 641 161 fd->ino = je32_to_cpu(rd->ino); 642 162 fd->type = rd->type; 643 163 164 + if (fd->version > rii->highest_version) 165 + rii->highest_version = fd->version; 166 + 644 167 /* Pick out the mctime of the latest dirent */ 645 - if(fd->version > *mctime_ver && je32_to_cpu(rd->mctime)) { 646 - *mctime_ver = fd->version; 647 - *latest_mctime = je32_to_cpu(rd->mctime); 168 + if(fd->version > rii->mctime_ver && je32_to_cpu(rd->mctime)) { 169 + rii->mctime_ver = fd->version; 170 + rii->latest_mctime = je32_to_cpu(rd->mctime); 648 171 } 649 172 650 173 /* ··· 684 201 * Wheee. We now have a complete jffs2_full_dirent structure, with 685 202 * the name in it and everything. Link it into the list 686 203 */ 687 - jffs2_add_fd_to_list(c, fd, fdp); 204 + jffs2_add_fd_to_list(c, fd, &rii->fds); 688 205 689 206 return 0; 690 207 } ··· 693 210 * Helper function for jffs2_get_inode_nodes(). 694 211 * It is called every time an inode node is found. 695 212 * 696 - * Returns: 0 on succes; 213 + * Returns: 0 on success; 697 214 * 1 if the node should be marked obsolete; 698 215 * negative error code on failure. 699 216 */ 700 217 static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, 701 - struct jffs2_raw_inode *rd, struct rb_root *tnp, int rdlen, 702 - uint32_t *latest_mctime, uint32_t *mctime_ver) 218 + struct jffs2_raw_inode *rd, int rdlen, 219 + struct jffs2_readinode_info *rii) 703 220 { 704 221 struct jffs2_tmp_dnode_info *tn; 705 222 uint32_t len, csize; ··· 713 230 if (unlikely(crc != je32_to_cpu(rd->node_crc))) { 714 231 JFFS2_NOTICE("node CRC failed on dnode at %#08x: read %#08x, calculated %#08x\n", 715 232 ref_offset(ref), je32_to_cpu(rd->node_crc), crc); 716 - return 1; 233 + jffs2_mark_node_obsolete(c, ref); 234 + return 0; 717 235 } 718 236 719 237 tn = jffs2_alloc_tmp_dnode_info(); ··· 826 342 tn->data_crc = je32_to_cpu(rd->data_crc); 827 343 tn->csize = csize; 828 344 tn->fn->raw = ref; 345 + tn->overlapped = 0; 346 + 347 + if (tn->version > rii->highest_version) 348 + rii->highest_version = tn->version; 829 349 830 350 /* There was a bug where we wrote hole nodes out with 831 351 csize/dsize swapped. Deal with it */ ··· 841 353 dbg_readinode("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n", 842 354 ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize); 843 355 844 - jffs2_add_tn_to_tree(tn, tnp); 356 + ret = jffs2_add_tn_to_tree(c, rii, tn); 845 357 358 + if (ret) { 359 + jffs2_free_full_dnode(tn->fn); 360 + free_out: 361 + jffs2_free_tmp_dnode_info(tn); 362 + return ret; 363 + } 364 + #ifdef JFFS2_DBG_READINODE_MESSAGES 365 + dbg_readinode("After adding ver %d:\n", tn->version); 366 + tn = tn_first(&rii->tn_root); 367 + while (tn) { 368 + dbg_readinode("%p: v %d r 0x%x-0x%x ov %d\n", 369 + tn, tn->version, tn->fn->ofs, 370 + tn->fn->ofs+tn->fn->size, tn->overlapped); 371 + tn = tn_next(tn); 372 + } 373 + #endif 846 374 return 0; 847 - 848 - free_out: 849 - jffs2_free_tmp_dnode_info(tn); 850 - return ret; 851 375 } 852 376 853 377 /* ··· 879 379 JFFS2_ERROR("Node is {%04x,%04x,%08x,%08x}. Please report this error.\n", 880 380 je16_to_cpu(un->magic), je16_to_cpu(un->nodetype), 881 381 je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc)); 882 - return 1; 382 + jffs2_mark_node_obsolete(c, ref); 383 + return 0; 883 384 } 884 385 885 386 un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype)); ··· 908 407 case JFFS2_FEATURE_RWCOMPAT_DELETE: 909 408 JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n", 910 409 je16_to_cpu(un->nodetype), ref_offset(ref)); 911 - return 1; 410 + jffs2_mark_node_obsolete(c, ref); 411 + return 0; 912 412 } 913 413 914 414 return 0; ··· 923 421 * negative error code on failure. 924 422 */ 925 423 static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, 926 - int right_size, int *rdlen, unsigned char *buf, unsigned char *bufstart) 424 + int needed_len, int *rdlen, unsigned char *buf) 927 425 { 928 - int right_len, err, len; 426 + int err, to_read = needed_len - *rdlen; 929 427 size_t retlen; 930 428 uint32_t offs; 931 429 932 430 if (jffs2_is_writebuffered(c)) { 933 - right_len = c->wbuf_pagesize - (bufstart - buf); 934 - if (right_size + (int)(bufstart - buf) > c->wbuf_pagesize) 935 - right_len += c->wbuf_pagesize; 936 - } else 937 - right_len = right_size; 431 + int rem = to_read % c->wbuf_pagesize; 938 432 939 - if (*rdlen == right_len) 940 - return 0; 433 + if (rem) 434 + to_read += c->wbuf_pagesize - rem; 435 + } 941 436 942 437 /* We need to read more data */ 943 438 offs = ref_offset(ref) + *rdlen; 944 - if (jffs2_is_writebuffered(c)) { 945 - bufstart = buf + c->wbuf_pagesize; 946 - len = c->wbuf_pagesize; 947 - } else { 948 - bufstart = buf + *rdlen; 949 - len = right_size - *rdlen; 950 - } 951 439 952 - dbg_readinode("read more %d bytes\n", len); 440 + dbg_readinode("read more %d bytes\n", to_read); 953 441 954 - err = jffs2_flash_read(c, offs, len, &retlen, bufstart); 442 + err = jffs2_flash_read(c, offs, to_read, &retlen, buf + *rdlen); 955 443 if (err) { 956 444 JFFS2_ERROR("can not read %d bytes from 0x%08x, " 957 - "error code: %d.\n", len, offs, err); 445 + "error code: %d.\n", to_read, offs, err); 958 446 return err; 959 447 } 960 448 961 - if (retlen < len) { 449 + if (retlen < to_read) { 962 450 JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n", 963 - offs, retlen, len); 451 + offs, retlen, to_read); 964 452 return -EIO; 965 453 } 966 454 967 - *rdlen = right_len; 968 - 455 + *rdlen += to_read; 969 456 return 0; 970 457 } 971 458 972 459 /* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated 973 - with this ino, returning the former in order of version */ 460 + with this ino. Perform a preliminary ordering on data nodes, throwing away 461 + those which are completely obsoleted by newer ones. The naïve approach we 462 + use to take of just returning them _all_ in version order will cause us to 463 + run out of memory in certain degenerate cases. */ 974 464 static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f, 975 - struct rb_root *tnp, struct jffs2_full_dirent **fdp, 976 - uint32_t *highest_version, uint32_t *latest_mctime, 977 - uint32_t *mctime_ver) 465 + struct jffs2_readinode_info *rii) 978 466 { 979 467 struct jffs2_raw_node_ref *ref, *valid_ref; 980 - struct rb_root ret_tn = RB_ROOT; 981 - struct jffs2_full_dirent *ret_fd = NULL; 982 468 unsigned char *buf = NULL; 983 469 union jffs2_node_union *node; 984 470 size_t retlen; 985 471 int len, err; 986 472 987 - *mctime_ver = 0; 473 + rii->mctime_ver = 0; 988 474 989 475 dbg_readinode("ino #%u\n", f->inocache->ino); 990 476 991 - if (jffs2_is_writebuffered(c)) { 992 - /* 993 - * If we have the write buffer, we assume the minimal I/O unit 994 - * is c->wbuf_pagesize. We implement some optimizations which in 995 - * this case and we need a temporary buffer of size = 996 - * 2*c->wbuf_pagesize bytes (see comments in read_dnode()). 997 - * Basically, we want to read not only the node header, but the 998 - * whole wbuf (NAND page in case of NAND) or 2, if the node 999 - * header overlaps the border between the 2 wbufs. 1000 - */ 1001 - len = 2*c->wbuf_pagesize; 1002 - } else { 1003 - /* 1004 - * When there is no write buffer, the size of the temporary 1005 - * buffer is the size of the larges node header. 1006 - */ 1007 - len = sizeof(union jffs2_node_union); 1008 - } 1009 - 1010 477 /* FIXME: in case of NOR and available ->point() this 1011 478 * needs to be fixed. */ 479 + len = sizeof(union jffs2_node_union) + c->wbuf_pagesize; 1012 480 buf = kmalloc(len, GFP_KERNEL); 1013 481 if (!buf) 1014 482 return -ENOMEM; ··· 988 516 if (!valid_ref && f->inocache->ino != 1) 989 517 JFFS2_WARNING("Eep. No valid nodes for ino #%u.\n", f->inocache->ino); 990 518 while (valid_ref) { 991 - unsigned char *bufstart; 992 - 993 519 /* We can hold a pointer to a non-obsolete node without the spinlock, 994 520 but _obsolete_ nodes may disappear at any time, if the block 995 521 they're in gets erased. So if we mark 'ref' obsolete while we're ··· 1003 533 /* 1004 534 * At this point we don't know the type of the node we're going 1005 535 * to read, so we do not know the size of its header. In order 1006 - * to minimize the amount of flash IO we assume the node has 1007 - * size = JFFS2_MIN_NODE_HEADER. 536 + * to minimize the amount of flash IO we assume the header is 537 + * of size = JFFS2_MIN_NODE_HEADER. 1008 538 */ 539 + len = JFFS2_MIN_NODE_HEADER; 1009 540 if (jffs2_is_writebuffered(c)) { 541 + int end, rem; 542 + 1010 543 /* 1011 - * We treat 'buf' as 2 adjacent wbufs. We want to 1012 - * adjust bufstart such as it points to the 1013 - * beginning of the node within this wbuf. 544 + * We are about to read JFFS2_MIN_NODE_HEADER bytes, 545 + * but this flash has some minimal I/O unit. It is 546 + * possible that we'll need to read more soon, so read 547 + * up to the next min. I/O unit, in order not to 548 + * re-read the same min. I/O unit twice. 1014 549 */ 1015 - bufstart = buf + (ref_offset(ref) % c->wbuf_pagesize); 1016 - /* We will read either one wbuf or 2 wbufs. */ 1017 - len = c->wbuf_pagesize - (bufstart - buf); 1018 - if (JFFS2_MIN_NODE_HEADER + (int)(bufstart - buf) > c->wbuf_pagesize) { 1019 - /* The header spans the border of the first wbuf */ 1020 - len += c->wbuf_pagesize; 1021 - } 1022 - } else { 1023 - bufstart = buf; 1024 - len = JFFS2_MIN_NODE_HEADER; 550 + end = ref_offset(ref) + len; 551 + rem = end % c->wbuf_pagesize; 552 + if (rem) 553 + end += c->wbuf_pagesize - rem; 554 + len = end - ref_offset(ref); 1025 555 } 1026 556 1027 557 dbg_readinode("read %d bytes at %#08x(%d).\n", len, ref_offset(ref), ref_flags(ref)); 1028 558 1029 559 /* FIXME: point() */ 1030 - err = jffs2_flash_read(c, ref_offset(ref), len, 1031 - &retlen, bufstart); 560 + err = jffs2_flash_read(c, ref_offset(ref), len, &retlen, buf); 1032 561 if (err) { 1033 562 JFFS2_ERROR("can not read %d bytes from 0x%08x, " "error code: %d.\n", len, ref_offset(ref), err); 1034 563 goto free_out; ··· 1039 570 goto free_out; 1040 571 } 1041 572 1042 - node = (union jffs2_node_union *)bufstart; 573 + node = (union jffs2_node_union *)buf; 1043 574 1044 575 /* No need to mask in the valid bit; it shouldn't be invalid */ 1045 576 if (je32_to_cpu(node->u.hdr_crc) != crc32(0, node, sizeof(node->u)-4)) { ··· 1052 583 jffs2_mark_node_obsolete(c, ref); 1053 584 goto cont; 1054 585 } 1055 - /* Due to poor choice of crc32 seed, an all-zero node will have a correct CRC */ 1056 - if (!je32_to_cpu(node->u.hdr_crc) && !je16_to_cpu(node->u.nodetype) && 1057 - !je16_to_cpu(node->u.magic) && !je32_to_cpu(node->u.totlen)) { 1058 - JFFS2_NOTICE("All zero node header at %#08x.\n", ref_offset(ref)); 586 + if (je16_to_cpu(node->u.magic) != JFFS2_MAGIC_BITMASK) { 587 + /* Not a JFFS2 node, whinge and move on */ 588 + JFFS2_NOTICE("Wrong magic bitmask 0x%04x in node header at %#08x.\n", 589 + je16_to_cpu(node->u.magic), ref_offset(ref)); 1059 590 jffs2_mark_node_obsolete(c, ref); 1060 591 goto cont; 1061 592 } ··· 1065 596 case JFFS2_NODETYPE_DIRENT: 1066 597 1067 598 if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent)) { 1068 - err = read_more(c, ref, sizeof(struct jffs2_raw_dirent), &len, buf, bufstart); 599 + err = read_more(c, ref, sizeof(struct jffs2_raw_dirent), &len, buf); 1069 600 if (unlikely(err)) 1070 601 goto free_out; 1071 602 } 1072 603 1073 - err = read_direntry(c, ref, &node->d, retlen, &ret_fd, latest_mctime, mctime_ver); 1074 - if (err == 1) { 1075 - jffs2_mark_node_obsolete(c, ref); 1076 - break; 1077 - } else if (unlikely(err)) 604 + err = read_direntry(c, ref, &node->d, retlen, rii); 605 + if (unlikely(err)) 1078 606 goto free_out; 1079 - 1080 - if (je32_to_cpu(node->d.version) > *highest_version) 1081 - *highest_version = je32_to_cpu(node->d.version); 1082 607 1083 608 break; 1084 609 1085 610 case JFFS2_NODETYPE_INODE: 1086 611 1087 612 if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode)) { 1088 - err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf, bufstart); 613 + err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf); 1089 614 if (unlikely(err)) 1090 615 goto free_out; 1091 616 } 1092 617 1093 - err = read_dnode(c, ref, &node->i, &ret_tn, len, latest_mctime, mctime_ver); 1094 - if (err == 1) { 1095 - jffs2_mark_node_obsolete(c, ref); 1096 - break; 1097 - } else if (unlikely(err)) 618 + err = read_dnode(c, ref, &node->i, len, rii); 619 + if (unlikely(err)) 1098 620 goto free_out; 1099 - 1100 - if (je32_to_cpu(node->i.version) > *highest_version) 1101 - *highest_version = je32_to_cpu(node->i.version); 1102 621 1103 622 break; 1104 623 1105 624 default: 1106 625 if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_unknown_node)) { 1107 - err = read_more(c, ref, sizeof(struct jffs2_unknown_node), &len, buf, bufstart); 626 + err = read_more(c, ref, sizeof(struct jffs2_unknown_node), &len, buf); 1108 627 if (unlikely(err)) 1109 628 goto free_out; 1110 629 } ··· 1110 653 } 1111 654 1112 655 spin_unlock(&c->erase_completion_lock); 1113 - *tnp = ret_tn; 1114 - *fdp = ret_fd; 1115 656 kfree(buf); 1116 657 658 + f->highest_version = rii->highest_version; 659 + 1117 660 dbg_readinode("nodes of inode #%u were read, the highest version is %u, latest_mctime %u, mctime_ver %u.\n", 1118 - f->inocache->ino, *highest_version, *latest_mctime, *mctime_ver); 661 + f->inocache->ino, rii->highest_version, rii->latest_mctime, 662 + rii->mctime_ver); 1119 663 return 0; 1120 664 1121 665 free_out: 1122 - jffs2_free_tmp_dnode_info_list(&ret_tn); 1123 - jffs2_free_full_dirent_list(ret_fd); 666 + jffs2_free_tmp_dnode_info_list(&rii->tn_root); 667 + jffs2_free_full_dirent_list(rii->fds); 668 + rii->fds = NULL; 1124 669 kfree(buf); 1125 670 return err; 1126 671 } ··· 1131 672 struct jffs2_inode_info *f, 1132 673 struct jffs2_raw_inode *latest_node) 1133 674 { 1134 - struct jffs2_tmp_dnode_info *tn; 1135 - struct rb_root tn_list; 1136 - struct rb_node *rb, *repl_rb; 1137 - struct jffs2_full_dirent *fd_list; 1138 - struct jffs2_full_dnode *fn, *first_fn = NULL; 1139 - uint32_t crc; 1140 - uint32_t latest_mctime, mctime_ver; 675 + struct jffs2_readinode_info rii; 676 + uint32_t crc, new_size; 1141 677 size_t retlen; 1142 678 int ret; 1143 679 1144 680 dbg_readinode("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink); 1145 681 682 + memset(&rii, 0, sizeof(rii)); 683 + 1146 684 /* Grab all nodes relevant to this ino */ 1147 - ret = jffs2_get_inode_nodes(c, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver); 685 + ret = jffs2_get_inode_nodes(c, f, &rii); 1148 686 1149 687 if (ret) { 1150 688 JFFS2_ERROR("cannot read nodes for ino %u, returned error is %d\n", f->inocache->ino, ret); ··· 1149 693 jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); 1150 694 return ret; 1151 695 } 1152 - f->dents = fd_list; 1153 696 1154 - rb = rb_first(&tn_list); 1155 - 1156 - while (rb) { 1157 - cond_resched(); 1158 - tn = rb_entry(rb, struct jffs2_tmp_dnode_info, rb); 1159 - fn = tn->fn; 1160 - ret = 1; 1161 - dbg_readinode("consider node ver %u, phys offset " 1162 - "%#08x(%d), range %u-%u.\n", tn->version, 1163 - ref_offset(fn->raw), ref_flags(fn->raw), 1164 - fn->ofs, fn->ofs + fn->size); 1165 - 1166 - if (fn->size) { 1167 - ret = jffs2_add_older_frag_to_fragtree(c, f, tn); 1168 - /* TODO: the error code isn't checked, check it */ 1169 - jffs2_dbg_fragtree_paranoia_check_nolock(f); 1170 - BUG_ON(ret < 0); 1171 - if (!first_fn && ret == 0) 1172 - first_fn = fn; 1173 - } else if (!first_fn) { 1174 - first_fn = fn; 1175 - f->metadata = fn; 1176 - ret = 0; /* Prevent freeing the metadata update node */ 1177 - } else 1178 - jffs2_mark_node_obsolete(c, fn->raw); 1179 - 1180 - BUG_ON(rb->rb_left); 1181 - if (rb_parent(rb) && rb_parent(rb)->rb_left == rb) { 1182 - /* We were then left-hand child of our parent. We need 1183 - * to move our own right-hand child into our place. */ 1184 - repl_rb = rb->rb_right; 1185 - if (repl_rb) 1186 - rb_set_parent(repl_rb, rb_parent(rb)); 1187 - } else 1188 - repl_rb = NULL; 1189 - 1190 - rb = rb_next(rb); 1191 - 1192 - /* Remove the spent tn from the tree; don't bother rebalancing 1193 - * but put our right-hand child in our own place. */ 1194 - if (rb_parent(&tn->rb)) { 1195 - if (rb_parent(&tn->rb)->rb_left == &tn->rb) 1196 - rb_parent(&tn->rb)->rb_left = repl_rb; 1197 - else if (rb_parent(&tn->rb)->rb_right == &tn->rb) 1198 - rb_parent(&tn->rb)->rb_right = repl_rb; 1199 - else BUG(); 1200 - } else if (tn->rb.rb_right) 1201 - rb_set_parent(tn->rb.rb_right, NULL); 1202 - 1203 - jffs2_free_tmp_dnode_info(tn); 1204 - if (ret) { 1205 - dbg_readinode("delete dnode %u-%u.\n", 1206 - fn->ofs, fn->ofs + fn->size); 1207 - jffs2_free_full_dnode(fn); 697 + ret = jffs2_build_inode_fragtree(c, f, &rii); 698 + if (ret) { 699 + JFFS2_ERROR("Failed to build final fragtree for inode #%u: error %d\n", 700 + f->inocache->ino, ret); 701 + if (f->inocache->state == INO_STATE_READING) 702 + jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); 703 + jffs2_free_tmp_dnode_info_list(&rii.tn_root); 704 + /* FIXME: We could at least crc-check them all */ 705 + if (rii.mdata_tn) { 706 + jffs2_free_full_dnode(rii.mdata_tn->fn); 707 + jffs2_free_tmp_dnode_info(rii.mdata_tn); 708 + rii.mdata_tn = NULL; 1208 709 } 710 + return ret; 1209 711 } 712 + 713 + if (rii.mdata_tn) { 714 + if (rii.mdata_tn->fn->raw == rii.latest_ref) { 715 + f->metadata = rii.mdata_tn->fn; 716 + jffs2_free_tmp_dnode_info(rii.mdata_tn); 717 + } else { 718 + jffs2_kill_tn(c, rii.mdata_tn); 719 + } 720 + rii.mdata_tn = NULL; 721 + } 722 + 723 + f->dents = rii.fds; 724 + 1210 725 jffs2_dbg_fragtree_paranoia_check_nolock(f); 1211 726 1212 - BUG_ON(first_fn && ref_obsolete(first_fn->raw)); 1213 - 1214 - fn = first_fn; 1215 - if (unlikely(!first_fn)) { 727 + if (unlikely(!rii.latest_ref)) { 1216 728 /* No data nodes for this inode. */ 1217 729 if (f->inocache->ino != 1) { 1218 730 JFFS2_WARNING("no data nodes found for ino #%u\n", f->inocache->ino); 1219 - if (!fd_list) { 731 + if (!rii.fds) { 1220 732 if (f->inocache->state == INO_STATE_READING) 1221 733 jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); 1222 734 return -EIO; ··· 1202 778 return 0; 1203 779 } 1204 780 1205 - ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(*latest_node), &retlen, (void *)latest_node); 781 + ret = jffs2_flash_read(c, ref_offset(rii.latest_ref), sizeof(*latest_node), &retlen, (void *)latest_node); 1206 782 if (ret || retlen != sizeof(*latest_node)) { 1207 783 JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n", 1208 784 ret, retlen, sizeof(*latest_node)); ··· 1215 791 crc = crc32(0, latest_node, sizeof(*latest_node)-8); 1216 792 if (crc != je32_to_cpu(latest_node->node_crc)) { 1217 793 JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n", 1218 - f->inocache->ino, ref_offset(fn->raw)); 794 + f->inocache->ino, ref_offset(rii.latest_ref)); 1219 795 up(&f->sem); 1220 796 jffs2_do_clear_inode(c, f); 1221 797 return -EIO; ··· 1223 799 1224 800 switch(jemode_to_cpu(latest_node->mode) & S_IFMT) { 1225 801 case S_IFDIR: 1226 - if (mctime_ver > je32_to_cpu(latest_node->version)) { 802 + if (rii.mctime_ver > je32_to_cpu(latest_node->version)) { 1227 803 /* The times in the latest_node are actually older than 1228 804 mctime in the latest dirent. Cheat. */ 1229 - latest_node->ctime = latest_node->mtime = cpu_to_je32(latest_mctime); 805 + latest_node->ctime = latest_node->mtime = cpu_to_je32(rii.latest_mctime); 1230 806 } 1231 807 break; 1232 808 1233 809 1234 810 case S_IFREG: 1235 811 /* If it was a regular file, truncate it to the latest node's isize */ 1236 - jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize)); 812 + new_size = jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize)); 813 + if (new_size != je32_to_cpu(latest_node->isize)) { 814 + JFFS2_WARNING("Truncating ino #%u to %d bytes failed because it only had %d bytes to start with!\n", 815 + f->inocache->ino, je32_to_cpu(latest_node->isize), new_size); 816 + latest_node->isize = cpu_to_je32(new_size); 817 + } 1237 818 break; 1238 819 1239 820 case S_IFLNK: ··· 1261 832 return -ENOMEM; 1262 833 } 1263 834 1264 - ret = jffs2_flash_read(c, ref_offset(fn->raw) + sizeof(*latest_node), 835 + ret = jffs2_flash_read(c, ref_offset(rii.latest_ref) + sizeof(*latest_node), 1265 836 je32_to_cpu(latest_node->csize), &retlen, (char *)f->target); 1266 837 1267 838 if (ret || retlen != je32_to_cpu(latest_node->csize)) {
+29 -33
fs/jffs2/scan.c
··· 1 1 /* 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 6 * Created by David Woodhouse <dwmw2@infradead.org> 7 7 * 8 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 12 #include <linux/kernel.h> 14 13 #include <linux/sched.h> 15 14 #include <linux/slab.h> ··· 635 636 636 637 if (*(uint32_t *)(&buf[ofs-buf_ofs]) == 0xffffffff) { 637 638 uint32_t inbuf_ofs; 638 - uint32_t empty_start; 639 + uint32_t empty_start, scan_end; 639 640 640 641 empty_start = ofs; 641 642 ofs += 4; 643 + scan_end = min_t(uint32_t, EMPTY_SCAN_SIZE(c->sector_size)/8, buf_len); 642 644 643 645 D1(printk(KERN_DEBUG "Found empty flash at 0x%08x\n", ofs)); 644 646 more_empty: 645 647 inbuf_ofs = ofs - buf_ofs; 646 - while (inbuf_ofs < buf_len) { 647 - if (*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff) { 648 + while (inbuf_ofs < scan_end) { 649 + if (unlikely(*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff)) { 648 650 printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x\n", 649 651 empty_start, ofs); 650 652 if ((err = jffs2_scan_dirty_space(c, jeb, ofs-empty_start))) ··· 666 666 D1(printk(KERN_DEBUG "%d bytes at start of block seems clean... assuming all clean\n", EMPTY_SCAN_SIZE(c->sector_size))); 667 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 674 /* See how much more there is to read in this eraseblock... */ 671 675 buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); 672 676 if (!buf_len) { ··· 680 676 empty_start)); 681 677 break; 682 678 } 679 + /* point never reaches here */ 680 + scan_end = buf_len; 683 681 D1(printk(KERN_DEBUG "Reading another 0x%x at 0x%08x\n", buf_len, ofs)); 684 682 err = jffs2_fill_scan_buf(c, buf, ofs, buf_len); 685 683 if (err) ··· 740 734 ofs += 4; 741 735 continue; 742 736 } 743 - /* Due to poor choice of crc32 seed, an all-zero node will have a correct CRC */ 744 - if (!je32_to_cpu(node->hdr_crc) && !je16_to_cpu(node->nodetype) && 745 - !je16_to_cpu(node->magic) && !je32_to_cpu(node->totlen)) { 746 - noisy_printk(&noise, "jffs2_scan_eraseblock(): All zero node header at 0x%08x.\n", ofs); 747 - if ((err = jffs2_scan_dirty_space(c, jeb, 4))) 748 - return err; 749 - ofs += 4; 750 - continue; 751 - } 752 737 753 - if (ofs + je32_to_cpu(node->totlen) > 754 - jeb->offset + c->sector_size) { 738 + if (ofs + je32_to_cpu(node->totlen) > jeb->offset + c->sector_size) { 755 739 /* Eep. Node goes over the end of the erase block. */ 756 740 printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n", 757 741 ofs, je32_to_cpu(node->totlen)); ··· 948 952 struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s) 949 953 { 950 954 struct jffs2_inode_cache *ic; 951 - uint32_t ino = je32_to_cpu(ri->ino); 952 - int err; 955 + uint32_t crc, ino = je32_to_cpu(ri->ino); 953 956 954 957 D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", ofs)); 955 958 ··· 961 966 Which means that the _full_ amount of time to get to proper write mode with GC 962 967 operational may actually be _longer_ than before. Sucks to be me. */ 963 968 969 + /* Check the node CRC in any case. */ 970 + crc = crc32(0, ri, sizeof(*ri)-8); 971 + if (crc != je32_to_cpu(ri->node_crc)) { 972 + printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on " 973 + "node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", 974 + ofs, je32_to_cpu(ri->node_crc), crc); 975 + /* 976 + * We believe totlen because the CRC on the node 977 + * _header_ was OK, just the node itself failed. 978 + */ 979 + return jffs2_scan_dirty_space(c, jeb, 980 + PAD(je32_to_cpu(ri->totlen))); 981 + } 982 + 964 983 ic = jffs2_get_ino_cache(c, ino); 965 984 if (!ic) { 966 - /* Inocache get failed. Either we read a bogus ino# or it's just genuinely the 967 - first node we found for this inode. Do a CRC check to protect against the former 968 - case */ 969 - uint32_t crc = crc32(0, ri, sizeof(*ri)-8); 970 - 971 - if (crc != je32_to_cpu(ri->node_crc)) { 972 - printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", 973 - ofs, je32_to_cpu(ri->node_crc), crc); 974 - /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */ 975 - if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(ri->totlen))))) 976 - return err; 977 - return 0; 978 - } 979 985 ic = jffs2_scan_make_ino_cache(c, ino); 980 986 if (!ic) 981 987 return -ENOMEM;
+2 -1
fs/jffs2/security.c
··· 1 1 /* 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 6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 9 * 10 10 */ 11 + 11 12 #include <linux/kernel.h> 12 13 #include <linux/slab.h> 13 14 #include <linux/fs.h>
+5 -7
fs/jffs2/summary.c
··· 1 1 /* 2 2 * JFFS2 -- Journalling Flash File System, Version 2. 3 3 * 4 - * Copyright (C) 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>, 5 - * Zoltan Sogor <weth@inf.u-szeged.hu>, 6 - * Patrik Kluba <pajko@halom.u-szeged.hu>, 7 - * University of Szeged, Hungary 8 - * 2006 KaiGai Kohei <kaigai@ak.jp.nec.com> 4 + * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>, 5 + * Zoltan Sogor <weth@inf.u-szeged.hu>, 6 + * Patrik Kluba <pajko@halom.u-szeged.hu>, 7 + * University of Szeged, Hungary 8 + * 2006 KaiGai Kohei <kaigai@ak.jp.nec.com> 9 9 * 10 10 * For licensing information, see the file 'LICENCE' in this directory. 11 - * 12 - * $Id: summary.c,v 1.4 2005/09/26 11:37:21 havasi Exp $ 13 11 * 14 12 */ 15 13
+4 -6
fs/jffs2/summary.h
··· 1 1 /* 2 2 * JFFS2 -- Journalling Flash File System, Version 2. 3 3 * 4 - * Copyright (C) 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>, 5 - * Zoltan Sogor <weth@inf.u-szeged.hu>, 6 - * Patrik Kluba <pajko@halom.u-szeged.hu>, 7 - * University of Szeged, Hungary 4 + * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>, 5 + * Zoltan Sogor <weth@inf.u-szeged.hu>, 6 + * Patrik Kluba <pajko@halom.u-szeged.hu>, 7 + * University of Szeged, Hungary 8 8 * 9 9 * For licensing information, see the file 'LICENCE' in this directory. 10 - * 11 - * $Id: summary.h,v 1.2 2005/09/26 11:37:21 havasi Exp $ 12 10 * 13 11 */ 14 12
+2 -4
fs/jffs2/super.c
··· 1 1 /* 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 6 * Created by David Woodhouse <dwmw2@infradead.org> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 - * 10 - * $Id: super.c,v 1.110 2005/11/07 11:14:42 gleixner Exp $ 11 9 * 12 10 */ 13 11 ··· 345 347 #ifdef CONFIG_JFFS2_SUMMARY 346 348 " (SUMMARY) " 347 349 #endif 348 - " (C) 2001-2006 Red Hat, Inc.\n"); 350 + " © 2001-2006 Red Hat, Inc.\n"); 349 351 350 352 jffs2_inode_cachep = kmem_cache_create("jffs2_i", 351 353 sizeof(struct jffs2_inode_info),
+1 -4
fs/jffs2/symlink.c
··· 1 1 /* 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 6 * Created by David Woodhouse <dwmw2@infradead.org> 7 7 * 8 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 - 14 11 15 12 #include <linux/kernel.h> 16 13 #include <linux/slab.h>
+8 -7
fs/jffs2/wbuf.c
··· 1 1 /* 2 2 * JFFS2 -- Journalling Flash File System, Version 2. 3 3 * 4 - * Copyright (C) 2001-2003 Red Hat, Inc. 5 - * Copyright (C) 2004 Thomas Gleixner <tglx@linutronix.de> 4 + * Copyright © 2001-2007 Red Hat, Inc. 5 + * Copyright © 2004 Thomas Gleixner <tglx@linutronix.de> 6 6 * 7 7 * Created by David Woodhouse <dwmw2@infradead.org> 8 8 * Modified debugged and enhanced by Thomas Gleixner <tglx@linutronix.de> 9 9 * 10 10 * For licensing information, see the file 'LICENCE' in this directory. 11 - * 12 - * $Id: wbuf.c,v 1.100 2005/09/30 13:59:13 dedekind Exp $ 13 11 * 14 12 */ 15 13 ··· 342 344 kfree(buf); 343 345 return; 344 346 } 347 + 348 + /* The summary is not recovered, so it must be disabled for this erase block */ 349 + jffs2_sum_disable_collecting(c->summary); 345 350 346 351 ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, nr_refile); 347 352 if (ret) { ··· 968 967 969 968 static const struct jffs2_unknown_node oob_cleanmarker = 970 969 { 971 - .magic = cpu_to_je16(JFFS2_MAGIC_BITMASK), 972 - .nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER), 973 - .totlen = cpu_to_je32(8) 970 + .magic = constant_cpu_to_je16(JFFS2_MAGIC_BITMASK), 971 + .nodetype = constant_cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER), 972 + .totlen = constant_cpu_to_je32(8) 974 973 }; 975 974 976 975 /*
+2 -5
fs/jffs2/write.c
··· 1 1 /* 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 6 * Created by David Woodhouse <dwmw2@infradead.org> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 - * 10 - * $Id: write.c,v 1.97 2005/11/07 11:14:42 gleixner Exp $ 11 9 * 12 10 */ 13 11 ··· 505 507 uint32_t alloclen; 506 508 int ret; 507 509 508 - if (1 /* alternative branch needs testing */ || 509 - !jffs2_can_mark_obsolete(c)) { 510 + if (!jffs2_can_mark_obsolete(c)) { 510 511 /* We can't mark stuff obsolete on the medium. We need to write a deletion dirent */ 511 512 512 513 rd = jffs2_alloc_raw_dirent();
+1 -3
fs/jffs2/writev.c
··· 1 1 /* 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 6 * Created by David Woodhouse <dwmw2@infradead.org> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 - * 10 - * $Id: writev.c,v 1.8 2005/09/09 15:11:58 havasi Exp $ 11 9 * 12 10 */ 13 11
+2 -1
fs/jffs2/xattr.c
··· 1 1 /* 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 6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 9 * 10 10 */ 11 + 11 12 #include <linux/kernel.h> 12 13 #include <linux/slab.h> 13 14 #include <linux/fs.h>
+2 -1
fs/jffs2/xattr.h
··· 1 1 /* 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 6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 9 * 10 10 */ 11 + 11 12 #ifndef _JFFS2_FS_XATTR_H_ 12 13 #define _JFFS2_FS_XATTR_H_ 13 14
+2 -1
fs/jffs2/xattr_trusted.c
··· 1 1 /* 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 6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 9 * 10 10 */ 11 + 11 12 #include <linux/kernel.h> 12 13 #include <linux/fs.h> 13 14 #include <linux/jffs2.h>
+2 -1
fs/jffs2/xattr_user.c
··· 1 1 /* 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 6 * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> 7 7 * 8 8 * For licensing information, see the file 'LICENCE' in this directory. 9 9 * 10 10 */ 11 + 11 12 #include <linux/kernel.h> 12 13 #include <linux/fs.h> 13 14 #include <linux/jffs2.h>
-98
include/linux/mtd/iflash.h
··· 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__ */
+1
include/linux/mtd/mtd.h
··· 53 53 u_int32_t offset; /* At which this region starts, from the beginning of the MTD */ 54 54 u_int32_t erasesize; /* For this region */ 55 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 /*
+1
include/linux/mtd/nand.h
··· 431 431 #define NAND_MFR_RENESAS 0x07 432 432 #define NAND_MFR_STMICRO 0x20 433 433 #define NAND_MFR_HYNIX 0xad 434 + #define NAND_MFR_MICRON 0x2c 434 435 435 436 /** 436 437 * struct nand_flash_dev - NAND Flash Device ID Structure