Message ID | 1254819360-17191-2-git-send-email-ext-mika.2.korhonen@nokia.com |
---|---|
State | New, archived |
Headers | show |
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
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
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;
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(-)