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 33 struct iio_loop_info { 34 struct iio_sw_trigger swt; 35 struct task_struct *task; 36 }; 37 38 static const struct config_item_type iio_loop_type = { 39 .ct_owner = THIS_MODULE, 40 }; 41 42 static 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 55 static 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 74 static const struct iio_trigger_ops iio_loop_trigger_ops = { 75 .set_trigger_state = iio_loop_trigger_set_state, 76 }; 77 78 static 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("%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 104 err_free_trigger: 105 iio_trigger_free(trig_info->swt.trigger); 106 err_free_trig_info: 107 kfree(trig_info); 108 109 return ERR_PTR(ret); 110 } 111 112 static 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 125 static const struct iio_sw_trigger_ops iio_trig_loop_ops = { 126 .probe = iio_trig_loop_probe, 127 .remove = iio_trig_loop_remove, 128 }; 129 130 static struct iio_sw_trigger_type iio_trig_loop = { 131 .name = "loop", 132 .owner = THIS_MODULE, 133 .ops = &iio_trig_loop_ops, 134 }; 135 136 module_iio_sw_trigger_driver(iio_trig_loop); 137 138 MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); 139 MODULE_DESCRIPTION("Loop based trigger for the iio subsystem"); 140 MODULE_LICENSE("GPL v2"); 141 MODULE_ALIAS("platform:iio-trig-loop"); 142