staging:iio: Add support for multiple buffers
authorJonathan Cameron <jic23@kernel.org>
Sat, 30 Jun 2012 19:06:00 +0000 (20:06 +0100)
committerJonathan Cameron <jic23@kernel.org>
Sat, 10 Nov 2012 10:17:21 +0000 (10:17 +0000)
Route all buffer writes through the demux.
Addition or removal of a buffer results in tear down and
setup of all the buffers for a given device.

Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Tested-by: srinivas pandruvada <srinivas.pandruvada@intel.com>
30 files changed:
drivers/iio/accel/hid-sensor-accel-3d.c
drivers/iio/adc/ad7266.c
drivers/iio/adc/ad7476.c
drivers/iio/adc/ad7887.c
drivers/iio/adc/ad_sigma_delta.c
drivers/iio/adc/at91_adc.c
drivers/iio/gyro/hid-sensor-gyro-3d.c
drivers/iio/industrialio-buffer.c
drivers/iio/industrialio-core.c
drivers/iio/light/adjd_s311.c
drivers/iio/light/hid-sensor-als.c
drivers/iio/magnetometer/hid-sensor-magn-3d.c
drivers/staging/iio/accel/adis16201_ring.c
drivers/staging/iio/accel/adis16203_ring.c
drivers/staging/iio/accel/adis16204_ring.c
drivers/staging/iio/accel/adis16209_ring.c
drivers/staging/iio/accel/adis16240_ring.c
drivers/staging/iio/accel/lis3l02dq_ring.c
drivers/staging/iio/adc/ad7298_ring.c
drivers/staging/iio/adc/ad7606_ring.c
drivers/staging/iio/adc/ad799x_ring.c
drivers/staging/iio/adc/max1363_ring.c
drivers/staging/iio/adc/mxs-lradc.c
drivers/staging/iio/gyro/adis16260_ring.c
drivers/staging/iio/iio_simple_dummy_buffer.c
drivers/staging/iio/impedance-analyzer/ad5933.c
drivers/staging/iio/imu/adis16400_ring.c
drivers/staging/iio/meter/ade7758_ring.c
include/linux/iio/buffer.h
include/linux/iio/iio.h

index 314a405..a95cda0 100644 (file)
@@ -197,21 +197,8 @@ static const struct iio_info accel_3d_info = {
 /* Function to push data to buffer */
 static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len)
 {
-       struct iio_buffer *buffer = indio_dev->buffer;
-       int datum_sz;
-
        dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
-       if (!buffer) {
-               dev_err(&indio_dev->dev, "Buffer == NULL\n");
-               return;
-       }
-       datum_sz = buffer->access->get_bytes_per_datum(buffer);
-       if (len > datum_sz) {
-               dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len,
-                               datum_sz);
-               return;
-       }
-       iio_push_to_buffer(buffer, (u8 *)data);
+       iio_push_to_buffers(indio_dev, (u8 *)data);
 }
 
 /* Callback handler to send event after all samples are received and captured */
index b11f214..a6f4fc5 100644 (file)
@@ -91,7 +91,6 @@ static irqreturn_t ad7266_trigger_handler(int irq, void *p)
 {
        struct iio_poll_func *pf = p;
        struct iio_dev *indio_dev = pf->indio_dev;
-       struct iio_buffer *buffer = indio_dev->buffer;
        struct ad7266_state *st = iio_priv(indio_dev);
        int ret;
 
@@ -99,7 +98,7 @@ static irqreturn_t ad7266_trigger_handler(int irq, void *p)
        if (ret == 0) {
                if (indio_dev->scan_timestamp)
                        ((s64 *)st->data)[1] = pf->timestamp;
-               iio_push_to_buffer(buffer, (u8 *)st->data);
+               iio_push_to_buffers(indio_dev, (u8 *)st->data);
        }
 
        iio_trigger_notify_done(indio_dev->trig);
index 7f2f45a..330248b 100644 (file)
@@ -76,7 +76,7 @@ static irqreturn_t ad7476_trigger_handler(int irq, void  *p)
        if (indio_dev->scan_timestamp)
                ((s64 *)st->data)[1] = time_ns;
 
-       iio_push_to_buffer(indio_dev->buffer, st->data);
+       iio_push_to_buffers(indio_dev, st->data);
 done:
        iio_trigger_notify_done(indio_dev->trig);
 
index fd62309..81153fa 100644 (file)
@@ -134,7 +134,7 @@ static irqreturn_t ad7887_trigger_handler(int irq, void *p)
                memcpy(st->data + indio_dev->scan_bytes - sizeof(s64),
                       &time_ns, sizeof(time_ns));
 
-       iio_push_to_buffer(indio_dev->buffer, st->data);
+       iio_push_to_buffers(indio_dev, st->data);
 done:
        iio_trigger_notify_done(indio_dev->trig);
 
index 67baa13..afe6d78 100644 (file)
@@ -391,7 +391,7 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
                break;
        }
 
