Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Registration for chip drivers
0004  *
0005  */
0006 
0007 #include <linux/kernel.h>
0008 #include <linux/module.h>
0009 #include <linux/kmod.h>
0010 #include <linux/spinlock.h>
0011 #include <linux/slab.h>
0012 #include <linux/mtd/map.h>
0013 #include <linux/mtd/mtd.h>
0014 
0015 static DEFINE_SPINLOCK(chip_drvs_lock);
0016 static LIST_HEAD(chip_drvs_list);
0017 
0018 void register_mtd_chip_driver(struct mtd_chip_driver *drv)
0019 {
0020     spin_lock(&chip_drvs_lock);
0021     list_add(&drv->list, &chip_drvs_list);
0022     spin_unlock(&chip_drvs_lock);
0023 }
0024 
0025 void unregister_mtd_chip_driver(struct mtd_chip_driver *drv)
0026 {
0027     spin_lock(&chip_drvs_lock);
0028     list_del(&drv->list);
0029     spin_unlock(&chip_drvs_lock);
0030 }
0031 
0032 static struct mtd_chip_driver *get_mtd_chip_driver (const char *name)
0033 {
0034     struct mtd_chip_driver *ret = NULL, *this;
0035 
0036     spin_lock(&chip_drvs_lock);
0037 
0038     list_for_each_entry(this, &chip_drvs_list, list) {
0039         if (!strcmp(this->name, name)) {
0040             ret = this;
0041             break;
0042         }
0043     }
0044     if (ret && !try_module_get(ret->module))
0045         ret = NULL;
0046 
0047     spin_unlock(&chip_drvs_lock);
0048 
0049     return ret;
0050 }
0051 
0052     /* Hide all the horrid details, like some silly person taking
0053        get_module_symbol() away from us, from the caller. */
0054 
0055 struct mtd_info *do_map_probe(const char *name, struct map_info *map)
0056 {
0057     struct mtd_chip_driver *drv;
0058     struct mtd_info *ret;
0059 
0060     drv = get_mtd_chip_driver(name);
0061 
0062     if (!drv && !request_module("%s", name))
0063         drv = get_mtd_chip_driver(name);
0064 
0065     if (!drv)
0066         return NULL;
0067 
0068     ret = drv->probe(map);
0069 
0070     /* We decrease the use count here. It may have been a
0071        probe-only module, which is no longer required from this
0072        point, having given us a handle on (and increased the use
0073        count of) the actual driver code.
0074     */
0075     module_put(drv->module);
0076 
0077     return ret;
0078 }
0079 /*
0080  * Destroy an MTD device which was created for a map device.
0081  * Make sure the MTD device is already unregistered before calling this
0082  */
0083 void map_destroy(struct mtd_info *mtd)
0084 {
0085     struct map_info *map = mtd->priv;
0086 
0087     if (map->fldrv->destroy)
0088         map->fldrv->destroy(mtd);
0089 
0090     module_put(map->fldrv->module);
0091 
0092     kfree(mtd);
0093 }
0094 
0095 EXPORT_SYMBOL(register_mtd_chip_driver);
0096 EXPORT_SYMBOL(unregister_mtd_chip_driver);
0097 EXPORT_SYMBOL(do_map_probe);
0098 EXPORT_SYMBOL(map_destroy);
0099 
0100 MODULE_LICENSE("GPL");
0101 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
0102 MODULE_DESCRIPTION("Core routines for registering and invoking MTD chip drivers");