Commit 84b36ce5 authored by Jonathan Cameron's avatar Jonathan Cameron

staging:iio: Add support for multiple buffers

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: default avatarJonathan Cameron <jic23@kernel.org>
Tested-by: default avatarsrinivas pandruvada <srinivas.pandruvada@intel.com>
parent 4eb3ccf1
...@@ -197,21 +197,8 @@ static const struct iio_info accel_3d_info = { ...@@ -197,21 +197,8 @@ static const struct iio_info accel_3d_info = {
/* Function to push data to buffer */ /* Function to push data to buffer */
static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len) 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"); dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
if (!buffer) { iio_push_to_buffers(indio_dev, (u8 *)data);
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);
} }
/* Callback handler to send event after all samples are received and captured */ /* Callback handler to send event after all samples are received and captured */
......
...@@ -91,7 +91,6 @@ static irqreturn_t ad7266_trigger_handler(int irq, void *p) ...@@ -91,7 +91,6 @@ static irqreturn_t ad7266_trigger_handler(int irq, void *p)
{ {
struct iio_poll_func *pf = p; struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev; struct iio_dev *indio_dev = pf->indio_dev;
struct iio_buffer *buffer = indio_dev->buffer;
struct ad7266_state *st = iio_priv(indio_dev); struct ad7266_state *st = iio_priv(indio_dev);
int ret; int ret;
...@@ -99,7 +98,7 @@ static irqreturn_t ad7266_trigger_handler(int irq, void *p) ...@@ -99,7 +98,7 @@ static irqreturn_t ad7266_trigger_handler(int irq, void *p)
if (ret == 0) { if (ret == 0) {
if (indio_dev->scan_timestamp) if (indio_dev->scan_timestamp)
((s64 *)st->data)[1] = pf->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); iio_trigger_notify_done(indio_dev->trig);
......
...@@ -76,7 +76,7 @@ static irqreturn_t ad7476_trigger_handler(int irq, void *p) ...@@ -76,7 +76,7 @@ static irqreturn_t ad7476_trigger_handler(int irq, void *p)
if (indio_dev->scan_timestamp) if (indio_dev->scan_timestamp)
((s64 *)st->data)[1] = time_ns; ((s64 *)st->data)[1] = time_ns;
iio_push_to_buffer(indio_dev->buffer, st->data); iio_push_to_buffers(indio_dev, st->data);
done: done:
iio_trigger_notify_done(indio_dev->trig); iio_trigger_notify_done(indio_dev->trig);
......
...@@ -134,7 +134,7 @@ static irqreturn_t ad7887_trigger_handler(int irq, void *p) ...@@ -134,7 +134,7 @@ static irqreturn_t ad7887_trigger_handler(int irq, void *p)
memcpy(st->data + indio_dev->scan_bytes - sizeof(s64), memcpy(st->data + indio_dev->scan_bytes - sizeof(s64),
&time_ns, sizeof(time_ns)); &time_ns, sizeof(time_ns));
iio_push_to_buffer(indio_dev->buffer, st->data); iio_push_to_buffers(indio_dev, st->data);
done: done:
iio_trigger_notify_done(indio_dev->trig); iio_trigger_notify_done(indio_dev->trig);
......
...@@ -391,7 +391,7 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p) ...@@ -391,7 +391,7 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
break; 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); iio_trigger_notify_done(indio_dev->trig);
sigma_delta->irq_dis = false; sigma_delta->irq_dis = false;
......
...@@ -65,7 +65,6 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p) ...@@ -65,7 +65,6 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p; struct iio_poll_func *pf = p;
struct iio_dev *idev = pf->indio_dev; struct iio_dev *idev = pf->indio_dev;
struct at91_adc_state *st = iio_priv(idev); struct at91_adc_state *st = iio_priv(idev);
struct iio_buffer *buffer = idev->buffer;
int i, j = 0; int i, j = 0;
for (i = 0; i < idev->masklength; i++) { for (i = 0; i < idev->masklength; i++) {
...@@ -81,7 +80,7 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p) ...@@ -81,7 +80,7 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
*timestamp = pf->timestamp; *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); iio_trigger_notify_done(idev->trig);
......
...@@ -197,21 +197,8 @@ static const struct iio_info gyro_3d_info = { ...@@ -197,21 +197,8 @@ static const struct iio_info gyro_3d_info = {
/* Function to push data to buffer */ /* Function to push data to buffer */
static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len) 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"); dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
if (!buffer) { iio_push_to_buffers(indio_dev, (u8 *)data);
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);
} }
/* Callback handler to send event after all samples are received and captured */ /* Callback handler to send event after all samples are received and captured */
......
...@@ -31,6 +31,18 @@ static const char * const iio_endian_prefix[] = { ...@@ -31,6 +31,18 @@ static const char * const iio_endian_prefix[] = {
[IIO_LE] = "le", [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 * 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, ...@@ -134,7 +146,7 @@ static ssize_t iio_scan_el_store(struct device *dev,
if (ret < 0) if (ret < 0)
return ret; return ret;
mutex_lock(&indio_dev->mlock); mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev)) { if (iio_buffer_is_active(indio_dev, indio_dev->buffer)) {
ret = -EBUSY; ret = -EBUSY;
goto error_ret; goto error_ret;
} }
...@@ -180,12 +192,11 @@ static ssize_t iio_scan_el_ts_store(struct device *dev, ...@@ -180,12 +192,11 @@ static ssize_t iio_scan_el_ts_store(struct device *dev,
return ret; return ret;
mutex_lock(&indio_dev->mlock); mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev)) { if (iio_buffer_is_active(indio_dev, indio_dev->buffer)) {
ret = -EBUSY; ret = -EBUSY;
goto error_ret; goto error_ret;
} }
indio_dev->buffer->scan_timestamp = state; indio_dev->buffer->scan_timestamp = state;
indio_dev->scan_timestamp = state;
error_ret: error_ret:
mutex_unlock(&indio_dev->mlock); mutex_unlock(&indio_dev->mlock);
...@@ -385,7 +396,7 @@ ssize_t iio_buffer_write_length(struct device *dev, ...@@ -385,7 +396,7 @@ ssize_t iio_buffer_write_length(struct device *dev,
return len; return len;
mutex_lock(&indio_dev->mlock); mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev)) { if (iio_buffer_is_active(indio_dev, indio_dev->buffer)) {
ret = -EBUSY; ret = -EBUSY;
} else { } else {
if (buffer->access->set_length) if (buffer->access->set_length)
...@@ -398,102 +409,14 @@ ssize_t iio_buffer_write_length(struct device *dev, ...@@ -398,102 +409,14 @@ ssize_t iio_buffer_write_length(struct device *dev,
} }
EXPORT_SYMBOL(iio_buffer_write_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, ssize_t iio_buffer_show_enable(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct iio_dev *indio_dev = dev_to_iio_dev(dev); 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); EXPORT_SYMBOL(iio_buffer_show_enable);
...@@ -537,35 +460,220 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const long *mask, ...@@ -537,35 +460,220 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const long *mask,
return bytes; 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; int ret;
dev_dbg(&indio_dev->dev, "%s\n", __func__); int success = 0;
struct iio_buffer *buffer;
unsigned long *compound_mask;
const unsigned long *old_mask;
/* How much space will the demuxed element take? */ /* Wind down existing buffers - iff there are any */
indio_dev->scan_bytes = if (!list_empty(&indio_dev->buffer_list)) {
iio_compute_scan_bytes(indio_dev, buffer->scan_mask, if (indio_dev->setup_ops->predisable) {
buffer->scan_timestamp); ret = indio_dev->setup_ops->predisable(indio_dev);
buffer->access->set_bytes_per_datum(buffer, indio_dev->scan_bytes); 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 ?*/ /* 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 = indio_dev->active_scan_mask =
iio_scan_mask_match(indio_dev->available_scan_masks, iio_scan_mask_match(indio_dev->available_scan_masks,
indio_dev->masklength, indio_dev->masklength,
buffer->scan_mask); compound_mask);
else if (indio_dev->active_scan_mask == NULL) {
indio_dev->active_scan_mask = buffer->scan_mask; /*
* Roll back.
if (indio_dev->active_scan_mask == NULL) * Note can only occur when adding a buffer.
return -EINVAL; */
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); iio_update_demux(indio_dev);
if (indio_dev->info->update_scan_mode) /* Wind up again */
return indio_dev->info 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, ->update_scan_mode(indio_dev,
indio_dev->active_scan_mask); 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; return 0;
} }
EXPORT_SYMBOL(iio_sw_buffer_preenable); EXPORT_SYMBOL(iio_sw_buffer_preenable);
...@@ -599,7 +707,11 @@ static bool iio_validate_scan_mask(struct iio_dev *indio_dev, ...@@ -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 * iio_scan_mask_set() - set particular bit in the scan mask
* @buffer: the buffer whose scan mask we are interested in * @buffer: the buffer whose scan mask we are interested in
* @bit: the bit to be set. * @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, int iio_scan_mask_set(struct iio_dev *indio_dev,
struct iio_buffer *buffer, int bit) struct iio_buffer *buffer, int bit)
{ {
...@@ -682,13 +794,12 @@ static unsigned char *iio_demux(struct iio_buffer *buffer, ...@@ -682,13 +794,12 @@ static unsigned char *iio_demux(struct iio_buffer *buffer,
return buffer->demux_bounce; 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); unsigned char *dataout = iio_demux(buffer, data);
return buffer->access->store_to(buffer, dataout); return buffer->access->store_to(buffer, dataout);
} }
EXPORT_SYMBOL_GPL(iio_push_to_buffer);
static void iio_buffer_demux_free(struct iio_buffer *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) ...@@ -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; const struct iio_chan_spec *ch;
struct iio_buffer *buffer = indio_dev->buffer;
int ret, in_ind = -1, out_ind, length; int ret, in_ind = -1, out_ind, length;
unsigned in_loc = 0, out_loc = 0; unsigned in_loc = 0, out_loc = 0;
struct iio_demux_table *p; struct iio_demux_table *p;
...@@ -787,4 +914,23 @@ int iio_update_demux(struct iio_dev *indio_dev) ...@@ -787,4 +914,23 @@ int iio_update_demux(struct iio_dev *indio_dev)
return ret; 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); EXPORT_SYMBOL_GPL(iio_update_demux);
...@@ -856,6 +856,7 @@ struct iio_dev *iio_device_alloc(int sizeof_priv) ...@@ -856,6 +856,7 @@ struct iio_dev *iio_device_alloc(int sizeof_priv)
return NULL; return NULL;
} }
dev_set_name(&dev->dev, "iio:device%d", dev->id); dev_set_name(&dev->dev, "iio:device%d", dev->id);
INIT_LIST_HEAD(&dev->buffer_list);
} }
return dev; return dev;
......
...@@ -164,7 +164,6 @@ static irqreturn_t adjd_s311_trigger_handler(int irq, void *p) ...@@ -164,7 +164,6 @@ static irqreturn_t adjd_s311_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p; struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev; struct iio_dev *indio_dev = pf->indio_dev;
struct adjd_s311_data *data = iio_priv(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(); s64 time_ns = iio_get_time_ns();
int len = 0; int len = 0;
int i, j = 0; int i, j = 0;
...@@ -187,7 +186,7 @@ static irqreturn_t adjd_s311_trigger_handler(int irq, void *p) ...@@ -187,7 +186,7 @@ static irqreturn_t adjd_s311_trigger_handler(int irq, void *p)
if (indio_dev->scan_timestamp) if (indio_dev->scan_timestamp)
*(s64 *)((u8 *)data->buffer + ALIGN(len, sizeof(s64))) *(s64 *)((u8 *)data->buffer + ALIGN(len, sizeof(s64)))
= time_ns; = time_ns;
iio_push_to_buffer(buffer, (u8 *)data->buffer); iio_push_to_buffers(indio_dev, (u8 *)data->buffer);
done: done:
iio_trigger_notify_done(indio_dev->trig); iio_trigger_notify_done(indio_dev->trig);
......
...@@ -176,21 +176,8 @@ static const struct iio_info als_info = { ...@@ -176,21 +176,8 @@ static const struct iio_info als_info = {
/* Function to push data to buffer */ /* Function to push data to buffer */
static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len) 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"); dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
if (!buffer) { iio_push_to_buffers(indio_dev, (u8 *)data);
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);
} }
/* Callback handler to send event after all samples are received and captured */ /* Callback handler to send event after all samples are received and captured */
......
...@@ -198,21 +198,8 @@ static const struct iio_info magn_3d_info = { ...@@ -198,21 +198,8 @@ static const struct iio_info magn_3d_info = {
/* Function to push data to buffer */ /* Function to push data to buffer */
static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len) 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"); dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
if (!buffer) { iio_push_to_buffers(indio_dev, (u8 *)data);
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);
} }
/* Callback handler to send event after all samples are received and captured */ /* Callback handler to send event after all samples are received and captured */
......
...@@ -82,7 +82,7 @@ static irqreturn_t adis16201_trigger_handler(int irq, void *p) ...@@ -82,7 +82,7 @@ static irqreturn_t adis16201_trigger_handler(int irq, void *p)
if (indio_dev->scan_timestamp) if (indio_dev->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = pf->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); kfree(data);
done: done:
......
...@@ -81,7 +81,7 @@ static irqreturn_t adis16203_trigger_handler(int irq, void *p) ...@@ -81,7 +81,7 @@ static irqreturn_t adis16203_trigger_handler(int irq, void *p)
if (indio_dev->scan_timestamp) if (indio_dev->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = pf->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); kfree(data);
done: done:
......
...@@ -78,7 +78,7 @@ static irqreturn_t adis16204_trigger_handler(int irq, void *p) ...@@ -78,7 +78,7 @@ static irqreturn_t adis16204_trigger_handler(int irq, void *p)
if (indio_dev->scan_timestamp) if (indio_dev->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = pf->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); kfree(data);
done: done:
......
...@@ -78,7 +78,7 @@ static irqreturn_t adis16209_trigger_handler(int irq, void *p) ...@@ -78,7 +78,7 @@ static irqreturn_t adis16209_trigger_handler(int irq, void *p)
if (indio_dev->scan_timestamp) if (indio_dev->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = pf->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); kfree(data);
done: done:
......
...@@ -76,7 +76,7 @@ static irqreturn_t adis16240_trigger_handler(int irq, void *p) ...@@ -76,7 +76,7 @@ static irqreturn_t adis16240_trigger_handler(int irq, void *p)
if (indio_dev->scan_timestamp) if (indio_dev->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = pf->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); kfree(data);
done: done:
......
...@@ -154,7 +154,7 @@ static irqreturn_t lis3l02dq_trigger_handler(int irq, void *p) ...@@ -154,7 +154,7 @@ static irqreturn_t lis3l02dq_trigger_handler(int irq, void *p)
if (indio_dev->scan_timestamp) if (indio_dev->scan_timestamp)
*(s64 *)((u8 *)data + ALIGN(len, sizeof(s64))) *(s64 *)((u8 *)data + ALIGN(len, sizeof(s64)))
= pf->timestamp; = pf->timestamp;
iio_push_to_buffer(indio_dev->buffer, (u8 *)data); iio_push_to_buffers(indio_dev, (u8 *)data);
kfree(data); kfree(data);
done: done:
......
...@@ -93,7 +93,7 @@ static irqreturn_t ad7298_trigger_handler(int irq, void *p) ...@@ -93,7 +93,7 @@ static irqreturn_t ad7298_trigger_handler(int irq, void *p)
indio_dev->masklength); i++) indio_dev->masklength); i++)
buf[i] = be16_to_cpu(st->rx_buf[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: done:
iio_trigger_notify_done(indio_dev->trig); iio_trigger_notify_done(indio_dev->trig);
......
...@@ -83,7 +83,7 @@ static void ad7606_poll_bh_to_ring(struct work_struct *work_s) ...@@ -83,7 +83,7 @@ static void ad7606_poll_bh_to_ring(struct work_struct *work_s)
if (indio_dev->scan_timestamp) if (indio_dev->scan_timestamp)
*((s64 *)(buf + indio_dev->scan_bytes - sizeof(s64))) = time_ns; *((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: done:
gpio_set_value(st->pdata->gpio_convst, 0); gpio_set_value(st->pdata->gpio_convst, 0);
iio_trigger_notify_done(indio_dev->trig); iio_trigger_notify_done(indio_dev->trig);
......
...@@ -77,7 +77,7 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p) ...@@ -77,7 +77,7 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p)
memcpy(rxbuf + indio_dev->scan_bytes - sizeof(s64), memcpy(rxbuf + indio_dev->scan_bytes - sizeof(s64),
&time_ns, sizeof(time_ns)); &time_ns, sizeof(time_ns));
iio_push_to_buffer(indio_dev->buffer, rxbuf); iio_push_to_buffers(indio_dev, rxbuf);
done: done:
kfree(rxbuf); kfree(rxbuf);
out: out:
......
...@@ -80,7 +80,7 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p) ...@@ -80,7 +80,7 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p)
if (indio_dev->scan_timestamp) if (indio_dev->scan_timestamp)
memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns)); 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: done_free:
kfree(rxbuf); kfree(rxbuf);
......
...@@ -237,7 +237,6 @@ static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p) ...@@ -237,7 +237,6 @@ static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p; struct iio_poll_func *pf = p;
struct iio_dev *iio = pf->indio_dev; struct iio_dev *iio = pf->indio_dev;
struct mxs_lradc *lradc = iio_priv(iio); struct mxs_lradc *lradc = iio_priv(iio);
struct iio_buffer *buffer = iio->buffer;
const uint32_t chan_value = LRADC_CH_ACCUMULATE | const uint32_t chan_value = LRADC_CH_ACCUMULATE |
((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET); ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET);
int i, j = 0; int i, j = 0;
...@@ -256,7 +255,7 @@ static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p) ...@@ -256,7 +255,7 @@ static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p)
*timestamp = pf->timestamp; *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); iio_trigger_notify_done(iio->trig);
......
...@@ -81,7 +81,7 @@ static irqreturn_t adis16260_trigger_handler(int irq, void *p) ...@@ -81,7 +81,7 @@ static irqreturn_t adis16260_trigger_handler(int irq, void *p)
if (indio_dev->scan_timestamp) if (indio_dev->scan_timestamp)
*((s64 *)(data + ((i + 3)/4)*4)) = pf->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); kfree(data);
done: done:
......
...@@ -46,7 +46,6 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p) ...@@ -46,7 +46,6 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
{ {
struct iio_poll_func *pf = p; struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev; struct iio_dev *indio_dev = pf->indio_dev;
struct iio_buffer *buffer = indio_dev->buffer;
int len = 0; int len = 0;
u16 *data; u16 *data;
...@@ -76,7 +75,7 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p) ...@@ -76,7 +75,7 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
i < bitmap_weight(indio_dev->active_scan_mask, i < bitmap_weight(indio_dev->active_scan_mask,
indio_dev->masklength); indio_dev->masklength);
i++, j++) { i++, j++) {
j = find_next_bit(buffer->scan_mask, j = find_next_bit(indio_dev->active_scan_mask,
indio_dev->masklength, j); indio_dev->masklength, j);
/* random access read from the 'device' */ /* random access read from the 'device' */
data[i] = fakedata[j]; data[i] = fakedata[j];
...@@ -87,7 +86,7 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p) ...@@ -87,7 +86,7 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
if (indio_dev->scan_timestamp) if (indio_dev->scan_timestamp)
*(s64 *)((u8 *)data + ALIGN(len, sizeof(s64))) *(s64 *)((u8 *)data + ALIGN(len, sizeof(s64)))
= iio_get_time_ns(); = iio_get_time_ns();
iio_push_to_buffer(buffer, (u8 *)data); iio_push_to_buffers(indio_dev, (u8 *)data);
kfree(data); kfree(data);
......
...@@ -647,7 +647,6 @@ static void ad5933_work(struct work_struct *work) ...@@ -647,7 +647,6 @@ static void ad5933_work(struct work_struct *work)
struct ad5933_state *st = container_of(work, struct ad5933_state *st = container_of(work,
struct ad5933_state, work.work); struct ad5933_state, work.work);
struct iio_dev *indio_dev = i2c_get_clientdata(st->client); struct iio_dev *indio_dev = i2c_get_clientdata(st->client);
struct iio_buffer *ring = indio_dev->buffer;
signed short buf[2]; signed short buf[2];
unsigned char status; unsigned char status;
...@@ -677,8 +676,7 @@ static void ad5933_work(struct work_struct *work) ...@@ -677,8 +676,7 @@ static void ad5933_work(struct work_struct *work)
} else { } else {
buf[0] = be16_to_cpu(buf[0]); buf[0] = be16_to_cpu(buf[0]);
} }
/* save datum to the ring */ iio_push_to_buffers(indio_dev, (u8 *)buf);
iio_push_to_buffer(ring, (u8 *)buf);
} else { } else {
/* no data available - try again later */ /* no data available - try again later */
schedule_delayed_work(&st->work, st->poll_time_jiffies); schedule_delayed_work(&st->work, st->poll_time_jiffies);
......
...@@ -114,7 +114,6 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p) ...@@ -114,7 +114,6 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p; struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev; struct iio_dev *indio_dev = pf->indio_dev;
struct adis16400_state *st = iio_priv(indio_dev); struct adis16400_state *st = iio_priv(indio_dev);
struct iio_buffer *ring = indio_dev->buffer;
int i = 0, j, ret = 0; int i = 0, j, ret = 0;
s16 *data; s16 *data;
...@@ -148,9 +147,9 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p) ...@@ -148,9 +147,9 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p)
} }
} }
/* Guaranteed to be aligned with 8 byte boundary */ /* 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; *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
iio_push_to_buffer(ring, (u8 *) data); iio_push_to_buffers(indio_dev, (u8 *) data);
done: done:
kfree(data); kfree(data);
......
...@@ -73,7 +73,7 @@ static irqreturn_t ade7758_trigger_handler(int irq, void *p) ...@@ -73,7 +73,7 @@ static irqreturn_t ade7758_trigger_handler(int irq, void *p)
if (indio_dev->scan_timestamp) if (indio_dev->scan_timestamp)
dat64[1] = pf->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); iio_trigger_notify_done(indio_dev->trig);
......
...@@ -66,7 +66,8 @@ struct iio_buffer_access_funcs { ...@@ -66,7 +66,8 @@ struct iio_buffer_access_funcs {
* @stufftoread: [INTERN] flag to indicate new data. * @stufftoread: [INTERN] flag to indicate new data.
* @demux_list: [INTERN] list of operations required to demux the scan. * @demux_list: [INTERN] list of operations required to demux the scan.
* @demux_bounce: [INTERN] buffer for doing gather from incoming 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 { struct iio_buffer {
int length; int length;
int bytes_per_datum; int bytes_per_datum;
...@@ -81,8 +82,21 @@ struct iio_buffer { ...@@ -81,8 +82,21 @@ struct iio_buffer {
const struct attribute_group *attrs; const struct attribute_group *attrs;
struct list_head demux_list; struct list_head demux_list;
unsigned char *demux_bounce; 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 * iio_buffer_init() - Initialize the buffer structure
* @buffer: buffer to be initialized * @buffer: buffer to be initialized
...@@ -115,11 +129,11 @@ int iio_scan_mask_set(struct iio_dev *indio_dev, ...@@ -115,11 +129,11 @@ int iio_scan_mask_set(struct iio_dev *indio_dev,
struct iio_buffer *buffer, int bit); struct iio_buffer *buffer, int bit);
/** /**
* iio_push_to_buffer() - push to a registered buffer. * iio_push_to_buffers() - push to a registered buffer.
* @buffer: IIO buffer structure for device * @indio_dev: iio_dev structure for device.
* @data: the data to push to the buffer * @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); int iio_update_demux(struct iio_dev *indio_dev);
......
...@@ -410,6 +410,7 @@ struct iio_buffer_setup_ops { ...@@ -410,6 +410,7 @@ struct iio_buffer_setup_ops {
* and owner * and owner
* @event_interface: [INTERN] event chrdevs associated with interrupt lines * @event_interface: [INTERN] event chrdevs associated with interrupt lines
* @buffer: [DRIVER] any buffer present * @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 * @scan_bytes: [INTERN] num bytes captured to be fed to buffer demux
* @mlock: [INTERN] lock used to prevent simultaneous device state * @mlock: [INTERN] lock used to prevent simultaneous device state
* changes * changes
...@@ -448,6 +449,7 @@ struct iio_dev { ...@@ -448,6 +449,7 @@ struct iio_dev {
struct iio_event_interface *event_interface; struct iio_event_interface *event_interface;
struct iio_buffer *buffer; struct iio_buffer *buffer;
struct list_head buffer_list;
int scan_bytes; int scan_bytes;
struct mutex mlock; struct mutex mlock;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment