[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
  *
        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;
        }
                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);
 
                        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)
 }
 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);
 
        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);
  * 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)
 {
        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)
 {
        }
 }
 
-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;
 
        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);