mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-01 10:43:43 +00:00
[MTD] core: Clean up trailing white spaces
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
b95f9609c7
commit
97894cda57
@ -1,4 +1,4 @@
|
||||
# $Id: Kconfig,v 1.10 2005/07/11 10:39:27 gleixner Exp $
|
||||
# $Id: Kconfig,v 1.11 2005/11/07 11:14:19 gleixner Exp $
|
||||
|
||||
menu "Memory Technology Devices (MTD)"
|
||||
|
||||
@ -10,7 +10,7 @@ config MTD
|
||||
will provide the generic support for MTD drivers to register
|
||||
themselves with the kernel and for potential users of MTD devices
|
||||
to enumerate the devices which are present and obtain a handle on
|
||||
them. It will also allow you to select individual drivers for
|
||||
them. It will also allow you to select individual drivers for
|
||||
particular hardware and users of MTD devices. If unsure, say N.
|
||||
|
||||
config MTD_DEBUG
|
||||
@ -61,11 +61,11 @@ config MTD_REDBOOT_PARTS
|
||||
|
||||
If you need code which can detect and parse this table, and register
|
||||
MTD 'partitions' corresponding to each image in the table, enable
|
||||
this option.
|
||||
this option.
|
||||
|
||||
You will still need the parsing functions to be called by the driver
|
||||
for your particular device. It won't happen automatically. The
|
||||
SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for
|
||||
for your particular device. It won't happen automatically. The
|
||||
SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for
|
||||
example.
|
||||
|
||||
config MTD_REDBOOT_DIRECTORY_BLOCK
|
||||
@ -81,10 +81,10 @@ config MTD_REDBOOT_DIRECTORY_BLOCK
|
||||
partition table. A zero or positive value gives an absolete
|
||||
erase block number. A negative value specifies a number of
|
||||
sectors before the end of the device.
|
||||
|
||||
|
||||
For example "2" means block number 2, "-1" means the last
|
||||
block and "-2" means the penultimate block.
|
||||
|
||||
|
||||
config MTD_REDBOOT_PARTS_UNALLOCATED
|
||||
bool " Include unallocated flash regions"
|
||||
depends on MTD_REDBOOT_PARTS
|
||||
@ -105,11 +105,11 @@ config MTD_CMDLINE_PARTS
|
||||
---help---
|
||||
Allow generic configuration of the MTD paritition tables via the kernel
|
||||
command line. Multiple flash resources are supported for hardware where
|
||||
different kinds of flash memory are available.
|
||||
different kinds of flash memory are available.
|
||||
|
||||
You will still need the parsing functions to be called by the driver
|
||||
for your particular device. It won't happen automatically. The
|
||||
SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for
|
||||
for your particular device. It won't happen automatically. The
|
||||
SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for
|
||||
example.
|
||||
|
||||
The format for the command line is as follows:
|
||||
@ -118,12 +118,12 @@ config MTD_CMDLINE_PARTS
|
||||
<mtddef> := <mtd-id>:<partdef>[,<partdef>]
|
||||
<partdef> := <size>[@offset][<name>][ro]
|
||||
<mtd-id> := unique id used in mapping driver/device
|
||||
<size> := standard linux memsize OR "-" to denote all
|
||||
<size> := standard linux memsize OR "-" to denote all
|
||||
remaining space
|
||||
<name> := (NAME)
|
||||
|
||||
Due to the way Linux handles the command line, no spaces are
|
||||
allowed in the partition definition, including mtd id's and partition
|
||||
Due to the way Linux handles the command line, no spaces are
|
||||
allowed in the partition definition, including mtd id's and partition
|
||||
names.
|
||||
|
||||
Examples:
|
||||
@ -240,7 +240,7 @@ config INFTL
|
||||
tristate "INFTL (Inverse NAND Flash Translation Layer) support"
|
||||
depends on MTD
|
||||
---help---
|
||||
This provides support for the Inverse NAND Flash Translation
|
||||
This provides support for the Inverse NAND Flash Translation
|
||||
Layer which is used on M-Systems' newer DiskOnChip devices. It
|
||||
uses a kind of pseudo-file system on a flash device to emulate
|
||||
a block device with 512-byte sectors, on top of which you put
|
||||
@ -257,8 +257,8 @@ config RFD_FTL
|
||||
tristate "Resident Flash Disk (Flash Translation Layer) support"
|
||||
depends on MTD
|
||||
---help---
|
||||
This provides support for the flash translation layer known
|
||||
as the Resident Flash Disk (RFD), as used by the Embedded BIOS
|
||||
This provides support for the flash translation layer known
|
||||
as the Resident Flash Disk (RFD), as used by the Embedded BIOS
|
||||
of General Software. There is a blurb at:
|
||||
|
||||
http://www.gensw.com/pages/prod/bios/rfd.htm
|
||||
|
@ -1,27 +1,27 @@
|
||||
/*======================================================================
|
||||
|
||||
drivers/mtd/afs.c: ARM Flash Layout/Partitioning
|
||||
|
||||
|
||||
Copyright (C) 2000 ARM Limited
|
||||
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
This is access code for flashes using ARM's flash partitioning
|
||||
|
||||
This is access code for flashes using ARM's flash partitioning
|
||||
standards.
|
||||
|
||||
$Id: afs.c,v 1.13 2004/02/27 22:09:59 rmk Exp $
|
||||
$Id: afs.c,v 1.15 2005/11/07 11:14:19 gleixner Exp $
|
||||
|
||||
======================================================================*/
|
||||
|
||||
@ -163,7 +163,7 @@ afs_read_iis(struct mtd_info *mtd, struct image_info_struct *iis, u_int ptr)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int parse_afs_partitions(struct mtd_info *mtd,
|
||||
static int parse_afs_partitions(struct mtd_info *mtd,
|
||||
struct mtd_partition **pparts,
|
||||
unsigned long origin)
|
||||
{
|
||||
|
@ -1,24 +1,24 @@
|
||||
/*
|
||||
* $Id: cmdlinepart.c,v 1.18 2005/06/07 15:04:26 joern Exp $
|
||||
* $Id: cmdlinepart.c,v 1.19 2005/11/07 11:14:19 gleixner Exp $
|
||||
*
|
||||
* Read flash partition table from command line
|
||||
*
|
||||
* Copyright 2002 SYSGO Real-Time Solutions GmbH
|
||||
*
|
||||
* The format for the command line is as follows:
|
||||
*
|
||||
*
|
||||
* mtdparts=<mtddef>[;<mtddef]
|
||||
* <mtddef> := <mtd-id>:<partdef>[,<partdef>]
|
||||
* <partdef> := <size>[@offset][<name>][ro]
|
||||
* <mtd-id> := unique name used in mapping driver/device (mtd->name)
|
||||
* <size> := standard linux memsize OR "-" to denote all remaining space
|
||||
* <name> := '(' NAME ')'
|
||||
*
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
*
|
||||
* 1 NOR Flash, with 1 single writable partition:
|
||||
* edb7312-nor:-
|
||||
*
|
||||
*
|
||||
* 1 NOR Flash with 2 partitions, 1 NAND with one
|
||||
* edb7312-nor:256k(ARMboot)ro,-(root);edb7312-nand:-(home)
|
||||
*/
|
||||
@ -60,17 +60,17 @@ static int cmdline_parsed = 0;
|
||||
|
||||
/*
|
||||
* Parse one partition definition for an MTD. Since there can be many
|
||||
* comma separated partition definitions, this function calls itself
|
||||
* comma separated partition definitions, this function calls itself
|
||||
* recursively until no more partition definitions are found. Nice side
|
||||
* effect: the memory to keep the mtd_partition structs and the names
|
||||
* is allocated upon the last definition being found. At that point the
|
||||
* syntax has been verified ok.
|
||||
*/
|
||||
static struct mtd_partition * newpart(char *s,
|
||||
static struct mtd_partition * newpart(char *s,
|
||||
char **retptr,
|
||||
int *num_parts,
|
||||
int this_part,
|
||||
unsigned char **extra_mem_ptr,
|
||||
int this_part,
|
||||
unsigned char **extra_mem_ptr,
|
||||
int extra_mem_size)
|
||||
{
|
||||
struct mtd_partition *parts;
|
||||
@ -102,7 +102,7 @@ static struct mtd_partition * newpart(char *s,
|
||||
mask_flags = 0; /* this is going to be a regular partition */
|
||||
delim = 0;
|
||||
/* check for offset */
|
||||
if (*s == '@')
|
||||
if (*s == '@')
|
||||
{
|
||||
s++;
|
||||
offset = memparse(s, &s);
|
||||
@ -112,7 +112,7 @@ static struct mtd_partition * newpart(char *s,
|
||||
{
|
||||
delim = ')';
|
||||
}
|
||||
|
||||
|
||||
if (delim)
|
||||
{
|
||||
char *p;
|
||||
@ -131,12 +131,12 @@ static struct mtd_partition * newpart(char *s,
|
||||
name = NULL;
|
||||
name_len = 13; /* Partition_000 */
|
||||
}
|
||||
|
||||
|
||||
/* record name length for memory allocation later */
|
||||
extra_mem_size += name_len + 1;
|
||||
|
||||
/* test for options */
|
||||
if (strncmp(s, "ro", 2) == 0)
|
||||
if (strncmp(s, "ro", 2) == 0)
|
||||
{
|
||||
mask_flags |= MTD_WRITEABLE;
|
||||
s += 2;
|
||||
@ -151,7 +151,7 @@ static struct mtd_partition * newpart(char *s,
|
||||
return NULL;
|
||||
}
|
||||
/* more partitions follow, parse them */
|
||||
if ((parts = newpart(s + 1, &s, num_parts,
|
||||
if ((parts = newpart(s + 1, &s, num_parts,
|
||||
this_part + 1, &extra_mem, extra_mem_size)) == 0)
|
||||
return NULL;
|
||||
}
|
||||
@ -187,7 +187,7 @@ static struct mtd_partition * newpart(char *s,
|
||||
extra_mem += name_len + 1;
|
||||
|
||||
dbg(("partition %d: name <%s>, offset %x, size %x, mask flags %x\n",
|
||||
this_part,
|
||||
this_part,
|
||||
parts[this_part].name,
|
||||
parts[this_part].offset,
|
||||
parts[this_part].size,
|
||||
@ -204,8 +204,8 @@ static struct mtd_partition * newpart(char *s,
|
||||
return parts;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the command line.
|
||||
/*
|
||||
* Parse the command line.
|
||||
*/
|
||||
static int mtdpart_setup_real(char *s)
|
||||
{
|
||||
@ -230,7 +230,7 @@ static int mtdpart_setup_real(char *s)
|
||||
|
||||
dbg(("parsing <%s>\n", p+1));
|
||||
|
||||
/*
|
||||
/*
|
||||
* parse one mtd. have it reserve memory for the
|
||||
* struct cmdline_mtd_partition and the mtd-id string.
|
||||
*/
|
||||
@ -239,7 +239,7 @@ static int mtdpart_setup_real(char *s)
|
||||
&num_parts, /* out: number of parts */
|
||||
0, /* first partition */
|
||||
(unsigned char**)&this_mtd, /* out: extra mem */
|
||||
mtd_id_len + 1 + sizeof(*this_mtd) +
|
||||
mtd_id_len + 1 + sizeof(*this_mtd) +
|
||||
sizeof(void*)-1 /*alignment*/);
|
||||
if(!parts)
|
||||
{
|
||||
@ -254,21 +254,21 @@ static int mtdpart_setup_real(char *s)
|
||||
}
|
||||
|
||||
/* align this_mtd */
|
||||
this_mtd = (struct cmdline_mtd_partition *)
|
||||
this_mtd = (struct cmdline_mtd_partition *)
|
||||
ALIGN((unsigned long)this_mtd, sizeof(void*));
|
||||
/* enter results */
|
||||
/* enter results */
|
||||
this_mtd->parts = parts;
|
||||
this_mtd->num_parts = num_parts;
|
||||
this_mtd->mtd_id = (char*)(this_mtd + 1);
|
||||
strlcpy(this_mtd->mtd_id, mtd_id, mtd_id_len + 1);
|
||||
|
||||
/* link into chain */
|
||||
this_mtd->next = partitions;
|
||||
this_mtd->next = partitions;
|
||||
partitions = this_mtd;
|
||||
|
||||
dbg(("mtdid=<%s> num_parts=<%d>\n",
|
||||
dbg(("mtdid=<%s> num_parts=<%d>\n",
|
||||
this_mtd->mtd_id, this_mtd->num_parts));
|
||||
|
||||
|
||||
|
||||
/* EOS - we're done */
|
||||
if (*s == 0)
|
||||
@ -292,7 +292,7 @@ static int mtdpart_setup_real(char *s)
|
||||
* information. It returns partitions for the requested mtd device, or
|
||||
* the first one in the chain if a NULL mtd_id is passed in.
|
||||
*/
|
||||
static int parse_cmdline_partitions(struct mtd_info *master,
|
||||
static int parse_cmdline_partitions(struct mtd_info *master,
|
||||
struct mtd_partition **pparts,
|
||||
unsigned long origin)
|
||||
{
|
||||
@ -322,7 +322,7 @@ static int parse_cmdline_partitions(struct mtd_info *master,
|
||||
part->parts[i].size = master->size - offset;
|
||||
if (offset + part->parts[i].size > master->size)
|
||||
{
|
||||
printk(KERN_WARNING ERRP
|
||||
printk(KERN_WARNING ERRP
|
||||
"%s: partitioning exceeds flash size, truncating\n",
|
||||
part->mtd_id);
|
||||
part->parts[i].size = master->size - offset;
|
||||
@ -338,8 +338,8 @@ static int parse_cmdline_partitions(struct mtd_info *master,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This is the handler for our kernel parameter, called from
|
||||
/*
|
||||
* This is the handler for our kernel parameter, called from
|
||||
* main.c::checksetup(). Note that we can not yet kmalloc() anything,
|
||||
* so we only save the commandline for later processing.
|
||||
*
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* This version ported to the Linux-MTD system by dwmw2@infradead.org
|
||||
* $Id: ftl.c,v 1.55 2005/01/17 13:47:21 hvr Exp $
|
||||
* $Id: ftl.c,v 1.58 2005/11/07 11:14:19 gleixner Exp $
|
||||
*
|
||||
* Fixes: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
|
||||
* - fixes some leaks on failure in build_maps and ftl_notify_add, cleanups
|
||||
@ -53,7 +53,7 @@
|
||||
Use of the FTL format for non-PCMCIA applications may be an
|
||||
infringement of these patents. For additional information,
|
||||
contact M-Systems (http://www.m-sys.com) directly.
|
||||
|
||||
|
||||
======================================================================*/
|
||||
#include <linux/mtd/blktrans.h>
|
||||
#include <linux/module.h>
|
||||
@ -160,7 +160,7 @@ static void ftl_erase_callback(struct erase_info *done);
|
||||
Scan_header() checks to see if a memory region contains an FTL
|
||||
partition. build_maps() reads all the erase unit headers, builds
|
||||
the erase unit map, and then builds the virtual page map.
|
||||
|
||||
|
||||
======================================================================*/
|
||||
|
||||
static int scan_header(partition_t *part)
|
||||
@ -176,10 +176,10 @@ static int scan_header(partition_t *part)
|
||||
(offset + sizeof(header)) < max_offset;
|
||||
offset += part->mbd.mtd->erasesize ? : 0x2000) {
|
||||
|
||||
err = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &ret,
|
||||
err = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &ret,
|
||||
(unsigned char *)&header);
|
||||
|
||||
if (err)
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (strcmp(header.DataOrgTuple+3, "FTL100") == 0) break;
|
||||
@ -232,10 +232,10 @@ static int build_maps(partition_t *part)
|
||||
for (i = 0; i < le16_to_cpu(part->header.NumEraseUnits); i++) {
|
||||
offset = ((i + le16_to_cpu(part->header.FirstPhysicalEUN))
|
||||
<< part->header.EraseUnitSize);
|
||||
ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &retval,
|
||||
ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &retval,
|
||||
(unsigned char *)&header);
|
||||
|
||||
if (ret)
|
||||
|
||||
if (ret)
|
||||
goto out_XferInfo;
|
||||
|
||||
ret = -1;
|
||||
@ -274,7 +274,7 @@ static int build_maps(partition_t *part)
|
||||
"don't add up!\n");
|
||||
goto out_XferInfo;
|
||||
}
|
||||
|
||||
|
||||
/* Set up virtual page map */
|
||||
blocks = le32_to_cpu(header.FormattedSize) >> header.BlockSize;
|
||||
part->VirtualBlockMap = vmalloc(blocks * sizeof(u_int32_t));
|
||||
@ -296,12 +296,12 @@ static int build_maps(partition_t *part)
|
||||
part->EUNInfo[i].Free = 0;
|
||||
part->EUNInfo[i].Deleted = 0;
|
||||
offset = part->EUNInfo[i].Offset + le32_to_cpu(header.BAMOffset);
|
||||
|
||||
ret = part->mbd.mtd->read(part->mbd.mtd, offset,
|
||||
part->BlocksPerUnit * sizeof(u_int32_t), &retval,
|
||||
|
||||
ret = part->mbd.mtd->read(part->mbd.mtd, offset,
|
||||
part->BlocksPerUnit * sizeof(u_int32_t), &retval,
|
||||
(unsigned char *)part->bam_cache);
|
||||
|
||||
if (ret)
|
||||
|
||||
if (ret)
|
||||
goto out_bam_cache;
|
||||
|
||||
for (j = 0; j < part->BlocksPerUnit; j++) {
|
||||
@ -316,7 +316,7 @@ static int build_maps(partition_t *part)
|
||||
part->EUNInfo[i].Deleted++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ret = 0;
|
||||
goto out;
|
||||
|
||||
@ -336,7 +336,7 @@ static int build_maps(partition_t *part)
|
||||
|
||||
Erase_xfer() schedules an asynchronous erase operation for a
|
||||
transfer unit.
|
||||
|
||||
|
||||
======================================================================*/
|
||||
|
||||
static int erase_xfer(partition_t *part,
|
||||
@ -351,10 +351,10 @@ static int erase_xfer(partition_t *part,
|
||||
xfer->state = XFER_ERASING;
|
||||
|
||||
/* Is there a free erase slot? Always in MTD. */
|
||||
|
||||
|
||||
|
||||
|
||||
erase=kmalloc(sizeof(struct erase_info), GFP_KERNEL);
|
||||
if (!erase)
|
||||
if (!erase)
|
||||
return -ENOMEM;
|
||||
|
||||
erase->mtd = part->mbd.mtd;
|
||||
@ -362,7 +362,7 @@ static int erase_xfer(partition_t *part,
|
||||
erase->addr = xfer->Offset;
|
||||
erase->len = 1 << part->header.EraseUnitSize;
|
||||
erase->priv = (u_long)part;
|
||||
|
||||
|
||||
ret = part->mbd.mtd->erase(part->mbd.mtd, erase);
|
||||
|
||||
if (!ret)
|
||||
@ -377,7 +377,7 @@ static int erase_xfer(partition_t *part,
|
||||
|
||||
Prepare_xfer() takes a freshly erased transfer unit and gives
|
||||
it an appropriate header.
|
||||
|
||||
|
||||
======================================================================*/
|
||||
|
||||
static void ftl_erase_callback(struct erase_info *erase)
|
||||
@ -385,7 +385,7 @@ static void ftl_erase_callback(struct erase_info *erase)
|
||||
partition_t *part;
|
||||
struct xfer_info_t *xfer;
|
||||
int i;
|
||||
|
||||
|
||||
/* Look up the transfer unit */
|
||||
part = (partition_t *)(erase->priv);
|
||||
|
||||
@ -422,7 +422,7 @@ static int prepare_xfer(partition_t *part, int i)
|
||||
|
||||
xfer = &part->XferInfo[i];
|
||||
xfer->state = XFER_FAILED;
|
||||
|
||||
|
||||
DEBUG(1, "ftl_cs: preparing xfer unit at 0x%x\n", xfer->Offset);
|
||||
|
||||
/* Write the transfer unit header */
|
||||
@ -446,7 +446,7 @@ static int prepare_xfer(partition_t *part, int i)
|
||||
|
||||
for (i = 0; i < nbam; i++, offset += sizeof(u_int32_t)) {
|
||||
|
||||
ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int32_t),
|
||||
ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int32_t),
|
||||
&retlen, (u_char *)&ctl);
|
||||
|
||||
if (ret)
|
||||
@ -454,7 +454,7 @@ static int prepare_xfer(partition_t *part, int i)
|
||||
}
|
||||
xfer->state = XFER_PREPARED;
|
||||
return 0;
|
||||
|
||||
|
||||
} /* prepare_xfer */
|
||||
|
||||
/*======================================================================
|
||||
@ -466,7 +466,7 @@ static int prepare_xfer(partition_t *part, int i)
|
||||
All data blocks are copied to the corresponding blocks in the
|
||||
target unit, so the virtual block map does not need to be
|
||||
updated.
|
||||
|
||||
|
||||
======================================================================*/
|
||||
|
||||
static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
|
||||
@ -486,14 +486,14 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
|
||||
xfer = &part->XferInfo[xferunit];
|
||||
DEBUG(2, "ftl_cs: copying block 0x%x to 0x%x\n",
|
||||
eun->Offset, xfer->Offset);
|
||||
|
||||
|
||||
|
||||
|
||||
/* Read current BAM */
|
||||
if (part->bam_index != srcunit) {
|
||||
|
||||
offset = eun->Offset + le32_to_cpu(part->header.BAMOffset);
|
||||
|
||||
ret = part->mbd.mtd->read(part->mbd.mtd, offset,
|
||||
ret = part->mbd.mtd->read(part->mbd.mtd, offset,
|
||||
part->BlocksPerUnit * sizeof(u_int32_t),
|
||||
&retlen, (u_char *) (part->bam_cache));
|
||||
|
||||
@ -501,11 +501,11 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
|
||||
part->bam_index = 0xffff;
|
||||
|
||||
if (ret) {
|
||||
printk( KERN_WARNING "ftl: Failed to read BAM cache in copy_erase_unit()!\n");
|
||||
printk( KERN_WARNING "ftl: Failed to read BAM cache in copy_erase_unit()!\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Write the LogicalEUN for the transfer unit */
|
||||
xfer->state = XFER_UNKNOWN;
|
||||
offset = xfer->Offset + 20; /* Bad! */
|
||||
@ -513,12 +513,12 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
|
||||
|
||||
ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int16_t),
|
||||
&retlen, (u_char *) &unit);
|
||||
|
||||
|
||||
if (ret) {
|
||||
printk( KERN_WARNING "ftl: Failed to write back to BAM cache in copy_erase_unit()!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Copy all data blocks from source unit to transfer unit */
|
||||
src = eun->Offset; dest = xfer->Offset;
|
||||
|
||||
@ -558,15 +558,15 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
|
||||
}
|
||||
|
||||
/* Write the BAM to the transfer unit */
|
||||
ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + le32_to_cpu(part->header.BAMOffset),
|
||||
part->BlocksPerUnit * sizeof(int32_t), &retlen,
|
||||
ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + le32_to_cpu(part->header.BAMOffset),
|
||||
part->BlocksPerUnit * sizeof(int32_t), &retlen,
|
||||
(u_char *)part->bam_cache);
|
||||
if (ret) {
|
||||
printk( KERN_WARNING "ftl: Error writing BAM in copy_erase_unit\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* All clear? Then update the LogicalEUN again */
|
||||
ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + 20, sizeof(u_int16_t),
|
||||
&retlen, (u_char *)&srcunitswap);
|
||||
@ -574,9 +574,9 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
|
||||
if (ret) {
|
||||
printk(KERN_WARNING "ftl: Error writing new LogicalEUN in copy_erase_unit\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Update the maps and usage stats*/
|
||||
i = xfer->EraseCount;
|
||||
xfer->EraseCount = eun->EraseCount;
|
||||
@ -588,10 +588,10 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
|
||||
part->FreeTotal += free;
|
||||
eun->Free = free;
|
||||
eun->Deleted = 0;
|
||||
|
||||
|
||||
/* Now, the cache should be valid for the new block */
|
||||
part->bam_index = srcunit;
|
||||
|
||||
|
||||
return 0;
|
||||
} /* copy_erase_unit */
|
||||
|
||||
@ -608,7 +608,7 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
|
||||
oldest data unit instead. This means that we generally postpone
|
||||
the next reclaimation as long as possible, but shuffle static
|
||||
stuff around a bit for wear leveling.
|
||||
|
||||
|
||||
======================================================================*/
|
||||
|
||||
static int reclaim_block(partition_t *part)
|
||||
@ -666,7 +666,7 @@ static int reclaim_block(partition_t *part)
|
||||
else
|
||||
DEBUG(1, "ftl_cs: reclaim failed: no "
|
||||
"suitable transfer units!\n");
|
||||
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
@ -715,7 +715,7 @@ static int reclaim_block(partition_t *part)
|
||||
returns the block index -- the erase unit is just the currently
|
||||
cached unit. If there are no free blocks, it returns 0 -- this
|
||||
is never a valid data block because it contains the header.
|
||||
|
||||
|
||||
======================================================================*/
|
||||
|
||||
#ifdef PSYCHO_DEBUG
|
||||
@ -737,7 +737,7 @@ static u_int32_t find_free(partition_t *part)
|
||||
u_int32_t blk;
|
||||
size_t retlen;
|
||||
int ret;
|
||||
|
||||
|
||||
/* Find an erase unit with some free space */
|
||||
stop = (part->bam_index == 0xffff) ? 0 : part->bam_index;
|
||||
eun = stop;
|
||||
@ -749,17 +749,17 @@ static u_int32_t find_free(partition_t *part)
|
||||
|
||||
if (part->EUNInfo[eun].Free == 0)
|
||||
return 0;
|
||||
|
||||
|
||||
/* Is this unit's BAM cached? */
|
||||
if (eun != part->bam_index) {
|
||||
/* Invalidate cache */
|
||||
part->bam_index = 0xffff;
|
||||
|
||||
ret = part->mbd.mtd->read(part->mbd.mtd,
|
||||
ret = part->mbd.mtd->read(part->mbd.mtd,
|
||||
part->EUNInfo[eun].Offset + le32_to_cpu(part->header.BAMOffset),
|
||||
part->BlocksPerUnit * sizeof(u_int32_t),
|
||||
&retlen, (u_char *) (part->bam_cache));
|
||||
|
||||
|
||||
if (ret) {
|
||||
printk(KERN_WARNING"ftl: Error reading BAM in find_free\n");
|
||||
return 0;
|
||||
@ -781,14 +781,14 @@ static u_int32_t find_free(partition_t *part)
|
||||
}
|
||||
DEBUG(2, "ftl_cs: found free block at %d in %d\n", blk, eun);
|
||||
return blk;
|
||||
|
||||
|
||||
} /* find_free */
|
||||
|
||||
|
||||
/*======================================================================
|
||||
|
||||
Read a series of sectors from an FTL partition.
|
||||
|
||||
|
||||
======================================================================*/
|
||||
|
||||
static int ftl_read(partition_t *part, caddr_t buffer,
|
||||
@ -798,7 +798,7 @@ static int ftl_read(partition_t *part, caddr_t buffer,
|
||||
u_long i;
|
||||
int ret;
|
||||
size_t offset, retlen;
|
||||
|
||||
|
||||
DEBUG(2, "ftl_cs: ftl_read(0x%p, 0x%lx, %ld)\n",
|
||||
part, sector, nblocks);
|
||||
if (!(part->state & FTL_FORMATTED)) {
|
||||
@ -834,7 +834,7 @@ static int ftl_read(partition_t *part, caddr_t buffer,
|
||||
/*======================================================================
|
||||
|
||||
Write a series of sectors to an FTL partition
|
||||
|
||||
|
||||
======================================================================*/
|
||||
|
||||
static int set_bam_entry(partition_t *part, u_int32_t log_addr,
|
||||
@ -855,7 +855,7 @@ static int set_bam_entry(partition_t *part, u_int32_t log_addr,
|
||||
blk = (log_addr % bsize) / SECTOR_SIZE;
|
||||
offset = (part->EUNInfo[eun].Offset + blk * sizeof(u_int32_t) +
|
||||
le32_to_cpu(part->header.BAMOffset));
|
||||
|
||||
|
||||
#ifdef PSYCHO_DEBUG
|
||||
ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(u_int32_t),
|
||||
&retlen, (u_char *)&old_addr);
|
||||
@ -925,7 +925,7 @@ static int ftl_write(partition_t *part, caddr_t buffer,
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bsize = 1 << part->header.EraseUnitSize;
|
||||
|
||||
virt_addr = sector * SECTOR_SIZE | BLOCK_DATA;
|
||||
@ -949,12 +949,12 @@ static int ftl_write(partition_t *part, caddr_t buffer,
|
||||
log_addr = part->bam_index * bsize + blk * SECTOR_SIZE;
|
||||
part->EUNInfo[part->bam_index].Free--;
|
||||
part->FreeTotal--;
|
||||
if (set_bam_entry(part, log_addr, 0xfffffffe))
|
||||
if (set_bam_entry(part, log_addr, 0xfffffffe))
|
||||
return -EIO;
|
||||
part->EUNInfo[part->bam_index].Deleted++;
|
||||
offset = (part->EUNInfo[part->bam_index].Offset +
|
||||
blk * SECTOR_SIZE);
|
||||
ret = part->mbd.mtd->write(part->mbd.mtd, offset, SECTOR_SIZE, &retlen,
|
||||
ret = part->mbd.mtd->write(part->mbd.mtd, offset, SECTOR_SIZE, &retlen,
|
||||
buffer);
|
||||
|
||||
if (ret) {
|
||||
@ -964,7 +964,7 @@ static int ftl_write(partition_t *part, caddr_t buffer,
|
||||
offset);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
||||
/* Only delete the old entry when the new entry is ready */
|
||||
old_addr = part->VirtualBlockMap[sector+i];
|
||||
if (old_addr != 0xffffffff) {
|
||||
@ -979,7 +979,7 @@ static int ftl_write(partition_t *part, caddr_t buffer,
|
||||
return -EIO;
|
||||
part->VirtualBlockMap[sector+i] = log_addr;
|
||||
part->EUNInfo[part->bam_index].Deleted--;
|
||||
|
||||
|
||||
buffer += SECTOR_SIZE;
|
||||
virt_addr += SECTOR_SIZE;
|
||||
}
|
||||
@ -1034,20 +1034,20 @@ static void ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
|
||||
partition_t *partition;
|
||||
|
||||
partition = kmalloc(sizeof(partition_t), GFP_KERNEL);
|
||||
|
||||
|
||||
if (!partition) {
|
||||
printk(KERN_WARNING "No memory to scan for FTL on %s\n",
|
||||
mtd->name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
memset(partition, 0, sizeof(partition_t));
|
||||
|
||||
partition->mbd.mtd = mtd;
|
||||
|
||||
if ((scan_header(partition) == 0) &&
|
||||
if ((scan_header(partition) == 0) &&
|
||||
(build_maps(partition) == 0)) {
|
||||
|
||||
|
||||
partition->state = FTL_FORMATTED;
|
||||
#ifdef PCMCIA_DEBUG
|
||||
printk(KERN_INFO "ftl_cs: opening %d KiB FTL partition\n",
|
||||
@ -1086,7 +1086,7 @@ struct mtd_blktrans_ops ftl_tr = {
|
||||
|
||||
int init_ftl(void)
|
||||
{
|
||||
DEBUG(0, "$Id: ftl.c,v 1.55 2005/01/17 13:47:21 hvr Exp $\n");
|
||||
DEBUG(0, "$Id: ftl.c,v 1.58 2005/11/07 11:14:19 gleixner Exp $\n");
|
||||
|
||||
return register_mtd_blktrans(&ftl_tr);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* inftlcore.c -- Linux driver for Inverse Flash Translation Layer (INFTL)
|
||||
*
|
||||
* (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
|
||||
@ -7,7 +7,7 @@
|
||||
* (c) 1999 Machine Vision Holdings, Inc.
|
||||
* Author: David Woodhouse <dwmw2@infradead.org>
|
||||
*
|
||||
* $Id: inftlcore.c,v 1.18 2004/11/16 18:28:59 dwmw2 Exp $
|
||||
* $Id: inftlcore.c,v 1.19 2005/11/07 11:14:20 gleixner Exp $
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -113,14 +113,14 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
|
||||
|
||||
if (inftl->mbd.size != inftl->heads * inftl->cylinders * inftl->sectors) {
|
||||
/*
|
||||
Oh no we don't have
|
||||
Oh no we don't have
|
||||
mbd.size == heads * cylinders * sectors
|
||||
*/
|
||||
printk(KERN_WARNING "INFTL: cannot calculate a geometry to "
|
||||
"match size of 0x%lx.\n", inftl->mbd.size);
|
||||
printk(KERN_WARNING "INFTL: using C:%d H:%d S:%d "
|
||||
"(== 0x%lx sects)\n",
|
||||
inftl->cylinders, inftl->heads , inftl->sectors,
|
||||
inftl->cylinders, inftl->heads , inftl->sectors,
|
||||
(long)inftl->cylinders * (long)inftl->heads *
|
||||
(long)inftl->sectors );
|
||||
}
|
||||
@ -223,7 +223,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
|
||||
"Virtual Unit Chain %d!\n", thisVUC);
|
||||
return BLOCK_NIL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Scan to find the Erase Unit which holds the actual data for each
|
||||
* 512-byte block within the Chain.
|
||||
@ -264,7 +264,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
|
||||
"Unit Chain 0x%x\n", thisVUC);
|
||||
return BLOCK_NIL;
|
||||
}
|
||||
|
||||
|
||||
thisEUN = inftl->PUtable[thisEUN];
|
||||
}
|
||||
|
||||
@ -295,15 +295,15 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
|
||||
*/
|
||||
if (BlockMap[block] == BLOCK_NIL)
|
||||
continue;
|
||||
|
||||
|
||||
ret = MTD_READ(inftl->mbd.mtd, (inftl->EraseSize *
|
||||
BlockMap[block]) + (block * SECTORSIZE), SECTORSIZE,
|
||||
&retlen, movebuf);
|
||||
&retlen, movebuf);
|
||||
if (ret < 0) {
|
||||
ret = MTD_READ(inftl->mbd.mtd, (inftl->EraseSize *
|
||||
BlockMap[block]) + (block * SECTORSIZE),
|
||||
SECTORSIZE, &retlen, movebuf);
|
||||
if (ret != -EIO)
|
||||
if (ret != -EIO)
|
||||
DEBUG(MTD_DEBUG_LEVEL1, "INFTL: error went "
|
||||
"away on retry?\n");
|
||||
}
|
||||
@ -355,7 +355,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
|
||||
static u16 INFTL_makefreeblock(struct INFTLrecord *inftl, unsigned pendingblock)
|
||||
{
|
||||
/*
|
||||
* This is the part that needs some cleverness applied.
|
||||
* This is the part that needs some cleverness applied.
|
||||
* For now, I'm doing the minimum applicable to actually
|
||||
* get the thing to work.
|
||||
* Wear-levelling and other clever stuff needs to be implemented
|
||||
@ -414,7 +414,7 @@ static int nrbits(unsigned int val, int bitcount)
|
||||
}
|
||||
|
||||
/*
|
||||
* INFTL_findwriteunit: Return the unit number into which we can write
|
||||
* INFTL_findwriteunit: Return the unit number into which we can write
|
||||
* for this block. Make it available if it isn't already.
|
||||
*/
|
||||
static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)
|
||||
@ -463,10 +463,10 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)
|
||||
* Invalid block. Don't use it any more.
|
||||
* Must implement.
|
||||
*/
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!silly--) {
|
||||
|
||||
if (!silly--) {
|
||||
printk(KERN_WARNING "INFTL: infinite loop in "
|
||||
"Virtual Unit Chain 0x%x\n", thisVUC);
|
||||
return 0xffff;
|
||||
@ -482,7 +482,7 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)
|
||||
|
||||
|
||||
/*
|
||||
* OK. We didn't find one in the existing chain, or there
|
||||
* OK. We didn't find one in the existing chain, or there
|
||||
* is no existing chain. Allocate a new one.
|
||||
*/
|
||||
writeEUN = INFTL_findfreeblock(inftl, 0);
|
||||
@ -506,8 +506,8 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)
|
||||
if (writeEUN == BLOCK_NIL) {
|
||||
/*
|
||||
* Ouch. This should never happen - we should
|
||||
* always be able to make some room somehow.
|
||||
* If we get here, we've allocated more storage
|
||||
* always be able to make some room somehow.
|
||||
* If we get here, we've allocated more storage
|
||||
* space than actual media, or our makefreeblock
|
||||
* routine is missing something.
|
||||
*/
|
||||
@ -518,7 +518,7 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)
|
||||
INFTL_dumpVUchains(inftl);
|
||||
#endif
|
||||
return BLOCK_NIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -543,7 +543,7 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)
|
||||
parity |= (nrbits(prev_block, 16) & 0x1) ? 0x2 : 0;
|
||||
parity |= (nrbits(anac, 8) & 0x1) ? 0x4 : 0;
|
||||
parity |= (nrbits(nacs, 8) & 0x1) ? 0x8 : 0;
|
||||
|
||||
|
||||
oob.u.a.virtualUnitNo = cpu_to_le16(thisVUC);
|
||||
oob.u.a.prevUnitNo = cpu_to_le16(prev_block);
|
||||
oob.u.a.ANAC = anac;
|
||||
@ -562,7 +562,7 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)
|
||||
oob.u.b.parityPerField = parity;
|
||||
oob.u.b.discarded = 0xaa;
|
||||
|
||||
MTD_WRITEOOB(inftl->mbd.mtd, writeEUN * inftl->EraseSize +
|
||||
MTD_WRITEOOB(inftl->mbd.mtd, writeEUN * inftl->EraseSize +
|
||||
SECTORSIZE * 4 + 8, 8, &retlen, (char *)&oob.u);
|
||||
|
||||
inftl->PUtable[writeEUN] = inftl->VUtable[thisVUC];
|
||||
@ -602,7 +602,7 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
|
||||
"Virtual Unit Chain %d!\n", thisVUC);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Scan through the Erase Units to determine whether any data is in
|
||||
* each of the 512-byte blocks within the Chain.
|
||||
@ -642,7 +642,7 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
|
||||
"Unit Chain 0x%x\n", thisVUC);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
thisEUN = inftl->PUtable[thisEUN];
|
||||
}
|
||||
|
||||
@ -758,7 +758,7 @@ static int INFTL_deleteblock(struct INFTLrecord *inftl, unsigned block)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int inftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block,
|
||||
static int inftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block,
|
||||
char *buffer)
|
||||
{
|
||||
struct INFTLrecord *inftl = (void *)mbd;
|
||||
@ -893,7 +893,7 @@ extern char inftlmountrev[];
|
||||
|
||||
static int __init init_inftl(void)
|
||||
{
|
||||
printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.18 $, "
|
||||
printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.19 $, "
|
||||
"inftlmount.c %s\n", inftlmountrev);
|
||||
|
||||
return register_mtd_blktrans(&inftl_tr);
|
||||
|
@ -1,14 +1,14 @@
|
||||
/*
|
||||
/*
|
||||
* inftlmount.c -- INFTL mount code with extensive checks.
|
||||
*
|
||||
* Author: Greg Ungerer (gerg@snapgear.com)
|
||||
* (C) Copyright 2002-2003, Greg Ungerer (gerg@snapgear.com)
|
||||
*
|
||||
* Based heavily on the nftlmount.c code which is:
|
||||
* Author: Fabrice Bellard (fabrice.bellard@netgem.com)
|
||||
* Author: Fabrice Bellard (fabrice.bellard@netgem.com)
|
||||
* Copyright (C) 2000 Netgem S.A.
|
||||
*
|
||||
* $Id: inftlmount.c,v 1.17 2005/08/08 08:56:19 dwmw2 Exp $
|
||||
* $Id: inftlmount.c,v 1.18 2005/11/07 11:14:20 gleixner Exp $
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -41,7 +41,7 @@
|
||||
#include <linux/mtd/inftl.h>
|
||||
#include <linux/mtd/compatmac.h>
|
||||
|
||||
char inftlmountrev[]="$Revision: 1.17 $";
|
||||
char inftlmountrev[]="$Revision: 1.18 $";
|
||||
|
||||
/*
|
||||
* find_boot_record: Find the INFTL Media Header and its Spare copy which
|
||||
@ -273,7 +273,7 @@ static int find_boot_record(struct INFTLrecord *inftl)
|
||||
inftl->nb_boot_blocks);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
inftl->mbd.size = inftl->numvunits *
|
||||
(inftl->EraseSize / SECTORSIZE);
|
||||
|
||||
@ -302,7 +302,7 @@ static int find_boot_record(struct INFTLrecord *inftl)
|
||||
inftl->nb_blocks * sizeof(u16));
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
/* Mark the blocks before INFTL MediaHeader as reserved */
|
||||
for (i = 0; i < inftl->nb_boot_blocks; i++)
|
||||
inftl->PUtable[i] = BLOCK_RESERVED;
|
||||
@ -380,7 +380,7 @@ static int check_free_sectors(struct INFTLrecord *inftl, unsigned int address,
|
||||
*
|
||||
* Return: 0 when succeed, -1 on error.
|
||||
*
|
||||
* ToDo: 1. Is it neceressary to check_free_sector after erasing ??
|
||||
* ToDo: 1. Is it neceressary to check_free_sector after erasing ??
|
||||
*/
|
||||
int INFTL_formatblock(struct INFTLrecord *inftl, int block)
|
||||
{
|
||||
@ -578,7 +578,7 @@ int INFTL_mount(struct INFTLrecord *s)
|
||||
printk(KERN_ERR "INFTL: Out of memory.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
memset(ANACtable, 0, s->nb_blocks);
|
||||
|
||||
/*
|
||||
@ -600,7 +600,7 @@ int INFTL_mount(struct INFTLrecord *s)
|
||||
|
||||
for (chain_length = 0; ; chain_length++) {
|
||||
|
||||
if ((chain_length == 0) &&
|
||||
if ((chain_length == 0) &&
|
||||
(s->PUtable[block] != BLOCK_NOTEXPLORED)) {
|
||||
/* Nothing to do here, onto next block */
|
||||
break;
|
||||
@ -747,7 +747,7 @@ int INFTL_mount(struct INFTLrecord *s)
|
||||
"in virtual chain %d\n",
|
||||
s->PUtable[block], logical_block);
|
||||
s->PUtable[block] = BLOCK_NIL;
|
||||
|
||||
|
||||
}
|
||||
if (ANACtable[block] != ANAC) {
|
||||
/*
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: mtd_blkdevs.c,v 1.26 2005/07/29 19:42:04 tpoynor Exp $
|
||||
* $Id: mtd_blkdevs.c,v 1.27 2005/11/07 11:14:20 gleixner Exp $
|
||||
*
|
||||
* (C) 2003 David Woodhouse <dwmw2@infradead.org>
|
||||
*
|
||||
@ -85,7 +85,7 @@ static int mtd_blktrans_thread(void *arg)
|
||||
daemonize("%sd", tr->name);
|
||||
|
||||
/* daemonize() doesn't do this for us since some kernel threads
|
||||
actually want to deal with signals. We can't just call
|
||||
actually want to deal with signals. We can't just call
|
||||
exit_sighand() since that'll cause an oops when we finally
|
||||
do exit. */
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
@ -94,7 +94,7 @@ static int mtd_blktrans_thread(void *arg)
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
|
||||
spin_lock_irq(rq->queue_lock);
|
||||
|
||||
|
||||
while (!tr->blkcore_priv->exiting) {
|
||||
struct request *req;
|
||||
struct mtd_blktrans_dev *dev;
|
||||
@ -157,7 +157,7 @@ static int blktrans_open(struct inode *i, struct file *f)
|
||||
if (!try_module_get(tr->owner))
|
||||
goto out_tr;
|
||||
|
||||
/* FIXME: Locking. A hot pluggable device can go away
|
||||
/* FIXME: Locking. A hot pluggable device can go away
|
||||
(del_mtd_device can be called for it) without its module
|
||||
being unloaded. */
|
||||
dev->mtd->usecount++;
|
||||
@ -195,7 +195,7 @@ static int blktrans_release(struct inode *i, struct file *f)
|
||||
}
|
||||
|
||||
|
||||
static int blktrans_ioctl(struct inode *inode, struct file *file,
|
||||
static int blktrans_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct mtd_blktrans_dev *dev = inode->i_bdev->bd_disk->private_data;
|
||||
@ -264,7 +264,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
|
||||
/* Required number was free */
|
||||
list_add_tail(&new->list, &d->list);
|
||||
goto added;
|
||||
}
|
||||
}
|
||||
last_devnum = d->devnum;
|
||||
}
|
||||
if (new->devnum == -1)
|
||||
@ -288,7 +288,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
|
||||
gd->major = tr->major;
|
||||
gd->first_minor = (new->devnum) << tr->part_bits;
|
||||
gd->fops = &mtd_blktrans_ops;
|
||||
|
||||
|
||||
if (tr->part_bits)
|
||||
if (new->devnum < 26)
|
||||
snprintf(gd->disk_name, sizeof(gd->disk_name),
|
||||
@ -314,7 +314,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
|
||||
set_disk_ro(gd, 1);
|
||||
|
||||
add_disk(gd);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -329,7 +329,7 @@ int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old)
|
||||
|
||||
del_gendisk(old->blkcore_priv);
|
||||
put_disk(old->blkcore_priv);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -368,12 +368,12 @@ static struct mtd_notifier blktrans_notifier = {
|
||||
.add = blktrans_notify_add,
|
||||
.remove = blktrans_notify_remove,
|
||||
};
|
||||
|
||||
|
||||
int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
/* Register the notifier if/when the first device type is
|
||||
/* Register the notifier if/when the first device type is
|
||||
registered, to prevent the link/init ordering from fucking
|
||||
us over. */
|
||||
if (!blktrans_notifier.list.next)
|
||||
@ -416,7 +416,7 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
|
||||
kfree(tr->blkcore_priv);
|
||||
up(&mtd_table_mutex);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&tr->devs);
|
||||
list_add(&tr->list, &blktrans_majors);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
/*
|
||||
* Direct MTD block device access
|
||||
*
|
||||
* $Id: mtdblock.c,v 1.67 2005/11/06 10:04:37 gleixner Exp $
|
||||
* $Id: mtdblock.c,v 1.68 2005/11/07 11:14:20 gleixner Exp $
|
||||
*
|
||||
* (C) 2000-2003 Nicolas Pitre <nico@cam.org>
|
||||
* (C) 1999-2003 David Woodhouse <dwmw2@infradead.org>
|
||||
@ -32,7 +32,7 @@ static struct mtdblk_dev {
|
||||
|
||||
/*
|
||||
* Cache stuff...
|
||||
*
|
||||
*
|
||||
* Since typical flash erasable sectors are much larger than what Linux's
|
||||
* buffer cache can handle, we must implement read-modify-write on flash
|
||||
* sectors for each block write requests. To avoid over-erasing flash sectors
|
||||
@ -46,7 +46,7 @@ static void erase_callback(struct erase_info *done)
|
||||
wake_up(wait_q);
|
||||
}
|
||||
|
||||
static int erase_write (struct mtd_info *mtd, unsigned long pos,
|
||||
static int erase_write (struct mtd_info *mtd, unsigned long pos,
|
||||
int len, const char *buf)
|
||||
{
|
||||
struct erase_info erase;
|
||||
@ -104,18 +104,18 @@ static int write_cached_data (struct mtdblk_dev *mtdblk)
|
||||
return 0;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: writing cached data for \"%s\" "
|
||||
"at 0x%lx, size 0x%x\n", mtd->name,
|
||||
"at 0x%lx, size 0x%x\n", mtd->name,
|
||||
mtdblk->cache_offset, mtdblk->cache_size);
|
||||
|
||||
ret = erase_write (mtd, mtdblk->cache_offset,
|
||||
|
||||
ret = erase_write (mtd, mtdblk->cache_offset,
|
||||
mtdblk->cache_size, mtdblk->cache_data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Here we could argubly set the cache state to STATE_CLEAN.
|
||||
* However this could lead to inconsistency since we will not
|
||||
* be notified if this content is altered on the flash by other
|
||||
* However this could lead to inconsistency since we will not
|
||||
* be notified if this content is altered on the flash by other
|
||||
* means. Let's declare it empty and leave buffering tasks to
|
||||
* the buffer cache instead.
|
||||
*/
|
||||
@ -124,7 +124,7 @@ static int write_cached_data (struct mtdblk_dev *mtdblk)
|
||||
}
|
||||
|
||||
|
||||
static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos,
|
||||
static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos,
|
||||
int len, const char *buf)
|
||||
{
|
||||
struct mtd_info *mtd = mtdblk->mtd;
|
||||
@ -134,7 +134,7 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos,
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: write on \"%s\" at 0x%lx, size 0x%x\n",
|
||||
mtd->name, pos, len);
|
||||
|
||||
|
||||
if (!sect_size)
|
||||
return MTD_WRITE (mtd, pos, len, &retlen, buf);
|
||||
|
||||
@ -142,11 +142,11 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos,
|
||||
unsigned long sect_start = (pos/sect_size)*sect_size;
|
||||
unsigned int offset = pos - sect_start;
|
||||
unsigned int size = sect_size - offset;
|
||||
if( size > len )
|
||||
if( size > len )
|
||||
size = len;
|
||||
|
||||
if (size == sect_size) {
|
||||
/*
|
||||
/*
|
||||
* We are covering a whole sector. Thus there is no
|
||||
* need to bother with the cache while it may still be
|
||||
* useful for other partial writes.
|
||||
@ -160,7 +160,7 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos,
|
||||
if (mtdblk->cache_state == STATE_DIRTY &&
|
||||
mtdblk->cache_offset != sect_start) {
|
||||
ret = write_cached_data(mtdblk);
|
||||
if (ret)
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -193,7 +193,7 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos,
|
||||
}
|
||||
|
||||
|
||||
static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos,
|
||||
static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos,
|
||||
int len, char *buf)
|
||||
{
|
||||
struct mtd_info *mtd = mtdblk->mtd;
|
||||
@ -201,9 +201,9 @@ static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos,
|
||||
size_t retlen;
|
||||
int ret;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: read on \"%s\" at 0x%lx, size 0x%x\n",
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: read on \"%s\" at 0x%lx, size 0x%x\n",
|
||||
mtd->name, pos, len);
|
||||
|
||||
|
||||
if (!sect_size)
|
||||
return MTD_READ (mtd, pos, len, &retlen, buf);
|
||||
|
||||
@ -211,7 +211,7 @@ static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos,
|
||||
unsigned long sect_start = (pos/sect_size)*sect_size;
|
||||
unsigned int offset = pos - sect_start;
|
||||
unsigned int size = sect_size - offset;
|
||||
if (size > len)
|
||||
if (size > len)
|
||||
size = len;
|
||||
|
||||
/*
|
||||
@ -269,12 +269,12 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd)
|
||||
int dev = mbd->devnum;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n");
|
||||
|
||||
|
||||
if (mtdblks[dev]) {
|
||||
mtdblks[dev]->count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* OK, it's not open. Create cache info for it */
|
||||
mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);
|
||||
if (!mtdblk)
|
||||
@ -293,7 +293,7 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd)
|
||||
}
|
||||
|
||||
mtdblks[dev] = mtdblk;
|
||||
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL1, "ok\n");
|
||||
|
||||
return 0;
|
||||
@ -321,7 +321,7 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd)
|
||||
DEBUG(MTD_DEBUG_LEVEL1, "ok\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int mtdblock_flush(struct mtd_blktrans_dev *dev)
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: mtdchar.c,v 1.75 2005/11/06 10:04:37 gleixner Exp $
|
||||
* $Id: mtdchar.c,v 1.76 2005/11/07 11:14:20 gleixner Exp $
|
||||
*
|
||||
* Character-device access to raw MTD devices.
|
||||
*
|
||||
@ -28,7 +28,7 @@ static void mtd_notify_add(struct mtd_info* mtd)
|
||||
|
||||
class_device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
|
||||
NULL, "mtd%d", mtd->index);
|
||||
|
||||
|
||||
class_device_create(mtd_class, NULL,
|
||||
MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
|
||||
NULL, "mtd%dro", mtd->index);
|
||||
@ -108,23 +108,23 @@ static int mtd_open(struct inode *inode, struct file *file)
|
||||
return -EACCES;
|
||||
|
||||
mtd = get_mtd_device(NULL, devnum);
|
||||
|
||||
|
||||
if (!mtd)
|
||||
return -ENODEV;
|
||||
|
||||
|
||||
if (MTD_ABSENT == mtd->type) {
|
||||
put_mtd_device(mtd);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
file->private_data = mtd;
|
||||
|
||||
|
||||
/* You can't open it RW if it's not a writeable device */
|
||||
if ((file->f_mode & 2) && !(mtd->flags & MTD_WRITEABLE)) {
|
||||
put_mtd_device(mtd);
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
} /* mtd_open */
|
||||
|
||||
@ -137,10 +137,10 @@ static int mtd_close(struct inode *inode, struct file *file)
|
||||
DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n");
|
||||
|
||||
mtd = TO_MTD(file);
|
||||
|
||||
|
||||
if (mtd->sync)
|
||||
mtd->sync(mtd);
|
||||
|
||||
|
||||
put_mtd_device(mtd);
|
||||
|
||||
return 0;
|
||||
@ -159,7 +159,7 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t
|
||||
int ret=0;
|
||||
int len;
|
||||
char *kbuf;
|
||||
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL0,"MTD_read\n");
|
||||
|
||||
if (*ppos + count > mtd->size)
|
||||
@ -167,11 +167,11 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t
|
||||
|
||||
if (!count)
|
||||
return 0;
|
||||
|
||||
|
||||
/* FIXME: Use kiovec in 2.5 to lock down the user's buffers
|
||||
and pass them directly to the MTD functions */
|
||||
while (count) {
|
||||
if (count > MAX_KMALLOC_SIZE)
|
||||
if (count > MAX_KMALLOC_SIZE)
|
||||
len = MAX_KMALLOC_SIZE;
|
||||
else
|
||||
len = count;
|
||||
@ -179,7 +179,7 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t
|
||||
kbuf=kmalloc(len,GFP_KERNEL);
|
||||
if (!kbuf)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
switch (MTD_MODE(file)) {
|
||||
case MTD_MODE_OTP_FACT:
|
||||
ret = mtd->read_fact_prot_reg(mtd, *ppos, len, &retlen, kbuf);
|
||||
@ -192,7 +192,7 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t
|
||||
}
|
||||
/* Nand returns -EBADMSG on ecc errors, but it returns
|
||||
* the data. For our userspace tools it is important
|
||||
* to dump areas with ecc errors !
|
||||
* to dump areas with ecc errors !
|
||||
* Userspace software which accesses NAND this way
|
||||
* must be aware of the fact that it deals with NAND
|
||||
*/
|
||||
@ -214,7 +214,7 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t
|
||||
kfree(kbuf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
kfree(kbuf);
|
||||
}
|
||||
|
||||
@ -231,10 +231,10 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count
|
||||
int len;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL0,"MTD_write\n");
|
||||
|
||||
|
||||
if (*ppos == mtd->size)
|
||||
return -ENOSPC;
|
||||
|
||||
|
||||
if (*ppos + count > mtd->size)
|
||||
count = mtd->size - *ppos;
|
||||
|
||||
@ -242,7 +242,7 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count
|
||||
return 0;
|
||||
|
||||
while (count) {
|
||||
if (count > MAX_KMALLOC_SIZE)
|
||||
if (count > MAX_KMALLOC_SIZE)
|
||||
len = MAX_KMALLOC_SIZE;
|
||||
else
|
||||
len = count;
|
||||
@ -257,7 +257,7 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count
|
||||
kfree(kbuf);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
|
||||
switch (MTD_MODE(file)) {
|
||||
case MTD_MODE_OTP_FACT:
|
||||
ret = -EROFS;
|
||||
@ -282,7 +282,7 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count
|
||||
kfree(kbuf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
kfree(kbuf);
|
||||
}
|
||||
|
||||
@ -306,7 +306,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
|
||||
void __user *argp = (void __user *)arg;
|
||||
int ret = 0;
|
||||
u_long size;
|
||||
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL0, "MTD_ioctl\n");
|
||||
|
||||
size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
|
||||
@ -318,7 +318,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
|
||||
if (!access_ok(VERIFY_WRITE, argp, size))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
|
||||
switch (cmd) {
|
||||
case MEMGETREGIONCOUNT:
|
||||
if (copy_to_user(argp, &(mtd->numeraseregions), sizeof(int)))
|
||||
@ -370,11 +370,11 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
|
||||
erase->mtd = mtd;
|
||||
erase->callback = mtdchar_erase_callback;
|
||||
erase->priv = (unsigned long)&waitq;
|
||||
|
||||
|
||||
/*
|
||||
FIXME: Allow INTERRUPTIBLE. Which means
|
||||
not having the wait_queue head on the stack.
|
||||
|
||||
|
||||
If the wq_head is on the stack, and we
|
||||
leave because we got interrupted, then the
|
||||
wq_head is no longer there when the
|
||||
@ -402,13 +402,13 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
|
||||
struct mtd_oob_buf buf;
|
||||
void *databuf;
|
||||
ssize_t retlen;
|
||||
|
||||
|
||||
if(!(file->f_mode & 2))
|
||||
return -EPERM;
|
||||
|
||||
if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf)))
|
||||
return -EFAULT;
|
||||
|
||||
|
||||
if (buf.length > 0x4096)
|
||||
return -EINVAL;
|
||||
|
||||
@ -424,7 +424,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
|
||||
databuf = kmalloc(buf.length, GFP_KERNEL);
|
||||
if (!databuf)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
if (copy_from_user(databuf, buf.ptr, buf.length)) {
|
||||
kfree(databuf);
|
||||
return -EFAULT;
|
||||
@ -448,7 +448,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
|
||||
|
||||
if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf)))
|
||||
return -EFAULT;
|
||||
|
||||
|
||||
if (buf.length > 0x4096)
|
||||
return -EINVAL;
|
||||
|
||||
@ -464,14 +464,14 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
|
||||
databuf = kmalloc(buf.length, GFP_KERNEL);
|
||||
if (!databuf)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
ret = (mtd->read_oob)(mtd, buf.start, buf.length, &retlen, databuf);
|
||||
|
||||
if (put_user(retlen, (uint32_t __user *)argp))
|
||||
ret = -EFAULT;
|
||||
else if (retlen && copy_to_user(buf.ptr, databuf, retlen))
|
||||
ret = -EFAULT;
|
||||
|
||||
|
||||
kfree(databuf);
|
||||
break;
|
||||
}
|
||||
@ -521,7 +521,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
|
||||
case MEMGETBADBLOCK:
|
||||
{
|
||||
loff_t offs;
|
||||
|
||||
|
||||
if (copy_from_user(&offs, argp, sizeof(loff_t)))
|
||||
return -EFAULT;
|
||||
if (!mtd->block_isbad)
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
* This code is GPL
|
||||
*
|
||||
* $Id: mtdconcat.c,v 1.10 2005/11/06 10:04:37 gleixner Exp $
|
||||
* $Id: mtdconcat.c,v 1.11 2005/11/07 11:14:20 gleixner Exp $
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
@ -44,7 +44,7 @@ struct mtd_concat {
|
||||
*/
|
||||
#define CONCAT(x) ((struct mtd_concat *)(x))
|
||||
|
||||
/*
|
||||
/*
|
||||
* MTD methods which look up the relevant subdevice, translate the
|
||||
* effective address and pass through to the subdevice.
|
||||
*/
|
||||
@ -878,7 +878,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
|
||||
return &concat->mtd;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* This function destroys an MTD object obtained from concat_mtd_devs()
|
||||
*/
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: mtdcore.c,v 1.46 2005/08/11 17:13:43 gleixner Exp $
|
||||
* $Id: mtdcore.c,v 1.47 2005/11/07 11:14:20 gleixner Exp $
|
||||
*
|
||||
* Core registration and callback routines for MTD
|
||||
* drivers and users.
|
||||
@ -25,7 +25,7 @@
|
||||
|
||||
#include <linux/mtd/mtd.h>
|
||||
|
||||
/* These are exported solely for the purpose of mtd_blkdevs.c. You
|
||||
/* These are exported solely for the purpose of mtd_blkdevs.c. You
|
||||
should not use them for _anything_ else */
|
||||
DECLARE_MUTEX(mtd_table_mutex);
|
||||
struct mtd_info *mtd_table[MAX_MTD_DEVICES];
|
||||
@ -66,7 +66,7 @@ int add_mtd_device(struct mtd_info *mtd)
|
||||
struct mtd_notifier *not = list_entry(this, struct mtd_notifier, list);
|
||||
not->add(mtd);
|
||||
}
|
||||
|
||||
|
||||
up(&mtd_table_mutex);
|
||||
/* We _know_ we aren't being removed, because
|
||||
our caller is still holding us here. So none
|
||||
@ -75,7 +75,7 @@ int add_mtd_device(struct mtd_info *mtd)
|
||||
__module_get(THIS_MODULE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
up(&mtd_table_mutex);
|
||||
return 1;
|
||||
}
|
||||
@ -93,13 +93,13 @@ int add_mtd_device(struct mtd_info *mtd)
|
||||
int del_mtd_device (struct mtd_info *mtd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
||||
down(&mtd_table_mutex);
|
||||
|
||||
if (mtd_table[mtd->index] != mtd) {
|
||||
ret = -ENODEV;
|
||||
} else if (mtd->usecount) {
|
||||
printk(KERN_NOTICE "Removing MTD device #%d (%s) with use count %d\n",
|
||||
printk(KERN_NOTICE "Removing MTD device #%d (%s) with use count %d\n",
|
||||
mtd->index, mtd->name, mtd->usecount);
|
||||
ret = -EBUSY;
|
||||
} else {
|
||||
@ -140,7 +140,7 @@ void register_mtd_user (struct mtd_notifier *new)
|
||||
list_add(&new->list, &mtd_notifiers);
|
||||
|
||||
__module_get(THIS_MODULE);
|
||||
|
||||
|
||||
for (i=0; i< MAX_MTD_DEVICES; i++)
|
||||
if (mtd_table[i])
|
||||
new->add(mtd_table[i]);
|
||||
@ -169,7 +169,7 @@ int unregister_mtd_user (struct mtd_notifier *old)
|
||||
for (i=0; i< MAX_MTD_DEVICES; i++)
|
||||
if (mtd_table[i])
|
||||
old->remove(mtd_table[i]);
|
||||
|
||||
|
||||
list_del(&old->list);
|
||||
up(&mtd_table_mutex);
|
||||
return 0;
|
||||
@ -187,7 +187,7 @@ int unregister_mtd_user (struct mtd_notifier *old)
|
||||
* both, return the num'th driver only if its address matches. Return NULL
|
||||
* if not.
|
||||
*/
|
||||
|
||||
|
||||
struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
|
||||
{
|
||||
struct mtd_info *ret = NULL;
|
||||
|
@ -5,11 +5,11 @@
|
||||
*
|
||||
* This code is GPL
|
||||
*
|
||||
* $Id: mtdpart.c,v 1.54 2005/09/30 14:49:08 dedekind Exp $
|
||||
* $Id: mtdpart.c,v 1.55 2005/11/07 11:14:20 gleixner Exp $
|
||||
*
|
||||
* 02-21-2002 Thomas Gleixner <gleixner@autronix.de>
|
||||
* added support for read_oob, write_oob
|
||||
*/
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
@ -41,13 +41,13 @@ struct mtd_part {
|
||||
*/
|
||||
#define PART(x) ((struct mtd_part *)(x))
|
||||
|
||||
|
||||
/*
|
||||
|
||||
/*
|
||||
* MTD methods which simply translate the effective address and pass through
|
||||
* to the _real_ device.
|
||||
*/
|
||||
|
||||
static int part_read (struct mtd_info *mtd, loff_t from, size_t len,
|
||||
static int part_read (struct mtd_info *mtd, loff_t from, size_t len,
|
||||
size_t *retlen, u_char *buf)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
@ -55,15 +55,15 @@ static int part_read (struct mtd_info *mtd, loff_t from, size_t len,
|
||||
len = 0;
|
||||
else if (from + len > mtd->size)
|
||||
len = mtd->size - from;
|
||||
if (part->master->read_ecc == NULL)
|
||||
return part->master->read (part->master, from + part->offset,
|
||||
if (part->master->read_ecc == NULL)
|
||||
return part->master->read (part->master, from + part->offset,
|
||||
len, retlen, buf);
|
||||
else
|
||||
return part->master->read_ecc (part->master, from + part->offset,
|
||||
return part->master->read_ecc (part->master, from + part->offset,
|
||||
len, retlen, buf, NULL, &mtd->oobinfo);
|
||||
}
|
||||
|
||||
static int part_point (struct mtd_info *mtd, loff_t from, size_t len,
|
||||
static int part_point (struct mtd_info *mtd, loff_t from, size_t len,
|
||||
size_t *retlen, u_char **buf)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
@ -71,7 +71,7 @@ static int part_point (struct mtd_info *mtd, loff_t from, size_t len,
|
||||
len = 0;
|
||||
else if (from + len > mtd->size)
|
||||
len = mtd->size - from;
|
||||
return part->master->point (part->master, from + part->offset,
|
||||
return part->master->point (part->master, from + part->offset,
|
||||
len, retlen, buf);
|
||||
}
|
||||
static void part_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len)
|
||||
@ -82,7 +82,7 @@ static void part_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_
|
||||
}
|
||||
|
||||
|
||||
static int part_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
|
||||
static int part_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
|
||||
size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
@ -92,11 +92,11 @@ static int part_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
|
||||
len = 0;
|
||||
else if (from + len > mtd->size)
|
||||
len = mtd->size - from;
|
||||
return part->master->read_ecc (part->master, from + part->offset,
|
||||
return part->master->read_ecc (part->master, from + part->offset,
|
||||
len, retlen, buf, eccbuf, oobsel);
|
||||
}
|
||||
|
||||
static int part_read_oob (struct mtd_info *mtd, loff_t from, size_t len,
|
||||
static int part_read_oob (struct mtd_info *mtd, loff_t from, size_t len,
|
||||
size_t *retlen, u_char *buf)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
@ -104,15 +104,15 @@ static int part_read_oob (struct mtd_info *mtd, loff_t from, size_t len,
|
||||
len = 0;
|
||||
else if (from + len > mtd->size)
|
||||
len = mtd->size - from;
|
||||
return part->master->read_oob (part->master, from + part->offset,
|
||||
return part->master->read_oob (part->master, from + part->offset,
|
||||
len, retlen, buf);
|
||||
}
|
||||
|
||||
static int part_read_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len,
|
||||
static int part_read_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len,
|
||||
size_t *retlen, u_char *buf)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
return part->master->read_user_prot_reg (part->master, from,
|
||||
return part->master->read_user_prot_reg (part->master, from,
|
||||
len, retlen, buf);
|
||||
}
|
||||
|
||||
@ -123,11 +123,11 @@ static int part_get_user_prot_info (struct mtd_info *mtd,
|
||||
return part->master->get_user_prot_info (part->master, buf, len);
|
||||
}
|
||||
|
||||
static int part_read_fact_prot_reg (struct mtd_info *mtd, loff_t from, size_t len,
|
||||
static int part_read_fact_prot_reg (struct mtd_info *mtd, loff_t from, size_t len,
|
||||
size_t *retlen, u_char *buf)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
return part->master->read_fact_prot_reg (part->master, from,
|
||||
return part->master->read_fact_prot_reg (part->master, from,
|
||||
len, retlen, buf);
|
||||
}
|
||||
|
||||
@ -148,13 +148,13 @@ static int part_write (struct mtd_info *mtd, loff_t to, size_t len,
|
||||
len = 0;
|
||||
else if (to + len > mtd->size)
|
||||
len = mtd->size - to;
|
||||
if (part->master->write_ecc == NULL)
|
||||
return part->master->write (part->master, to + part->offset,
|
||||
if (part->master->write_ecc == NULL)
|
||||
return part->master->write (part->master, to + part->offset,
|
||||
len, retlen, buf);
|
||||
else
|
||||
return part->master->write_ecc (part->master, to + part->offset,
|
||||
return part->master->write_ecc (part->master, to + part->offset,
|
||||
len, retlen, buf, NULL, &mtd->oobinfo);
|
||||
|
||||
|
||||
}
|
||||
|
||||
static int part_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
|
||||
@ -170,7 +170,7 @@ static int part_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
|
||||
len = 0;
|
||||
else if (to + len > mtd->size)
|
||||
len = mtd->size - to;
|
||||
return part->master->write_ecc (part->master, to + part->offset,
|
||||
return part->master->write_ecc (part->master, to + part->offset,
|
||||
len, retlen, buf, eccbuf, oobsel);
|
||||
}
|
||||
|
||||
@ -184,19 +184,19 @@ static int part_write_oob (struct mtd_info *mtd, loff_t to, size_t len,
|
||||
len = 0;
|
||||
else if (to + len > mtd->size)
|
||||
len = mtd->size - to;
|
||||
return part->master->write_oob (part->master, to + part->offset,
|
||||
return part->master->write_oob (part->master, to + part->offset,
|
||||
len, retlen, buf);
|
||||
}
|
||||
|
||||
static int part_write_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len,
|
||||
static int part_write_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len,
|
||||
size_t *retlen, u_char *buf)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
return part->master->write_user_prot_reg (part->master, from,
|
||||
return part->master->write_user_prot_reg (part->master, from,
|
||||
len, retlen, buf);
|
||||
}
|
||||
|
||||
static int part_lock_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len)
|
||||
static int part_lock_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
return part->master->lock_user_prot_reg (part->master, from, len);
|
||||
@ -208,7 +208,7 @@ static int part_writev (struct mtd_info *mtd, const struct kvec *vecs,
|
||||
struct mtd_part *part = PART(mtd);
|
||||
if (!(mtd->flags & MTD_WRITEABLE))
|
||||
return -EROFS;
|
||||
if (part->master->writev_ecc == NULL)
|
||||
if (part->master->writev_ecc == NULL)
|
||||
return part->master->writev (part->master, vecs, count,
|
||||
to + part->offset, retlen);
|
||||
else
|
||||
@ -221,12 +221,12 @@ static int part_readv (struct mtd_info *mtd, struct kvec *vecs,
|
||||
unsigned long count, loff_t from, size_t *retlen)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
if (part->master->readv_ecc == NULL)
|
||||
if (part->master->readv_ecc == NULL)
|
||||
return part->master->readv (part->master, vecs, count,
|
||||
from + part->offset, retlen);
|
||||
else
|
||||
return part->master->readv_ecc (part->master, vecs, count,
|
||||
from + part->offset, retlen,
|
||||
from + part->offset, retlen,
|
||||
NULL, &mtd->oobinfo);
|
||||
}
|
||||
|
||||
@ -252,7 +252,7 @@ static int part_readv_ecc (struct mtd_info *mtd, struct kvec *vecs,
|
||||
if (oobsel == NULL)
|
||||
oobsel = &mtd->oobinfo;
|
||||
return part->master->readv_ecc (part->master, vecs, count,
|
||||
from + part->offset, retlen,
|
||||
from + part->offset, retlen,
|
||||
eccbuf, oobsel);
|
||||
}
|
||||
|
||||
@ -286,7 +286,7 @@ EXPORT_SYMBOL_GPL(mtd_erase_callback);
|
||||
static int part_lock (struct mtd_info *mtd, loff_t ofs, size_t len)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
if ((len + ofs) > mtd->size)
|
||||
if ((len + ofs) > mtd->size)
|
||||
return -EINVAL;
|
||||
return part->master->lock(part->master, ofs + part->offset, len);
|
||||
}
|
||||
@ -294,7 +294,7 @@ static int part_lock (struct mtd_info *mtd, loff_t ofs, size_t len)
|
||||
static int part_unlock (struct mtd_info *mtd, loff_t ofs, size_t len)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
if ((len + ofs) > mtd->size)
|
||||
if ((len + ofs) > mtd->size)
|
||||
return -EINVAL;
|
||||
return part->master->unlock(part->master, ofs + part->offset, len);
|
||||
}
|
||||
@ -337,8 +337,8 @@ static int part_block_markbad (struct mtd_info *mtd, loff_t ofs)
|
||||
return part->master->block_markbad(part->master, ofs);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function unregisters and destroy all slave MTD objects which are
|
||||
/*
|
||||
* This function unregisters and destroy all slave MTD objects which are
|
||||
* attached to the given master MTD object.
|
||||
*/
|
||||
|
||||
@ -371,7 +371,7 @@ int del_mtd_partitions(struct mtd_info *master)
|
||||
* (Q: should we register the master MTD object as well?)
|
||||
*/
|
||||
|
||||
int add_mtd_partitions(struct mtd_info *master,
|
||||
int add_mtd_partitions(struct mtd_info *master,
|
||||
const struct mtd_partition *parts,
|
||||
int nbparts)
|
||||
{
|
||||
@ -414,7 +414,7 @@ int add_mtd_partitions(struct mtd_info *master,
|
||||
slave->mtd.point = part_point;
|
||||
slave->mtd.unpoint = part_unpoint;
|
||||
}
|
||||
|
||||
|
||||
if (master->read_ecc)
|
||||
slave->mtd.read_ecc = part_read_ecc;
|
||||
if (master->write_ecc)
|
||||
@ -477,8 +477,8 @@ int add_mtd_partitions(struct mtd_info *master,
|
||||
if (slave->mtd.size == MTDPART_SIZ_FULL)
|
||||
slave->mtd.size = master->size - slave->offset;
|
||||
cur_offset = slave->offset + slave->mtd.size;
|
||||
|
||||
printk (KERN_NOTICE "0x%08x-0x%08x : \"%s\"\n", slave->offset,
|
||||
|
||||
printk (KERN_NOTICE "0x%08x-0x%08x : \"%s\"\n", slave->offset,
|
||||
slave->offset + slave->mtd.size, slave->mtd.name);
|
||||
|
||||
/* let's do some sanity checks */
|
||||
@ -498,7 +498,7 @@ int add_mtd_partitions(struct mtd_info *master,
|
||||
/* Deal with variable erase size stuff */
|
||||
int i;
|
||||
struct mtd_erase_region_info *regions = master->eraseregions;
|
||||
|
||||
|
||||
/* Find the first erase regions which is part of this partition. */
|
||||
for (i=0; i < master->numeraseregions && slave->offset >= regions[i].offset; i++)
|
||||
;
|
||||
@ -513,7 +513,7 @@ int add_mtd_partitions(struct mtd_info *master,
|
||||
slave->mtd.erasesize = master->erasesize;
|
||||
}
|
||||
|
||||
if ((slave->mtd.flags & MTD_WRITEABLE) &&
|
||||
if ((slave->mtd.flags & MTD_WRITEABLE) &&
|
||||
(slave->offset % slave->mtd.erasesize)) {
|
||||
/* Doesn't start on a boundary of major erase size */
|
||||
/* FIXME: Let it be writable if it is on a boundary of _minor_ erase size though */
|
||||
@ -521,14 +521,14 @@ int add_mtd_partitions(struct mtd_info *master,
|
||||
printk ("mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",
|
||||
parts[i].name);
|
||||
}
|
||||
if ((slave->mtd.flags & MTD_WRITEABLE) &&
|
||||
if ((slave->mtd.flags & MTD_WRITEABLE) &&
|
||||
(slave->mtd.size % slave->mtd.erasesize)) {
|
||||
slave->mtd.flags &= ~MTD_WRITEABLE;
|
||||
printk ("mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",
|
||||
parts[i].name);
|
||||
}
|
||||
|
||||
/* copy oobinfo from master */
|
||||
/* copy oobinfo from master */
|
||||
memcpy(&slave->mtd.oobinfo, &master->oobinfo, sizeof(slave->mtd.oobinfo));
|
||||
|
||||
if(parts[i].mtdp)
|
||||
@ -589,12 +589,12 @@ int deregister_mtd_parser(struct mtd_part_parser *p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_mtd_partitions(struct mtd_info *master, const char **types,
|
||||
int parse_mtd_partitions(struct mtd_info *master, const char **types,
|
||||
struct mtd_partition **pparts, unsigned long origin)
|
||||
{
|
||||
struct mtd_part_parser *parser;
|
||||
int ret = 0;
|
||||
|
||||
|
||||
for ( ; ret <= 0 && *types; types++) {
|
||||
parser = get_partition_parser(*types);
|
||||
#ifdef CONFIG_KMOD
|
||||
@ -608,7 +608,7 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types,
|
||||
}
|
||||
ret = (*parser->parse_fn)(master, pparts, origin);
|
||||
if (ret > 0) {
|
||||
printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n",
|
||||
printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n",
|
||||
ret, parser->name, master->name);
|
||||
}
|
||||
put_partition_parser(parser);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* Linux driver for NAND Flash Translation Layer */
|
||||
/* (c) 1999 Machine Vision Holdings, Inc. */
|
||||
/* Author: David Woodhouse <dwmw2@infradead.org> */
|
||||
/* $Id: nftlcore.c,v 1.97 2004/11/16 18:28:59 dwmw2 Exp $ */
|
||||
/* $Id: nftlcore.c,v 1.98 2005/11/07 11:14:21 gleixner Exp $ */
|
||||
|
||||
/*
|
||||
The contents of this file are distributed under the GNU General
|
||||
@ -101,14 +101,14 @@ static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
|
||||
|
||||
if (nftl->mbd.size != nftl->heads * nftl->cylinders * nftl->sectors) {
|
||||
/*
|
||||
Oh no we don't have
|
||||
Oh no we don't have
|
||||
mbd.size == heads * cylinders * sectors
|
||||
*/
|
||||
printk(KERN_WARNING "NFTL: cannot calculate a geometry to "
|
||||
"match size of 0x%lx.\n", nftl->mbd.size);
|
||||
printk(KERN_WARNING "NFTL: using C:%d H:%d S:%d "
|
||||
"(== 0x%lx sects)\n",
|
||||
nftl->cylinders, nftl->heads , nftl->sectors,
|
||||
nftl->cylinders, nftl->heads , nftl->sectors,
|
||||
(long)nftl->cylinders * (long)nftl->heads *
|
||||
(long)nftl->sectors );
|
||||
}
|
||||
@ -178,7 +178,7 @@ static u16 NFTL_findfreeblock(struct NFTLrecord *nftl, int desperate )
|
||||
|
||||
if (!silly--) {
|
||||
printk("Argh! No free blocks found! LastFreeEUN = %d, "
|
||||
"FirstEUN = %d\n", nftl->LastFreeEUN,
|
||||
"FirstEUN = %d\n", nftl->LastFreeEUN,
|
||||
le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN));
|
||||
return 0xffff;
|
||||
}
|
||||
@ -210,7 +210,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
|
||||
"Virtual Unit Chain %d!\n", thisVUC);
|
||||
return BLOCK_NIL;
|
||||
}
|
||||
|
||||
|
||||
/* Scan to find the Erase Unit which holds the actual data for each
|
||||
512-byte block within the Chain.
|
||||
*/
|
||||
@ -227,7 +227,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
|
||||
if (block == 2) {
|
||||
foldmark = oob.u.c.FoldMark | oob.u.c.FoldMark1;
|
||||
if (foldmark == FOLD_MARK_IN_PROGRESS) {
|
||||
DEBUG(MTD_DEBUG_LEVEL1,
|
||||
DEBUG(MTD_DEBUG_LEVEL1,
|
||||
"Write Inhibited on EUN %d\n", thisEUN);
|
||||
inplace = 0;
|
||||
} else {
|
||||
@ -249,7 +249,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
|
||||
if (!BlockFreeFound[block])
|
||||
BlockMap[block] = thisEUN;
|
||||
else
|
||||
printk(KERN_WARNING
|
||||
printk(KERN_WARNING
|
||||
"SECTOR_USED found after SECTOR_FREE "
|
||||
"in Virtual Unit Chain %d for block %d\n",
|
||||
thisVUC, block);
|
||||
@ -258,7 +258,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
|
||||
if (!BlockFreeFound[block])
|
||||
BlockMap[block] = BLOCK_NIL;
|
||||
else
|
||||
printk(KERN_WARNING
|
||||
printk(KERN_WARNING
|
||||
"SECTOR_DELETED found after SECTOR_FREE "
|
||||
"in Virtual Unit Chain %d for block %d\n",
|
||||
thisVUC, block);
|
||||
@ -277,14 +277,14 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
|
||||
thisVUC);
|
||||
return BLOCK_NIL;
|
||||
}
|
||||
|
||||
|
||||
thisEUN = nftl->ReplUnitTable[thisEUN];
|
||||
}
|
||||
|
||||
if (inplace) {
|
||||
/* We're being asked to be a fold-in-place. Check
|
||||
that all blocks which actually have data associated
|
||||
with them (i.e. BlockMap[block] != BLOCK_NIL) are
|
||||
with them (i.e. BlockMap[block] != BLOCK_NIL) are
|
||||
either already present or SECTOR_FREE in the target
|
||||
block. If not, we're going to have to fold out-of-place
|
||||
anyway.
|
||||
@ -297,7 +297,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
|
||||
"block %d was %x lastEUN, "
|
||||
"and is in EUN %d (%s) %d\n",
|
||||
thisVUC, block, BlockLastState[block],
|
||||
BlockMap[block],
|
||||
BlockMap[block],
|
||||
BlockMap[block]== targetEUN ? "==" : "!=",
|
||||
targetEUN);
|
||||
inplace = 0;
|
||||
@ -314,17 +314,17 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
|
||||
inplace = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!inplace) {
|
||||
DEBUG(MTD_DEBUG_LEVEL1, "Cannot fold Virtual Unit Chain %d in place. "
|
||||
"Trying out-of-place\n", thisVUC);
|
||||
/* We need to find a targetEUN to fold into. */
|
||||
targetEUN = NFTL_findfreeblock(nftl, 1);
|
||||
if (targetEUN == BLOCK_NIL) {
|
||||
/* Ouch. Now we're screwed. We need to do a
|
||||
/* Ouch. Now we're screwed. We need to do a
|
||||
fold-in-place of another chain to make room
|
||||
for this one. We need a better way of selecting
|
||||
which chain to fold, because makefreeblock will
|
||||
which chain to fold, because makefreeblock will
|
||||
only ask us to fold the same one again.
|
||||
*/
|
||||
printk(KERN_WARNING
|
||||
@ -338,7 +338,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
|
||||
chain by selecting the longer one */
|
||||
oob.u.c.FoldMark = oob.u.c.FoldMark1 = cpu_to_le16(FOLD_MARK_IN_PROGRESS);
|
||||
oob.u.c.unused = 0xffffffff;
|
||||
MTD_WRITEOOB(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8,
|
||||
MTD_WRITEOOB(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8,
|
||||
8, &retlen, (char *)&oob.u);
|
||||
}
|
||||
|
||||
@ -361,14 +361,14 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
|
||||
happen in case of media errors or deleted blocks) */
|
||||
if (BlockMap[block] == BLOCK_NIL)
|
||||
continue;
|
||||
|
||||
|
||||
ret = MTD_READ(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512),
|
||||
512, &retlen, movebuf);
|
||||
512, &retlen, movebuf);
|
||||
if (ret < 0) {
|
||||
ret = MTD_READ(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block])
|
||||
+ (block * 512), 512, &retlen,
|
||||
movebuf);
|
||||
if (ret != -EIO)
|
||||
movebuf);
|
||||
if (ret != -EIO)
|
||||
printk("Error went away on retry.\n");
|
||||
}
|
||||
memset(&oob, 0xff, sizeof(struct nftl_oob));
|
||||
@ -376,18 +376,18 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
|
||||
MTD_WRITEECC(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + (block * 512),
|
||||
512, &retlen, movebuf, (char *)&oob, &nftl->oobinfo);
|
||||
}
|
||||
|
||||
|
||||
/* add the header so that it is now a valid chain */
|
||||
oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum
|
||||
= cpu_to_le16(thisVUC);
|
||||
oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff;
|
||||
|
||||
MTD_WRITEOOB(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 8,
|
||||
|
||||
MTD_WRITEOOB(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 8,
|
||||
8, &retlen, (char *)&oob.u);
|
||||
|
||||
/* OK. We've moved the whole lot into the new block. Now we have to free the original blocks. */
|
||||
|
||||
/* At this point, we have two different chains for this Virtual Unit, and no way to tell
|
||||
/* At this point, we have two different chains for this Virtual Unit, and no way to tell
|
||||
them apart. If we crash now, we get confused. However, both contain the same data, so we
|
||||
shouldn't actually lose data in this case. It's just that when we load up on a medium which
|
||||
has duplicate chains, we need to free one of the chains because it's not necessary any more.
|
||||
@ -395,7 +395,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
|
||||
thisEUN = nftl->EUNtable[thisVUC];
|
||||
DEBUG(MTD_DEBUG_LEVEL1,"Want to erase\n");
|
||||
|
||||
/* For each block in the old chain (except the targetEUN of course),
|
||||
/* For each block in the old chain (except the targetEUN of course),
|
||||
free it and make it available for future use */
|
||||
while (thisEUN <= nftl->lastEUN && thisEUN != targetEUN) {
|
||||
unsigned int EUNtmp;
|
||||
@ -413,7 +413,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
|
||||
}
|
||||
thisEUN = EUNtmp;
|
||||
}
|
||||
|
||||
|
||||
/* Make this the new start of chain for thisVUC */
|
||||
nftl->ReplUnitTable[targetEUN] = BLOCK_NIL;
|
||||
nftl->EUNtable[thisVUC] = targetEUN;
|
||||
@ -423,7 +423,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
|
||||
|
||||
static u16 NFTL_makefreeblock( struct NFTLrecord *nftl , unsigned pendingblock)
|
||||
{
|
||||
/* This is the part that needs some cleverness applied.
|
||||
/* This is the part that needs some cleverness applied.
|
||||
For now, I'm doing the minimum applicable to actually
|
||||
get the thing to work.
|
||||
Wear-levelling and other clever stuff needs to be implemented
|
||||
@ -470,7 +470,7 @@ static u16 NFTL_makefreeblock( struct NFTLrecord *nftl , unsigned pendingblock)
|
||||
return NFTL_foldchain (nftl, LongestChain, pendingblock);
|
||||
}
|
||||
|
||||
/* NFTL_findwriteunit: Return the unit number into which we can write
|
||||
/* NFTL_findwriteunit: Return the unit number into which we can write
|
||||
for this block. Make it available if it isn't already
|
||||
*/
|
||||
static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)
|
||||
@ -488,7 +488,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)
|
||||
a free space for the block in question.
|
||||
*/
|
||||
|
||||
/* This condition catches the 0x[7f]fff cases, as well as
|
||||
/* This condition catches the 0x[7f]fff cases, as well as
|
||||
being a sanity check for past-end-of-media access
|
||||
*/
|
||||
lastEUN = BLOCK_NIL;
|
||||
@ -503,7 +503,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)
|
||||
|
||||
MTD_READOOB(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs,
|
||||
8, &retlen, (char *)&bci);
|
||||
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "Status of block %d in EUN %d is %x\n",
|
||||
block , writeEUN, le16_to_cpu(bci.Status));
|
||||
|
||||
@ -518,10 +518,10 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)
|
||||
break;
|
||||
default:
|
||||
// Invalid block. Don't use it any more. Must implement.
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!silly--) {
|
||||
|
||||
if (!silly--) {
|
||||
printk(KERN_WARNING
|
||||
"Infinite loop in Virtual Unit Chain 0x%x\n",
|
||||
thisVUC);
|
||||
@ -532,7 +532,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)
|
||||
writeEUN = nftl->ReplUnitTable[writeEUN];
|
||||
}
|
||||
|
||||
/* OK. We didn't find one in the existing chain, or there
|
||||
/* OK. We didn't find one in the existing chain, or there
|
||||
is no existing chain. */
|
||||
|
||||
/* Try to find an already-free block */
|
||||
@ -546,12 +546,12 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)
|
||||
|
||||
/* First remember the start of this chain */
|
||||
//u16 startEUN = nftl->EUNtable[thisVUC];
|
||||
|
||||
|
||||
//printk("Write to VirtualUnitChain %d, calling makefreeblock()\n", thisVUC);
|
||||
writeEUN = NFTL_makefreeblock(nftl, 0xffff);
|
||||
|
||||
if (writeEUN == BLOCK_NIL) {
|
||||
/* OK, we accept that the above comment is
|
||||
/* OK, we accept that the above comment is
|
||||
lying - there may have been free blocks
|
||||
last time we called NFTL_findfreeblock(),
|
||||
but they are reserved for when we're
|
||||
@ -562,21 +562,21 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)
|
||||
}
|
||||
if (writeEUN == BLOCK_NIL) {
|
||||
/* Ouch. This should never happen - we should
|
||||
always be able to make some room somehow.
|
||||
If we get here, we've allocated more storage
|
||||
always be able to make some room somehow.
|
||||
If we get here, we've allocated more storage
|
||||
space than actual media, or our makefreeblock
|
||||
routine is missing something.
|
||||
*/
|
||||
printk(KERN_WARNING "Cannot make free space.\n");
|
||||
return BLOCK_NIL;
|
||||
}
|
||||
}
|
||||
//printk("Restarting scan\n");
|
||||
lastEUN = BLOCK_NIL;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We've found a free block. Insert it into the chain. */
|
||||
|
||||
|
||||
if (lastEUN != BLOCK_NIL) {
|
||||
thisVUC |= 0x8000; /* It's a replacement block */
|
||||
} else {
|
||||
@ -749,7 +749,7 @@ extern char nftlmountrev[];
|
||||
|
||||
static int __init init_nftl(void)
|
||||
{
|
||||
printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.97 $, nftlmount.c %s\n", nftlmountrev);
|
||||
printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.98 $, nftlmount.c %s\n", nftlmountrev);
|
||||
|
||||
return register_mtd_blktrans(&nftl_tr);
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
/*
|
||||
/*
|
||||
* NFTL mount code with extensive checks
|
||||
*
|
||||
* Author: Fabrice Bellard (fabrice.bellard@netgem.com)
|
||||
* Author: Fabrice Bellard (fabrice.bellard@netgem.com)
|
||||
* Copyright (C) 2000 Netgem S.A.
|
||||
*
|
||||
* $Id: nftlmount.c,v 1.40 2004/11/22 14:38:29 kalev Exp $
|
||||
* $Id: nftlmount.c,v 1.41 2005/11/07 11:14:21 gleixner Exp $
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -31,7 +31,7 @@
|
||||
|
||||
#define SECTORSIZE 512
|
||||
|
||||
char nftlmountrev[]="$Revision: 1.40 $";
|
||||
char nftlmountrev[]="$Revision: 1.41 $";
|
||||
|
||||
/* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the
|
||||
* various device information of the NFTL partition and Bad Unit Table. Update
|
||||
@ -47,7 +47,7 @@ static int find_boot_record(struct NFTLrecord *nftl)
|
||||
struct NFTLMediaHeader *mh = &nftl->MediaHdr;
|
||||
unsigned int i;
|
||||
|
||||
/* Assume logical EraseSize == physical erasesize for starting the scan.
|
||||
/* Assume logical EraseSize == physical erasesize for starting the scan.
|
||||
We'll sort it out later if we find a MediaHeader which says otherwise */
|
||||
/* Actually, we won't. The new DiskOnChip driver has already scanned
|
||||
the MediaHeader and adjusted the virtual erasesize it presents in
|
||||
@ -83,9 +83,9 @@ static int find_boot_record(struct NFTLrecord *nftl)
|
||||
if (retlen < 6 || memcmp(buf, "ANAND", 6)) {
|
||||
/* ANAND\0 not found. Continue */
|
||||
#if 0
|
||||
printk(KERN_DEBUG "ANAND header not found at 0x%x in mtd%d\n",
|
||||
printk(KERN_DEBUG "ANAND header not found at 0x%x in mtd%d\n",
|
||||
block * nftl->EraseSize, nftl->mbd.mtd->index);
|
||||
#endif
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -103,7 +103,7 @@ static int find_boot_record(struct NFTLrecord *nftl)
|
||||
*/
|
||||
if (le16_to_cpu(h1.EraseMark | h1.EraseMark1) != ERASE_MARK) {
|
||||
printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but erase mark not present (0x%04x,0x%04x instead)\n",
|
||||
block * nftl->EraseSize, nftl->mbd.mtd->index,
|
||||
block * nftl->EraseSize, nftl->mbd.mtd->index,
|
||||
le16_to_cpu(h1.EraseMark), le16_to_cpu(h1.EraseMark1));
|
||||
continue;
|
||||
}
|
||||
@ -175,7 +175,7 @@ device is already correct.
|
||||
nftl->nb_boot_blocks = le16_to_cpu(mh->FirstPhysicalEUN);
|
||||
if ((nftl->nb_boot_blocks + 2) >= nftl->nb_blocks) {
|
||||
printk(KERN_NOTICE "NFTL Media Header sanity check failed:\n");
|
||||
printk(KERN_NOTICE "nb_boot_blocks (%d) + 2 > nb_blocks (%d)\n",
|
||||
printk(KERN_NOTICE "nb_boot_blocks (%d) + 2 > nb_blocks (%d)\n",
|
||||
nftl->nb_boot_blocks, nftl->nb_blocks);
|
||||
return -1;
|
||||
}
|
||||
@ -187,7 +187,7 @@ device is already correct.
|
||||
nftl->numvunits, nftl->nb_blocks, nftl->nb_boot_blocks);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
nftl->mbd.size = nftl->numvunits * (nftl->EraseSize / SECTORSIZE);
|
||||
|
||||
/* If we're not using the last sectors in the device for some reason,
|
||||
@ -210,12 +210,12 @@ device is already correct.
|
||||
printk(KERN_NOTICE "NFTL: allocation of ReplUnitTable failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
/* mark the bios blocks (blocks before NFTL MediaHeader) as reserved */
|
||||
for (i = 0; i < nftl->nb_boot_blocks; i++)
|
||||
nftl->ReplUnitTable[i] = BLOCK_RESERVED;
|
||||
/* mark all remaining blocks as potentially containing data */
|
||||
for (; i < nftl->nb_blocks; i++) {
|
||||
for (; i < nftl->nb_blocks; i++) {
|
||||
nftl->ReplUnitTable[i] = BLOCK_NOTEXPLORED;
|
||||
}
|
||||
|
||||
@ -245,12 +245,12 @@ The new DiskOnChip driver already scanned the bad block table. Just query it.
|
||||
if (nftl->mbd.mtd->block_isbad(nftl->mbd.mtd, i * nftl->EraseSize))
|
||||
nftl->ReplUnitTable[i] = BLOCK_RESERVED;
|
||||
}
|
||||
|
||||
|
||||
nftl->MediaUnit = block;
|
||||
boot_record_count++;
|
||||
|
||||
|
||||
} /* foreach (block) */
|
||||
|
||||
|
||||
return boot_record_count?0:-1;
|
||||
}
|
||||
|
||||
@ -265,7 +265,7 @@ static int memcmpb(void *a, int c, int n)
|
||||
}
|
||||
|
||||
/* check_free_sector: check if a free sector is actually FREE, i.e. All 0xff in data and oob area */
|
||||
static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int len,
|
||||
static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int len,
|
||||
int check_oob)
|
||||
{
|
||||
int i;
|
||||
@ -293,7 +293,7 @@ static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int
|
||||
*
|
||||
* Return: 0 when succeed, -1 on error.
|
||||
*
|
||||
* ToDo: 1. Is it neceressary to check_free_sector after erasing ??
|
||||
* ToDo: 1. Is it neceressary to check_free_sector after erasing ??
|
||||
*/
|
||||
int NFTL_formatblock(struct NFTLrecord *nftl, int block)
|
||||
{
|
||||
@ -385,7 +385,7 @@ static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_b
|
||||
/* verify that the sector is really free. If not, mark
|
||||
as ignore */
|
||||
if (memcmpb(&bci, 0xff, 8) != 0 ||
|
||||
check_free_sectors(nftl, block * nftl->EraseSize + i * SECTORSIZE,
|
||||
check_free_sectors(nftl, block * nftl->EraseSize + i * SECTORSIZE,
|
||||
SECTORSIZE, 0) != 0) {
|
||||
printk("Incorrect free sector %d in block %d: "
|
||||
"marking it as ignored\n",
|
||||
@ -486,7 +486,7 @@ static int check_and_mark_free_block(struct NFTLrecord *nftl, int block)
|
||||
size_t retlen;
|
||||
|
||||
/* check erase mark. */
|
||||
if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
|
||||
if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
|
||||
&retlen, (char *)&h1) < 0)
|
||||
return -1;
|
||||
|
||||
@ -501,7 +501,7 @@ static int check_and_mark_free_block(struct NFTLrecord *nftl, int block)
|
||||
h1.EraseMark = cpu_to_le16(ERASE_MARK);
|
||||
h1.EraseMark1 = cpu_to_le16(ERASE_MARK);
|
||||
h1.WearInfo = cpu_to_le32(0);
|
||||
if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
|
||||
if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
|
||||
&retlen, (char *)&h1) < 0)
|
||||
return -1;
|
||||
} else {
|
||||
@ -582,9 +582,9 @@ int NFTL_mount(struct NFTLrecord *s)
|
||||
|
||||
for (;;) {
|
||||
/* read the block header. If error, we format the chain */
|
||||
if (MTD_READOOB(s->mbd.mtd, block * s->EraseSize + 8, 8,
|
||||
if (MTD_READOOB(s->mbd.mtd, block * s->EraseSize + 8, 8,
|
||||
&retlen, (char *)&h0) < 0 ||
|
||||
MTD_READOOB(s->mbd.mtd, block * s->EraseSize + SECTORSIZE + 8, 8,
|
||||
MTD_READOOB(s->mbd.mtd, block * s->EraseSize + SECTORSIZE + 8, 8,
|
||||
&retlen, (char *)&h1) < 0) {
|
||||
s->ReplUnitTable[block] = BLOCK_NIL;
|
||||
do_format_chain = 1;
|
||||
@ -639,7 +639,7 @@ int NFTL_mount(struct NFTLrecord *s)
|
||||
first_logical_block = logical_block;
|
||||
} else {
|
||||
if (logical_block != first_logical_block) {
|
||||
printk("Block %d: incorrect logical block: %d expected: %d\n",
|
||||
printk("Block %d: incorrect logical block: %d expected: %d\n",
|
||||
block, logical_block, first_logical_block);
|
||||
/* the chain is incorrect : we must format it,
|
||||
but we need to read it completly */
|
||||
@ -668,7 +668,7 @@ int NFTL_mount(struct NFTLrecord *s)
|
||||
s->ReplUnitTable[block] = BLOCK_NIL;
|
||||
break;
|
||||
} else if (rep_block >= s->nb_blocks) {
|
||||
printk("Block %d: referencing invalid block %d\n",
|
||||
printk("Block %d: referencing invalid block %d\n",
|
||||
block, rep_block);
|
||||
do_format_chain = 1;
|
||||
s->ReplUnitTable[block] = BLOCK_NIL;
|
||||
@ -688,7 +688,7 @@ int NFTL_mount(struct NFTLrecord *s)
|
||||
s->ReplUnitTable[block] = rep_block;
|
||||
s->EUNtable[first_logical_block] = BLOCK_NIL;
|
||||
} else {
|
||||
printk("Block %d: referencing block %d already in another chain\n",
|
||||
printk("Block %d: referencing block %d already in another chain\n",
|
||||
block, rep_block);
|
||||
/* XXX: should handle correctly fold in progress chains */
|
||||
do_format_chain = 1;
|
||||
@ -710,7 +710,7 @@ int NFTL_mount(struct NFTLrecord *s)
|
||||
} else {
|
||||
unsigned int first_block1, chain_to_format, chain_length1;
|
||||
int fold_mark;
|
||||
|
||||
|
||||
/* valid chain : get foldmark */
|
||||
fold_mark = get_fold_mark(s, first_block);
|
||||
if (fold_mark == 0) {
|
||||
@ -729,9 +729,9 @@ int NFTL_mount(struct NFTLrecord *s)
|
||||
if (first_block1 != BLOCK_NIL) {
|
||||
/* XXX: what to do if same length ? */
|
||||
chain_length1 = calc_chain_length(s, first_block1);
|
||||
printk("Two chains at blocks %d (len=%d) and %d (len=%d)\n",
|
||||
printk("Two chains at blocks %d (len=%d) and %d (len=%d)\n",
|
||||
first_block1, chain_length1, first_block, chain_length);
|
||||
|
||||
|
||||
if (chain_length >= chain_length1) {
|
||||
chain_to_format = first_block1;
|
||||
s->EUNtable[first_logical_block] = first_block;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: redboot.c,v 1.17 2004/11/22 11:33:56 ijc Exp $
|
||||
* $Id: redboot.c,v 1.18 2005/11/07 11:14:21 gleixner Exp $
|
||||
*
|
||||
* Parse RedBoot-style Flash Image System (FIS) tables and
|
||||
* produce a Linux partition array to match.
|
||||
@ -39,7 +39,7 @@ static inline int redboot_checksum(struct fis_image_desc *img)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int parse_redboot_partitions(struct mtd_info *master,
|
||||
static int parse_redboot_partitions(struct mtd_info *master,
|
||||
struct mtd_partition **pparts,
|
||||
unsigned long fis_origin)
|
||||
{
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2005 Sean Young <sean@mess.org>
|
||||
*
|
||||
* $Id: rfd_ftl.c,v 1.4 2005/07/31 22:49:14 sean Exp $
|
||||
* $Id: rfd_ftl.c,v 1.5 2005/11/07 11:14:21 gleixner Exp $
|
||||
*
|
||||
* This type of flash translation layer (FTL) is used by the Embedded BIOS
|
||||
* by General Software. It is known as the Resident Flash Disk (RFD), see:
|
||||
@ -95,7 +95,7 @@ static int build_block_map(struct partition *part, int block_no)
|
||||
{
|
||||
struct block *block = &part->blocks[block_no];
|
||||
int i;
|
||||
|
||||
|
||||
block->offset = part->block_size * block_no;
|
||||
|
||||
if (le16_to_cpu(part->header_cache[0]) != RFD_MAGIC) {
|
||||
@ -109,12 +109,12 @@ static int build_block_map(struct partition *part, int block_no)
|
||||
|
||||
for (i=0; i<part->data_sectors_per_block; i++) {
|
||||
u16 entry;
|
||||
|
||||
|
||||
entry = le16_to_cpu(part->header_cache[HEADER_MAP_OFFSET + i]);
|
||||
|
||||
if (entry == SECTOR_DELETED)
|
||||
continue;
|
||||
|
||||
|
||||
if (entry == SECTOR_FREE) {
|
||||
block->free_sectors++;
|
||||
continue;
|
||||
@ -122,9 +122,9 @@ static int build_block_map(struct partition *part, int block_no)
|
||||
|
||||
if (entry == SECTOR_ZERO)
|
||||
entry = 0;
|
||||
|
||||
|
||||
if (entry >= part->sector_count) {
|
||||
printk(KERN_NOTICE PREFIX
|
||||
printk(KERN_NOTICE PREFIX
|
||||
"'%s': unit #%d: entry %d corrupt, "
|
||||
"sector %d out of range\n",
|
||||
part->mbd.mtd->name, block_no, i, entry);
|
||||
@ -132,14 +132,14 @@ static int build_block_map(struct partition *part, int block_no)
|
||||
}
|
||||
|
||||
if (part->sector_map[entry] != -1) {
|
||||
printk(KERN_NOTICE PREFIX
|
||||
printk(KERN_NOTICE PREFIX
|
||||
"'%s': more than one entry for sector %d\n",
|
||||
part->mbd.mtd->name, entry);
|
||||
part->errors = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
part->sector_map[entry] = block->offset +
|
||||
part->sector_map[entry] = block->offset +
|
||||
(i + part->header_sectors_per_block) * SECTOR_SIZE;
|
||||
|
||||
block->used_sectors++;
|
||||
@ -165,14 +165,14 @@ static int scan_header(struct partition *part)
|
||||
return -ENOENT;
|
||||
|
||||
/* each erase block has three bytes header, followed by the map */
|
||||
part->header_sectors_per_block =
|
||||
((HEADER_MAP_OFFSET + sectors_per_block) *
|
||||
part->header_sectors_per_block =
|
||||
((HEADER_MAP_OFFSET + sectors_per_block) *
|
||||
sizeof(u16) + SECTOR_SIZE - 1) / SECTOR_SIZE;
|
||||
|
||||
part->data_sectors_per_block = sectors_per_block -
|
||||
part->data_sectors_per_block = sectors_per_block -
|
||||
part->header_sectors_per_block;
|
||||
|
||||
part->header_size = (HEADER_MAP_OFFSET +
|
||||
part->header_size = (HEADER_MAP_OFFSET +
|
||||
part->data_sectors_per_block) * sizeof(u16);
|
||||
|
||||
part->cylinders = (part->data_sectors_per_block *
|
||||
@ -188,7 +188,7 @@ static int scan_header(struct partition *part)
|
||||
if (!part->header_cache)
|
||||
goto err;
|
||||
|
||||
part->blocks = kcalloc(part->total_blocks, sizeof(struct block),
|
||||
part->blocks = kcalloc(part->total_blocks, sizeof(struct block),
|
||||
GFP_KERNEL);
|
||||
if (!part->blocks)
|
||||
goto err;
|
||||
@ -200,18 +200,18 @@ static int scan_header(struct partition *part)
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i=0; i<part->sector_count; i++)
|
||||
for (i=0; i<part->sector_count; i++)
|
||||
part->sector_map[i] = -1;
|
||||
|
||||
for (i=0, blocks_found=0; i<part->total_blocks; i++) {
|
||||
rc = part->mbd.mtd->read(part->mbd.mtd,
|
||||
rc = part->mbd.mtd->read(part->mbd.mtd,
|
||||
i * part->block_size, part->header_size,
|
||||
&retlen, (u_char*)part->header_cache);
|
||||
|
||||
if (!rc && retlen != part->header_size)
|
||||
rc = -EIO;
|
||||
|
||||
if (rc)
|
||||
if (rc)
|
||||
goto err;
|
||||
|
||||
if (!build_block_map(part, i))
|
||||
@ -226,7 +226,7 @@ static int scan_header(struct partition *part)
|
||||
}
|
||||
|
||||
if (part->reserved_block == -1) {
|
||||
printk(KERN_NOTICE PREFIX "'%s': no empty erase unit found\n",
|
||||
printk(KERN_NOTICE PREFIX "'%s': no empty erase unit found\n",
|
||||
part->mbd.mtd->name);
|
||||
|
||||
part->errors = 1;
|
||||
@ -248,7 +248,7 @@ static int rfd_ftl_readsect(struct mtd_blktrans_dev *dev, u_long sector, char *b
|
||||
u_long addr;
|
||||
size_t retlen;
|
||||
int rc;
|
||||
|
||||
|
||||
if (sector >= part->sector_count)
|
||||
return -EIO;
|
||||
|
||||
@ -266,9 +266,9 @@ static int rfd_ftl_readsect(struct mtd_blktrans_dev *dev, u_long sector, char *b
|
||||
}
|
||||
} else
|
||||
memset(buf, 0, SECTOR_SIZE);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void erase_callback(struct erase_info *erase)
|
||||
{
|
||||
@ -288,7 +288,7 @@ static void erase_callback(struct erase_info *erase)
|
||||
|
||||
if (erase->state != MTD_ERASE_DONE) {
|
||||
printk(KERN_WARNING PREFIX "erase failed at 0x%x on '%s', "
|
||||
"state %d\n", erase->addr,
|
||||
"state %d\n", erase->addr,
|
||||
part->mbd.mtd->name, erase->state);
|
||||
|
||||
part->blocks[i].state = BLOCK_FAILED;
|
||||
@ -307,17 +307,17 @@ static void erase_callback(struct erase_info *erase)
|
||||
part->blocks[i].used_sectors = 0;
|
||||
part->blocks[i].erases++;
|
||||
|
||||
rc = part->mbd.mtd->write(part->mbd.mtd,
|
||||
part->blocks[i].offset, sizeof(magic), &retlen,
|
||||
rc = part->mbd.mtd->write(part->mbd.mtd,
|
||||
part->blocks[i].offset, sizeof(magic), &retlen,
|
||||
(u_char*)&magic);
|
||||
|
||||
|
||||
if (!rc && retlen != sizeof(magic))
|
||||
rc = -EIO;
|
||||
|
||||
if (rc) {
|
||||
printk(KERN_NOTICE PREFIX "'%s': unable to write RFD "
|
||||
"header at 0x%lx\n",
|
||||
part->mbd.mtd->name,
|
||||
part->mbd.mtd->name,
|
||||
part->blocks[i].offset);
|
||||
part->blocks[i].state = BLOCK_FAILED;
|
||||
}
|
||||
@ -374,17 +374,17 @@ static int move_block_contents(struct partition *part, int block_no, u_long *old
|
||||
map = kmalloc(part->header_size, GFP_KERNEL);
|
||||
if (!map)
|
||||
goto err2;
|
||||
|
||||
rc = part->mbd.mtd->read(part->mbd.mtd,
|
||||
part->blocks[block_no].offset, part->header_size,
|
||||
|
||||
rc = part->mbd.mtd->read(part->mbd.mtd,
|
||||
part->blocks[block_no].offset, part->header_size,
|
||||
&retlen, (u_char*)map);
|
||||
|
||||
|
||||
if (!rc && retlen != part->header_size)
|
||||
rc = -EIO;
|
||||
|
||||
if (rc) {
|
||||
printk(KERN_NOTICE PREFIX "error reading '%s' at "
|
||||
"0x%lx\n", part->mbd.mtd->name,
|
||||
"0x%lx\n", part->mbd.mtd->name,
|
||||
part->blocks[block_no].offset);
|
||||
|
||||
goto err;
|
||||
@ -398,11 +398,11 @@ static int move_block_contents(struct partition *part, int block_no, u_long *old
|
||||
if (entry == SECTOR_FREE || entry == SECTOR_DELETED)
|
||||
continue;
|
||||
|
||||
if (entry == SECTOR_ZERO)
|
||||
if (entry == SECTOR_ZERO)
|
||||
entry = 0;
|
||||
|
||||
/* already warned about and ignored in build_block_map() */
|
||||
if (entry >= part->sector_count)
|
||||
if (entry >= part->sector_count)
|
||||
continue;
|
||||
|
||||
addr = part->blocks[block_no].offset +
|
||||
@ -418,7 +418,7 @@ static int move_block_contents(struct partition *part, int block_no, u_long *old
|
||||
}
|
||||
rc = part->mbd.mtd->read(part->mbd.mtd, addr,
|
||||
SECTOR_SIZE, &retlen, sector_data);
|
||||
|
||||
|
||||
if (!rc && retlen != SECTOR_SIZE)
|
||||
rc = -EIO;
|
||||
|
||||
@ -429,11 +429,11 @@ static int move_block_contents(struct partition *part, int block_no, u_long *old
|
||||
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
||||
rc = rfd_ftl_writesect((struct mtd_blktrans_dev*)part,
|
||||
entry, sector_data);
|
||||
|
||||
if (rc)
|
||||
|
||||
if (rc)
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -447,11 +447,11 @@ static int move_block_contents(struct partition *part, int block_no, u_long *old
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int reclaim_block(struct partition *part, u_long *old_sector)
|
||||
static int reclaim_block(struct partition *part, u_long *old_sector)
|
||||
{
|
||||
int block, best_block, score, old_sector_block;
|
||||
int rc;
|
||||
|
||||
|
||||
/* we have a race if sync doesn't exist */
|
||||
if (part->mbd.mtd->sync)
|
||||
part->mbd.mtd->sync(part->mbd.mtd);
|
||||
@ -474,16 +474,16 @@ static int reclaim_block(struct partition *part, u_long *old_sector)
|
||||
* more removed sectors is more efficient (have to move
|
||||
* less).
|
||||
*/
|
||||
if (part->blocks[block].free_sectors)
|
||||
if (part->blocks[block].free_sectors)
|
||||
return 0;
|
||||
|
||||
this_score = part->blocks[block].used_sectors;
|
||||
|
||||
if (block == old_sector_block)
|
||||
if (block == old_sector_block)
|
||||
this_score--;
|
||||
else {
|
||||
/* no point in moving a full block */
|
||||
if (part->blocks[block].used_sectors ==
|
||||
if (part->blocks[block].used_sectors ==
|
||||
part->data_sectors_per_block)
|
||||
continue;
|
||||
}
|
||||
@ -529,7 +529,7 @@ static int find_free_block(const struct partition *part)
|
||||
stop = block;
|
||||
|
||||
do {
|
||||
if (part->blocks[block].free_sectors &&
|
||||
if (part->blocks[block].free_sectors &&
|
||||
block != part->reserved_block)
|
||||
return block;
|
||||
|
||||
@ -563,7 +563,7 @@ static int find_writeable_block(struct partition *part, u_long *old_sector)
|
||||
}
|
||||
}
|
||||
|
||||
rc = part->mbd.mtd->read(part->mbd.mtd, part->blocks[block].offset,
|
||||
rc = part->mbd.mtd->read(part->mbd.mtd, part->blocks[block].offset,
|
||||
part->header_size, &retlen, (u_char*)part->header_cache);
|
||||
|
||||
if (!rc && retlen != part->header_size)
|
||||
@ -571,7 +571,7 @@ static int find_writeable_block(struct partition *part, u_long *old_sector)
|
||||
|
||||
if (rc) {
|
||||
printk(KERN_NOTICE PREFIX "'%s': unable to read header at "
|
||||
"0x%lx\n", part->mbd.mtd->name,
|
||||
"0x%lx\n", part->mbd.mtd->name,
|
||||
part->blocks[block].offset);
|
||||
goto err;
|
||||
}
|
||||
@ -580,7 +580,7 @@ static int find_writeable_block(struct partition *part, u_long *old_sector)
|
||||
|
||||
err:
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
static int mark_sector_deleted(struct partition *part, u_long old_addr)
|
||||
{
|
||||
@ -590,7 +590,7 @@ static int mark_sector_deleted(struct partition *part, u_long old_addr)
|
||||
u16 del = const_cpu_to_le16(SECTOR_DELETED);
|
||||
|
||||
block = old_addr / part->block_size;
|
||||
offset = (old_addr % part->block_size) / SECTOR_SIZE -
|
||||
offset = (old_addr % part->block_size) / SECTOR_SIZE -
|
||||
part->header_sectors_per_block;
|
||||
|
||||
addr = part->blocks[block].offset +
|
||||
@ -604,7 +604,7 @@ static int mark_sector_deleted(struct partition *part, u_long old_addr)
|
||||
if (rc) {
|
||||
printk(KERN_WARNING PREFIX "error writing '%s' at "
|
||||
"0x%lx\n", part->mbd.mtd->name, addr);
|
||||
if (rc)
|
||||
if (rc)
|
||||
goto err;
|
||||
}
|
||||
if (block == part->current_block)
|
||||
@ -627,7 +627,7 @@ static int find_free_sector(const struct partition *part, const struct block *bl
|
||||
i = stop = part->data_sectors_per_block - block->free_sectors;
|
||||
|
||||
do {
|
||||
if (le16_to_cpu(part->header_cache[HEADER_MAP_OFFSET + i])
|
||||
if (le16_to_cpu(part->header_cache[HEADER_MAP_OFFSET + i])
|
||||
== SECTOR_FREE)
|
||||
return i;
|
||||
|
||||
@ -653,7 +653,7 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf,
|
||||
!part->blocks[part->current_block].free_sectors) {
|
||||
|
||||
rc = find_writeable_block(part, old_addr);
|
||||
if (rc)
|
||||
if (rc)
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -665,10 +665,10 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf,
|
||||
rc = -ENOSPC;
|
||||
goto err;
|
||||
}
|
||||
|
||||
addr = (i + part->header_sectors_per_block) * SECTOR_SIZE +
|
||||
|
||||
addr = (i + part->header_sectors_per_block) * SECTOR_SIZE +
|
||||
block->offset;
|
||||
rc = part->mbd.mtd->write(part->mbd.mtd,
|
||||
rc = part->mbd.mtd->write(part->mbd.mtd,
|
||||
addr, SECTOR_SIZE, &retlen, (u_char*)buf);
|
||||
|
||||
if (!rc && retlen != SECTOR_SIZE)
|
||||
@ -677,7 +677,7 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf,
|
||||
if (rc) {
|
||||
printk(KERN_WARNING PREFIX "error writing '%s' at 0x%lx\n",
|
||||
part->mbd.mtd->name, addr);
|
||||
if (rc)
|
||||
if (rc)
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -697,7 +697,7 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf,
|
||||
if (rc) {
|
||||
printk(KERN_WARNING PREFIX "error writing '%s' at 0x%lx\n",
|
||||
part->mbd.mtd->name, addr);
|
||||
if (rc)
|
||||
if (rc)
|
||||
goto err;
|
||||
}
|
||||
block->used_sectors++;
|
||||
@ -738,7 +738,7 @@ static int rfd_ftl_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == SECTOR_SIZE)
|
||||
if (i == SECTOR_SIZE)
|
||||
part->sector_map[sector] = -1;
|
||||
|
||||
if (old_addr != -1)
|
||||
@ -801,7 +801,7 @@ static void rfd_ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
|
||||
|
||||
if (!add_mtd_blktrans_dev((void*)part))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
kfree(part);
|
||||
}
|
||||
@ -828,7 +828,7 @@ struct mtd_blktrans_ops rfd_ftl_tr = {
|
||||
.major = RFD_FTL_MAJOR,
|
||||
.part_bits = PART_BITS,
|
||||
.readsect = rfd_ftl_readsect,
|
||||
.writesect = rfd_ftl_writesect,
|
||||
.writesect = rfd_ftl_writesect,
|
||||
.getgeo = rfd_ftl_getgeo,
|
||||
.add_mtd = rfd_ftl_add_mtd,
|
||||
.remove_dev = rfd_ftl_remove_dev,
|
||||
|
Loading…
Reference in New Issue
Block a user