Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright 2016 Jonathan Cameron <jic23@kernel.org>
0004  *
0005  * Based on a mashup of the hrtimer trigger and continuous sampling proposal of
0006  * Gregor Boirie <gregor.boirie@parrot.com>
0007  *
0008  * Note this is still rather experimental and may eat babies.
0009  *
0010  * Todo
0011  * * Protect against connection of devices that 'need' the top half
0012  *   handler.
0013  * * Work out how to run top half handlers in this context if it is
0014  *   safe to do so (timestamp grabbing for example)
0015  *
0016  * Tested against a max1363. Used about 33% cpu for the thread and 20%
0017  * for generic_buffer piping to /dev/null. Watermark set at 64 on a 128
0018  * element kfifo buffer.
0019  */
0020 
0021 #include <linux/kernel.h>
0022 #include <linux/module.h>
0023 #include <linux/platform_device.h>
0024 #include <linux/slab.h>
0025 #include <linux/irq_work.h>
0026 #include <linux/kthread.h>
0027 #include <linux/freezer.h>
0028 
0029 #include <linux/iio/iio.h>
0030 #include <linux/iio/trigger.h>
0031 #include <linux/iio/sw_trigger.h>
0032 
0033 struct iio_loop_info {
0034     struct iio_sw_trigger swt;
0035     struct task_struct *task;
0036 };
0037 
0038 static const struct config_item_type iio_loop_type = {
0039     .ct_owner = THIS_MODULE,
0040 };
0041 
0042 static int iio_loop_thread(void *data)
0043 {
0044     struct iio_trigger *trig = data;
0045 
0046     set_freezable();
0047 
0048     do {
0049         iio_trigger_poll_chained(trig);
0050     } while (likely(!kthread_freezable_should_stop(NULL)));
0051 
0052     return 0;
0053 }
0054 
0055 static int iio_loop_trigger_set_state(struct iio_trigger *trig, bool state)
0056 {
0057     struct iio_loop_info *loop_trig = iio_trigger_get_drvdata(trig);
0058 
0059     if (state) {
0060         loop_trig->task = kthread_run(iio_loop_thread,
0061                           trig, trig->name);
0062         if (IS_ERR(loop_trig->task)) {
0063             dev_err(&trig->dev,
0064                 "failed to create trigger loop thread\n");
0065             return PTR_ERR(loop_trig->task);
0066         }
0067     } else {
0068         kthread_stop(loop_trig->task);
0069     }
0070 
0071     return 0;
0072 }
0073 
0074 static const struct iio_trigger_ops iio_loop_trigger_ops = {
0075     .set_trigger_state = iio_loop_trigger_set_state,
0076 };
0077 
0078 static struct iio_sw_trigger *iio_trig_loop_probe(const char *name)
0079 {
0080     struct iio_loop_info *trig_info;
0081     int ret;
0082 
0083     trig_info = kzalloc(sizeof(*trig_info), GFP_KERNEL);
0084     if (!trig_info)
0085         return ERR_PTR(-ENOMEM);
0086 
0087     trig_info->swt.trigger = iio_trigger_alloc(NULL, "%s", name);
0088     if (!trig_info->swt.trigger) {
0089         ret = -ENOMEM;
0090         goto err_free_trig_info;
0091     }
0092 
0093     iio_trigger_set_drvdata(trig_info->swt.trigger, trig_info);
0094     trig_info->swt.trigger->ops = &iio_loop_trigger_ops;
0095 
0096     ret = iio_trigger_register(trig_info->swt.trigger);
0097     if (ret)
0098         goto err_free_trigger;
0099 
0100     iio_swt_group_init_type_name(&trig_info->swt, name, &iio_loop_type);
0101 
0102     return &trig_info->swt;
0103 
0104 err_free_trigger:
0105     iio_trigger_free(trig_info->swt.trigger);
0106 err_free_trig_info:
0107     kfree(trig_info);
0108 
0109     return ERR_PTR(ret);
0110 }
0111 
0112 static int iio_trig_loop_remove(struct iio_sw_trigger *swt)
0113 {
0114     struct iio_loop_info *trig_info;
0115 
0116     trig_info = iio_trigger_get_drvdata(swt->trigger);
0117 
0118     iio_trigger_unregister(swt->trigger);
0119     iio_trigger_free(swt->trigger);
0120     kfree(trig_info);
0121 
0122     return 0;
0123 }
0124 
0125 static const struct iio_sw_trigger_ops iio_trig_loop_ops = {
0126     .probe = iio_trig_loop_probe,
0127     .remove = iio_trig_loop_remove,
0128 };
0129 
0130 static struct iio_sw_trigger_type iio_trig_loop = {
0131     .name = "loop",
0132     .owner = THIS_MODULE,
0133     .ops = &iio_trig_loop_ops,
0134 };
0135 
0136 module_iio_sw_trigger_driver(iio_trig_loop);
0137 
0138 MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
0139 MODULE_DESCRIPTION("Loop based trigger for the iio subsystem");
0140 MODULE_LICENSE("GPL v2");
0141 MODULE_ALIAS("platform:iio-trig-loop");