mtd: tests: stresstest: bail out if device has not enough eraseblocks
[pandora-kernel.git] / drivers / mtd / nftlcore.c
1 /*
2  * Linux driver for NAND Flash Translation Layer
3  *
4  * Copyright © 1999 Machine Vision Holdings, Inc.
5  * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #define PRERELEASE
23
24 #include <linux/kernel.h>
25 #include <linux/module.h>
26 #include <asm/errno.h>
27 #include <asm/io.h>
28 #include <asm/uaccess.h>
29 #include <linux/delay.h>
30 #include <linux/slab.h>
31 #include <linux/init.h>
32 #include <linux/hdreg.h>
33 #include <linux/blkdev.h>
34
35 #include <linux/kmod.h>
36 #include <linux/mtd/mtd.h>
37 #include <linux/mtd/nand.h>
38 #include <linux/mtd/nftl.h>
39 #include <linux/mtd/blktrans.h>
40
41 /* maximum number of loops while examining next block, to have a
42    chance to detect consistency problems (they should never happen
43    because of the checks done in the mounting */
44
45 #define MAX_LOOPS 10000
46
47
48 static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
49 {
50         struct NFTLrecord *nftl;
51         unsigned long temp;
52
53         if (mtd->type != MTD_NANDFLASH || mtd->size > UINT_MAX)
54                 return;
55         /* OK, this is moderately ugly.  But probably safe.  Alternatives? */
56         if (memcmp(mtd->name, "DiskOnChip", 10))
57                 return;
58
59         if (!mtd->block_isbad) {
60                 printk(KERN_ERR
61 "NFTL no longer supports the old DiskOnChip drivers loaded via docprobe.\n"
62 "Please use the new diskonchip driver under the NAND subsystem.\n");
63                 return;
64         }
65
66         pr_debug("NFTL: add_mtd for %s\n", mtd->name);
67
68         nftl = kzalloc(sizeof(struct NFTLrecord), GFP_KERNEL);
69
70         if (!nftl)
71                 return;
72
73         nftl->mbd.mtd = mtd;
74         nftl->mbd.devnum = -1;
75
76         nftl->mbd.tr = tr;
77
78         if (NFTL_mount(nftl) < 0) {
79                 printk(KERN_WARNING "NFTL: could not mount device\n");
80                 kfree(nftl);
81                 return;
82         }
83
84         /* OK, it's a new one. Set up all the data structures. */
85
86         /* Calculate geometry */
87         nftl->cylinders = 1024;
88         nftl->heads = 16;
89
90         temp = nftl->cylinders * nftl->heads;
91         nftl->sectors = nftl->mbd.size / temp;
92         if (nftl->mbd.size % temp) {
93                 nftl->sectors++;
94                 temp = nftl->cylinders * nftl->sectors;
95                 nftl->heads = nftl->mbd.size / temp;
96
97                 if (nftl->mbd.size % temp) {
98                         nftl->heads++;
99                         temp = nftl->heads * nftl->sectors;
100                         nftl->cylinders = nftl->mbd.size / temp;
101                 }
102         }
103
104         if (nftl->mbd.size != nftl->heads * nftl->cylinders * nftl->sectors) {
105                 /*
106                   Oh no we don't have
107                    mbd.size == heads * cylinders * sectors
108                 */
109                 printk(KERN_WARNING "NFTL: cannot calculate a geometry to "
110                        "match size of 0x%lx.\n", nftl->mbd.size);
111                 printk(KERN_WARNING "NFTL: using C:%d H:%d S:%d "
112                         "(== 0x%lx sects)\n",
113                         nftl->cylinders, nftl->heads , nftl->sectors,
114                         (long)nftl->cylinders * (long)nftl->heads *
115                         (long)nftl->sectors );
116         }
117
118         if (add_mtd_blktrans_dev(&nftl->mbd)) {
119                 kfree(nftl->ReplUnitTable);
120                 kfree(nftl->EUNtable);
121                 kfree(nftl);
122                 return;
123         }
124 #ifdef PSYCHO_DEBUG
125         printk(KERN_INFO "NFTL: Found new nftl%c\n", nftl->mbd.devnum + 'a');
126 #endif
127 }
128
129 static void nftl_remove_dev(struct mtd_blktrans_dev *dev)
130 {
131         struct NFTLrecord *nftl = (void *)dev;
132
133         pr_debug("NFTL: remove_dev (i=%d)\n", dev->devnum);
134
135         del_mtd_blktrans_dev(dev);
136         kfree(nftl->ReplUnitTable);
137         kfree(nftl->EUNtable);
138 }
139
140 /*
141  * Read oob data from flash
142  */
143 int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
144                   size_t *retlen, uint8_t *buf)
145 {
146         loff_t mask = mtd->writesize - 1;
147         struct mtd_oob_ops ops;
148         int res;
149
150         ops.mode = MTD_OPS_PLACE_OOB;
151         ops.ooboffs = offs & mask;
152         ops.ooblen = len;
153         ops.oobbuf = buf;
154         ops.datbuf = NULL;
155
156         res = mtd->read_oob(mtd, offs & ~mask, &ops);
157         *retlen = ops.oobretlen;
158         return res;
159 }
160
161 /*
162  * Write oob data to flash
163  */
164 int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
165                    size_t *retlen, uint8_t *buf)
166 {
167         loff_t mask = mtd->writesize - 1;
168         struct mtd_oob_ops ops;
169         int res;
170
171         ops.mode = MTD_OPS_PLACE_OOB;
172         ops.ooboffs = offs & mask;
173         ops.ooblen = len;
174         ops.oobbuf = buf;
175         ops.datbuf = NULL;
176
177         res = mtd->write_oob(mtd, offs & ~mask, &ops);
178         *retlen = ops.oobretlen;
179         return res;
180 }
181
182 #ifdef CONFIG_NFTL_RW
183
184 /*
185  * Write data and oob to flash
186  */
187 static int nftl_write(struct mtd_info *mtd, loff_t offs, size_t len,
188                       size_t *retlen, uint8_t *buf, uint8_t *oob)
189 {
190         loff_t mask = mtd->writesize - 1;
191         struct mtd_oob_ops ops;
192         int res;
193
194         ops.mode = MTD_OPS_PLACE_OOB;
195         ops.ooboffs = offs & mask;
196         ops.ooblen = mtd->oobsize;
197         ops.oobbuf = oob;
198         ops.datbuf = buf;
199         ops.len = len;
200
201         res = mtd->write_oob(mtd, offs & ~mask, &ops);
202         *retlen = ops.retlen;
203         return res;
204 }
205
206 /* Actual NFTL access routines */
207 /* NFTL_findfreeblock: Find a free Erase Unit on the NFTL partition. This function is used
208  *      when the give Virtual Unit Chain
209  */
210 static u16 NFTL_findfreeblock(struct NFTLrecord *nftl, int desperate )
211 {
212         /* For a given Virtual Unit Chain: find or create a free block and
213            add it to the chain */
214         /* We're passed the number of the last EUN in the chain, to save us from
215            having to look it up again */
216         u16 pot = nftl->LastFreeEUN;
217         int silly = nftl->nb_blocks;
218
219         /* Normally, we force a fold to happen before we run out of free blocks completely */
220         if (!desperate && nftl->numfreeEUNs < 2) {
221                 pr_debug("NFTL_findfreeblock: there are too few free EUNs\n");
222                 return BLOCK_NIL;
223         }
224
225         /* Scan for a free block */
226         do {
227                 if (nftl->ReplUnitTable[pot] == BLOCK_FREE) {
228                         nftl->LastFreeEUN = pot;
229                         nftl->numfreeEUNs--;
230                         return pot;
231                 }
232
233                 /* This will probably point to the MediaHdr unit itself,
234                    right at the beginning of the partition. But that unit
235                    (and the backup unit too) should have the UCI set
236                    up so that it's not selected for overwriting */
237                 if (++pot > nftl->lastEUN)
238                         pot = le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN);
239
240                 if (!silly--) {
241                         printk("Argh! No free blocks found! LastFreeEUN = %d, "
242                                "FirstEUN = %d\n", nftl->LastFreeEUN,
243                                le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN));
244                         return BLOCK_NIL;
245                 }
246         } while (pot != nftl->LastFreeEUN);
247
248         return BLOCK_NIL;
249 }
250
251 static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned pendingblock )
252 {
253         struct mtd_info *mtd = nftl->mbd.mtd;
254         u16 BlockMap[MAX_SECTORS_PER_UNIT];
255         unsigned char BlockLastState[MAX_SECTORS_PER_UNIT];
256         unsigned char BlockFreeFound[MAX_SECTORS_PER_UNIT];
257         unsigned int thisEUN;
258         int block;
259         int silly;
260         unsigned int targetEUN;
261         struct nftl_oob oob;
262         int inplace = 1;
263         size_t retlen;
264
265         memset(BlockMap, 0xff, sizeof(BlockMap));
266         memset(BlockFreeFound, 0, sizeof(BlockFreeFound));
267
268         thisEUN = nftl->EUNtable[thisVUC];
269
270         if (thisEUN == BLOCK_NIL) {
271                 printk(KERN_WARNING "Trying to fold non-existent "
272                        "Virtual Unit Chain %d!\n", thisVUC);
273                 return BLOCK_NIL;
274         }
275
276         /* Scan to find the Erase Unit which holds the actual data for each
277            512-byte block within the Chain.
278         */
279         silly = MAX_LOOPS;
280         targetEUN = BLOCK_NIL;
281         while (thisEUN <= nftl->lastEUN ) {
282                 unsigned int status, foldmark;
283
284                 targetEUN = thisEUN;
285                 for (block = 0; block < nftl->EraseSize / 512; block ++) {
286                         nftl_read_oob(mtd, (thisEUN * nftl->EraseSize) +
287                                       (block * 512), 16 , &retlen,
288                                       (char *)&oob);
289                         if (block == 2) {
290                                 foldmark = oob.u.c.FoldMark | oob.u.c.FoldMark1;
291                                 if (foldmark == FOLD_MARK_IN_PROGRESS) {
292                                         pr_debug("Write Inhibited on EUN %d\n", thisEUN);
293                                         inplace = 0;
294                                 } else {
295                                         /* There's no other reason not to do inplace,
296                                            except ones that come later. So we don't need
297                                            to preserve inplace */
298                                         inplace = 1;
299                                 }
300                         }
301                         status = oob.b.Status | oob.b.Status1;
302                         BlockLastState[block] = status;
303
304                         switch(status) {
305                         case SECTOR_FREE:
306                                 BlockFreeFound[block] = 1;
307                                 break;
308
309                         case SECTOR_USED:
310                                 if (!BlockFreeFound[block])
311                                         BlockMap[block] = thisEUN;
312                                 else
313                                         printk(KERN_WARNING
314                                                "SECTOR_USED found after SECTOR_FREE "
315                                                "in Virtual Unit Chain %d for block %d\n",
316                                                thisVUC, block);
317                                 break;
318                         case SECTOR_DELETED:
319                                 if (!BlockFreeFound[block])
320                                         BlockMap[block] = BLOCK_NIL;
321                                 else
322                                         printk(KERN_WARNING
323                                                "SECTOR_DELETED found after SECTOR_FREE "
324                                                "in Virtual Unit Chain %d for block %d\n",
325                                                thisVUC, block);
326                                 break;
327
328                         case SECTOR_IGNORE:
329                                 break;
330                         default:
331                                 printk("Unknown status for block %d in EUN %d: %x\n",
332                                        block, thisEUN, status);
333                         }
334                 }
335
336                 if (!silly--) {
337                         printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n",
338                                thisVUC);
339                         return BLOCK_NIL;
340                 }
341
342                 thisEUN = nftl->ReplUnitTable[thisEUN];
343         }
344
345         if (inplace) {
346                 /* We're being asked to be a fold-in-place. Check
347                    that all blocks which actually have data associated
348                    with them (i.e. BlockMap[block] != BLOCK_NIL) are
349                    either already present or SECTOR_FREE in the target
350                    block. If not, we're going to have to fold out-of-place
351                    anyway.
352                 */
353                 for (block = 0; block < nftl->EraseSize / 512 ; block++) {
354                         if (BlockLastState[block] != SECTOR_FREE &&
355                             BlockMap[block] != BLOCK_NIL &&
356                             BlockMap[block] != targetEUN) {
357                                 pr_debug("Setting inplace to 0. VUC %d, "
358                                       "block %d was %x lastEUN, "
359                                       "and is in EUN %d (%s) %d\n",
360                                       thisVUC, block, BlockLastState[block],
361                                       BlockMap[block],
362                                       BlockMap[block]== targetEUN ? "==" : "!=",
363                                       targetEUN);
364                                 inplace = 0;
365                                 break;
366                         }
367                 }
368
369                 if (pendingblock >= (thisVUC * (nftl->EraseSize / 512)) &&
370                     pendingblock < ((thisVUC + 1)* (nftl->EraseSize / 512)) &&
371                     BlockLastState[pendingblock - (thisVUC * (nftl->EraseSize / 512))] !=
372                     SECTOR_FREE) {
373                         pr_debug("Pending write not free in EUN %d. "
374                               "Folding out of place.\n", targetEUN);
375                         inplace = 0;
376                 }
377         }
378
379         if (!inplace) {
380                 pr_debug("Cannot fold Virtual Unit Chain %d in place. "
381                       "Trying out-of-place\n", thisVUC);
382                 /* We need to find a targetEUN to fold into. */
383                 targetEUN = NFTL_findfreeblock(nftl, 1);
384                 if (targetEUN == BLOCK_NIL) {
385                         /* Ouch. Now we're screwed. We need to do a
386                            fold-in-place of another chain to make room
387                            for this one. We need a better way of selecting
388                            which chain to fold, because makefreeblock will
389                            only ask us to fold the same one again.
390                         */
391                         printk(KERN_WARNING
392                                "NFTL_findfreeblock(desperate) returns 0xffff.\n");
393                         return BLOCK_NIL;
394                 }
395         } else {
396                 /* We put a fold mark in the chain we are folding only if we
397                fold in place to help the mount check code. If we do not fold in
398                place, it is possible to find the valid chain by selecting the
399                longer one */
400                 oob.u.c.FoldMark = oob.u.c.FoldMark1 = cpu_to_le16(FOLD_MARK_IN_PROGRESS);
401                 oob.u.c.unused = 0xffffffff;
402                 nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8,
403                                8, &retlen, (char *)&oob.u);
404         }
405
406         /* OK. We now know the location of every block in the Virtual Unit Chain,
407            and the Erase Unit into which we are supposed to be copying.
408            Go for it.
409         */
410         pr_debug("Folding chain %d into unit %d\n", thisVUC, targetEUN);
411         for (block = 0; block < nftl->EraseSize / 512 ; block++) {
412                 unsigned char movebuf[512];
413                 int ret;
414
415                 /* If it's in the target EUN already, or if it's pending write, do nothing */
416                 if (BlockMap[block] == targetEUN ||
417                     (pendingblock == (thisVUC * (nftl->EraseSize / 512) + block))) {
418                         continue;
419                 }
420
421                 /* copy only in non free block (free blocks can only
422                    happen in case of media errors or deleted blocks) */
423                 if (BlockMap[block] == BLOCK_NIL)
424                         continue;
425
426                 ret = mtd->read(mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512),
427                                 512, &retlen, movebuf);
428                 if (ret < 0 && !mtd_is_bitflip(ret)) {
429                         ret = mtd->read(mtd, (nftl->EraseSize * BlockMap[block])
430                                         + (block * 512), 512, &retlen,
431                                         movebuf);
432                         if (ret != -EIO)
433                                 printk("Error went away on retry.\n");
434                 }
435                 memset(&oob, 0xff, sizeof(struct nftl_oob));
436                 oob.b.Status = oob.b.Status1 = SECTOR_USED;
437
438                 nftl_write(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) +
439                            (block * 512), 512, &retlen, movebuf, (char *)&oob);
440         }
441
442         /* add the header so that it is now a valid chain */
443         oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC);
444         oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = BLOCK_NIL;
445
446         nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 8,
447                        8, &retlen, (char *)&oob.u);
448
449         /* OK. We've moved the whole lot into the new block. Now we have to free the original blocks. */
450
451         /* At this point, we have two different chains for this Virtual Unit, and no way to tell
452            them apart. If we crash now, we get confused. However, both contain the same data, so we
453            shouldn't actually lose data in this case. It's just that when we load up on a medium which
454            has duplicate chains, we need to free one of the chains because it's not necessary any more.
455         */
456         thisEUN = nftl->EUNtable[thisVUC];
457         pr_debug("Want to erase\n");
458
459         /* For each block in the old chain (except the targetEUN of course),
460            free it and make it available for future use */
461         while (thisEUN <= nftl->lastEUN && thisEUN != targetEUN) {
462                 unsigned int EUNtmp;
463
464                 EUNtmp = nftl->ReplUnitTable[thisEUN];
465
466                 if (NFTL_formatblock(nftl, thisEUN) < 0) {
467                         /* could not erase : mark block as reserved
468                          */
469                         nftl->ReplUnitTable[thisEUN] = BLOCK_RESERVED;
470                 } else {
471                         /* correctly erased : mark it as free */
472                         nftl->ReplUnitTable[thisEUN] = BLOCK_FREE;
473                         nftl->numfreeEUNs++;
474                 }
475                 thisEUN = EUNtmp;
476         }
477
478         /* Make this the new start of chain for thisVUC */
479         nftl->ReplUnitTable[targetEUN] = BLOCK_NIL;
480         nftl->EUNtable[thisVUC] = targetEUN;
481
482         return targetEUN;
483 }
484
485 static u16 NFTL_makefreeblock( struct NFTLrecord *nftl , unsigned pendingblock)
486 {
487         /* This is the part that needs some cleverness applied.
488            For now, I'm doing the minimum applicable to actually
489            get the thing to work.
490            Wear-levelling and other clever stuff needs to be implemented
491            and we also need to do some assessment of the results when
492            the system loses power half-way through the routine.
493         */
494         u16 LongestChain = 0;
495         u16 ChainLength = 0, thislen;
496         u16 chain, EUN;
497
498         for (chain = 0; chain < le32_to_cpu(nftl->MediaHdr.FormattedSize) / nftl->EraseSize; chain++) {
499                 EUN = nftl->EUNtable[chain];
500                 thislen = 0;
501
502                 while (EUN <= nftl->lastEUN) {
503                         thislen++;
504                         //printk("VUC %d reaches len %d with EUN %d\n", chain, thislen, EUN);
505                         EUN = nftl->ReplUnitTable[EUN] & 0x7fff;
506                         if (thislen > 0xff00) {
507                                 printk("Endless loop in Virtual Chain %d: Unit %x\n",
508                                        chain, EUN);
509                         }
510                         if (thislen > 0xff10) {
511                                 /* Actually, don't return failure. Just ignore this chain and
512                                    get on with it. */
513                                 thislen = 0;
514                                 break;
515                         }
516                 }
517
518                 if (thislen > ChainLength) {
519                         //printk("New longest chain is %d with length %d\n", chain, thislen);
520                         ChainLength = thislen;
521                         LongestChain = chain;
522                 }
523         }
524
525         if (ChainLength < 2) {
526                 printk(KERN_WARNING "No Virtual Unit Chains available for folding. "
527                        "Failing request\n");
528                 return BLOCK_NIL;
529         }
530
531         return NFTL_foldchain (nftl, LongestChain, pendingblock);
532 }
533
534 /* NFTL_findwriteunit: Return the unit number into which we can write
535                        for this block. Make it available if it isn't already
536 */
537 static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)
538 {
539         u16 lastEUN;
540         u16 thisVUC = block / (nftl->EraseSize / 512);
541         struct mtd_info *mtd = nftl->mbd.mtd;
542         unsigned int writeEUN;
543         unsigned long blockofs = (block * 512) & (nftl->EraseSize -1);
544         size_t retlen;
545         int silly, silly2 = 3;
546         struct nftl_oob oob;
547
548         do {
549                 /* Scan the media to find a unit in the VUC which has
550                    a free space for the block in question.
551                 */
552
553                 /* This condition catches the 0x[7f]fff cases, as well as
554                    being a sanity check for past-end-of-media access
555                 */
556                 lastEUN = BLOCK_NIL;
557                 writeEUN = nftl->EUNtable[thisVUC];
558                 silly = MAX_LOOPS;
559                 while (writeEUN <= nftl->lastEUN) {
560                         struct nftl_bci bci;
561                         size_t retlen;
562                         unsigned int status;
563
564                         lastEUN = writeEUN;
565
566                         nftl_read_oob(mtd,
567                                       (writeEUN * nftl->EraseSize) + blockofs,
568                                       8, &retlen, (char *)&bci);
569
570                         pr_debug("Status of block %d in EUN %d is %x\n",
571                               block , writeEUN, le16_to_cpu(bci.Status));
572
573                         status = bci.Status | bci.Status1;
574                         switch(status) {
575                         case SECTOR_FREE:
576                                 return writeEUN;
577
578                         case SECTOR_DELETED:
579                         case SECTOR_USED:
580                         case SECTOR_IGNORE:
581                                 break;
582                         default:
583                                 // Invalid block. Don't use it any more. Must implement.
584                                 break;
585                         }
586
587                         if (!silly--) {
588                                 printk(KERN_WARNING
589                                        "Infinite loop in Virtual Unit Chain 0x%x\n",
590                                        thisVUC);
591                                 return BLOCK_NIL;
592                         }
593
594                         /* Skip to next block in chain */
595                         writeEUN = nftl->ReplUnitTable[writeEUN];
596                 }
597
598                 /* OK. We didn't find one in the existing chain, or there
599                    is no existing chain. */
600
601                 /* Try to find an already-free block */
602                 writeEUN = NFTL_findfreeblock(nftl, 0);
603
604                 if (writeEUN == BLOCK_NIL) {
605                         /* That didn't work - there were no free blocks just
606                            waiting to be picked up. We're going to have to fold
607                            a chain to make room.
608                         */
609
610                         /* First remember the start of this chain */
611                         //u16 startEUN = nftl->EUNtable[thisVUC];
612
613                         //printk("Write to VirtualUnitChain %d, calling makefreeblock()\n", thisVUC);
614                         writeEUN = NFTL_makefreeblock(nftl, BLOCK_NIL);
615
616                         if (writeEUN == BLOCK_NIL) {
617                                 /* OK, we accept that the above comment is
618                                    lying - there may have been free blocks
619                                    last time we called NFTL_findfreeblock(),
620                                    but they are reserved for when we're
621                                    desperate. Well, now we're desperate.
622                                 */
623                                 pr_debug("Using desperate==1 to find free EUN to accommodate write to VUC %d\n", thisVUC);
624                                 writeEUN = NFTL_findfreeblock(nftl, 1);
625                         }
626                         if (writeEUN == BLOCK_NIL) {
627                                 /* Ouch. This should never happen - we should
628                                    always be able to make some room somehow.
629                                    If we get here, we've allocated more storage
630                                    space than actual media, or our makefreeblock
631                                    routine is missing something.
632                                 */
633                                 printk(KERN_WARNING "Cannot make free space.\n");
634                                 return BLOCK_NIL;
635                         }
636                         //printk("Restarting scan\n");
637                         lastEUN = BLOCK_NIL;
638                         continue;
639                 }
640
641                 /* We've found a free block. Insert it into the chain. */
642
643                 if (lastEUN != BLOCK_NIL) {
644                         thisVUC |= 0x8000; /* It's a replacement block */
645                 } else {
646                         /* The first block in a new chain */
647                         nftl->EUNtable[thisVUC] = writeEUN;
648                 }
649
650                 /* set up the actual EUN we're writing into */
651                 /* Both in our cache... */
652                 nftl->ReplUnitTable[writeEUN] = BLOCK_NIL;
653
654                 /* ... and on the flash itself */
655                 nftl_read_oob(mtd, writeEUN * nftl->EraseSize + 8, 8,
656                               &retlen, (char *)&oob.u);
657
658                 oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC);
659
660                 nftl_write_oob(mtd, writeEUN * nftl->EraseSize + 8, 8,
661                                &retlen, (char *)&oob.u);
662
663                 /* we link the new block to the chain only after the
664                    block is ready. It avoids the case where the chain
665                    could point to a free block */
666                 if (lastEUN != BLOCK_NIL) {
667                         /* Both in our cache... */
668                         nftl->ReplUnitTable[lastEUN] = writeEUN;
669                         /* ... and on the flash itself */
670                         nftl_read_oob(mtd, (lastEUN * nftl->EraseSize) + 8,
671                                       8, &retlen, (char *)&oob.u);
672
673                         oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum
674                                 = cpu_to_le16(writeEUN);
675
676                         nftl_write_oob(mtd, (lastEUN * nftl->EraseSize) + 8,
677                                        8, &retlen, (char *)&oob.u);
678                 }
679
680                 return writeEUN;
681
682         } while (silly2--);
683
684         printk(KERN_WARNING "Error folding to make room for Virtual Unit Chain 0x%x\n",
685                thisVUC);
686         return BLOCK_NIL;
687 }
688
689 static int nftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block,
690                            char *buffer)
691 {
692         struct NFTLrecord *nftl = (void *)mbd;
693         u16 writeEUN;
694         unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1);
695         size_t retlen;
696         struct nftl_oob oob;
697
698         writeEUN = NFTL_findwriteunit(nftl, block);
699
700         if (writeEUN == BLOCK_NIL) {
701                 printk(KERN_WARNING
702                        "NFTL_writeblock(): Cannot find block to write to\n");
703                 /* If we _still_ haven't got a block to use, we're screwed */
704                 return 1;
705         }
706
707         memset(&oob, 0xff, sizeof(struct nftl_oob));
708         oob.b.Status = oob.b.Status1 = SECTOR_USED;
709
710         nftl_write(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs,
711                    512, &retlen, (char *)buffer, (char *)&oob);
712         return 0;
713 }
714 #endif /* CONFIG_NFTL_RW */
715
716 static int nftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,
717                           char *buffer)
718 {
719         struct NFTLrecord *nftl = (void *)mbd;
720         struct mtd_info *mtd = nftl->mbd.mtd;
721         u16 lastgoodEUN;
722         u16 thisEUN = nftl->EUNtable[block / (nftl->EraseSize / 512)];
723         unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1);
724         unsigned int status;
725         int silly = MAX_LOOPS;
726         size_t retlen;
727         struct nftl_bci bci;
728
729         lastgoodEUN = BLOCK_NIL;
730
731         if (thisEUN != BLOCK_NIL) {
732                 while (thisEUN < nftl->nb_blocks) {
733                         if (nftl_read_oob(mtd, (thisEUN * nftl->EraseSize) +
734                                           blockofs, 8, &retlen,
735                                           (char *)&bci) < 0)
736                                 status = SECTOR_IGNORE;
737                         else
738                                 status = bci.Status | bci.Status1;
739
740                         switch (status) {
741                         case SECTOR_FREE:
742                                 /* no modification of a sector should follow a free sector */
743                                 goto the_end;
744                         case SECTOR_DELETED:
745                                 lastgoodEUN = BLOCK_NIL;
746                                 break;
747                         case SECTOR_USED:
748                                 lastgoodEUN = thisEUN;
749                                 break;
750                         case SECTOR_IGNORE:
751                                 break;
752                         default:
753                                 printk("Unknown status for block %ld in EUN %d: %x\n",
754                                        block, thisEUN, status);
755                                 break;
756                         }
757
758                         if (!silly--) {
759                                 printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%lx\n",
760                                        block / (nftl->EraseSize / 512));
761                                 return 1;
762                         }
763                         thisEUN = nftl->ReplUnitTable[thisEUN];
764                 }
765         }
766
767  the_end:
768         if (lastgoodEUN == BLOCK_NIL) {
769                 /* the requested block is not on the media, return all 0x00 */
770                 memset(buffer, 0, 512);
771         } else {
772                 loff_t ptr = (lastgoodEUN * nftl->EraseSize) + blockofs;
773                 size_t retlen;
774                 int res = mtd->read(mtd, ptr, 512, &retlen, buffer);
775
776                 if (res < 0 && !mtd_is_bitflip(res))
777                         return -EIO;
778         }
779         return 0;
780 }
781
782 static int nftl_getgeo(struct mtd_blktrans_dev *dev,  struct hd_geometry *geo)
783 {
784         struct NFTLrecord *nftl = (void *)dev;
785
786         geo->heads = nftl->heads;
787         geo->sectors = nftl->sectors;
788         geo->cylinders = nftl->cylinders;
789
790         return 0;
791 }
792
793 /****************************************************************************
794  *
795  * Module stuff
796  *
797  ****************************************************************************/
798
799
800 static struct mtd_blktrans_ops nftl_tr = {
801         .name           = "nftl",
802         .major          = NFTL_MAJOR,
803         .part_bits      = NFTL_PARTN_BITS,
804         .blksize        = 512,
805         .getgeo         = nftl_getgeo,
806         .readsect       = nftl_readblock,
807 #ifdef CONFIG_NFTL_RW
808         .writesect      = nftl_writeblock,
809 #endif
810         .add_mtd        = nftl_add_mtd,
811         .remove_dev     = nftl_remove_dev,
812         .owner          = THIS_MODULE,
813 };
814
815 static int __init init_nftl(void)
816 {
817         return register_mtd_blktrans(&nftl_tr);
818 }
819
820 static void __exit cleanup_nftl(void)
821 {
822         deregister_mtd_blktrans(&nftl_tr);
823 }
824
825 module_init(init_nftl);
826 module_exit(cleanup_nftl);
827
828 MODULE_LICENSE("GPL");
829 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>, Fabrice Bellard <fabrice.bellard@netgem.com> et al.");
830 MODULE_DESCRIPTION("Support code for NAND Flash Translation Layer, used on M-Systems DiskOnChip 2000 and Millennium");
831 MODULE_ALIAS_BLOCKDEV_MAJOR(NFTL_MAJOR);