chipreg.c (2328B)
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 15static DEFINE_SPINLOCK(chip_drvs_lock); 16static LIST_HEAD(chip_drvs_list); 17 18void 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 25void 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 32static 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 55struct 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 */ 83void 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 95EXPORT_SYMBOL(register_mtd_chip_driver); 96EXPORT_SYMBOL(unregister_mtd_chip_driver); 97EXPORT_SYMBOL(do_map_probe); 98EXPORT_SYMBOL(map_destroy); 99 100MODULE_LICENSE("GPL"); 101MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); 102MODULE_DESCRIPTION("Core routines for registering and invoking MTD chip drivers");