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