-       iio_push_to_buffer(indio_dev->buffer, (uint8_t *)data);
+       iio_push_to_buffers(indio_dev, (uint8_t *)data);
 
        iio_trigger_notify_done(indio_dev->trig);
        sigma_delta->irq_dis = false;
index 2e2c9a8..03b8594 100644 (file)
@@ -65,7 +65,6 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
        struct iio_poll_func *pf = p;
        struct iio_dev *idev = pf->indio_dev;
        struct at91_adc_state *st = iio_priv(idev);
-       struct iio_buffer *buffer = idev->buffer;
        int i, j = 0;
 
        for (i = 0; i < idev->masklength; i++) {
@@ -81,7 +80,7 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
                *timestamp = pf->timestamp;
        }
 
-       iio_push_to_buffer(buffer, st->buffer);
+       iio_push_to_buffers(indio_dev, (u8 *)st->buffer);
 
        iio_trigger_notify_done(idev->trig);
 
index 4c56ada..02ef989 100644 (file)
@@ -197,21 +197,8 @@ static const struct iio_info gyro_3d_info = {
 /* Function to push data to buffer */
 static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len)
 {
-       struct iio_buffer *buffer = indio_dev->buffer;
-       int datum_sz;
-
        dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
-       if (!buffer) {
-               dev_err(&indio_dev->dev, "Buffer == NULL\n");
-               return;
-       }
-       datum_sz = buffer->access->get_bytes_per_datum(buffer);
-       if (len > datum_sz) {
-               dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len,
-                               datum_sz);
-               return;
-       }
-       iio_push_to_buffer(buffer, (u8 *)data);
+       iio_push_to_buffers(indio_dev, (u8 *)data);
 }
 
 /* Callback handler to send event after all samples are received and captured */
index 722a83f..aaadd32 100644 (file)
@@ -31,6 +31,18 @@ static const char * const iio_endian_prefix[] = {
        [IIO_LE] = "le",
 };
 
