#include <linux/kernel.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/err.h> #include <linux/usb/composite.h> static LIST_HEAD(func_list); static DEFINE_MUTEX(func_lock); static struct usb_function_instance *try_get_usb_function_instance(const char *name) { struct usb_function_driver *fd; struct usb_function_instance *fi; fi = ERR_PTR(-ENOENT); mutex_lock(&func_lock); list_for_each_entry(fd, &func_list, list) { if (strcmp(name, fd->name)) continue; if (!try_module_get(fd->mod)) { fi = ERR_PTR(-EBUSY); break; } fi = fd->alloc_inst(); if (IS_ERR(fi)) module_put(fd->mod); else fi->fd = fd; break; } mutex_unlock(&func_lock); return fi; } struct usb_function_instance *usb_get_function_instance(const char *name) { struct usb_function_instance *fi; int ret; fi = try_get_usb_function_instance(name); if (!IS_ERR(fi)) return fi; ret = PTR_ERR(fi); if (ret != -ENOENT) return fi; ret = request_module("usbfunc:%s", name); if (ret < 0) return ERR_PTR(ret); return try_get_usb_function_instance(name); } EXPORT_SYMBOL_GPL(usb_get_function_instance); struct usb_function *usb_get_function(struct usb_function_instance *fi) { struct usb_function *f; f = fi->fd->alloc_func(fi); if (IS_ERR(f)) return f; f->fi = fi; return f; } EXPORT_SYMBOL_GPL(usb_get_function); void usb_put_function_instance(struct usb_function_instance *fi) { struct module *mod; if (!fi) return; mod = fi->fd->mod; fi->free_func_inst(fi); module_put(mod); } EXPORT_SYMBOL_GPL(usb_put_function_instance); void usb_put_function(struct usb_function *f) { if (!f) return; f->free_func(f); } EXPORT_SYMBOL_GPL(usb_put_function); int usb_function_register(struct usb_function_driver *newf) { struct usb_function_driver *fd; int ret; ret = -EEXIST; mutex_lock(&func_lock); list_for_each_entry(fd, &func_list, list) { if (!strcmp(fd->name, newf->name)) goto out; } ret = 0; list_add_tail(&newf->list, &func_list); out: mutex_unlock(&func_lock); return ret; } EXPORT_SYMBOL_GPL(usb_function_register); void usb_function_unregister(struct usb_function_driver *fd) { mutex_lock(&func_lock); list_del(&fd->list); mutex_unlock(&func_lock); } EXPORT_SYMBOL_GPL(usb_function_unregister); -next.git/log/sound/soc/atmel'> <input type='hidden' name='h' value='nds-private-remove'/><input type='hidden' name='id' value='5c178d81b69f08ca3195427a6ea9a46d9af23127'/><select name='qt'> <option value='grep'>log msg</option> <option value='author'>author</option> <option value='committer'>committer</option> <option value='range'>range</option> </select> <input class='txt' type='search' size='10' name='q' value=''/> <input type='submit' value='search'/> </form> </td></tr></table> <div class='path'>path: <a href='/cgit.cgi/linux/net-next.git/log/?h=nds-private-remove&id=5c178d81b69f08ca3195427a6ea9a46d9af23127'>root</a>/<a href='/cgit.cgi/linux/net-next.git/log/sound?h=nds-private-remove&id=5c178d81b69f08ca3195427a6ea9a46d9af23127'>sound</a>/<a href='/cgit.cgi/linux/net-next.git/log/sound/soc?h=nds-private-remove&id=5c178d81b69f08ca3195427a6ea9a46d9af23127'>soc</a>/<a href='/cgit.cgi/linux/net-next.git/log/sound/soc/atmel?h=nds-private-remove&id=5c178d81b69f08ca3195427a6ea9a46d9af23127'>atmel</a></div><div class='content'><table class='list nowrap'><tr class='nohover'><th class='left'>Age</th><th class='left'>Commit message (<a href='/cgit.cgi/linux/net-next.git/log/sound/soc/atmel?h=nds-private-remove&id=5c178d81b69f08ca3195427a6ea9a46d9af23127&showmsg=1'>Expand</a>)</th><th class='left'>Author</th><th class='left'>Files</th><th class='left'>Lines</th></tr>