V4L/DVB (5229): Gl861: use qt1010_tuner_attach function from qt1010.h
[pandora-kernel.git] / drivers / mtd / mtdpart.c
index f22aecc..633def3 100644 (file)
@@ -16,7 +16,6 @@
 #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>
@@ -51,12 +50,21 @@ static int part_read (struct mtd_info *mtd, loff_t from, size_t len,
                        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,
@@ -82,12 +90,21 @@ 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)
                return -EINVAL;
-       if (from + ops->len > mtd->size)
+       if (ops->datbuf && from + ops->len > mtd->size)
                return -EINVAL;
-       return part->master->read_oob(part->master, from + part->offset, ops);
+       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,
@@ -144,7 +161,7 @@ static int part_write_oob(struct mtd_info *mtd, loff_t to,
 
        if (to >= mtd->size)
                return -EINVAL;
-       if (to + ops->len > mtd->size)
+       if (ops->datbuf && to + ops->len > mtd->size)
                return -EINVAL;
        return part->master->write_oob(part->master, to + part->offset, ops);
 }
@@ -246,12 +263,17 @@ static int part_block_isbad (struct mtd_info *mtd, loff_t ofs)
 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;
 }
 
 /*
@@ -301,14 +323,13 @@ int add_mtd_partitions(struct mtd_info *master,
        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 */
@@ -317,8 +338,7 @@ int add_mtd_partitions(struct mtd_info *master,
                slave->mtd.size = parts[i].size;
                slave->mtd.writesize = master->writesize;
                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;
@@ -436,6 +456,16 @@ int add_mtd_partitions(struct mtd_info *master,
                }
 
                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 */