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

industrialio-sw-device.c (4162B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * The Industrial I/O core, software IIO devices functions
      4 *
      5 * Copyright (c) 2016 Intel Corporation
      6 */
      7
      8#include <linux/module.h>
      9#include <linux/init.h>
     10#include <linux/kmod.h>
     11#include <linux/list.h>
     12#include <linux/slab.h>
     13
     14#include <linux/iio/sw_device.h>
     15#include <linux/iio/configfs.h>
     16#include <linux/configfs.h>
     17
     18static struct config_group *iio_devices_group;
     19static const struct config_item_type iio_device_type_group_type;
     20
     21static const struct config_item_type iio_devices_group_type = {
     22	.ct_owner = THIS_MODULE,
     23};
     24
     25static LIST_HEAD(iio_device_types_list);
     26static DEFINE_MUTEX(iio_device_types_lock);
     27
     28static
     29struct iio_sw_device_type *__iio_find_sw_device_type(const char *name,
     30						     unsigned len)
     31{
     32	struct iio_sw_device_type *d = NULL, *iter;
     33
     34	list_for_each_entry(iter, &iio_device_types_list, list)
     35		if (!strcmp(iter->name, name)) {
     36			d = iter;
     37			break;
     38		}
     39
     40	return d;
     41}
     42
     43int iio_register_sw_device_type(struct iio_sw_device_type *d)
     44{
     45	struct iio_sw_device_type *iter;
     46	int ret = 0;
     47
     48	mutex_lock(&iio_device_types_lock);
     49	iter = __iio_find_sw_device_type(d->name, strlen(d->name));
     50	if (iter)
     51		ret = -EBUSY;
     52	else
     53		list_add_tail(&d->list, &iio_device_types_list);
     54	mutex_unlock(&iio_device_types_lock);
     55
     56	if (ret)
     57		return ret;
     58
     59	d->group = configfs_register_default_group(iio_devices_group, d->name,
     60						&iio_device_type_group_type);
     61	if (IS_ERR(d->group))
     62		ret = PTR_ERR(d->group);
     63
     64	return ret;
     65}
     66EXPORT_SYMBOL(iio_register_sw_device_type);
     67
     68void iio_unregister_sw_device_type(struct iio_sw_device_type *dt)
     69{
     70	struct iio_sw_device_type *iter;
     71
     72	mutex_lock(&iio_device_types_lock);
     73	iter = __iio_find_sw_device_type(dt->name, strlen(dt->name));
     74	if (iter)
     75		list_del(&dt->list);
     76	mutex_unlock(&iio_device_types_lock);
     77
     78	configfs_unregister_default_group(dt->group);
     79}
     80EXPORT_SYMBOL(iio_unregister_sw_device_type);
     81
     82static
     83struct iio_sw_device_type *iio_get_sw_device_type(const char *name)
     84{
     85	struct iio_sw_device_type *dt;
     86
     87	mutex_lock(&iio_device_types_lock);
     88	dt = __iio_find_sw_device_type(name, strlen(name));
     89	if (dt && !try_module_get(dt->owner))
     90		dt = NULL;
     91	mutex_unlock(&iio_device_types_lock);
     92
     93	return dt;
     94}
     95
     96struct iio_sw_device *iio_sw_device_create(const char *type, const char *name)
     97{
     98	struct iio_sw_device *d;
     99	struct iio_sw_device_type *dt;
    100
    101	dt = iio_get_sw_device_type(type);
    102	if (!dt) {
    103		pr_err("Invalid device type: %s\n", type);
    104		return ERR_PTR(-EINVAL);
    105	}
    106	d = dt->ops->probe(name);
    107	if (IS_ERR(d))
    108		goto out_module_put;
    109
    110	d->device_type = dt;
    111
    112	return d;
    113out_module_put:
    114	module_put(dt->owner);
    115	return d;
    116}
    117EXPORT_SYMBOL(iio_sw_device_create);
    118
    119void iio_sw_device_destroy(struct iio_sw_device *d)
    120{
    121	struct iio_sw_device_type *dt = d->device_type;
    122
    123	dt->ops->remove(d);
    124	module_put(dt->owner);
    125}
    126EXPORT_SYMBOL(iio_sw_device_destroy);
    127
    128static struct config_group *device_make_group(struct config_group *group,
    129					      const char *name)
    130{
    131	struct iio_sw_device *d;
    132
    133	d = iio_sw_device_create(group->cg_item.ci_name, name);
    134	if (IS_ERR(d))
    135		return ERR_CAST(d);
    136
    137	config_item_set_name(&d->group.cg_item, "%s", name);
    138
    139	return &d->group;
    140}
    141
    142static void device_drop_group(struct config_group *group,
    143			      struct config_item *item)
    144{
    145	struct iio_sw_device *d = to_iio_sw_device(item);
    146
    147	iio_sw_device_destroy(d);
    148	config_item_put(item);
    149}
    150
    151static struct configfs_group_operations device_ops = {
    152	.make_group	= &device_make_group,
    153	.drop_item	= &device_drop_group,
    154};
    155
    156static const struct config_item_type iio_device_type_group_type = {
    157	.ct_group_ops = &device_ops,
    158	.ct_owner       = THIS_MODULE,
    159};
    160
    161static int __init iio_sw_device_init(void)
    162{
    163	iio_devices_group =
    164		configfs_register_default_group(&iio_configfs_subsys.su_group,
    165						"devices",
    166						&iio_devices_group_type);
    167	return PTR_ERR_OR_ZERO(iio_devices_group);
    168}
    169module_init(iio_sw_device_init);
    170
    171static void __exit iio_sw_device_exit(void)
    172{
    173	configfs_unregister_default_group(iio_devices_group);
    174}
    175module_exit(iio_sw_device_exit);
    176
    177MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>");
    178MODULE_DESCRIPTION("Industrial I/O software devices support");
    179MODULE_LICENSE("GPL v2");