Commit 7e1f0dc0 authored by Artem Bityutskiy's avatar Artem Bityutskiy Committed by David Woodhouse

mtd: introduce mtd_erase interface

This patch is part of a patch-set which changes the MTD interface
from 'mtd->func()' form to 'mtd_func()' form. We need this because
we want to add common code to to all drivers in the mtd core level,
which is impossible with the current interface when MTD clients
call driver functions like 'read()' or 'write()' directly.

At this point we just introduce a new inline wrapper function, but
later some of them are expected to gain more code. E.g., the input
parameters check should be moved to the wrappers rather than be
duplicated at many drivers.

This particular patch introduced the 'mtd_erase()' interface. The
following patches add all the other interfaces one by one.
Signed-off-by: default avatarArtem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent 969e57ad
...@@ -355,7 +355,7 @@ static int erase_xfer(partition_t *part, ...@@ -355,7 +355,7 @@ static int erase_xfer(partition_t *part,
erase->len = 1 << part->header.EraseUnitSize; erase->len = 1 << part->header.EraseUnitSize;
erase->priv = (u_long)part; erase->priv = (u_long)part;
ret = part->mbd.mtd->erase(part->mbd.mtd, erase); ret = mtd_erase(part->mbd.mtd, erase);
if (!ret) if (!ret)
xfer->EraseCount++; xfer->EraseCount++;
......
...@@ -220,7 +220,7 @@ static int find_boot_record(struct INFTLrecord *inftl) ...@@ -220,7 +220,7 @@ static int find_boot_record(struct INFTLrecord *inftl)
*/ */
instr->addr = ip->Reserved0 * inftl->EraseSize; instr->addr = ip->Reserved0 * inftl->EraseSize;
instr->len = inftl->EraseSize; instr->len = inftl->EraseSize;
mtd->erase(mtd, instr); mtd_erase(mtd, instr);
} }
if ((ip->lastUnit - ip->firstUnit + 1) < ip->virtualUnits) { if ((ip->lastUnit - ip->firstUnit + 1) < ip->virtualUnits) {
printk(KERN_WARNING "INFTL: Media Header " printk(KERN_WARNING "INFTL: Media Header "
...@@ -393,7 +393,7 @@ int INFTL_formatblock(struct INFTLrecord *inftl, int block) ...@@ -393,7 +393,7 @@ int INFTL_formatblock(struct INFTLrecord *inftl, int block)
mark only the failed block in the bbt. */ mark only the failed block in the bbt. */
for (physblock = 0; physblock < inftl->EraseSize; for (physblock = 0; physblock < inftl->EraseSize;
physblock += instr->len, instr->addr += instr->len) { physblock += instr->len, instr->addr += instr->len) {
mtd->erase(inftl->mbd.mtd, instr); mtd_erase(inftl->mbd.mtd, instr);
if (instr->state == MTD_ERASE_FAILED) { if (instr->state == MTD_ERASE_FAILED) {
printk(KERN_WARNING "INFTL: error while formatting block %d\n", printk(KERN_WARNING "INFTL: error while formatting block %d\n",
......
...@@ -85,7 +85,7 @@ static int erase_write (struct mtd_info *mtd, unsigned long pos, ...@@ -85,7 +85,7 @@ static int erase_write (struct mtd_info *mtd, unsigned long pos,
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&wait_q, &wait); add_wait_queue(&wait_q, &wait);
ret = mtd->erase(mtd, &erase); ret = mtd_erase(mtd, &erase);
if (ret) { if (ret) {
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
remove_wait_queue(&wait_q, &wait); remove_wait_queue(&wait_q, &wait);
......
...@@ -731,7 +731,7 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg) ...@@ -731,7 +731,7 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg)
wq_head is no longer there when the wq_head is no longer there when the
callback routine tries to wake us up. callback routine tries to wake us up.
*/ */
ret = mtd->erase(mtd, erase); ret = mtd_erase(mtd, erase);
if (!ret) { if (!ret) {
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&waitq, &wait); add_wait_queue(&waitq, &wait);
......
...@@ -379,7 +379,7 @@ static int concat_dev_erase(struct mtd_info *mtd, struct erase_info *erase) ...@@ -379,7 +379,7 @@ static int concat_dev_erase(struct mtd_info *mtd, struct erase_info *erase)
* FIXME: Allow INTERRUPTIBLE. Which means * FIXME: Allow INTERRUPTIBLE. Which means
* not having the wait_queue head on the stack. * not having the wait_queue head on the stack.
*/ */
err = mtd->erase(mtd, erase); err = mtd_erase(mtd, erase);
if (!err) { if (!err) {
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&waitq, &wait); add_wait_queue(&waitq, &wait);
......
...@@ -112,7 +112,7 @@ static int mtdoops_erase_block(struct mtdoops_context *cxt, int offset) ...@@ -112,7 +112,7 @@ static int mtdoops_erase_block(struct mtdoops_context *cxt, int offset)
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&wait_q, &wait); add_wait_queue(&wait_q, &wait);
ret = mtd->erase(mtd, &erase); ret = mtd_erase(mtd, &erase);
if (ret) { if (ret) {
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
remove_wait_queue(&wait_q, &wait); remove_wait_queue(&wait_q, &wait);
......
...@@ -257,7 +257,7 @@ static int part_erase(struct mtd_info *mtd, struct erase_info *instr) ...@@ -257,7 +257,7 @@ static int part_erase(struct mtd_info *mtd, struct erase_info *instr)
if (instr->addr >= mtd->size) if (instr->addr >= mtd->size)
return -EINVAL; return -EINVAL;
instr->addr += part->offset; instr->addr += part->offset;
ret = part->master->erase(part->master, instr); ret = mtd_erase(part->master, instr);
if (ret) { if (ret) {
if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN) if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
instr->fail_addr -= part->offset; instr->fail_addr -= part->offset;
......
...@@ -567,7 +567,7 @@ static int mtdswap_erase_block(struct mtdswap_dev *d, struct swap_eb *eb) ...@@ -567,7 +567,7 @@ static int mtdswap_erase_block(struct mtdswap_dev *d, struct swap_eb *eb)
erase.len = mtd->erasesize; erase.len = mtd->erasesize;
erase.priv = (u_long)&wq; erase.priv = (u_long)&wq;
ret = mtd->erase(mtd, &erase); ret = mtd_erase(mtd, &erase);
if (ret) { if (ret) {
if (retries++ < MTDSWAP_ERASE_RETRIES) { if (retries++ < MTDSWAP_ERASE_RETRIES) {
dev_warn(d->dev, dev_warn(d->dev,
......
...@@ -326,7 +326,7 @@ int NFTL_formatblock(struct NFTLrecord *nftl, int block) ...@@ -326,7 +326,7 @@ int NFTL_formatblock(struct NFTLrecord *nftl, int block)
instr->mtd = nftl->mbd.mtd; instr->mtd = nftl->mbd.mtd;
instr->addr = block * nftl->EraseSize; instr->addr = block * nftl->EraseSize;
instr->len = nftl->EraseSize; instr->len = nftl->EraseSize;
mtd->erase(mtd, instr); mtd_erase(mtd, instr);
if (instr->state == MTD_ERASE_FAILED) { if (instr->state == MTD_ERASE_FAILED) {
printk("Error while formatting block %d\n", block); printk("Error while formatting block %d\n", block);
......
...@@ -342,7 +342,7 @@ static int erase_block(struct partition *part, int block) ...@@ -342,7 +342,7 @@ static int erase_block(struct partition *part, int block)
part->blocks[block].state = BLOCK_ERASING; part->blocks[block].state = BLOCK_ERASING;
part->blocks[block].free_sectors = 0; part->blocks[block].free_sectors = 0;
rc = part->mbd.mtd->erase(part->mbd.mtd, erase); rc = mtd_erase(part->mbd.mtd, erase);
if (rc) { if (rc) {
printk(KERN_ERR PREFIX "erase of region %llx,%llx on '%s' " printk(KERN_ERR PREFIX "erase of region %llx,%llx on '%s' "
......
...@@ -479,7 +479,7 @@ static int sm_erase_block(struct sm_ftl *ftl, int zone_num, uint16_t block, ...@@ -479,7 +479,7 @@ static int sm_erase_block(struct sm_ftl *ftl, int zone_num, uint16_t block,
return -EIO; return -EIO;
} }
if (mtd->erase(mtd, &erase)) { if (mtd_erase(mtd, &erase)) {
sm_printk("erase of block %d in zone %d failed", sm_printk("erase of block %d in zone %d failed",
block, zone_num); block, zone_num);
goto error; goto error;
......
...@@ -78,7 +78,7 @@ static int erase_eraseblock(int ebnum) ...@@ -78,7 +78,7 @@ static int erase_eraseblock(int ebnum)
ei.addr = addr; ei.addr = addr;
ei.len = mtd->erasesize; ei.len = mtd->erasesize;
err = mtd->erase(mtd, &ei); err = mtd_erase(mtd, &ei);
if (err) { if (err) {
printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
return err; return err;
......
...@@ -77,7 +77,7 @@ static int erase_eraseblock(int ebnum) ...@@ -77,7 +77,7 @@ static int erase_eraseblock(int ebnum)
ei.addr = addr; ei.addr = addr;
ei.len = mtd->erasesize; ei.len = mtd->erasesize;
err = mtd->erase(mtd, &ei); err = mtd_erase(mtd, &ei);
if (err) { if (err) {
printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
return err; return err;
......
...@@ -79,7 +79,7 @@ static int erase_eraseblock(int ebnum) ...@@ -79,7 +79,7 @@ static int erase_eraseblock(int ebnum)
ei.addr = addr; ei.addr = addr;
ei.len = mtd->erasesize; ei.len = mtd->erasesize;
err = mtd->erase(mtd, &ei); err = mtd_erase(mtd, &ei);
if (err) { if (err) {
printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
return err; return err;
...@@ -105,7 +105,7 @@ static int multiblock_erase(int ebnum, int blocks) ...@@ -105,7 +105,7 @@ static int multiblock_erase(int ebnum, int blocks)
ei.addr = addr; ei.addr = addr;
ei.len = mtd->erasesize * blocks; ei.len = mtd->erasesize * blocks;
err = mtd->erase(mtd, &ei); err = mtd_erase(mtd, &ei);
if (err) { if (err) {
printk(PRINT_PREF "error %d while erasing EB %d, blocks %d\n", printk(PRINT_PREF "error %d while erasing EB %d, blocks %d\n",
err, ebnum, blocks); err, ebnum, blocks);
......
...@@ -112,7 +112,7 @@ static int erase_eraseblock(int ebnum) ...@@ -112,7 +112,7 @@ static int erase_eraseblock(int ebnum)
ei.addr = addr; ei.addr = addr;
ei.len = mtd->erasesize; ei.len = mtd->erasesize;
err = mtd->erase(mtd, &ei); err = mtd_erase(mtd, &ei);
if (unlikely(err)) { if (unlikely(err)) {
printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
return err; return err;
......
...@@ -80,7 +80,7 @@ static int erase_eraseblock(int ebnum) ...@@ -80,7 +80,7 @@ static int erase_eraseblock(int ebnum)
ei.addr = addr; ei.addr = addr;
ei.len = mtd->erasesize; ei.len = mtd->erasesize;
err = mtd->erase(mtd, &ei); err = mtd_erase(mtd, &ei);
if (err) { if (err) {
printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
return err; return err;
......
...@@ -105,7 +105,7 @@ static inline int erase_eraseblock(int ebnum) ...@@ -105,7 +105,7 @@ static inline int erase_eraseblock(int ebnum)
ei.addr = addr; ei.addr = addr;
ei.len = mtd->erasesize; ei.len = mtd->erasesize;
err = mtd->erase(mtd, &ei); err = mtd_erase(mtd, &ei);
if (err) { if (err) {
printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum); printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
return err; return err;
......
...@@ -361,7 +361,7 @@ static int do_sync_erase(struct ubi_device *ubi, int pnum) ...@@ -361,7 +361,7 @@ static int do_sync_erase(struct ubi_device *ubi, int pnum)
ei.callback = erase_callback; ei.callback = erase_callback;
ei.priv = (unsigned long)&wq; ei.priv = (unsigned long)&wq;
err = ubi->mtd->erase(ubi->mtd, &ei); err = mtd_erase(ubi->mtd, &ei);
if (err) { if (err) {
if (retries++ < UBI_IO_RETRIES) { if (retries++ < UBI_IO_RETRIES) {
dbg_io("error %d while erasing PEB %d, retry", dbg_io("error %d while erasing PEB %d, retry",
......
...@@ -188,7 +188,7 @@ u16 mtd_Erase_Block(u32 block_add) ...@@ -188,7 +188,7 @@ u16 mtd_Erase_Block(u32 block_add)
erase.len = spectra_mtd->erasesize; erase.len = spectra_mtd->erasesize;
erase.priv = (unsigned long)&comp; erase.priv = (unsigned long)&comp;
ret = spectra_mtd->erase(spectra_mtd, &erase); ret = mtd_erase(spectra_mtd, &erase);
if (!ret) { if (!ret) {
wait_for_completion(&comp); wait_for_completion(&comp);
if (erase.state != MTD_ERASE_DONE) if (erase.state != MTD_ERASE_DONE)
......
...@@ -74,7 +74,7 @@ static void jffs2_erase_block(struct jffs2_sb_info *c, ...@@ -74,7 +74,7 @@ static void jffs2_erase_block(struct jffs2_sb_info *c,
((struct erase_priv_struct *)instr->priv)->jeb = jeb; ((struct erase_priv_struct *)instr->priv)->jeb = jeb;
((struct erase_priv_struct *)instr->priv)->c = c; ((struct erase_priv_struct *)instr->priv)->c = c;
ret = c->mtd->erase(c->mtd, instr); ret = mtd_erase(c->mtd, instr);
if (!ret) if (!ret)
return; return;
......
...@@ -105,7 +105,7 @@ static int logfs_mtd_erase(struct super_block *sb, loff_t ofs, size_t len, ...@@ -105,7 +105,7 @@ static int logfs_mtd_erase(struct super_block *sb, loff_t ofs, size_t len,
ei.len = len; ei.len = len;
ei.callback = logfs_erase_callback; ei.callback = logfs_erase_callback;
ei.priv = (long)&complete; ei.priv = (long)&complete;
ret = mtd->erase(mtd, &ei); ret = mtd_erase(mtd, &ei);
if (ret) if (ret)
return -EIO; return -EIO;
......
...@@ -171,11 +171,8 @@ struct mtd_info { ...@@ -171,11 +171,8 @@ struct mtd_info {
struct mtd_erase_region_info *eraseregions; struct mtd_erase_region_info *eraseregions;
/* /*
* Erase is an asynchronous operation. Device drivers are supposed * Do not call via these pointers, use corresponding mtd_*()
* to call instr->callback() whenever the operation completes, even * wrappers instead.
* if it completes with a failure.
* Callers are supposed to pass a callback function and wait for it
* to be called before writing to the block.
*/ */
int (*erase) (struct mtd_info *mtd, struct erase_info *instr); int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
...@@ -274,6 +271,18 @@ struct mtd_info { ...@@ -274,6 +271,18 @@ struct mtd_info {
void (*put_device) (struct mtd_info *mtd); void (*put_device) (struct mtd_info *mtd);
}; };
/*
* Erase is an asynchronous operation. Device drivers are supposed
* to call instr->callback() whenever the operation completes, even
* if it completes with a failure.
* Callers are supposed to pass a callback function and wait for it
* to be called before writing to the block.
*/
static inline int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
{
return mtd->erase(mtd, instr);
}
static inline struct mtd_info *dev_to_mtd(struct device *dev) static inline struct mtd_info *dev_to_mtd(struct device *dev)
{ {
return dev ? dev_get_drvdata(dev) : NULL; return dev ? dev_get_drvdata(dev) : NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment