diff options
author | Sean Young <sean@mess.org> | 2006-05-17 07:45:34 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2006-05-17 07:45:34 -0400 |
commit | 683b30c8e78ab363dc8d8c94bdb61b64d1f6f5e2 (patch) | |
tree | 85ec4bf9ee63e8531c338c82c0609c48c7618d09 /drivers/mtd | |
parent | ae282d497d5631ce31539717131c760e3872c539 (diff) |
[MTD] RFD FTL: Be noisier, and don't assume block without RFD magic are erased
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/rfd_ftl.c | 48 |
1 files changed, 25 insertions, 23 deletions
diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c index a3e00a4635a5..fa4362fb4dd8 100644 --- a/drivers/mtd/rfd_ftl.c +++ b/drivers/mtd/rfd_ftl.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2005 Sean Young <sean@mess.org> | 4 | * Copyright (C) 2005 Sean Young <sean@mess.org> |
5 | * | 5 | * |
6 | * $Id: rfd_ftl.c,v 1.5 2005/11/07 11:14:21 gleixner Exp $ | 6 | * $Id: rfd_ftl.c,v 1.8 2006/01/15 12:51:44 sean Exp $ |
7 | * | 7 | * |
8 | * This type of flash translation layer (FTL) is used by the Embedded BIOS | 8 | * This type of flash translation layer (FTL) is used by the Embedded BIOS |
9 | * by General Software. It is known as the Resident Flash Disk (RFD), see: | 9 | * by General Software. It is known as the Resident Flash Disk (RFD), see: |
@@ -61,6 +61,7 @@ struct block { | |||
61 | BLOCK_OK, | 61 | BLOCK_OK, |
62 | BLOCK_ERASING, | 62 | BLOCK_ERASING, |
63 | BLOCK_ERASED, | 63 | BLOCK_ERASED, |
64 | BLOCK_UNUSED, | ||
64 | BLOCK_FAILED | 65 | BLOCK_FAILED |
65 | } state; | 66 | } state; |
66 | int free_sectors; | 67 | int free_sectors; |
@@ -99,10 +100,8 @@ static int build_block_map(struct partition *part, int block_no) | |||
99 | block->offset = part->block_size * block_no; | 100 | block->offset = part->block_size * block_no; |
100 | 101 | ||
101 | if (le16_to_cpu(part->header_cache[0]) != RFD_MAGIC) { | 102 | if (le16_to_cpu(part->header_cache[0]) != RFD_MAGIC) { |
102 | block->state = BLOCK_ERASED; /* assumption */ | 103 | block->state = BLOCK_UNUSED; |
103 | block->free_sectors = part->data_sectors_per_block; | 104 | return -ENOENT; |
104 | part->reserved_block = block_no; | ||
105 | return 1; | ||
106 | } | 105 | } |
107 | 106 | ||
108 | block->state = BLOCK_OK; | 107 | block->state = BLOCK_OK; |
@@ -124,7 +123,7 @@ static int build_block_map(struct partition *part, int block_no) | |||
124 | entry = 0; | 123 | entry = 0; |
125 | 124 | ||
126 | if (entry >= part->sector_count) { | 125 | if (entry >= part->sector_count) { |
127 | printk(KERN_NOTICE PREFIX | 126 | printk(KERN_WARNING PREFIX |
128 | "'%s': unit #%d: entry %d corrupt, " | 127 | "'%s': unit #%d: entry %d corrupt, " |
129 | "sector %d out of range\n", | 128 | "sector %d out of range\n", |
130 | part->mbd.mtd->name, block_no, i, entry); | 129 | part->mbd.mtd->name, block_no, i, entry); |
@@ -132,7 +131,7 @@ static int build_block_map(struct partition *part, int block_no) | |||
132 | } | 131 | } |
133 | 132 | ||
134 | if (part->sector_map[entry] != -1) { | 133 | if (part->sector_map[entry] != -1) { |
135 | printk(KERN_NOTICE PREFIX | 134 | printk(KERN_WARNING PREFIX |
136 | "'%s': more than one entry for sector %d\n", | 135 | "'%s': more than one entry for sector %d\n", |
137 | part->mbd.mtd->name, entry); | 136 | part->mbd.mtd->name, entry); |
138 | part->errors = 1; | 137 | part->errors = 1; |
@@ -167,7 +166,7 @@ static int scan_header(struct partition *part) | |||
167 | /* each erase block has three bytes header, followed by the map */ | 166 | /* each erase block has three bytes header, followed by the map */ |
168 | part->header_sectors_per_block = | 167 | part->header_sectors_per_block = |
169 | ((HEADER_MAP_OFFSET + sectors_per_block) * | 168 | ((HEADER_MAP_OFFSET + sectors_per_block) * |
170 | sizeof(u16) + SECTOR_SIZE - 1) / SECTOR_SIZE; | 169 | sizeof(u16) + SECTOR_SIZE - 1) / SECTOR_SIZE; |
171 | 170 | ||
172 | part->data_sectors_per_block = sectors_per_block - | 171 | part->data_sectors_per_block = sectors_per_block - |
173 | part->header_sectors_per_block; | 172 | part->header_sectors_per_block; |
@@ -226,7 +225,7 @@ static int scan_header(struct partition *part) | |||
226 | } | 225 | } |
227 | 226 | ||
228 | if (part->reserved_block == -1) { | 227 | if (part->reserved_block == -1) { |
229 | printk(KERN_NOTICE PREFIX "'%s': no empty erase unit found\n", | 228 | printk(KERN_WARNING PREFIX "'%s': no empty erase unit found\n", |
230 | part->mbd.mtd->name); | 229 | part->mbd.mtd->name); |
231 | 230 | ||
232 | part->errors = 1; | 231 | part->errors = 1; |
@@ -315,7 +314,7 @@ static void erase_callback(struct erase_info *erase) | |||
315 | rc = -EIO; | 314 | rc = -EIO; |
316 | 315 | ||
317 | if (rc) { | 316 | if (rc) { |
318 | printk(KERN_NOTICE PREFIX "'%s': unable to write RFD " | 317 | printk(KERN_ERR PREFIX "'%s': unable to write RFD " |
319 | "header at 0x%lx\n", | 318 | "header at 0x%lx\n", |
320 | part->mbd.mtd->name, | 319 | part->mbd.mtd->name, |
321 | part->blocks[i].offset); | 320 | part->blocks[i].offset); |
@@ -348,7 +347,7 @@ static int erase_block(struct partition *part, int block) | |||
348 | rc = part->mbd.mtd->erase(part->mbd.mtd, erase); | 347 | rc = part->mbd.mtd->erase(part->mbd.mtd, erase); |
349 | 348 | ||
350 | if (rc) { | 349 | if (rc) { |
351 | printk(KERN_WARNING PREFIX "erase of region %x,%x on '%s' " | 350 | printk(KERN_ERR PREFIX "erase of region %x,%x on '%s' " |
352 | "failed\n", erase->addr, erase->len, | 351 | "failed\n", erase->addr, erase->len, |
353 | part->mbd.mtd->name); | 352 | part->mbd.mtd->name); |
354 | kfree(erase); | 353 | kfree(erase); |
@@ -383,7 +382,7 @@ static int move_block_contents(struct partition *part, int block_no, u_long *old | |||
383 | rc = -EIO; | 382 | rc = -EIO; |
384 | 383 | ||
385 | if (rc) { | 384 | if (rc) { |
386 | printk(KERN_NOTICE PREFIX "error reading '%s' at " | 385 | printk(KERN_ERR PREFIX "error reading '%s' at " |
387 | "0x%lx\n", part->mbd.mtd->name, | 386 | "0x%lx\n", part->mbd.mtd->name, |
388 | part->blocks[block_no].offset); | 387 | part->blocks[block_no].offset); |
389 | 388 | ||
@@ -423,7 +422,7 @@ static int move_block_contents(struct partition *part, int block_no, u_long *old | |||
423 | rc = -EIO; | 422 | rc = -EIO; |
424 | 423 | ||
425 | if (rc) { | 424 | if (rc) { |
426 | printk(KERN_NOTICE PREFIX "'%s': Unable to " | 425 | printk(KERN_ERR PREFIX "'%s': Unable to " |
427 | "read sector for relocation\n", | 426 | "read sector for relocation\n", |
428 | part->mbd.mtd->name); | 427 | part->mbd.mtd->name); |
429 | 428 | ||
@@ -520,7 +519,7 @@ static int reclaim_block(struct partition *part, u_long *old_sector) | |||
520 | * because if we fill that one up first it'll have the most chance of having | 519 | * because if we fill that one up first it'll have the most chance of having |
521 | * the least live sectors at reclaim. | 520 | * the least live sectors at reclaim. |
522 | */ | 521 | */ |
523 | static int find_free_block(const struct partition *part) | 522 | static int find_free_block(struct partition *part) |
524 | { | 523 | { |
525 | int block, stop; | 524 | int block, stop; |
526 | 525 | ||
@@ -533,6 +532,9 @@ static int find_free_block(const struct partition *part) | |||
533 | block != part->reserved_block) | 532 | block != part->reserved_block) |
534 | return block; | 533 | return block; |
535 | 534 | ||
535 | if (part->blocks[block].state == BLOCK_UNUSED) | ||
536 | erase_block(part, block); | ||
537 | |||
536 | if (++block >= part->total_blocks) | 538 | if (++block >= part->total_blocks) |
537 | block = 0; | 539 | block = 0; |
538 | 540 | ||
@@ -541,7 +543,7 @@ static int find_free_block(const struct partition *part) | |||
541 | return -1; | 543 | return -1; |
542 | } | 544 | } |
543 | 545 | ||
544 | static int find_writeable_block(struct partition *part, u_long *old_sector) | 546 | static int find_writable_block(struct partition *part, u_long *old_sector) |
545 | { | 547 | { |
546 | int rc, block; | 548 | int rc, block; |
547 | size_t retlen; | 549 | size_t retlen; |
@@ -570,7 +572,7 @@ static int find_writeable_block(struct partition *part, u_long *old_sector) | |||
570 | rc = -EIO; | 572 | rc = -EIO; |
571 | 573 | ||
572 | if (rc) { | 574 | if (rc) { |
573 | printk(KERN_NOTICE PREFIX "'%s': unable to read header at " | 575 | printk(KERN_ERR PREFIX "'%s': unable to read header at " |
574 | "0x%lx\n", part->mbd.mtd->name, | 576 | "0x%lx\n", part->mbd.mtd->name, |
575 | part->blocks[block].offset); | 577 | part->blocks[block].offset); |
576 | goto err; | 578 | goto err; |
@@ -602,7 +604,7 @@ static int mark_sector_deleted(struct partition *part, u_long old_addr) | |||
602 | rc = -EIO; | 604 | rc = -EIO; |
603 | 605 | ||
604 | if (rc) { | 606 | if (rc) { |
605 | printk(KERN_WARNING PREFIX "error writing '%s' at " | 607 | printk(KERN_ERR PREFIX "error writing '%s' at " |
606 | "0x%lx\n", part->mbd.mtd->name, addr); | 608 | "0x%lx\n", part->mbd.mtd->name, addr); |
607 | if (rc) | 609 | if (rc) |
608 | goto err; | 610 | goto err; |
@@ -652,7 +654,7 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf, | |||
652 | if (part->current_block == -1 || | 654 | if (part->current_block == -1 || |
653 | !part->blocks[part->current_block].free_sectors) { | 655 | !part->blocks[part->current_block].free_sectors) { |
654 | 656 | ||
655 | rc = find_writeable_block(part, old_addr); | 657 | rc = find_writable_block(part, old_addr); |
656 | if (rc) | 658 | if (rc) |
657 | goto err; | 659 | goto err; |
658 | } | 660 | } |
@@ -675,7 +677,7 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf, | |||
675 | rc = -EIO; | 677 | rc = -EIO; |
676 | 678 | ||
677 | if (rc) { | 679 | if (rc) { |
678 | printk(KERN_WARNING PREFIX "error writing '%s' at 0x%lx\n", | 680 | printk(KERN_ERR PREFIX "error writing '%s' at 0x%lx\n", |
679 | part->mbd.mtd->name, addr); | 681 | part->mbd.mtd->name, addr); |
680 | if (rc) | 682 | if (rc) |
681 | goto err; | 683 | goto err; |
@@ -695,7 +697,7 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf, | |||
695 | rc = -EIO; | 697 | rc = -EIO; |
696 | 698 | ||
697 | if (rc) { | 699 | if (rc) { |
698 | printk(KERN_WARNING PREFIX "error writing '%s' at 0x%lx\n", | 700 | printk(KERN_ERR PREFIX "error writing '%s' at 0x%lx\n", |
699 | part->mbd.mtd->name, addr); | 701 | part->mbd.mtd->name, addr); |
700 | if (rc) | 702 | if (rc) |
701 | goto err; | 703 | goto err; |
@@ -776,7 +778,7 @@ static void rfd_ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) | |||
776 | part->block_size = block_size; | 778 | part->block_size = block_size; |
777 | else { | 779 | else { |
778 | if (!mtd->erasesize) { | 780 | if (!mtd->erasesize) { |
779 | printk(KERN_NOTICE PREFIX "please provide block_size"); | 781 | printk(KERN_WARNING PREFIX "please provide block_size"); |
780 | return; | 782 | return; |
781 | } | 783 | } |
782 | else | 784 | else |
@@ -791,8 +793,8 @@ static void rfd_ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) | |||
791 | if (!(mtd->flags & MTD_WRITEABLE)) | 793 | if (!(mtd->flags & MTD_WRITEABLE)) |
792 | part->mbd.readonly = 1; | 794 | part->mbd.readonly = 1; |
793 | else if (part->errors) { | 795 | else if (part->errors) { |
794 | printk(KERN_NOTICE PREFIX "'%s': errors found, " | 796 | printk(KERN_WARNING PREFIX "'%s': errors found, " |
795 | "setting read-only", mtd->name); | 797 | "setting read-only\n", mtd->name); |
796 | part->mbd.readonly = 1; | 798 | part->mbd.readonly = 1; |
797 | } | 799 | } |
798 | 800 | ||