X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fmtd%2Fmtdblock.c;h=952da30b17452d829bc97b669b626a38d1836ab5;hb=refs%2Fheads%2Fvserver;hp=965c5954d7281638f011dcc299a2b8f4096069d1;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c index 965c5954d..952da30b1 100644 --- a/drivers/mtd/mtdblock.c +++ b/drivers/mtd/mtdblock.c @@ -1,27 +1,30 @@ -/* +/* * Direct MTD block device access * - * $Id: mtdblock.c,v 1.63 2003/06/23 12:00:08 dwmw2 Exp $ + * $Id: mtdblock.c,v 1.68 2005/11/07 11:14:20 gleixner Exp $ * * (C) 2000-2003 Nicolas Pitre * (C) 1999-2003 David Woodhouse */ -#include -#include -#include -#include #include #include +#include +#include +#include #include +#include #include + #include #include +#include + static struct mtdblk_dev { struct mtd_info *mtd; int count; - struct semaphore cache_sem; + struct mutex cache_mutex; unsigned char *cache_data; unsigned long cache_offset; unsigned int cache_size; @@ -30,7 +33,7 @@ static struct mtdblk_dev { /* * Cache stuff... - * + * * Since typical flash erasable sectors are much larger than what Linux's * buffer cache can handle, we must implement read-modify-write on flash * sectors for each block write requests. To avoid over-erasing flash sectors @@ -44,7 +47,7 @@ static void erase_callback(struct erase_info *done) wake_up(wait_q); } -static int erase_write (struct mtd_info *mtd, unsigned long pos, +static int erase_write (struct mtd_info *mtd, unsigned long pos, int len, const char *buf) { struct erase_info erase; @@ -67,7 +70,7 @@ static int erase_write (struct mtd_info *mtd, unsigned long pos, set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&wait_q, &wait); - ret = MTD_ERASE(mtd, &erase); + ret = mtd->erase(mtd, &erase); if (ret) { set_current_state(TASK_RUNNING); remove_wait_queue(&wait_q, &wait); @@ -84,7 +87,7 @@ static int erase_write (struct mtd_info *mtd, unsigned long pos, * Next, writhe data to flash. */ - ret = MTD_WRITE (mtd, pos, len, &retlen, buf); + ret = mtd->write(mtd, pos, len, &retlen, buf); if (ret) return ret; if (retlen != len) @@ -102,18 +105,18 @@ static int write_cached_data (struct mtdblk_dev *mtdblk) return 0; DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: writing cached data for \"%s\" " - "at 0x%lx, size 0x%x\n", mtd->name, + "at 0x%lx, size 0x%x\n", mtd->name, mtdblk->cache_offset, mtdblk->cache_size); - - ret = erase_write (mtd, mtdblk->cache_offset, + + ret = erase_write (mtd, mtdblk->cache_offset, mtdblk->cache_size, mtdblk->cache_data); if (ret) return ret; /* * Here we could argubly set the cache state to STATE_CLEAN. - * However this could lead to inconsistency since we will not - * be notified if this content is altered on the flash by other + * However this could lead to inconsistency since we will not + * be notified if this content is altered on the flash by other * means. Let's declare it empty and leave buffering tasks to * the buffer cache instead. */ @@ -122,7 +125,7 @@ static int write_cached_data (struct mtdblk_dev *mtdblk) } -static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos, +static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos, int len, const char *buf) { struct mtd_info *mtd = mtdblk->mtd; @@ -132,19 +135,19 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos, DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: write on \"%s\" at 0x%lx, size 0x%x\n", mtd->name, pos, len); - + if (!sect_size) - return MTD_WRITE (mtd, pos, len, &retlen, buf); + return mtd->write(mtd, pos, len, &retlen, buf); while (len > 0) { unsigned long sect_start = (pos/sect_size)*sect_size; unsigned int offset = pos - sect_start; unsigned int size = sect_size - offset; - if( size > len ) + if( size > len ) size = len; if (size == sect_size) { - /* + /* * We are covering a whole sector. Thus there is no * need to bother with the cache while it may still be * useful for other partial writes. @@ -158,7 +161,7 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos, if (mtdblk->cache_state == STATE_DIRTY && mtdblk->cache_offset != sect_start) { ret = write_cached_data(mtdblk); - if (ret) + if (ret) return ret; } @@ -166,7 +169,8 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos, mtdblk->cache_offset != sect_start) { /* fill the cache with the current sector */ mtdblk->cache_state = STATE_EMPTY; - ret = MTD_READ(mtd, sect_start, sect_size, &retlen, mtdblk->cache_data); + ret = mtd->read(mtd, sect_start, sect_size, + &retlen, mtdblk->cache_data); if (ret) return ret; if (retlen != sect_size) @@ -191,7 +195,7 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos, } -static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos, +static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos, int len, char *buf) { struct mtd_info *mtd = mtdblk->mtd; @@ -199,17 +203,17 @@ static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos, size_t retlen; int ret; - DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: read on \"%s\" at 0x%lx, size 0x%x\n", + DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: read on \"%s\" at 0x%lx, size 0x%x\n", mtd->name, pos, len); - + if (!sect_size) - return MTD_READ (mtd, pos, len, &retlen, buf); + return mtd->read(mtd, pos, len, &retlen, buf); while (len > 0) { unsigned long sect_start = (pos/sect_size)*sect_size; unsigned int offset = pos - sect_start; unsigned int size = sect_size - offset; - if (size > len) + if (size > len) size = len; /* @@ -222,7 +226,7 @@ static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos, mtdblk->cache_offset == sect_start) { memcpy (buf, mtdblk->cache_data + offset, size); } else { - ret = MTD_READ (mtd, pos, size, &retlen, buf); + ret = mtd->read(mtd, pos, size, &retlen, buf); if (ret) return ret; if (retlen != size) @@ -248,7 +252,7 @@ static int mtdblock_writesect(struct mtd_blktrans_dev *dev, unsigned long block, char *buf) { struct mtdblk_dev *mtdblk = mtdblks[dev->devnum]; - if (unlikely(!mtdblk->cache_data)) { + if (unlikely(!mtdblk->cache_data && mtdblk->cache_size)) { mtdblk->cache_data = vmalloc(mtdblk->mtd->erasesize); if (!mtdblk->cache_data) return -EINTR; @@ -267,31 +271,29 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd) int dev = mbd->devnum; DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n"); - + if (mtdblks[dev]) { mtdblks[dev]->count++; return 0; } - + /* OK, it's not open. Create cache info for it */ - mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL); - if (!mtdblks) + mtdblk = kzalloc(sizeof(struct mtdblk_dev), GFP_KERNEL); + if (!mtdblk) return -ENOMEM; - memset(mtdblk, 0, sizeof(*mtdblk)); mtdblk->count = 1; mtdblk->mtd = mtd; - init_MUTEX (&mtdblk->cache_sem); + mutex_init(&mtdblk->cache_mutex); mtdblk->cache_state = STATE_EMPTY; - if ((mtdblk->mtd->flags & MTD_CAP_RAM) != MTD_CAP_RAM && - mtdblk->mtd->erasesize) { + if ( !(mtdblk->mtd->flags & MTD_NO_ERASE) && mtdblk->mtd->erasesize) { mtdblk->cache_size = mtdblk->mtd->erasesize; mtdblk->cache_data = NULL; } mtdblks[dev] = mtdblk; - + DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); return 0; @@ -304,9 +306,9 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd) DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n"); - down(&mtdblk->cache_sem); + mutex_lock(&mtdblk->cache_mutex); write_cached_data(mtdblk); - up(&mtdblk->cache_sem); + mutex_unlock(&mtdblk->cache_mutex); if (!--mtdblk->count) { /* It was the last usage. Free the device */ @@ -319,15 +321,15 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd) DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); return 0; -} +} static int mtdblock_flush(struct mtd_blktrans_dev *dev) { struct mtdblk_dev *mtdblk = mtdblks[dev->devnum]; - down(&mtdblk->cache_sem); + mutex_lock(&mtdblk->cache_mutex); write_cached_data(mtdblk); - up(&mtdblk->cache_sem); + mutex_unlock(&mtdblk->cache_mutex); if (mtdblk->mtd->sync) mtdblk->mtd->sync(mtdblk->mtd); @@ -336,16 +338,14 @@ static int mtdblock_flush(struct mtd_blktrans_dev *dev) static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) { - struct mtd_blktrans_dev *dev = kmalloc(sizeof(*dev), GFP_KERNEL); + struct mtd_blktrans_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return; - memset(dev, 0, sizeof(*dev)); - dev->mtd = mtd; dev->devnum = mtd->index; - dev->blksize = 512; + dev->size = mtd->size >> 9; dev->tr = tr; @@ -361,10 +361,11 @@ static void mtdblock_remove_dev(struct mtd_blktrans_dev *dev) kfree(dev); } -struct mtd_blktrans_ops mtdblock_tr = { +static struct mtd_blktrans_ops mtdblock_tr = { .name = "mtdblock", .major = 31, .part_bits = 0, + .blksize = 512, .open = mtdblock_open, .flush = mtdblock_flush, .release = mtdblock_release, @@ -375,7 +376,7 @@ struct mtd_blktrans_ops mtdblock_tr = { .owner = THIS_MODULE, }; -int __init init_mtdblock(void) +static int __init init_mtdblock(void) { return register_mtd_blktrans(&mtdblock_tr); }