VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / drivers / mtd / mtdpart.c
index 460d56f..c3369e0 100644 (file)
@@ -5,7 +5,7 @@
  *
  * This code is GPL
  *
- * $Id: mtdpart.c,v 1.41 2003/06/18 14:53:02 dwmw2 Exp $
+ * $Id: mtdpart.c,v 1.50 2004/08/10 16:18:34 dwmw2 Exp $
  *
  *     02-21-2002      Thomas Gleixner <gleixner@autronix.de>
  *                     added support for read_oob, write_oob
@@ -182,7 +182,7 @@ static int part_write_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t l
                                        len, retlen, buf);
 }
 
-static int part_writev (struct mtd_info *mtd,  const struct iovec *vecs,
+static int part_writev (struct mtd_info *mtd,  const struct kvec *vecs,
                         unsigned long count, loff_t to, size_t *retlen)
 {
        struct mtd_part *part = PART(mtd);
@@ -197,7 +197,7 @@ static int part_writev (struct mtd_info *mtd,  const struct iovec *vecs,
                                        NULL, &mtd->oobinfo);
 }
 
-static int part_readv (struct mtd_info *mtd,  struct iovec *vecs,
+static int part_readv (struct mtd_info *mtd,  struct kvec *vecs,
                         unsigned long count, loff_t from, size_t *retlen)
 {
        struct mtd_part *part = PART(mtd);
@@ -210,7 +210,7 @@ static int part_readv (struct mtd_info *mtd,  struct iovec *vecs,
                                        NULL, &mtd->oobinfo);
 }
 
-static int part_writev_ecc (struct mtd_info *mtd,  const struct iovec *vecs,
+static int part_writev_ecc (struct mtd_info *mtd,  const struct kvec *vecs,
                         unsigned long count, loff_t to, size_t *retlen,
                         u_char *eccbuf,  struct nand_oobinfo *oobsel)
 {
@@ -224,7 +224,7 @@ static int part_writev_ecc (struct mtd_info *mtd,  const struct iovec *vecs,
                                        eccbuf, oobsel);
 }
 
-static int part_readv_ecc (struct mtd_info *mtd,  struct iovec *vecs,
+static int part_readv_ecc (struct mtd_info *mtd,  struct kvec *vecs,
                         unsigned long count, loff_t from, size_t *retlen,
                         u_char *eccbuf,  struct nand_oobinfo *oobsel)
 {
@@ -239,13 +239,29 @@ static int part_readv_ecc (struct mtd_info *mtd,  struct iovec *vecs,
 static int 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;
-       return part->master->erase(part->master, instr);
+       ret = part->master->erase(part->master, instr);
+       return ret;
+}
+
+void mtd_erase_callback(struct erase_info *instr)
+{
+       if (instr->mtd->erase == part_erase) {
+               struct mtd_part *part = PART(instr->mtd);
+
+               if (instr->fail_addr != 0xffffffff)
+                       instr->fail_addr -= part->offset;
+               instr->addr -= part->offset;
+       }
+       if (instr->callback)
+               instr->callback(instr);
 }
+EXPORT_SYMBOL_GPL(mtd_erase_callback);
 
 static int part_lock (struct mtd_info *mtd, loff_t ofs, size_t len)
 {
@@ -281,6 +297,26 @@ static void part_resume(struct mtd_info *mtd)
        part->master->resume(part->master);
 }
 
+static int 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 part->master->block_isbad(part->master, ofs);
+}
+
+static int part_block_markbad (struct mtd_info *mtd, loff_t ofs)
+{
+       struct mtd_part *part = PART(mtd);
+       if (!(mtd->flags & MTD_WRITEABLE))
+               return -EROFS;
+       if (ofs >= mtd->size)
+               return -EINVAL;
+       ofs += part->offset;
+       return part->master->block_markbad(part->master, ofs);
+}
+
 /* 
  * This function unregisters and destroy all slave MTD objects which are 
  * attached to the given master MTD object.
@@ -316,7 +352,7 @@ int del_mtd_partitions(struct mtd_info *master)
  */
 
 int add_mtd_partitions(struct mtd_info *master, 
-                      struct mtd_partition *parts,
+                      const struct mtd_partition *parts,
                       int nbparts)
 {
        struct mtd_part *slave;
@@ -391,6 +427,10 @@ int add_mtd_partitions(struct mtd_info *master,
                        slave->mtd.lock = part_lock;
                if (master->unlock)
                        slave->mtd.unlock = part_unlock;
+               if (master->block_isbad)
+                       slave->mtd.block_isbad = part_block_isbad;
+               if (master->block_markbad)
+                       slave->mtd.block_markbad = part_block_markbad;
                slave->mtd.erase = part_erase;
                slave->master = master;
                slave->offset = parts[i].offset;
@@ -461,6 +501,9 @@ int add_mtd_partitions(struct mtd_info *master,
                                parts[i].name);
                }
 
+               /* copy oobinfo from master */ 
+               memcpy(&slave->mtd.oobinfo, &master->oobinfo, sizeof(slave->mtd.oobinfo));
+
                if(parts[i].mtdp)
                {       /* store the object pointer (caller may or may not register it */
                        *parts[i].mtdp = &slave->mtd;