Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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)