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