blob: 1871140e1e781d72a49f3c564bfbf3513c4e6fbb [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright (C) 2001-2003 Red Hat, Inc.
5 * Copyright (C) 2004 Thomas Gleixner <tglx@linutronix.de>
6 *
7 * Created by David Woodhouse <dwmw2@infradead.org>
8 * Modified debugged and enhanced by Thomas Gleixner <tglx@linutronix.de>
9 *
10 * For licensing information, see the file 'LICENCE' in this directory.
11 *
Artem B. Bityutskiydaba5cc2005-09-30 14:59:17 +010012 * $Id: wbuf.c,v 1.100 2005/09/30 13:59:13 dedekind Exp $
Linus Torvalds1da177e2005-04-16 15:20:36 -070013 *
14 */
15
16#include <linux/kernel.h>
17#include <linux/slab.h>
18#include <linux/mtd/mtd.h>
19#include <linux/crc32.h>
20#include <linux/mtd/nand.h>
Tim Schmielau4e57b682005-10-30 15:03:48 -080021#include <linux/jiffies.h>
22
Linus Torvalds1da177e2005-04-16 15:20:36 -070023#include "nodelist.h"
24
25/* For testing write failures */
26#undef BREAKME
27#undef BREAKMEHEADER
28
29#ifdef BREAKME
30static unsigned char *brokenbuf;
31#endif
32
Artem B. Bityutskiydaba5cc2005-09-30 14:59:17 +010033#define PAGE_DIV(x) ( ((unsigned long)(x) / (unsigned long)(c->wbuf_pagesize)) * (unsigned long)(c->wbuf_pagesize) )
34#define PAGE_MOD(x) ( (unsigned long)(x) % (unsigned long)(c->wbuf_pagesize) )
35
Linus Torvalds1da177e2005-04-16 15:20:36 -070036/* max. erase failures before we mark a block bad */
37#define MAX_ERASE_FAILURES 2
38
Linus Torvalds1da177e2005-04-16 15:20:36 -070039struct jffs2_inodirty {
40 uint32_t ino;
41 struct jffs2_inodirty *next;
42};
43
44static struct jffs2_inodirty inodirty_nomem;
45
46static int jffs2_wbuf_pending_for_ino(struct jffs2_sb_info *c, uint32_t ino)
47{
48 struct jffs2_inodirty *this = c->wbuf_inodes;
49
50 /* If a malloc failed, consider _everything_ dirty */
51 if (this == &inodirty_nomem)
52 return 1;
53
54 /* If ino == 0, _any_ non-GC writes mean 'yes' */
55 if (this && !ino)
56 return 1;
57
58 /* Look to see if the inode in question is pending in the wbuf */
59 while (this) {
60 if (this->ino == ino)
61 return 1;
62 this = this->next;
63 }
64 return 0;
65}
66
67static void jffs2_clear_wbuf_ino_list(struct jffs2_sb_info *c)
68{
69 struct jffs2_inodirty *this;
70
71 this = c->wbuf_inodes;
72
73 if (this != &inodirty_nomem) {
74 while (this) {
75 struct jffs2_inodirty *next = this->next;
76 kfree(this);
77 this = next;
78 }
79 }
80 c->wbuf_inodes = NULL;
81}
82
83static void jffs2_wbuf_dirties_inode(struct jffs2_sb_info *c, uint32_t ino)
84{
85 struct jffs2_inodirty *new;
86
87 /* Mark the superblock dirty so that kupdated will flush... */
Artem B. Bityuckiy4d952702005-03-18 09:58:09 +000088 jffs2_erase_pending_trigger(c);
Linus Torvalds1da177e2005-04-16 15:20:36 -070089
90 if (jffs2_wbuf_pending_for_ino(c, ino))
91 return;
92
93 new = kmalloc(sizeof(*new), GFP_KERNEL);
94 if (!new) {
95 D1(printk(KERN_DEBUG "No memory to allocate inodirty. Fallback to all considered dirty\n"));
96 jffs2_clear_wbuf_ino_list(c);
97 c->wbuf_inodes = &inodirty_nomem;
98 return;
99 }
100 new->ino = ino;
101 new->next = c->wbuf_inodes;
102 c->wbuf_inodes = new;
103 return;
104}
105
106static inline void jffs2_refile_wbuf_blocks(struct jffs2_sb_info *c)
107{
108 struct list_head *this, *next;
109 static int n;
110
111 if (list_empty(&c->erasable_pending_wbuf_list))
112 return;
113
114 list_for_each_safe(this, next, &c->erasable_pending_wbuf_list) {
115 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
116
117 D1(printk(KERN_DEBUG "Removing eraseblock at 0x%08x from erasable_pending_wbuf_list...\n", jeb->offset));
118 list_del(this);
119 if ((jiffies + (n++)) & 127) {
120 /* Most of the time, we just erase it immediately. Otherwise we
121 spend ages scanning it on mount, etc. */
122 D1(printk(KERN_DEBUG "...and adding to erase_pending_list\n"));
123 list_add_tail(&jeb->list, &c->erase_pending_list);
124 c->nr_erasing_blocks++;
125 jffs2_erase_pending_trigger(c);
126 } else {
127 /* Sometimes, however, we leave it elsewhere so it doesn't get
128 immediately reused, and we spread the load a bit. */
129 D1(printk(KERN_DEBUG "...and adding to erasable_list\n"));
130 list_add_tail(&jeb->list, &c->erasable_list);
131 }
132 }
133}
134
Estelle Hammache7f716cf2005-01-24 21:24:18 +0000135#define REFILE_NOTEMPTY 0
136#define REFILE_ANYWAY 1
137
138static void jffs2_block_refile(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, int allow_empty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139{
140 D1(printk("About to refile bad block at %08x\n", jeb->offset));
141
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 /* File the existing block on the bad_used_list.... */
143 if (c->nextblock == jeb)
144 c->nextblock = NULL;
145 else /* Not sure this should ever happen... need more coffee */
146 list_del(&jeb->list);
147 if (jeb->first_node) {
148 D1(printk("Refiling block at %08x to bad_used_list\n", jeb->offset));
149 list_add(&jeb->list, &c->bad_used_list);
150 } else {
Estelle Hammache9b88f472005-01-28 18:53:05 +0000151 BUG_ON(allow_empty == REFILE_NOTEMPTY);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 /* It has to have had some nodes or we couldn't be here */
153 D1(printk("Refiling block at %08x to erase_pending_list\n", jeb->offset));
154 list_add(&jeb->list, &c->erase_pending_list);
155 c->nr_erasing_blocks++;
156 jffs2_erase_pending_trigger(c);
157 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158
159 /* Adjust its size counts accordingly */
160 c->wasted_size += jeb->free_size;
161 c->free_size -= jeb->free_size;
162 jeb->wasted_size += jeb->free_size;
163 jeb->free_size = 0;
164
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100165 jffs2_dbg_dump_block_lists_nolock(c);
166 jffs2_dbg_acct_sanity_check_nolock(c,jeb);
167 jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168}
169
170/* Recover from failure to write wbuf. Recover the nodes up to the
171 * wbuf, not the one which we were starting to try to write. */
172
173static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
174{
175 struct jffs2_eraseblock *jeb, *new_jeb;
176 struct jffs2_raw_node_ref **first_raw, **raw;
177 size_t retlen;
178 int ret;
179 unsigned char *buf;
180 uint32_t start, end, ofs, len;
181
David Woodhouse2f785402006-05-24 02:04:45 +0100182 if (jffs2_prealloc_raw_node_refs(c, c->reserved_refs + 1))
183 return;
184
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 spin_lock(&c->erase_completion_lock);
186
187 jeb = &c->blocks[c->wbuf_ofs / c->sector_size];
188
Estelle Hammache7f716cf2005-01-24 21:24:18 +0000189 jffs2_block_refile(c, jeb, REFILE_NOTEMPTY);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190
191 /* Find the first node to be recovered, by skipping over every
192 node which ends before the wbuf starts, or which is obsolete. */
193 first_raw = &jeb->first_node;
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000194 while (*first_raw &&
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 (ref_obsolete(*first_raw) ||
196 (ref_offset(*first_raw)+ref_totlen(c, jeb, *first_raw)) < c->wbuf_ofs)) {
197 D1(printk(KERN_DEBUG "Skipping node at 0x%08x(%d)-0x%08x which is either before 0x%08x or obsolete\n",
198 ref_offset(*first_raw), ref_flags(*first_raw),
199 (ref_offset(*first_raw) + ref_totlen(c, jeb, *first_raw)),
200 c->wbuf_ofs));
201 first_raw = &(*first_raw)->next_phys;
202 }
203
204 if (!*first_raw) {
205 /* All nodes were obsolete. Nothing to recover. */
206 D1(printk(KERN_DEBUG "No non-obsolete nodes to be recovered. Just filing block bad\n"));
207 spin_unlock(&c->erase_completion_lock);
208 return;
209 }
210
211 start = ref_offset(*first_raw);
212 end = ref_offset(*first_raw) + ref_totlen(c, jeb, *first_raw);
213
214 /* Find the last node to be recovered */
215 raw = first_raw;
216 while ((*raw)) {
217 if (!ref_obsolete(*raw))
218 end = ref_offset(*raw) + ref_totlen(c, jeb, *raw);
219
220 raw = &(*raw)->next_phys;
221 }
222 spin_unlock(&c->erase_completion_lock);
223
224 D1(printk(KERN_DEBUG "wbuf recover %08x-%08x\n", start, end));
225
226 buf = NULL;
227 if (start < c->wbuf_ofs) {
228 /* First affected node was already partially written.
229 * Attempt to reread the old data into our buffer. */
230
231 buf = kmalloc(end - start, GFP_KERNEL);
232 if (!buf) {
233 printk(KERN_CRIT "Malloc failure in wbuf recovery. Data loss ensues.\n");
234
235 goto read_failed;
236 }
237
238 /* Do the read... */
Thomas Gleixner9223a452006-05-23 17:21:03 +0200239 ret = c->mtd->read(c->mtd, start, c->wbuf_ofs - start, &retlen, buf);
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000240
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 if (ret == -EBADMSG && retlen == c->wbuf_ofs - start) {
242 /* ECC recovered */
243 ret = 0;
244 }
245 if (ret || retlen != c->wbuf_ofs - start) {
246 printk(KERN_CRIT "Old data are already lost in wbuf recovery. Data loss ensues.\n");
247
248 kfree(buf);
249 buf = NULL;
250 read_failed:
251 first_raw = &(*first_raw)->next_phys;
252 /* If this was the only node to be recovered, give up */
253 if (!(*first_raw))
254 return;
255
256 /* It wasn't. Go on and try to recover nodes complete in the wbuf */
257 start = ref_offset(*first_raw);
258 } else {
259 /* Read succeeded. Copy the remaining data from the wbuf */
260 memcpy(buf + (c->wbuf_ofs - start), c->wbuf, end - c->wbuf_ofs);
261 }
262 }
263 /* OK... we're to rewrite (end-start) bytes of data from first_raw onwards.
264 Either 'buf' contains the data, or we find it in the wbuf */
265
266
267 /* ... and get an allocation of space from a shiny new block instead */
David Woodhouse9fe48542006-05-23 00:38:06 +0100268 ret = jffs2_reserve_space_gc(c, end-start, &len, JFFS2_SUMMARY_NOSUM_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 if (ret) {
270 printk(KERN_WARNING "Failed to allocate space for wbuf recovery. Data loss ensues.\n");
Estelle Hammache9b88f472005-01-28 18:53:05 +0000271 kfree(buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 return;
273 }
David Woodhouse9fe48542006-05-23 00:38:06 +0100274 ofs = write_ofs(c);
275
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 if (end-start >= c->wbuf_pagesize) {
Estelle Hammache7f716cf2005-01-24 21:24:18 +0000277 /* Need to do another write immediately, but it's possible
Estelle Hammache9b88f472005-01-28 18:53:05 +0000278 that this is just because the wbuf itself is completely
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000279 full, and there's nothing earlier read back from the
280 flash. Hence 'buf' isn't necessarily what we're writing
Estelle Hammache9b88f472005-01-28 18:53:05 +0000281 from. */
Estelle Hammache7f716cf2005-01-24 21:24:18 +0000282 unsigned char *rewrite_buf = buf?:c->wbuf;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 uint32_t towrite = (end-start) - ((end-start)%c->wbuf_pagesize);
284
285 D1(printk(KERN_DEBUG "Write 0x%x bytes at 0x%08x in wbuf recover\n",
286 towrite, ofs));
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000287
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288#ifdef BREAKMEHEADER
289 static int breakme;
290 if (breakme++ == 20) {
291 printk(KERN_NOTICE "Faking write error at 0x%08x\n", ofs);
292 breakme = 0;
Thomas Gleixner9223a452006-05-23 17:21:03 +0200293 c->mtd->write(c->mtd, ofs, towrite, &retlen,
294 brokenbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 ret = -EIO;
296 } else
297#endif
Thomas Gleixner9223a452006-05-23 17:21:03 +0200298 ret = c->mtd->write(c->mtd, ofs, towrite, &retlen,
299 rewrite_buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300
301 if (ret || retlen != towrite) {
302 /* Argh. We tried. Really we did. */
303 printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n");
Estelle Hammache9b88f472005-01-28 18:53:05 +0000304 kfree(buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305
David Woodhouse2f785402006-05-24 02:04:45 +0100306 if (retlen)
307 jffs2_add_physical_node_ref(c, ofs | REF_OBSOLETE, ref_totlen(c, jeb, *first_raw), NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 return;
310 }
311 printk(KERN_NOTICE "Recovery of wbuf succeeded to %08x\n", ofs);
312
313 c->wbuf_len = (end - start) - towrite;
314 c->wbuf_ofs = ofs + towrite;
Estelle Hammache7f716cf2005-01-24 21:24:18 +0000315 memmove(c->wbuf, rewrite_buf + towrite, c->wbuf_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 /* Don't muck about with c->wbuf_inodes. False positives are harmless. */
Jesper Juhlf99d49a2005-11-07 01:01:34 -0800317 kfree(buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 } else {
319 /* OK, now we're left with the dregs in whichever buffer we're using */
320 if (buf) {
321 memcpy(c->wbuf, buf, end-start);
322 kfree(buf);
323 } else {
324 memmove(c->wbuf, c->wbuf + (start - c->wbuf_ofs), end - start);
325 }
326 c->wbuf_ofs = ofs;
327 c->wbuf_len = end - start;
328 }
329
330 /* Now sort out the jffs2_raw_node_refs, moving them from the old to the next block */
331 new_jeb = &c->blocks[ofs / c->sector_size];
332
333 spin_lock(&c->erase_completion_lock);
334 if (new_jeb->first_node) {
335 /* Odd, but possible with ST flash later maybe */
336 new_jeb->last_node->next_phys = *first_raw;
337 } else {
338 new_jeb->first_node = *first_raw;
339 }
340
341 raw = first_raw;
342 while (*raw) {
343 uint32_t rawlen = ref_totlen(c, jeb, *raw);
344
345 D1(printk(KERN_DEBUG "Refiling block of %08x at %08x(%d) to %08x\n",
346 rawlen, ref_offset(*raw), ref_flags(*raw), ofs));
347
348 if (ref_obsolete(*raw)) {
349 /* Shouldn't really happen much */
350 new_jeb->dirty_size += rawlen;
351 new_jeb->free_size -= rawlen;
352 c->dirty_size += rawlen;
353 } else {
354 new_jeb->used_size += rawlen;
355 new_jeb->free_size -= rawlen;
356 jeb->dirty_size += rawlen;
357 jeb->used_size -= rawlen;
358 c->dirty_size += rawlen;
359 }
360 c->free_size -= rawlen;
361 (*raw)->flash_offset = ofs | ref_flags(*raw);
362 ofs += rawlen;
363 new_jeb->last_node = *raw;
364
365 raw = &(*raw)->next_phys;
366 }
367
368 /* Fix up the original jeb now it's on the bad_list */
369 *first_raw = NULL;
370 if (first_raw == &jeb->first_node) {
371 jeb->last_node = NULL;
372 D1(printk(KERN_DEBUG "Failing block at %08x is now empty. Moving to erase_pending_list\n", jeb->offset));
373 list_del(&jeb->list);
374 list_add(&jeb->list, &c->erase_pending_list);
375 c->nr_erasing_blocks++;
376 jffs2_erase_pending_trigger(c);
377 }
378 else
379 jeb->last_node = container_of(first_raw, struct jffs2_raw_node_ref, next_phys);
380
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100381 jffs2_dbg_acct_sanity_check_nolock(c, jeb);
382 jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100384 jffs2_dbg_acct_sanity_check_nolock(c, new_jeb);
385 jffs2_dbg_acct_paranoia_check_nolock(c, new_jeb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386
387 spin_unlock(&c->erase_completion_lock);
388
389 D1(printk(KERN_DEBUG "wbuf recovery completed OK\n"));
390}
391
392/* Meaning of pad argument:
393 0: Do not pad. Probably pointless - we only ever use this when we can't pad anyway.
394 1: Pad, do not adjust nextblock free_size
395 2: Pad, adjust nextblock free_size
396*/
397#define NOPAD 0
398#define PAD_NOACCOUNT 1
399#define PAD_ACCOUNTING 2
400
401static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
402{
403 int ret;
404 size_t retlen;
405
Andrew Victor3be36672005-02-09 09:09:05 +0000406 /* Nothing to do if not write-buffering the flash. In particular, we shouldn't
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 del_timer() the timer we never initialised. */
Andrew Victor3be36672005-02-09 09:09:05 +0000408 if (!jffs2_is_writebuffered(c))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 return 0;
410
411 if (!down_trylock(&c->alloc_sem)) {
412 up(&c->alloc_sem);
413 printk(KERN_CRIT "jffs2_flush_wbuf() called with alloc_sem not locked!\n");
414 BUG();
415 }
416
Andrew Victor3be36672005-02-09 09:09:05 +0000417 if (!c->wbuf_len) /* already checked c->wbuf above */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 return 0;
419
David Woodhouse2f785402006-05-24 02:04:45 +0100420 if (jffs2_prealloc_raw_node_refs(c, c->reserved_refs + 1))
421 return -ENOMEM;
422
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 /* claim remaining space on the page
424 this happens, if we have a change to a new block,
425 or if fsync forces us to flush the writebuffer.
426 if we have a switch to next page, we will not have
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000427 enough remaining space for this.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 */
Artem B. Bityutskiydaba5cc2005-09-30 14:59:17 +0100429 if (pad ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 c->wbuf_len = PAD(c->wbuf_len);
431
432 /* Pad with JFFS2_DIRTY_BITMASK initially. this helps out ECC'd NOR
433 with 8 byte page size */
434 memset(c->wbuf + c->wbuf_len, 0, c->wbuf_pagesize - c->wbuf_len);
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000435
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 if ( c->wbuf_len + sizeof(struct jffs2_unknown_node) < c->wbuf_pagesize) {
437 struct jffs2_unknown_node *padnode = (void *)(c->wbuf + c->wbuf_len);
438 padnode->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
439 padnode->nodetype = cpu_to_je16(JFFS2_NODETYPE_PADDING);
440 padnode->totlen = cpu_to_je32(c->wbuf_pagesize - c->wbuf_len);
441 padnode->hdr_crc = cpu_to_je32(crc32(0, padnode, sizeof(*padnode)-4));
442 }
443 }
444 /* else jffs2_flash_writev has actually filled in the rest of the
445 buffer for us, and will deal with the node refs etc. later. */
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000446
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447#ifdef BREAKME
448 static int breakme;
449 if (breakme++ == 20) {
450 printk(KERN_NOTICE "Faking write error at 0x%08x\n", c->wbuf_ofs);
451 breakme = 0;
Thomas Gleixner9223a452006-05-23 17:21:03 +0200452 c->mtd->write(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen,
453 brokenbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 ret = -EIO;
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000455 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456#endif
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000457
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 ret = c->mtd->write(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf);
459
460 if (ret || retlen != c->wbuf_pagesize) {
461 if (ret)
462 printk(KERN_WARNING "jffs2_flush_wbuf(): Write failed with %d\n",ret);
463 else {
464 printk(KERN_WARNING "jffs2_flush_wbuf(): Write was short: %zd instead of %d\n",
465 retlen, c->wbuf_pagesize);
466 ret = -EIO;
467 }
468
469 jffs2_wbuf_recover(c);
470
471 return ret;
472 }
473
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 /* Adjust free size of the block if we padded. */
Artem B. Bityutskiydaba5cc2005-09-30 14:59:17 +0100475 if (pad) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 struct jffs2_eraseblock *jeb;
David Woodhouse0bcc0992006-05-21 13:00:54 +0100477 uint32_t waste = c->wbuf_pagesize - c->wbuf_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478
479 jeb = &c->blocks[c->wbuf_ofs / c->sector_size];
480
481 D1(printk(KERN_DEBUG "jffs2_flush_wbuf() adjusting free_size of %sblock at %08x\n",
482 (jeb==c->nextblock)?"next":"", jeb->offset));
483
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000484 /* wbuf_pagesize - wbuf_len is the amount of space that's to be
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 padded. If there is less free space in the block than that,
486 something screwed up */
David Woodhouse0bcc0992006-05-21 13:00:54 +0100487 if (jeb->free_size < waste) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 printk(KERN_CRIT "jffs2_flush_wbuf(): Accounting error. wbuf at 0x%08x has 0x%03x bytes, 0x%03x left.\n",
David Woodhouse0bcc0992006-05-21 13:00:54 +0100489 c->wbuf_ofs, c->wbuf_len, waste);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 printk(KERN_CRIT "jffs2_flush_wbuf(): But free_size for block at 0x%08x is only 0x%08x\n",
491 jeb->offset, jeb->free_size);
492 BUG();
493 }
David Woodhouse0bcc0992006-05-21 13:00:54 +0100494
495 spin_lock(&c->erase_completion_lock);
496
David Woodhouse2f785402006-05-24 02:04:45 +0100497 jffs2_link_node_ref(c, jeb, (c->wbuf_ofs + c->wbuf_len) | REF_OBSOLETE, waste, NULL);
David Woodhouse0bcc0992006-05-21 13:00:54 +0100498 /* FIXME: that made it count as dirty. Convert to wasted */
499 jeb->dirty_size -= waste;
500 c->dirty_size -= waste;
501 jeb->wasted_size += waste;
502 c->wasted_size += waste;
503 } else
504 spin_lock(&c->erase_completion_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505
506 /* Stick any now-obsoleted blocks on the erase_pending_list */
507 jffs2_refile_wbuf_blocks(c);
508 jffs2_clear_wbuf_ino_list(c);
509 spin_unlock(&c->erase_completion_lock);
510
511 memset(c->wbuf,0xff,c->wbuf_pagesize);
512 /* adjust write buffer offset, else we get a non contiguous write bug */
513 c->wbuf_ofs += c->wbuf_pagesize;
514 c->wbuf_len = 0;
515 return 0;
516}
517
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000518/* Trigger garbage collection to flush the write-buffer.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 If ino arg is zero, do it if _any_ real (i.e. not GC) writes are
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000520 outstanding. If ino arg non-zero, do it only if a write for the
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 given inode is outstanding. */
522int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino)
523{
524 uint32_t old_wbuf_ofs;
525 uint32_t old_wbuf_len;
526 int ret = 0;
527
528 D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() called for ino #%u...\n", ino));
529
David Woodhouse8aee6ac2005-02-02 22:12:08 +0000530 if (!c->wbuf)
531 return 0;
532
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 down(&c->alloc_sem);
534 if (!jffs2_wbuf_pending_for_ino(c, ino)) {
535 D1(printk(KERN_DEBUG "Ino #%d not pending in wbuf. Returning\n", ino));
536 up(&c->alloc_sem);
537 return 0;
538 }
539
540 old_wbuf_ofs = c->wbuf_ofs;
541 old_wbuf_len = c->wbuf_len;
542
543 if (c->unchecked_size) {
544 /* GC won't make any progress for a while */
545 D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() padding. Not finished checking\n"));
546 down_write(&c->wbuf_sem);
547 ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING);
Estelle Hammache7f716cf2005-01-24 21:24:18 +0000548 /* retry flushing wbuf in case jffs2_wbuf_recover
549 left some data in the wbuf */
550 if (ret)
Estelle Hammache7f716cf2005-01-24 21:24:18 +0000551 ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 up_write(&c->wbuf_sem);
553 } else while (old_wbuf_len &&
554 old_wbuf_ofs == c->wbuf_ofs) {
555
556 up(&c->alloc_sem);
557
558 D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() calls gc pass\n"));
559
560 ret = jffs2_garbage_collect_pass(c);
561 if (ret) {
562 /* GC failed. Flush it with padding instead */
563 down(&c->alloc_sem);
564 down_write(&c->wbuf_sem);
565 ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING);
Estelle Hammache7f716cf2005-01-24 21:24:18 +0000566 /* retry flushing wbuf in case jffs2_wbuf_recover
567 left some data in the wbuf */
568 if (ret)
Estelle Hammache7f716cf2005-01-24 21:24:18 +0000569 ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 up_write(&c->wbuf_sem);
571 break;
572 }
573 down(&c->alloc_sem);
574 }
575
576 D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() ends...\n"));
577
578 up(&c->alloc_sem);
579 return ret;
580}
581
582/* Pad write-buffer to end and write it, wasting space. */
583int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c)
584{
585 int ret;
586
David Woodhouse8aee6ac2005-02-02 22:12:08 +0000587 if (!c->wbuf)
588 return 0;
589
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 down_write(&c->wbuf_sem);
591 ret = __jffs2_flush_wbuf(c, PAD_NOACCOUNT);
Estelle Hammache7f716cf2005-01-24 21:24:18 +0000592 /* retry - maybe wbuf recover left some data in wbuf. */
593 if (ret)
594 ret = __jffs2_flush_wbuf(c, PAD_NOACCOUNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 up_write(&c->wbuf_sem);
596
597 return ret;
598}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599
Thomas Gleixnerdcb09322006-05-23 11:49:14 +0200600static size_t jffs2_fill_wbuf(struct jffs2_sb_info *c, const uint8_t *buf,
601 size_t len)
602{
603 if (len && !c->wbuf_len && (len >= c->wbuf_pagesize))
604 return 0;
605
606 if (len > (c->wbuf_pagesize - c->wbuf_len))
607 len = c->wbuf_pagesize - c->wbuf_len;
608 memcpy(c->wbuf + c->wbuf_len, buf, len);
609 c->wbuf_len += (uint32_t) len;
610 return len;
611}
612
613int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs,
614 unsigned long count, loff_t to, size_t *retlen,
615 uint32_t ino)
616{
617 struct jffs2_eraseblock *jeb;
618 size_t wbuf_retlen, donelen = 0;
619 uint32_t outvec_to = to;
620 int ret, invec;
621
622 /* If not writebuffered flash, don't bother */
Andrew Victor3be36672005-02-09 09:09:05 +0000623 if (!jffs2_is_writebuffered(c))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 return jffs2_flash_direct_writev(c, invecs, count, to, retlen);
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000625
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 down_write(&c->wbuf_sem);
627
628 /* If wbuf_ofs is not initialized, set it to target address */
629 if (c->wbuf_ofs == 0xFFFFFFFF) {
630 c->wbuf_ofs = PAGE_DIV(to);
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000631 c->wbuf_len = PAGE_MOD(to);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 memset(c->wbuf,0xff,c->wbuf_pagesize);
633 }
634
Thomas Gleixnerdcb09322006-05-23 11:49:14 +0200635 /*
Thomas Gleixnerdcb09322006-05-23 11:49:14 +0200636 * Sanity checks on target address. It's permitted to write
637 * at PAD(c->wbuf_len+c->wbuf_ofs), and it's permitted to
638 * write at the beginning of a new erase block. Anything else,
639 * and you die. New block starts at xxx000c (0-b = block
640 * header)
641 */
Andrew Victor3be36672005-02-09 09:09:05 +0000642 if (SECTOR_ADDR(to) != SECTOR_ADDR(c->wbuf_ofs)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 /* It's a write to a new block */
644 if (c->wbuf_len) {
Thomas Gleixnerdcb09322006-05-23 11:49:14 +0200645 D1(printk(KERN_DEBUG "jffs2_flash_writev() to 0x%lx "
646 "causes flush of wbuf at 0x%08x\n",
647 (unsigned long)to, c->wbuf_ofs));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 ret = __jffs2_flush_wbuf(c, PAD_NOACCOUNT);
Thomas Gleixnerdcb09322006-05-23 11:49:14 +0200649 if (ret)
650 goto outerr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 }
652 /* set pointer to new block */
653 c->wbuf_ofs = PAGE_DIV(to);
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000654 c->wbuf_len = PAGE_MOD(to);
655 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656
657 if (to != PAD(c->wbuf_ofs + c->wbuf_len)) {
658 /* We're not writing immediately after the writebuffer. Bad. */
Thomas Gleixnerdcb09322006-05-23 11:49:14 +0200659 printk(KERN_CRIT "jffs2_flash_writev(): Non-contiguous write "
660 "to %08lx\n", (unsigned long)to);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 if (c->wbuf_len)
662 printk(KERN_CRIT "wbuf was previously %08x-%08x\n",
Thomas Gleixnerdcb09322006-05-23 11:49:14 +0200663 c->wbuf_ofs, c->wbuf_ofs+c->wbuf_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 BUG();
665 }
666
Thomas Gleixnerdcb09322006-05-23 11:49:14 +0200667 /* adjust alignment offset */
668 if (c->wbuf_len != PAGE_MOD(to)) {
669 c->wbuf_len = PAGE_MOD(to);
670 /* take care of alignment to next page */
671 if (!c->wbuf_len) {
672 c->wbuf_len = c->wbuf_pagesize;
673 ret = __jffs2_flush_wbuf(c, NOPAD);
674 if (ret)
675 goto outerr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 }
677 }
678
Thomas Gleixnerdcb09322006-05-23 11:49:14 +0200679 for (invec = 0; invec < count; invec++) {
680 int vlen = invecs[invec].iov_len;
681 uint8_t *v = invecs[invec].iov_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682
Thomas Gleixnerdcb09322006-05-23 11:49:14 +0200683 wbuf_retlen = jffs2_fill_wbuf(c, v, vlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684
Thomas Gleixnerdcb09322006-05-23 11:49:14 +0200685 if (c->wbuf_len == c->wbuf_pagesize) {
686 ret = __jffs2_flush_wbuf(c, NOPAD);
687 if (ret)
688 goto outerr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 }
Thomas Gleixnerdcb09322006-05-23 11:49:14 +0200690 vlen -= wbuf_retlen;
691 outvec_to += wbuf_retlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 donelen += wbuf_retlen;
Thomas Gleixnerdcb09322006-05-23 11:49:14 +0200693 v += wbuf_retlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694
Thomas Gleixnerdcb09322006-05-23 11:49:14 +0200695 if (vlen >= c->wbuf_pagesize) {
696 ret = c->mtd->write(c->mtd, outvec_to, PAGE_DIV(vlen),
697 &wbuf_retlen, v);
698 if (ret < 0 || wbuf_retlen != PAGE_DIV(vlen))
699 goto outfile;
700
701 vlen -= wbuf_retlen;
702 outvec_to += wbuf_retlen;
703 c->wbuf_ofs = outvec_to;
704 donelen += wbuf_retlen;
705 v += wbuf_retlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 }
707
Thomas Gleixnerdcb09322006-05-23 11:49:14 +0200708 wbuf_retlen = jffs2_fill_wbuf(c, v, vlen);
709 if (c->wbuf_len == c->wbuf_pagesize) {
710 ret = __jffs2_flush_wbuf(c, NOPAD);
711 if (ret)
712 goto outerr;
713 }
714
715 outvec_to += wbuf_retlen;
716 donelen += wbuf_retlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 }
718
Thomas Gleixnerdcb09322006-05-23 11:49:14 +0200719 /*
720 * If there's a remainder in the wbuf and it's a non-GC write,
721 * remember that the wbuf affects this ino
722 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 *retlen = donelen;
724
Ferenc Havasie631ddb2005-09-07 09:35:26 +0100725 if (jffs2_sum_active()) {
726 int res = jffs2_sum_add_kvec(c, invecs, count, (uint32_t) to);
727 if (res)
728 return res;
729 }
730
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 if (c->wbuf_len && ino)
732 jffs2_wbuf_dirties_inode(c, ino);
733
734 ret = 0;
Thomas Gleixnerdcb09322006-05-23 11:49:14 +0200735 up_write(&c->wbuf_sem);
736 return ret;
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000737
Thomas Gleixnerdcb09322006-05-23 11:49:14 +0200738outfile:
739 /*
740 * At this point we have no problem, c->wbuf is empty. However
741 * refile nextblock to avoid writing again to same address.
742 */
743
744 spin_lock(&c->erase_completion_lock);
745
746 jeb = &c->blocks[outvec_to / c->sector_size];
747 jffs2_block_refile(c, jeb, REFILE_ANYWAY);
748
749 spin_unlock(&c->erase_completion_lock);
750
751outerr:
752 *retlen = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 up_write(&c->wbuf_sem);
754 return ret;
755}
756
757/*
758 * This is the entry for flash write.
759 * Check, if we work on NAND FLASH, if so build an kvec and write it via vritev
760*/
761int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, const u_char *buf)
762{
763 struct kvec vecs[1];
764
Andrew Victor3be36672005-02-09 09:09:05 +0000765 if (!jffs2_is_writebuffered(c))
Ferenc Havasie631ddb2005-09-07 09:35:26 +0100766 return jffs2_flash_direct_write(c, ofs, len, retlen, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767
768 vecs[0].iov_base = (unsigned char *) buf;
769 vecs[0].iov_len = len;
770 return jffs2_flash_writev(c, vecs, 1, ofs, retlen, 0);
771}
772
773/*
774 Handle readback from writebuffer and ECC failure return
775*/
776int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, u_char *buf)
777{
778 loff_t orbf = 0, owbf = 0, lwbf = 0;
779 int ret;
780
Andrew Victor3be36672005-02-09 09:09:05 +0000781 if (!jffs2_is_writebuffered(c))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 return c->mtd->read(c->mtd, ofs, len, retlen, buf);
783
Andrew Victor3be36672005-02-09 09:09:05 +0000784 /* Read flash */
Artem B. Bityuckiy894214d2005-04-05 13:51:58 +0100785 down_read(&c->wbuf_sem);
Thomas Gleixner9223a452006-05-23 17:21:03 +0200786 ret = c->mtd->read(c->mtd, ofs, len, retlen, buf);
Andrew Victor3be36672005-02-09 09:09:05 +0000787
788 if ( (ret == -EBADMSG) && (*retlen == len) ) {
789 printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx) returned ECC error\n",
790 len, ofs);
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000791 /*
792 * We have the raw data without ECC correction in the buffer, maybe
Andrew Victor3be36672005-02-09 09:09:05 +0000793 * we are lucky and all data or parts are correct. We check the node.
794 * If data are corrupted node check will sort it out.
795 * We keep this block, it will fail on write or erase and the we
796 * mark it bad. Or should we do that now? But we should give him a chance.
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000797 * Maybe we had a system crash or power loss before the ecc write or
Andrew Victor3be36672005-02-09 09:09:05 +0000798 * a erase was completed.
799 * So we return success. :)
800 */
801 ret = 0;
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000802 }
Andrew Victor3be36672005-02-09 09:09:05 +0000803
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 /* if no writebuffer available or write buffer empty, return */
805 if (!c->wbuf_pagesize || !c->wbuf_len)
Artem B. Bityuckiy894214d2005-04-05 13:51:58 +0100806 goto exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807
808 /* if we read in a different block, return */
Andrew Victor3be36672005-02-09 09:09:05 +0000809 if (SECTOR_ADDR(ofs) != SECTOR_ADDR(c->wbuf_ofs))
Artem B. Bityuckiy894214d2005-04-05 13:51:58 +0100810 goto exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811
812 if (ofs >= c->wbuf_ofs) {
813 owbf = (ofs - c->wbuf_ofs); /* offset in write buffer */
814 if (owbf > c->wbuf_len) /* is read beyond write buffer ? */
815 goto exit;
816 lwbf = c->wbuf_len - owbf; /* number of bytes to copy */
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000817 if (lwbf > len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 lwbf = len;
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000819 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 orbf = (c->wbuf_ofs - ofs); /* offset in read buffer */
821 if (orbf > len) /* is write beyond write buffer ? */
822 goto exit;
823 lwbf = len - orbf; /* number of bytes to copy */
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000824 if (lwbf > c->wbuf_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 lwbf = c->wbuf_len;
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000826 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 if (lwbf > 0)
828 memcpy(buf+orbf,c->wbuf+owbf,lwbf);
829
830exit:
831 up_read(&c->wbuf_sem);
832 return ret;
833}
834
835/*
836 * Check, if the out of band area is empty
837 */
838int jffs2_check_oob_empty( struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, int mode)
839{
840 unsigned char *buf;
841 int ret = 0;
842 int i,len,page;
843 size_t retlen;
844 int oob_size;
845
846 /* allocate a buffer for all oob data in this sector */
847 oob_size = c->mtd->oobsize;
848 len = 4 * oob_size;
849 buf = kmalloc(len, GFP_KERNEL);
850 if (!buf) {
851 printk(KERN_NOTICE "jffs2_check_oob_empty(): allocation of temporary data buffer for oob check failed\n");
852 return -ENOMEM;
853 }
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000854 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 * if mode = 0, we scan for a total empty oob area, else we have
856 * to take care of the cleanmarker in the first page of the block
857 */
858 ret = jffs2_flash_read_oob(c, jeb->offset, len , &retlen, buf);
859 if (ret) {
860 D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB failed %d for block at %08x\n", ret, jeb->offset));
861 goto out;
862 }
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000863
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 if (retlen < len) {
865 D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB return short read "
866 "(%zd bytes not %d) for block at %08x\n", retlen, len, jeb->offset));
867 ret = -EIO;
868 goto out;
869 }
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000870
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 /* Special check for first page */
872 for(i = 0; i < oob_size ; i++) {
873 /* Yeah, we know about the cleanmarker. */
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000874 if (mode && i >= c->fsdata_pos &&
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 i < c->fsdata_pos + c->fsdata_len)
876 continue;
877
878 if (buf[i] != 0xFF) {
879 D2(printk(KERN_DEBUG "Found %02x at %x in OOB for %08x\n",
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100880 buf[i], i, jeb->offset));
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000881 ret = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 goto out;
883 }
884 }
885
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000886 /* we know, we are aligned :) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 for (page = oob_size; page < len; page += sizeof(long)) {
888 unsigned long dat = *(unsigned long *)(&buf[page]);
889 if(dat != -1) {
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000890 ret = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 goto out;
892 }
893 }
894
895out:
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000896 kfree(buf);
897
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 return ret;
899}
900
901/*
902* Scan for a valid cleanmarker and for bad blocks
903* For virtual blocks (concatenated physical blocks) check the cleanmarker
904* only in the first page of the first physical block, but scan for bad blocks in all
905* physical blocks
906*/
907int jffs2_check_nand_cleanmarker (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
908{
909 struct jffs2_unknown_node n;
910 unsigned char buf[2 * NAND_MAX_OOBSIZE];
911 unsigned char *p;
912 int ret, i, cnt, retval = 0;
913 size_t retlen, offset;
914 int oob_size;
915
916 offset = jeb->offset;
917 oob_size = c->mtd->oobsize;
918
919 /* Loop through the physical blocks */
920 for (cnt = 0; cnt < (c->sector_size / c->mtd->erasesize); cnt++) {
921 /* Check first if the block is bad. */
922 if (c->mtd->block_isbad (c->mtd, offset)) {
923 D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Bad block at %08x\n", jeb->offset));
924 return 2;
925 }
926 /*
927 * We read oob data from page 0 and 1 of the block.
928 * page 0 contains cleanmarker and badblock info
929 * page 1 contains failure count of this block
930 */
931 ret = c->mtd->read_oob (c->mtd, offset, oob_size << 1, &retlen, buf);
932
933 if (ret) {
934 D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Read OOB failed %d for block at %08x\n", ret, jeb->offset));
935 return ret;
936 }
937 if (retlen < (oob_size << 1)) {
938 D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Read OOB return short read (%zd bytes not %d) for block at %08x\n", retlen, oob_size << 1, jeb->offset));
939 return -EIO;
940 }
941
942 /* Check cleanmarker only on the first physical block */
943 if (!cnt) {
944 n.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
945 n.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
946 n.totlen = cpu_to_je32 (8);
947 p = (unsigned char *) &n;
948
949 for (i = 0; i < c->fsdata_len; i++) {
950 if (buf[c->fsdata_pos + i] != p[i]) {
951 retval = 1;
952 }
953 }
954 D1(if (retval == 1) {
955 printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): Cleanmarker node not detected in block at %08x\n", jeb->offset);
956 printk(KERN_WARNING "OOB at %08x was ", offset);
957 for (i=0; i < oob_size; i++) {
958 printk("%02x ", buf[i]);
959 }
960 printk("\n");
961 })
962 }
963 offset += c->mtd->erasesize;
964 }
965 return retval;
966}
967
968int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
969{
970 struct jffs2_unknown_node n;
971 int ret;
972 size_t retlen;
973
974 n.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
975 n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
976 n.totlen = cpu_to_je32(8);
977
978 ret = jffs2_flash_write_oob(c, jeb->offset + c->fsdata_pos, c->fsdata_len, &retlen, (unsigned char *)&n);
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000979
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 if (ret) {
981 D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Write failed for block at %08x: error %d\n", jeb->offset, ret));
982 return ret;
983 }
984 if (retlen != c->fsdata_len) {
985 D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Short write for block at %08x: %zd not %d\n", jeb->offset, retlen, c->fsdata_len));
986 return ret;
987 }
988 return 0;
989}
990
Thomas Gleixner182ec4e2005-11-07 11:16:07 +0000991/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 * On NAND we try to mark this block bad. If the block was erased more
993 * than MAX_ERASE_FAILURES we mark it finaly bad.
994 * Don't care about failures. This block remains on the erase-pending
995 * or badblock list as long as nobody manipulates the flash with
996 * a bootloader or something like that.
997 */
998
999int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t bad_offset)
1000{
1001 int ret;
1002
1003 /* if the count is < max, we try to write the counter to the 2nd page oob area */
1004 if( ++jeb->bad_count < MAX_ERASE_FAILURES)
1005 return 0;
1006
1007 if (!c->mtd->block_markbad)
1008 return 1; // What else can we do?
1009
1010 D1(printk(KERN_WARNING "jffs2_write_nand_badblock(): Marking bad block at %08x\n", bad_offset));
1011 ret = c->mtd->block_markbad(c->mtd, bad_offset);
Thomas Gleixner182ec4e2005-11-07 11:16:07 +00001012
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 if (ret) {
1014 D1(printk(KERN_WARNING "jffs2_write_nand_badblock(): Write failed for block at %08x: error %d\n", jeb->offset, ret));
1015 return ret;
1016 }
1017 return 1;
1018}
1019
1020#define NAND_JFFS2_OOB16_FSDALEN 8
1021
1022static struct nand_oobinfo jffs2_oobinfo_docecc = {
1023 .useecc = MTD_NANDECC_PLACE,
1024 .eccbytes = 6,
1025 .eccpos = {0,1,2,3,4,5}
1026};
1027
1028
1029static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c)
1030{
1031 struct nand_oobinfo *oinfo = &c->mtd->oobinfo;
1032
1033 /* Do this only, if we have an oob buffer */
1034 if (!c->mtd->oobsize)
1035 return 0;
Thomas Gleixner182ec4e2005-11-07 11:16:07 +00001036
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 /* Cleanmarker is out-of-band, so inline size zero */
1038 c->cleanmarker_size = 0;
1039
1040 /* Should we use autoplacement ? */
1041 if (oinfo && oinfo->useecc == MTD_NANDECC_AUTOPLACE) {
1042 D1(printk(KERN_DEBUG "JFFS2 using autoplace on NAND\n"));
1043 /* Get the position of the free bytes */
1044 if (!oinfo->oobfree[0][1]) {
1045 printk (KERN_WARNING "jffs2_nand_set_oobinfo(): Eeep. Autoplacement selected and no empty space in oob\n");
1046 return -ENOSPC;
1047 }
1048 c->fsdata_pos = oinfo->oobfree[0][0];
1049 c->fsdata_len = oinfo->oobfree[0][1];
1050 if (c->fsdata_len > 8)
1051 c->fsdata_len = 8;
1052 } else {
1053 /* This is just a legacy fallback and should go away soon */
1054 switch(c->mtd->ecctype) {
1055 case MTD_ECC_RS_DiskOnChip:
1056 printk(KERN_WARNING "JFFS2 using DiskOnChip hardware ECC without autoplacement. Fix it!\n");
1057 c->oobinfo = &jffs2_oobinfo_docecc;
1058 c->fsdata_pos = 6;
1059 c->fsdata_len = NAND_JFFS2_OOB16_FSDALEN;
1060 c->badblock_pos = 15;
1061 break;
Thomas Gleixner182ec4e2005-11-07 11:16:07 +00001062
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 default:
1064 D1(printk(KERN_DEBUG "JFFS2 on NAND. No autoplacment info found\n"));
1065 return -EINVAL;
1066 }
1067 }
1068 return 0;
1069}
1070
1071int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
1072{
1073 int res;
1074
1075 /* Initialise write buffer */
1076 init_rwsem(&c->wbuf_sem);
Joern Engel28318772006-05-22 23:18:05 +02001077 c->wbuf_pagesize = c->mtd->writesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 c->wbuf_ofs = 0xFFFFFFFF;
Thomas Gleixner182ec4e2005-11-07 11:16:07 +00001079
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
1081 if (!c->wbuf)
1082 return -ENOMEM;
1083
1084 res = jffs2_nand_set_oobinfo(c);
1085
1086#ifdef BREAKME
1087 if (!brokenbuf)
1088 brokenbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
1089 if (!brokenbuf) {
1090 kfree(c->wbuf);
1091 return -ENOMEM;
1092 }
1093 memset(brokenbuf, 0xdb, c->wbuf_pagesize);
1094#endif
1095 return res;
1096}
1097
1098void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c)
1099{
1100 kfree(c->wbuf);
1101}
1102
Andrew Victor8f15fd52005-02-09 09:17:45 +00001103int jffs2_dataflash_setup(struct jffs2_sb_info *c) {
1104 c->cleanmarker_size = 0; /* No cleanmarkers needed */
Thomas Gleixner182ec4e2005-11-07 11:16:07 +00001105
Andrew Victor8f15fd52005-02-09 09:17:45 +00001106 /* Initialize write buffer */
1107 init_rwsem(&c->wbuf_sem);
Andrew Victor8f15fd52005-02-09 09:17:45 +00001108
Thomas Gleixner182ec4e2005-11-07 11:16:07 +00001109
Artem B. Bityutskiydaba5cc2005-09-30 14:59:17 +01001110 c->wbuf_pagesize = c->mtd->erasesize;
Thomas Gleixner182ec4e2005-11-07 11:16:07 +00001111
Artem B. Bityutskiydaba5cc2005-09-30 14:59:17 +01001112 /* Find a suitable c->sector_size
1113 * - Not too much sectors
1114 * - Sectors have to be at least 4 K + some bytes
1115 * - All known dataflashes have erase sizes of 528 or 1056
1116 * - we take at least 8 eraseblocks and want to have at least 8K size
1117 * - The concatenation should be a power of 2
1118 */
Andrew Victor8f15fd52005-02-09 09:17:45 +00001119
Artem B. Bityutskiydaba5cc2005-09-30 14:59:17 +01001120 c->sector_size = 8 * c->mtd->erasesize;
Thomas Gleixner182ec4e2005-11-07 11:16:07 +00001121
Artem B. Bityutskiydaba5cc2005-09-30 14:59:17 +01001122 while (c->sector_size < 8192) {
1123 c->sector_size *= 2;
1124 }
Thomas Gleixner182ec4e2005-11-07 11:16:07 +00001125
Artem B. Bityutskiydaba5cc2005-09-30 14:59:17 +01001126 /* It may be necessary to adjust the flash size */
1127 c->flash_size = c->mtd->size;
1128
1129 if ((c->flash_size % c->sector_size) != 0) {
1130 c->flash_size = (c->flash_size / c->sector_size) * c->sector_size;
1131 printk(KERN_WARNING "JFFS2 flash size adjusted to %dKiB\n", c->flash_size);
1132 };
Thomas Gleixner182ec4e2005-11-07 11:16:07 +00001133
Artem B. Bityutskiydaba5cc2005-09-30 14:59:17 +01001134 c->wbuf_ofs = 0xFFFFFFFF;
Andrew Victor8f15fd52005-02-09 09:17:45 +00001135 c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
1136 if (!c->wbuf)
1137 return -ENOMEM;
1138
Artem B. Bityutskiydaba5cc2005-09-30 14:59:17 +01001139 printk(KERN_INFO "JFFS2 write-buffering enabled buffer (%d) erasesize (%d)\n", c->wbuf_pagesize, c->sector_size);
Andrew Victor8f15fd52005-02-09 09:17:45 +00001140
1141 return 0;
1142}
1143
1144void jffs2_dataflash_cleanup(struct jffs2_sb_info *c) {
1145 kfree(c->wbuf);
1146}
Andrew Victor8f15fd52005-02-09 09:17:45 +00001147
Nicolas Pitre59da7212005-08-06 05:51:33 +01001148int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c) {
Joern Engelc8b229d2006-05-22 23:18:12 +02001149 /* Cleanmarker currently occupies whole programming regions,
1150 * either one or 2 for 8Byte STMicro flashes. */
1151 c->cleanmarker_size = max(16u, c->mtd->writesize);
Nicolas Pitre59da7212005-08-06 05:51:33 +01001152
1153 /* Initialize write buffer */
1154 init_rwsem(&c->wbuf_sem);
Joern Engel28318772006-05-22 23:18:05 +02001155 c->wbuf_pagesize = c->mtd->writesize;
Nicolas Pitre59da7212005-08-06 05:51:33 +01001156 c->wbuf_ofs = 0xFFFFFFFF;
1157
1158 c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
1159 if (!c->wbuf)
1160 return -ENOMEM;
1161
1162 return 0;
1163}
1164
1165void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c) {
1166 kfree(c->wbuf);
1167}