aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/inftlcore.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/inftlcore.c')
-rw-r--r--drivers/mtd/inftlcore.c60
1 files changed, 28 insertions, 32 deletions
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c
index 39eb53f6551f..8a544890173d 100644
--- a/drivers/mtd/inftlcore.c
+++ b/drivers/mtd/inftlcore.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * inftlcore.c -- Linux driver for Inverse Flash Translation Layer (INFTL) 2 * inftlcore.c -- Linux driver for Inverse Flash Translation Layer (INFTL)
3 * 3 *
4 * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com) 4 * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
@@ -7,7 +7,7 @@
7 * (c) 1999 Machine Vision Holdings, Inc. 7 * (c) 1999 Machine Vision Holdings, Inc.
8 * Author: David Woodhouse <dwmw2@infradead.org> 8 * Author: David Woodhouse <dwmw2@infradead.org>
9 * 9 *
10 * $Id: inftlcore.c,v 1.18 2004/11/16 18:28:59 dwmw2 Exp $ 10 * $Id: inftlcore.c,v 1.19 2005/11/07 11:14:20 gleixner Exp $
11 * 11 *
12 * This program is free software; you can redistribute it and/or modify 12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by 13 * it under the terms of the GNU General Public License as published by
@@ -113,23 +113,21 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
113 113
114 if (inftl->mbd.size != inftl->heads * inftl->cylinders * inftl->sectors) { 114 if (inftl->mbd.size != inftl->heads * inftl->cylinders * inftl->sectors) {
115 /* 115 /*
116 Oh no we don't have 116 Oh no we don't have
117 mbd.size == heads * cylinders * sectors 117 mbd.size == heads * cylinders * sectors
118 */ 118 */
119 printk(KERN_WARNING "INFTL: cannot calculate a geometry to " 119 printk(KERN_WARNING "INFTL: cannot calculate a geometry to "
120 "match size of 0x%lx.\n", inftl->mbd.size); 120 "match size of 0x%lx.\n", inftl->mbd.size);
121 printk(KERN_WARNING "INFTL: using C:%d H:%d S:%d " 121 printk(KERN_WARNING "INFTL: using C:%d H:%d S:%d "
122 "(== 0x%lx sects)\n", 122 "(== 0x%lx sects)\n",
123 inftl->cylinders, inftl->heads , inftl->sectors, 123 inftl->cylinders, inftl->heads , inftl->sectors,
124 (long)inftl->cylinders * (long)inftl->heads * 124 (long)inftl->cylinders * (long)inftl->heads *
125 (long)inftl->sectors ); 125 (long)inftl->sectors );
126 } 126 }
127 127
128 if (add_mtd_blktrans_dev(&inftl->mbd)) { 128 if (add_mtd_blktrans_dev(&inftl->mbd)) {
129 if (inftl->PUtable) 129 kfree(inftl->PUtable);
130 kfree(inftl->PUtable); 130 kfree(inftl->VUtable);
131 if (inftl->VUtable)
132 kfree(inftl->VUtable);
133 kfree(inftl); 131 kfree(inftl);
134 return; 132 return;
135 } 133 }
@@ -147,10 +145,8 @@ static void inftl_remove_dev(struct mtd_blktrans_dev *dev)
147 145
148 del_mtd_blktrans_dev(dev); 146 del_mtd_blktrans_dev(dev);
149 147
150 if (inftl->PUtable) 148 kfree(inftl->PUtable);
151 kfree(inftl->PUtable); 149 kfree(inftl->VUtable);
152 if (inftl->VUtable)
153 kfree(inftl->VUtable);
154 kfree(inftl); 150 kfree(inftl);
155} 151}
156 152
@@ -223,7 +219,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
223 "Virtual Unit Chain %d!\n", thisVUC); 219 "Virtual Unit Chain %d!\n", thisVUC);
224 return BLOCK_NIL; 220 return BLOCK_NIL;
225 } 221 }
226 222
227 /* 223 /*
228 * Scan to find the Erase Unit which holds the actual data for each 224 * Scan to find the Erase Unit which holds the actual data for each
229 * 512-byte block within the Chain. 225 * 512-byte block within the Chain.
@@ -264,7 +260,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
264 "Unit Chain 0x%x\n", thisVUC); 260 "Unit Chain 0x%x\n", thisVUC);
265 return BLOCK_NIL; 261 return BLOCK_NIL;
266 } 262 }
267 263
268 thisEUN = inftl->PUtable[thisEUN]; 264 thisEUN = inftl->PUtable[thisEUN];
269 } 265 }
270 266
@@ -295,15 +291,15 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
295 */ 291 */
296 if (BlockMap[block] == BLOCK_NIL) 292 if (BlockMap[block] == BLOCK_NIL)
297 continue; 293 continue;
298 294
299 ret = MTD_READ(inftl->mbd.mtd, (inftl->EraseSize * 295 ret = MTD_READ(inftl->mbd.mtd, (inftl->EraseSize *
300 BlockMap[block]) + (block * SECTORSIZE), SECTORSIZE, 296 BlockMap[block]) + (block * SECTORSIZE), SECTORSIZE,
301 &retlen, movebuf); 297 &retlen, movebuf);
302 if (ret < 0) { 298 if (ret < 0) {
303 ret = MTD_READ(inftl->mbd.mtd, (inftl->EraseSize * 299 ret = MTD_READ(inftl->mbd.mtd, (inftl->EraseSize *
304 BlockMap[block]) + (block * SECTORSIZE), 300 BlockMap[block]) + (block * SECTORSIZE),
305 SECTORSIZE, &retlen, movebuf); 301 SECTORSIZE, &retlen, movebuf);
306 if (ret != -EIO) 302 if (ret != -EIO)
307 DEBUG(MTD_DEBUG_LEVEL1, "INFTL: error went " 303 DEBUG(MTD_DEBUG_LEVEL1, "INFTL: error went "
308 "away on retry?\n"); 304 "away on retry?\n");
309 } 305 }
@@ -355,7 +351,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
355static u16 INFTL_makefreeblock(struct INFTLrecord *inftl, unsigned pendingblock) 351static u16 INFTL_makefreeblock(struct INFTLrecord *inftl, unsigned pendingblock)
356{ 352{
357 /* 353 /*
358 * This is the part that needs some cleverness applied. 354 * This is the part that needs some cleverness applied.
359 * For now, I'm doing the minimum applicable to actually 355 * For now, I'm doing the minimum applicable to actually
360 * get the thing to work. 356 * get the thing to work.
361 * Wear-levelling and other clever stuff needs to be implemented 357 * Wear-levelling and other clever stuff needs to be implemented
@@ -414,7 +410,7 @@ static int nrbits(unsigned int val, int bitcount)
414} 410}
415 411
416/* 412/*
417 * INFTL_findwriteunit: Return the unit number into which we can write 413 * INFTL_findwriteunit: Return the unit number into which we can write
418 * for this block. Make it available if it isn't already. 414 * for this block. Make it available if it isn't already.
419 */ 415 */
420static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block) 416static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)
@@ -463,10 +459,10 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)
463 * Invalid block. Don't use it any more. 459 * Invalid block. Don't use it any more.
464 * Must implement. 460 * Must implement.
465 */ 461 */
466 break; 462 break;
467 } 463 }
468 464
469 if (!silly--) { 465 if (!silly--) {
470 printk(KERN_WARNING "INFTL: infinite loop in " 466 printk(KERN_WARNING "INFTL: infinite loop in "
471 "Virtual Unit Chain 0x%x\n", thisVUC); 467 "Virtual Unit Chain 0x%x\n", thisVUC);
472 return 0xffff; 468 return 0xffff;
@@ -482,7 +478,7 @@ hitused:
482 478
483 479
484 /* 480 /*
485 * OK. We didn't find one in the existing chain, or there 481 * OK. We didn't find one in the existing chain, or there
486 * is no existing chain. Allocate a new one. 482 * is no existing chain. Allocate a new one.
487 */ 483 */
488 writeEUN = INFTL_findfreeblock(inftl, 0); 484 writeEUN = INFTL_findfreeblock(inftl, 0);
@@ -506,8 +502,8 @@ hitused:
506 if (writeEUN == BLOCK_NIL) { 502 if (writeEUN == BLOCK_NIL) {
507 /* 503 /*
508 * Ouch. This should never happen - we should 504 * Ouch. This should never happen - we should
509 * always be able to make some room somehow. 505 * always be able to make some room somehow.
510 * If we get here, we've allocated more storage 506 * If we get here, we've allocated more storage
511 * space than actual media, or our makefreeblock 507 * space than actual media, or our makefreeblock
512 * routine is missing something. 508 * routine is missing something.
513 */ 509 */
@@ -518,7 +514,7 @@ hitused:
518 INFTL_dumpVUchains(inftl); 514 INFTL_dumpVUchains(inftl);
519#endif 515#endif
520 return BLOCK_NIL; 516 return BLOCK_NIL;
521 } 517 }
522 } 518 }
523 519
524 /* 520 /*
@@ -543,7 +539,7 @@ hitused:
543 parity |= (nrbits(prev_block, 16) & 0x1) ? 0x2 : 0; 539 parity |= (nrbits(prev_block, 16) & 0x1) ? 0x2 : 0;
544 parity |= (nrbits(anac, 8) & 0x1) ? 0x4 : 0; 540 parity |= (nrbits(anac, 8) & 0x1) ? 0x4 : 0;
545 parity |= (nrbits(nacs, 8) & 0x1) ? 0x8 : 0; 541 parity |= (nrbits(nacs, 8) & 0x1) ? 0x8 : 0;
546 542
547 oob.u.a.virtualUnitNo = cpu_to_le16(thisVUC); 543 oob.u.a.virtualUnitNo = cpu_to_le16(thisVUC);
548 oob.u.a.prevUnitNo = cpu_to_le16(prev_block); 544 oob.u.a.prevUnitNo = cpu_to_le16(prev_block);
549 oob.u.a.ANAC = anac; 545 oob.u.a.ANAC = anac;
@@ -562,7 +558,7 @@ hitused:
562 oob.u.b.parityPerField = parity; 558 oob.u.b.parityPerField = parity;
563 oob.u.b.discarded = 0xaa; 559 oob.u.b.discarded = 0xaa;
564 560
565 MTD_WRITEOOB(inftl->mbd.mtd, writeEUN * inftl->EraseSize + 561 MTD_WRITEOOB(inftl->mbd.mtd, writeEUN * inftl->EraseSize +
566 SECTORSIZE * 4 + 8, 8, &retlen, (char *)&oob.u); 562 SECTORSIZE * 4 + 8, 8, &retlen, (char *)&oob.u);
567 563
568 inftl->PUtable[writeEUN] = inftl->VUtable[thisVUC]; 564 inftl->PUtable[writeEUN] = inftl->VUtable[thisVUC];
@@ -602,7 +598,7 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
602 "Virtual Unit Chain %d!\n", thisVUC); 598 "Virtual Unit Chain %d!\n", thisVUC);
603 return; 599 return;
604 } 600 }
605 601
606 /* 602 /*
607 * Scan through the Erase Units to determine whether any data is in 603 * Scan through the Erase Units to determine whether any data is in
608 * each of the 512-byte blocks within the Chain. 604 * each of the 512-byte blocks within the Chain.
@@ -642,7 +638,7 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
642 "Unit Chain 0x%x\n", thisVUC); 638 "Unit Chain 0x%x\n", thisVUC);
643 return; 639 return;
644 } 640 }
645 641
646 thisEUN = inftl->PUtable[thisEUN]; 642 thisEUN = inftl->PUtable[thisEUN];
647 } 643 }
648 644
@@ -758,7 +754,7 @@ foundit:
758 return 0; 754 return 0;
759} 755}
760 756
761static int inftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block, 757static int inftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block,
762 char *buffer) 758 char *buffer)
763{ 759{
764 struct INFTLrecord *inftl = (void *)mbd; 760 struct INFTLrecord *inftl = (void *)mbd;
@@ -893,7 +889,7 @@ extern char inftlmountrev[];
893 889
894static int __init init_inftl(void) 890static int __init init_inftl(void)
895{ 891{
896 printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.18 $, " 892 printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.19 $, "
897 "inftlmount.c %s\n", inftlmountrev); 893 "inftlmount.c %s\n", inftlmountrev);
898 894
899 return register_mtd_blktrans(&inftl_tr); 895 return register_mtd_blktrans(&inftl_tr);