+static bool iio_buffer_is_active(struct iio_dev *indio_dev,
+                                struct iio_buffer *buf)
+{
+       struct list_head *p;
+
+       list_for_each(p, &indio_dev->buffer_list)
+               if (p == &buf->buffer_list)
+                       return true;
+
+       return false;
+}
+
 /**
  * iio_buffer_read_first_n_outer() - chrdev read for buffer access
  *
@@ -134,7 +146,7 @@ static ssize_t iio_scan_el_store(struct device *dev,
        if (ret < 0)
                return ret;
        mutex_lock(&indio_dev->mlock);
-       if (iio_buffer_enabled(indio_dev)) {
+       if (iio_buffer_is_active(indio_dev, indio_dev->buffer)) {
                ret = -EBUSY;
                goto error_ret;
        }
@@ -180,12 +192,11 @@ static ssize_t iio_scan_el_ts_store(struct device *dev,
                return ret;
 
        mutex_lock(&indio_dev->mlock);
-       if (iio_buffer_enabled(indio_dev)) {
+       if (iio_buffer_is_active(indio_dev, indio_dev->buffer)) {
                ret = -EBUSY;
                goto error_ret;
        }
        indio_dev->buffer->scan_timestamp = state;
-       indio_dev->scan_timestamp = state;
 error_ret:
        mutex_unlock(&indio_dev->mlock);
 
@@ -385,7 +396,7 @@ ssize_t iio_buffer_write_length(struct device *dev,
                        return len;
 
        mutex_lock(&indio_dev->mlock);
-       if (iio_buffer_enabled(indio_dev)) {
+       if (iio_buffer_is_active(indio_dev, indio_dev->buffer)) {
                ret = -EBUSY;
        } else {
                if (buffer->access->set_length)
@@ -398,102 +409,14 @@ ssize_t iio_buffer_write_length(struct device *dev,
 }
 EXPORT_SYMBOL(iio_buffer_write_length);
 
-ssize_t iio_buffer_store_enable(struct device *dev,
-                               struct device_attribute *attr,
-                               const char *buf,
-                               size_t len)
-{
-       int ret;
-       bool requested_state, current_state;
-       int previous_mode;
-       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-       struct iio_buffer *buffer = indio_dev->buffer;
-
-       mutex_lock(&indio_dev->mlock);
-       previous_mode = indio_dev->currentmode;
-       requested_state = !(buf[0] == '0');
-       current_state = iio_buffer_enabled(indio_dev);
-       if (current_state == requested_state) {
-               printk(KERN_INFO "iio-buffer, current state requested again\n");
-               goto done;
-       }
-       if (requested_state) {
-               if (indio_dev->setup_ops->preenable) {
-                       ret = indio_dev->setup_ops->preenable(indio_dev);
-                       if (ret) {
-                               printk(KERN_ERR
-                                      "Buffer not started: "
-                                      "buffer preenable failed\n");
-                               goto error_ret;
-                       }
-               }
-               if (buffer->access->request_update) {
-                       ret = buffer->access->request_update(buffer);
-                       if (ret) {
-                               printk(KERN_INFO
-                                      "Buffer not started: "
-                                      "buffer parameter update failed\n");
-                               goto error_ret;
-                       }
-               }
-               /* Definitely possible for devices to support both of these. */
-               if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) {
-                       if (!indio_dev->trig) {
-                               printk(KERN_INFO
-                                      "Buffer not started: no trigger\n");
-                               ret = -EINVAL;
-                               goto error_ret;
-                       }
-                       indio_dev->currentmode = INDIO_BUFFER_TRIGGERED;
-               } else if (indio_dev->modes & INDIO_BUFFER_HARDWARE)
-                       indio_dev->currentmode = INDIO_BUFFER_HARDWARE;
-               else { /* should never be reached */
-                       ret = -EINVAL;
-                       goto error_ret;
-               }
-
-               if (indio_dev->setup_ops->postenable) {
-                       ret = indio_dev->setup_ops->postenable(indio_dev);
-                       if (ret) {
-                               printk(KERN_INFO
-                                      "Buffer not started: "
-                                      "postenable failed\n");
-                               indio_dev->currentmode = previous_mode;
-                               if (indio_dev->setup_ops->postdisable)
-                                       indio_dev->setup_ops->
-                                               postdisable(indio_dev);
-                               goto error_ret;
-                       }
-               }
-       } else {
-               if (indio_dev->setup_ops->predisable) {
-                       ret = indio_dev->setup_ops->predisable(indio_dev);
-                       if (ret)
-                               goto error_ret;
-               }
-               indio_dev->currentmode = INDIO_DIRECT_MODE;
-               if (indio_dev->setup_ops->postdisable) {
-                       ret = indio_dev->setup_ops->postdisable(indio_dev);
-                       if (ret)
-                               goto error_ret;
-               }
-       }
-done:
-       mutex_unlock(&indio_dev->mlock);
-       return len;
-
-error_ret:
-       mutex_unlock(&indio_dev->mlock);
-       return ret;
-}
-EXPORT_SYMBOL(iio_buffer_store_enable);
-
 ssize_t iio_buffer_show_enable(struct device *dev,
                               struct device_attribute *attr,
                               char *buf)
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-       return sprintf(buf, "%d\n", iio_buffer_enabled(indio_dev));
+       return sprintf(buf, "%d\n",
+                      iio_buffer_is_active(indio_dev,
+                                           indio_dev->buffer));
 }
 EXPORT_SYMBOL(iio_buffer_show_enable);
 
@@ -537,35 +460,220 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const long *mask,
        return bytes;
 }
 
