]> git.karo-electronics.de Git - linux-beck.git/commitdiff
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 314a4057879e6dc3e785a54f0baa1b7459d30f9e..a95cda0e387f6c2781fa663bd020211693671d57 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 b11f214779a2def29323c938c7dca736b99e087f..a6f4fc5f8201a414f653d86db92b7ef03a9c1705 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 7f2f45a0a48d086e62963af5a9f95de5bcf697b2..330248bfebaecffdf8b042738f64ff134a8a73f8 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 fd62309b4d3d23217ea7d165dba897f033b3c9b3..81153fafac7a928fa4f15cff0ba8dee55da026ec 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 67baa1363d7a026f5bdd48ed3fe4f72115ef5e7e..afe6d78c8ff0f6cf4dcb54727e2999749010bdba 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 2e2c9a80aa37c1eff8e124a1b09bb3e778107054..03b85940f4ba373ac9f2e907418e513d9374b264 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 4c56ada51c3958343df1e56913a0b3ca56cf1be6..02ef989b830d2d897ba580c8cc3c3305b06ba31b 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 722a83fd8d85a4b2bb8bd4fde7fc315627e43d5f..aaadd32f9f0d4da915d96c37fb33b52c6ef0febe 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 cd700368eed064e3fadb0da8c0e0dc9a2d99be2c..060a4045be85e00536f9a018524bcf03b3b72af6 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 164b62b91a4bbded4ee56bb8db645ad9b75e0ba9..36d210a06b28feb3284e67031ee60455b23b394b 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 96e3691e42c4970727f8240df40e8779aa9b0bd0..8e1f69844eea796da357ac67aded7959a7c70557 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 c4f0d274f577471b15fe0d5e8d3f60b3c63292fe..d1b5fb74b9bf1b92091287223f2cd0e8a28e5882 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 97c09f0c26aea3c4fb21b42cbe6413c0516deb06..e14ca60092a2fdf7e68a0be87439214d9ad9241c 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 7507e1a0459186f1b6e565704eecc8059821fde8..eba2e285c84a8fc6f4748f52ea2563e66c40c185 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 4c976bec986b7beadb5faccfd8fcaed3be94a898..3611a13836c9223d10ccc196f5213f0876fc8ce5 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 f939e29d6c82d515fa0157877d253a3fb6cf988a..6af9a5dbc7097003582bfef3222bef4844494065 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 caff8e25e0a2557cd181ed1995e3e53639c5c8ee..e2ac8a8c81071dc7c5d9091a4310d3a5023f3ec5 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 246352716537cf363cf456fd6dd802aa03e779b4..bc38651c315e6ca49943d0ab118706e794e023c8 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 c2906a85fedb355791a2dd0bb2dbae42275f2fd3..b3dd514b9627fc4f5a1c38ceea42dc3cdcde9387 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 ba04d0ffd4f49066aac2b04aa595ff88b16604ea..2b25cb07fe41d1470513424380de4ab439657191 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 86026d9b20bc604e5acb8643891d7ed34d62d44a..2c5f38475a8edfef700d924f110de25e35263fdd 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 5f74f3b7671af40c21bc6c3e14ca463eb41881c0..688304bdbaf0815452765b3c75e11bfc6cfcf2a8 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 df5bba284b73055d3b821e7d86eade25749db86b..3b467d8c588262d56dea61efbc1e08fc73853a2f 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 e294cb49736d05947a6024f909fc4d4af197d2e0..d6c48f850a9e65e699d0c617da06c5adb749fd96 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 697d9700db2f698619145363dc4b8a591d67fad4..dee16f0e7570bf1335479d3133a4d9d5007e4348 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 de21d47f33e91386969171eb024086659005bd06..b1fef147d5b50ae617bee5abd555eb869d0580b9 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 260bdd1a468174e0f2572b8a5743b93d2519c56d..d46c1e38cf7bd0df87c4d1b50ddd97f87a2a563e 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 9e49baccf660eb4d303859fc8166df6817b2326e..4552a4c7fe33b0d65d14d073abe5601781e9ff41 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 c629b3a1d9a95a22d81e7d7ed293fef5a43612e3..0270405691803339f143879cd6a1a7eb1b933141 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,8 +82,21 @@ 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 7806c24e5bc8173a004597a1dd266f8e14900de6..adca93a999a747329ed0e3aaa497f9eea4a3cdd9 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;