cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

functions.c (2307B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include <linux/kernel.h>
      3#include <linux/slab.h>
      4#include <linux/module.h>
      5#include <linux/err.h>
      6
      7#include <linux/usb/composite.h>
      8
      9static LIST_HEAD(func_list);
     10static DEFINE_MUTEX(func_lock);
     11
     12static struct usb_function_instance *try_get_usb_function_instance(const char *name)
     13{
     14	struct usb_function_driver *fd;
     15	struct usb_function_instance *fi;
     16
     17	fi = ERR_PTR(-ENOENT);
     18	mutex_lock(&func_lock);
     19	list_for_each_entry(fd, &func_list, list) {
     20
     21		if (strcmp(name, fd->name))
     22			continue;
     23
     24		if (!try_module_get(fd->mod)) {
     25			fi = ERR_PTR(-EBUSY);
     26			break;
     27		}
     28		fi = fd->alloc_inst();
     29		if (IS_ERR(fi))
     30			module_put(fd->mod);
     31		else
     32			fi->fd = fd;
     33		break;
     34	}
     35	mutex_unlock(&func_lock);
     36	return fi;
     37}
     38
     39struct usb_function_instance *usb_get_function_instance(const char *name)
     40{
     41	struct usb_function_instance *fi;
     42	int ret;
     43
     44	fi = try_get_usb_function_instance(name);
     45	if (!IS_ERR(fi))
     46		return fi;
     47	ret = PTR_ERR(fi);
     48	if (ret != -ENOENT)
     49		return fi;
     50	ret = request_module("usbfunc:%s", name);
     51	if (ret < 0)
     52		return ERR_PTR(ret);
     53	return try_get_usb_function_instance(name);
     54}
     55EXPORT_SYMBOL_GPL(usb_get_function_instance);
     56
     57struct usb_function *usb_get_function(struct usb_function_instance *fi)
     58{
     59	struct usb_function *f;
     60
     61	f = fi->fd->alloc_func(fi);
     62	if (IS_ERR(f))
     63		return f;
     64	f->fi = fi;
     65	return f;
     66}
     67EXPORT_SYMBOL_GPL(usb_get_function);
     68
     69void usb_put_function_instance(struct usb_function_instance *fi)
     70{
     71	struct module *mod;
     72
     73	if (!fi)
     74		return;
     75
     76	mod = fi->fd->mod;
     77	fi->free_func_inst(fi);
     78	module_put(mod);
     79}
     80EXPORT_SYMBOL_GPL(usb_put_function_instance);
     81
     82void usb_put_function(struct usb_function *f)
     83{
     84	if (!f)
     85		return;
     86
     87	f->free_func(f);
     88}
     89EXPORT_SYMBOL_GPL(usb_put_function);
     90
     91int usb_function_register(struct usb_function_driver *newf)
     92{
     93	struct usb_function_driver *fd;
     94	int ret;
     95
     96	ret = -EEXIST;
     97
     98	mutex_lock(&func_lock);
     99	list_for_each_entry(fd, &func_list, list) {
    100		if (!strcmp(fd->name, newf->name))
    101			goto out;
    102	}
    103	ret = 0;
    104	list_add_tail(&newf->list, &func_list);
    105out:
    106	mutex_unlock(&func_lock);
    107	return ret;
    108}
    109EXPORT_SYMBOL_GPL(usb_function_register);
    110
    111void usb_function_unregister(struct usb_function_driver *fd)
    112{
    113	mutex_lock(&func_lock);
    114	list_del(&fd->list);
    115	mutex_unlock(&func_lock);
    116}
    117EXPORT_SYMBOL_GPL(usb_function_unregister);