mtd: Simplify partitions
Embed the partition information in struct mtd_info. This makes the mtd partition code simpler. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
parent
403fbbbc34
commit
29ea8bcd94
|
@ -4,29 +4,19 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
|
||||
struct mtd_part {
|
||||
struct mtd_info mtd;
|
||||
struct mtd_info *master;
|
||||
uint64_t offset;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
#define PART(x) ((struct mtd_part *)(x))
|
||||
|
||||
static int mtd_part_read(struct mtd_info *mtd, loff_t from, size_t len,
|
||||
size_t *retlen, u_char *buf)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
struct mtd_ecc_stats stats;
|
||||
int res;
|
||||
|
||||
stats = part->master->ecc_stats;
|
||||
stats = mtd->master->ecc_stats;
|
||||
|
||||
if (from >= mtd->size)
|
||||
len = 0;
|
||||
else if (from + len > mtd->size)
|
||||
len = mtd->size - from;
|
||||
res = part->master->read(part->master, from + part->offset,
|
||||
res = mtd->master->read(mtd->master, from + mtd->master_offset,
|
||||
len, retlen, buf);
|
||||
return res;
|
||||
}
|
||||
|
@ -34,57 +24,52 @@ static int mtd_part_read(struct mtd_info *mtd, loff_t from, size_t len,
|
|||
static int mtd_part_write(struct mtd_info *mtd, loff_t to, size_t len,
|
||||
size_t *retlen, const u_char *buf)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
|
||||
if (!(mtd->flags & MTD_WRITEABLE))
|
||||
return -EROFS;
|
||||
if (to >= mtd->size)
|
||||
len = 0;
|
||||
else if (to + len > mtd->size)
|
||||
len = mtd->size - to;
|
||||
return part->master->write(part->master, to + part->offset,
|
||||
return mtd->master->write(mtd->master, to + mtd->master_offset,
|
||||
len, retlen, buf);
|
||||
}
|
||||
|
||||
static int mtd_part_erase(struct mtd_info *mtd, struct erase_info *instr)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
int ret;
|
||||
|
||||
if (!(mtd->flags & MTD_WRITEABLE))
|
||||
return -EROFS;
|
||||
if (instr->addr >= mtd->size)
|
||||
return -EINVAL;
|
||||
instr->addr += part->offset;
|
||||
ret = part->master->erase(part->master, instr);
|
||||
instr->addr += mtd->master_offset;
|
||||
ret = mtd->master->erase(mtd->master, instr);
|
||||
if (ret) {
|
||||
if (instr->fail_addr != 0xffffffff)
|
||||
instr->fail_addr -= part->offset;
|
||||
instr->addr -= part->offset;
|
||||
instr->fail_addr -= mtd->master_offset;
|
||||
instr->addr -= mtd->master_offset;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mtd_part_block_isbad(struct mtd_info *mtd, loff_t ofs)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
if (ofs >= mtd->size)
|
||||
return -EINVAL;
|
||||
ofs += part->offset;
|
||||
return mtd_block_isbad(part->master, ofs);
|
||||
ofs += mtd->master_offset;
|
||||
return mtd_block_isbad(mtd->master, ofs);
|
||||
}
|
||||
|
||||
static int mtd_part_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
int res;
|
||||
|
||||
if (!(mtd->flags & MTD_WRITEABLE))
|
||||
return -EROFS;
|
||||
if (ofs >= mtd->size)
|
||||
return -EINVAL;
|
||||
ofs += part->offset;
|
||||
res = part->master->block_markbad(part->master, ofs);
|
||||
ofs += mtd->master_offset;
|
||||
res = mtd->master->block_markbad(mtd->master, ofs);
|
||||
if (!res)
|
||||
mtd->ecc_stats.badblocks++;
|
||||
return res;
|
||||
|
@ -93,14 +78,12 @@ static int mtd_part_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
|||
struct mtd_info *mtd_add_partition(struct mtd_info *mtd, off_t offset, size_t size,
|
||||
unsigned long flags, const char *name)
|
||||
{
|
||||
struct mtd_part *slave;
|
||||
struct mtd_info *slave_mtd;
|
||||
struct mtd_info *part;
|
||||
int start = 0, end = 0, i;
|
||||
|
||||
slave = xzalloc(sizeof(*slave));
|
||||
slave_mtd = &slave->mtd;
|
||||
part = xzalloc(sizeof(*part));
|
||||
|
||||
memcpy(slave_mtd, mtd, sizeof(*slave));
|
||||
memcpy(part, mtd, sizeof(*part));
|
||||
|
||||
/*
|
||||
* find the number of eraseregions the partition includes.
|
||||
|
@ -118,26 +101,29 @@ struct mtd_info *mtd_add_partition(struct mtd_info *mtd, off_t offset, size_t si
|
|||
end = i;
|
||||
}
|
||||
|
||||
slave_mtd->numeraseregions = end - start;
|
||||
part->numeraseregions = end - start;
|
||||
|
||||
slave_mtd->read = mtd_part_read;
|
||||
slave_mtd->write = mtd_part_write;
|
||||
slave_mtd->erase = mtd_part_erase;
|
||||
slave_mtd->block_isbad = mtd->block_isbad ? mtd_part_block_isbad : NULL;
|
||||
slave_mtd->block_markbad = mtd->block_markbad ? mtd_part_block_markbad : NULL;
|
||||
slave_mtd->size = size;
|
||||
slave_mtd->name = strdup(name);
|
||||
part->read = mtd_part_read;
|
||||
part->write = mtd_part_write;
|
||||
part->erase = mtd_part_erase;
|
||||
part->block_isbad = mtd->block_isbad ? mtd_part_block_isbad : NULL;
|
||||
part->block_markbad = mtd->block_markbad ? mtd_part_block_markbad : NULL;
|
||||
part->size = size;
|
||||
part->name = strdup(name);
|
||||
|
||||
slave->offset = offset;
|
||||
slave->master = mtd;
|
||||
part->master_offset = offset;
|
||||
part->master = mtd;
|
||||
|
||||
return slave_mtd;
|
||||
return part;
|
||||
}
|
||||
|
||||
void mtd_del_partition(struct mtd_info *mtd)
|
||||
int mtd_del_partition(struct mtd_info *part)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
if (!part->master)
|
||||
return -EINVAL;
|
||||
|
||||
free(mtd->name);
|
||||
free(part->name);
|
||||
free(part);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -217,6 +217,9 @@ struct mtd_info {
|
|||
/* If true erasing bad blocks is allowed, this is set via a device parameter */
|
||||
bool allow_erasebad;
|
||||
int p_allow_erasebad;
|
||||
|
||||
struct mtd_info *master;
|
||||
uint32_t master_offset;
|
||||
};
|
||||
|
||||
int mtd_erase(struct mtd_info *mtd, struct erase_info *instr);
|
||||
|
@ -272,7 +275,7 @@ struct mtd_notifier {
|
|||
|
||||
struct mtd_info *mtd_add_partition(struct mtd_info *mtd, off_t offset, size_t size,
|
||||
unsigned long flags, const char *name);
|
||||
void mtd_del_partition(struct mtd_info *mtd);
|
||||
int mtd_del_partition(struct mtd_info *mtd);
|
||||
|
||||
extern void register_mtd_user (struct mtd_notifier *new);
|
||||
extern int unregister_mtd_user (struct mtd_notifier *old);
|
||||
|
|
Loading…
Reference in New Issue