···11-# $Id: Kconfig,v 1.10 2005/07/11 10:39:27 gleixner Exp $11+# $Id: Kconfig,v 1.11 2005/11/07 11:14:19 gleixner Exp $2233menu "Memory Technology Devices (MTD)"44···1010 will provide the generic support for MTD drivers to register1111 themselves with the kernel and for potential users of MTD devices1212 to enumerate the devices which are present and obtain a handle on1313- them. It will also allow you to select individual drivers for 1313+ them. It will also allow you to select individual drivers for1414 particular hardware and users of MTD devices. If unsure, say N.15151616config MTD_DEBUG···61616262 If you need code which can detect and parse this table, and register6363 MTD 'partitions' corresponding to each image in the table, enable6464- this option. 6464+ this option.65656666 You will still need the parsing functions to be called by the driver6767- for your particular device. It won't happen automatically. The 6868- SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for 6767+ for your particular device. It won't happen automatically. The6868+ SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for6969 example.70707171config MTD_REDBOOT_DIRECTORY_BLOCK···8181 partition table. A zero or positive value gives an absolete8282 erase block number. A negative value specifies a number of8383 sectors before the end of the device.8484-8484+8585 For example "2" means block number 2, "-1" means the last8686 block and "-2" means the penultimate block.8787-8787+8888config MTD_REDBOOT_PARTS_UNALLOCATED8989 bool " Include unallocated flash regions"9090 depends on MTD_REDBOOT_PARTS···105105 ---help---106106 Allow generic configuration of the MTD paritition tables via the kernel107107 command line. Multiple flash resources are supported for hardware where108108- different kinds of flash memory are available. 108108+ different kinds of flash memory are available.109109110110 You will still need the parsing functions to be called by the driver111111- for your particular device. It won't happen automatically. The 112112- SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for 111111+ for your particular device. It won't happen automatically. The112112+ SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for113113 example.114114115115 The format for the command line is as follows:···118118 <mtddef> := <mtd-id>:<partdef>[,<partdef>]119119 <partdef> := <size>[@offset][<name>][ro]120120 <mtd-id> := unique id used in mapping driver/device121121- <size> := standard linux memsize OR "-" to denote all 121121+ <size> := standard linux memsize OR "-" to denote all122122 remaining space123123 <name> := (NAME)124124125125- Due to the way Linux handles the command line, no spaces are 126126- allowed in the partition definition, including mtd id's and partition 125125+ Due to the way Linux handles the command line, no spaces are126126+ allowed in the partition definition, including mtd id's and partition127127 names.128128129129 Examples:···240240 tristate "INFTL (Inverse NAND Flash Translation Layer) support"241241 depends on MTD242242 ---help---243243- This provides support for the Inverse NAND Flash Translation 243243+ This provides support for the Inverse NAND Flash Translation244244 Layer which is used on M-Systems' newer DiskOnChip devices. It245245 uses a kind of pseudo-file system on a flash device to emulate246246 a block device with 512-byte sectors, on top of which you put···257257 tristate "Resident Flash Disk (Flash Translation Layer) support"258258 depends on MTD259259 ---help---260260- This provides support for the flash translation layer known 261261- as the Resident Flash Disk (RFD), as used by the Embedded BIOS 260260+ This provides support for the flash translation layer known261261+ as the Resident Flash Disk (RFD), as used by the Embedded BIOS262262 of General Software. There is a blurb at:263263264264 http://www.gensw.com/pages/prod/bios/rfd.htm
+8-8
drivers/mtd/afs.c
···11/*======================================================================2233 drivers/mtd/afs.c: ARM Flash Layout/Partitioning44-44+55 Copyright (C) 2000 ARM Limited66-66+77 This program is free software; you can redistribute it and/or modify88 it under the terms of the GNU General Public License as published by99 the Free Software Foundation; either version 2 of the License, or1010 (at your option) any later version.1111-1111+1212 This program is distributed in the hope that it will be useful,1313 but WITHOUT ANY WARRANTY; without even the implied warranty of1414 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1515 GNU General Public License for more details.1616-1616+1717 You should have received a copy of the GNU General Public License1818 along with this program; if not, write to the Free Software1919 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA2020-2121- This is access code for flashes using ARM's flash partitioning 2020+2121+ This is access code for flashes using ARM's flash partitioning2222 standards.23232424- $Id: afs.c,v 1.13 2004/02/27 22:09:59 rmk Exp $2424+ $Id: afs.c,v 1.15 2005/11/07 11:14:19 gleixner Exp $25252626======================================================================*/2727···163163 return ret;164164}165165166166-static int parse_afs_partitions(struct mtd_info *mtd, 166166+static int parse_afs_partitions(struct mtd_info *mtd,167167 struct mtd_partition **pparts,168168 unsigned long origin)169169{
+28-28
drivers/mtd/cmdlinepart.c
···11/*22- * $Id: cmdlinepart.c,v 1.18 2005/06/07 15:04:26 joern Exp $22+ * $Id: cmdlinepart.c,v 1.19 2005/11/07 11:14:19 gleixner Exp $33 *44 * Read flash partition table from command line55 *66 * Copyright 2002 SYSGO Real-Time Solutions GmbH77 *88 * The format for the command line is as follows:99- * 99+ *1010 * mtdparts=<mtddef>[;<mtddef]1111 * <mtddef> := <mtd-id>:<partdef>[,<partdef>]1212 * <partdef> := <size>[@offset][<name>][ro]1313 * <mtd-id> := unique name used in mapping driver/device (mtd->name)1414 * <size> := standard linux memsize OR "-" to denote all remaining space1515 * <name> := '(' NAME ')'1616- * 1616+ *1717 * Examples:1818- * 1818+ *1919 * 1 NOR Flash, with 1 single writable partition:2020 * edb7312-nor:-2121- * 2121+ *2222 * 1 NOR Flash with 2 partitions, 1 NAND with one2323 * edb7312-nor:256k(ARMboot)ro,-(root);edb7312-nand:-(home)2424 */···60606161/*6262 * Parse one partition definition for an MTD. Since there can be many6363- * comma separated partition definitions, this function calls itself 6363+ * comma separated partition definitions, this function calls itself6464 * recursively until no more partition definitions are found. Nice side6565 * effect: the memory to keep the mtd_partition structs and the names6666 * is allocated upon the last definition being found. At that point the6767 * syntax has been verified ok.6868 */6969-static struct mtd_partition * newpart(char *s, 6969+static struct mtd_partition * newpart(char *s,7070 char **retptr,7171 int *num_parts,7272- int this_part, 7373- unsigned char **extra_mem_ptr, 7272+ int this_part,7373+ unsigned char **extra_mem_ptr,7474 int extra_mem_size)7575{7676 struct mtd_partition *parts;···102102 mask_flags = 0; /* this is going to be a regular partition */103103 delim = 0;104104 /* check for offset */105105- if (*s == '@') 105105+ if (*s == '@')106106 {107107 s++;108108 offset = memparse(s, &s);···112112 {113113 delim = ')';114114 }115115-115115+116116 if (delim)117117 {118118 char *p;···131131 name = NULL;132132 name_len = 13; /* Partition_000 */133133 }134134-134134+135135 /* record name length for memory allocation later */136136 extra_mem_size += name_len + 1;137137138138 /* test for options */139139- if (strncmp(s, "ro", 2) == 0) 139139+ if (strncmp(s, "ro", 2) == 0)140140 {141141 mask_flags |= MTD_WRITEABLE;142142 s += 2;···151151 return NULL;152152 }153153 /* more partitions follow, parse them */154154- if ((parts = newpart(s + 1, &s, num_parts, 154154+ if ((parts = newpart(s + 1, &s, num_parts,155155 this_part + 1, &extra_mem, extra_mem_size)) == 0)156156 return NULL;157157 }···187187 extra_mem += name_len + 1;188188189189 dbg(("partition %d: name <%s>, offset %x, size %x, mask flags %x\n",190190- this_part, 190190+ this_part,191191 parts[this_part].name,192192 parts[this_part].offset,193193 parts[this_part].size,···204204 return parts;205205}206206207207-/* 208208- * Parse the command line. 207207+/*208208+ * Parse the command line.209209 */210210static int mtdpart_setup_real(char *s)211211{···230230231231 dbg(("parsing <%s>\n", p+1));232232233233- /* 233233+ /*234234 * parse one mtd. have it reserve memory for the235235 * struct cmdline_mtd_partition and the mtd-id string.236236 */···239239 &num_parts, /* out: number of parts */240240 0, /* first partition */241241 (unsigned char**)&this_mtd, /* out: extra mem */242242- mtd_id_len + 1 + sizeof(*this_mtd) + 242242+ mtd_id_len + 1 + sizeof(*this_mtd) +243243 sizeof(void*)-1 /*alignment*/);244244 if(!parts)245245 {···254254 }255255256256 /* align this_mtd */257257- this_mtd = (struct cmdline_mtd_partition *) 257257+ this_mtd = (struct cmdline_mtd_partition *)258258 ALIGN((unsigned long)this_mtd, sizeof(void*));259259- /* enter results */ 259259+ /* enter results */260260 this_mtd->parts = parts;261261 this_mtd->num_parts = num_parts;262262 this_mtd->mtd_id = (char*)(this_mtd + 1);263263 strlcpy(this_mtd->mtd_id, mtd_id, mtd_id_len + 1);264264265265 /* link into chain */266266- this_mtd->next = partitions; 266266+ this_mtd->next = partitions;267267 partitions = this_mtd;268268269269- dbg(("mtdid=<%s> num_parts=<%d>\n", 269269+ dbg(("mtdid=<%s> num_parts=<%d>\n",270270 this_mtd->mtd_id, this_mtd->num_parts));271271-271271+272272273273 /* EOS - we're done */274274 if (*s == 0)···292292 * information. It returns partitions for the requested mtd device, or293293 * the first one in the chain if a NULL mtd_id is passed in.294294 */295295-static int parse_cmdline_partitions(struct mtd_info *master, 295295+static int parse_cmdline_partitions(struct mtd_info *master,296296 struct mtd_partition **pparts,297297 unsigned long origin)298298{···322322 part->parts[i].size = master->size - offset;323323 if (offset + part->parts[i].size > master->size)324324 {325325- printk(KERN_WARNING ERRP 325325+ printk(KERN_WARNING ERRP326326 "%s: partitioning exceeds flash size, truncating\n",327327 part->mtd_id);328328 part->parts[i].size = master->size - offset;···338338}339339340340341341-/* 342342- * This is the handler for our kernel parameter, called from 341341+/*342342+ * This is the handler for our kernel parameter, called from343343 * main.c::checksetup(). Note that we can not yet kmalloc() anything,344344 * so we only save the commandline for later processing.345345 *
+64-64
drivers/mtd/ftl.c
···11/* This version ported to the Linux-MTD system by dwmw2@infradead.org22- * $Id: ftl.c,v 1.55 2005/01/17 13:47:21 hvr Exp $22+ * $Id: ftl.c,v 1.58 2005/11/07 11:14:19 gleixner Exp $33 *44 * Fixes: Arnaldo Carvalho de Melo <acme@conectiva.com.br>55 * - fixes some leaks on failure in build_maps and ftl_notify_add, cleanups···5353 Use of the FTL format for non-PCMCIA applications may be an5454 infringement of these patents. For additional information,5555 contact M-Systems (http://www.m-sys.com) directly.5656-5656+5757======================================================================*/5858#include <linux/mtd/blktrans.h>5959#include <linux/module.h>···160160 Scan_header() checks to see if a memory region contains an FTL161161 partition. build_maps() reads all the erase unit headers, builds162162 the erase unit map, and then builds the virtual page map.163163-163163+164164======================================================================*/165165166166static int scan_header(partition_t *part)···176176 (offset + sizeof(header)) < max_offset;177177 offset += part->mbd.mtd->erasesize ? : 0x2000) {178178179179- err = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &ret, 179179+ err = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &ret,180180 (unsigned char *)&header);181181-182182- if (err) 181181+182182+ if (err)183183 return err;184184185185 if (strcmp(header.DataOrgTuple+3, "FTL100") == 0) break;···232232 for (i = 0; i < le16_to_cpu(part->header.NumEraseUnits); i++) {233233 offset = ((i + le16_to_cpu(part->header.FirstPhysicalEUN))234234 << part->header.EraseUnitSize);235235- ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &retval, 235235+ ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &retval,236236 (unsigned char *)&header);237237-238238- if (ret) 237237+238238+ if (ret)239239 goto out_XferInfo;240240241241 ret = -1;···274274 "don't add up!\n");275275 goto out_XferInfo;276276 }277277-277277+278278 /* Set up virtual page map */279279 blocks = le32_to_cpu(header.FormattedSize) >> header.BlockSize;280280 part->VirtualBlockMap = vmalloc(blocks * sizeof(u_int32_t));···296296 part->EUNInfo[i].Free = 0;297297 part->EUNInfo[i].Deleted = 0;298298 offset = part->EUNInfo[i].Offset + le32_to_cpu(header.BAMOffset);299299-300300- ret = part->mbd.mtd->read(part->mbd.mtd, offset, 301301- part->BlocksPerUnit * sizeof(u_int32_t), &retval, 299299+300300+ ret = part->mbd.mtd->read(part->mbd.mtd, offset,301301+ part->BlocksPerUnit * sizeof(u_int32_t), &retval,302302 (unsigned char *)part->bam_cache);303303-304304- if (ret) 303303+304304+ if (ret)305305 goto out_bam_cache;306306307307 for (j = 0; j < part->BlocksPerUnit; j++) {···316316 part->EUNInfo[i].Deleted++;317317 }318318 }319319-319319+320320 ret = 0;321321 goto out;322322···336336337337 Erase_xfer() schedules an asynchronous erase operation for a338338 transfer unit.339339-339339+340340======================================================================*/341341342342static int erase_xfer(partition_t *part,···351351 xfer->state = XFER_ERASING;352352353353 /* Is there a free erase slot? Always in MTD. */354354-355355-354354+355355+356356 erase=kmalloc(sizeof(struct erase_info), GFP_KERNEL);357357- if (!erase) 357357+ if (!erase)358358 return -ENOMEM;359359360360 erase->mtd = part->mbd.mtd;···362362 erase->addr = xfer->Offset;363363 erase->len = 1 << part->header.EraseUnitSize;364364 erase->priv = (u_long)part;365365-365365+366366 ret = part->mbd.mtd->erase(part->mbd.mtd, erase);367367368368 if (!ret)···377377378378 Prepare_xfer() takes a freshly erased transfer unit and gives379379 it an appropriate header.380380-380380+381381======================================================================*/382382383383static void ftl_erase_callback(struct erase_info *erase)···385385 partition_t *part;386386 struct xfer_info_t *xfer;387387 int i;388388-388388+389389 /* Look up the transfer unit */390390 part = (partition_t *)(erase->priv);391391···422422423423 xfer = &part->XferInfo[i];424424 xfer->state = XFER_FAILED;425425-425425+426426 DEBUG(1, "ftl_cs: preparing xfer unit at 0x%x\n", xfer->Offset);427427428428 /* Write the transfer unit header */···446446447447 for (i = 0; i < nbam; i++, offset += sizeof(u_int32_t)) {448448449449- ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int32_t), 449449+ ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int32_t),450450 &retlen, (u_char *)&ctl);451451452452 if (ret)···454454 }455455 xfer->state = XFER_PREPARED;456456 return 0;457457-457457+458458} /* prepare_xfer */459459460460/*======================================================================···466466 All data blocks are copied to the corresponding blocks in the467467 target unit, so the virtual block map does not need to be468468 updated.469469-469469+470470======================================================================*/471471472472static int copy_erase_unit(partition_t *part, u_int16_t srcunit,···486486 xfer = &part->XferInfo[xferunit];487487 DEBUG(2, "ftl_cs: copying block 0x%x to 0x%x\n",488488 eun->Offset, xfer->Offset);489489-490490-489489+490490+491491 /* Read current BAM */492492 if (part->bam_index != srcunit) {493493494494 offset = eun->Offset + le32_to_cpu(part->header.BAMOffset);495495496496- ret = part->mbd.mtd->read(part->mbd.mtd, offset, 496496+ ret = part->mbd.mtd->read(part->mbd.mtd, offset,497497 part->BlocksPerUnit * sizeof(u_int32_t),498498 &retlen, (u_char *) (part->bam_cache));499499···501501 part->bam_index = 0xffff;502502503503 if (ret) {504504- printk( KERN_WARNING "ftl: Failed to read BAM cache in copy_erase_unit()!\n"); 504504+ printk( KERN_WARNING "ftl: Failed to read BAM cache in copy_erase_unit()!\n");505505 return ret;506506 }507507 }508508-508508+509509 /* Write the LogicalEUN for the transfer unit */510510 xfer->state = XFER_UNKNOWN;511511 offset = xfer->Offset + 20; /* Bad! */···513513514514 ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int16_t),515515 &retlen, (u_char *) &unit);516516-516516+517517 if (ret) {518518 printk( KERN_WARNING "ftl: Failed to write back to BAM cache in copy_erase_unit()!\n");519519 return ret;520520 }521521-521521+522522 /* Copy all data blocks from source unit to transfer unit */523523 src = eun->Offset; dest = xfer->Offset;524524···558558 }559559560560 /* Write the BAM to the transfer unit */561561- ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + le32_to_cpu(part->header.BAMOffset), 562562- part->BlocksPerUnit * sizeof(int32_t), &retlen, 561561+ ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + le32_to_cpu(part->header.BAMOffset),562562+ part->BlocksPerUnit * sizeof(int32_t), &retlen,563563 (u_char *)part->bam_cache);564564 if (ret) {565565 printk( KERN_WARNING "ftl: Error writing BAM in copy_erase_unit\n");566566 return ret;567567 }568568569569-569569+570570 /* All clear? Then update the LogicalEUN again */571571 ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + 20, sizeof(u_int16_t),572572 &retlen, (u_char *)&srcunitswap);···574574 if (ret) {575575 printk(KERN_WARNING "ftl: Error writing new LogicalEUN in copy_erase_unit\n");576576 return ret;577577- } 578578-579579-577577+ }578578+579579+580580 /* Update the maps and usage stats*/581581 i = xfer->EraseCount;582582 xfer->EraseCount = eun->EraseCount;···588588 part->FreeTotal += free;589589 eun->Free = free;590590 eun->Deleted = 0;591591-591591+592592 /* Now, the cache should be valid for the new block */593593 part->bam_index = srcunit;594594-594594+595595 return 0;596596} /* copy_erase_unit */597597···608608 oldest data unit instead. This means that we generally postpone609609 the next reclaimation as long as possible, but shuffle static610610 stuff around a bit for wear leveling.611611-611611+612612======================================================================*/613613614614static int reclaim_block(partition_t *part)···666666 else667667 DEBUG(1, "ftl_cs: reclaim failed: no "668668 "suitable transfer units!\n");669669-669669+670670 return -EIO;671671 }672672 }···715715 returns the block index -- the erase unit is just the currently716716 cached unit. If there are no free blocks, it returns 0 -- this717717 is never a valid data block because it contains the header.718718-718718+719719======================================================================*/720720721721#ifdef PSYCHO_DEBUG···737737 u_int32_t blk;738738 size_t retlen;739739 int ret;740740-740740+741741 /* Find an erase unit with some free space */742742 stop = (part->bam_index == 0xffff) ? 0 : part->bam_index;743743 eun = stop;···749749750750 if (part->EUNInfo[eun].Free == 0)751751 return 0;752752-752752+753753 /* Is this unit's BAM cached? */754754 if (eun != part->bam_index) {755755 /* Invalidate cache */756756 part->bam_index = 0xffff;757757758758- ret = part->mbd.mtd->read(part->mbd.mtd, 758758+ ret = part->mbd.mtd->read(part->mbd.mtd,759759 part->EUNInfo[eun].Offset + le32_to_cpu(part->header.BAMOffset),760760 part->BlocksPerUnit * sizeof(u_int32_t),761761 &retlen, (u_char *) (part->bam_cache));762762-762762+763763 if (ret) {764764 printk(KERN_WARNING"ftl: Error reading BAM in find_free\n");765765 return 0;···781781 }782782 DEBUG(2, "ftl_cs: found free block at %d in %d\n", blk, eun);783783 return blk;784784-784784+785785} /* find_free */786786787787788788/*======================================================================789789790790 Read a series of sectors from an FTL partition.791791-791791+792792======================================================================*/793793794794static int ftl_read(partition_t *part, caddr_t buffer,···798798 u_long i;799799 int ret;800800 size_t offset, retlen;801801-801801+802802 DEBUG(2, "ftl_cs: ftl_read(0x%p, 0x%lx, %ld)\n",803803 part, sector, nblocks);804804 if (!(part->state & FTL_FORMATTED)) {···834834/*======================================================================835835836836 Write a series of sectors to an FTL partition837837-837837+838838======================================================================*/839839840840static int set_bam_entry(partition_t *part, u_int32_t log_addr,···855855 blk = (log_addr % bsize) / SECTOR_SIZE;856856 offset = (part->EUNInfo[eun].Offset + blk * sizeof(u_int32_t) +857857 le32_to_cpu(part->header.BAMOffset));858858-858858+859859#ifdef PSYCHO_DEBUG860860 ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(u_int32_t),861861 &retlen, (u_char *)&old_addr);···925925 if (ret)926926 return ret;927927 }928928-928928+929929 bsize = 1 << part->header.EraseUnitSize;930930931931 virt_addr = sector * SECTOR_SIZE | BLOCK_DATA;···949949 log_addr = part->bam_index * bsize + blk * SECTOR_SIZE;950950 part->EUNInfo[part->bam_index].Free--;951951 part->FreeTotal--;952952- if (set_bam_entry(part, log_addr, 0xfffffffe)) 952952+ if (set_bam_entry(part, log_addr, 0xfffffffe))953953 return -EIO;954954 part->EUNInfo[part->bam_index].Deleted++;955955 offset = (part->EUNInfo[part->bam_index].Offset +956956 blk * SECTOR_SIZE);957957- ret = part->mbd.mtd->write(part->mbd.mtd, offset, SECTOR_SIZE, &retlen, 957957+ ret = part->mbd.mtd->write(part->mbd.mtd, offset, SECTOR_SIZE, &retlen,958958 buffer);959959960960 if (ret) {···964964 offset);965965 return -EIO;966966 }967967-967967+968968 /* Only delete the old entry when the new entry is ready */969969 old_addr = part->VirtualBlockMap[sector+i];970970 if (old_addr != 0xffffffff) {···979979 return -EIO;980980 part->VirtualBlockMap[sector+i] = log_addr;981981 part->EUNInfo[part->bam_index].Deleted--;982982-982982+983983 buffer += SECTOR_SIZE;984984 virt_addr += SECTOR_SIZE;985985 }···10341034 partition_t *partition;1035103510361036 partition = kmalloc(sizeof(partition_t), GFP_KERNEL);10371037-10371037+10381038 if (!partition) {10391039 printk(KERN_WARNING "No memory to scan for FTL on %s\n",10401040 mtd->name);10411041 return;10421042- } 10421042+ }1043104310441044 memset(partition, 0, sizeof(partition_t));1045104510461046 partition->mbd.mtd = mtd;1047104710481048- if ((scan_header(partition) == 0) && 10481048+ if ((scan_header(partition) == 0) &&10491049 (build_maps(partition) == 0)) {10501050-10501050+10511051 partition->state = FTL_FORMATTED;10521052#ifdef PCMCIA_DEBUG10531053 printk(KERN_INFO "ftl_cs: opening %d KiB FTL partition\n",···1086108610871087int init_ftl(void)10881088{10891089- DEBUG(0, "$Id: ftl.c,v 1.55 2005/01/17 13:47:21 hvr Exp $\n");10891089+ DEBUG(0, "$Id: ftl.c,v 1.58 2005/11/07 11:14:19 gleixner Exp $\n");1090109010911091 return register_mtd_blktrans(&ftl_tr);10921092}
+24-24
drivers/mtd/inftlcore.c
···11-/* 11+/*22 * inftlcore.c -- Linux driver for Inverse Flash Translation Layer (INFTL)33 *44 * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)···77 * (c) 1999 Machine Vision Holdings, Inc.88 * Author: David Woodhouse <dwmw2@infradead.org>99 *1010- * $Id: inftlcore.c,v 1.18 2004/11/16 18:28:59 dwmw2 Exp $1010+ * $Id: inftlcore.c,v 1.19 2005/11/07 11:14:20 gleixner Exp $1111 *1212 * This program is free software; you can redistribute it and/or modify1313 * it under the terms of the GNU General Public License as published by···113113114114 if (inftl->mbd.size != inftl->heads * inftl->cylinders * inftl->sectors) {115115 /*116116- Oh no we don't have 116116+ Oh no we don't have117117 mbd.size == heads * cylinders * sectors118118 */119119 printk(KERN_WARNING "INFTL: cannot calculate a geometry to "120120 "match size of 0x%lx.\n", inftl->mbd.size);121121 printk(KERN_WARNING "INFTL: using C:%d H:%d S:%d "122122 "(== 0x%lx sects)\n",123123- inftl->cylinders, inftl->heads , inftl->sectors, 123123+ inftl->cylinders, inftl->heads , inftl->sectors,124124 (long)inftl->cylinders * (long)inftl->heads *125125 (long)inftl->sectors );126126 }···223223 "Virtual Unit Chain %d!\n", thisVUC);224224 return BLOCK_NIL;225225 }226226-226226+227227 /*228228 * Scan to find the Erase Unit which holds the actual data for each229229 * 512-byte block within the Chain.···264264 "Unit Chain 0x%x\n", thisVUC);265265 return BLOCK_NIL;266266 }267267-267267+268268 thisEUN = inftl->PUtable[thisEUN];269269 }270270···295295 */296296 if (BlockMap[block] == BLOCK_NIL)297297 continue;298298-298298+299299 ret = MTD_READ(inftl->mbd.mtd, (inftl->EraseSize *300300 BlockMap[block]) + (block * SECTORSIZE), SECTORSIZE,301301- &retlen, movebuf); 301301+ &retlen, movebuf);302302 if (ret < 0) {303303 ret = MTD_READ(inftl->mbd.mtd, (inftl->EraseSize *304304 BlockMap[block]) + (block * SECTORSIZE),305305 SECTORSIZE, &retlen, movebuf);306306- if (ret != -EIO) 306306+ if (ret != -EIO)307307 DEBUG(MTD_DEBUG_LEVEL1, "INFTL: error went "308308 "away on retry?\n");309309 }···355355static u16 INFTL_makefreeblock(struct INFTLrecord *inftl, unsigned pendingblock)356356{357357 /*358358- * This is the part that needs some cleverness applied. 358358+ * This is the part that needs some cleverness applied.359359 * For now, I'm doing the minimum applicable to actually360360 * get the thing to work.361361 * Wear-levelling and other clever stuff needs to be implemented···414414}415415416416/*417417- * INFTL_findwriteunit: Return the unit number into which we can write 417417+ * INFTL_findwriteunit: Return the unit number into which we can write418418 * for this block. Make it available if it isn't already.419419 */420420static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)···463463 * Invalid block. Don't use it any more.464464 * Must implement.465465 */466466- break; 466466+ break;467467 }468468-469469- if (!silly--) { 468468+469469+ if (!silly--) {470470 printk(KERN_WARNING "INFTL: infinite loop in "471471 "Virtual Unit Chain 0x%x\n", thisVUC);472472 return 0xffff;···482482483483484484 /*485485- * OK. We didn't find one in the existing chain, or there 485485+ * OK. We didn't find one in the existing chain, or there486486 * is no existing chain. Allocate a new one.487487 */488488 writeEUN = INFTL_findfreeblock(inftl, 0);···506506 if (writeEUN == BLOCK_NIL) {507507 /*508508 * Ouch. This should never happen - we should509509- * always be able to make some room somehow. 510510- * If we get here, we've allocated more storage 509509+ * always be able to make some room somehow.510510+ * If we get here, we've allocated more storage511511 * space than actual media, or our makefreeblock512512 * routine is missing something.513513 */···518518 INFTL_dumpVUchains(inftl);519519#endif520520 return BLOCK_NIL;521521- } 521521+ }522522 }523523524524 /*···543543 parity |= (nrbits(prev_block, 16) & 0x1) ? 0x2 : 0;544544 parity |= (nrbits(anac, 8) & 0x1) ? 0x4 : 0;545545 parity |= (nrbits(nacs, 8) & 0x1) ? 0x8 : 0;546546-546546+547547 oob.u.a.virtualUnitNo = cpu_to_le16(thisVUC);548548 oob.u.a.prevUnitNo = cpu_to_le16(prev_block);549549 oob.u.a.ANAC = anac;···562562 oob.u.b.parityPerField = parity;563563 oob.u.b.discarded = 0xaa;564564565565- MTD_WRITEOOB(inftl->mbd.mtd, writeEUN * inftl->EraseSize + 565565+ MTD_WRITEOOB(inftl->mbd.mtd, writeEUN * inftl->EraseSize +566566 SECTORSIZE * 4 + 8, 8, &retlen, (char *)&oob.u);567567568568 inftl->PUtable[writeEUN] = inftl->VUtable[thisVUC];···602602 "Virtual Unit Chain %d!\n", thisVUC);603603 return;604604 }605605-605605+606606 /*607607 * Scan through the Erase Units to determine whether any data is in608608 * each of the 512-byte blocks within the Chain.···642642 "Unit Chain 0x%x\n", thisVUC);643643 return;644644 }645645-645645+646646 thisEUN = inftl->PUtable[thisEUN];647647 }648648···758758 return 0;759759}760760761761-static int inftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block, 761761+static int inftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block,762762 char *buffer)763763{764764 struct INFTLrecord *inftl = (void *)mbd;···893893894894static int __init init_inftl(void)895895{896896- printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.18 $, "896896+ printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.19 $, "897897 "inftlmount.c %s\n", inftlmountrev);898898899899 return register_mtd_blktrans(&inftl_tr);
+10-10
drivers/mtd/inftlmount.c
···11-/* 11+/*22 * inftlmount.c -- INFTL mount code with extensive checks.33 *44 * Author: Greg Ungerer (gerg@snapgear.com)55 * (C) Copyright 2002-2003, Greg Ungerer (gerg@snapgear.com)66 *77 * Based heavily on the nftlmount.c code which is:88- * Author: Fabrice Bellard (fabrice.bellard@netgem.com) 88+ * Author: Fabrice Bellard (fabrice.bellard@netgem.com)99 * Copyright (C) 2000 Netgem S.A.1010 *1111- * $Id: inftlmount.c,v 1.17 2005/08/08 08:56:19 dwmw2 Exp $1111+ * $Id: inftlmount.c,v 1.18 2005/11/07 11:14:20 gleixner Exp $1212 *1313 * This program is free software; you can redistribute it and/or modify1414 * it under the terms of the GNU General Public License as published by···4141#include <linux/mtd/inftl.h>4242#include <linux/mtd/compatmac.h>43434444-char inftlmountrev[]="$Revision: 1.17 $";4444+char inftlmountrev[]="$Revision: 1.18 $";45454646/*4747 * find_boot_record: Find the INFTL Media Header and its Spare copy which···273273 inftl->nb_boot_blocks);274274 return -1;275275 }276276-276276+277277 inftl->mbd.size = inftl->numvunits *278278 (inftl->EraseSize / SECTORSIZE);279279···302302 inftl->nb_blocks * sizeof(u16));303303 return -ENOMEM;304304 }305305-305305+306306 /* Mark the blocks before INFTL MediaHeader as reserved */307307 for (i = 0; i < inftl->nb_boot_blocks; i++)308308 inftl->PUtable[i] = BLOCK_RESERVED;···380380 *381381 * Return: 0 when succeed, -1 on error.382382 *383383- * ToDo: 1. Is it neceressary to check_free_sector after erasing ?? 383383+ * ToDo: 1. Is it neceressary to check_free_sector after erasing ??384384 */385385int INFTL_formatblock(struct INFTLrecord *inftl, int block)386386{···578578 printk(KERN_ERR "INFTL: Out of memory.\n");579579 return -ENOMEM;580580 }581581-581581+582582 memset(ANACtable, 0, s->nb_blocks);583583584584 /*···600600601601 for (chain_length = 0; ; chain_length++) {602602603603- if ((chain_length == 0) && 603603+ if ((chain_length == 0) &&604604 (s->PUtable[block] != BLOCK_NOTEXPLORED)) {605605 /* Nothing to do here, onto next block */606606 break;···747747 "in virtual chain %d\n",748748 s->PUtable[block], logical_block);749749 s->PUtable[block] = BLOCK_NIL;750750-750750+751751 }752752 if (ANACtable[block] != ANAC) {753753 /*
+12-12
drivers/mtd/mtd_blkdevs.c
···11/*22- * $Id: mtd_blkdevs.c,v 1.26 2005/07/29 19:42:04 tpoynor Exp $22+ * $Id: mtd_blkdevs.c,v 1.27 2005/11/07 11:14:20 gleixner Exp $33 *44 * (C) 2003 David Woodhouse <dwmw2@infradead.org>55 *···8585 daemonize("%sd", tr->name);86868787 /* daemonize() doesn't do this for us since some kernel threads8888- actually want to deal with signals. We can't just call 8888+ actually want to deal with signals. We can't just call8989 exit_sighand() since that'll cause an oops when we finally9090 do exit. */9191 spin_lock_irq(¤t->sighand->siglock);···9494 spin_unlock_irq(¤t->sighand->siglock);95959696 spin_lock_irq(rq->queue_lock);9797-9797+9898 while (!tr->blkcore_priv->exiting) {9999 struct request *req;100100 struct mtd_blktrans_dev *dev;···157157 if (!try_module_get(tr->owner))158158 goto out_tr;159159160160- /* FIXME: Locking. A hot pluggable device can go away 160160+ /* FIXME: Locking. A hot pluggable device can go away161161 (del_mtd_device can be called for it) without its module162162 being unloaded. */163163 dev->mtd->usecount++;···195195}196196197197198198-static int blktrans_ioctl(struct inode *inode, struct file *file, 198198+static int blktrans_ioctl(struct inode *inode, struct file *file,199199 unsigned int cmd, unsigned long arg)200200{201201 struct mtd_blktrans_dev *dev = inode->i_bdev->bd_disk->private_data;···264264 /* Required number was free */265265 list_add_tail(&new->list, &d->list);266266 goto added;267267- } 267267+ }268268 last_devnum = d->devnum;269269 }270270 if (new->devnum == -1)···288288 gd->major = tr->major;289289 gd->first_minor = (new->devnum) << tr->part_bits;290290 gd->fops = &mtd_blktrans_ops;291291-291291+292292 if (tr->part_bits)293293 if (new->devnum < 26)294294 snprintf(gd->disk_name, sizeof(gd->disk_name),···314314 set_disk_ro(gd, 1);315315316316 add_disk(gd);317317-317317+318318 return 0;319319}320320···329329330330 del_gendisk(old->blkcore_priv);331331 put_disk(old->blkcore_priv);332332-332332+333333 return 0;334334}335335···368368 .add = blktrans_notify_add,369369 .remove = blktrans_notify_remove,370370};371371-371371+372372int register_mtd_blktrans(struct mtd_blktrans_ops *tr)373373{374374 int ret, i;375375376376- /* Register the notifier if/when the first device type is 376376+ /* Register the notifier if/when the first device type is377377 registered, to prevent the link/init ordering from fucking378378 us over. */379379 if (!blktrans_notifier.list.next)···416416 kfree(tr->blkcore_priv);417417 up(&mtd_table_mutex);418418 return ret;419419- } 419419+ }420420421421 INIT_LIST_HEAD(&tr->devs);422422 list_add(&tr->list, &blktrans_majors);
+22-22
drivers/mtd/mtdblock.c
···11-/* 11+/*22 * Direct MTD block device access33 *44- * $Id: mtdblock.c,v 1.67 2005/11/06 10:04:37 gleixner Exp $44+ * $Id: mtdblock.c,v 1.68 2005/11/07 11:14:20 gleixner Exp $55 *66 * (C) 2000-2003 Nicolas Pitre <nico@cam.org>77 * (C) 1999-2003 David Woodhouse <dwmw2@infradead.org>···32323333/*3434 * Cache stuff...3535- * 3535+ *3636 * Since typical flash erasable sectors are much larger than what Linux's3737 * buffer cache can handle, we must implement read-modify-write on flash3838 * sectors for each block write requests. To avoid over-erasing flash sectors···4646 wake_up(wait_q);4747}48484949-static int erase_write (struct mtd_info *mtd, unsigned long pos, 4949+static int erase_write (struct mtd_info *mtd, unsigned long pos,5050 int len, const char *buf)5151{5252 struct erase_info erase;···104104 return 0;105105106106 DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: writing cached data for \"%s\" "107107- "at 0x%lx, size 0x%x\n", mtd->name, 107107+ "at 0x%lx, size 0x%x\n", mtd->name,108108 mtdblk->cache_offset, mtdblk->cache_size);109109-110110- ret = erase_write (mtd, mtdblk->cache_offset, 109109+110110+ ret = erase_write (mtd, mtdblk->cache_offset,111111 mtdblk->cache_size, mtdblk->cache_data);112112 if (ret)113113 return ret;114114115115 /*116116 * Here we could argubly set the cache state to STATE_CLEAN.117117- * However this could lead to inconsistency since we will not 118118- * be notified if this content is altered on the flash by other 117117+ * However this could lead to inconsistency since we will not118118+ * be notified if this content is altered on the flash by other119119 * means. Let's declare it empty and leave buffering tasks to120120 * the buffer cache instead.121121 */···124124}125125126126127127-static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos, 127127+static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos,128128 int len, const char *buf)129129{130130 struct mtd_info *mtd = mtdblk->mtd;···134134135135 DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: write on \"%s\" at 0x%lx, size 0x%x\n",136136 mtd->name, pos, len);137137-137137+138138 if (!sect_size)139139 return MTD_WRITE (mtd, pos, len, &retlen, buf);140140···142142 unsigned long sect_start = (pos/sect_size)*sect_size;143143 unsigned int offset = pos - sect_start;144144 unsigned int size = sect_size - offset;145145- if( size > len ) 145145+ if( size > len )146146 size = len;147147148148 if (size == sect_size) {149149- /* 149149+ /*150150 * We are covering a whole sector. Thus there is no151151 * need to bother with the cache while it may still be152152 * useful for other partial writes.···160160 if (mtdblk->cache_state == STATE_DIRTY &&161161 mtdblk->cache_offset != sect_start) {162162 ret = write_cached_data(mtdblk);163163- if (ret) 163163+ if (ret)164164 return ret;165165 }166166···193193}194194195195196196-static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos, 196196+static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos,197197 int len, char *buf)198198{199199 struct mtd_info *mtd = mtdblk->mtd;···201201 size_t retlen;202202 int ret;203203204204- DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: read on \"%s\" at 0x%lx, size 0x%x\n", 204204+ DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: read on \"%s\" at 0x%lx, size 0x%x\n",205205 mtd->name, pos, len);206206-206206+207207 if (!sect_size)208208 return MTD_READ (mtd, pos, len, &retlen, buf);209209···211211 unsigned long sect_start = (pos/sect_size)*sect_size;212212 unsigned int offset = pos - sect_start;213213 unsigned int size = sect_size - offset;214214- if (size > len) 214214+ if (size > len)215215 size = len;216216217217 /*···269269 int dev = mbd->devnum;270270271271 DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n");272272-272272+273273 if (mtdblks[dev]) {274274 mtdblks[dev]->count++;275275 return 0;276276 }277277-277277+278278 /* OK, it's not open. Create cache info for it */279279 mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);280280 if (!mtdblk)···293293 }294294295295 mtdblks[dev] = mtdblk;296296-296296+297297 DEBUG(MTD_DEBUG_LEVEL1, "ok\n");298298299299 return 0;···321321 DEBUG(MTD_DEBUG_LEVEL1, "ok\n");322322323323 return 0;324324-} 324324+}325325326326static int mtdblock_flush(struct mtd_blktrans_dev *dev)327327{
+30-30
drivers/mtd/mtdchar.c
···11/*22- * $Id: mtdchar.c,v 1.75 2005/11/06 10:04:37 gleixner Exp $22+ * $Id: mtdchar.c,v 1.76 2005/11/07 11:14:20 gleixner Exp $33 *44 * Character-device access to raw MTD devices.55 *···28282929 class_device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2),3030 NULL, "mtd%d", mtd->index);3131-3131+3232 class_device_create(mtd_class, NULL,3333 MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),3434 NULL, "mtd%dro", mtd->index);···108108 return -EACCES;109109110110 mtd = get_mtd_device(NULL, devnum);111111-111111+112112 if (!mtd)113113 return -ENODEV;114114-114114+115115 if (MTD_ABSENT == mtd->type) {116116 put_mtd_device(mtd);117117 return -ENODEV;118118 }119119120120 file->private_data = mtd;121121-121121+122122 /* You can't open it RW if it's not a writeable device */123123 if ((file->f_mode & 2) && !(mtd->flags & MTD_WRITEABLE)) {124124 put_mtd_device(mtd);125125 return -EACCES;126126 }127127-127127+128128 return 0;129129} /* mtd_open */130130···137137 DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n");138138139139 mtd = TO_MTD(file);140140-140140+141141 if (mtd->sync)142142 mtd->sync(mtd);143143-143143+144144 put_mtd_device(mtd);145145146146 return 0;···159159 int ret=0;160160 int len;161161 char *kbuf;162162-162162+163163 DEBUG(MTD_DEBUG_LEVEL0,"MTD_read\n");164164165165 if (*ppos + count > mtd->size)···167167168168 if (!count)169169 return 0;170170-170170+171171 /* FIXME: Use kiovec in 2.5 to lock down the user's buffers172172 and pass them directly to the MTD functions */173173 while (count) {174174- if (count > MAX_KMALLOC_SIZE) 174174+ if (count > MAX_KMALLOC_SIZE)175175 len = MAX_KMALLOC_SIZE;176176 else177177 len = count;···179179 kbuf=kmalloc(len,GFP_KERNEL);180180 if (!kbuf)181181 return -ENOMEM;182182-182182+183183 switch (MTD_MODE(file)) {184184 case MTD_MODE_OTP_FACT:185185 ret = mtd->read_fact_prot_reg(mtd, *ppos, len, &retlen, kbuf);···192192 }193193 /* Nand returns -EBADMSG on ecc errors, but it returns194194 * the data. For our userspace tools it is important195195- * to dump areas with ecc errors ! 195195+ * to dump areas with ecc errors !196196 * Userspace software which accesses NAND this way197197 * must be aware of the fact that it deals with NAND198198 */···214214 kfree(kbuf);215215 return ret;216216 }217217-217217+218218 kfree(kbuf);219219 }220220···231231 int len;232232233233 DEBUG(MTD_DEBUG_LEVEL0,"MTD_write\n");234234-234234+235235 if (*ppos == mtd->size)236236 return -ENOSPC;237237-237237+238238 if (*ppos + count > mtd->size)239239 count = mtd->size - *ppos;240240···242242 return 0;243243244244 while (count) {245245- if (count > MAX_KMALLOC_SIZE) 245245+ if (count > MAX_KMALLOC_SIZE)246246 len = MAX_KMALLOC_SIZE;247247 else248248 len = count;···257257 kfree(kbuf);258258 return -EFAULT;259259 }260260-260260+261261 switch (MTD_MODE(file)) {262262 case MTD_MODE_OTP_FACT:263263 ret = -EROFS;···282282 kfree(kbuf);283283 return ret;284284 }285285-285285+286286 kfree(kbuf);287287 }288288···306306 void __user *argp = (void __user *)arg;307307 int ret = 0;308308 u_long size;309309-309309+310310 DEBUG(MTD_DEBUG_LEVEL0, "MTD_ioctl\n");311311312312 size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;···318318 if (!access_ok(VERIFY_WRITE, argp, size))319319 return -EFAULT;320320 }321321-321321+322322 switch (cmd) {323323 case MEMGETREGIONCOUNT:324324 if (copy_to_user(argp, &(mtd->numeraseregions), sizeof(int)))···370370 erase->mtd = mtd;371371 erase->callback = mtdchar_erase_callback;372372 erase->priv = (unsigned long)&waitq;373373-373373+374374 /*375375 FIXME: Allow INTERRUPTIBLE. Which means376376 not having the wait_queue head on the stack.377377-377377+378378 If the wq_head is on the stack, and we379379 leave because we got interrupted, then the380380 wq_head is no longer there when the···402402 struct mtd_oob_buf buf;403403 void *databuf;404404 ssize_t retlen;405405-405405+406406 if(!(file->f_mode & 2))407407 return -EPERM;408408409409 if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf)))410410 return -EFAULT;411411-411411+412412 if (buf.length > 0x4096)413413 return -EINVAL;414414···424424 databuf = kmalloc(buf.length, GFP_KERNEL);425425 if (!databuf)426426 return -ENOMEM;427427-427427+428428 if (copy_from_user(databuf, buf.ptr, buf.length)) {429429 kfree(databuf);430430 return -EFAULT;···448448449449 if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf)))450450 return -EFAULT;451451-451451+452452 if (buf.length > 0x4096)453453 return -EINVAL;454454···464464 databuf = kmalloc(buf.length, GFP_KERNEL);465465 if (!databuf)466466 return -ENOMEM;467467-467467+468468 ret = (mtd->read_oob)(mtd, buf.start, buf.length, &retlen, databuf);469469470470 if (put_user(retlen, (uint32_t __user *)argp))471471 ret = -EFAULT;472472 else if (retlen && copy_to_user(buf.ptr, databuf, retlen))473473 ret = -EFAULT;474474-474474+475475 kfree(databuf);476476 break;477477 }···521521 case MEMGETBADBLOCK:522522 {523523 loff_t offs;524524-524524+525525 if (copy_from_user(&offs, argp, sizeof(loff_t)))526526 return -EFAULT;527527 if (!mtd->block_isbad)
+3-3
drivers/mtd/mtdconcat.c
···77 *88 * This code is GPL99 *1010- * $Id: mtdconcat.c,v 1.10 2005/11/06 10:04:37 gleixner Exp $1010+ * $Id: mtdconcat.c,v 1.11 2005/11/07 11:14:20 gleixner Exp $1111 */12121313#include <linux/kernel.h>···4444 */4545#define CONCAT(x) ((struct mtd_concat *)(x))46464747-/* 4747+/*4848 * MTD methods which look up the relevant subdevice, translate the4949 * effective address and pass through to the subdevice.5050 */···878878 return &concat->mtd;879879}880880881881-/* 881881+/*882882 * This function destroys an MTD object obtained from concat_mtd_devs()883883 */884884
+9-9
drivers/mtd/mtdcore.c
···11/*22- * $Id: mtdcore.c,v 1.46 2005/08/11 17:13:43 gleixner Exp $22+ * $Id: mtdcore.c,v 1.47 2005/11/07 11:14:20 gleixner Exp $33 *44 * Core registration and callback routines for MTD55 * drivers and users.···25252626#include <linux/mtd/mtd.h>27272828-/* These are exported solely for the purpose of mtd_blkdevs.c. You 2828+/* These are exported solely for the purpose of mtd_blkdevs.c. You2929 should not use them for _anything_ else */3030DECLARE_MUTEX(mtd_table_mutex);3131struct mtd_info *mtd_table[MAX_MTD_DEVICES];···6666 struct mtd_notifier *not = list_entry(this, struct mtd_notifier, list);6767 not->add(mtd);6868 }6969-6969+7070 up(&mtd_table_mutex);7171 /* We _know_ we aren't being removed, because7272 our caller is still holding us here. So none···7575 __module_get(THIS_MODULE);7676 return 0;7777 }7878-7878+7979 up(&mtd_table_mutex);8080 return 1;8181}···9393int del_mtd_device (struct mtd_info *mtd)9494{9595 int ret;9696-9696+9797 down(&mtd_table_mutex);98989999 if (mtd_table[mtd->index] != mtd) {100100 ret = -ENODEV;101101 } else if (mtd->usecount) {102102- printk(KERN_NOTICE "Removing MTD device #%d (%s) with use count %d\n", 102102+ printk(KERN_NOTICE "Removing MTD device #%d (%s) with use count %d\n",103103 mtd->index, mtd->name, mtd->usecount);104104 ret = -EBUSY;105105 } else {···140140 list_add(&new->list, &mtd_notifiers);141141142142 __module_get(THIS_MODULE);143143-143143+144144 for (i=0; i< MAX_MTD_DEVICES; i++)145145 if (mtd_table[i])146146 new->add(mtd_table[i]);···169169 for (i=0; i< MAX_MTD_DEVICES; i++)170170 if (mtd_table[i])171171 old->remove(mtd_table[i]);172172-172172+173173 list_del(&old->list);174174 up(&mtd_table_mutex);175175 return 0;···187187 * both, return the num'th driver only if its address matches. Return NULL188188 * if not.189189 */190190-190190+191191struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)192192{193193 struct mtd_info *ret = NULL;
+46-46
drivers/mtd/mtdpart.c
···55 *66 * This code is GPL77 *88- * $Id: mtdpart.c,v 1.54 2005/09/30 14:49:08 dedekind Exp $88+ * $Id: mtdpart.c,v 1.55 2005/11/07 11:14:20 gleixner Exp $99 *1010 * 02-21-2002 Thomas Gleixner <gleixner@autronix.de>1111 * added support for read_oob, write_oob1212- */ 1212+ */13131414#include <linux/module.h>1515#include <linux/types.h>···4141 */4242#define PART(x) ((struct mtd_part *)(x))43434444-4545-/* 4444+4545+/*4646 * MTD methods which simply translate the effective address and pass through4747 * to the _real_ device.4848 */49495050-static int part_read (struct mtd_info *mtd, loff_t from, size_t len, 5050+static int part_read (struct mtd_info *mtd, loff_t from, size_t len,5151 size_t *retlen, u_char *buf)5252{5353 struct mtd_part *part = PART(mtd);···5555 len = 0;5656 else if (from + len > mtd->size)5757 len = mtd->size - from;5858- if (part->master->read_ecc == NULL) 5959- return part->master->read (part->master, from + part->offset, 5858+ if (part->master->read_ecc == NULL)5959+ return part->master->read (part->master, from + part->offset,6060 len, retlen, buf);6161 else6262- return part->master->read_ecc (part->master, from + part->offset, 6262+ return part->master->read_ecc (part->master, from + part->offset,6363 len, retlen, buf, NULL, &mtd->oobinfo);6464}65656666-static int part_point (struct mtd_info *mtd, loff_t from, size_t len, 6666+static int part_point (struct mtd_info *mtd, loff_t from, size_t len,6767 size_t *retlen, u_char **buf)6868{6969 struct mtd_part *part = PART(mtd);···7171 len = 0;7272 else if (from + len > mtd->size)7373 len = mtd->size - from;7474- return part->master->point (part->master, from + part->offset, 7474+ return part->master->point (part->master, from + part->offset,7575 len, retlen, buf);7676}7777static void part_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len)···8282}838384848585-static int part_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, 8585+static int part_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,8686 size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel)8787{8888 struct mtd_part *part = PART(mtd);···9292 len = 0;9393 else if (from + len > mtd->size)9494 len = mtd->size - from;9595- return part->master->read_ecc (part->master, from + part->offset, 9595+ return part->master->read_ecc (part->master, from + part->offset,9696 len, retlen, buf, eccbuf, oobsel);9797}98989999-static int part_read_oob (struct mtd_info *mtd, loff_t from, size_t len, 9999+static int part_read_oob (struct mtd_info *mtd, loff_t from, size_t len,100100 size_t *retlen, u_char *buf)101101{102102 struct mtd_part *part = PART(mtd);···104104 len = 0;105105 else if (from + len > mtd->size)106106 len = mtd->size - from;107107- return part->master->read_oob (part->master, from + part->offset, 107107+ return part->master->read_oob (part->master, from + part->offset,108108 len, retlen, buf);109109}110110111111-static int part_read_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, 111111+static int part_read_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len,112112 size_t *retlen, u_char *buf)113113{114114 struct mtd_part *part = PART(mtd);115115- return part->master->read_user_prot_reg (part->master, from, 115115+ return part->master->read_user_prot_reg (part->master, from,116116 len, retlen, buf);117117}118118···123123 return part->master->get_user_prot_info (part->master, buf, len);124124}125125126126-static int part_read_fact_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, 126126+static int part_read_fact_prot_reg (struct mtd_info *mtd, loff_t from, size_t len,127127 size_t *retlen, u_char *buf)128128{129129 struct mtd_part *part = PART(mtd);130130- return part->master->read_fact_prot_reg (part->master, from, 130130+ return part->master->read_fact_prot_reg (part->master, from,131131 len, retlen, buf);132132}133133···148148 len = 0;149149 else if (to + len > mtd->size)150150 len = mtd->size - to;151151- if (part->master->write_ecc == NULL) 152152- return part->master->write (part->master, to + part->offset, 151151+ if (part->master->write_ecc == NULL)152152+ return part->master->write (part->master, to + part->offset,153153 len, retlen, buf);154154 else155155- return part->master->write_ecc (part->master, to + part->offset, 155155+ return part->master->write_ecc (part->master, to + part->offset,156156 len, retlen, buf, NULL, &mtd->oobinfo);157157-157157+158158}159159160160static int part_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,···170170 len = 0;171171 else if (to + len > mtd->size)172172 len = mtd->size - to;173173- return part->master->write_ecc (part->master, to + part->offset, 173173+ return part->master->write_ecc (part->master, to + part->offset,174174 len, retlen, buf, eccbuf, oobsel);175175}176176···184184 len = 0;185185 else if (to + len > mtd->size)186186 len = mtd->size - to;187187- return part->master->write_oob (part->master, to + part->offset, 187187+ return part->master->write_oob (part->master, to + part->offset,188188 len, retlen, buf);189189}190190191191-static int part_write_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, 191191+static int part_write_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len,192192 size_t *retlen, u_char *buf)193193{194194 struct mtd_part *part = PART(mtd);195195- return part->master->write_user_prot_reg (part->master, from, 195195+ return part->master->write_user_prot_reg (part->master, from,196196 len, retlen, buf);197197}198198199199-static int part_lock_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len) 199199+static int part_lock_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len)200200{201201 struct mtd_part *part = PART(mtd);202202 return part->master->lock_user_prot_reg (part->master, from, len);···208208 struct mtd_part *part = PART(mtd);209209 if (!(mtd->flags & MTD_WRITEABLE))210210 return -EROFS;211211- if (part->master->writev_ecc == NULL) 211211+ if (part->master->writev_ecc == NULL)212212 return part->master->writev (part->master, vecs, count,213213 to + part->offset, retlen);214214 else···221221 unsigned long count, loff_t from, size_t *retlen)222222{223223 struct mtd_part *part = PART(mtd);224224- if (part->master->readv_ecc == NULL) 224224+ if (part->master->readv_ecc == NULL)225225 return part->master->readv (part->master, vecs, count,226226 from + part->offset, retlen);227227 else228228 return part->master->readv_ecc (part->master, vecs, count,229229- from + part->offset, retlen, 229229+ from + part->offset, retlen,230230 NULL, &mtd->oobinfo);231231}232232···252252 if (oobsel == NULL)253253 oobsel = &mtd->oobinfo;254254 return part->master->readv_ecc (part->master, vecs, count,255255- from + part->offset, retlen, 255255+ from + part->offset, retlen,256256 eccbuf, oobsel);257257}258258···286286static int part_lock (struct mtd_info *mtd, loff_t ofs, size_t len)287287{288288 struct mtd_part *part = PART(mtd);289289- if ((len + ofs) > mtd->size) 289289+ if ((len + ofs) > mtd->size)290290 return -EINVAL;291291 return part->master->lock(part->master, ofs + part->offset, len);292292}···294294static int part_unlock (struct mtd_info *mtd, loff_t ofs, size_t len)295295{296296 struct mtd_part *part = PART(mtd);297297- if ((len + ofs) > mtd->size) 297297+ if ((len + ofs) > mtd->size)298298 return -EINVAL;299299 return part->master->unlock(part->master, ofs + part->offset, len);300300}···337337 return part->master->block_markbad(part->master, ofs);338338}339339340340-/* 341341- * This function unregisters and destroy all slave MTD objects which are 340340+/*341341+ * This function unregisters and destroy all slave MTD objects which are342342 * attached to the given master MTD object.343343 */344344···371371 * (Q: should we register the master MTD object as well?)372372 */373373374374-int add_mtd_partitions(struct mtd_info *master, 374374+int add_mtd_partitions(struct mtd_info *master,375375 const struct mtd_partition *parts,376376 int nbparts)377377{···414414 slave->mtd.point = part_point;415415 slave->mtd.unpoint = part_unpoint;416416 }417417-417417+418418 if (master->read_ecc)419419 slave->mtd.read_ecc = part_read_ecc;420420 if (master->write_ecc)···477477 if (slave->mtd.size == MTDPART_SIZ_FULL)478478 slave->mtd.size = master->size - slave->offset;479479 cur_offset = slave->offset + slave->mtd.size;480480-481481- printk (KERN_NOTICE "0x%08x-0x%08x : \"%s\"\n", slave->offset, 480480+481481+ printk (KERN_NOTICE "0x%08x-0x%08x : \"%s\"\n", slave->offset,482482 slave->offset + slave->mtd.size, slave->mtd.name);483483484484 /* let's do some sanity checks */···498498 /* Deal with variable erase size stuff */499499 int i;500500 struct mtd_erase_region_info *regions = master->eraseregions;501501-501501+502502 /* Find the first erase regions which is part of this partition. */503503 for (i=0; i < master->numeraseregions && slave->offset >= regions[i].offset; i++)504504 ;···513513 slave->mtd.erasesize = master->erasesize;514514 }515515516516- if ((slave->mtd.flags & MTD_WRITEABLE) && 516516+ if ((slave->mtd.flags & MTD_WRITEABLE) &&517517 (slave->offset % slave->mtd.erasesize)) {518518 /* Doesn't start on a boundary of major erase size */519519 /* FIXME: Let it be writable if it is on a boundary of _minor_ erase size though */···521521 printk ("mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",522522 parts[i].name);523523 }524524- if ((slave->mtd.flags & MTD_WRITEABLE) && 524524+ if ((slave->mtd.flags & MTD_WRITEABLE) &&525525 (slave->mtd.size % slave->mtd.erasesize)) {526526 slave->mtd.flags &= ~MTD_WRITEABLE;527527 printk ("mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",528528 parts[i].name);529529 }530530531531- /* copy oobinfo from master */ 531531+ /* copy oobinfo from master */532532 memcpy(&slave->mtd.oobinfo, &master->oobinfo, sizeof(slave->mtd.oobinfo));533533534534 if(parts[i].mtdp)···589589 return 0;590590}591591592592-int parse_mtd_partitions(struct mtd_info *master, const char **types, 592592+int parse_mtd_partitions(struct mtd_info *master, const char **types,593593 struct mtd_partition **pparts, unsigned long origin)594594{595595 struct mtd_part_parser *parser;596596 int ret = 0;597597-597597+598598 for ( ; ret <= 0 && *types; types++) {599599 parser = get_partition_parser(*types);600600#ifdef CONFIG_KMOD···608608 }609609 ret = (*parser->parse_fn)(master, pparts, origin);610610 if (ret > 0) {611611- printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n", 611611+ printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n",612612 ret, parser->name, master->name);613613 }614614 put_partition_parser(parser);
+40-40
drivers/mtd/nftlcore.c
···11/* Linux driver for NAND Flash Translation Layer */22/* (c) 1999 Machine Vision Holdings, Inc. */33/* Author: David Woodhouse <dwmw2@infradead.org> */44-/* $Id: nftlcore.c,v 1.97 2004/11/16 18:28:59 dwmw2 Exp $ */44+/* $Id: nftlcore.c,v 1.98 2005/11/07 11:14:21 gleixner Exp $ */5566/*77 The contents of this file are distributed under the GNU General···101101102102 if (nftl->mbd.size != nftl->heads * nftl->cylinders * nftl->sectors) {103103 /*104104- Oh no we don't have 104104+ Oh no we don't have105105 mbd.size == heads * cylinders * sectors106106 */107107 printk(KERN_WARNING "NFTL: cannot calculate a geometry to "108108 "match size of 0x%lx.\n", nftl->mbd.size);109109 printk(KERN_WARNING "NFTL: using C:%d H:%d S:%d "110110 "(== 0x%lx sects)\n",111111- nftl->cylinders, nftl->heads , nftl->sectors, 111111+ nftl->cylinders, nftl->heads , nftl->sectors,112112 (long)nftl->cylinders * (long)nftl->heads *113113 (long)nftl->sectors );114114 }···178178179179 if (!silly--) {180180 printk("Argh! No free blocks found! LastFreeEUN = %d, "181181- "FirstEUN = %d\n", nftl->LastFreeEUN, 181181+ "FirstEUN = %d\n", nftl->LastFreeEUN,182182 le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN));183183 return 0xffff;184184 }···210210 "Virtual Unit Chain %d!\n", thisVUC);211211 return BLOCK_NIL;212212 }213213-213213+214214 /* Scan to find the Erase Unit which holds the actual data for each215215 512-byte block within the Chain.216216 */···227227 if (block == 2) {228228 foldmark = oob.u.c.FoldMark | oob.u.c.FoldMark1;229229 if (foldmark == FOLD_MARK_IN_PROGRESS) {230230- DEBUG(MTD_DEBUG_LEVEL1, 230230+ DEBUG(MTD_DEBUG_LEVEL1,231231 "Write Inhibited on EUN %d\n", thisEUN);232232 inplace = 0;233233 } else {···249249 if (!BlockFreeFound[block])250250 BlockMap[block] = thisEUN;251251 else252252- printk(KERN_WARNING 252252+ printk(KERN_WARNING253253 "SECTOR_USED found after SECTOR_FREE "254254 "in Virtual Unit Chain %d for block %d\n",255255 thisVUC, block);···258258 if (!BlockFreeFound[block])259259 BlockMap[block] = BLOCK_NIL;260260 else261261- printk(KERN_WARNING 261261+ printk(KERN_WARNING262262 "SECTOR_DELETED found after SECTOR_FREE "263263 "in Virtual Unit Chain %d for block %d\n",264264 thisVUC, block);···277277 thisVUC);278278 return BLOCK_NIL;279279 }280280-280280+281281 thisEUN = nftl->ReplUnitTable[thisEUN];282282 }283283284284 if (inplace) {285285 /* We're being asked to be a fold-in-place. Check286286 that all blocks which actually have data associated287287- with them (i.e. BlockMap[block] != BLOCK_NIL) are 287287+ with them (i.e. BlockMap[block] != BLOCK_NIL) are288288 either already present or SECTOR_FREE in the target289289 block. If not, we're going to have to fold out-of-place290290 anyway.···297297 "block %d was %x lastEUN, "298298 "and is in EUN %d (%s) %d\n",299299 thisVUC, block, BlockLastState[block],300300- BlockMap[block], 300300+ BlockMap[block],301301 BlockMap[block]== targetEUN ? "==" : "!=",302302 targetEUN);303303 inplace = 0;···314314 inplace = 0;315315 }316316 }317317-317317+318318 if (!inplace) {319319 DEBUG(MTD_DEBUG_LEVEL1, "Cannot fold Virtual Unit Chain %d in place. "320320 "Trying out-of-place\n", thisVUC);321321 /* We need to find a targetEUN to fold into. */322322 targetEUN = NFTL_findfreeblock(nftl, 1);323323 if (targetEUN == BLOCK_NIL) {324324- /* Ouch. Now we're screwed. We need to do a 324324+ /* Ouch. Now we're screwed. We need to do a325325 fold-in-place of another chain to make room326326 for this one. We need a better way of selecting327327- which chain to fold, because makefreeblock will 327327+ which chain to fold, because makefreeblock will328328 only ask us to fold the same one again.329329 */330330 printk(KERN_WARNING···338338 chain by selecting the longer one */339339 oob.u.c.FoldMark = oob.u.c.FoldMark1 = cpu_to_le16(FOLD_MARK_IN_PROGRESS);340340 oob.u.c.unused = 0xffffffff;341341- MTD_WRITEOOB(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8, 341341+ MTD_WRITEOOB(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8,342342 8, &retlen, (char *)&oob.u);343343 }344344···361361 happen in case of media errors or deleted blocks) */362362 if (BlockMap[block] == BLOCK_NIL)363363 continue;364364-364364+365365 ret = MTD_READ(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512),366366- 512, &retlen, movebuf); 366366+ 512, &retlen, movebuf);367367 if (ret < 0) {368368 ret = MTD_READ(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block])369369 + (block * 512), 512, &retlen,370370- movebuf); 371371- if (ret != -EIO) 370370+ movebuf);371371+ if (ret != -EIO)372372 printk("Error went away on retry.\n");373373 }374374 memset(&oob, 0xff, sizeof(struct nftl_oob));···376376 MTD_WRITEECC(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + (block * 512),377377 512, &retlen, movebuf, (char *)&oob, &nftl->oobinfo);378378 }379379-379379+380380 /* add the header so that it is now a valid chain */381381 oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum382382 = cpu_to_le16(thisVUC);383383 oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff;384384-385385- MTD_WRITEOOB(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 8, 384384+385385+ MTD_WRITEOOB(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 8,386386 8, &retlen, (char *)&oob.u);387387388388 /* OK. We've moved the whole lot into the new block. Now we have to free the original blocks. */389389390390- /* At this point, we have two different chains for this Virtual Unit, and no way to tell 390390+ /* At this point, we have two different chains for this Virtual Unit, and no way to tell391391 them apart. If we crash now, we get confused. However, both contain the same data, so we392392 shouldn't actually lose data in this case. It's just that when we load up on a medium which393393 has duplicate chains, we need to free one of the chains because it's not necessary any more.···395395 thisEUN = nftl->EUNtable[thisVUC];396396 DEBUG(MTD_DEBUG_LEVEL1,"Want to erase\n");397397398398- /* For each block in the old chain (except the targetEUN of course), 398398+ /* For each block in the old chain (except the targetEUN of course),399399 free it and make it available for future use */400400 while (thisEUN <= nftl->lastEUN && thisEUN != targetEUN) {401401 unsigned int EUNtmp;···413413 }414414 thisEUN = EUNtmp;415415 }416416-416416+417417 /* Make this the new start of chain for thisVUC */418418 nftl->ReplUnitTable[targetEUN] = BLOCK_NIL;419419 nftl->EUNtable[thisVUC] = targetEUN;···423423424424static u16 NFTL_makefreeblock( struct NFTLrecord *nftl , unsigned pendingblock)425425{426426- /* This is the part that needs some cleverness applied. 426426+ /* This is the part that needs some cleverness applied.427427 For now, I'm doing the minimum applicable to actually428428 get the thing to work.429429 Wear-levelling and other clever stuff needs to be implemented···470470 return NFTL_foldchain (nftl, LongestChain, pendingblock);471471}472472473473-/* NFTL_findwriteunit: Return the unit number into which we can write 473473+/* NFTL_findwriteunit: Return the unit number into which we can write474474 for this block. Make it available if it isn't already475475*/476476static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)···488488 a free space for the block in question.489489 */490490491491- /* This condition catches the 0x[7f]fff cases, as well as 491491+ /* This condition catches the 0x[7f]fff cases, as well as492492 being a sanity check for past-end-of-media access493493 */494494 lastEUN = BLOCK_NIL;···503503504504 MTD_READOOB(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs,505505 8, &retlen, (char *)&bci);506506-506506+507507 DEBUG(MTD_DEBUG_LEVEL2, "Status of block %d in EUN %d is %x\n",508508 block , writeEUN, le16_to_cpu(bci.Status));509509···518518 break;519519 default:520520 // Invalid block. Don't use it any more. Must implement.521521- break; 521521+ break;522522 }523523-524524- if (!silly--) { 523523+524524+ if (!silly--) {525525 printk(KERN_WARNING526526 "Infinite loop in Virtual Unit Chain 0x%x\n",527527 thisVUC);···532532 writeEUN = nftl->ReplUnitTable[writeEUN];533533 }534534535535- /* OK. We didn't find one in the existing chain, or there 535535+ /* OK. We didn't find one in the existing chain, or there536536 is no existing chain. */537537538538 /* Try to find an already-free block */···546546547547 /* First remember the start of this chain */548548 //u16 startEUN = nftl->EUNtable[thisVUC];549549-549549+550550 //printk("Write to VirtualUnitChain %d, calling makefreeblock()\n", thisVUC);551551 writeEUN = NFTL_makefreeblock(nftl, 0xffff);552552553553 if (writeEUN == BLOCK_NIL) {554554- /* OK, we accept that the above comment is 554554+ /* OK, we accept that the above comment is555555 lying - there may have been free blocks556556 last time we called NFTL_findfreeblock(),557557 but they are reserved for when we're···562562 }563563 if (writeEUN == BLOCK_NIL) {564564 /* Ouch. This should never happen - we should565565- always be able to make some room somehow. 566566- If we get here, we've allocated more storage 565565+ always be able to make some room somehow.566566+ If we get here, we've allocated more storage567567 space than actual media, or our makefreeblock568568 routine is missing something.569569 */570570 printk(KERN_WARNING "Cannot make free space.\n");571571 return BLOCK_NIL;572572- } 572572+ }573573 //printk("Restarting scan\n");574574 lastEUN = BLOCK_NIL;575575 continue;576576 }577577578578 /* We've found a free block. Insert it into the chain. */579579-579579+580580 if (lastEUN != BLOCK_NIL) {581581 thisVUC |= 0x8000; /* It's a replacement block */582582 } else {···749749750750static int __init init_nftl(void)751751{752752- printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.97 $, nftlmount.c %s\n", nftlmountrev);752752+ printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.98 $, nftlmount.c %s\n", nftlmountrev);753753754754 return register_mtd_blktrans(&nftl_tr);755755}
+28-28
drivers/mtd/nftlmount.c
···11-/* 11+/*22 * NFTL mount code with extensive checks33 *44- * Author: Fabrice Bellard (fabrice.bellard@netgem.com) 44+ * Author: Fabrice Bellard (fabrice.bellard@netgem.com)55 * Copyright (C) 2000 Netgem S.A.66 *77- * $Id: nftlmount.c,v 1.40 2004/11/22 14:38:29 kalev Exp $77+ * $Id: nftlmount.c,v 1.41 2005/11/07 11:14:21 gleixner Exp $88 *99 * This program is free software; you can redistribute it and/or modify1010 * it under the terms of the GNU General Public License as published by···31313232#define SECTORSIZE 51233333434-char nftlmountrev[]="$Revision: 1.40 $";3434+char nftlmountrev[]="$Revision: 1.41 $";35353636/* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the3737 * various device information of the NFTL partition and Bad Unit Table. Update···4747 struct NFTLMediaHeader *mh = &nftl->MediaHdr;4848 unsigned int i;49495050- /* Assume logical EraseSize == physical erasesize for starting the scan. 5050+ /* Assume logical EraseSize == physical erasesize for starting the scan.5151 We'll sort it out later if we find a MediaHeader which says otherwise */5252 /* Actually, we won't. The new DiskOnChip driver has already scanned5353 the MediaHeader and adjusted the virtual erasesize it presents in···8383 if (retlen < 6 || memcmp(buf, "ANAND", 6)) {8484 /* ANAND\0 not found. Continue */8585#if 08686- printk(KERN_DEBUG "ANAND header not found at 0x%x in mtd%d\n", 8686+ printk(KERN_DEBUG "ANAND header not found at 0x%x in mtd%d\n",8787 block * nftl->EraseSize, nftl->mbd.mtd->index);8888-#endif 8888+#endif8989 continue;9090 }9191···103103 */104104 if (le16_to_cpu(h1.EraseMark | h1.EraseMark1) != ERASE_MARK) {105105 printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but erase mark not present (0x%04x,0x%04x instead)\n",106106- block * nftl->EraseSize, nftl->mbd.mtd->index, 106106+ block * nftl->EraseSize, nftl->mbd.mtd->index,107107 le16_to_cpu(h1.EraseMark), le16_to_cpu(h1.EraseMark1));108108 continue;109109 }···175175 nftl->nb_boot_blocks = le16_to_cpu(mh->FirstPhysicalEUN);176176 if ((nftl->nb_boot_blocks + 2) >= nftl->nb_blocks) {177177 printk(KERN_NOTICE "NFTL Media Header sanity check failed:\n");178178- printk(KERN_NOTICE "nb_boot_blocks (%d) + 2 > nb_blocks (%d)\n", 178178+ printk(KERN_NOTICE "nb_boot_blocks (%d) + 2 > nb_blocks (%d)\n",179179 nftl->nb_boot_blocks, nftl->nb_blocks);180180 return -1;181181 }···187187 nftl->numvunits, nftl->nb_blocks, nftl->nb_boot_blocks);188188 return -1;189189 }190190-190190+191191 nftl->mbd.size = nftl->numvunits * (nftl->EraseSize / SECTORSIZE);192192193193 /* If we're not using the last sectors in the device for some reason,···210210 printk(KERN_NOTICE "NFTL: allocation of ReplUnitTable failed\n");211211 return -ENOMEM;212212 }213213-213213+214214 /* mark the bios blocks (blocks before NFTL MediaHeader) as reserved */215215 for (i = 0; i < nftl->nb_boot_blocks; i++)216216 nftl->ReplUnitTable[i] = BLOCK_RESERVED;217217 /* mark all remaining blocks as potentially containing data */218218- for (; i < nftl->nb_blocks; i++) { 218218+ for (; i < nftl->nb_blocks; i++) {219219 nftl->ReplUnitTable[i] = BLOCK_NOTEXPLORED;220220 }221221···245245 if (nftl->mbd.mtd->block_isbad(nftl->mbd.mtd, i * nftl->EraseSize))246246 nftl->ReplUnitTable[i] = BLOCK_RESERVED;247247 }248248-248248+249249 nftl->MediaUnit = block;250250 boot_record_count++;251251-251251+252252 } /* foreach (block) */253253-253253+254254 return boot_record_count?0:-1;255255}256256···265265}266266267267/* check_free_sector: check if a free sector is actually FREE, i.e. All 0xff in data and oob area */268268-static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int len, 268268+static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int len,269269 int check_oob)270270{271271 int i;···293293 *294294 * Return: 0 when succeed, -1 on error.295295 *296296- * ToDo: 1. Is it neceressary to check_free_sector after erasing ?? 296296+ * ToDo: 1. Is it neceressary to check_free_sector after erasing ??297297 */298298int NFTL_formatblock(struct NFTLrecord *nftl, int block)299299{···385385 /* verify that the sector is really free. If not, mark386386 as ignore */387387 if (memcmpb(&bci, 0xff, 8) != 0 ||388388- check_free_sectors(nftl, block * nftl->EraseSize + i * SECTORSIZE, 388388+ check_free_sectors(nftl, block * nftl->EraseSize + i * SECTORSIZE,389389 SECTORSIZE, 0) != 0) {390390 printk("Incorrect free sector %d in block %d: "391391 "marking it as ignored\n",···486486 size_t retlen;487487488488 /* check erase mark. */489489- if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, 489489+ if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,490490 &retlen, (char *)&h1) < 0)491491 return -1;492492···501501 h1.EraseMark = cpu_to_le16(ERASE_MARK);502502 h1.EraseMark1 = cpu_to_le16(ERASE_MARK);503503 h1.WearInfo = cpu_to_le32(0);504504- if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, 504504+ if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,505505 &retlen, (char *)&h1) < 0)506506 return -1;507507 } else {···582582583583 for (;;) {584584 /* read the block header. If error, we format the chain */585585- if (MTD_READOOB(s->mbd.mtd, block * s->EraseSize + 8, 8, 585585+ if (MTD_READOOB(s->mbd.mtd, block * s->EraseSize + 8, 8,586586 &retlen, (char *)&h0) < 0 ||587587- MTD_READOOB(s->mbd.mtd, block * s->EraseSize + SECTORSIZE + 8, 8, 587587+ MTD_READOOB(s->mbd.mtd, block * s->EraseSize + SECTORSIZE + 8, 8,588588 &retlen, (char *)&h1) < 0) {589589 s->ReplUnitTable[block] = BLOCK_NIL;590590 do_format_chain = 1;···639639 first_logical_block = logical_block;640640 } else {641641 if (logical_block != first_logical_block) {642642- printk("Block %d: incorrect logical block: %d expected: %d\n", 642642+ printk("Block %d: incorrect logical block: %d expected: %d\n",643643 block, logical_block, first_logical_block);644644 /* the chain is incorrect : we must format it,645645 but we need to read it completly */···668668 s->ReplUnitTable[block] = BLOCK_NIL;669669 break;670670 } else if (rep_block >= s->nb_blocks) {671671- printk("Block %d: referencing invalid block %d\n", 671671+ printk("Block %d: referencing invalid block %d\n",672672 block, rep_block);673673 do_format_chain = 1;674674 s->ReplUnitTable[block] = BLOCK_NIL;···688688 s->ReplUnitTable[block] = rep_block;689689 s->EUNtable[first_logical_block] = BLOCK_NIL;690690 } else {691691- printk("Block %d: referencing block %d already in another chain\n", 691691+ printk("Block %d: referencing block %d already in another chain\n",692692 block, rep_block);693693 /* XXX: should handle correctly fold in progress chains */694694 do_format_chain = 1;···710710 } else {711711 unsigned int first_block1, chain_to_format, chain_length1;712712 int fold_mark;713713-713713+714714 /* valid chain : get foldmark */715715 fold_mark = get_fold_mark(s, first_block);716716 if (fold_mark == 0) {···729729 if (first_block1 != BLOCK_NIL) {730730 /* XXX: what to do if same length ? */731731 chain_length1 = calc_chain_length(s, first_block1);732732- printk("Two chains at blocks %d (len=%d) and %d (len=%d)\n", 732732+ printk("Two chains at blocks %d (len=%d) and %d (len=%d)\n",733733 first_block1, chain_length1, first_block, chain_length);734734-734734+735735 if (chain_length >= chain_length1) {736736 chain_to_format = first_block1;737737 s->EUNtable[first_logical_block] = first_block;
+2-2
drivers/mtd/redboot.c
···11/*22- * $Id: redboot.c,v 1.17 2004/11/22 11:33:56 ijc Exp $22+ * $Id: redboot.c,v 1.18 2005/11/07 11:14:21 gleixner Exp $33 *44 * Parse RedBoot-style Flash Image System (FIS) tables and55 * produce a Linux partition array to match.···3939 return 1;4040}41414242-static int parse_redboot_partitions(struct mtd_info *master, 4242+static int parse_redboot_partitions(struct mtd_info *master,4343 struct mtd_partition **pparts,4444 unsigned long fis_origin)4545{
+57-57
drivers/mtd/rfd_ftl.c
···33 *44 * Copyright (C) 2005 Sean Young <sean@mess.org>55 *66- * $Id: rfd_ftl.c,v 1.4 2005/07/31 22:49:14 sean Exp $66+ * $Id: rfd_ftl.c,v 1.5 2005/11/07 11:14:21 gleixner Exp $77 *88 * This type of flash translation layer (FTL) is used by the Embedded BIOS99 * by General Software. It is known as the Resident Flash Disk (RFD), see:···9595{9696 struct block *block = &part->blocks[block_no];9797 int i;9898-9898+9999 block->offset = part->block_size * block_no;100100101101 if (le16_to_cpu(part->header_cache[0]) != RFD_MAGIC) {···109109110110 for (i=0; i<part->data_sectors_per_block; i++) {111111 u16 entry;112112-112112+113113 entry = le16_to_cpu(part->header_cache[HEADER_MAP_OFFSET + i]);114114115115 if (entry == SECTOR_DELETED)116116 continue;117117-117117+118118 if (entry == SECTOR_FREE) {119119 block->free_sectors++;120120 continue;···122122123123 if (entry == SECTOR_ZERO)124124 entry = 0;125125-125125+126126 if (entry >= part->sector_count) {127127- printk(KERN_NOTICE PREFIX 127127+ printk(KERN_NOTICE PREFIX128128 "'%s': unit #%d: entry %d corrupt, "129129 "sector %d out of range\n",130130 part->mbd.mtd->name, block_no, i, entry);···132132 }133133134134 if (part->sector_map[entry] != -1) {135135- printk(KERN_NOTICE PREFIX 135135+ printk(KERN_NOTICE PREFIX136136 "'%s': more than one entry for sector %d\n",137137 part->mbd.mtd->name, entry);138138 part->errors = 1;139139 continue;140140 }141141142142- part->sector_map[entry] = block->offset + 142142+ part->sector_map[entry] = block->offset +143143 (i + part->header_sectors_per_block) * SECTOR_SIZE;144144145145 block->used_sectors++;···165165 return -ENOENT;166166167167 /* each erase block has three bytes header, followed by the map */168168- part->header_sectors_per_block = 169169- ((HEADER_MAP_OFFSET + sectors_per_block) * 168168+ part->header_sectors_per_block =169169+ ((HEADER_MAP_OFFSET + sectors_per_block) *170170 sizeof(u16) + SECTOR_SIZE - 1) / SECTOR_SIZE;171171172172- part->data_sectors_per_block = sectors_per_block - 172172+ part->data_sectors_per_block = sectors_per_block -173173 part->header_sectors_per_block;174174175175- part->header_size = (HEADER_MAP_OFFSET + 175175+ part->header_size = (HEADER_MAP_OFFSET +176176 part->data_sectors_per_block) * sizeof(u16);177177178178 part->cylinders = (part->data_sectors_per_block *···188188 if (!part->header_cache)189189 goto err;190190191191- part->blocks = kcalloc(part->total_blocks, sizeof(struct block), 191191+ part->blocks = kcalloc(part->total_blocks, sizeof(struct block),192192 GFP_KERNEL);193193 if (!part->blocks)194194 goto err;···200200 goto err;201201 }202202203203- for (i=0; i<part->sector_count; i++) 203203+ for (i=0; i<part->sector_count; i++)204204 part->sector_map[i] = -1;205205206206 for (i=0, blocks_found=0; i<part->total_blocks; i++) {207207- rc = part->mbd.mtd->read(part->mbd.mtd, 207207+ rc = part->mbd.mtd->read(part->mbd.mtd,208208 i * part->block_size, part->header_size,209209 &retlen, (u_char*)part->header_cache);210210211211 if (!rc && retlen != part->header_size)212212 rc = -EIO;213213214214- if (rc) 214214+ if (rc)215215 goto err;216216217217 if (!build_block_map(part, i))···226226 }227227228228 if (part->reserved_block == -1) {229229- printk(KERN_NOTICE PREFIX "'%s': no empty erase unit found\n", 229229+ printk(KERN_NOTICE PREFIX "'%s': no empty erase unit found\n",230230 part->mbd.mtd->name);231231232232 part->errors = 1;···248248 u_long addr;249249 size_t retlen;250250 int rc;251251-251251+252252 if (sector >= part->sector_count)253253 return -EIO;254254···266266 }267267 } else268268 memset(buf, 0, SECTOR_SIZE);269269-269269+270270 return 0;271271-} 271271+}272272273273static void erase_callback(struct erase_info *erase)274274{···288288289289 if (erase->state != MTD_ERASE_DONE) {290290 printk(KERN_WARNING PREFIX "erase failed at 0x%x on '%s', "291291- "state %d\n", erase->addr, 291291+ "state %d\n", erase->addr,292292 part->mbd.mtd->name, erase->state);293293294294 part->blocks[i].state = BLOCK_FAILED;···307307 part->blocks[i].used_sectors = 0;308308 part->blocks[i].erases++;309309310310- rc = part->mbd.mtd->write(part->mbd.mtd, 311311- part->blocks[i].offset, sizeof(magic), &retlen, 310310+ rc = part->mbd.mtd->write(part->mbd.mtd,311311+ part->blocks[i].offset, sizeof(magic), &retlen,312312 (u_char*)&magic);313313-313313+314314 if (!rc && retlen != sizeof(magic))315315 rc = -EIO;316316317317 if (rc) {318318 printk(KERN_NOTICE PREFIX "'%s': unable to write RFD "319319 "header at 0x%lx\n",320320- part->mbd.mtd->name, 320320+ part->mbd.mtd->name,321321 part->blocks[i].offset);322322 part->blocks[i].state = BLOCK_FAILED;323323 }···374374 map = kmalloc(part->header_size, GFP_KERNEL);375375 if (!map)376376 goto err2;377377-378378- rc = part->mbd.mtd->read(part->mbd.mtd, 379379- part->blocks[block_no].offset, part->header_size, 377377+378378+ rc = part->mbd.mtd->read(part->mbd.mtd,379379+ part->blocks[block_no].offset, part->header_size,380380 &retlen, (u_char*)map);381381-381381+382382 if (!rc && retlen != part->header_size)383383 rc = -EIO;384384385385 if (rc) {386386 printk(KERN_NOTICE PREFIX "error reading '%s' at "387387- "0x%lx\n", part->mbd.mtd->name, 387387+ "0x%lx\n", part->mbd.mtd->name,388388 part->blocks[block_no].offset);389389390390 goto err;···398398 if (entry == SECTOR_FREE || entry == SECTOR_DELETED)399399 continue;400400401401- if (entry == SECTOR_ZERO) 401401+ if (entry == SECTOR_ZERO)402402 entry = 0;403403404404 /* already warned about and ignored in build_block_map() */405405- if (entry >= part->sector_count) 405405+ if (entry >= part->sector_count)406406 continue;407407408408 addr = part->blocks[block_no].offset +···418418 }419419 rc = part->mbd.mtd->read(part->mbd.mtd, addr,420420 SECTOR_SIZE, &retlen, sector_data);421421-421421+422422 if (!rc && retlen != SECTOR_SIZE)423423 rc = -EIO;424424···429429430430 goto err;431431 }432432-432432+433433 rc = rfd_ftl_writesect((struct mtd_blktrans_dev*)part,434434 entry, sector_data);435435-436436- if (rc) 435435+436436+ if (rc)437437 goto err;438438 }439439···447447 return rc;448448}449449450450-static int reclaim_block(struct partition *part, u_long *old_sector) 450450+static int reclaim_block(struct partition *part, u_long *old_sector)451451{452452 int block, best_block, score, old_sector_block;453453 int rc;454454-454454+455455 /* we have a race if sync doesn't exist */456456 if (part->mbd.mtd->sync)457457 part->mbd.mtd->sync(part->mbd.mtd);···474474 * more removed sectors is more efficient (have to move475475 * less).476476 */477477- if (part->blocks[block].free_sectors) 477477+ if (part->blocks[block].free_sectors)478478 return 0;479479480480 this_score = part->blocks[block].used_sectors;481481482482- if (block == old_sector_block) 482482+ if (block == old_sector_block)483483 this_score--;484484 else {485485 /* no point in moving a full block */486486- if (part->blocks[block].used_sectors == 486486+ if (part->blocks[block].used_sectors ==487487 part->data_sectors_per_block)488488 continue;489489 }···529529 stop = block;530530531531 do {532532- if (part->blocks[block].free_sectors && 532532+ if (part->blocks[block].free_sectors &&533533 block != part->reserved_block)534534 return block;535535···563563 }564564 }565565566566- rc = part->mbd.mtd->read(part->mbd.mtd, part->blocks[block].offset, 566566+ rc = part->mbd.mtd->read(part->mbd.mtd, part->blocks[block].offset,567567 part->header_size, &retlen, (u_char*)part->header_cache);568568569569 if (!rc && retlen != part->header_size)···571571572572 if (rc) {573573 printk(KERN_NOTICE PREFIX "'%s': unable to read header at "574574- "0x%lx\n", part->mbd.mtd->name, 574574+ "0x%lx\n", part->mbd.mtd->name,575575 part->blocks[block].offset);576576 goto err;577577 }···580580581581err:582582 return rc;583583-} 583583+}584584585585static int mark_sector_deleted(struct partition *part, u_long old_addr)586586{···590590 u16 del = const_cpu_to_le16(SECTOR_DELETED);591591592592 block = old_addr / part->block_size;593593- offset = (old_addr % part->block_size) / SECTOR_SIZE - 593593+ offset = (old_addr % part->block_size) / SECTOR_SIZE -594594 part->header_sectors_per_block;595595596596 addr = part->blocks[block].offset +···604604 if (rc) {605605 printk(KERN_WARNING PREFIX "error writing '%s' at "606606 "0x%lx\n", part->mbd.mtd->name, addr);607607- if (rc) 607607+ if (rc)608608 goto err;609609 }610610 if (block == part->current_block)···627627 i = stop = part->data_sectors_per_block - block->free_sectors;628628629629 do {630630- if (le16_to_cpu(part->header_cache[HEADER_MAP_OFFSET + i]) 630630+ if (le16_to_cpu(part->header_cache[HEADER_MAP_OFFSET + i])631631 == SECTOR_FREE)632632 return i;633633···653653 !part->blocks[part->current_block].free_sectors) {654654655655 rc = find_writeable_block(part, old_addr);656656- if (rc) 656656+ if (rc)657657 goto err;658658 }659659···665665 rc = -ENOSPC;666666 goto err;667667 }668668-669669- addr = (i + part->header_sectors_per_block) * SECTOR_SIZE + 668668+669669+ addr = (i + part->header_sectors_per_block) * SECTOR_SIZE +670670 block->offset;671671- rc = part->mbd.mtd->write(part->mbd.mtd, 671671+ rc = part->mbd.mtd->write(part->mbd.mtd,672672 addr, SECTOR_SIZE, &retlen, (u_char*)buf);673673674674 if (!rc && retlen != SECTOR_SIZE)···677677 if (rc) {678678 printk(KERN_WARNING PREFIX "error writing '%s' at 0x%lx\n",679679 part->mbd.mtd->name, addr);680680- if (rc) 680680+ if (rc)681681 goto err;682682 }683683···697697 if (rc) {698698 printk(KERN_WARNING PREFIX "error writing '%s' at 0x%lx\n",699699 part->mbd.mtd->name, addr);700700- if (rc) 700700+ if (rc)701701 goto err;702702 }703703 block->used_sectors++;···738738 break;739739 }740740741741- if (i == SECTOR_SIZE) 741741+ if (i == SECTOR_SIZE)742742 part->sector_map[sector] = -1;743743744744 if (old_addr != -1)···801801802802 if (!add_mtd_blktrans_dev((void*)part))803803 return;804804- } 804804+ }805805806806 kfree(part);807807}···828828 .major = RFD_FTL_MAJOR,829829 .part_bits = PART_BITS,830830 .readsect = rfd_ftl_readsect,831831- .writesect = rfd_ftl_writesect, 831831+ .writesect = rfd_ftl_writesect,832832 .getgeo = rfd_ftl_getgeo,833833 .add_mtd = rfd_ftl_add_mtd,834834 .remove_dev = rfd_ftl_remove_dev,