xref: /linux/drivers/mtd/ftl.c (revision f7511d5f66f01fc451747b24e79f3ada7a3af9af)
1 /* This version ported to the Linux-MTD system by dwmw2@infradead.org
2  * $Id: ftl.c,v 1.59 2005/11/29 14:48:31 gleixner Exp $
3  *
4  * Fixes: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
5  * - fixes some leaks on failure in build_maps and ftl_notify_add, cleanups
6  *
7  * Based on:
8  */
9 /*======================================================================
10 
11     A Flash Translation Layer memory card driver
12 
13     This driver implements a disk-like block device driver with an
14     apparent block size of 512 bytes for flash memory cards.
15 
16     ftl_cs.c 1.62 2000/02/01 00:59:04
17 
18     The contents of this file are subject to the Mozilla Public
19     License Version 1.1 (the "License"); you may not use this file
20     except in compliance with the License. You may obtain a copy of
21     the License at http://www.mozilla.org/MPL/
22 
23     Software distributed under the License is distributed on an "AS
24     IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
25     implied. See the License for the specific language governing
26     rights and limitations under the License.
27 
28     The initial developer of the original code is David A. Hinds
29     <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
30     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
31 
32     Alternatively, the contents of this file may be used under the
33     terms of the GNU General Public License version 2 (the "GPL"), in
34     which case the provisions of the GPL are applicable instead of the
35     above.  If you wish to allow the use of your version of this file
36     only under the terms of the GPL and not to allow others to use
37     your version of this file under the MPL, indicate your decision
38     by deleting the provisions above and replace them with the notice
39     and other provisions required by the GPL.  If you do not delete
40     the provisions above, a recipient may use your version of this
41     file under either the MPL or the GPL.
42 
43     LEGAL NOTE: The FTL format is patented by M-Systems.  They have
44     granted a license for its use with PCMCIA devices:
45 
46      "M-Systems grants a royalty-free, non-exclusive license under
47       any presently existing M-Systems intellectual property rights
48       necessary for the design and development of FTL-compatible
49       drivers, file systems and utilities using the data formats with
50       PCMCIA PC Cards as described in the PCMCIA Flash Translation
51       Layer (FTL) Specification."
52 
53     Use of the FTL format for non-PCMCIA applications may be an
54     infringement of these patents.  For additional information,
55     contact M-Systems (http://www.m-sys.com) directly.
56 
57 ======================================================================*/
58 #include <linux/mtd/blktrans.h>
59 #include <linux/module.h>
60 #include <linux/mtd/mtd.h>
61 /*#define PSYCHO_DEBUG */
62 
63 #include <linux/kernel.h>
64 #include <linux/ptrace.h>
65 #include <linux/slab.h>
66 #include <linux/string.h>
67 #include <linux/timer.h>
68 #include <linux/major.h>
69 #include <linux/fs.h>
70 #include <linux/init.h>
71 #include <linux/hdreg.h>
72 #include <linux/vmalloc.h>
73 #include <linux/blkpg.h>
74 #include <asm/uaccess.h>
75 
76 #include <linux/mtd/ftl.h>
77 
78 /*====================================================================*/
79 
80 /* Parameters that can be set with 'insmod' */
81 static int shuffle_freq = 50;
82 module_param(shuffle_freq, int, 0);
83 
84 /*====================================================================*/
85 
86 /* Major device # for FTL device */
87 #ifndef FTL_MAJOR
88 #define FTL_MAJOR	44
89 #endif
90 
91 
92 /*====================================================================*/
93 
94 /* Maximum number of separate memory devices we'll allow */
95 #define MAX_DEV		4
96 
97 /* Maximum number of regions per device */
98 #define MAX_REGION	4
99 
100 /* Maximum number of partitions in an FTL region */
101 #define PART_BITS	4
102 
103 /* Maximum number of outstanding erase requests per socket */
104 #define MAX_ERASE	8
105 
106 /* Sector size -- shouldn't need to change */
107 #define SECTOR_SIZE	512
108 
109 
110 /* Each memory region corresponds to a minor device */
111 typedef struct partition_t {
112     struct mtd_blktrans_dev mbd;
113     u_int32_t		state;
114     u_int32_t		*VirtualBlockMap;
115     u_int32_t		*VirtualPageMap;
116     u_int32_t		FreeTotal;
117     struct eun_info_t {
118 	u_int32_t		Offset;
119 	u_int32_t		EraseCount;
120 	u_int32_t		Free;
121 	u_int32_t		Deleted;
122     } *EUNInfo;
123     struct xfer_info_t {
124 	u_int32_t		Offset;
125 	u_int32_t		EraseCount;
126 	u_int16_t		state;
127     } *XferInfo;
128     u_int16_t		bam_index;
129     u_int32_t		*bam_cache;
130     u_int16_t		DataUnits;
131     u_int32_t		BlocksPerUnit;
132     erase_unit_header_t	header;
133 #if 0
134     region_info_t	region;
135     memory_handle_t	handle;
136 #endif
137 } partition_t;
138 
139 /* Partition state flags */
140 #define FTL_FORMATTED	0x01
141 
142 /* Transfer unit states */
143 #define XFER_UNKNOWN	0x00
144 #define XFER_ERASING	0x01
145 #define XFER_ERASED	0x02
146 #define XFER_PREPARED	0x03
147 #define XFER_FAILED	0x04
148 
149 /*====================================================================*/
150 
151 
152 static void ftl_erase_callback(struct erase_info *done);
153 
154 
155 /*======================================================================
156 
157     Scan_header() checks to see if a memory region contains an FTL
158     partition.  build_maps() reads all the erase unit headers, builds
159     the erase unit map, and then builds the virtual page map.
160 
161 ======================================================================*/
162 
163 static int scan_header(partition_t *part)
164 {
165     erase_unit_header_t header;
166     loff_t offset, max_offset;
167     size_t ret;
168     int err;
169     part->header.FormattedSize = 0;
170     max_offset = (0x100000<part->mbd.mtd->size)?0x100000:part->mbd.mtd->size;
171     /* Search first megabyte for a valid FTL header */
172     for (offset = 0;
173 	 (offset + sizeof(header)) < max_offset;
174 	 offset += part->mbd.mtd->erasesize ? : 0x2000) {
175 
176 	err = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &ret,
177 			      (unsigned char *)&header);
178 
179 	if (err)
180 	    return err;
181 
182 	if (strcmp(header.DataOrgTuple+3, "FTL100") == 0) break;
183     }
184 
185     if (offset == max_offset) {
186 	printk(KERN_NOTICE "ftl_cs: FTL header not found.\n");
187 	return -ENOENT;
188     }
189     if (header.BlockSize != 9 ||
190 	(header.EraseUnitSize < 10) || (header.EraseUnitSize > 31) ||
191 	(header.NumTransferUnits >= le16_to_cpu(header.NumEraseUnits))) {
192 	printk(KERN_NOTICE "ftl_cs: FTL header corrupt!\n");
193 	return -1;
194     }
195     if ((1 << header.EraseUnitSize) != part->mbd.mtd->erasesize) {
196 	printk(KERN_NOTICE "ftl: FTL EraseUnitSize %x != MTD erasesize %x\n",
197 	       1 << header.EraseUnitSize,part->mbd.mtd->erasesize);
198 	return -1;
199     }
200     part->header = header;
201     return 0;
202 }
203 
204 static int build_maps(partition_t *part)
205 {
206     erase_unit_header_t header;
207     u_int16_t xvalid, xtrans, i;
208     u_int blocks, j;
209     int hdr_ok, ret = -1;
210     ssize_t retval;
211     loff_t offset;
212 
213     /* Set up erase unit maps */
214     part->DataUnits = le16_to_cpu(part->header.NumEraseUnits) -
215 	part->header.NumTransferUnits;
216     part->EUNInfo = kmalloc(part->DataUnits * sizeof(struct eun_info_t),
217 			    GFP_KERNEL);
218     if (!part->EUNInfo)
219 	    goto out;
220     for (i = 0; i < part->DataUnits; i++)
221 	part->EUNInfo[i].Offset = 0xffffffff;
222     part->XferInfo =
223 	kmalloc(part->header.NumTransferUnits * sizeof(struct xfer_info_t),
224 		GFP_KERNEL);
225     if (!part->XferInfo)
226 	    goto out_EUNInfo;
227 
228     xvalid = xtrans = 0;
229     for (i = 0; i < le16_to_cpu(part->header.NumEraseUnits); i++) {
230 	offset = ((i + le16_to_cpu(part->header.FirstPhysicalEUN))
231 		      << part->header.EraseUnitSize);
232 	ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &retval,
233 			      (unsigned char *)&header);
234 
235 	if (ret)
236 	    goto out_XferInfo;
237 
238 	ret = -1;
239 	/* Is this a transfer partition? */
240 	hdr_ok = (strcmp(header.DataOrgTuple+3, "FTL100") == 0);
241 	if (hdr_ok && (le16_to_cpu(header.LogicalEUN) < part->DataUnits) &&
242 	    (part->EUNInfo[le16_to_cpu(header.LogicalEUN)].Offset == 0xffffffff)) {
243 	    part->EUNInfo[le16_to_cpu(header.LogicalEUN)].Offset = offset;
244 	    part->EUNInfo[le16_to_cpu(header.LogicalEUN)].EraseCount =
245 		le32_to_cpu(header.EraseCount);
246 	    xvalid++;
247 	} else {
248 	    if (xtrans == part->header.NumTransferUnits) {
249 		printk(KERN_NOTICE "ftl_cs: format error: too many "
250 		       "transfer units!\n");
251 		goto out_XferInfo;
252 	    }
253 	    if (hdr_ok && (le16_to_cpu(header.LogicalEUN) == 0xffff)) {
254 		part->XferInfo[xtrans].state = XFER_PREPARED;
255 		part->XferInfo[xtrans].EraseCount = le32_to_cpu(header.EraseCount);
256 	    } else {
257 		part->XferInfo[xtrans].state = XFER_UNKNOWN;
258 		/* Pick anything reasonable for the erase count */
259 		part->XferInfo[xtrans].EraseCount =
260 		    le32_to_cpu(part->header.EraseCount);
261 	    }
262 	    part->XferInfo[xtrans].Offset = offset;
263 	    xtrans++;
264 	}
265     }
266     /* Check for format trouble */
267     header = part->header;
268     if ((xtrans != header.NumTransferUnits) ||
269 	(xvalid+xtrans != le16_to_cpu(header.NumEraseUnits))) {
270 	printk(KERN_NOTICE "ftl_cs: format error: erase units "
271 	       "don't add up!\n");
272 	goto out_XferInfo;
273     }
274 
275     /* Set up virtual page map */
276     blocks = le32_to_cpu(header.FormattedSize) >> header.BlockSize;
277     part->VirtualBlockMap = vmalloc(blocks * sizeof(u_int32_t));
278     if (!part->VirtualBlockMap)
279 	    goto out_XferInfo;
280 
281     memset(part->VirtualBlockMap, 0xff, blocks * sizeof(u_int32_t));
282     part->BlocksPerUnit = (1 << header.EraseUnitSize) >> header.BlockSize;
283 
284     part->bam_cache = kmalloc(part->BlocksPerUnit * sizeof(u_int32_t),
285 			      GFP_KERNEL);
286     if (!part->bam_cache)
287 	    goto out_VirtualBlockMap;
288 
289     part->bam_index = 0xffff;
290     part->FreeTotal = 0;
291 
292     for (i = 0; i < part->DataUnits; i++) {
293 	part->EUNInfo[i].Free = 0;
294 	part->EUNInfo[i].Deleted = 0;
295 	offset = part->EUNInfo[i].Offset + le32_to_cpu(header.BAMOffset);
296 
297 	ret = part->mbd.mtd->read(part->mbd.mtd, offset,
298 			      part->BlocksPerUnit * sizeof(u_int32_t), &retval,
299 			      (unsigned char *)part->bam_cache);
300 
301 	if (ret)
302 		goto out_bam_cache;
303 
304 	for (j = 0; j < part->BlocksPerUnit; j++) {
305 	    if (BLOCK_FREE(le32_to_cpu(part->bam_cache[j]))) {
306 		part->EUNInfo[i].Free++;
307 		part->FreeTotal++;
308 	    } else if ((BLOCK_TYPE(le32_to_cpu(part->bam_cache[j])) == BLOCK_DATA) &&
309 		     (BLOCK_NUMBER(le32_to_cpu(part->bam_cache[j])) < blocks))
310 		part->VirtualBlockMap[BLOCK_NUMBER(le32_to_cpu(part->bam_cache[j]))] =
311 		    (i << header.EraseUnitSize) + (j << header.BlockSize);
312 	    else if (BLOCK_DELETED(le32_to_cpu(part->bam_cache[j])))
313 		part->EUNInfo[i].Deleted++;
314 	}
315     }
316 
317     ret = 0;
318     goto out;
319 
320 out_bam_cache:
321     kfree(part->bam_cache);
322 out_VirtualBlockMap:
323     vfree(part->VirtualBlockMap);
324 out_XferInfo:
325     kfree(part->XferInfo);
326 out_EUNInfo:
327     kfree(part->EUNInfo);
328 out:
329     return ret;
330 } /* build_maps */
331 
332 /*======================================================================
333 
334     Erase_xfer() schedules an asynchronous erase operation for a
335     transfer unit.
336 
337 ======================================================================*/
338 
339 static int erase_xfer(partition_t *part,
340 		      u_int16_t xfernum)
341 {
342     int ret;
343     struct xfer_info_t *xfer;
344     struct erase_info *erase;
345 
346     xfer = &part->XferInfo[xfernum];
347     DEBUG(1, "ftl_cs: erasing xfer unit at 0x%x\n", xfer->Offset);
348     xfer->state = XFER_ERASING;
349 
350     /* Is there a free erase slot? Always in MTD. */
351 
352 
353     erase=kmalloc(sizeof(struct erase_info), GFP_KERNEL);
354     if (!erase)
355             return -ENOMEM;
356 
357     erase->mtd = part->mbd.mtd;
358     erase->callback = ftl_erase_callback;
359     erase->addr = xfer->Offset;
360     erase->len = 1 << part->header.EraseUnitSize;
361     erase->priv = (u_long)part;
362 
363     ret = part->mbd.mtd->erase(part->mbd.mtd, erase);
364 
365     if (!ret)
366 	    xfer->EraseCount++;
367     else
368 	    kfree(erase);
369 
370     return ret;
371 } /* erase_xfer */
372 
373 /*======================================================================
374 
375     Prepare_xfer() takes a freshly erased transfer unit and gives
376     it an appropriate header.
377 
378 ======================================================================*/
379 
380 static void ftl_erase_callback(struct erase_info *erase)
381 {
382     partition_t *part;
383     struct xfer_info_t *xfer;
384     int i;
385 
386     /* Look up the transfer unit */
387     part = (partition_t *)(erase->priv);
388 
389     for (i = 0; i < part->header.NumTransferUnits; i++)
390 	if (part->XferInfo[i].Offset == erase->addr) break;
391 
392     if (i == part->header.NumTransferUnits) {
393 	printk(KERN_NOTICE "ftl_cs: internal error: "
394 	       "erase lookup failed!\n");
395 	return;
396     }
397 
398     xfer = &part->XferInfo[i];
399     if (erase->state == MTD_ERASE_DONE)
400 	xfer->state = XFER_ERASED;
401     else {
402 	xfer->state = XFER_FAILED;
403 	printk(KERN_NOTICE "ftl_cs: erase failed: state = %d\n",
404 	       erase->state);
405     }
406 
407     kfree(erase);
408 
409 } /* ftl_erase_callback */
410 
411 static int prepare_xfer(partition_t *part, int i)
412 {
413     erase_unit_header_t header;
414     struct xfer_info_t *xfer;
415     int nbam, ret;
416     u_int32_t ctl;
417     ssize_t retlen;
418     loff_t offset;
419 
420     xfer = &part->XferInfo[i];
421     xfer->state = XFER_FAILED;
422 
423     DEBUG(1, "ftl_cs: preparing xfer unit at 0x%x\n", xfer->Offset);
424 
425     /* Write the transfer unit header */
426     header = part->header;
427     header.LogicalEUN = cpu_to_le16(0xffff);
428     header.EraseCount = cpu_to_le32(xfer->EraseCount);
429 
430     ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset, sizeof(header),
431 			   &retlen, (u_char *)&header);
432 
433     if (ret) {
434 	return ret;
435     }
436 
437     /* Write the BAM stub */
438     nbam = (part->BlocksPerUnit * sizeof(u_int32_t) +
439 	    le32_to_cpu(part->header.BAMOffset) + SECTOR_SIZE - 1) / SECTOR_SIZE;
440 
441     offset = xfer->Offset + le32_to_cpu(part->header.BAMOffset);
442     ctl = cpu_to_le32(BLOCK_CONTROL);
443 
444     for (i = 0; i < nbam; i++, offset += sizeof(u_int32_t)) {
445 
446 	ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int32_t),
447 			       &retlen, (u_char *)&ctl);
448 
449 	if (ret)
450 	    return ret;
451     }
452     xfer->state = XFER_PREPARED;
453     return 0;
454 
455 } /* prepare_xfer */
456 
457 /*======================================================================
458 
459     Copy_erase_unit() takes a full erase block and a transfer unit,
460     copies everything to the transfer unit, then swaps the block
461     pointers.
462 
463     All data blocks are copied to the corresponding blocks in the
464     target unit, so the virtual block map does not need to be
465     updated.
466 
467 ======================================================================*/
468 
469 static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
470 			   u_int16_t xferunit)
471 {
472     u_char buf[SECTOR_SIZE];
473     struct eun_info_t *eun;
474     struct xfer_info_t *xfer;
475     u_int32_t src, dest, free, i;
476     u_int16_t unit;
477     int ret;
478     ssize_t retlen;
479     loff_t offset;
480     u_int16_t srcunitswap = cpu_to_le16(srcunit);
481 
482     eun = &part->EUNInfo[srcunit];
483     xfer = &part->XferInfo[xferunit];
484     DEBUG(2, "ftl_cs: copying block 0x%x to 0x%x\n",
485 	  eun->Offset, xfer->Offset);
486 
487 
488     /* Read current BAM */
489     if (part->bam_index != srcunit) {
490 
491 	offset = eun->Offset + le32_to_cpu(part->header.BAMOffset);
492 
493 	ret = part->mbd.mtd->read(part->mbd.mtd, offset,
494 			      part->BlocksPerUnit * sizeof(u_int32_t),
495 			      &retlen, (u_char *) (part->bam_cache));
496 
497 	/* mark the cache bad, in case we get an error later */
498 	part->bam_index = 0xffff;
499 
500 	if (ret) {
501 	    printk( KERN_WARNING "ftl: Failed to read BAM cache in copy_erase_unit()!\n");
502 	    return ret;
503 	}
504     }
505 
506     /* Write the LogicalEUN for the transfer unit */
507     xfer->state = XFER_UNKNOWN;
508     offset = xfer->Offset + 20; /* Bad! */
509     unit = cpu_to_le16(0x7fff);
510 
511     ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int16_t),
512 			   &retlen, (u_char *) &unit);
513 
514     if (ret) {
515 	printk( KERN_WARNING "ftl: Failed to write back to BAM cache in copy_erase_unit()!\n");
516 	return ret;
517     }
518 
519     /* Copy all data blocks from source unit to transfer unit */
520     src = eun->Offset; dest = xfer->Offset;
521 
522     free = 0;
523     ret = 0;
524     for (i = 0; i < part->BlocksPerUnit; i++) {
525 	switch (BLOCK_TYPE(le32_to_cpu(part->bam_cache[i]))) {
526 	case BLOCK_CONTROL:
527 	    /* This gets updated later */
528 	    break;
529 	case BLOCK_DATA:
530 	case BLOCK_REPLACEMENT:
531 	    ret = part->mbd.mtd->read(part->mbd.mtd, src, SECTOR_SIZE,
532                         &retlen, (u_char *) buf);
533 	    if (ret) {
534 		printk(KERN_WARNING "ftl: Error reading old xfer unit in copy_erase_unit\n");
535 		return ret;
536             }
537 
538 
539 	    ret = part->mbd.mtd->write(part->mbd.mtd, dest, SECTOR_SIZE,
540                         &retlen, (u_char *) buf);
541 	    if (ret)  {
542 		printk(KERN_WARNING "ftl: Error writing new xfer unit in copy_erase_unit\n");
543 		return ret;
544             }
545 
546 	    break;
547 	default:
548 	    /* All other blocks must be free */
549 	    part->bam_cache[i] = cpu_to_le32(0xffffffff);
550 	    free++;
551 	    break;
552 	}
553 	src += SECTOR_SIZE;
554 	dest += SECTOR_SIZE;
555     }
556 
557     /* Write the BAM to the transfer unit */
558     ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + le32_to_cpu(part->header.BAMOffset),
559                     part->BlocksPerUnit * sizeof(int32_t), &retlen,
560 		    (u_char *)part->bam_cache);
561     if (ret) {
562 	printk( KERN_WARNING "ftl: Error writing BAM in copy_erase_unit\n");
563 	return ret;
564     }
565 
566 
567     /* All clear? Then update the LogicalEUN again */
568     ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + 20, sizeof(u_int16_t),
569 			   &retlen, (u_char *)&srcunitswap);
570 
571     if (ret) {
572 	printk(KERN_WARNING "ftl: Error writing new LogicalEUN in copy_erase_unit\n");
573 	return ret;
574     }
575 
576 
577     /* Update the maps and usage stats*/
578     i = xfer->EraseCount;
579     xfer->EraseCount = eun->EraseCount;
580     eun->EraseCount = i;
581     i = xfer->Offset;
582     xfer->Offset = eun->Offset;
583     eun->Offset = i;
584     part->FreeTotal -= eun->Free;
585     part->FreeTotal += free;
586     eun->Free = free;
587     eun->Deleted = 0;
588 
589     /* Now, the cache should be valid for the new block */
590     part->bam_index = srcunit;
591 
592     return 0;
593 } /* copy_erase_unit */
594 
595 /*======================================================================
596 
597     reclaim_block() picks a full erase unit and a transfer unit and
598     then calls copy_erase_unit() to copy one to the other.  Then, it
599     schedules an erase on the expired block.
600 
601     What's a good way to decide which transfer unit and which erase
602     unit to use?  Beats me.  My way is to always pick the transfer
603     unit with the fewest erases, and usually pick the data unit with
604     the most deleted blocks.  But with a small probability, pick the
605     oldest data unit instead.  This means that we generally postpone
606     the next reclaimation as long as possible, but shuffle static
607     stuff around a bit for wear leveling.
608 
609 ======================================================================*/
610 
611 static int reclaim_block(partition_t *part)
612 {
613     u_int16_t i, eun, xfer;
614     u_int32_t best;
615     int queued, ret;
616 
617     DEBUG(0, "ftl_cs: reclaiming space...\n");
618     DEBUG(3, "NumTransferUnits == %x\n", part->header.NumTransferUnits);
619     /* Pick the least erased transfer unit */
620     best = 0xffffffff; xfer = 0xffff;
621     do {
622 	queued = 0;
623 	for (i = 0; i < part->header.NumTransferUnits; i++) {
624 	    int n=0;
625 	    if (part->XferInfo[i].state == XFER_UNKNOWN) {
626 		DEBUG(3,"XferInfo[%d].state == XFER_UNKNOWN\n",i);
627 		n=1;
628 		erase_xfer(part, i);
629 	    }
630 	    if (part->XferInfo[i].state == XFER_ERASING) {
631 		DEBUG(3,"XferInfo[%d].state == XFER_ERASING\n",i);
632 		n=1;
633 		queued = 1;
634 	    }
635 	    else if (part->XferInfo[i].state == XFER_ERASED) {
636 		DEBUG(3,"XferInfo[%d].state == XFER_ERASED\n",i);
637 		n=1;
638 		prepare_xfer(part, i);
639 	    }
640 	    if (part->XferInfo[i].state == XFER_PREPARED) {
641 		DEBUG(3,"XferInfo[%d].state == XFER_PREPARED\n",i);
642 		n=1;
643 		if (part->XferInfo[i].EraseCount <= best) {
644 		    best = part->XferInfo[i].EraseCount;
645 		    xfer = i;
646 		}
647 	    }
648 		if (!n)
649 		    DEBUG(3,"XferInfo[%d].state == %x\n",i, part->XferInfo[i].state);
650 
651 	}
652 	if (xfer == 0xffff) {
653 	    if (queued) {
654 		DEBUG(1, "ftl_cs: waiting for transfer "
655 		      "unit to be prepared...\n");
656 		if (part->mbd.mtd->sync)
657 			part->mbd.mtd->sync(part->mbd.mtd);
658 	    } else {
659 		static int ne = 0;
660 		if (++ne < 5)
661 		    printk(KERN_NOTICE "ftl_cs: reclaim failed: no "
662 			   "suitable transfer units!\n");
663 		else
664 		    DEBUG(1, "ftl_cs: reclaim failed: no "
665 			  "suitable transfer units!\n");
666 
667 		return -EIO;
668 	    }
669 	}
670     } while (xfer == 0xffff);
671 
672     eun = 0;
673     if ((jiffies % shuffle_freq) == 0) {
674 	DEBUG(1, "ftl_cs: recycling freshest block...\n");
675 	best = 0xffffffff;
676 	for (i = 0; i < part->DataUnits; i++)
677 	    if (part->EUNInfo[i].EraseCount <= best) {
678 		best = part->EUNInfo[i].EraseCount;
679 		eun = i;
680 	    }
681     } else {
682 	best = 0;
683 	for (i = 0; i < part->DataUnits; i++)
684 	    if (part->EUNInfo[i].Deleted >= best) {
685 		best = part->EUNInfo[i].Deleted;
686 		eun = i;
687 	    }
688 	if (best == 0) {
689 	    static int ne = 0;
690 	    if (++ne < 5)
691 		printk(KERN_NOTICE "ftl_cs: reclaim failed: "
692 		       "no free blocks!\n");
693 	    else
694 		DEBUG(1,"ftl_cs: reclaim failed: "
695 		       "no free blocks!\n");
696 
697 	    return -EIO;
698 	}
699     }
700     ret = copy_erase_unit(part, eun, xfer);
701     if (!ret)
702 	erase_xfer(part, xfer);
703     else
704 	printk(KERN_NOTICE "ftl_cs: copy_erase_unit failed!\n");
705     return ret;
706 } /* reclaim_block */
707 
708 /*======================================================================
709 
710     Find_free() searches for a free block.  If necessary, it updates
711     the BAM cache for the erase unit containing the free block.  It
712     returns the block index -- the erase unit is just the currently
713     cached unit.  If there are no free blocks, it returns 0 -- this
714     is never a valid data block because it contains the header.
715 
716 ======================================================================*/
717 
718 #ifdef PSYCHO_DEBUG
719 static void dump_lists(partition_t *part)
720 {
721     int i;
722     printk(KERN_DEBUG "ftl_cs: Free total = %d\n", part->FreeTotal);
723     for (i = 0; i < part->DataUnits; i++)
724 	printk(KERN_DEBUG "ftl_cs:   unit %d: %d phys, %d free, "
725 	       "%d deleted\n", i,
726 	       part->EUNInfo[i].Offset >> part->header.EraseUnitSize,
727 	       part->EUNInfo[i].Free, part->EUNInfo[i].Deleted);
728 }
729 #endif
730 
731 static u_int32_t find_free(partition_t *part)
732 {
733     u_int16_t stop, eun;
734     u_int32_t blk;
735     size_t retlen;
736     int ret;
737 
738     /* Find an erase unit with some free space */
739     stop = (part->bam_index == 0xffff) ? 0 : part->bam_index;
740     eun = stop;
741     do {
742 	if (part->EUNInfo[eun].Free != 0) break;
743 	/* Wrap around at end of table */
744 	if (++eun == part->DataUnits) eun = 0;
745     } while (eun != stop);
746 
747     if (part->EUNInfo[eun].Free == 0)
748 	return 0;
749 
750     /* Is this unit's BAM cached? */
751     if (eun != part->bam_index) {
752 	/* Invalidate cache */
753 	part->bam_index = 0xffff;
754 
755 	ret = part->mbd.mtd->read(part->mbd.mtd,
756 		       part->EUNInfo[eun].Offset + le32_to_cpu(part->header.BAMOffset),
757 		       part->BlocksPerUnit * sizeof(u_int32_t),
758 		       &retlen, (u_char *) (part->bam_cache));
759 
760 	if (ret) {
761 	    printk(KERN_WARNING"ftl: Error reading BAM in find_free\n");
762 	    return 0;
763 	}
764 	part->bam_index = eun;
765     }
766 
767     /* Find a free block */
768     for (blk = 0; blk < part->BlocksPerUnit; blk++)
769 	if (BLOCK_FREE(le32_to_cpu(part->bam_cache[blk]))) break;
770     if (blk == part->BlocksPerUnit) {
771 #ifdef PSYCHO_DEBUG
772 	static int ne = 0;
773 	if (++ne == 1)
774 	    dump_lists(part);
775 #endif
776 	printk(KERN_NOTICE "ftl_cs: bad free list!\n");
777 	return 0;
778     }
779     DEBUG(2, "ftl_cs: found free block at %d in %d\n", blk, eun);
780     return blk;
781 
782 } /* find_free */
783 
784 
785 /*======================================================================
786 
787     Read a series of sectors from an FTL partition.
788 
789 ======================================================================*/
790 
791 static int ftl_read(partition_t *part, caddr_t buffer,
792 		    u_long sector, u_long nblocks)
793 {
794     u_int32_t log_addr, bsize;
795     u_long i;
796     int ret;
797     size_t offset, retlen;
798 
799     DEBUG(2, "ftl_cs: ftl_read(0x%p, 0x%lx, %ld)\n",
800 	  part, sector, nblocks);
801     if (!(part->state & FTL_FORMATTED)) {
802 	printk(KERN_NOTICE "ftl_cs: bad partition\n");
803 	return -EIO;
804     }
805     bsize = 1 << part->header.EraseUnitSize;
806 
807     for (i = 0; i < nblocks; i++) {
808 	if (((sector+i) * SECTOR_SIZE) >= le32_to_cpu(part->header.FormattedSize)) {
809 	    printk(KERN_NOTICE "ftl_cs: bad read offset\n");
810 	    return -EIO;
811 	}
812 	log_addr = part->VirtualBlockMap[sector+i];
813 	if (log_addr == 0xffffffff)
814 	    memset(buffer, 0, SECTOR_SIZE);
815 	else {
816 	    offset = (part->EUNInfo[log_addr / bsize].Offset
817 			  + (log_addr % bsize));
818 	    ret = part->mbd.mtd->read(part->mbd.mtd, offset, SECTOR_SIZE,
819 			   &retlen, (u_char *) buffer);
820 
821 	    if (ret) {
822 		printk(KERN_WARNING "Error reading MTD device in ftl_read()\n");
823 		return ret;
824 	    }
825 	}
826 	buffer += SECTOR_SIZE;
827     }
828     return 0;
829 } /* ftl_read */
830 
831 /*======================================================================
832 
833     Write a series of sectors to an FTL partition
834 
835 ======================================================================*/
836 
837 static int set_bam_entry(partition_t *part, u_int32_t log_addr,
838 			 u_int32_t virt_addr)
839 {
840     u_int32_t bsize, blk, le_virt_addr;
841 #ifdef PSYCHO_DEBUG
842     u_int32_t old_addr;
843 #endif
844     u_int16_t eun;
845     int ret;
846     size_t retlen, offset;
847 
848     DEBUG(2, "ftl_cs: set_bam_entry(0x%p, 0x%x, 0x%x)\n",
849 	  part, log_addr, virt_addr);
850     bsize = 1 << part->header.EraseUnitSize;
851     eun = log_addr / bsize;
852     blk = (log_addr % bsize) / SECTOR_SIZE;
853     offset = (part->EUNInfo[eun].Offset + blk * sizeof(u_int32_t) +
854 		  le32_to_cpu(part->header.BAMOffset));
855 
856 #ifdef PSYCHO_DEBUG
857     ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(u_int32_t),
858                         &retlen, (u_char *)&old_addr);
859     if (ret) {
860 	printk(KERN_WARNING"ftl: Error reading old_addr in set_bam_entry: %d\n",ret);
861 	return ret;
862     }
863     old_addr = le32_to_cpu(old_addr);
864 
865     if (((virt_addr == 0xfffffffe) && !BLOCK_FREE(old_addr)) ||
866 	((virt_addr == 0) && (BLOCK_TYPE(old_addr) != BLOCK_DATA)) ||
867 	(!BLOCK_DELETED(virt_addr) && (old_addr != 0xfffffffe))) {
868 	static int ne = 0;
869 	if (++ne < 5) {
870 	    printk(KERN_NOTICE "ftl_cs: set_bam_entry() inconsistency!\n");
871 	    printk(KERN_NOTICE "ftl_cs:   log_addr = 0x%x, old = 0x%x"
872 		   ", new = 0x%x\n", log_addr, old_addr, virt_addr);
873 	}
874 	return -EIO;
875     }
876 #endif
877     le_virt_addr = cpu_to_le32(virt_addr);
878     if (part->bam_index == eun) {
879 #ifdef PSYCHO_DEBUG
880 	if (le32_to_cpu(part->bam_cache[blk]) != old_addr) {
881 	    static int ne = 0;
882 	    if (++ne < 5) {
883 		printk(KERN_NOTICE "ftl_cs: set_bam_entry() "
884 		       "inconsistency!\n");
885 		printk(KERN_NOTICE "ftl_cs:   log_addr = 0x%x, cache"
886 		       " = 0x%x\n",
887 		       le32_to_cpu(part->bam_cache[blk]), old_addr);
888 	    }
889 	    return -EIO;
890 	}
891 #endif
892 	part->bam_cache[blk] = le_virt_addr;
893     }
894     ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int32_t),
895                             &retlen, (u_char *)&le_virt_addr);
896 
897     if (ret) {
898 	printk(KERN_NOTICE "ftl_cs: set_bam_entry() failed!\n");
899 	printk(KERN_NOTICE "ftl_cs:   log_addr = 0x%x, new = 0x%x\n",
900 	       log_addr, virt_addr);
901     }
902     return ret;
903 } /* set_bam_entry */
904 
905 static int ftl_write(partition_t *part, caddr_t buffer,
906 		     u_long sector, u_long nblocks)
907 {
908     u_int32_t bsize, log_addr, virt_addr, old_addr, blk;
909     u_long i;
910     int ret;
911     size_t retlen, offset;
912 
913     DEBUG(2, "ftl_cs: ftl_write(0x%p, %ld, %ld)\n",
914 	  part, sector, nblocks);
915     if (!(part->state & FTL_FORMATTED)) {
916 	printk(KERN_NOTICE "ftl_cs: bad partition\n");
917 	return -EIO;
918     }
919     /* See if we need to reclaim space, before we start */
920     while (part->FreeTotal < nblocks) {
921 	ret = reclaim_block(part);
922 	if (ret)
923 	    return ret;
924     }
925 
926     bsize = 1 << part->header.EraseUnitSize;
927 
928     virt_addr = sector * SECTOR_SIZE | BLOCK_DATA;
929     for (i = 0; i < nblocks; i++) {
930 	if (virt_addr >= le32_to_cpu(part->header.FormattedSize)) {
931 	    printk(KERN_NOTICE "ftl_cs: bad write offset\n");
932 	    return -EIO;
933 	}
934 
935 	/* Grab a free block */
936 	blk = find_free(part);
937 	if (blk == 0) {
938 	    static int ne = 0;
939 	    if (++ne < 5)
940 		printk(KERN_NOTICE "ftl_cs: internal error: "
941 		       "no free blocks!\n");
942 	    return -ENOSPC;
943 	}
944 
945 	/* Tag the BAM entry, and write the new block */
946 	log_addr = part->bam_index * bsize + blk * SECTOR_SIZE;
947 	part->EUNInfo[part->bam_index].Free--;
948 	part->FreeTotal--;
949 	if (set_bam_entry(part, log_addr, 0xfffffffe))
950 	    return -EIO;
951 	part->EUNInfo[part->bam_index].Deleted++;
952 	offset = (part->EUNInfo[part->bam_index].Offset +
953 		      blk * SECTOR_SIZE);
954 	ret = part->mbd.mtd->write(part->mbd.mtd, offset, SECTOR_SIZE, &retlen,
955                                      buffer);
956 
957 	if (ret) {
958 	    printk(KERN_NOTICE "ftl_cs: block write failed!\n");
959 	    printk(KERN_NOTICE "ftl_cs:   log_addr = 0x%x, virt_addr"
960 		   " = 0x%x, Offset = 0x%zx\n", log_addr, virt_addr,
961 		   offset);
962 	    return -EIO;
963 	}
964 
965 	/* Only delete the old entry when the new entry is ready */
966 	old_addr = part->VirtualBlockMap[sector+i];
967 	if (old_addr != 0xffffffff) {
968 	    part->VirtualBlockMap[sector+i] = 0xffffffff;
969 	    part->EUNInfo[old_addr/bsize].Deleted++;
970 	    if (set_bam_entry(part, old_addr, 0))
971 		return -EIO;
972 	}
973 
974 	/* Finally, set up the new pointers */
975 	if (set_bam_entry(part, log_addr, virt_addr))
976 	    return -EIO;
977 	part->VirtualBlockMap[sector+i] = log_addr;
978 	part->EUNInfo[part->bam_index].Deleted--;
979 
980 	buffer += SECTOR_SIZE;
981 	virt_addr += SECTOR_SIZE;
982     }
983     return 0;
984 } /* ftl_write */
985 
986 static int ftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo)
987 {
988 	partition_t *part = (void *)dev;
989 	u_long sect;
990 
991 	/* Sort of arbitrary: round size down to 4KiB boundary */
992 	sect = le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE;
993 
994 	geo->heads = 1;
995 	geo->sectors = 8;
996 	geo->cylinders = sect >> 3;
997 
998 	return 0;
999 }
1000 
1001 static int ftl_readsect(struct mtd_blktrans_dev *dev,
1002 			      unsigned long block, char *buf)
1003 {
1004 	return ftl_read((void *)dev, buf, block, 1);
1005 }
1006 
1007 static int ftl_writesect(struct mtd_blktrans_dev *dev,
1008 			      unsigned long block, char *buf)
1009 {
1010 	return ftl_write((void *)dev, buf, block, 1);
1011 }
1012 
1013 /*====================================================================*/
1014 
1015 static void ftl_freepart(partition_t *part)
1016 {
1017 	vfree(part->VirtualBlockMap);
1018 	part->VirtualBlockMap = NULL;
1019 	kfree(part->VirtualPageMap);
1020 	part->VirtualPageMap = NULL;
1021 	kfree(part->EUNInfo);
1022 	part->EUNInfo = NULL;
1023 	kfree(part->XferInfo);
1024 	part->XferInfo = NULL;
1025 	kfree(part->bam_cache);
1026 	part->bam_cache = NULL;
1027 } /* ftl_freepart */
1028 
1029 static void ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
1030 {
1031 	partition_t *partition;
1032 
1033 	partition = kzalloc(sizeof(partition_t), GFP_KERNEL);
1034 
1035 	if (!partition) {
1036 		printk(KERN_WARNING "No memory to scan for FTL on %s\n",
1037 		       mtd->name);
1038 		return;
1039 	}
1040 
1041 	partition->mbd.mtd = mtd;
1042 
1043 	if ((scan_header(partition) == 0) &&
1044 	    (build_maps(partition) == 0)) {
1045 
1046 		partition->state = FTL_FORMATTED;
1047 #ifdef PCMCIA_DEBUG
1048 		printk(KERN_INFO "ftl_cs: opening %d KiB FTL partition\n",
1049 		       le32_to_cpu(partition->header.FormattedSize) >> 10);
1050 #endif
1051 		partition->mbd.size = le32_to_cpu(partition->header.FormattedSize) >> 9;
1052 
1053 		partition->mbd.tr = tr;
1054 		partition->mbd.devnum = -1;
1055 		if (!add_mtd_blktrans_dev((void *)partition))
1056 			return;
1057 	}
1058 
1059 	ftl_freepart(partition);
1060 	kfree(partition);
1061 }
1062 
1063 static void ftl_remove_dev(struct mtd_blktrans_dev *dev)
1064 {
1065 	del_mtd_blktrans_dev(dev);
1066 	ftl_freepart((partition_t *)dev);
1067 	kfree(dev);
1068 }
1069 
1070 static struct mtd_blktrans_ops ftl_tr = {
1071 	.name		= "ftl",
1072 	.major		= FTL_MAJOR,
1073 	.part_bits	= PART_BITS,
1074 	.blksize 	= SECTOR_SIZE,
1075 	.readsect	= ftl_readsect,
1076 	.writesect	= ftl_writesect,
1077 	.getgeo		= ftl_getgeo,
1078 	.add_mtd	= ftl_add_mtd,
1079 	.remove_dev	= ftl_remove_dev,
1080 	.owner		= THIS_MODULE,
1081 };
1082 
1083 static int init_ftl(void)
1084 {
1085 	DEBUG(0, "$Id: ftl.c,v 1.59 2005/11/29 14:48:31 gleixner Exp $\n");
1086 
1087 	return register_mtd_blktrans(&ftl_tr);
1088 }
1089 
1090 static void __exit cleanup_ftl(void)
1091 {
1092 	deregister_mtd_blktrans(&ftl_tr);
1093 }
1094 
1095 module_init(init_ftl);
1096 module_exit(cleanup_ftl);
1097 
1098 
1099 MODULE_LICENSE("Dual MPL/GPL");
1100 MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
1101 MODULE_DESCRIPTION("Support code for Flash Translation Layer, used on PCMCIA devices");
1102