diff options
Diffstat (limited to 'drivers/mtd/mtdblock.c')
-rw-r--r-- | drivers/mtd/mtdblock.c | 53 |
1 files changed, 27 insertions, 26 deletions
diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c index 400dd9c89883..e84756644fd1 100644 --- a/drivers/mtd/mtdblock.c +++ b/drivers/mtd/mtdblock.c | |||
@@ -1,21 +1,22 @@ | |||
1 | /* | 1 | /* |
2 | * Direct MTD block device access | 2 | * Direct MTD block device access |
3 | * | 3 | * |
4 | * $Id: mtdblock.c,v 1.66 2004/11/25 13:52:52 joern Exp $ | 4 | * $Id: mtdblock.c,v 1.68 2005/11/07 11:14:20 gleixner Exp $ |
5 | * | 5 | * |
6 | * (C) 2000-2003 Nicolas Pitre <nico@cam.org> | 6 | * (C) 2000-2003 Nicolas Pitre <nico@cam.org> |
7 | * (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> | 7 | * (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/config.h> | 10 | #include <linux/config.h> |
11 | #include <linux/types.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/fs.h> | 11 | #include <linux/fs.h> |
15 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/kernel.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/sched.h> | ||
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/types.h> | ||
17 | #include <linux/vmalloc.h> | 18 | #include <linux/vmalloc.h> |
18 | #include <linux/sched.h> /* TASK_* */ | 19 | |
19 | #include <linux/mtd/mtd.h> | 20 | #include <linux/mtd/mtd.h> |
20 | #include <linux/mtd/blktrans.h> | 21 | #include <linux/mtd/blktrans.h> |
21 | 22 | ||
@@ -31,7 +32,7 @@ static struct mtdblk_dev { | |||
31 | 32 | ||
32 | /* | 33 | /* |
33 | * Cache stuff... | 34 | * Cache stuff... |
34 | * | 35 | * |
35 | * Since typical flash erasable sectors are much larger than what Linux's | 36 | * Since typical flash erasable sectors are much larger than what Linux's |
36 | * buffer cache can handle, we must implement read-modify-write on flash | 37 | * buffer cache can handle, we must implement read-modify-write on flash |
37 | * sectors for each block write requests. To avoid over-erasing flash sectors | 38 | * sectors for each block write requests. To avoid over-erasing flash sectors |
@@ -45,7 +46,7 @@ static void erase_callback(struct erase_info *done) | |||
45 | wake_up(wait_q); | 46 | wake_up(wait_q); |
46 | } | 47 | } |
47 | 48 | ||
48 | static int erase_write (struct mtd_info *mtd, unsigned long pos, | 49 | static int erase_write (struct mtd_info *mtd, unsigned long pos, |
49 | int len, const char *buf) | 50 | int len, const char *buf) |
50 | { | 51 | { |
51 | struct erase_info erase; | 52 | struct erase_info erase; |
@@ -103,18 +104,18 @@ static int write_cached_data (struct mtdblk_dev *mtdblk) | |||
103 | return 0; | 104 | return 0; |
104 | 105 | ||
105 | DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: writing cached data for \"%s\" " | 106 | DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: writing cached data for \"%s\" " |
106 | "at 0x%lx, size 0x%x\n", mtd->name, | 107 | "at 0x%lx, size 0x%x\n", mtd->name, |
107 | mtdblk->cache_offset, mtdblk->cache_size); | 108 | mtdblk->cache_offset, mtdblk->cache_size); |
108 | 109 | ||
109 | ret = erase_write (mtd, mtdblk->cache_offset, | 110 | ret = erase_write (mtd, mtdblk->cache_offset, |
110 | mtdblk->cache_size, mtdblk->cache_data); | 111 | mtdblk->cache_size, mtdblk->cache_data); |
111 | if (ret) | 112 | if (ret) |
112 | return ret; | 113 | return ret; |
113 | 114 | ||
114 | /* | 115 | /* |
115 | * Here we could argubly set the cache state to STATE_CLEAN. | 116 | * Here we could argubly set the cache state to STATE_CLEAN. |
116 | * However this could lead to inconsistency since we will not | 117 | * However this could lead to inconsistency since we will not |
117 | * be notified if this content is altered on the flash by other | 118 | * be notified if this content is altered on the flash by other |
118 | * means. Let's declare it empty and leave buffering tasks to | 119 | * means. Let's declare it empty and leave buffering tasks to |
119 | * the buffer cache instead. | 120 | * the buffer cache instead. |
120 | */ | 121 | */ |
@@ -123,7 +124,7 @@ static int write_cached_data (struct mtdblk_dev *mtdblk) | |||
123 | } | 124 | } |
124 | 125 | ||
125 | 126 | ||
126 | static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos, | 127 | static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos, |
127 | int len, const char *buf) | 128 | int len, const char *buf) |
128 | { | 129 | { |
129 | struct mtd_info *mtd = mtdblk->mtd; | 130 | struct mtd_info *mtd = mtdblk->mtd; |
@@ -133,7 +134,7 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos, | |||
133 | 134 | ||
134 | DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: write on \"%s\" at 0x%lx, size 0x%x\n", | 135 | DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: write on \"%s\" at 0x%lx, size 0x%x\n", |
135 | mtd->name, pos, len); | 136 | mtd->name, pos, len); |
136 | 137 | ||
137 | if (!sect_size) | 138 | if (!sect_size) |
138 | return MTD_WRITE (mtd, pos, len, &retlen, buf); | 139 | return MTD_WRITE (mtd, pos, len, &retlen, buf); |
139 | 140 | ||
@@ -141,11 +142,11 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos, | |||
141 | unsigned long sect_start = (pos/sect_size)*sect_size; | 142 | unsigned long sect_start = (pos/sect_size)*sect_size; |
142 | unsigned int offset = pos - sect_start; | 143 | unsigned int offset = pos - sect_start; |
143 | unsigned int size = sect_size - offset; | 144 | unsigned int size = sect_size - offset; |
144 | if( size > len ) | 145 | if( size > len ) |
145 | size = len; | 146 | size = len; |
146 | 147 | ||
147 | if (size == sect_size) { | 148 | if (size == sect_size) { |
148 | /* | 149 | /* |
149 | * We are covering a whole sector. Thus there is no | 150 | * We are covering a whole sector. Thus there is no |
150 | * need to bother with the cache while it may still be | 151 | * need to bother with the cache while it may still be |
151 | * useful for other partial writes. | 152 | * useful for other partial writes. |
@@ -159,7 +160,7 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos, | |||
159 | if (mtdblk->cache_state == STATE_DIRTY && | 160 | if (mtdblk->cache_state == STATE_DIRTY && |
160 | mtdblk->cache_offset != sect_start) { | 161 | mtdblk->cache_offset != sect_start) { |
161 | ret = write_cached_data(mtdblk); | 162 | ret = write_cached_data(mtdblk); |
162 | if (ret) | 163 | if (ret) |
163 | return ret; | 164 | return ret; |
164 | } | 165 | } |
165 | 166 | ||
@@ -192,7 +193,7 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos, | |||
192 | } | 193 | } |
193 | 194 | ||
194 | 195 | ||
195 | static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos, | 196 | static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos, |
196 | int len, char *buf) | 197 | int len, char *buf) |
197 | { | 198 | { |
198 | struct mtd_info *mtd = mtdblk->mtd; | 199 | struct mtd_info *mtd = mtdblk->mtd; |
@@ -200,9 +201,9 @@ static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos, | |||
200 | size_t retlen; | 201 | size_t retlen; |
201 | int ret; | 202 | int ret; |
202 | 203 | ||
203 | DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: read on \"%s\" at 0x%lx, size 0x%x\n", | 204 | DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: read on \"%s\" at 0x%lx, size 0x%x\n", |
204 | mtd->name, pos, len); | 205 | mtd->name, pos, len); |
205 | 206 | ||
206 | if (!sect_size) | 207 | if (!sect_size) |
207 | return MTD_READ (mtd, pos, len, &retlen, buf); | 208 | return MTD_READ (mtd, pos, len, &retlen, buf); |
208 | 209 | ||
@@ -210,7 +211,7 @@ static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos, | |||
210 | unsigned long sect_start = (pos/sect_size)*sect_size; | 211 | unsigned long sect_start = (pos/sect_size)*sect_size; |
211 | unsigned int offset = pos - sect_start; | 212 | unsigned int offset = pos - sect_start; |
212 | unsigned int size = sect_size - offset; | 213 | unsigned int size = sect_size - offset; |
213 | if (size > len) | 214 | if (size > len) |
214 | size = len; | 215 | size = len; |
215 | 216 | ||
216 | /* | 217 | /* |
@@ -268,12 +269,12 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd) | |||
268 | int dev = mbd->devnum; | 269 | int dev = mbd->devnum; |
269 | 270 | ||
270 | DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n"); | 271 | DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n"); |
271 | 272 | ||
272 | if (mtdblks[dev]) { | 273 | if (mtdblks[dev]) { |
273 | mtdblks[dev]->count++; | 274 | mtdblks[dev]->count++; |
274 | return 0; | 275 | return 0; |
275 | } | 276 | } |
276 | 277 | ||
277 | /* OK, it's not open. Create cache info for it */ | 278 | /* OK, it's not open. Create cache info for it */ |
278 | mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL); | 279 | mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL); |
279 | if (!mtdblk) | 280 | if (!mtdblk) |
@@ -292,7 +293,7 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd) | |||
292 | } | 293 | } |
293 | 294 | ||
294 | mtdblks[dev] = mtdblk; | 295 | mtdblks[dev] = mtdblk; |
295 | 296 | ||
296 | DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); | 297 | DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); |
297 | 298 | ||
298 | return 0; | 299 | return 0; |
@@ -320,7 +321,7 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd) | |||
320 | DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); | 321 | DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); |
321 | 322 | ||
322 | return 0; | 323 | return 0; |
323 | } | 324 | } |
324 | 325 | ||
325 | static int mtdblock_flush(struct mtd_blktrans_dev *dev) | 326 | static int mtdblock_flush(struct mtd_blktrans_dev *dev) |
326 | { | 327 | { |