On 22/05/16 22:30, Jonathan Cameron wrote: > On 06/03/16 20:02, Jonathan Cameron wrote: >> This patch is in response to that of >> Gregor Boirie <gregor.boirie@xxxxxxxxxx> >> who proposed using a tight kthread within a device driver (be it with the >> support factored out into a helper library) in order to basically spin as >> fast as possible. >> >> It is meant as a talking point rather than a formal proposal of the code >> (though we are heading towards that I think). >> Also gives people some working code to mess around with. >> >> I proposed that this could be done with a trigger with a few constraints >> and this is the proof (be it ugly) of that. >> >> There are some constraints though, some of which we would want to relax >> if this were to move forward. >> >> * Will only run the thread part of the registered pollfunc. This is to >> avoid the overhead of jumping in and out of interrupt context. Is the >> overhead significant? Not certain but feels like it should be! >> >> * This limitation precludes any device that 'must' do some work in >> interrupt context. However, that is true of few if any drivers and >> I suspect that any that do will be restricted to using triggers they >> provide themselves. Usually we have a top half mainly to grab a >> timestamp as soon after the dataready type signal as possible. >> >> Signed-off-by: Jonathan Cameron <jic23@xxxxxxxxxx> > Any comments on this anyone? > > Whilst we still haven't dealt with the question of neatly handling > the missing top halves (where relevant) I think it might be worth taking this > soonish as we have genuine use cases... > > Would be easy enough to modify the pollfunc generic timestamp code to play > a few games to ensure it grabs a software timestamp in the threaded handler if needed > (inserting an appropriate access function into all users).. > say > iio_pollfunc_get_ts_best_effort() that uses the top half stored one if available > (also setting a 'new timestamp' available if from a hardware source) or if not > grabs one at call time in the threaded handler. > > > Jonathan This needs a review from someone!.. Daniel, it uses your configfs stuff so could you take a look if no one else does? Thanks, Jonathan >> --- >> drivers/iio/trigger/Kconfig | 12 +++ >> drivers/iio/trigger/Makefile | 1 + >> drivers/iio/trigger/iio-trig-loop.c | 143 ++++++++++++++++++++++++++++++++++++ >> 3 files changed, 156 insertions(+) >> >> diff --git a/drivers/iio/trigger/Kconfig b/drivers/iio/trigger/Kconfig >> index 519e6772f6f5..9feabe95eeda 100644 >> --- a/drivers/iio/trigger/Kconfig >> +++ b/drivers/iio/trigger/Kconfig >> @@ -24,6 +24,18 @@ config IIO_INTERRUPT_TRIGGER >> To compile this driver as a module, choose M here: the >> module will be called iio-trig-interrupt. >> >> +config IIO_TIGHTLOOP_TRIGGER >> + tristate "A kthread based hammering loop trigger" >> + depends on IIO_SW_TRIGGER >> + help >> + An experimental trigger, used to allow sensors to be sampled as fast >> + as possible under the limitations of whatever else is going on. >> + Uses a tight loop in a kthread. Will only work with lower half only >> + trigger consumers. >> + >> + To compile this driver as a module, choose M here: the >> + module will be called iio-trig-loop. >> + >> config IIO_SYSFS_TRIGGER >> tristate "SYSFS trigger" >> depends on SYSFS >> diff --git a/drivers/iio/trigger/Makefile b/drivers/iio/trigger/Makefile >> index fe06eb564367..aab4dc23303d 100644 >> --- a/drivers/iio/trigger/Makefile >> +++ b/drivers/iio/trigger/Makefile >> @@ -7,3 +7,4 @@ >> obj-$(CONFIG_IIO_HRTIMER_TRIGGER) += iio-trig-hrtimer.o >> obj-$(CONFIG_IIO_INTERRUPT_TRIGGER) += iio-trig-interrupt.o >> obj-$(CONFIG_IIO_SYSFS_TRIGGER) += iio-trig-sysfs.o >> +obj-$(CONFIG_IIO_TIGHTLOOP_TRIGGER) += iio-trig-loop.o >> diff --git a/drivers/iio/trigger/iio-trig-loop.c b/drivers/iio/trigger/iio-trig-loop.c >> new file mode 100644 >> index 000000000000..dc6be28f96fe >> --- /dev/null >> +++ b/drivers/iio/trigger/iio-trig-loop.c >> @@ -0,0 +1,143 @@ >> +/* >> + * Copyright 2016 Jonathan Cameron <jic23@xxxxxxxxxx> >> + * >> + * Licensed under the GPL-2. >> + * >> + * Based on a mashup of the hrtimer trigger and continuous sampling proposal of >> + * Gregor Boirie <gregor.boirie@xxxxxxxxxx> >> + * >> + * Note this is still rather experimental and may eat babies. >> + * >> + * Todo >> + * * Protect against connection of devices that 'need' the top half >> + * handler. >> + * * Work out how to run top half handlers in this context if it is >> + * safe to do so (timestamp grabbing for example) >> + * >> + * Tested against a max1363. Used about 33% cpu for the thread and 20% >> + * for generic_buffer piping to /dev/null. Watermark set at 64 on a 128 >> + * element kfifo buffer. >> + */ >> + >> +#include <linux/kernel.h> >> +#include <linux/module.h> >> +#include <linux/platform_device.h> >> +#include <linux/slab.h> >> +#include <linux/irq_work.h> >> +#include <linux/kthread.h> >> +#include <linux/freezer.h> >> + >> +#include <linux/iio/iio.h> >> +#include <linux/iio/trigger.h> >> +#include <linux/iio/sw_trigger.h> >> + >> +struct iio_loop_info { >> + struct iio_sw_trigger swt; >> + struct task_struct *task; >> +}; >> + >> +static struct config_item_type iio_loop_type = { >> + .ct_owner = THIS_MODULE, >> +}; >> + >> +static int iio_loop_thread(void *data) >> +{ >> + struct iio_trigger *trig = data; >> + >> + set_freezable(); >> + >> + do { >> + iio_trigger_poll_chained(trig); >> + } while (likely(!kthread_freezable_should_stop(NULL))); >> + >> + return 0; >> +} >> + >> +static int iio_loop_trigger_set_state(struct iio_trigger *trig, bool state) >> +{ >> + struct iio_loop_info *loop_trig = iio_trigger_get_drvdata(trig); >> + >> + if (state) { >> + loop_trig->task = kthread_run(iio_loop_thread, >> + trig, trig->name); >> + if (unlikely(IS_ERR(loop_trig->task))) { >> + dev_err(&trig->dev, >> + "failed to create trigger loop thread\n"); >> + return PTR_ERR(loop_trig->task); >> + } >> + } else { >> + kthread_stop(loop_trig->task); >> + } >> + >> + return 0; >> +} >> + >> +static const struct iio_trigger_ops iio_loop_trigger_ops = { >> + .set_trigger_state = iio_loop_trigger_set_state, >> + .owner = THIS_MODULE, >> +}; >> + >> +static struct iio_sw_trigger *iio_trig_loop_probe(const char *name) >> +{ >> + struct iio_loop_info *trig_info; >> + int ret; >> + >> + trig_info = kzalloc(sizeof(*trig_info), GFP_KERNEL); >> + if (!trig_info) >> + return ERR_PTR(-ENOMEM); >> + >> + trig_info->swt.trigger = iio_trigger_alloc("%s", name); >> + if (!trig_info->swt.trigger) { >> + ret = -ENOMEM; >> + goto err_free_trig_info; >> + } >> + >> + iio_trigger_set_drvdata(trig_info->swt.trigger, trig_info); >> + trig_info->swt.trigger->ops = &iio_loop_trigger_ops; >> + >> + ret = iio_trigger_register(trig_info->swt.trigger); >> + if (ret) >> + goto err_free_trigger; >> + >> + iio_swt_group_init_type_name(&trig_info->swt, name, &iio_loop_type); >> + >> + return &trig_info->swt; >> + >> +err_free_trigger: >> + iio_trigger_free(trig_info->swt.trigger); >> +err_free_trig_info: >> + kfree(trig_info); >> + >> + return ERR_PTR(ret); >> +} >> + >> +static int iio_trig_loop_remove(struct iio_sw_trigger *swt) >> +{ >> + struct iio_loop_info *trig_info; >> + >> + trig_info = iio_trigger_get_drvdata(swt->trigger); >> + >> + iio_trigger_unregister(swt->trigger); >> + iio_trigger_free(swt->trigger); >> + kfree(trig_info); >> + >> + return 0; >> +} >> + >> +static const struct iio_sw_trigger_ops iio_trig_loop_ops = { >> + .probe = iio_trig_loop_probe, >> + .remove = iio_trig_loop_remove, >> +}; >> + >> +static struct iio_sw_trigger_type iio_trig_loop = { >> + .name = "loop", >> + .owner = THIS_MODULE, >> + .ops = &iio_trig_loop_ops, >> +}; >> + >> +module_iio_sw_trigger_driver(iio_trig_loop); >> + >> +MODULE_AUTHOR("Jonathan Cameron <jic23@xxxxxxxxxx>"); >> +MODULE_DESCRIPTION("Loop based trigger for the iio subsystem"); >> +MODULE_LICENSE("GPL v2"); >> +MODULE_ALIAS("platform:iio-trig-loop"); >> > > -- > To unsubscribe from this list: send the line "unsubscribe linux-iio" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html > -- To unsubscribe from this list: send the line "unsubscribe linux-iio" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html