-int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
+int iio_update_buffers(struct iio_dev *indio_dev,
+                      struct iio_buffer *insert_buffer,
+                      struct iio_buffer *remove_buffer)
 {
-       struct iio_buffer *buffer = indio_dev->buffer;
-       dev_dbg(&indio_dev->dev, "%s\n", __func__);
+       int ret;
+       int success = 0;
+       struct iio_buffer *buffer;
+       unsigned long *compound_mask;
+       const unsigned long *old_mask;
 
-       /* How much space will the demuxed element take? */
-       indio_dev->scan_bytes =
-               iio_compute_scan_bytes(indio_dev, buffer->scan_mask,
-                                      buffer->scan_timestamp);
-       buffer->access->set_bytes_per_datum(buffer, indio_dev->scan_bytes);
+       /* Wind down existing buffers - iff there are any */
+       if (!list_empty(&indio_dev->buffer_list)) {
+               if (indio_dev->setup_ops->predisable) {
+                       ret = indio_dev->setup_ops->predisable(indio_dev);
+                       if (ret)
+                               goto error_ret;
+               }
+               indio_dev->currentmode = INDIO_DIRECT_MODE;
+               if (indio_dev->setup_ops->postdisable) {
+                       ret = indio_dev->setup_ops->postdisable(indio_dev);
+                       if (ret)
+                               goto error_ret;
+               }
+       }
+       /* Keep a copy of current setup to allow roll back */
+       old_mask = indio_dev->active_scan_mask;
+       if (!indio_dev->available_scan_masks)
+               indio_dev->active_scan_mask = NULL;
+
+       if (remove_buffer)
+               list_del(&remove_buffer->buffer_list);
+       if (insert_buffer)
+               list_add(&insert_buffer->buffer_list, &indio_dev->buffer_list);
+
+       /* If no buffers in list, we are done */
+       if (list_empty(&indio_dev->buffer_list)) {
+               indio_dev->currentmode = INDIO_DIRECT_MODE;
+               if (indio_dev->available_scan_masks == NULL)
+                       kfree(old_mask);
+               return 0;
+       }
 
        /* What scan mask do we actually have ?*/
-       if (indio_dev->available_scan_masks)
+       compound_mask = kcalloc(BITS_TO_LONGS(indio_dev->masklength),
+                               sizeof(long), GFP_KERNEL);
+       if (compound_mask == NULL) {
+               if (indio_dev->available_scan_masks == NULL)
+                       kfree(old_mask);
+               return -ENOMEM;
+       }
+       indio_dev->scan_timestamp = 0;
+
+       list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) {
+               bitmap_or(compound_mask, compound_mask, buffer->scan_mask,
+                         indio_dev->masklength);
+               indio_dev->scan_timestamp |= buffer->scan_timestamp;
+       }
+       if (indio_dev->available_scan_masks) {
                indio_dev->active_scan_mask =
                        iio_scan_mask_match(indio_dev->available_scan_masks,
                                            indio_dev->masklength,
-                                           buffer->scan_mask);
-       else
-               indio_dev->active_scan_mask = buffer->scan_mask;
-
-       if (indio_dev->active_scan_mask == NULL)
-               return -EINVAL;
+                                           compound_mask);
+               if (indio_dev->active_scan_mask == NULL) {
+                       /*
+                        * Roll back.
+                        * Note can only occur when adding a buffer.
+                        */
+                       list_del(&insert_buffer->buffer_list);
+                       indio_dev->active_scan_mask = old_mask;
+                       success = -EINVAL;
+               }
+       } else {
+               indio_dev->active_scan_mask = compound_mask;
+       }
 
        iio_update_demux(indio_dev);
 
-       if (indio_dev->info->update_scan_mode)
-               return indio_dev->info
+       /* Wind up again */
+       if (indio_dev->setup_ops->preenable) {
+               ret = indio_dev->setup_ops->preenable(indio_dev);
+               if (ret) {
+                       printk(KERN_ERR
+                              "Buffer not started:"
+                              "buffer preenable failed\n");
+                       goto error_remove_inserted;
+               }
+       }
+       indio_dev->scan_bytes =
+               iio_compute_scan_bytes(indio_dev,
+                                      indio_dev->active_scan_mask,
+                                      indio_dev->scan_timestamp);
+       list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list)
+               if (buffer->access->request_update) {
+                       ret = buffer->access->request_update(buffer);
+                       if (ret) {
+                               printk(KERN_INFO
+                                      "Buffer not started:"
+                                      "buffer parameter update failed\n");
+                               goto error_run_postdisable;
+                       }
+               }
+       if (indio_dev->info->update_scan_mode) {
+               ret = indio_dev->info
                        ->update_scan_mode(indio_dev,
                                           indio_dev->active_scan_mask);
+               if (ret < 0) {
+                       printk(KERN_INFO "update scan mode failed\n");
+                       goto error_run_postdisable;
+               }
+       }
+       /* Definitely possible for devices to support both of these.*/
+       if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) {
+               if (!indio_dev->trig) {
+                       printk(KERN_INFO "Buffer not started: no trigger\n");
+                       ret = -EINVAL;
+                       /* Can only occur on first buffer */
+                       goto error_run_postdisable;
+               }
+               indio_dev->currentmode = INDIO_BUFFER_TRIGGERED;
+       } else if (indio_dev->modes & INDIO_BUFFER_HARDWARE) {
+               indio_dev->currentmode = INDIO_BUFFER_HARDWARE;
+       } else { /* should never be reached */
+               ret = -EINVAL;
+               goto error_run_postdisable;
+       }
+
+       if (indio_dev->setup_ops->postenable) {
+               ret = indio_dev->setup_ops->postenable(indio_dev);
+               if (ret) {
+                       printk(KERN_INFO
+                              "Buffer not started: postenable failed\n");
+                       indio_dev->currentmode = INDIO_DIRECT_MODE;
+                       if (indio_dev->setup_ops->postdisable)
+                               indio_dev->setup_ops->postdisable(indio_dev);
+                       goto error_disable_all_buffers;
+               }
+       }
+
+       if (indio_dev->available_scan_masks)
+               kfree(compound_mask);
+       else
+               kfree(old_mask);
+
+       return success;
+
+error_disable_all_buffers:
+       indio_dev->currentmode = INDIO_DIRECT_MODE;
+error_run_postdisable:
+       if (indio_dev->setup_ops->postdisable)
+               indio_dev->setup_ops->postdisable(indio_dev);
+error_remove_inserted:
+
+       if (insert_buffer)
+               list_del(&insert_buffer->buffer_list);
+       indio_dev->active_scan_mask = old_mask;
+       kfree(compound_mask);
+error_ret:
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(iio_update_buffers);
+
+ssize_t iio_buffer_store_enable(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf,
+                               size_t len)
+{
+       int ret;
+       bool requested_state;
+       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct iio_buffer *pbuf = indio_dev->buffer;
+       bool inlist;
+
+       ret = strtobool(buf, &requested_state);
+       if (ret < 0)
+               return ret;
+
+       mutex_lock(&indio_dev->mlock);
+
+       /* Find out if it is in the list */
+       inlist = iio_buffer_is_active(indio_dev, pbuf);
+       /* Already in desired state */
+       if (inlist == requested_state)
+               goto done;
+
+       if (requested_state)
+               ret = iio_update_buffers(indio_dev,
+                                        indio_dev->buffer, NULL);
+       else
+               ret = iio_update_buffers(indio_dev,
+                                        NULL, indio_dev->buffer);
+
+       if (ret < 0)
+               goto done;
+done:
+       mutex_unlock(&indio_dev->mlock);
+       return (ret < 0) ? ret : len;
+}
+EXPORT_SYMBOL(iio_buffer_store_enable);
+
+int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
+{
+       struct iio_buffer *buffer;
+       unsigned bytes;
+       dev_dbg(&indio_dev->dev, "%s\n", __func__);
+
+       list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list)
+               if (buffer->access->set_bytes_per_datum) {
+                       bytes = iio_compute_scan_bytes(indio_dev,
+                                                      buffer->scan_mask,
+                                                      buffer->scan_timestamp);
+
+                       buffer->access->set_bytes_per_datum(buffer, bytes);
+               }
        return 0;
 }
 EXPORT_SYMBOL(iio_sw_buffer_preenable);
