^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * rfd_ftl.c -- resident flash disk (flash translation layer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright © 2005 Sean Young <sean@mess.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This type of flash translation layer (FTL) is used by the Embedded BIOS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * by General Software. It is known as the Resident Flash Disk (RFD), see:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * http://www.gensw.com/pages/prod/bios/rfd.htm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * based on ftl.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/hdreg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/mtd/blktrans.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/mtd/mtd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <asm/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static int block_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) module_param(block_size, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) MODULE_PARM_DESC(block_size, "Block size to use by RFD, defaults to erase unit size");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define PREFIX "rfd_ftl: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /* This major has been assigned by device@lanana.org */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #ifndef RFD_FTL_MAJOR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define RFD_FTL_MAJOR 256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /* Maximum number of partitions in an FTL region */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define PART_BITS 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* An erase unit should start with this value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define RFD_MAGIC 0x9193
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /* the second value is 0xffff or 0xffc8; function unknown */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /* the third value is always 0xffff, ignored */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* next is an array of mapping for each corresponding sector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define HEADER_MAP_OFFSET 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define SECTOR_DELETED 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define SECTOR_ZERO 0xfffe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define SECTOR_FREE 0xffff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define SECTOR_SIZE 512
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define SECTORS_PER_TRACK 63
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct block {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) BLOCK_OK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) BLOCK_ERASING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) BLOCK_ERASED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) BLOCK_UNUSED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) BLOCK_FAILED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) } state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) int free_sectors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) int used_sectors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) int erases;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) u_long offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct partition {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct mtd_blktrans_dev mbd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) u_int block_size; /* size of erase unit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) u_int total_blocks; /* number of erase units */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) u_int header_sectors_per_block; /* header sectors in erase unit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) u_int data_sectors_per_block; /* data sectors in erase unit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) u_int sector_count; /* sectors in translated disk */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) u_int header_size; /* bytes in header sector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) int reserved_block; /* block next up for reclaim */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) int current_block; /* block to write to */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) u16 *header_cache; /* cached header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) int is_reclaiming;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) int cylinders;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) int errors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) u_long *sector_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) struct block *blocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static int rfd_ftl_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static int build_block_map(struct partition *part, int block_no)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct block *block = &part->blocks[block_no];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) block->offset = part->block_size * block_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (le16_to_cpu(part->header_cache[0]) != RFD_MAGIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) block->state = BLOCK_UNUSED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) block->state = BLOCK_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) for (i=0; i<part->data_sectors_per_block; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) u16 entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) entry = le16_to_cpu(part->header_cache[HEADER_MAP_OFFSET + i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (entry == SECTOR_DELETED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (entry == SECTOR_FREE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) block->free_sectors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (entry == SECTOR_ZERO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) entry = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (entry >= part->sector_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) printk(KERN_WARNING PREFIX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) "'%s': unit #%d: entry %d corrupt, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) "sector %d out of range\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) part->mbd.mtd->name, block_no, i, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (part->sector_map[entry] != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) printk(KERN_WARNING PREFIX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) "'%s': more than one entry for sector %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) part->mbd.mtd->name, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) part->errors = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) part->sector_map[entry] = block->offset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) (i + part->header_sectors_per_block) * SECTOR_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) block->used_sectors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (block->free_sectors == part->data_sectors_per_block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) part->reserved_block = block_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static int scan_header(struct partition *part)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) int sectors_per_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) int i, rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) int blocks_found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) size_t retlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) sectors_per_block = part->block_size / SECTOR_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) part->total_blocks = (u32)part->mbd.mtd->size / part->block_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (part->total_blocks < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) /* each erase block has three bytes header, followed by the map */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) part->header_sectors_per_block =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) ((HEADER_MAP_OFFSET + sectors_per_block) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) sizeof(u16) + SECTOR_SIZE - 1) / SECTOR_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) part->data_sectors_per_block = sectors_per_block -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) part->header_sectors_per_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) part->header_size = (HEADER_MAP_OFFSET +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) part->data_sectors_per_block) * sizeof(u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) part->cylinders = (part->data_sectors_per_block *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) (part->total_blocks - 1) - 1) / SECTORS_PER_TRACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) part->sector_count = part->cylinders * SECTORS_PER_TRACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) part->current_block = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) part->reserved_block = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) part->is_reclaiming = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) part->header_cache = kmalloc(part->header_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (!part->header_cache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) part->blocks = kcalloc(part->total_blocks, sizeof(struct block),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (!part->blocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) part->sector_map = vmalloc(array_size(sizeof(u_long),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) part->sector_count));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (!part->sector_map) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) printk(KERN_ERR PREFIX "'%s': unable to allocate memory for "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) "sector map", part->mbd.mtd->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) for (i=0; i<part->sector_count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) part->sector_map[i] = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) for (i=0, blocks_found=0; i<part->total_blocks; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) rc = mtd_read(part->mbd.mtd, i * part->block_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) part->header_size, &retlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) (u_char *)part->header_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (!rc && retlen != part->header_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (!build_block_map(part, i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) blocks_found++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (blocks_found == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) printk(KERN_NOTICE PREFIX "no RFD magic found in '%s'\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) part->mbd.mtd->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) rc = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (part->reserved_block == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) printk(KERN_WARNING PREFIX "'%s': no empty erase unit found\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) part->mbd.mtd->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) part->errors = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) vfree(part->sector_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) kfree(part->header_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) kfree(part->blocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) static int rfd_ftl_readsect(struct mtd_blktrans_dev *dev, u_long sector, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) struct partition *part = (struct partition*)dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) u_long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) size_t retlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (sector >= part->sector_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) addr = part->sector_map[sector];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (addr != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) rc = mtd_read(part->mbd.mtd, addr, SECTOR_SIZE, &retlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) (u_char *)buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (!rc && retlen != SECTOR_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) printk(KERN_WARNING PREFIX "error reading '%s' at "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) "0x%lx\n", part->mbd.mtd->name, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) memset(buf, 0, SECTOR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static int erase_block(struct partition *part, int block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) struct erase_info *erase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) erase = kmalloc(sizeof(struct erase_info), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (!erase)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) erase->addr = part->blocks[block].offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) erase->len = part->block_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) part->blocks[block].state = BLOCK_ERASING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) part->blocks[block].free_sectors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) rc = mtd_erase(part->mbd.mtd, erase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) printk(KERN_ERR PREFIX "erase of region %llx,%llx on '%s' "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) "failed\n", (unsigned long long)erase->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) (unsigned long long)erase->len, part->mbd.mtd->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) part->blocks[block].state = BLOCK_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) part->blocks[block].free_sectors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) part->blocks[block].used_sectors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) u16 magic = cpu_to_le16(RFD_MAGIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) size_t retlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) part->blocks[block].state = BLOCK_ERASED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) part->blocks[block].free_sectors = part->data_sectors_per_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) part->blocks[block].used_sectors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) part->blocks[block].erases++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) rc = mtd_write(part->mbd.mtd, part->blocks[block].offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) sizeof(magic), &retlen, (u_char *)&magic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (!rc && retlen != sizeof(magic))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) pr_err(PREFIX "'%s': unable to write RFD header at 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) part->mbd.mtd->name, part->blocks[block].offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) part->blocks[block].state = BLOCK_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) part->blocks[block].state = BLOCK_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) kfree(erase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) static int move_block_contents(struct partition *part, int block_no, u_long *old_sector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) void *sector_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) u16 *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) size_t retlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) int i, rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) part->is_reclaiming = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) sector_data = kmalloc(SECTOR_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (!sector_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) goto err3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) map = kmalloc(part->header_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (!map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) goto err2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) rc = mtd_read(part->mbd.mtd, part->blocks[block_no].offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) part->header_size, &retlen, (u_char *)map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (!rc && retlen != part->header_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) printk(KERN_ERR PREFIX "error reading '%s' at "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) "0x%lx\n", part->mbd.mtd->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) part->blocks[block_no].offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) for (i=0; i<part->data_sectors_per_block; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) u16 entry = le16_to_cpu(map[HEADER_MAP_OFFSET + i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) u_long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (entry == SECTOR_FREE || entry == SECTOR_DELETED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (entry == SECTOR_ZERO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) entry = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) /* already warned about and ignored in build_block_map() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (entry >= part->sector_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) addr = part->blocks[block_no].offset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) (i + part->header_sectors_per_block) * SECTOR_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (*old_sector == addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) *old_sector = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (!part->blocks[block_no].used_sectors--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) rc = erase_block(part, block_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) rc = mtd_read(part->mbd.mtd, addr, SECTOR_SIZE, &retlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) sector_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (!rc && retlen != SECTOR_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) printk(KERN_ERR PREFIX "'%s': Unable to "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) "read sector for relocation\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) part->mbd.mtd->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) rc = rfd_ftl_writesect((struct mtd_blktrans_dev*)part,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) entry, sector_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) kfree(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) err2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) kfree(sector_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) err3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) part->is_reclaiming = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) static int reclaim_block(struct partition *part, u_long *old_sector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) int block, best_block, score, old_sector_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) /* we have a race if sync doesn't exist */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) mtd_sync(part->mbd.mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) score = 0x7fffffff; /* MAX_INT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) best_block = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (*old_sector != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) old_sector_block = *old_sector / part->block_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) old_sector_block = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) for (block=0; block<part->total_blocks; block++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) int this_score;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (block == part->reserved_block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) * Postpone reclaiming if there is a free sector as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) * more removed sectors is more efficient (have to move
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) * less).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (part->blocks[block].free_sectors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) this_score = part->blocks[block].used_sectors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (block == old_sector_block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) this_score--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) /* no point in moving a full block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (part->blocks[block].used_sectors ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) part->data_sectors_per_block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) this_score += part->blocks[block].erases;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (this_score < score) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) best_block = block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) score = this_score;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (best_block == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) part->current_block = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) part->reserved_block = best_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) pr_debug("reclaim_block: reclaiming block #%d with %d used "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) "%d free sectors\n", best_block,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) part->blocks[best_block].used_sectors,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) part->blocks[best_block].free_sectors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (part->blocks[best_block].used_sectors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) rc = move_block_contents(part, best_block, old_sector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) rc = erase_block(part, best_block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) * IMPROVE: It would be best to choose the block with the most deleted sectors,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) * because if we fill that one up first it'll have the most chance of having
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) * the least live sectors at reclaim.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) static int find_free_block(struct partition *part)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) int block, stop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) block = part->current_block == -1 ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) jiffies % part->total_blocks : part->current_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) stop = block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (part->blocks[block].free_sectors &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) block != part->reserved_block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) return block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) if (part->blocks[block].state == BLOCK_UNUSED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) erase_block(part, block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (++block >= part->total_blocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) block = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) } while (block != stop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) static int find_writable_block(struct partition *part, u_long *old_sector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) int rc, block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) size_t retlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) block = find_free_block(part);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (block == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (!part->is_reclaiming) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) rc = reclaim_block(part, old_sector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) block = find_free_block(part);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) if (block == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) rc = -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) rc = mtd_read(part->mbd.mtd, part->blocks[block].offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) part->header_size, &retlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) (u_char *)part->header_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (!rc && retlen != part->header_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) printk(KERN_ERR PREFIX "'%s': unable to read header at "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) "0x%lx\n", part->mbd.mtd->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) part->blocks[block].offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) part->current_block = block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) static int mark_sector_deleted(struct partition *part, u_long old_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) int block, offset, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) u_long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) size_t retlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) u16 del = cpu_to_le16(SECTOR_DELETED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) block = old_addr / part->block_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) offset = (old_addr % part->block_size) / SECTOR_SIZE -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) part->header_sectors_per_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) addr = part->blocks[block].offset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) (HEADER_MAP_OFFSET + offset) * sizeof(u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) rc = mtd_write(part->mbd.mtd, addr, sizeof(del), &retlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) (u_char *)&del);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) if (!rc && retlen != sizeof(del))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) printk(KERN_ERR PREFIX "error writing '%s' at "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) "0x%lx\n", part->mbd.mtd->name, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (block == part->current_block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) part->header_cache[offset + HEADER_MAP_OFFSET] = del;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) part->blocks[block].used_sectors--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) if (!part->blocks[block].used_sectors &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) !part->blocks[block].free_sectors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) rc = erase_block(part, block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) static int find_free_sector(const struct partition *part, const struct block *block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) int i, stop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) i = stop = part->data_sectors_per_block - block->free_sectors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if (le16_to_cpu(part->header_cache[HEADER_MAP_OFFSET + i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) == SECTOR_FREE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if (++i == part->data_sectors_per_block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) while(i != stop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf, ulong *old_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) struct partition *part = (struct partition*)dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) struct block *block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) u_long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) size_t retlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) u16 entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) if (part->current_block == -1 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) !part->blocks[part->current_block].free_sectors) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) rc = find_writable_block(part, old_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) block = &part->blocks[part->current_block];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) i = find_free_sector(part, block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) if (i < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) rc = -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) addr = (i + part->header_sectors_per_block) * SECTOR_SIZE +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) block->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) rc = mtd_write(part->mbd.mtd, addr, SECTOR_SIZE, &retlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) (u_char *)buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (!rc && retlen != SECTOR_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) printk(KERN_ERR PREFIX "error writing '%s' at 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) part->mbd.mtd->name, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) part->sector_map[sector] = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) entry = cpu_to_le16(sector == 0 ? SECTOR_ZERO : sector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) part->header_cache[i + HEADER_MAP_OFFSET] = entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) addr = block->offset + (HEADER_MAP_OFFSET + i) * sizeof(u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) rc = mtd_write(part->mbd.mtd, addr, sizeof(entry), &retlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) (u_char *)&entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (!rc && retlen != sizeof(entry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) printk(KERN_ERR PREFIX "error writing '%s' at 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) part->mbd.mtd->name, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) block->used_sectors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) block->free_sectors--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) static int rfd_ftl_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) struct partition *part = (struct partition*)dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) u_long old_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) pr_debug("rfd_ftl_writesect(sector=0x%lx)\n", sector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (part->reserved_block == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) rc = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (sector >= part->sector_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) old_addr = part->sector_map[sector];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) for (i=0; i<SECTOR_SIZE; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (!buf[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) rc = do_writesect(dev, sector, buf, &old_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) if (i == SECTOR_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) part->sector_map[sector] = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (old_addr != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) rc = mark_sector_deleted(part, old_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) static int rfd_ftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) struct partition *part = (struct partition*)dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) geo->heads = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) geo->sectors = SECTORS_PER_TRACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) geo->cylinders = part->cylinders;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) static void rfd_ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) struct partition *part;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) if (mtd->type != MTD_NORFLASH || mtd->size > UINT_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) part = kzalloc(sizeof(struct partition), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (!part)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) part->mbd.mtd = mtd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (block_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) part->block_size = block_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) if (!mtd->erasesize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) printk(KERN_WARNING PREFIX "please provide block_size");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) part->block_size = mtd->erasesize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) if (scan_header(part) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) part->mbd.size = part->sector_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) part->mbd.tr = tr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) part->mbd.devnum = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (!(mtd->flags & MTD_WRITEABLE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) part->mbd.readonly = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) else if (part->errors) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) printk(KERN_WARNING PREFIX "'%s': errors found, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) "setting read-only\n", mtd->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) part->mbd.readonly = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) printk(KERN_INFO PREFIX "name: '%s' type: %d flags %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) mtd->name, mtd->type, mtd->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) if (!add_mtd_blktrans_dev((void*)part))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) kfree(part);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) static void rfd_ftl_remove_dev(struct mtd_blktrans_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) struct partition *part = (struct partition*)dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) for (i=0; i<part->total_blocks; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) pr_debug("rfd_ftl_remove_dev:'%s': erase unit #%02d: %d erases\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) part->mbd.mtd->name, i, part->blocks[i].erases);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) del_mtd_blktrans_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) vfree(part->sector_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) kfree(part->header_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) kfree(part->blocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) static struct mtd_blktrans_ops rfd_ftl_tr = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) .name = "rfd",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) .major = RFD_FTL_MAJOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) .part_bits = PART_BITS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) .blksize = SECTOR_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) .readsect = rfd_ftl_readsect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) .writesect = rfd_ftl_writesect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) .getgeo = rfd_ftl_getgeo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) .add_mtd = rfd_ftl_add_mtd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) .remove_dev = rfd_ftl_remove_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) static int __init init_rfd_ftl(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) return register_mtd_blktrans(&rfd_ftl_tr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) static void __exit cleanup_rfd_ftl(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) deregister_mtd_blktrans(&rfd_ftl_tr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) module_init(init_rfd_ftl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) module_exit(cleanup_rfd_ftl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) MODULE_AUTHOR("Sean Young <sean@mess.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) MODULE_DESCRIPTION("Support code for RFD Flash Translation Layer, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) "used by General Software's Embedded BIOS");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)