1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Registration for chip drivers 4 * 5 */ 6 7 #include <linux/kernel.h> 8 #include <linux/module.h> 9 #include <linux/kmod.h> 10 #include <linux/spinlock.h> 11 #include <linux/slab.h> 12 #include <linux/mtd/map.h> 13 #include <linux/mtd/mtd.h> 14 15 static DEFINE_SPINLOCK(chip_drvs_lock); 16 static LIST_HEAD(chip_drvs_list); 17 18 void register_mtd_chip_driver(struct mtd_chip_driver *drv) 19 { 20 spin_lock(&chip_drvs_lock); 21 list_add(&drv->list, &chip_drvs_list); 22 spin_unlock(&chip_drvs_lock); 23 } 24 25 void unregister_mtd_chip_driver(struct mtd_chip_driver *drv) 26 { 27 spin_lock(&chip_drvs_lock); 28 list_del(&drv->list); 29 spin_unlock(&chip_drvs_lock); 30 } 31 32 static struct mtd_chip_driver *get_mtd_chip_driver (const char *name) 33 { 34 struct mtd_chip_driver *ret = NULL, *this; 35 36 spin_lock(&chip_drvs_lock); 37 38 list_for_each_entry(this, &chip_drvs_list, list) { 39 if (!strcmp(this->name, name)) { 40 ret = this; 41 break; 42 } 43 } 44 if (ret && !try_module_get(ret->module)) 45 ret = NULL; 46 47 spin_unlock(&chip_drvs_lock); 48 49 return ret; 50 } 51 52 /* Hide all the horrid details, like some silly person taking 53 get_module_symbol() away from us, from the caller. */ 54 55 struct mtd_info *do_map_probe(const char *name, struct map_info *map) 56 { 57 struct mtd_chip_driver *drv; 58 struct mtd_info *ret; 59 60 drv = get_mtd_chip_driver(name); 61 62 if (!drv && !request_module("%s", name)) 63 drv = get_mtd_chip_driver(name); 64 65 if (!drv) 66 return NULL; 67 68 ret = drv->probe(map); 69 70 /* We decrease the use count here. It may have been a 71 probe-only module, which is no longer required from this 72 point, having given us a handle on (and increased the use 73 count of) the actual driver code. 74 */ 75 module_put(drv->module); 76 77 return ret; 78 } 79 /* 80 * Destroy an MTD device which was created for a map device. 81 * Make sure the MTD device is already unregistered before calling this 82 */ 83 void map_destroy(struct mtd_info *mtd) 84 { 85 struct map_info *map = mtd->priv; 86 87 if (map->fldrv->destroy) 88 map->fldrv->destroy(mtd); 89 90 module_put(map->fldrv->module); 91 92 kfree(mtd); 93 } 94 95 EXPORT_SYMBOL(register_mtd_chip_driver); 96 EXPORT_SYMBOL(unregister_mtd_chip_driver); 97 EXPORT_SYMBOL(do_map_probe); 98 EXPORT_SYMBOL(map_destroy); 99 100 MODULE_LICENSE("GPL"); 101 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); 102 MODULE_DESCRIPTION("Core routines for registering and invoking MTD chip drivers"); 103