@@ -599,7 +707,11 @@ static bool iio_validate_scan_mask(struct iio_dev *indio_dev,
  * iio_scan_mask_set() - set particular bit in the scan mask
  * @buffer: the buffer whose scan mask we are interested in
  * @bit: the bit to be set.
- **/
+ *
+ * Note that at this point we have no way of knowing what other
+ * buffers might request, hence this code only verifies that the
+ * individual buffers request is plausible.
+ */
 int iio_scan_mask_set(struct iio_dev *indio_dev,
                      struct iio_buffer *buffer, int bit)
 {
@@ -682,13 +794,12 @@ static unsigned char *iio_demux(struct iio_buffer *buffer,
        return buffer->demux_bounce;
 }
 
-int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data)
+static int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data)
 {
        unsigned char *dataout = iio_demux(buffer, data);
 
        return buffer->access->store_to(buffer, dataout);
 }
-EXPORT_SYMBOL_GPL(iio_push_to_buffer);
 
 static void iio_buffer_demux_free(struct iio_buffer *buffer)
 {
@@ -699,10 +810,26 @@ static void iio_buffer_demux_free(struct iio_buffer *buffer)
        }
 }
 
-int iio_update_demux(struct iio_dev *indio_dev)
+
+int iio_push_to_buffers(struct iio_dev *indio_dev, unsigned char *data)
+{
+       int ret;
+       struct iio_buffer *buf;
+
+       list_for_each_entry(buf, &indio_dev->buffer_list, buffer_list) {
+               ret = iio_push_to_buffer(buf, data);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(iio_push_to_buffers);
+
+static int iio_buffer_update_demux(struct iio_dev *indio_dev,
+                                  struct iio_buffer *buffer)
 {
        const struct iio_chan_spec *ch;
-       struct iio_buffer *buffer = indio_dev->buffer;
        int ret, in_ind = -1, out_ind, length;
        unsigned in_loc = 0, out_loc = 0;
        struct iio_demux_table *p;
@@ -787,4 +914,23 @@ error_clear_mux_table:
 
        return ret;
 }
+
+int iio_update_demux(struct iio_dev *indio_dev)
+{
+       struct iio_buffer *buffer;
+       int ret;
+
+       list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) {
+               ret = iio_buffer_update_demux(indio_dev, buffer);
+               if (ret < 0)
+                       goto error_clear_mux_table;
+       }
+       return 0;
+
+error_clear_mux_table:
+       list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list)
+               iio_buffer_demux_free(buffer);
+
+       return ret;
+}
 EXPORT_SYMBOL_GPL(iio_update_demux);
index cd70036..060a404 100644 (file)
@@ -856,6 +856,7 @@ struct iio_dev *iio_device_alloc(int sizeof_priv)
                        return NULL;
                }
                dev_set_name(&dev->dev, "iio:device%d", dev->id);
+               INIT_LIST_HEAD(&dev->buffer_list);
        }
 
        return dev;
