Re: [Uclinux-dist-devel] IIO ring buffer

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

 



Hi Jonathan,
Thanks very much for your long description. But i am difficult to
understand all those,  so if there are pseudo codes, that will be much
more helpful to me.
I think you want to say
1. change iio_common_trigger_bh_to_ring into 3 step:
get_data_from_hardware()
fill_ring_buffer()
notify_buffer_change()
Yes. I completely agree because that will make it suitable for more cases.

2. remove work_cont struct since it is useless.

3.you want to say there is only one-copy for trigger , then another
device will destory current device if using it as the trigger?
 IIO_EVENT_SH(common_trig, &iio_common_trigger_poll);
Here we can build one copy for every device.

Thanks
Barry

On Sun, Jun 13, 2010 at 1:35 AM, Jonathan Cameron <jic23@xxxxxxxxx> wrote:
> On 06/12/10 03:26, Barry Song wrote:
> Hi Barry,
>
> I'm afraid I'm still on a useless net connection so don't have option
> to review the code properly.
>
>> The driver doesn't aim to replace what has existed in iio core. Just
>> improvement and a module which can be shared by most devices. Devices
>> which have special path can still self-define like before.
> Indeed, this is a good idea. I'm just disagreeing with a few of the details.
> As things stand with this patch at the mo, its a take it or leave it
> situation. I'd like to have it so drivers can cherry pick those elements
> they want as that will give us the most advantages.
>>
>> On Fri, Jun 11, 2010 at 6:22 PM, Jonathan Cameron <jic23@xxxxxxxxx> wrote:
>>> On 06/11/10 04:19, Barry Song wrote:
>>>> On Thu, Jun 10, 2010 at 9:48 PM, Jonathan Cameron <jic23@xxxxxxxxx> wrote:
>>>>> On 06/10/10 05:48, Barry Song wrote:
>>>>>> Just RFC for discussion. It is not the last patch To keep the change
>>>>>> lest, i extract the common factor for most iio devices to a common
>>>>>> ring trigger module. Most devices can use the interfaces in this
>>>>>> module directly. So copy-paste for ring and trigger is not necessary
>>>>>> now.
>>>>> Hi Barry,
>>>>>
>>>>> I'm afraid I'm not in a position to take a particularly
>>>>> close look at this right now (on a rather slow net connection)
>>>>> Thanks for taking a look at what we can unify.
>>>>>
>>>>> My immediate thought is that this patch may go a little too far,
>>>>> certainly at this stage.  It produces generic support for a
>>>>> particular type of trigger (fine and useful) but I'm not
>>>>> sure this should be grouped with the ring buffer setup elements.
>>>>> There are plenty of devices that would benefit from parts of this
>>>>> code, but currently it is all of the take it or leave it variety.
>>>>>
>>>>> In particular I'm not sure the ring buffer filling code should
>>>>> be in here.  It really isn't as consistent as the code implies
>>>>> and by the presense of that element you have reduces the general
>>>>> usefulness of rest. I'm very doubtful that we want to move things
>>>>> like the rx and tx buffers out of the device drivers themselves.
>>>>> The device drivers should control all access to the device,
>>>>> not a core driver like this.
>>>> Basically, rx and tx can be mo/ved into the priv of iio_state. Or
>>>> iio_state can be moved into iio_dev? Then this structure is not
>>>> needed?
>>> They could but I still think these should be part of the locale
>>> device driver state. I agree they don't need to be, but conceptualy
>>> to my mind everything to do with actual communications with the chip
>>> is not something the core (or helper modules like this one) should
>>> touch.
>> The bottom level hardware read/write can be part of the device driver.
>> But the flow can be in the core.
>> The iio_state is derived from objects like nand_chip, nand_base can
>> handle data flow, the bottom_level nand driver just fill the last
>> hardware access entries.
> Exactly, but in there case they have a pretty good idea of what is coming
> down the line. Here we don't, so i would prefer to see the separation being
> at the level of driver gets data and pushes to the core (in this case the
> buffer) rather than your proposal to insert another layer pulling from the
> driver and pushing to the core. I agree there looks to be a lot of shared
> code in various drivers and it is nice to get rid of it where possible.
> However this should be constrained by the need to maintain readability of
> the code. In this particular case (just the buffer filling function not the
> rest which looks pretty good to me!) I think we loose clarity to save
> few lines.  My proposal is that, rather than passing your low level
> get data function to the handling code, just step up one level and pass
> the work struct (or related function) instead.  Thus all device related
> manipulation remains in the device driver, and we still get the benefit
> of saving on a lot of replication.
>
> The principle issue here is that, even with your patch the core doesn't know
> anywhere near enough about the incoming data from the chip. It currently
> has access to how many channels there are and whether there is a timestamp.
> To do the buffer fill it would need to know:
> 1) Offsets in raw data coming off the chip (common case is to start all reads
> with a status byte - to get rid of this in your current code involve an extra
> copy of all data)
> 2) The size of each element being read back.
> 3) Packing of the data
>
> I can see your point that your current driver covers a number of devices
> that we already have drivers for. My issue is that with this one element
> removed it covers pretty much any device with a dataready trigger. That
> seems like a bigger gain to me.
>
> If we divide things a little further, separating the ring buffer related
> elements and the trigger related elements then some elements are useful
> to every driver with a software buffer.  It is that gain that would be
> most beneficial.
>>>>>
>>>>> Currently we don't have internal hooks to the contents
>>>>> of the 'scans '.  These could be added, but I think that would
>>>>> add more complexity than simply allowing the drivers to handle
>>>>> this aspect, not to mention adding some unecessary time penalty
>>>>> to this path.
>>>>>
>>>>>>
>>>>>> For iio core changes:
>>>>>> 1. extract xxx_state to iio_state and add a private data to contain
>>>>>> chip-specific data
>>>>>> 2. extract all xxx_ring/xxx_trigger api to common api
>>>>>>
>>>>>> Index: drivers/staging/iio/iio.h
>>>>>> ===================================================================
>>>>>> --- drivers/staging/iio/iio.h (revision 8893)
>>>>>> +++ drivers/staging/iio/iio.h (working copy)
>>>>>> @@ -447,4 +447,46 @@
>>>>>>
>>>>>>  int iio_get_new_idr_val(struct idr *this_idr);
>>>>>>  void iio_free_idr_val(struct idr *this_idr, int id);
>>>>>> +
>>>>>> +/**
>>>>>> + * struct iio_state - hardware level hooks for iio device
>>>>>> + * @work_trigger_to_ring: bh for triggered event handling
>>>>>> + * @work_cont_thresh: CLEAN
>>>>>> + * @inter:           used to check if new interrupt has been triggered
>>>>>> + * @last_timestamp:  passing timestamp from th to bh of interrupt handler
>>>>>> + * @indio_dev:               industrial I/O device structure
>>>>>> + * @trig:            data ready trigger registered with iio
>>>>>> + * @tx:                      transmit buffer
>>>>>> + * @rx:                      recieve buffer
>>>>>> + * @buf_lock:                mutex to protect tx and rx
>>>>>> + * @irq:                interrupt number
>>>>>> + * @set_irq:            control the disable/enable of external interrupt
>>>>>> + * @hw_read_ring:       read ring data from hardware by spi/i2c.
>>>>>> + **/
>>>>>> +struct iio_state {
>>>>>> +     struct device                   *parent_dev
>>>>>> +     struct work_struct              work_trigger_to_ring;
>>>>>
> Whilst we are here, note the recent patch to remove work_cont structure.
> We have nothing that currently needs it so it shouldn't be here.
>>>>>> +     struct iio_work_cont            work_cont_thresh;
>>>>>> +     s64                             last_timestamp;
>>>>>> +     struct iio_dev                  *indio_dev;
>>>>>> +     struct iio_trigger              *trig;
>>>>>> +     u8                              *tx;
>>>>>> +     u8                              *rx;
>>>>>> +     struct mutex                    buf_lock;
>>>>>> +     int                             irq;
>>>>>> +     int (*set_irq)(struct iio_state *st, bool enable);
>>>>>> +     int (*hw_read_ring)(struct iio_state *st, u8 *rx);
>>>>>> +     void *priv;
>>>>>> +};
>>>>>> +
>>>>>> +static inline void iio_state_set_privdata(struct iio_state *st, void *data)
>>>>>> +{
>>>>>> +     st->priv = data;
>>>>>> +}
>>>>>> +
>>>>>> +static inline void * iio_state_get_privdata(struct iio_state *st)
>>>>>> +{
>>>>>> +     return st->priv;
>>>>>> +}
>>>>>> +
>>>>>>  #endif /* _INDUSTRIAL_IO_H_ */
>>>>>> Index: drivers/staging/iio/common-ring-trigger.c
>>>>>> ===================================================================
>>>>>> --- drivers/staging/iio/common-ring-trigger.c (revision 0)
>>>>>> +++ drivers/staging/iio/common-ring-trigger.c (revision 0)
>>>>>> @@ -0,0 +1,277 @@
>>>>>> +/* The software ring with trigger which can be used by most drivers
>>>>>> + *
>>>>>> + * Copyright (c) 2010 Barry Song
>>>>>> + *
>>>>>> + * 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/kernel.h>
>>>>>> +#include <linux/device.h>
>>>>>> +#include <linux/interrupt.h>
>>>>>> +#include <linux/fs.h>
>>>>>> +#include <linux/poll.h>
>>>>>> +#include <linux/module.h>
>>>>>> +#include <linux/cdev.h>
>>>>>> +#include <linux/slab.h>
>>>>>> +
>>>>>> +#include "iio.h"
>>>>>> +#include "ring_generic.h"
>>>>>> +#include "trigger.h"
>>>>>> +#include "ring_sw.h"
>>>>>> +
>>>>>> +/*
>>>>>> + * combine_8_to_16(): utility function to munge to u8s into u16
>>>>>> + */
>>>>>> +static inline u16 combine_8_to_16(u8 lower, u8 upper)
>>>>>> +{
>>>>>> +     u16 _lower = lower;
>>>>>> +     u16 _upper = upper;
>>>>>> +     return _lower | (_upper << 8);
>>>>>> +}
>>>>>> +
>>>>>> +static void iio_common_ring_poll_func_th(struct iio_dev *indio_dev)
>>>>>> +{
>>>>>> +     struct iio_state *st = iio_dev_get_devdata(indio_dev);
>>>>>> +     st->last_timestamp = indio_dev->trig->timestamp;
>>>>>> +     schedule_work(&st->work_trigger_to_ring);
>>>>>> +}
>>>>>> +/
>>>>>
>>>>> This function is the one that mainly bothers me.  We might
>>>>> have a number of devices that do fit in here but there are
>>>>> others that would use pretty much everything else but
>>>>> this.  I'd possibly be more inclined to leave this
>>>>> to the drivers.  That is where the knowledge about the
>>>>> data layout in 'rx' comes from.
>>>>
>>>> Here we can let the hw_read_ring() do more, not only read hw, but also
>>>> fill the last data buffer, like combine_8_to_16().
>>> but once it is doing that much, what is te point of the following?
>>> You will save a few repeated lines, but at the cost of driver
>>> readability. I'm yet to be convinced that this function should exist.
>>> Why not pass the appropriate work struct in having initialized it
>>> in the chip driver?  There are certainly elements of this code that
>>> will not be ideal for every device anyway (such as the kmalloc
>>> being in here!)
>> not just several saved lines. But mean the bottom level driver doesn't
>> need to care the flow of trigger_bh_to_ring().
>> Bottom level driver doesn't need to self-define its
>> trigger_bh_to_ring(), it only read hardware data and fill the data
>> buffer. That's what the bottom level driver wants to do.
> I agree that has a certain elegance, but unfortunately the bottom
> level driver is still responsible for telling userspace what is
> in the buffer.  Thus I am yet to be convinced it shouldn't also
> be responsible for filling the buffer.  If we really want
> to hide this from the device, then the following would work
>
> //Ask the driver for a suitably aligned pointer to the data
> u8 *dat = iio_dev.get_data_for_buffer(u8 alignment);
> ring.push_to_ring(dat);
> iio_dev.notify_buffer_data_done();
>
> Or (and this approach is needed if a device can use the buffer
> elements directly for dma).
>
> u8 *data = ring.allocate_data(sizeofdata);
> iio_dev.get_data_for_buffer(data);
> ring.notify_filled();
>
> Perhaps we should leave this element as one that need more
> thought / debate and push on with the others.
>
> Also worth noting is that pretty much all these dataready
> triggers will not currently work if 'only' another device
> is using them as a trigger. (nothing clears the interrupt).
> It may seem to be a fairly odd thing to do, and I'm still
> wondering if it is better to insist this should work in
> all drivers, or to actively prevent it. Both options are
> non trivial.
>
> Looking more at the functions covered I'm not sure
> that it wouldn't be better to just provide the useful
> ones as 'library functions' that a driver can cherry
> pick it they are applicable or in some cases make
> the the default with the option to override deliberately
> for cases they do not cover.
>
>
>>>>
>>>>>> +static void iio_common_trigger_bh_to_ring(struct work_struct *work_s)
>>>>>> +{
>>>>>> +     struct iio_state *st
>>>>>> +             = container_of(work_s, struct iio_state,
>>>>>> +                             work_trigger_to_ring);
>>>>>> +
>>>>>> +     int i = 0;
>>>>>> +     s16 *data;
>>>>>> +     size_t datasize = st->indio_dev
>>>>>> +             ->ring->access.get_bpd(st->indio_dev->ring);
>>>>>> +
>>>>>> +     data = kmalloc(datasize , GFP_KERNEL);
>>>>>> +        if (data == NULL) {
>>>>>> +                dev_err(st->parent_dev, "memory alloc failed in ring bh");
>>>>>> +                return;
>>>>>> +        }
>>>>>> +
>>>>>> +     if (st->indio_dev->scan_count)
>>>>>> +             if (st->hw_read_ring(st, st->rx) >= 0)
>>>>>> +                     for (; i < st->indio_dev->scan_count; i++) {
>>>>>> +                             data[i] = combine_8_to_16(st->rx[i*2+1],
>>>>>> +                                             st->rx[i*2]);
>>>>>> +                     }
>>>>>> +
>>>>>> +        /* Guaranteed to be aligned with 8 byte boundary */
>>>>>> +        if (st->indio_dev->scan_timestamp)
>>>>>> +                *((s64 *)(data + ((i + 3)/4)*4)) = st->last_timestamp;
>>>>>> +
>>>>>> +        st->indio_dev->ring->access.store_to(st->indio_dev->ring,
>>>>>> +                                            (u8 *)data,
>>>>>> +                                            st->last_timestamp);
>>>>>> +
>>>>>> +        iio_trigger_notify_done(st->indio_dev->trig);
>>>>>> +        kfree(data);
>>>>>> +
>>>>>> +        return;
>>>>>> +}
>>>>>> +
>>>>>> +static int iio_common_ring_preenable(struct iio_dev *indio_dev)
>>>>>> +{
>>>>>> +     size_t size;
>>>>>> +     dev_dbg(&indio_dev->dev, "%s\n", __func__);
>>>>>> +     /* Check if there are any scan elements enabled, if not fail*/
>>>>>> +     if (!(indio_dev->scan_count || indio_dev->scan_timestamp))
>>>>>> +             return -EINVAL;
>>>>>> +
>>>>>> +     if (indio_dev->ring->access.set_bpd) {
>>>>>> +             if (indio_dev->scan_timestamp)
>>>>>> +                     if (indio_dev->scan_count)
>>>>>> +                             /* Timestamp (aligned to s64) and data */
>>>>>> +                             size = (((indio_dev->scan_count * sizeof(s16))
>>>>>> +                                                     + sizeof(s64) - 1)
>>>>>> +                                             & ~(sizeof(s64) - 1))
>>>>>> +                                     + sizeof(s64);
>>>>>> +                     else /* Timestamp only  */
>>>>>> +                             size = sizeof(s64);
>>>>>> +             else /* Data only */
>>>>>> +                     size = indio_dev->scan_count*sizeof(s16);
>>>>>> +             indio_dev->ring->access.set_bpd(indio_dev->ring, size);
>>>>>> +     }
>>>>>> +
>>>>>> +     return 0;
>>>>>> +}
>>>>>> +
>>>>>> +static int iio_common_ring_postenable(struct iio_dev *indio_dev)
>>>>>> +{
>>>>>> +        return indio_dev->trig
>>>>>> +                ? iio_trigger_attach_poll_func(indio_dev->trig,
>>>>>> +                                               indio_dev->pollfunc)
>>>>>> +                : 0;
>>>>>> +}
>>>>>> +
>>>>>> +static int iio_common_ring_predisable(struct iio_dev *indio_dev)
>>>>>> +{
>>>>>> +        return indio_dev->trig
>>>>>> +                ? iio_trigger_dettach_poll_func(indio_dev->trig,
>>>>>> +                                                indio_dev->pollfunc)
>>>>>> +                : 0;
>>>>>> +}
>>>>>> +
>>>>>> +int iio_configure_common_ring(struct iio_dev *indio_dev)
>>>>>> +{
>>>>>> +     int ret = 0;
>>>>>> +     struct iio_state *st = indio_dev->dev_data;
>>>>>> +     struct iio_ring_buffer *ring;
>>>>>> +     INIT_WORK(&st->work_trigger_to_ring, iio_common_trigger_bh_to_ring);
>>>>>> +
>>>>>> +     ring = iio_sw_rb_allocate(indio_dev);
>>>>>> +     if (!ring) {
>>>>>> +             ret = -ENOMEM;
>>>>>> +             return ret;
>>>>>> +     }
>>>>>> +     indio_dev->ring = ring;
>>>>>> +
>>>>>> +     iio_ring_sw_register_funcs(&ring->access);
>>>>>> +     ring->preenable = &iio_common_ring_preenable;
>>>>>> +     ring->postenable = &iio_common_ring_postenable;
>>>>>> +     ring->predisable = &iio_common_ring_predisable;
>>>>>> +     ring->owner = THIS_MODULE;
>>>>>> +
>>>>>> +     indio_dev->pollfunc = kzalloc(sizeof(*indio_dev->pollfunc), GFP_KERNEL);
>>>>>> +     if (indio_dev->pollfunc == NULL) {
>>>>>> +             ret = -ENOMEM;
>>>>>> +             goto error_iio_sw_rb_free;;
>>>>>> +     }
>>>>>> +     indio_dev->pollfunc->poll_func_main = &iio_common_ring_poll_func_th;
>>>>>> +     indio_dev->pollfunc->private_data = indio_dev;
>>>>>> +     indio_dev->modes |= INDIO_RING_TRIGGERED;
>>>>>> +     return 0;
>>>>>> +
>>>>>> +error_iio_sw_rb_free:
>>>>>> +     iio_sw_rb_free(indio_dev->ring);
>>>>>> +     return ret;
>>>>>> +}
>>>>>> +EXPORT_SYMBOL(iio_configure_common_ring);
>>>>>> +
>>>>>> +void iio_unconfigure_common_ring(struct iio_dev *indio_dev)
>>>>>> +{
>>>>>> +     kfree(indio_dev->pollfunc);
>>>>>> +     iio_sw_rb_free(indio_dev->ring);
>>>>>> +}
>>>>>> +EXPORT_SYMBOL(iio_unconfigure_common_ring);
>>>>>> +
>>>>> This next one is pointless except possibly to unify
>>>>> some naming so why do it?
>>>> Just a copy-paste and rename for existing code. Here we can let driver
>>>> call  iio_ring_buffer_register/iio_ring_buffer_unregister directly?
>>> exactly.
>>>>>> +int iio_initialize_common_ring(struct iio_ring_buffer *ring)
>>>>>> +{
>>>>>> +     return iio_ring_buffer_register(ring, 0);
>>>>>> +}
>>>>>> +EXPORT_SYMBOL(iio_initialize_common_ring);
>>>>>> +
>>>>>> +void iio_uninitialize_common_ring(struct iio_ring_buffer *ring)
>>>>>> +{
>>>>>> +     iio_ring_buffer_unregister(ring);
>>>>>> +}
>>>>>> +EXPORT_SYMBOL(iio_uninitialize_common_ring);
>>>>>> +
>>>>>> +static int iio_common_trigger_poll(struct iio_dev *dev_info,
>>>>>> +                                    int index,
>>>>>> +                                    s64 timestamp,
>>>>>> +                                    int no_test)
>>>>>> +{
>>>>>> +     struct iio_state *st = iio_dev_get_devdata(dev_info);
>>>>>> +     struct iio_trigger *trig = st->trig;
>>>>>> +
>>>>>> +     trig->timestamp = timestamp;
>>>>>> +     iio_trigger_poll(trig);
>>>>>> +
>>>>>> +     return IRQ_HANDLED;
>>>>>> +}
>>>>>> +
>>>>>> +IIO_EVENT_SH(common_trig, &iio_common_trigger_poll);
>>>>>> +
>>>>>> +static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL);
>>>>>> +
>>>>>> +static struct attribute *iio_trigger_attrs[] = {
>>>>>> +     &dev_attr_name.attr,
>>>>>> +     NULL,
>>>>>> +};
>>>>>> +
>>>>>> +static const struct attribute_group iio_trigger_attr_group = {
>>>>>> +     .attrs = iio_trigger_attrs,
>>>>>> +};
>>>>>> +
>>>>>> +static int iio_common_trigger_try_reen(struct iio_trigger *trig)
>>>>>> +{
>>>>>> +     struct iio_state *st = trig->private_data;
>>>>>> +     enable_irq(st->irq);
>>>>>> +     return 0;
>>>>>> +}
>>>>>> +
>>>>>> +static int iio_common_trigger_set_state(struct iio_trigger *trig,
>>>>>> +             bool state)
>>>>>> +{
>>>>>> +     struct iio_state *st = trig->private_data;
>>>>>> +     struct iio_dev *indio_dev = st->indio_dev;
>>>>>> +     int ret = 0;
>>>>>> +
>>>>>> +     dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
>>>>>> +     ret = st->set_irq(st, state);
>>>>> This again is making some nasty assumptions. Yes some drivers
>>>>> use a shared event to supply dat ready events, others do not
>>>>> and if the line isn't shared they shouldn't as it adds a fair
>>>>> bit of complexity to this fast path.
>>>> you mean we should know the right interrupt line for data ready event
>>>> if there are more than one indio_dev->interrupts elemant?
>>>
>>> no. I meant that indio_dev->interrupts is meant to be NULL in those
>>> cases where the only interrupt (on a given line) is used for triggering.
>>> The situation
>>> used here is only meant to occur if the same line may indicate data
>>> ready or say a threshold interrupt and has to check which it is.
>>> If we only have a dataready signal this path adds considerably
>>> complexity for no reason.  The reason I didn't comment on this in
>>> your drivers is that I assumed that event functionality was in the
>>> works.  As it currently stands none of them should be using this
>>> method, they should all be using and handling the interrupt directly.
>>> The reason this complexity exists in the lis3l02dq is that it only
>>> has a single physical interrupt line an this is shared between data
>>> ready and theshold events.  In my original adis16350 I dedicated
>>> one line to the alarms and one to the data ready.  Obviously this
>>> is a bit restrictive on possible wiring so it may make sense to go
>>> the more complex route in software.
>>>>
>>>>>> +     if (state == false) {
>>>>>> +             iio_remove_event_from_list(&iio_event_common_trig,
>>>>>> +                             &indio_dev->interrupts[0]
>>>>>> +                             ->ev_list);
>>>>>> +             flush_scheduled_work();
>>>>>> +     } else {
>>>>>> +             iio_add_event_to_list(&iio_event_common_trig,
>>>>>> +                             &indio_dev->interrupts[0]->ev_list);
>>>>>> +     }
>>>>>> +     return ret;
>>>>>> +}
>>>>>> +
>>>>>> +int iio_probe_common_trigger(struct iio_dev *indio_dev)
>>>>>> +{
>>>>>> +     int ret;
>>>>>> +     struct iio_state *st = indio_dev->dev_data;
>>>>>> +
>>>>>> +     st->trig = iio_allocate_trigger();
>>>>>> +     st->trig->name = kmalloc(IIO_TRIGGER_NAME_LENGTH, GFP_KERNEL);
>>>>>> +     if (!st->trig->name) {
>>>>>> +             ret = -ENOMEM;
>>>>>> +             goto error_free_trig;
>>>>>> +     }
>>>>>> +     snprintf((char *)st->trig->name,
>>>>>> +                     IIO_TRIGGER_NAME_LENGTH,
>>>>>> +                     "iio-dev%d", indio_dev->id);
>>>>>> +     st->trig->dev.parent = st->parent_dev;
>>>>>> +     st->trig->owner = THIS_MODULE;
>>>>>> +     st->trig->private_data = st;
>>>>>> +     st->trig->set_trigger_state = &iio_common_trigger_set_state;
>>>>>> +     st->trig->try_reenable = &iio_common_trigger_try_reen;
>>>>>> +     st->trig->control_attrs = &iio_trigger_attr_group;
>>>>>> +     ret = iio_trigger_register(st->trig);
>>>>>> +
>>>>>> +     /* select default trigger */
>>>>>> +     indio_dev->trig = st->trig;
>>>>>> +     if (ret)
>>>>>> +             goto error_free_trig_name;
>>>>>> +
>>>>>> +     return 0;
>>>>>> +
>>>>>> +error_free_trig_name:
>>>>>> +     kfree(st->trig->name);
>>>>>> +error_free_trig:
>>>>>> +     iio_free_trigger(st->trig);
>>>>>> +
>>>>>> +     return ret;
>>>>>> +}
>>>>>> +EXPORT_SYMBOL(iio_probe_common_trigger);
>>>>>> +
>>>>>> +void iio_remove_common_trigger(struct iio_dev *indio_dev)
>>>>>> +{
>>>>>> +     struct iio_state *state = indio_dev->dev_data;
>>>>>> +
>>>>>> +     iio_trigger_unregister(state->trig);
>>>>>> +     kfree(state->trig->name);
>>>>>> +     iio_free_trigger(state->trig);
>>>>>> +}
>>>>>> +EXPORT_SYMBOL(iio_remove_common_trigger);
>>>>>> Index: drivers/staging/iio/common-ring-trigger.h
>>>>>> ===================================================================
>>>>>> --- drivers/staging/iio/common-ring-trigger.h (revision 0)
>>>>>> +++ drivers/staging/iio/common-ring-trigger.h (revision 0)
>>>>>> @@ -0,0 +1,24 @@
>>>>>> +/* The industrial I/O frequently used ring with trigger
>>>>>> + *
>>>>>> + * Copyright (c) 2010 Barry Song
>>>>>> + *
>>>>>> + * 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.
>>>>>> + *
>>>>>> + */
>>>>>> +
>>>>>> +#ifndef _IIO_COMMON_RING_TRIGGER_H_
>>>>>> +#define _IIO_COMMON_RING_TRIGGER_H_
>>>>>> +
>>>>>> +#include "iio.h"
>>>>>> +#include "ring_generic.h"
>>>>>> +
>>>>>> +int iio_configure_common_ring(struct iio_dev *indio_dev);
>>>>>> +void iio_unconfigure_common_ring(struct iio_dev *indio_dev);
>>>>>> +int iio_initialize_common_ring(struct iio_ring_buffer *ring);
>>>>>> +void iio_uninitialize_common_ring(struct iio_ring_buffer *ring);
>>>>>> +
>>>>>> +int iio_probe_common_trigger(struct iio_dev *indio_dev);
>>>>>> +void iio_remove_common_trigger(struct iio_dev *indio_dev);
>>>>>> +#endif /* _IIO_COMMON_RING_TRIGGER_H_ */
>>>>>> Index: drivers/staging/iio/Kconfig
>>>>>> ===================================================================
>>>>>> --- drivers/staging/iio/Kconfig       (revision 8893)
>>>>>> +++ drivers/staging/iio/Kconfig       (working copy)
>>>>>> @@ -38,6 +38,12 @@
>>>>>>         ring buffers.  The triggers are effectively a 'capture
>>>>>>         data now' interrupt.
>>>>>>
>>>>>> +config IIO_COMMON_RING_TRIGGER
>>>>>> +     boolean "Enable frequently used ring with trigger"
>>>>>> +     depends on IIO_SW_RING && IIO_TRIGGER
>>>>>> +     help
>>>>>> +       Provides a generic ring with trigger. I can be used by most
>>>>>> +       IIO devices.
>>>>>>
>>>>>>  source "drivers/staging/iio/accel/Kconfig"
>>>>>>  source "drivers/staging/iio/adc/Kconfig"
>>>>>> Index: drivers/staging/iio/Makefile
>>>>>> ===================================================================
>>>>>> --- drivers/staging/iio/Makefile      (revision 8893)
>>>>>> +++ drivers/staging/iio/Makefile      (working copy)
>>>>>> @@ -9,6 +9,8 @@
>>>>>>
>>>>>>  obj-$(CONFIG_IIO_SW_RING) += ring_sw.o
>>>>>>
>>>>>> +obj-$(CONFIG_IIO_COMMON_RING_TRIGGER) += common-ring-trigger.o
>>>>>> +
>>>>>>  obj-y += accel/
>>>>>>  obj-y += adc/
>>>>>>  obj-y += addac/
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>>
>>>>
>>>
>>>
>>
>
>
--
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