On Sat, Mar 28, 2015 at 1:50 PM, Jonathan Cameron <ji...@kernel.org> wrote:
> On 27/03/15 17:17, Lars-Peter Clausen wrote:
>> On 03/25/2015 06:00 PM, Daniel Baluta wrote:
>>> This creates an IIO configfs subsystem named "iio", which has one default
>>> group named "triggers". This allows us to easily create/destroy software
>>> triggers. One must create a driver which implements iio_configfs_trigger.h
>>> interface and then add its trigger type to IIO configfs core.
>>>
>>> See Documentation/iio/iio_configfs.txt for more details on how configfs
>>> support for IIO works.
>>>
>>> Signed-off-by: Daniel Baluta <daniel.bal...@intel.com>
>>
>> Very good stuff, thanks.
>>
>> [...]
>>> diff --git a/drivers/iio/industrialio-configfs.c 
>>> b/drivers/iio/industrialio-configfs.c
>>> new file mode 100644
>>> index 0000000..4d2133a
>>> --- /dev/null
>>> +++ b/drivers/iio/industrialio-configfs.c
>>> @@ -0,0 +1,297 @@
>>> +/*
>>> + * Industrial I/O configfs bits
>>> + *
>>> + * Copyright (c) 2015 Intel Corporation
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify it
>>> + * under the terms of the GNU General Public License version 2 as 
>>> published by
>>> + * the Free Software Foundation.
>>> + */
>>> +
>>> +#include <linux/configfs.h>
>>> +#include <linux/module.h>
>>> +#include <linux/slab.h>
>>> +
>>> +#include <linux/iio/iio_configfs_trigger.h>
>>> +
>>> +static const char *trigger_types[] =
>>> +{
>>> +    "none",
>>> +};
>>
>> This doesn't necessarily need to be in the initial implementation, but it 
>> would be good instead of having a global registry inside the core module to 
>> have a set of functions that allow to register a configfs trigger. These 
>> functions can be called from the module that implements the trigger in the 
>> init and exit section. A helper macro similar to module_platform_driver that 
>> auto-generates those section would be helpful.
>>
>> Cause right now we do have the dependencies wrong. The core module has a 
>> symbol dependency on the trigger modules implementing the trigger. That 
>> means you need to load the trigger module before the core module and also 
>> means that if at least one trigger is build as a module the core also needs 
>> to be built as a module.
>>
>> E.g. lets say there are triggerA, triggerB and triggerC. All build as a 
>> module. If you want to use any of them you still have to load all of them 
>> since the core module has a dependency on all of them.

Good point. I think this is the correct solution. I will add this approach
in v2.

>>
>>> +
>>> +struct iio_configfs_ops iio_none_ops = {
>>> +    .get_freq    = iio_none_get_freq,
>>> +    .set_freq    = iio_none_set_freq,
>>> +    .probe        = iio_none_probe,
>>> +    .remove        = iio_none_remove,
>>> +};
>>> +
>>> +struct iio_trigger_item {
>>> +    struct config_item item;
>>> +    struct iio_configfs_trigger_info *trigger_info;
>>> +};
>>> +
>>> +static
>>> +inline struct iio_trigger_item *to_iio_trigger_item(struct config_item 
>>> *item)
>>> +{
>>> +    if (!item)
>>> +        return NULL;
>>> +    return container_of(item, struct iio_trigger_item, item);
>>> +}
>>> +
>>> +static unsigned int iio_trigger_get_type(const char *type_str)
>>> +{
>>> +    int i;
>>> +
>>> +    for (i = 0; i < ARRAY_SIZE(trigger_types); i++) {
>>> +        if (!strncmp(trigger_types[i], type_str,
>>> +                strlen(trigger_types[i])))
>>> +            return i;
>>> +    }
>>> +    return -EINVAL;
>>> +}
>>> +
>>> +static
>>> +void iio_trigger_set_configfs_ops(struct iio_configfs_trigger_info 
>>> *trig_info,
>>> +                  unsigned int type)
>>> +{
>>> +    switch (type) {
>>> +    case IIO_TRIGGER_TYPE_NONE:
>>> +        trig_info->configfs_ops = &iio_none_ops;
>>> +        break;
>>> +    default:
>>> +        pr_err("Setting configfs ops failed! Unknown type %d\n", type);
>>> +        break;
>>> +    }
>>> +}
>>
>
>> I wonder if it is not better to have a sub-directory per trigger type
>> and if you create a trigger in the sub-directory it is automatically
>> of that type.
> I agree, this would perhaps be more flexible / intuitive.