index 164b62b..36d210a 100644 (file)
@@ -164,7 +164,6 @@ static irqreturn_t adjd_s311_trigger_handler(int irq, void *p)
        struct iio_poll_func *pf = p;
        struct iio_dev *indio_dev = pf->indio_dev;
        struct adjd_s311_data *data = iio_priv(indio_dev);
-       struct iio_buffer *buffer = indio_dev->buffer;
        s64 time_ns = iio_get_time_ns();
        int len = 0;
        int i, j = 0;
@@ -187,7 +186,7 @@ static irqreturn_t adjd_s311_trigger_handler(int irq, void *p)
        if (indio_dev->scan_timestamp)
                *(s64 *)((u8 *)data->buffer + ALIGN(len, sizeof(s64)))
                        = time_ns;
-       iio_push_to_buffer(buffer, (u8 *)data->buffer);
+       iio_push_to_buffers(indio_dev, (u8 *)data->buffer);
 
 done:
        iio_trigger_notify_done(indio_dev->trig);
index 96e3691..8e1f698 100644 (file)
@@ -176,21 +176,8 @@ static const struct iio_info als_info = {
 /* Function to push data to buffer */
 static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len)
 {
-       struct iio_buffer *buffer = indio_dev->buffer;
-       int datum_sz;
-
        dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
-       if (!buffer) {
-               dev_err(&indio_dev->dev, "Buffer == NULL\n");
-               return;
-       }
-       datum_sz = buffer->access->get_bytes_per_datum(buffer);
-       if (len > datum_sz) {
-               dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len,
-                               datum_sz);
-               return;
-       }
-       iio_push_to_buffer(buffer, (u8 *)data);
+       iio_push_to_buffers(indio_dev, (u8 *)data);
 }
 
 /* Callback handler to send event after all samples are received and captured */
index c4f0d27..d1b5fb7 100644 (file)
@@ -198,21 +198,8 @@ static const struct iio_info magn_3d_info = {
 /* Function to push data to buffer */
 static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len)
 {
-       struct iio_buffer *buffer = indio_dev->buffer;
-       int datum_sz;
-
        dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
-       if (!buffer) {
-               dev_err(&indio_dev->dev, "Buffer == NULL\n");
-               return;
-       }
-       datum_sz = buffer->access->get_bytes_per_datum(buffer);
-       if (len > datum_sz) {
-               dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len,
-                               datum_sz);
-               return;
-       }
-       iio_push_to_buffer(buffer, (u8 *)data);
+       iio_push_to_buffers(indio_dev, (u8 *)data);
 }
 
 /* Callback handler to send event after all samples are received and captured */
index 97c09f0..e14ca60 100644 (file)
@@ -82,7 +82,7 @@ static irqreturn_t adis16201_trigger_handler(int irq, void *p)
        if (indio_dev->scan_timestamp)
                *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
 
-       iio_push_to_buffer(indio_dev->buffer, (u8 *)data);
+       iio_push_to_buffers(indio_dev, (u8 *)data);
 
        kfree(data);
 done:
index 7507e1a..eba2e28 100644 (file)
@@ -81,7 +81,7 @@ static irqreturn_t adis16203_trigger_handler(int irq, void *p)
        if (indio_dev->scan_timestamp)
                *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
 
-       iio_push_to_buffer(indio_dev->buffer, (u8 *)data);
+       iio_push_to_buffers(indio_dev, (u8 *)data);
 
        kfree(data);
 done:
index 4c976be..3611a13 100644 (file)
@@ -78,7 +78,7 @@ static irqreturn_t adis16204_trigger_handler(int irq, void *p)
        if (indio_dev->scan_timestamp)
                *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
 
-       iio_push_to_buffer(indio_dev->buffer, (u8 *)data);
+       iio_push_to_buffers(indio_dev, (u8 *)data);
 
        kfree(data);
 done:
index f939e29..6af9a5d 100644 (file)
@@ -78,7 +78,7 @@ static irqreturn_t adis16209_trigger_handler(int irq, void *p)
        if (indio_dev->scan_timestamp)
                *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
 
-       iio_push_to_buffer(indio_dev->buffer, (u8 *)data);
+       iio_push_to_buffers(indio_dev, (u8 *)data);
 
        kfree(data);
 done:
index caff8e2..e2ac8a8 100644 (file)
@@ -76,7 +76,7 @@ static irqreturn_t adis16240_trigger_handler(int irq, void *p)
        if (indio_dev->scan_timestamp)
                *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
 
-       iio_push_to_buffer(indio_dev->buffer, (u8 *)data);
+       iio_push_to_buffers(indio_dev, (u8 *)data);
 
        kfree(data);
 done:
index 2463527..bc38651 100644 (file)
@@ -154,7 +154,7 @@ static irqreturn_t lis3l02dq_trigger_handler(int irq, void *p)
        if (indio_dev->scan_timestamp)
                *(s64 *)((u8 *)data + ALIGN(len, sizeof(s64)))
                        = pf->timestamp;
-       iio_push_to_buffer(indio_dev->buffer, (u8 *)data);
+       iio_push_to_buffers(indio_dev, (u8 *)data);
 
        kfree(data);
 done:
index c2906a8..b3dd514 100644 (file)
@@ -93,7 +93,7 @@ static irqreturn_t ad7298_trigger_handler(int irq, void *p)
                                                 indio_dev->masklength); i++)
                buf[i] = be16_to_cpu(st->rx_buf[i]);
 
-       iio_push_to_buffer(indio_dev->buffer, (u8 *)buf);
+       iio_push_to_buffers(indio_dev, (u8 *)buf);
 
 done:
        iio_trigger_notify_done(indio_dev->trig);
index ba04d0f..2b25cb0 100644 (file)
@@ -83,7 +83,7 @@ static void ad7606_poll_bh_to_ring(struct work_struct *work_s)
        if (indio_dev->scan_timestamp)
                *((s64 *)(buf + indio_dev->scan_bytes - sizeof(s64))) = time_ns;
 
-       iio_push_to_buffer(indio_dev->buffer, buf);
+       iio_push_to_buffers(indio_dev, buf);
 done:
        gpio_set_value(st->pdata->gpio_convst, 0);
        iio_trigger_notify_done(indio_dev->trig);
index 86026d9..2c5f384 100644 (file)
@@ -77,7 +77,7 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p)
                memcpy(rxbuf + indio_dev->scan_bytes - sizeof(s64),
                        &time_ns, sizeof(time_ns));
 
-       iio_push_to_buffer(indio_dev->buffer, rxbuf);
+       iio_push_to_buffers(indio_dev, rxbuf);
 done:
        kfree(rxbuf);
 out:
index 5f74f3b..688304b 100644 (file)
@@ -80,7 +80,7 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p)
 
        if (indio_dev->scan_timestamp)
                memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns));
-       iio_push_to_buffer(indio_dev->buffer, rxbuf);
+       iio_push_to_buffers(indio_dev, rxbuf);
 
 done_free:
        kfree(rxbuf);
index df5bba2..3b467d8 100644 (file)
@@ -237,7 +237,6 @@ static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p)
        struct iio_poll_func *pf = p;
        struct iio_dev *iio = pf->indio_dev;
        struct mxs_lradc *lradc = iio_priv(iio);
-       struct iio_buffer *buffer = iio->buffer;
        const uint32_t chan_value = LRADC_CH_ACCUMULATE |
                ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET);
        int i, j = 0;
@@ -256,7 +255,7 @@ static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p)
                *timestamp = pf->timestamp;
        }
 
-       iio_push_to_buffer(buffer, (u8 *)lradc->buffer);
+       iio_push_to_buffers(iio, (u8 *)lradc->buffer);
 
        iio_trigger_notify_done(iio->trig);
 
index e294cb4..d6c48f8 100644 (file)
@@ -81,7 +81,7 @@ static irqreturn_t adis16260_trigger_handler(int irq, void *p)
        if (indio_dev->scan_timestamp)
                *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
 
-       iio_push_to_buffer(indio_dev->buffer, (u8 *)data);
+       iio_push_to_buffers(indio_dev, (u8 *)data);
 
        kfree(data);
 done:
index 697d970..dee16f0 100644 (file)
@@ -46,7 +46,6 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
 {
        struct iio_poll_func *pf = p;
        struct iio_dev *indio_dev = pf->indio_dev;
-       struct iio_buffer *buffer = indio_dev->buffer;
        int len = 0;
        u16 *data;
 
@@ -76,7 +75,7 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
                     i < bitmap_weight(indio_dev->active_scan_mask,
                                       indio_dev->masklength);
                     i++, j++) {
-                       j = find_next_bit(buffer->scan_mask,
+                       j = find_next_bit(indio_dev->active_scan_mask,
                                          indio_dev->masklength, j);
                        /* random access read from the 'device' */
                        data[i] = fakedata[j];
@@ -87,7 +86,7 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
        if (indio_dev->scan_timestamp)
                *(s64 *)((u8 *)data + ALIGN(len, sizeof(s64)))
                        = iio_get_time_ns();
-       iio_push_to_buffer(buffer, (u8 *)data);
+       iio_push_to_buffers(indio_dev, (u8 *)data);
 
        kfree(data);
 
index de21d47..b1fef14 100644 (file)
@@ -647,7 +647,6 @@ static void ad5933_work(struct work_struct *work)
        struct ad5933_state *st = container_of(work,
                struct ad5933_state, work.work);
        struct iio_dev *indio_dev = i2c_get_clientdata(st->client);
-       struct iio_buffer *ring = indio_dev->buffer;
        signed short buf[2];
        unsigned char status;
 
@@ -677,8 +676,7 @@ static void ad5933_work(struct work_struct *work)
                } else {
                        buf[0] = be16_to_cpu(buf[0]);
                }
-               /* save datum to the ring */
-               iio_push_to_buffer(ring, (u8 *)buf);
+               iio_push_to_buffers(indio_dev, (u8 *)buf);
        } else {
                /* no data available - try again later */
                schedule_delayed_work(&st->work, st->poll_time_jiffies);
index 260bdd1..d46c1e3 100644 (file)
@@ -114,7 +114,6 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p)
        struct iio_poll_func *pf = p;
        struct iio_dev *indio_dev = pf->indio_dev;
        struct adis16400_state *st = iio_priv(indio_dev);
