]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/mtd/mtdcore.c
vmemmap: warn about page_structs with remote distance
[linux-2.6-omap-h63xx.git] / drivers / mtd / mtdcore.c
index c4d26de74349e55f9ae32269ff780b0dde50e767..a9d246949820a9b0b61aef86061ddf341be21f92 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: mtdcore.c,v 1.47 2005/11/07 11:14:20 gleixner Exp $
- *
  * Core registration and callback routines for MTD
  * drivers and users.
  *
@@ -8,13 +6,13 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/major.h>
 #include <linux/fs.h>
+#include <linux/err.h>
 #include <linux/ioctl.h>
 #include <linux/init.h>
 #include <linux/mtd/compatmac.h>
@@ -22,6 +20,8 @@
 
 #include <linux/mtd/mtd.h>
 
+#include "mtdcore.h"
+
 /* These are exported solely for the purpose of mtd_blkdevs.c. You
    should not use them for _anything_ else */
 DEFINE_MUTEX(mtd_table_mutex);
@@ -51,7 +51,7 @@ int add_mtd_device(struct mtd_info *mtd)
 
        for (i=0; i < MAX_MTD_DEVICES; i++)
                if (!mtd_table[i]) {
-                       struct list_head *this;
+                       struct mtd_notifier *not;
 
                        mtd_table[i] = mtd;
                        mtd->index = i;
@@ -59,7 +59,7 @@ int add_mtd_device(struct mtd_info *mtd)
 
                        /* Some chips always power up locked. Unlock them now */
                        if ((mtd->flags & MTD_WRITEABLE)
-                           && (mtd->flags & MTD_STUPID_LOCK) && mtd->unlock) {
+                           && (mtd->flags & MTD_POWERUP_LOCK) && mtd->unlock) {
                                if (mtd->unlock(mtd, 0, mtd->size))
                                        printk(KERN_WARNING
                                               "%s: unlock failed, "
@@ -70,10 +70,8 @@ int add_mtd_device(struct mtd_info *mtd)
                        DEBUG(0, "mtd: Giving out device %d to %s\n",i, mtd->name);
                        /* No need to get a refcount on the module containing
                           the notifier, since we hold the mtd_table_mutex */
-                       list_for_each(this, &mtd_notifiers) {
-                               struct mtd_notifier *not = list_entry(this, struct mtd_notifier, list);
+                       list_for_each_entry(not, &mtd_notifiers, list)
                                not->add(mtd);
-                       }
 
                        mutex_unlock(&mtd_table_mutex);
                        /* We _know_ we aren't being removed, because
@@ -111,14 +109,12 @@ int del_mtd_device (struct mtd_info *mtd)
                       mtd->index, mtd->name, mtd->usecount);
                ret = -EBUSY;
        } else {
-               struct list_head *this;
+               struct mtd_notifier *not;
 
                /* No need to get a refcount on the module containing
                   the notifier, since we hold the mtd_table_mutex */
-               list_for_each(this, &mtd_notifiers) {
-                       struct mtd_notifier *not = list_entry(this, struct mtd_notifier, list);
+               list_for_each_entry(not, &mtd_notifiers, list)
                        not->remove(mtd);
-               }
 
                mtd_table[mtd->index] = NULL;
 
@@ -192,14 +188,14 @@ int unregister_mtd_user (struct mtd_notifier *old)
  *     Given a number and NULL address, return the num'th entry in the device
  *     table, if any.  Given an address and num == -1, search the device table
  *     for a device with that address and return if it's still present. Given
- *     both, return the num'th driver only if its address matches. Return NULL
- *     if not.
+ *     both, return the num'th driver only if its address matches. Return
+ *     error code if not.
  */
 
 struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
 {
        struct mtd_info *ret = NULL;
-       int i;
+       int i, err = -ENODEV;
 
        mutex_lock(&mtd_table_mutex);
 
@@ -213,14 +209,73 @@ struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
                        ret = NULL;
        }
 
-       if (ret && !try_module_get(ret->owner))
-               ret = NULL;
+       if (!ret)
+               goto out_unlock;
+
+       if (!try_module_get(ret->owner))
+               goto out_unlock;
 
-       if (ret)
-               ret->usecount++;
+       if (ret->get_device) {
+               err = ret->get_device(ret);
+               if (err)
+                       goto out_put;
+       }
 
+       ret->usecount++;
        mutex_unlock(&mtd_table_mutex);
        return ret;
+
+out_put:
+       module_put(ret->owner);
+out_unlock:
+       mutex_unlock(&mtd_table_mutex);
+       return ERR_PTR(err);
+}
+
+/**
+ *     get_mtd_device_nm - obtain a validated handle for an MTD device by
+ *     device name
+ *     @name: MTD device name to open
+ *
+ *     This function returns MTD device description structure in case of
+ *     success and an error code in case of failure.
+ */
+
+struct mtd_info *get_mtd_device_nm(const char *name)
+{
+       int i, err = -ENODEV;
+       struct mtd_info *mtd = NULL;
+
+       mutex_lock(&mtd_table_mutex);
+
+       for (i = 0; i < MAX_MTD_DEVICES; i++) {
+               if (mtd_table[i] && !strcmp(name, mtd_table[i]->name)) {
+                       mtd = mtd_table[i];
+                       break;
+               }
+       }
+
+       if (!mtd)
+               goto out_unlock;
+
+       if (!try_module_get(mtd->owner))
+               goto out_unlock;
+
+       if (mtd->get_device) {
+               err = mtd->get_device(mtd);
+               if (err)
+                       goto out_put;
+       }
+
+       mtd->usecount++;
+       mutex_unlock(&mtd_table_mutex);
+       return mtd;
+
+out_put:
+       module_put(mtd->owner);
+out_unlock:
+       mutex_unlock(&mtd_table_mutex);
+       return ERR_PTR(err);
 }
 
 void put_mtd_device(struct mtd_info *mtd)
@@ -229,6 +284,8 @@ void put_mtd_device(struct mtd_info *mtd)
 
        mutex_lock(&mtd_table_mutex);
        c = --mtd->usecount;
+       if (mtd->put_device)
+               mtd->put_device(mtd);
        mutex_unlock(&mtd_table_mutex);
        BUG_ON(c < 0);
 
@@ -236,7 +293,7 @@ void put_mtd_device(struct mtd_info *mtd)
 }
 
 /* default_mtd_writev - default mtd writev method for MTD devices that
- *                     dont implement their own
+ *                     don't implement their own
  */
 
 int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
@@ -264,13 +321,14 @@ int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
        return ret;
 }
 
-EXPORT_SYMBOL(add_mtd_device);
-EXPORT_SYMBOL(del_mtd_device);
-EXPORT_SYMBOL(get_mtd_device);
-EXPORT_SYMBOL(put_mtd_device);
-EXPORT_SYMBOL(register_mtd_user);
-EXPORT_SYMBOL(unregister_mtd_user);
-EXPORT_SYMBOL(default_mtd_writev);
+EXPORT_SYMBOL_GPL(add_mtd_device);
+EXPORT_SYMBOL_GPL(del_mtd_device);
+EXPORT_SYMBOL_GPL(get_mtd_device);
+EXPORT_SYMBOL_GPL(get_mtd_device_nm);
+EXPORT_SYMBOL_GPL(put_mtd_device);
+EXPORT_SYMBOL_GPL(register_mtd_user);
+EXPORT_SYMBOL_GPL(unregister_mtd_user);
+EXPORT_SYMBOL_GPL(default_mtd_writev);
 
 #ifdef CONFIG_PROC_FS