Great, this sounds more in the spirit of configfs. Will add it in v2.

>>
>> The advantage is that you can have e.g. trigger specific properties.
> The initial set of triggers will be (I guess!)
>
> * high resolution timer
> * sysfs (userspace trigger) - in parallel with it's existing sysfs interface
>   which unfortunately we'll have to keep for at least a few years.
> Later on, once we have in kernel interfaces for events I'd expect we'll
> want event fired triggers (grab data based on an event from the same device
> or a different one for that matter)...
>
> Anyhow, definitely going to want different properties for these!
>
>>
>> The downside is that you no longer have a global namespace and there
>> could be name collisions by creating triggers with the same name, but
>> with different types. This could be solved though by making sure that
>> the internal name is pre-fixed by the type. E.g. "hrtimer-foobar" or
>> "hrtimer/foobar".
> Yes, the prefix would be sensible.

It is sensible, but we will enforce it at the driver level.

>
>>> +
>>> +CONFIGFS_ATTR_STRUCT(iio_trigger_item);
>>> +
>>> +#define IIO_TRIGGER_ITEM_ATTR(_name, _mode, _show, _store) \
>>> +struct iio_trigger_item_attribute iio_trigger_item_attr_##_name = \
>>> +    __CONFIGFS_ATTR(_name, _mode, _show, _store)
>>> +
>>> +static ssize_t iio_trigger_item_type_read(struct iio_trigger_item *item,
>>> +                      char *page)
>>> +{
>>> +    return sprintf(page, "%s\n", trigger_types[item->trigger_info->type]);
>>> +}
>>> +
>>> +static ssize_t iio_trigger_item_type_write(struct iio_trigger_item *item,
>>> +                       const char *page, size_t count)
>>> +{
>>> +    int type;
>>> +
>>> +    if (item->trigger_info->active)
>>> +        return -EBUSY;
>>> +
>>> +    type = iio_trigger_get_type(page);
>>> +    if (type < 0)
>>> +        return -EINVAL;
>>> +
>>> +    item->trigger_info->type = type;
>>> +
>>> +    iio_trigger_set_configfs_ops(item->trigger_info, type);
>>> +
>>> +    return count;
>>> +}
>>> +
>>> +static ssize_t iio_trigger_item_activate_read(struct iio_trigger_item 
>>> *item,
>>> +                          char *page)
>>> +{
>>> +    return sprintf(page, "%d\n", item->trigger_info->active);
>>> +}
>>> +
>>> +static ssize_t iio_trigger_item_activate_write(struct iio_trigger_item 
>>> *item,
>>> +                           const char *page, size_t count)
>>> +{
>>> +    bool requested_action;
>>> +    int ret;
>>> +
>>> +    ret = strtobool(page, &requested_action);
>>> +    if (ret < 0)
>>> +        return ret;
>>> +
>>> +    if (requested_action == item->trigger_info->active)
>>> +        return -EINVAL;
>>> +
>>> +    if (requested_action)
>>> +        item->trigger_info->configfs_ops->probe(item->trigger_info);
>>> +    else
>>> +        item->trigger_info->configfs_ops->remove(item->trigger_info);
>>> +
>>> +    item->trigger_info->active = requested_action;
>>> +
>>> +    return count;
>>> +}
>>
>> Do we need the activate attribute? Shouldn't the trigger be
>> create/destroyed if the type field is changed? Or if we have one
>> directory per trigger type when the directory for the trigger is
>> created using mkdir? I think that would make a nice more natural
>> API.>
>> [...]
> Only exception would be a trigger that has no meaning until we have
> configured it - e.g. the event triggers mentioned above.  That would
> need an explicit activate.  Question is whether we want to start
> out with that interface for all triggers on the basis it will be
> needed later?

Yes, I was thinking at the case where the trigger needs first to be
configured and then activated. But for hrtimers I think we can remove
activate attribute for now.

>
> Actually come to think of it, there is no problem with registering
> an unconfigured trigger - just with using it.  Hence we could do
> so and only fault out when a buffer using the trigger is started.
> That works for the complex usecase (as long as we spit out appropriate
> log messages / error codes).
>
> Hence if we can get away with doing everything on the mkdir that
> would be great.

Thanks for the feedback. I will send v2 asap.

Daniel.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to