-       struct iio_buffer *ring = indio_dev->buffer;
        int i = 0, j, ret = 0;
        s16 *data;
 
@@ -148,9 +147,9 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p)
                }
        }
        /* Guaranteed to be aligned with 8 byte boundary */
-       if (ring->scan_timestamp)
+       if (indio_dev->scan_timestamp)
                *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
-       iio_push_to_buffer(ring, (u8 *) data);
+       iio_push_to_buffers(indio_dev, (u8 *) data);
 
 done:
        kfree(data);
index 9e49bac..4552a4c 100644 (file)
@@ -73,7 +73,7 @@ static irqreturn_t ade7758_trigger_handler(int irq, void *p)
        if (indio_dev->scan_timestamp)
                dat64[1] = pf->timestamp;
 
-       iio_push_to_buffer(indio_dev->buffer, (u8 *)dat64);
+       iio_push_to_buffers(indio_dev, (u8 *)dat64);
 
        iio_trigger_notify_done(indio_dev->trig);
 
index c629b3a..0270405 100644 (file)
@@ -66,7 +66,8 @@ struct iio_buffer_access_funcs {
  * @stufftoread:       [INTERN] flag to indicate new data.
  * @demux_list:                [INTERN] list of operations required to demux the scan.
  * @demux_bounce:      [INTERN] buffer for doing gather from incoming scan.
- **/
+ * @buffer_list:       [INTERN] entry in the devices list of current buffers.
+ */
 struct iio_buffer {
        int                                     length;
        int                                     bytes_per_datum;
@@ -81,9 +82,22 @@ struct iio_buffer {
        const struct attribute_group *attrs;
        struct list_head                        demux_list;
        unsigned char                           *demux_bounce;
+       struct list_head                        buffer_list;
 };
 
 /**
+ * iio_update_buffers() - add or remove buffer from active list
+ * @indio_dev:         device to add buffer to
+ * @insert_buffer:     buffer to insert
+ * @remove_buffer:     buffer_to_remove
+ *
+ * Note this will tear down the all buffering and build it up again
+ */
+int iio_update_buffers(struct iio_dev *indio_dev,
+                      struct iio_buffer *insert_buffer,
+                      struct iio_buffer *remove_buffer);
+
+/**
  * iio_buffer_init() - Initialize the buffer structure
  * @buffer:            buffer to be initialized
  **/
@@ -115,11 +129,11 @@ int iio_scan_mask_set(struct iio_dev *indio_dev,
                      struct iio_buffer *buffer, int bit);
 
 /**
- * iio_push_to_buffer() - push to a registered buffer.
- * @buffer:            IIO buffer structure for device
- * @data:              the data to push to the buffer
+ * iio_push_to_buffers() - push to a registered buffer.
+ * @indio_dev:         iio_dev structure for device.
+ * @data:              Full scan.
  */
-int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data);
+int iio_push_to_buffers(struct iio_dev *indio_dev, unsigned char *data);
 
 int iio_update_demux(struct iio_dev *indio_dev);
 
index 7806c24..adca93a 100644 (file)
@@ -410,6 +410,7 @@ struct iio_buffer_setup_ops {
  *                     and owner
  * @event_interface:   [INTERN] event chrdevs associated with interrupt lines
  * @buffer:            [DRIVER] any buffer present
+ * @buffer_list:       [INTERN] list of all buffers currently attached
  * @scan_bytes:                [INTERN] num bytes captured to be fed to buffer demux
  * @mlock:             [INTERN] lock used to prevent simultaneous device state
  *                     changes
@@ -448,6 +449,7 @@ struct iio_dev {
        struct iio_event_interface      *event_interface;
 
        struct iio_buffer               *buffer;
+       struct list_head                buffer_list;
        int                             scan_bytes;
        struct mutex                    mlock;