#include #include #include #include #include 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); d=7a7b5df84b6b4e5d599c7289526eed96541a0654'>diff
diff options
context:
space:
mode:
authorJohan Hovold <johan@kernel.org>2017-01-30 11:26:38 +0100
committerJiri Kosina <jkosina@suse.cz>2017-01-31 12:59:32 +0100
commit7a7b5df84b6b4e5d599c7289526eed96541a0654 (patch)
treecf7514c7ddf4410fe37ca9099a2785e1cf08fa7d /tools/testing/selftests/lib
parent877a021e08ccb6434718c0cc781fdf943c884cc0 (diff)
HID: cp2112: fix sleep-while-atomic
A recent commit fixing DMA-buffers on stack added a shared transfer buffer protected by a spinlock. This is broken as the USB HID request callbacks can sleep. Fix this up by replacing the spinlock with a mutex. Fixes: 1ffb3c40ffb5 ("HID: cp2112: make transfer buffers DMA capable") Cc: stable <stable@vger.kernel.org> # 4.9 Signed-off-by: Johan Hovold <johan@kernel.org> Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'tools/testing/selftests/lib')