#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/list.h>
-#include <linux/config.h>
#include <linux/kmod.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
size_t *retlen, u_char *buf)
{
struct mtd_part *part = PART(mtd);
+ int res;
+
if (from >= mtd->size)
len = 0;
else if (from + len > mtd->size)
len = mtd->size - from;
- return part->master->read (part->master, from + part->offset,
+ res = part->master->read (part->master, from + part->offset,
len, retlen, buf);
+ if (unlikely(res)) {
+ if (res == -EUCLEAN)
+ mtd->ecc_stats.corrected++;
+ if (res == -EBADMSG)
+ mtd->ecc_stats.failed++;
+ }
+ return res;
}
static int part_point (struct mtd_info *mtd, loff_t from, size_t len,
part->master->unpoint (part->master, addr, from + part->offset, len);
}
-static int part_read_oob (struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, u_char *buf)
+static int part_read_oob(struct mtd_info *mtd, loff_t from,
+ struct mtd_oob_ops *ops)
{
struct mtd_part *part = PART(mtd);
+ int res;
+
if (from >= mtd->size)
- len = 0;
- else if (from + len > mtd->size)
- len = mtd->size - from;
- return part->master->read_oob (part->master, from + part->offset,
- len, retlen, buf);
+ return -EINVAL;
+ if (ops->datbuf && from + ops->len > mtd->size)
+ return -EINVAL;
+ res = part->master->read_oob(part->master, from + part->offset, ops);
+
+ if (unlikely(res)) {
+ if (res == -EUCLEAN)
+ mtd->ecc_stats.corrected++;
+ if (res == -EBADMSG)
+ mtd->ecc_stats.failed++;
+ }
+ return res;
}
static int part_read_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len,
len, retlen, buf);
}
-static int part_write_oob (struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const u_char *buf)
+static int part_write_oob(struct mtd_info *mtd, loff_t to,
+ struct mtd_oob_ops *ops)
{
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_oob (part->master, to + part->offset,
- len, retlen, buf);
+ return -EINVAL;
+ if (ops->datbuf && to + ops->len > mtd->size)
+ return -EINVAL;
+ return part->master->write_oob(part->master, to + part->offset, ops);
}
static int part_write_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len,
static int 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;
- return part->master->block_markbad(part->master, ofs);
+ res = part->master->block_markbad(part->master, ofs);
+ if (!res)
+ mtd->ecc_stats.badblocks++;
+ return res;
}
/*
for (i = 0; i < nbparts; i++) {
/* allocate the partition structure */
- slave = kmalloc (sizeof(*slave), GFP_KERNEL);
+ slave = kzalloc (sizeof(*slave), GFP_KERNEL);
if (!slave) {
printk ("memory allocation error while creating partitions for \"%s\"\n",
master->name);
del_mtd_partitions(master);
return -ENOMEM;
}
- memset(slave, 0, sizeof(*slave));
list_add(&slave->list, &mtd_partitions);
/* set up the MTD object for this partition */
slave->mtd.oobsize = master->oobsize;
slave->mtd.ecctype = master->ecctype;
slave->mtd.eccsize = master->eccsize;
+ slave->mtd.subpage_sft = master->subpage_sft;
slave->mtd.name = parts[i].name;
slave->mtd.bank_size = master->bank_size;
parts[i].name);
}
- slave->mtd.oobinfo = master->oobinfo;
+ slave->mtd.ecclayout = master->ecclayout;
+ if (master->block_isbad) {
+ uint32_t offs = 0;
+
+ while(offs < slave->mtd.size) {
+ if (master->block_isbad(master,
+ offs + slave->offset))
+ slave->mtd.ecc_stats.badblocks++;
+ offs += slave->mtd.erasesize;
+ }
+ }
if(parts[i].mtdp)
{ /* store the object pointer (caller may or may not register it */