summaryrefslogtreecommitdiffstats
path: root/linux-2.4.x/drivers/mtd/mtdblock.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux-2.4.x/drivers/mtd/mtdblock.c')
-rw-r--r--linux-2.4.x/drivers/mtd/mtdblock.c535
1 files changed, 109 insertions, 426 deletions
diff --git a/linux-2.4.x/drivers/mtd/mtdblock.c b/linux-2.4.x/drivers/mtd/mtdblock.c
index fdea52d..3605286 100644
--- a/linux-2.4.x/drivers/mtd/mtdblock.c
+++ b/linux-2.4.x/drivers/mtd/mtdblock.c
@@ -1,76 +1,40 @@
-/*
+/*
* Direct MTD block device access
*
- * $Id: mtdblock.c,v 1.51 2001/11/20 11:42:33 dwmw2 Exp $
+ * $Id: mtdblock.c,v 1.69 2006/03/29 08:26:27 dwmw2 Exp $
*
- * 02-nov-2000 Nicolas Pitre Added read-modify-write with cache
+ * (C) 2000-2003 Nicolas Pitre <nico@cam.org>
+ * (C) 1999-2003 David Woodhouse <dwmw2@infradead.org>
*/
#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/vmalloc.h>
+
#include <linux/mtd/mtd.h>
-#include <linux/mtd/compatmac.h>
-
-#define MAJOR_NR MTD_BLOCK_MAJOR
-#define DEVICE_NAME "mtdblock"
-#define DEVICE_REQUEST mtdblock_request
-#define DEVICE_NR(device) (device)
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
-#define DEVICE_NO_RANDOM
-#include <linux/blk.h>
-/* for old kernels... */
-#ifndef QUEUE_EMPTY
-#define QUEUE_EMPTY (!CURRENT)
-#endif
-#if LINUX_VERSION_CODE < 0x20300
-#define QUEUE_PLUGGED (blk_dev[MAJOR_NR].plug_tq.sync)
-#else
-#define QUEUE_PLUGGED (blk_dev[MAJOR_NR].request_queue.plugged)
-#endif
-
-#ifdef CONFIG_DEVFS_FS
-#include <linux/devfs_fs_kernel.h>
-static void mtd_notify_add(struct mtd_info* mtd);
-static void mtd_notify_remove(struct mtd_info* mtd);
-static struct mtd_notifier notifier = {
- mtd_notify_add,
- mtd_notify_remove,
- NULL
-};
-static devfs_handle_t devfs_dir_handle = NULL;
-static devfs_handle_t devfs_rw_handle[MAX_MTD_DEVICES];
-#endif
+#include <linux/mtd/blktrans.h>
+#include <linux/mutex.h>
+
static struct mtdblk_dev {
- struct mtd_info *mtd; /* Locked */
+ 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;
enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state;
} *mtdblks[MAX_MTD_DEVICES];
-static spinlock_t mtdblks_lock;
-
-static int mtd_sizes[MAX_MTD_DEVICES];
-static int mtd_blksizes[MAX_MTD_DEVICES];
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,14)
-#define BLK_INC_USE_COUNT MOD_INC_USE_COUNT
-#define BLK_DEC_USE_COUNT MOD_DEC_USE_COUNT
-#else
-#define BLK_INC_USE_COUNT do {} while(0)
-#define BLK_DEC_USE_COUNT do {} while(0)
-#endif
-
/*
* 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
@@ -84,7 +48,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;
@@ -142,18 +106,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 argably 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
+ * 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
* means. Let's declare it empty and leave buffering tasks to
* the buffer cache instead.
*/
@@ -162,7 +126,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;
@@ -172,7 +136,7 @@ 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);
@@ -180,11 +144,11 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos,
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.
@@ -198,7 +162,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;
}
@@ -231,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;
@@ -239,9 +203,9 @@ 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);
@@ -249,7 +213,7 @@ static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos,
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;
/*
@@ -277,433 +241,152 @@ static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos,
return 0;
}
+static int mtdblock_readsect(struct mtd_blktrans_dev *dev,
+ unsigned long block, char *buf)
+{
+ struct mtdblk_dev *mtdblk = mtdblks[dev->devnum];
+ return do_cached_read(mtdblk, block<<9, 512, buf);
+}
+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 && mtdblk->cache_size)) {
+ mtdblk->cache_data = vmalloc(mtdblk->mtd->erasesize);
+ if (!mtdblk->cache_data)
+ return -EINTR;
+ /* -EINTR is not really correct, but it is the best match
+ * documented in man 2 write for all cases. We could also
+ * return -EAGAIN sometimes, but why bother?
+ */
+ }
+ return do_cached_write(mtdblk, block<<9, 512, buf);
+}
-static int mtdblock_open(struct inode *inode, struct file *file)
+static int mtdblock_open(struct mtd_blktrans_dev *mbd)
{
struct mtdblk_dev *mtdblk;
- struct mtd_info *mtd;
- int dev;
+ struct mtd_info *mtd = mbd->mtd;
+ int dev = mbd->devnum;
DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n");
-
- if (!inode)
- return -EINVAL;
-
- dev = MINOR(inode->i_rdev);
- if (dev >= MAX_MTD_DEVICES)
- return -EINVAL;
-
- BLK_INC_USE_COUNT;
-
- mtd = get_mtd_device(NULL, dev);
- if (!mtd)
- return -ENODEV;
- if (MTD_ABSENT == mtd->type) {
- put_mtd_device(mtd);
- BLK_DEC_USE_COUNT;
- return -ENODEV;
- }
-
- spin_lock(&mtdblks_lock);
- /* If it's already open, no need to piss about. */
if (mtdblks[dev]) {
mtdblks[dev]->count++;
- spin_unlock(&mtdblks_lock);
return 0;
}
-
- /* OK, it's not open. Try to find it */
-
- /* First we have to drop the lock, because we have to
- to things which might sleep.
- */
- spin_unlock(&mtdblks_lock);
+ /* OK, it's not open. Create cache info for it */
mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);
- if (!mtdblk) {
- put_mtd_device(mtd);
- BLK_DEC_USE_COUNT;
+ 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) {
mtdblk->cache_size = mtdblk->mtd->erasesize;
- mtdblk->cache_data = vmalloc(mtdblk->mtd->erasesize);
- if (!mtdblk->cache_data) {
- put_mtd_device(mtdblk->mtd);
- kfree(mtdblk);
- BLK_DEC_USE_COUNT;
- return -ENOMEM;
- }
- }
-
- /* OK, we've created a new one. Add it to the list. */
-
- spin_lock(&mtdblks_lock);
-
- if (mtdblks[dev]) {
- /* Another CPU made one at the same time as us. */
- mtdblks[dev]->count++;
- spin_unlock(&mtdblks_lock);
- put_mtd_device(mtdblk->mtd);
- vfree(mtdblk->cache_data);
- kfree(mtdblk);
- return 0;
+ mtdblk->cache_data = NULL;
}
mtdblks[dev] = mtdblk;
- mtd_sizes[dev] = mtdblk->mtd->size/1024;
- if (mtdblk->mtd->erasesize)
- mtd_blksizes[dev] = mtdblk->mtd->erasesize;
- if (mtd_blksizes[dev] > PAGE_SIZE)
- mtd_blksizes[dev] = PAGE_SIZE;
- set_device_ro (inode->i_rdev, !(mtdblk->mtd->flags & MTD_WRITEABLE));
-
- spin_unlock(&mtdblks_lock);
-
+
DEBUG(MTD_DEBUG_LEVEL1, "ok\n");
return 0;
}
-static release_t mtdblock_release(struct inode *inode, struct file *file)
+static int mtdblock_release(struct mtd_blktrans_dev *mbd)
{
- int dev;
- struct mtdblk_dev *mtdblk;
- DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n");
-
- if (inode == NULL)
- release_return(-ENODEV);
+ int dev = mbd->devnum;
+ struct mtdblk_dev *mtdblk = mtdblks[dev];
- dev = MINOR(inode->i_rdev);
- mtdblk = mtdblks[dev];
+ 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);
- spin_lock(&mtdblks_lock);
if (!--mtdblk->count) {
/* It was the last usage. Free the device */
mtdblks[dev] = NULL;
- spin_unlock(&mtdblks_lock);
if (mtdblk->mtd->sync)
mtdblk->mtd->sync(mtdblk->mtd);
- put_mtd_device(mtdblk->mtd);
vfree(mtdblk->cache_data);
kfree(mtdblk);
- } else {
- spin_unlock(&mtdblks_lock);
}
-
DEBUG(MTD_DEBUG_LEVEL1, "ok\n");
- BLK_DEC_USE_COUNT;
- release_return(0);
-}
-
-
-/*
- * This is a special request_fn because it is executed in a process context
- * to be able to sleep independently of the caller. The io_request_lock
- * is held upon entry and exit.
- * The head of our request queue is considered active so there is no need
- * to dequeue requests before we are done.
- */
-static void handle_mtdblock_request(void)
-{
- struct request *req;
- struct mtdblk_dev *mtdblk;
- unsigned int res;
-
- for (;;) {
- INIT_REQUEST;
- req = CURRENT;
- spin_unlock_irq(&io_request_lock);
- mtdblk = mtdblks[MINOR(req->rq_dev)];
- res = 0;
-
- if (MINOR(req->rq_dev) >= MAX_MTD_DEVICES)
- panic(__FUNCTION__": minor out of bound");
-
- if ((req->sector + req->current_nr_sectors) > (mtdblk->mtd->size >> 9))
- goto end_req;
-
- // Handle the request
- switch (req->cmd)
- {
- int err;
-
- case READ:
- down(&mtdblk->cache_sem);
- err = do_cached_read (mtdblk, req->sector << 9,
- req->current_nr_sectors << 9,
- req->buffer);
- up(&mtdblk->cache_sem);
- if (!err)
- res = 1;
- break;
-
- case WRITE:
- // Read only device
- if ( !(mtdblk->mtd->flags & MTD_WRITEABLE) )
- break;
-
- // Do the write
- down(&mtdblk->cache_sem);
- err = do_cached_write (mtdblk, req->sector << 9,
- req->current_nr_sectors << 9,
- req->buffer);
- up(&mtdblk->cache_sem);
- if (!err)
- res = 1;
- break;
- }
-
-end_req:
- spin_lock_irq(&io_request_lock);
- end_request(res);
- }
+ return 0;
}
-static volatile int leaving = 0;
-static DECLARE_MUTEX_LOCKED(thread_sem);
-static DECLARE_WAIT_QUEUE_HEAD(thr_wq);
-
-int mtdblock_thread(void *dummy)
+static int mtdblock_flush(struct mtd_blktrans_dev *dev)
{
- struct task_struct *tsk = current;
- DECLARE_WAITQUEUE(wait, tsk);
-
- tsk->session = 1;
- tsk->pgrp = 1;
- /* we might get involved when memory gets low, so use PF_MEMALLOC */
- tsk->flags |= PF_MEMALLOC;
- strcpy(tsk->comm, "mtdblockd");
- tsk->tty = NULL;
- spin_lock_irq(&tsk->sigmask_lock);
- sigfillset(&tsk->blocked);
- recalc_sigpending(tsk);
- spin_unlock_irq(&tsk->sigmask_lock);
- exit_mm(tsk);
- exit_files(tsk);
- exit_sighand(tsk);
- exit_fs(tsk);
-
- while (!leaving) {
- add_wait_queue(&thr_wq, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
- spin_lock_irq(&io_request_lock);
- if (QUEUE_EMPTY || QUEUE_PLUGGED) {
- spin_unlock_irq(&io_request_lock);
- schedule();
- remove_wait_queue(&thr_wq, &wait);
- } else {
- remove_wait_queue(&thr_wq, &wait);
- set_current_state(TASK_RUNNING);
- handle_mtdblock_request();
- spin_unlock_irq(&io_request_lock);
- }
- }
+ struct mtdblk_dev *mtdblk = mtdblks[dev->devnum];
+
+ mutex_lock(&mtdblk->cache_mutex);
+ write_cached_data(mtdblk);
+ mutex_unlock(&mtdblk->cache_mutex);
- up(&thread_sem);
+ if (mtdblk->mtd->sync)
+ mtdblk->mtd->sync(mtdblk->mtd);
return 0;
}
-#if LINUX_VERSION_CODE < 0x20300
-#define RQFUNC_ARG void
-#else
-#define RQFUNC_ARG request_queue_t *q
-#endif
-
-static void mtdblock_request(RQFUNC_ARG)
+static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
{
- /* Don't do anything, except wake the thread if necessary */
- wake_up(&thr_wq);
-}
+ struct mtd_blktrans_dev *dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return;
-static int mtdblock_ioctl(struct inode * inode, struct file * file,
- unsigned int cmd, unsigned long arg)
-{
- struct mtdblk_dev *mtdblk;
+ memset(dev, 0, sizeof(*dev));
- mtdblk = mtdblks[MINOR(inode->i_rdev)];
+ dev->mtd = mtd;
+ dev->devnum = mtd->index;
+ dev->blksize = 512;
+ dev->size = mtd->size >> 9;
+ dev->tr = tr;
-#ifdef PARANOIA
- if (!mtdblk)
- BUG();
-#endif
-
- switch (cmd) {
- case BLKGETSIZE: /* Return device size */
- return put_user((mtdblk->mtd->size >> 9), (unsigned long *) arg);
-
-#ifdef BLKGETSIZE64
- case BLKGETSIZE64:
- return put_user((u64)mtdblk->mtd->size, (u64 *)arg);
-#endif
-
- case BLKFLSBUF:
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
- if(!capable(CAP_SYS_ADMIN))
- return -EACCES;
-#endif
- fsync_dev(inode->i_rdev);
- invalidate_buffers(inode->i_rdev);
- down(&mtdblk->cache_sem);
- write_cached_data(mtdblk);
- up(&mtdblk->cache_sem);
- if (mtdblk->mtd->sync)
- mtdblk->mtd->sync(mtdblk->mtd);
- return 0;
+ if (!(mtd->flags & MTD_WRITEABLE))
+ dev->readonly = 1;
- default:
- return -EINVAL;
- }
+ add_mtd_blktrans_dev(dev);
}
-
-#ifdef MAGIC_ROM_PTR
-static int
-mtdblock_romptr(kdev_t dev, struct vm_area_struct * vma)
+static void mtdblock_remove_dev(struct mtd_blktrans_dev *dev)
{
- struct mtd_info *mtd;
- u_char *ptr;
- size_t len;
-
- mtd = __get_mtd_device(NULL, MINOR(dev));
-
- if (!mtd->point)
- return -ENOSYS; /* Can't do it, No function to point to correct addr */
-
- if ((*mtd->point)(mtd,vma->vm_offset,vma->vm_end-vma->vm_start,&len,&ptr) != 0)
- return -ENOSYS;
-
- vma->vm_start = (unsigned long) ptr;
- vma->vm_end = vma->vm_start + len;
- return 0;
+ del_mtd_blktrans_dev(dev);
+ kfree(dev);
}
-#endif
-
-#if LINUX_VERSION_CODE < 0x20326
-static struct file_operations mtd_fops =
-{
- open: mtdblock_open,
- ioctl: mtdblock_ioctl,
- release: mtdblock_release,
- read: block_read,
-#ifdef MAGIC_ROM_PTR
- romptr: mtdblock_romptr,
-#endif
- write: block_write
-};
-#else
-static struct block_device_operations mtd_fops =
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,14)
- owner: THIS_MODULE,
-#endif
- open: mtdblock_open,
- release: mtdblock_release,
-#ifdef MAGIC_ROM_PTR
- romptr: mtdblock_romptr,
-#endif
- ioctl: mtdblock_ioctl
+static struct mtd_blktrans_ops mtdblock_tr = {
+ .name = "mtdblock",
+ .major = 31,
+ .part_bits = 0,
+ .open = mtdblock_open,
+ .flush = mtdblock_flush,
+ .release = mtdblock_release,
+ .readsect = mtdblock_readsect,
+ .writesect = mtdblock_writesect,
+ .add_mtd = mtdblock_add_mtd,
+ .remove_dev = mtdblock_remove_dev,
+ .owner = THIS_MODULE,
};
-#endif
-
-#ifdef CONFIG_DEVFS_FS
-/* Notification that a new device has been added. Create the devfs entry for
- * it. */
-
-static void mtd_notify_add(struct mtd_info* mtd)
-{
- char name[8];
- if (!mtd || mtd->type == MTD_ABSENT)
- return;
-
- sprintf(name, "%d", mtd->index);
- devfs_rw_handle[mtd->index] = devfs_register(devfs_dir_handle, name,
- DEVFS_FL_DEFAULT, MTD_BLOCK_MAJOR, mtd->index,
- S_IFBLK | S_IRUGO | S_IWUGO,
- &mtd_fops, NULL);
-}
-
-static void mtd_notify_remove(struct mtd_info* mtd)
-{
- if (!mtd || mtd->type == MTD_ABSENT)
- return;
-
- devfs_unregister(devfs_rw_handle[mtd->index]);
-}
-#endif
-
-int __init init_mtdblock(void)
+static int __init init_mtdblock(void)
{
- int i;
-
- spin_lock_init(&mtdblks_lock);
-#ifdef CONFIG_DEVFS_FS
- if (devfs_register_blkdev(MTD_BLOCK_MAJOR, DEVICE_NAME, &mtd_fops))
- {
- printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",
- MTD_BLOCK_MAJOR);
- return -EAGAIN;
- }
-
- devfs_dir_handle = devfs_mk_dir(NULL, DEVICE_NAME, NULL);
- register_mtd_user(&notifier);
-#else
- if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) {
- printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",
- MTD_BLOCK_MAJOR);
- return -EAGAIN;
- }
-#endif
- DEBUG(MTD_DEBUG_LEVEL3,
- "init_mtdblock: allocated major number %d.\n", MTD_BLOCK_MAJOR);
-
- /* We fill it in at open() time. */
- for (i=0; i< MAX_MTD_DEVICES; i++) {
- mtd_sizes[i] = 0;
- mtd_blksizes[i] = BLOCK_SIZE;
- }
- init_waitqueue_head(&thr_wq);
- /* Allow the block size to default to BLOCK_SIZE. */
- blksize_size[MAJOR_NR] = mtd_blksizes;
- blk_size[MAJOR_NR] = mtd_sizes;
-
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &mtdblock_request);
- kernel_thread (mtdblock_thread, NULL, CLONE_FS|CLONE_FILES|CLONE_SIGHAND);
- return 0;
+ return register_mtd_blktrans(&mtdblock_tr);
}
static void __exit cleanup_mtdblock(void)
{
- leaving = 1;
- wake_up(&thr_wq);
- down(&thread_sem);
-#ifdef CONFIG_DEVFS_FS
- unregister_mtd_user(&notifier);
- devfs_unregister(devfs_dir_handle);
- devfs_unregister_blkdev(MTD_BLOCK_MAJOR, DEVICE_NAME);
-#else
- unregister_blkdev(MAJOR_NR,DEVICE_NAME);
-#endif
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
- blksize_size[MAJOR_NR] = NULL;
- blk_size[MAJOR_NR] = NULL;
+ deregister_mtd_blktrans(&mtdblock_tr);
}
module_init(init_mtdblock);