Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband
[powerpc.git] / drivers / mtd / mtdcore.c
index 06ec9f8..7070110 100644 (file)
@@ -193,14 +193,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);
 
@@ -214,14 +214,27 @@ 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);
 }
 
 /**
@@ -235,8 +248,8 @@ struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
 
 struct mtd_info *get_mtd_device_nm(const char *name)
 {
-       int i;
-       struct mtd_info *mtd = ERR_PTR(-ENODEV);
+       int i, err = -ENODEV;
+       struct mtd_info *mtd = NULL;
 
        mutex_lock(&mtd_table_mutex);
 
@@ -247,17 +260,27 @@ struct mtd_info *get_mtd_device_nm(const char *name)
                }
        }
 
-       if (i == MAX_MTD_DEVICES)
+       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 mtd;
+       return ERR_PTR(err);
 }
 
 void put_mtd_device(struct mtd_info *mtd)
@@ -266,6 +289,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);
 
@@ -273,7 +298,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,
@@ -301,14 +326,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(get_mtd_device_nm);
-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