Patchwork [1/2] MTD: OneNAND: move erase method to a separate function

login
register
mail settings
Submitter Mika Korhonen
Date Oct. 6, 2009, 8:55 a.m.
Message ID <1254819360-17191-2-git-send-email-ext-mika.2.korhonen@nokia.com>
Download mbox | patch
Permalink /patch/35077/
State New, archived
Headers show

Comments

Mika Korhonen - Oct. 6, 2009, 8:55 a.m.
Separate the actual execution of erase to a new function:
onenand_block_by_block_erase(). This is done in preparation for
the multiblock erase support.

Signed-off-by: Mika Korhonen <ext-mika.2.korhonen@nokia.com>
---
 drivers/mtd/onenand/onenand_base.c |  143 +++++++++++++++++++++---------------
 1 files changed, 84 insertions(+), 59 deletions(-)
Kyungmin Park - Oct. 6, 2009, 9:13 a.m.
On Tue, Oct 6, 2009 at 5:55 PM, Mika Korhonen
<ext-mika.2.korhonen@nokia.com> wrote:
> Separate the actual execution of erase to a new function:
> onenand_block_by_block_erase(). This is done in preparation for
> the multiblock erase support.
>
> Signed-off-by: Mika Korhonen <ext-mika.2.korhonen@nokia.com>
> ---
>  drivers/mtd/onenand/onenand_base.c |  143 +++++++++++++++++++++---------------
>  1 files changed, 84 insertions(+), 59 deletions(-)
>
> diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
> index ff66e43..13090f3 100644
> --- a/drivers/mtd/onenand/onenand_base.c
> +++ b/drivers/mtd/onenand/onenand_base.c
> @@ -2141,77 +2141,43 @@ static int onenand_block_isbad_nolock(struct mtd_info *mtd, loff_t ofs, int allo
>  }
>
>  /**
> - * onenand_erase - [MTD Interface] erase block(s)
> + * onenand_block_by_block_erase - [Internal] erase block(s) using regular erase
>  * @param mtd          MTD device structure
>  * @param instr                erase instruction
> + * @param region       erase region
> + * @param block_size   erase block size
>  *
> - * Erase one ore more blocks
> + * Erase one or more blocks one block at a time
>  */
> -static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
> +static int onenand_block_by_block_erase(struct mtd_info *mtd,
> +                                       struct erase_info *instr,
> +                                       struct mtd_erase_region_info *region,
> +                                       unsigned int block_size)
>  {
>        struct onenand_chip *this = mtd->priv;
> -       unsigned int block_size;
>        loff_t addr = instr->addr;
> -       loff_t len = instr->len;
> -       int ret = 0, i;
> -       struct mtd_erase_region_info *region = NULL;
> +       int len = instr->len;
>        loff_t region_end = 0;
> +       int ret = 0;
>
> -       DEBUG(MTD_DEBUG_LEVEL3, "onenand_erase: start = 0x%012llx, len = %llu\n", (unsigned long long) instr->addr, (unsigned long long) instr->len);
> -
> -       /* Do not allow erase past end of device */
> -       if (unlikely((len + addr) > mtd->size)) {
> -               printk(KERN_ERR "onenand_erase: Erase past end of device\n");
> -               return -EINVAL;
> -       }
> -
> -       if (FLEXONENAND(this)) {
> -               /* Find the eraseregion of this address */
> -               i = flexonenand_region(mtd, addr);
> -               region = &mtd->eraseregions[i];
> -
> -               block_size = region->erasesize;
> +       if (region) {
> +               /* region is set for Flex-OneNAND */
>                region_end = region->offset + region->erasesize * region->numblocks;
> -
> -               /* Start address within region must align on block boundary.
> -                * Erase region's start offset is always block start address.
> -                */
> -               if (unlikely((addr - region->offset) & (block_size - 1))) {
> -                       printk(KERN_ERR "onenand_erase: Unaligned address\n");
> -                       return -EINVAL;
> -               }
> -       } else {
> -               block_size = 1 << this->erase_shift;
> -
> -               /* Start address must align on block boundary */
> -               if (unlikely(addr & (block_size - 1))) {
> -                       printk(KERN_ERR "onenand_erase: Unaligned address\n");
> -                       return -EINVAL;
> -               }
> -       }
> -
> -       /* Length must align on block boundary */
> -       if (unlikely(len & (block_size - 1))) {
> -               printk(KERN_ERR "onenand_erase: Length not block aligned\n");
> -               return -EINVAL;
>        }
>
> -       instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
> -
> -       /* Grab the lock and see if the device is available */
> -       onenand_get_device(mtd, FL_ERASING);
> -
> -       /* Loop through the blocks */
>        instr->state = MTD_ERASING;
>
> +       /* Loop through the blocks */
>        while (len) {
>                cond_resched();
>
>                /* Check if we have a bad block, we do not erase bad blocks */
>                if (onenand_block_isbad_nolock(mtd, addr, 0)) {
> -                       printk (KERN_WARNING "onenand_erase: attempt to erase a bad block at addr 0x%012llx\n", (unsigned long long) addr);
> +                       printk(KERN_WARNING "onenand_block_by_block_erase: "
> +                              "attempt to erase a bad block at addr "
> +                              "0x%012llx\n", (unsigned long long) addr);
>                        instr->state = MTD_ERASE_FAILED;
> -                       goto erase_exit;
> +                       return -EIO;
>                }
>
>                this->command(mtd, ONENAND_CMD_ERASE, addr, block_size);
> @@ -2221,11 +2187,12 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
>                ret = this->wait(mtd, FL_ERASING);
>                /* Check, if it is write protected */
>                if (ret) {
> -                       printk(KERN_ERR "onenand_erase: Failed erase, block %d\n",
> -                                                onenand_block(this, addr));
> +                       printk(KERN_ERR "onenand_block_by_block_erase: "
> +                              "Failed erase, block %d\n",
> +                              onenand_block(this, addr));
>                        instr->state = MTD_ERASE_FAILED;
>                        instr->fail_addr = addr;
> -                       goto erase_exit;
> +                       return -EIO;
>                }
>
>                len -= block_size;
> @@ -2241,24 +2208,82 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
>
>                        if (len & (block_size - 1)) {
>                                /* FIXME: This should be handled at MTD partitioning level. */
> -                               printk(KERN_ERR "onenand_erase: Unaligned address\n");
> -                               goto erase_exit;
> +                               printk(KERN_ERR "onenand_block_by_block_erase: "
> +                                      "Unaligned address\n");
> +                               return -EIO;
>                        }
>                }
> +       }
> +       return 0;
> +}
> +
> +/**
> + * onenand_erase - [MTD Interface] erase block(s)
> + * @param mtd          MTD device structure
> + * @param instr                erase instruction
> + *
> + * Erase one or more blocks
> + */
> +static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
> +{
> +       struct onenand_chip *this = mtd->priv;
> +       unsigned int block_size;
> +       loff_t addr = instr->addr;
> +       loff_t len = instr->len;
> +       int ret = 0;
> +       struct mtd_erase_region_info *region = NULL;
> +       loff_t region_offset = 0;
> +
> +       DEBUG(MTD_DEBUG_LEVEL3, "onenand_erase: start=0x%012llx, len=%llu\n",
> +             (unsigned long long) instr->addr,
> +             (unsigned long long) instr->len);
> +
> +       /* Do not allow erase past end of device */
> +       if (unlikely((len + addr) > mtd->size)) {
> +               printk(KERN_ERR "onenand_erase: Erase past end of device\n");
> +               return -EINVAL;
> +       }
> +
> +       if (FLEXONENAND(this)) {
> +               /* Find the eraseregion of this address */
> +               int i = flexonenand_region(mtd, addr);
> +
> +               region = &mtd->eraseregions[i];
> +               block_size = region->erasesize;
> +
> +               /* Start address within region must align on block boundary.
> +                * Erase region's start offset is always block start address.
> +                */
> +               region_offset = region->offset;
> +       } else {
> +               block_size = 1 << this->erase_shift;
> +       }

No { } here.

>
> +       /* Start address must align on block boundary */
> +       if (unlikely((addr - region_offset) & (block_size - 1))) {
> +               printk(KERN_ERR "onenand_erase: Unaligned address\n");
> +               return -EINVAL;
>        }
>
> -       instr->state = MTD_ERASE_DONE;
> +       /* Length must align on block boundary */
> +       if (unlikely(len & (block_size - 1))) {
> +               printk(KERN_ERR "onenand_erase: Length not block aligned\n");
> +               return -EINVAL;
> +       }
> +
> +       instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
>
> -erase_exit:
> +       /* Grab the lock and see if the device is available */
> +       onenand_get_device(mtd, FL_ERASING);
>
> -       ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
> +       ret = onenand_block_by_block_erase(mtd, instr, region, block_size);
>
>        /* Deselect and wake up anyone waiting on the device */
>        onenand_release_device(mtd);
>
>        /* Do call back function */
>        if (!ret)
> +               instr->state = MTD_ERASE_DONE;
>                mtd_erase_callback(instr);

Are you missing curly braces { } here?

Thank you
Kyungmin Park
Mika Korhonen - Oct. 6, 2009, 9:18 a.m.
ext Kyungmin Park wrote:
> On Tue, Oct 6, 2009 at 5:55 PM, Mika Korhonen
> <ext-mika.2.korhonen@nokia.com> wrote:
>   
>> Separate the actual execution of erase to a new function:
>> onenand_block_by_block_erase(). This is done in preparation for
>> the multiblock erase support.
>>
>> Signed-off-by: Mika Korhonen <ext-mika.2.korhonen@nokia.com>
>> ---
>>  drivers/mtd/onenand/onenand_base.c |  143 +++++++++++++++++++++---------------
>>  1 files changed, 84 insertions(+), 59 deletions(-)
>>     
[...]
>>        /* Do call back function */
>>        if (!ret)
>> +               instr->state = MTD_ERASE_DONE;
>>                mtd_erase_callback(instr);
>>     
>
> Are you missing curly braces { } here?
>
> Thank you
> Kyungmin Park
>   
Yes, I am. Thanks!

br
Mika

Patch

diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index ff66e43..13090f3 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -2141,77 +2141,43 @@  static int onenand_block_isbad_nolock(struct mtd_info *mtd, loff_t ofs, int allo
 }
 
 /**
- * onenand_erase - [MTD Interface] erase block(s)
+ * onenand_block_by_block_erase - [Internal] erase block(s) using regular erase
  * @param mtd		MTD device structure
  * @param instr		erase instruction
+ * @param region	erase region
+ * @param block_size	erase block size
  *
- * Erase one ore more blocks
+ * Erase one or more blocks one block at a time
  */
-static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
+static int onenand_block_by_block_erase(struct mtd_info *mtd,
+					struct erase_info *instr,
+					struct mtd_erase_region_info *region,
+					unsigned int block_size)
 {
 	struct onenand_chip *this = mtd->priv;
-	unsigned int block_size;
 	loff_t addr = instr->addr;
-	loff_t len = instr->len;
-	int ret = 0, i;
-	struct mtd_erase_region_info *region = NULL;
+	int len = instr->len;
 	loff_t region_end = 0;
+	int ret = 0;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "onenand_erase: start = 0x%012llx, len = %llu\n", (unsigned long long) instr->addr, (unsigned long long) instr->len);
-
-	/* Do not allow erase past end of device */
-	if (unlikely((len + addr) > mtd->size)) {
-		printk(KERN_ERR "onenand_erase: Erase past end of device\n");
-		return -EINVAL;
-	}
-
-	if (FLEXONENAND(this)) {
-		/* Find the eraseregion of this address */
-		i = flexonenand_region(mtd, addr);
-		region = &mtd->eraseregions[i];
-
-		block_size = region->erasesize;
+	if (region) {
+		/* region is set for Flex-OneNAND */
 		region_end = region->offset + region->erasesize * region->numblocks;
-
-		/* Start address within region must align on block boundary.
-		 * Erase region's start offset is always block start address.
-		 */
-		if (unlikely((addr - region->offset) & (block_size - 1))) {
-			printk(KERN_ERR "onenand_erase: Unaligned address\n");
-			return -EINVAL;
-		}
-	} else {
-		block_size = 1 << this->erase_shift;
-
-		/* Start address must align on block boundary */
-		if (unlikely(addr & (block_size - 1))) {
-			printk(KERN_ERR "onenand_erase: Unaligned address\n");
-			return -EINVAL;
-		}
-	}
-
-	/* Length must align on block boundary */
-	if (unlikely(len & (block_size - 1))) {
-		printk(KERN_ERR "onenand_erase: Length not block aligned\n");
-		return -EINVAL;
 	}
 
-	instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
-
-	/* Grab the lock and see if the device is available */
-	onenand_get_device(mtd, FL_ERASING);
-
-	/* Loop through the blocks */
 	instr->state = MTD_ERASING;
 
+	/* Loop through the blocks */
 	while (len) {
 		cond_resched();
 
 		/* Check if we have a bad block, we do not erase bad blocks */
 		if (onenand_block_isbad_nolock(mtd, addr, 0)) {
-			printk (KERN_WARNING "onenand_erase: attempt to erase a bad block at addr 0x%012llx\n", (unsigned long long) addr);
+			printk(KERN_WARNING "onenand_block_by_block_erase: "
+			       "attempt to erase a bad block at addr "
+			       "0x%012llx\n", (unsigned long long) addr);
 			instr->state = MTD_ERASE_FAILED;
-			goto erase_exit;
+			return -EIO;
 		}
 
 		this->command(mtd, ONENAND_CMD_ERASE, addr, block_size);
@@ -2221,11 +2187,12 @@  static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
 		ret = this->wait(mtd, FL_ERASING);
 		/* Check, if it is write protected */
 		if (ret) {
-			printk(KERN_ERR "onenand_erase: Failed erase, block %d\n",
-						 onenand_block(this, addr));
+			printk(KERN_ERR "onenand_block_by_block_erase: "
+			       "Failed erase, block %d\n",
+			       onenand_block(this, addr));
 			instr->state = MTD_ERASE_FAILED;
 			instr->fail_addr = addr;
-			goto erase_exit;
+			return -EIO;
 		}
 
 		len -= block_size;
@@ -2241,24 +2208,82 @@  static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
 
 			if (len & (block_size - 1)) {
 				/* FIXME: This should be handled at MTD partitioning level. */
-				printk(KERN_ERR "onenand_erase: Unaligned address\n");
-				goto erase_exit;
+				printk(KERN_ERR "onenand_block_by_block_erase: "
+				       "Unaligned address\n");
+				return -EIO;
 			}
 		}
+	}
+	return 0;
+}
+
+/**
+ * onenand_erase - [MTD Interface] erase block(s)
+ * @param mtd		MTD device structure
+ * @param instr		erase instruction
+ *
+ * Erase one or more blocks
+ */
+static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct onenand_chip *this = mtd->priv;
+	unsigned int block_size;
+	loff_t addr = instr->addr;
+	loff_t len = instr->len;
+	int ret = 0;
+	struct mtd_erase_region_info *region = NULL;
+	loff_t region_offset = 0;
+
+	DEBUG(MTD_DEBUG_LEVEL3, "onenand_erase: start=0x%012llx, len=%llu\n",
+	      (unsigned long long) instr->addr,
+	      (unsigned long long) instr->len);
+
+	/* Do not allow erase past end of device */
+	if (unlikely((len + addr) > mtd->size)) {
+		printk(KERN_ERR "onenand_erase: Erase past end of device\n");
+		return -EINVAL;
+	}
+
+	if (FLEXONENAND(this)) {
+		/* Find the eraseregion of this address */
+		int i = flexonenand_region(mtd, addr);
+
+		region = &mtd->eraseregions[i];
+		block_size = region->erasesize;
+
+		/* Start address within region must align on block boundary.
+		 * Erase region's start offset is always block start address.
+		 */
+		region_offset = region->offset;
+	} else {
+		block_size = 1 << this->erase_shift;
+	}
 
+	/* Start address must align on block boundary */
+	if (unlikely((addr - region_offset) & (block_size - 1))) {
+		printk(KERN_ERR "onenand_erase: Unaligned address\n");
+		return -EINVAL;
 	}
 
-	instr->state = MTD_ERASE_DONE;
+	/* Length must align on block boundary */
+	if (unlikely(len & (block_size - 1))) {
+		printk(KERN_ERR "onenand_erase: Length not block aligned\n");
+		return -EINVAL;
+	}
+
+	instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
 
-erase_exit:
+	/* Grab the lock and see if the device is available */
+	onenand_get_device(mtd, FL_ERASING);
 
-	ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
+	ret = onenand_block_by_block_erase(mtd, instr, region, block_size);
 
 	/* Deselect and wake up anyone waiting on the device */
 	onenand_release_device(mtd);
 
 	/* Do call back function */
 	if (!ret)
+		instr->state = MTD_ERASE_DONE;
 		mtd_erase_callback(instr);
 
 	return ret;