Re: [RFC PATCH V2] iio:trigger: Experimental kthread tight loop trigger (thread only)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux