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