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

iio-trig-loop.c (3421B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright 2016 Jonathan Cameron <jic23@kernel.org>
      4 *
      5 * Based on a mashup of the hrtimer trigger and continuous sampling proposal of
      6 * Gregor Boirie <gregor.boirie@parrot.com>
      7 *
      8 * Note this is still rather experimental and may eat babies.
      9 *
     10 * Todo
     11 * * Protect against connection of devices that 'need' the top half
     12 *   handler.
     13 * * Work out how to run top half handlers in this context if it is
     14 *   safe to do so (timestamp grabbing for example)
     15 *
     16 * Tested against a max1363. Used about 33% cpu for the thread and 20%
     17 * for generic_buffer piping to /dev/null. Watermark set at 64 on a 128
     18 * element kfifo buffer.
     19 */
     20
     21#include <linux/kernel.h>
     22#include <linux/module.h>
     23#include <linux/platform_device.h>
     24#include <linux/slab.h>
     25#include <linux/irq_work.h>
     26#include <linux/kthread.h>
     27#include <linux/freezer.h>
     28
     29#include <linux/iio/iio.h>
     30#include <linux/iio/trigger.h>
     31#include <linux/iio/sw_trigger.h>
     32
     33struct iio_loop_info {
     34	struct iio_sw_trigger swt;
     35	struct task_struct *task;
     36};
     37
     38static const struct config_item_type iio_loop_type = {
     39	.ct_owner = THIS_MODULE,
     40};
     41
     42static int iio_loop_thread(void *data)
     43{
     44	struct iio_trigger *trig = data;
     45
     46	set_freezable();
     47
     48	do {
     49		iio_trigger_poll_chained(trig);
     50	} while (likely(!kthread_freezable_should_stop(NULL)));
     51
     52	return 0;
     53}
     54
     55static int iio_loop_trigger_set_state(struct iio_trigger *trig, bool state)
     56{
     57	struct iio_loop_info *loop_trig = iio_trigger_get_drvdata(trig);
     58
     59	if (state) {
     60		loop_trig->task = kthread_run(iio_loop_thread,
     61					      trig, trig->name);
     62		if (IS_ERR(loop_trig->task)) {
     63			dev_err(&trig->dev,
     64				"failed to create trigger loop thread\n");
     65			return PTR_ERR(loop_trig->task);
     66		}
     67	} else {
     68		kthread_stop(loop_trig->task);
     69	}
     70
     71	return 0;
     72}
     73
     74static const struct iio_trigger_ops iio_loop_trigger_ops = {
     75	.set_trigger_state = iio_loop_trigger_set_state,
     76};
     77
     78static struct iio_sw_trigger *iio_trig_loop_probe(const char *name)
     79{
     80	struct iio_loop_info *trig_info;
     81	int ret;
     82
     83	trig_info = kzalloc(sizeof(*trig_info), GFP_KERNEL);
     84	if (!trig_info)
     85		return ERR_PTR(-ENOMEM);
     86
     87	trig_info->swt.trigger = iio_trigger_alloc(NULL, "%s", name);
     88	if (!trig_info->swt.trigger) {
     89		ret = -ENOMEM;
     90		goto err_free_trig_info;
     91	}
     92
     93	iio_trigger_set_drvdata(trig_info->swt.trigger, trig_info);
     94	trig_info->swt.trigger->ops = &iio_loop_trigger_ops;
     95
     96	ret = iio_trigger_register(trig_info->swt.trigger);
     97	if (ret)
     98		goto err_free_trigger;
     99
    100	iio_swt_group_init_type_name(&trig_info->swt, name, &iio_loop_type);
    101
    102	return &trig_info->swt;
    103
    104err_free_trigger:
    105	iio_trigger_free(trig_info->swt.trigger);
    106err_free_trig_info:
    107	kfree(trig_info);
    108
    109	return ERR_PTR(ret);
    110}
    111
    112static int iio_trig_loop_remove(struct iio_sw_trigger *swt)
    113{
    114	struct iio_loop_info *trig_info;
    115
    116	trig_info = iio_trigger_get_drvdata(swt->trigger);
    117
    118	iio_trigger_unregister(swt->trigger);
    119	iio_trigger_free(swt->trigger);
    120	kfree(trig_info);
    121
    122	return 0;
    123}
    124
    125static const struct iio_sw_trigger_ops iio_trig_loop_ops = {
    126	.probe = iio_trig_loop_probe,
    127	.remove = iio_trig_loop_remove,
    128};
    129
    130static struct iio_sw_trigger_type iio_trig_loop = {
    131	.name = "loop",
    132	.owner = THIS_MODULE,
    133	.ops = &iio_trig_loop_ops,
    134};
    135
    136module_iio_sw_trigger_driver(iio_trig_loop);
    137
    138MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
    139MODULE_DESCRIPTION("Loop based trigger for the iio subsystem");
    140MODULE_LICENSE("GPL v2");
    141MODULE_ALIAS("platform:iio-trig-loop");