All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/7] Add scan demux unit and use it in max1363
@ 2011-11-27 13:10 Jonathan Cameron
  2011-11-27 13:10 ` [PATCH 1/7] staging:iio:find iio channel from scan index util function Jonathan Cameron
                   ` (6 more replies)
  0 siblings, 7 replies; 14+ messages in thread
From: Jonathan Cameron @ 2011-11-27 13:10 UTC (permalink / raw)
  To: linux-iio; +Cc: lars, Michael.Hennerich, Jonathan Cameron

The last patch technically is a simple bug fix, but included here as
it came up during testing of this series.

The 'interesting' bits are the rewrite of iio_sw_buffer_preenable. I'd like
people with drivers currently using that function to test and see what
I have broken.  We should also be able to drop a number of cases in specific
drivers in favour of this version.

The demux unit is designed to offer a straight path with little or no
overhead if the client (here still the IIO buffer) needs all the data and to
only get in the way when a subset of the active scan mask is requested.

I may well have messed this up so please please test this set.

Thanks,

Jonathan

Jonathan Cameron (7):
  staging:iio:find iio channel from scan index util function
  staging:iio:buffer add a cache of the timestamp scan index.
  staging:iio: add hook to allow core to perform scan related config.
  staging:iio: make iio_sw_buffer_preenable much more general.
  staging:iio: add demux optionally to path from device to buffer
  staging:iio:adc:max1363 use new demuxing support.
  staging:iio:adc:max1363 correctly set channels as big endian.

 drivers/staging/iio/adc/max1363.h         |   11 ++-
 drivers/staging/iio/adc/max1363_core.c    |   18 ++-
 drivers/staging/iio/adc/max1363_ring.c    |   51 ++-----
 drivers/staging/iio/buffer.h              |   16 ++
 drivers/staging/iio/iio.h                 |   13 ++-
 drivers/staging/iio/industrialio-buffer.c |  216 +++++++++++++++++++++++++----
 drivers/staging/iio/industrialio-core.c   |   11 ++
 7 files changed, 263 insertions(+), 73 deletions(-)

-- 
1.7.7.3

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/7] staging:iio:find iio channel from scan index util function
  2011-11-27 13:10 [PATCH 0/7] Add scan demux unit and use it in max1363 Jonathan Cameron
@ 2011-11-27 13:10 ` Jonathan Cameron
  2011-11-27 13:10 ` [PATCH 2/7] staging:iio:buffer add a cache of the timestamp scan index Jonathan Cameron
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: Jonathan Cameron @ 2011-11-27 13:10 UTC (permalink / raw)
  To: linux-iio; +Cc: lars, Michael.Hennerich, Jonathan Cameron

From: Jonathan Cameron <jic23@cam.ac.uk>

Useful for getting to the channel based on scan mask alone.

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/iio.h               |    8 ++++++++
 drivers/staging/iio/industrialio-core.c |   11 +++++++++++
 2 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h
index 4aed915..95d6318 100644
--- a/drivers/staging/iio/iio.h
+++ b/drivers/staging/iio/iio.h
@@ -323,6 +323,14 @@ struct iio_dev {
 };
 
 /**
+ * iio_find_channel_from_si() - get channel from its scan index
+ * @indio_dev:		device
+ * @si:			scan index to match
+ */
+const struct iio_chan_spec
+*iio_find_channel_from_si(struct iio_dev *indio_dev, int si);
+
+/**
  * iio_device_register() - register a device with the IIO subsystem
  * @indio_dev:		Device structure filled by the device driver
  **/
diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c
index 55c0b48..3754b85 100644
--- a/drivers/staging/iio/industrialio-core.c
+++ b/drivers/staging/iio/industrialio-core.c
@@ -89,6 +89,17 @@ static const char * const iio_chan_info_postfix[] = {
 	= "filter_low_pass_3db_frequency",
 };
 
+const struct iio_chan_spec
+*iio_find_channel_from_si(struct iio_dev *indio_dev, int si)
+{
+	int i;
+
+	for (i = 0; i < indio_dev->num_channels; i++)
+		if (indio_dev->channels[i].scan_index == si)
+			return &indio_dev->channels[i];
+	return NULL;
+}
+
 /**
  * struct iio_detected_event_list - list element for events that have occurred
  * @list:		linked list header
-- 
1.7.7.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/7] staging:iio:buffer add a cache of the timestamp scan index.
  2011-11-27 13:10 [PATCH 0/7] Add scan demux unit and use it in max1363 Jonathan Cameron
  2011-11-27 13:10 ` [PATCH 1/7] staging:iio:find iio channel from scan index util function Jonathan Cameron
@ 2011-11-27 13:10 ` Jonathan Cameron
  2011-11-27 13:10 ` [PATCH 3/7] staging:iio: add hook to allow core to perform scan related config Jonathan Cameron
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: Jonathan Cameron @ 2011-11-27 13:10 UTC (permalink / raw)
  To: linux-iio; +Cc: lars, Michael.Hennerich, Jonathan Cameron

From: Jonathan Cameron <jic23@cam.ac.uk>

Basically avoids looking it up lots of times.

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/buffer.h              |    1 +
 drivers/staging/iio/industrialio-buffer.c |    3 +++
 2 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/iio/buffer.h b/drivers/staging/iio/buffer.h
index 9de581e..4b8f619 100644
--- a/drivers/staging/iio/buffer.h
+++ b/drivers/staging/iio/buffer.h
@@ -106,6 +106,7 @@ struct iio_buffer {
 	int					scan_count;
 	long					*scan_mask;
 	bool					scan_timestamp;
+	unsigned				scan_index_timestamp;
 	const struct iio_buffer_access_funcs	*access;
 	const struct iio_buffer_setup_ops		*setup_ops;
 	struct list_head			scan_el_dev_attr_list;
diff --git a/drivers/staging/iio/industrialio-buffer.c b/drivers/staging/iio/industrialio-buffer.c
index f757bb7..cae7922 100644
--- a/drivers/staging/iio/industrialio-buffer.c
+++ b/drivers/staging/iio/industrialio-buffer.c
@@ -313,6 +313,9 @@ int iio_buffer_register(struct iio_dev *indio_dev,
 			if (ret < 0)
 				goto error_cleanup_dynamic;
 			attrcount += ret;
+			if (channels[i].type == IIO_TIMESTAMP)
+				buffer->scan_index_timestamp =
+					channels[i].scan_index;
 		}
 		if (indio_dev->masklength && buffer->scan_mask == NULL) {
 			buffer->scan_mask
-- 
1.7.7.3


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 3/7] staging:iio: add hook to allow core to perform scan related config.
  2011-11-27 13:10 [PATCH 0/7] Add scan demux unit and use it in max1363 Jonathan Cameron
  2011-11-27 13:10 ` [PATCH 1/7] staging:iio:find iio channel from scan index util function Jonathan Cameron
  2011-11-27 13:10 ` [PATCH 2/7] staging:iio:buffer add a cache of the timestamp scan index Jonathan Cameron
@ 2011-11-27 13:10 ` Jonathan Cameron
  2011-11-27 13:10 ` [PATCH 4/7] staging:iio: make iio_sw_buffer_preenable much more general Jonathan Cameron
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: Jonathan Cameron @ 2011-11-27 13:10 UTC (permalink / raw)
  To: linux-iio; +Cc: lars, Michael.Hennerich, Jonathan Cameron

Signed-off-by: Jonathan Cameron <jic23@kernel.org>
---
 drivers/staging/iio/iio.h |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h
index 95d6318..4fb8f2f 100644
--- a/drivers/staging/iio/iio.h
+++ b/drivers/staging/iio/iio.h
@@ -262,7 +262,8 @@ struct iio_info {
 				 int val);
 	int (*validate_trigger)(struct iio_dev *indio_dev,
 				struct iio_trigger *trig);
-
+	int (*update_scan_mode)(struct iio_dev *indio_dev,
+				const unsigned long *scan_mask);
 };
 
 /**
-- 
1.7.7.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 4/7] staging:iio: make iio_sw_buffer_preenable much more general.
  2011-11-27 13:10 [PATCH 0/7] Add scan demux unit and use it in max1363 Jonathan Cameron
                   ` (2 preceding siblings ...)
  2011-11-27 13:10 ` [PATCH 3/7] staging:iio: add hook to allow core to perform scan related config Jonathan Cameron
@ 2011-11-27 13:10 ` Jonathan Cameron
  2011-11-28  9:23   ` Lars-Peter Clausen
  2011-11-27 13:10 ` [PATCH 5/7] staging:iio: add demux optionally to path from device to buffer Jonathan Cameron
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 14+ messages in thread
From: Jonathan Cameron @ 2011-11-27 13:10 UTC (permalink / raw)
  To: linux-iio; +Cc: lars, Michael.Hennerich, Jonathan Cameron

Also introduces active_scan_mask storage to tell the core what is
really being currently captured from the device (different from
what is desired as often has bonus channels).

Signed-off-by: Jonathan Cameron <jic23@kernel.org>
---
 drivers/staging/iio/iio.h                 |    2 +
 drivers/staging/iio/industrialio-buffer.c |   65 +++++++++++++++++-----------
 2 files changed, 41 insertions(+), 26 deletions(-)

diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h
index 4fb8f2f..c225542 100644
--- a/drivers/staging/iio/iio.h
+++ b/drivers/staging/iio/iio.h
@@ -280,6 +280,7 @@ struct iio_info {
  * @available_scan_masks: [DRIVER] optional array of allowed bitmasks
  * @masklength:		[INTERN] the length of the mask established from
  *			channels
+ * @active_scan_mask:	[INTERN] union of all scan masks requested by buffers
  * @trig:		[INTERN] current device trigger (buffer modes)
  * @pollfunc:		[DRIVER] function run on trigger being received
  * @channels:		[DRIVER] channel specification structure table
@@ -307,6 +308,7 @@ struct iio_dev {
 
 	unsigned long			*available_scan_masks;
 	unsigned			masklength;
+	unsigned long			*active_scan_mask;
 	struct iio_trigger		*trig;
 	struct iio_poll_func		*pollfunc;
 
diff --git a/drivers/staging/iio/industrialio-buffer.c b/drivers/staging/iio/industrialio-buffer.c
index cae7922..fb14e37 100644
--- a/drivers/staging/iio/industrialio-buffer.c
+++ b/drivers/staging/iio/industrialio-buffer.c
@@ -533,32 +533,6 @@ ssize_t iio_buffer_show_enable(struct device *dev,
 }
 EXPORT_SYMBOL(iio_buffer_show_enable);
 
-int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
-{
-	struct iio_buffer *buffer = indio_dev->buffer;
-	size_t size;
-	dev_dbg(&indio_dev->dev, "%s\n", __func__);
-	/* Check if there are any scan elements enabled, if not fail*/
-	if (!(buffer->scan_count || buffer->scan_timestamp))
-		return -EINVAL;
-	if (buffer->scan_timestamp)
-		if (buffer->scan_count)
-			/* Timestamp (aligned to s64) and data */
-			size = (((buffer->scan_count * buffer->bpe)
-					+ sizeof(s64) - 1)
-				& ~(sizeof(s64) - 1))
-				+ sizeof(s64);
-		else /* Timestamp only  */
-			size = sizeof(s64);
-	else /* Data only */
-		size = buffer->scan_count * buffer->bpe;
-	buffer->access->set_bytes_per_datum(buffer, size);
-
-	return 0;
-}
-EXPORT_SYMBOL(iio_sw_buffer_preenable);
-
-
 /* note NULL used as error indicator as it doesn't make sense. */
 static unsigned long *iio_scan_mask_match(unsigned long *av_masks,
 					  unsigned int masklength,
@@ -574,6 +548,45 @@ static unsigned long *iio_scan_mask_match(unsigned long *av_masks,
 	return NULL;
 }
 
+int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
+{
+	struct iio_buffer *buffer = indio_dev->buffer;
+	const struct iio_chan_spec *ch;
+	unsigned bytes = 0;
+	int length, i;
+	dev_dbg(&indio_dev->dev, "%s\n", __func__);
+
+	/* How much space will the demuxed element take? */
+	for_each_set_bit(i, buffer->scan_mask,
+			 indio_dev->masklength) {
+		ch = iio_find_channel_from_si(indio_dev, i);
+		length = ch->scan_type.storagebits/8;
+		if (bytes % length)
+			bytes += length - bytes % length;
+		bytes += length;
+	}
+	if (buffer->scan_timestamp) {
+		ch = iio_find_channel_from_si(indio_dev,
+					      buffer->scan_index_timestamp);
+		length = ch->scan_type.storagebits/8;
+		if (bytes % length)
+			bytes += length - bytes % length;
+		bytes += length;
+	}
+	buffer->access->set_bytes_per_datum(buffer, bytes);
+
+	/* What scan mask do we actually have ?*/
+	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;
+	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
-- 
1.7.7.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 5/7] staging:iio: add demux optionally to path from device to buffer
  2011-11-27 13:10 [PATCH 0/7] Add scan demux unit and use it in max1363 Jonathan Cameron
                   ` (3 preceding siblings ...)
  2011-11-27 13:10 ` [PATCH 4/7] staging:iio: make iio_sw_buffer_preenable much more general Jonathan Cameron
@ 2011-11-27 13:10 ` Jonathan Cameron
  2011-11-28  9:39   ` Lars-Peter Clausen
  2011-11-27 13:10 ` [PATCH 6/7] staging:iio:adc:max1363 use new demuxing support Jonathan Cameron
  2011-11-27 13:10 ` [PATCH 7/7] staging:iio:adc:max1363 correctly set channels as big endian Jonathan Cameron
  6 siblings, 1 reply; 14+ messages in thread
From: Jonathan Cameron @ 2011-11-27 13:10 UTC (permalink / raw)
  To: linux-iio; +Cc: lars, Michael.Hennerich, Jonathan Cameron

From: Jonathan Cameron <jic23@cam.ac.uk>

This gives you only what you ask for which is handy
for some devices with weird scan combinations.

Routes all data flow through a core utility function.
That and this demuxing support will be needed to do
demuxing to multiple destinations in kernel.

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/buffer.h              |   15 +++
 drivers/staging/iio/industrialio-buffer.c |  148 ++++++++++++++++++++++++++++-
 2 files changed, 159 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/iio/buffer.h b/drivers/staging/iio/buffer.h
index 4b8f619..5282441 100644
--- a/drivers/staging/iio/buffer.h
+++ b/drivers/staging/iio/buffer.h
@@ -95,6 +95,8 @@ struct iio_buffer_setup_ops {
  * @access:		[DRIVER] buffer access functions associated with the
  *			implementation.
  * @flags:		[INTERN] file ops related flags including busy flag.
+ * @demux_list:		[INTERN] list of operations required to demux the scan.
+ * @demux_bounce:	[INTERN] buffer for doing gather from incoming scan.
  **/
 struct iio_buffer {
 	struct iio_dev				*indio_dev;
@@ -115,6 +117,8 @@ struct iio_buffer {
 	bool					stufftoread;
 	unsigned long				flags;
 	const struct attribute_group *attrs;
+	struct list_head			demux_list;
+	unsigned char				*demux_bounce;
 };
 
 /**
@@ -153,6 +157,17 @@ int iio_scan_mask_set(struct iio_buffer *buffer, int bit);
 	container_of(d, struct iio_buffer, dev)
 
 /**
+ * iio_push_to_buffer() - push to a registered buffer.
+ * @buffer:		IIO buffer structure for device
+ * @scan:		Full scan.
+ * @timestamp:
+ */
+int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data,
+		       s64 timestamp);
+
+int iio_update_demux(struct iio_dev *indio_dev);
+
+/**
  * iio_buffer_register() - register the buffer with IIO core
  * @indio_dev: device with the buffer to be registered
  **/
diff --git a/drivers/staging/iio/industrialio-buffer.c b/drivers/staging/iio/industrialio-buffer.c
index fb14e37..352f9f1 100644
--- a/drivers/staging/iio/industrialio-buffer.c
+++ b/drivers/staging/iio/industrialio-buffer.c
@@ -87,6 +87,7 @@ void iio_chrdev_buffer_release(struct iio_dev *indio_dev)
 
 void iio_buffer_init(struct iio_buffer *buffer, struct iio_dev *indio_dev)
 {
+	INIT_LIST_HEAD(&buffer->demux_list);
 	buffer->indio_dev = indio_dev;
 	init_waitqueue_head(&buffer->pollq);
 }
@@ -128,10 +129,9 @@ static ssize_t iio_scan_el_show(struct device *dev,
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 
-	ret = iio_scan_mask_query(indio_dev->buffer,
-				  to_iio_dev_attr(attr)->address);
-	if (ret < 0)
-		return ret;
+	ret = test_bit(to_iio_dev_attr(attr)->address,
+		       indio_dev->buffer->scan_mask);
+
 	return sprintf(buf, "%d\n", ret);
 }
 
@@ -583,6 +583,12 @@ int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
 					    buffer->scan_mask);
 	else
 		indio_dev->active_scan_mask = buffer->scan_mask;
+	iio_update_demux(indio_dev);
+
+	if (indio_dev->info->update_scan_mode)
+		return indio_dev->info
+			->update_scan_mode(indio_dev,
+					   indio_dev->active_scan_mask);
 	return 0;
 }
 EXPORT_SYMBOL(iio_sw_buffer_preenable);
@@ -652,3 +658,137 @@ int iio_scan_mask_query(struct iio_buffer *buffer, int bit)
 	return test_bit(bit, mask);
 };
 EXPORT_SYMBOL_GPL(iio_scan_mask_query);
+
+/**
+ * struct iio_demux_table() - table describing demux memcpy ops
+ * @from:	index to copy from
+ * @to:	index to copy to
+ * @length:	how many bytes to copy
+ * @l:		list head used for management
+ */
+struct iio_demux_table {
+	unsigned from;
+	unsigned to;
+	unsigned length;
+	struct list_head l;
+};
+
+static unsigned char *iio_demux(struct iio_buffer *buffer,
+				 unsigned char *datain)
+{
+	struct iio_demux_table *t;
+
+	if (list_empty(&buffer->demux_list))
+		return datain;
+	list_for_each_entry(t, &buffer->demux_list, l)
+		memcpy(buffer->demux_bounce + t->to,
+		       datain + t->from, t->length);
+
+	return buffer->demux_bounce;
+}
+
+int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data,
+		       s64 timestamp)
+{
+	unsigned char *dataout = iio_demux(buffer, data);
+
+	return buffer->access->store_to(buffer, dataout, timestamp);
+}
+EXPORT_SYMBOL_GPL(iio_push_to_buffer);
+
+int iio_update_demux(struct iio_dev *indio_dev)
+{
+	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, *q;
+
+	/* Clear out any old demux */
+	list_for_each_entry_safe(p, q, &buffer->demux_list, l) {
+		list_del(&p->l);
+		kfree(p);
+	}
+	kfree(buffer->demux_bounce);
+	buffer->demux_bounce = NULL;
+
+	/* First work out which scan mode we will actually have */
+	if (bitmap_equal(indio_dev->active_scan_mask,
+			 buffer->scan_mask,
+			 indio_dev->masklength))
+		return 0;
+
+	out_ind = find_first_bit(buffer->scan_mask, indio_dev->masklength);
+	/* Now we have the two masks, work from least sig and build up sizes */
+	while (out_ind != indio_dev->masklength) {
+		in_ind = find_next_bit(indio_dev->active_scan_mask,
+				       indio_dev->masklength,
+				       in_ind + 1);
+		while (in_ind != out_ind) {
+			in_ind = find_next_bit(indio_dev->active_scan_mask,
+					       indio_dev->masklength,
+					       in_ind + 1);
+			ch = iio_find_channel_from_si(indio_dev, in_ind);
+			length = ch->scan_type.storagebits/8;
+			/* Make sure we are aligned */
+			in_loc += length;
+			if (in_loc % length)
+				in_loc += length - in_loc % length;
+		}
+		p = kmalloc(sizeof(*p), GFP_KERNEL);
+		if (p == NULL) {
+			ret = -ENOMEM;
+			goto error_clear_mux_table;
+		}
+		ch = iio_find_channel_from_si(indio_dev, in_ind);
+		length = ch->scan_type.storagebits/8;
+		if (out_loc % length)
+			out_loc += length - out_loc % length;
+		if (in_loc % length)
+			in_loc += length - in_loc % length;
+		p->from = in_loc;
+		p->to = out_loc;
+		p->length = length;
+		list_add_tail(&p->l, &buffer->demux_list);
+		out_loc += length;
+		in_loc += length;
+		out_ind = find_next_bit(buffer->scan_mask,
+					indio_dev->masklength,
+					out_ind + 1);
+	}
+	/* Relies on scan_timestamp being last */
+	if (buffer->scan_timestamp) {
+		p = kmalloc(sizeof(*p), GFP_KERNEL);
+		if (p == NULL) {
+			ret = -ENOMEM;
+			goto error_clear_mux_table;
+		}
+		ch = iio_find_channel_from_si(indio_dev,
+			buffer->scan_index_timestamp);
+		length = ch->scan_type.storagebits/8;
+		if (out_loc % length)
+			out_loc += length - out_loc % length;
+		if (in_loc % length)
+			in_loc += length - in_loc % length;
+		p->from = in_loc;
+		p->to = out_loc;
+		p->length = length;
+		list_add_tail(&p->l, &buffer->demux_list);
+		out_loc += length;
+		in_loc += length;
+	}
+	buffer->demux_bounce = kzalloc(out_loc, GFP_KERNEL);
+	if (buffer->demux_bounce == NULL) {
+		ret = -ENOMEM;
+		goto error_clear_mux_table;
+	}
+	return 0;
+
+error_clear_mux_table:
+	list_for_each_entry_safe(p, q, &buffer->demux_list, l) {
+		list_del(&p->l);
+		kfree(p);
+	}
+	return ret;
+}
+EXPORT_SYMBOL_GPL(iio_update_demux);
-- 
1.7.7.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 6/7] staging:iio:adc:max1363 use new demuxing support.
  2011-11-27 13:10 [PATCH 0/7] Add scan demux unit and use it in max1363 Jonathan Cameron
                   ` (4 preceding siblings ...)
  2011-11-27 13:10 ` [PATCH 5/7] staging:iio: add demux optionally to path from device to buffer Jonathan Cameron
@ 2011-11-27 13:10 ` Jonathan Cameron
  2011-11-27 13:10 ` [PATCH 7/7] staging:iio:adc:max1363 correctly set channels as big endian Jonathan Cameron
  6 siblings, 0 replies; 14+ messages in thread
From: Jonathan Cameron @ 2011-11-27 13:10 UTC (permalink / raw)
  To: linux-iio; +Cc: lars, Michael.Hennerich, Jonathan Cameron

From: Jonathan Cameron <jic23@cam.ac.uk>

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/adc/max1363.h      |   11 +++++-
 drivers/staging/iio/adc/max1363_core.c |    4 ++-
 drivers/staging/iio/adc/max1363_ring.c |   51 +++++++++-----------------------
 3 files changed, 26 insertions(+), 40 deletions(-)

diff --git a/drivers/staging/iio/adc/max1363.h b/drivers/staging/iio/adc/max1363.h
index cbcb08a..fb52783 100644
--- a/drivers/staging/iio/adc/max1363.h
+++ b/drivers/staging/iio/adc/max1363.h
@@ -146,18 +146,25 @@ struct max1363_state {
 };
 
 const struct max1363_mode
-*max1363_match_mode(unsigned long *mask, const struct max1363_chip_info *ci);
+*max1363_match_mode(const unsigned long *mask,
+		    const struct max1363_chip_info *ci);
 
 int max1363_set_scan_mode(struct max1363_state *st);
 
 #ifdef CONFIG_MAX1363_RING_BUFFER
-
+int max1363_update_scan_mode(struct iio_dev *indio_dev,
+			     const unsigned long *scan_mask);
 int max1363_single_channel_from_ring(const long *mask,
 				     struct max1363_state *st);
 int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev);
 void max1363_ring_cleanup(struct iio_dev *indio_dev);
 
 #else /* CONFIG_MAX1363_RING_BUFFER */
+int max1363_update_scan_mode(struct iio_dev *indio_dev,
+			     const long *scan_mask)
+{
+	return 0;
+}
 
 int max1363_single_channel_from_ring(long mask, struct max1363_state *st)
 {
diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c
index c3e28e1..7e078fc 100644
--- a/drivers/staging/iio/adc/max1363_core.c
+++ b/drivers/staging/iio/adc/max1363_core.c
@@ -148,7 +148,8 @@ static const struct max1363_mode max1363_mode_table[] = {
 };
 
 const struct max1363_mode
-*max1363_match_mode(unsigned long *mask, const struct max1363_chip_info *ci)
+*max1363_match_mode(const unsigned long *mask,
+const struct max1363_chip_info *ci)
 {
 	int i;
 	if (mask)
@@ -834,6 +835,7 @@ static const struct iio_info max1363_info = {
 	.read_event_config = &max1363_read_event_config,
 	.write_event_config = &max1363_write_event_config,
 	.read_raw = &max1363_read_raw,
+	.update_scan_mode = &max1363_update_scan_mode,
 	.driver_module = THIS_MODULE,
 	.event_attrs = &max1363_event_attribute_group,
 };
diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c
index 3c5e199..19977a6 100644
--- a/drivers/staging/iio/adc/max1363_ring.c
+++ b/drivers/staging/iio/adc/max1363_ring.c
@@ -57,46 +57,19 @@ error_ret:
 	return ret;
 }
 
-
-/**
- * max1363_ring_preenable() - setup the parameters of the ring before enabling
- *
- * The complex nature of the setting of the nuber of bytes per datum is due
- * to this driver currently ensuring that the timestamp is stored at an 8
- * byte boundary.
- **/
-static int max1363_ring_preenable(struct iio_dev *indio_dev)
+int max1363_update_scan_mode(struct iio_dev *indio_dev,
+			     const unsigned long *scan_mask)
 {
 	struct max1363_state *st = iio_priv(indio_dev);
-	struct iio_buffer *ring = indio_dev->buffer;
-	size_t d_size = 0;
-	unsigned long numvals;
 
 	/*
 	 * Need to figure out the current mode based upon the requested
 	 * scan mask in iio_dev
 	 */
-	st->current_mode = max1363_match_mode(ring->scan_mask,
-					st->chip_info);
+	st->current_mode = max1363_match_mode(scan_mask, st->chip_info);
 	if (!st->current_mode)
 		return -EINVAL;
-
 	max1363_set_scan_mode(st);
-
-	numvals = bitmap_weight(st->current_mode->modemask,
-				indio_dev->masklength);
-	if (ring->access->set_bytes_per_datum) {
-		if (ring->scan_timestamp)
-			d_size += sizeof(s64);
-		if (st->chip_info->bits != 8)
-			d_size += numvals*2;
-		else
-			d_size += numvals;
-		if (ring->scan_timestamp && (d_size % 8))
-			d_size += 8 - (d_size % 8);
-		ring->access->set_bytes_per_datum(ring, d_size);
-	}
-
 	return 0;
 }
 
@@ -114,12 +87,14 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p)
 
 	/* Ensure the timestamp is 8 byte aligned */
 	if (st->chip_info->bits != 8)
-		d_size = numvals*2 + sizeof(s64);
+		d_size = numvals*2;
 	else
-		d_size = numvals + sizeof(s64);
-	if (d_size % sizeof(s64))
-		d_size += sizeof(s64) - (d_size % sizeof(s64));
-
+		d_size = numvals;
+	if (indio_dev->buffer->scan_timestamp) {
+		d_size += sizeof(s64);
+		if (d_size % sizeof(s64))
+			d_size += sizeof(s64) - (d_size % sizeof(s64));
+	}
 	/* Monitor mode prevents reading. Whilst not currently implemented
 	 * might as well have this test in here in the meantime as it does
 	 * no harm.
@@ -138,9 +113,11 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p)
 		goto done;
 
 	time_ns = iio_get_time_ns();
+
 	if (indio_dev->buffer->scan_timestamp)
 		memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns));
-	indio_dev->buffer->access->store_to(indio_dev->buffer, rxbuf, time_ns);
+	iio_push_to_buffer(indio_dev->buffer, rxbuf, time_ns);
+
 done:
 	iio_trigger_notify_done(indio_dev->trig);
 	kfree(rxbuf);
@@ -150,7 +127,7 @@ done:
 
 static const struct iio_buffer_setup_ops max1363_ring_setup_ops = {
 	.postenable = &iio_triggered_buffer_postenable,
-	.preenable = &max1363_ring_preenable,
+	.preenable = &iio_sw_buffer_preenable,
 	.predisable = &iio_triggered_buffer_predisable,
 };
 
-- 
1.7.7.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 7/7] staging:iio:adc:max1363 correctly set channels as big endian.
  2011-11-27 13:10 [PATCH 0/7] Add scan demux unit and use it in max1363 Jonathan Cameron
                   ` (5 preceding siblings ...)
  2011-11-27 13:10 ` [PATCH 6/7] staging:iio:adc:max1363 use new demuxing support Jonathan Cameron
@ 2011-11-27 13:10 ` Jonathan Cameron
  6 siblings, 0 replies; 14+ messages in thread
From: Jonathan Cameron @ 2011-11-27 13:10 UTC (permalink / raw)
  To: linux-iio; +Cc: lars, Michael.Hennerich, Jonathan Cameron

From: Jonathan Cameron <jic23@cam.ac.uk>

Also, the differential channels should always have been signed.

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/adc/max1363_core.c |   14 ++++++++++++--
 1 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c
index 7e078fc..9febd1b 100644
--- a/drivers/staging/iio/adc/max1363_core.c
+++ b/drivers/staging/iio/adc/max1363_core.c
@@ -298,7 +298,12 @@ static const enum max1363_modes max1363_mode_list[] = {
 		.channel = num,						\
 		.address = addr,					\
 		.info_mask = MAX1363_INFO_MASK,				\
-		.scan_type = IIO_ST('u', bits, (bits > 8) ? 16 : 8, 0), \
+		.scan_type = {						\
+			.sign = 'u',					\
+			.realbits = bits,				\
+			.storagebits = (bits > 8) ? 16 : 8,		\
+			.endianness = IIO_BE,				\
+		},							\
 		.scan_index = si,					\
 		.event_mask = evmask,					\
 	}
@@ -313,7 +318,12 @@ static const enum max1363_modes max1363_mode_list[] = {
 		.channel2 = num2,					\
 		.address = addr,					\
 		.info_mask = MAX1363_INFO_MASK,				\
-		.scan_type = IIO_ST('u', bits, (bits > 8) ? 16 : 8, 0), \
+		.scan_type = {						\
+			.sign = 's',					\
+			.realbits = bits,				\
+			.storagebits = (bits > 8) ? 16 : 8,		\
+			.endianness = IIO_BE,				\
+		},							\
 		.scan_index = si,					\
 		.event_mask = evmask,					\
 	}
-- 
1.7.7.3


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/7] staging:iio: make iio_sw_buffer_preenable much more general.
  2011-11-27 13:10 ` [PATCH 4/7] staging:iio: make iio_sw_buffer_preenable much more general Jonathan Cameron
@ 2011-11-28  9:23   ` Lars-Peter Clausen
  2011-12-01 21:17     ` Jonathan Cameron
  0 siblings, 1 reply; 14+ messages in thread
From: Lars-Peter Clausen @ 2011-11-28  9:23 UTC (permalink / raw)
  To: Jonathan Cameron; +Cc: linux-iio, Michael.Hennerich

On 11/27/2011 02:10 PM, Jonathan Cameron wrote:
> Also introduces active_scan_mask storage to tell the core what is
> really being currently captured from the device (different from
> what is desired as often has bonus channels).
> 
> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
> ---
>  drivers/staging/iio/iio.h                 |    2 +
>  drivers/staging/iio/industrialio-buffer.c |   65 +++++++++++++++++-----------
>  2 files changed, 41 insertions(+), 26 deletions(-)
> 
> diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h
> index 4fb8f2f..c225542 100644
> --- a/drivers/staging/iio/iio.h
> +++ b/drivers/staging/iio/iio.h
> @@ -280,6 +280,7 @@ struct iio_info {
>   * @available_scan_masks: [DRIVER] optional array of allowed bitmasks
>   * @masklength:		[INTERN] the length of the mask established from
>   *			channels
> + * @active_scan_mask:	[INTERN] union of all scan masks requested by buffers
>   * @trig:		[INTERN] current device trigger (buffer modes)
>   * @pollfunc:		[DRIVER] function run on trigger being received
>   * @channels:		[DRIVER] channel specification structure table
> @@ -307,6 +308,7 @@ struct iio_dev {
>  
>  	unsigned long			*available_scan_masks;
>  	unsigned			masklength;
> +	unsigned long			*active_scan_mask;
>  	struct iio_trigger		*trig;
>  	struct iio_poll_func		*pollfunc;
>  
> diff --git a/drivers/staging/iio/industrialio-buffer.c b/drivers/staging/iio/industrialio-buffer.c
> index cae7922..fb14e37 100644
> --- a/drivers/staging/iio/industrialio-buffer.c
> +++ b/drivers/staging/iio/industrialio-buffer.c
> @@ -533,32 +533,6 @@ ssize_t iio_buffer_show_enable(struct device *dev,
>  }
>  EXPORT_SYMBOL(iio_buffer_show_enable);
>  
> -int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
> -{
> -	struct iio_buffer *buffer = indio_dev->buffer;
> -	size_t size;
> -	dev_dbg(&indio_dev->dev, "%s\n", __func__);
> -	/* Check if there are any scan elements enabled, if not fail*/
> -	if (!(buffer->scan_count || buffer->scan_timestamp))
> -		return -EINVAL;
> -	if (buffer->scan_timestamp)
> -		if (buffer->scan_count)
> -			/* Timestamp (aligned to s64) and data */
> -			size = (((buffer->scan_count * buffer->bpe)
> -					+ sizeof(s64) - 1)
> -				& ~(sizeof(s64) - 1))
> -				+ sizeof(s64);
> -		else /* Timestamp only  */
> -			size = sizeof(s64);
> -	else /* Data only */
> -		size = buffer->scan_count * buffer->bpe;
> -	buffer->access->set_bytes_per_datum(buffer, size);
> -
> -	return 0;
> -}
> -EXPORT_SYMBOL(iio_sw_buffer_preenable);
> -
> -
>  /* note NULL used as error indicator as it doesn't make sense. */
>  static unsigned long *iio_scan_mask_match(unsigned long *av_masks,
>  					  unsigned int masklength,
> @@ -574,6 +548,45 @@ static unsigned long *iio_scan_mask_match(unsigned long *av_masks,
>  	return NULL;
>  }
>  
> +int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
> +{
> +	struct iio_buffer *buffer = indio_dev->buffer;
> +	const struct iio_chan_spec *ch;
> +	unsigned bytes = 0;
> +	int length, i;
> +	dev_dbg(&indio_dev->dev, "%s\n", __func__);
> +
> +	/* How much space will the demuxed element take? */
> +	for_each_set_bit(i, buffer->scan_mask,
> +			 indio_dev->masklength) {
> +		ch = iio_find_channel_from_si(indio_dev, i);
> +		length = ch->scan_type.storagebits/8;
> +		if (bytes % length)
> +			bytes += length - bytes % length;

bytes = ALIGN(bytes, length); would probably make it more obvious what is
going on here.

> +		bytes += length;
> +	}
> +	if (buffer->scan_timestamp) {
> +		ch = iio_find_channel_from_si(indio_dev,
> +					      buffer->scan_index_timestamp);
> +		length = ch->scan_type.storagebits/8;
> +		if (bytes % length)
> +			bytes += length - bytes % length;
> +		bytes += length;
> +	}
> +	buffer->access->set_bytes_per_datum(buffer, bytes);
> +
> +	/* What scan mask do we actually have ?*/
> +	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;
> +	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


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 5/7] staging:iio: add demux optionally to path from device to buffer
  2011-11-27 13:10 ` [PATCH 5/7] staging:iio: add demux optionally to path from device to buffer Jonathan Cameron
@ 2011-11-28  9:39   ` Lars-Peter Clausen
  2011-12-01 21:34     ` Jonathan Cameron
  0 siblings, 1 reply; 14+ messages in thread
From: Lars-Peter Clausen @ 2011-11-28  9:39 UTC (permalink / raw)
  To: Jonathan Cameron; +Cc: linux-iio, Michael.Hennerich, Jonathan Cameron

On 11/27/2011 02:10 PM, Jonathan Cameron wrote:
> From: Jonathan Cameron <jic23@cam.ac.uk>
> 
> This gives you only what you ask for which is handy
> for some devices with weird scan combinations.
> 
> Routes all data flow through a core utility function.
> That and this demuxing support will be needed to do
> demuxing to multiple destinations in kernel.
> 
> Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
> ---
>  drivers/staging/iio/buffer.h              |   15 +++
>  drivers/staging/iio/industrialio-buffer.c |  148 ++++++++++++++++++++++++++++-
>  2 files changed, 159 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/staging/iio/buffer.h b/drivers/staging/iio/buffer.h
> index 4b8f619..5282441 100644
> --- a/drivers/staging/iio/buffer.h
> +++ b/drivers/staging/iio/buffer.h
> @@ -95,6 +95,8 @@ struct iio_buffer_setup_ops {
>   * @access:		[DRIVER] buffer access functions associated with the
>   *			implementation.
>   * @flags:		[INTERN] file ops related flags including busy flag.
> + * @demux_list:		[INTERN] list of operations required to demux the scan.
> + * @demux_bounce:	[INTERN] buffer for doing gather from incoming scan.
>   **/
>  struct iio_buffer {
>  	struct iio_dev				*indio_dev;
> @@ -115,6 +117,8 @@ struct iio_buffer {
>  	bool					stufftoread;
>  	unsigned long				flags;
>  	const struct attribute_group *attrs;
> +	struct list_head			demux_list;
> +	unsigned char				*demux_bounce;
>  };
>  
>  /**
> @@ -153,6 +157,17 @@ int iio_scan_mask_set(struct iio_buffer *buffer, int bit);
>  	container_of(d, struct iio_buffer, dev)
>  
>  /**
> + * iio_push_to_buffer() - push to a registered buffer.
> + * @buffer:		IIO buffer structure for device
> + * @scan:		Full scan.
> + * @timestamp:
> + */
> +int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data,
> +		       s64 timestamp);
> +
> +int iio_update_demux(struct iio_dev *indio_dev);
> +
> +/**
>   * iio_buffer_register() - register the buffer with IIO core
>   * @indio_dev: device with the buffer to be registered
>   **/
> diff --git a/drivers/staging/iio/industrialio-buffer.c b/drivers/staging/iio/industrialio-buffer.c
> index fb14e37..352f9f1 100644
> --- a/drivers/staging/iio/industrialio-buffer.c
> +++ b/drivers/staging/iio/industrialio-buffer.c
> @@ -87,6 +87,7 @@ void iio_chrdev_buffer_release(struct iio_dev *indio_dev)
>  
>  void iio_buffer_init(struct iio_buffer *buffer, struct iio_dev *indio_dev)
>  {
> +	INIT_LIST_HEAD(&buffer->demux_list);
>  	buffer->indio_dev = indio_dev;
>  	init_waitqueue_head(&buffer->pollq);
>  }
> @@ -128,10 +129,9 @@ static ssize_t iio_scan_el_show(struct device *dev,
>  	int ret;
>  	struct iio_dev *indio_dev = dev_get_drvdata(dev);
>  
> -	ret = iio_scan_mask_query(indio_dev->buffer,
> -				  to_iio_dev_attr(attr)->address);
> -	if (ret < 0)
> -		return ret;
> +	ret = test_bit(to_iio_dev_attr(attr)->address,
> +		       indio_dev->buffer->scan_mask);
> +
>  	return sprintf(buf, "%d\n", ret);
>  }
>  
> @@ -583,6 +583,12 @@ int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
>  					    buffer->scan_mask);
>  	else
>  		indio_dev->active_scan_mask = buffer->scan_mask;
> +	iio_update_demux(indio_dev);
> +
> +	if (indio_dev->info->update_scan_mode)
> +		return indio_dev->info
> +			->update_scan_mode(indio_dev,
> +					   indio_dev->active_scan_mask);
>  	return 0;
>  }
>  EXPORT_SYMBOL(iio_sw_buffer_preenable);
> @@ -652,3 +658,137 @@ int iio_scan_mask_query(struct iio_buffer *buffer, int bit)
>  	return test_bit(bit, mask);
>  };
>  EXPORT_SYMBOL_GPL(iio_scan_mask_query);
> +
> +/**
> + * struct iio_demux_table() - table describing demux memcpy ops
> + * @from:	index to copy from
> + * @to:	index to copy to
> + * @length:	how many bytes to copy
> + * @l:		list head used for management
> + */
> +struct iio_demux_table {
> +	unsigned from;
> +	unsigned to;
> +	unsigned length;
> +	struct list_head l;
> +};
> +
> +static unsigned char *iio_demux(struct iio_buffer *buffer,
> +				 unsigned char *datain)
> +{
> +	struct iio_demux_table *t;
> +
> +	if (list_empty(&buffer->demux_list))
> +		return datain;
> +	list_for_each_entry(t, &buffer->demux_list, l)
> +		memcpy(buffer->demux_bounce + t->to,
> +		       datain + t->from, t->length);
> +
> +	return buffer->demux_bounce;
> +}
> +
> +int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data,
> +		       s64 timestamp)
> +{
> +	unsigned char *dataout = iio_demux(buffer, data);
> +
> +	return buffer->access->store_to(buffer, dataout, timestamp);
> +}
> +EXPORT_SYMBOL_GPL(iio_push_to_buffer);

I wonder if we want to integrate the demuxing into the store_to callbacks of
the buffer, this would avoid the need for the bounce buffer and reduce the
number of memcpys. But maybe we can just add it later.


> +
> +int iio_update_demux(struct iio_dev *indio_dev)
> +{
> +	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, *q;
> +
> +	/* Clear out any old demux */
> +	list_for_each_entry_safe(p, q, &buffer->demux_list, l) {
> +		list_del(&p->l);
> +		kfree(p);
> +	}
> +	kfree(buffer->demux_bounce);
> +	buffer->demux_bounce = NULL;
> +
> +	/* First work out which scan mode we will actually have */
> +	if (bitmap_equal(indio_dev->active_scan_mask,
> +			 buffer->scan_mask,
> +			 indio_dev->masklength))
> +		return 0;
> +
> +	out_ind = find_first_bit(buffer->scan_mask, indio_dev->masklength);
> +	/* Now we have the two masks, work from least sig and build up sizes */
> +	while (out_ind != indio_dev->masklength) {

	This looks a bit like an open-coded for_each_set_bit

> +		in_ind = find_next_bit(indio_dev->active_scan_mask,
> +				       indio_dev->masklength,
> +				       in_ind + 1);
> +		while (in_ind != out_ind) {
> +			in_ind = find_next_bit(indio_dev->active_scan_mask,
> +					       indio_dev->masklength,
> +					       in_ind + 1);

same here for_each_set_bit(in_ind, indio->active_scan_mask, out_ind)

> +			ch = iio_find_channel_from_si(indio_dev, in_ind);
> +			length = ch->scan_type.storagebits/8;
> +			/* Make sure we are aligned */
> +			in_loc += length;
> +			if (in_loc % length)
> +				in_loc += length - in_loc % length;
> +		}
> +		p = kmalloc(sizeof(*p), GFP_KERNEL);
> +		if (p == NULL) {
> +			ret = -ENOMEM;
> +			goto error_clear_mux_table;
> +		}
> +		ch = iio_find_channel_from_si(indio_dev, in_ind);
> +		length = ch->scan_type.storagebits/8;
> +		if (out_loc % length)
> +			out_loc += length - out_loc % length;
> +		if (in_loc % length)
> +			in_loc += length - in_loc % length;
> +		p->from = in_loc;
> +		p->to = out_loc;
> +		p->length = length;
> +		list_add_tail(&p->l, &buffer->demux_list);
> +		out_loc += length;
> +		in_loc += length;
> +		out_ind = find_next_bit(buffer->scan_mask,
> +					indio_dev->masklength,
> +					out_ind + 1);
> +	}
> +	/* Relies on scan_timestamp being last */
> +	if (buffer->scan_timestamp) {
> +		p = kmalloc(sizeof(*p), GFP_KERNEL);
> +		if (p == NULL) {
> +			ret = -ENOMEM;
> +			goto error_clear_mux_table;
> +		}
> +		ch = iio_find_channel_from_si(indio_dev,
> +			buffer->scan_index_timestamp);
> +		length = ch->scan_type.storagebits/8;
> +		if (out_loc % length)
> +			out_loc += length - out_loc % length;
> +		if (in_loc % length)
> +			in_loc += length - in_loc % length;
> +		p->from = in_loc;
> +		p->to = out_loc;
> +		p->length = length;
> +		list_add_tail(&p->l, &buffer->demux_list);
> +		out_loc += length;
> +		in_loc += length;
> +	}
> +	buffer->demux_bounce = kzalloc(out_loc, GFP_KERNEL);
> +	if (buffer->demux_bounce == NULL) {
> +		ret = -ENOMEM;
> +		goto error_clear_mux_table;
> +	}
> +	return 0;
> +
> +error_clear_mux_table:
> +	list_for_each_entry_safe(p, q, &buffer->demux_list, l) {
> +		list_del(&p->l);
> +		kfree(p);
> +	}
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(iio_update_demux);


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/7] staging:iio: make iio_sw_buffer_preenable much more general.
  2011-11-28  9:23   ` Lars-Peter Clausen
@ 2011-12-01 21:17     ` Jonathan Cameron
  0 siblings, 0 replies; 14+ messages in thread
From: Jonathan Cameron @ 2011-12-01 21:17 UTC (permalink / raw)
  To: Lars-Peter Clausen; +Cc: linux-iio, Michael.Hennerich

...
>> +int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
>> +{
>> +	struct iio_buffer *buffer = indio_dev->buffer;
>> +	const struct iio_chan_spec *ch;
>> +	unsigned bytes = 0;
>> +	int length, i;
>> +	dev_dbg(&indio_dev->dev, "%s\n", __func__);
>> +
>> +	/* How much space will the demuxed element take? */
>> +	for_each_set_bit(i, buffer->scan_mask,
>> +			 indio_dev->masklength) {
>> +		ch = iio_find_channel_from_si(indio_dev, i);
>> +		length = ch->scan_type.storagebits/8;
>> +		if (bytes % length)
>> +			bytes += length - bytes % length;
> 
> bytes = ALIGN(bytes, length); would probably make it more obvious what is
> going on here.
Good idea. Thanks.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 5/7] staging:iio: add demux optionally to path from device to buffer
  2011-11-28  9:39   ` Lars-Peter Clausen
@ 2011-12-01 21:34     ` Jonathan Cameron
  0 siblings, 0 replies; 14+ messages in thread
From: Jonathan Cameron @ 2011-12-01 21:34 UTC (permalink / raw)
  To: Lars-Peter Clausen; +Cc: linux-iio, Michael.Hennerich, Jonathan Cameron

On 11/28/2011 09:39 AM, Lars-Peter Clausen wrote:
> On 11/27/2011 02:10 PM, Jonathan Cameron wrote:
>> From: Jonathan Cameron <jic23@cam.ac.uk>
>>
>> This gives you only what you ask for which is handy
>> for some devices with weird scan combinations.
>>
>> Routes all data flow through a core utility function.
>> That and this demuxing support will be needed to do
>> demuxing to multiple destinations in kernel.
>>
>> Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
>> ---
>>  drivers/staging/iio/buffer.h              |   15 +++
>>  drivers/staging/iio/industrialio-buffer.c |  148 ++++++++++++++++++++++++++++-
>>  2 files changed, 159 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/staging/iio/buffer.h b/drivers/staging/iio/buffer.h
>> index 4b8f619..5282441 100644
>> --- a/drivers/staging/iio/buffer.h
>> +++ b/drivers/staging/iio/buffer.h
>> @@ -95,6 +95,8 @@ struct iio_buffer_setup_ops {
>>   * @access:		[DRIVER] buffer access functions associated with the
>>   *			implementation.
>>   * @flags:		[INTERN] file ops related flags including busy flag.
>> + * @demux_list:		[INTERN] list of operations required to demux the scan.
>> + * @demux_bounce:	[INTERN] buffer for doing gather from incoming scan.
>>   **/
>>  struct iio_buffer {
>>  	struct iio_dev				*indio_dev;
>> @@ -115,6 +117,8 @@ struct iio_buffer {
>>  	bool					stufftoread;
>>  	unsigned long				flags;
>>  	const struct attribute_group *attrs;
>> +	struct list_head			demux_list;
>> +	unsigned char				*demux_bounce;
>>  };
>>  
>>  /**
>> @@ -153,6 +157,17 @@ int iio_scan_mask_set(struct iio_buffer *buffer, int bit);
>>  	container_of(d, struct iio_buffer, dev)
>>  
>>  /**
>> + * iio_push_to_buffer() - push to a registered buffer.
>> + * @buffer:		IIO buffer structure for device
>> + * @scan:		Full scan.
>> + * @timestamp:
>> + */
>> +int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data,
>> +		       s64 timestamp);
>> +
>> +int iio_update_demux(struct iio_dev *indio_dev);
>> +
>> +/**
>>   * iio_buffer_register() - register the buffer with IIO core
>>   * @indio_dev: device with the buffer to be registered
>>   **/
>> diff --git a/drivers/staging/iio/industrialio-buffer.c b/drivers/staging/iio/industrialio-buffer.c
>> index fb14e37..352f9f1 100644
>> --- a/drivers/staging/iio/industrialio-buffer.c
>> +++ b/drivers/staging/iio/industrialio-buffer.c
>> @@ -87,6 +87,7 @@ void iio_chrdev_buffer_release(struct iio_dev *indio_dev)
>>  
>>  void iio_buffer_init(struct iio_buffer *buffer, struct iio_dev *indio_dev)
>>  {
>> +	INIT_LIST_HEAD(&buffer->demux_list);
>>  	buffer->indio_dev = indio_dev;
>>  	init_waitqueue_head(&buffer->pollq);
>>  }
>> @@ -128,10 +129,9 @@ static ssize_t iio_scan_el_show(struct device *dev,
>>  	int ret;
>>  	struct iio_dev *indio_dev = dev_get_drvdata(dev);
>>  
>> -	ret = iio_scan_mask_query(indio_dev->buffer,
>> -				  to_iio_dev_attr(attr)->address);
>> -	if (ret < 0)
>> -		return ret;
>> +	ret = test_bit(to_iio_dev_attr(attr)->address,
>> +		       indio_dev->buffer->scan_mask);
>> +
>>  	return sprintf(buf, "%d\n", ret);
>>  }
>>  
>> @@ -583,6 +583,12 @@ int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
>>  					    buffer->scan_mask);
>>  	else
>>  		indio_dev->active_scan_mask = buffer->scan_mask;
>> +	iio_update_demux(indio_dev);
>> +
>> +	if (indio_dev->info->update_scan_mode)
>> +		return indio_dev->info
>> +			->update_scan_mode(indio_dev,
>> +					   indio_dev->active_scan_mask);
>>  	return 0;
>>  }
>>  EXPORT_SYMBOL(iio_sw_buffer_preenable);
>> @@ -652,3 +658,137 @@ int iio_scan_mask_query(struct iio_buffer *buffer, int bit)
>>  	return test_bit(bit, mask);
>>  };
>>  EXPORT_SYMBOL_GPL(iio_scan_mask_query);
>> +
>> +/**
>> + * struct iio_demux_table() - table describing demux memcpy ops
>> + * @from:	index to copy from
>> + * @to:	index to copy to
>> + * @length:	how many bytes to copy
>> + * @l:		list head used for management
>> + */
>> +struct iio_demux_table {
>> +	unsigned from;
>> +	unsigned to;
>> +	unsigned length;
>> +	struct list_head l;
>> +};
>> +
>> +static unsigned char *iio_demux(struct iio_buffer *buffer,
>> +				 unsigned char *datain)
>> +{
>> +	struct iio_demux_table *t;
>> +
>> +	if (list_empty(&buffer->demux_list))
>> +		return datain;
>> +	list_for_each_entry(t, &buffer->demux_list, l)
>> +		memcpy(buffer->demux_bounce + t->to,
>> +		       datain + t->from, t->length);
>> +
>> +	return buffer->demux_bounce;
>> +}
>> +
>> +int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data,
>> +		       s64 timestamp)
>> +{
>> +	unsigned char *dataout = iio_demux(buffer, data);
>> +
>> +	return buffer->access->store_to(buffer, dataout, timestamp);
>> +}
>> +EXPORT_SYMBOL_GPL(iio_push_to_buffer);
> 
> I wonder if we want to integrate the demuxing into the store_to callbacks of
> the buffer, this would avoid the need for the bounce buffer and reduce the
> number of memcpys. But maybe we can just add it later.
I'd rather do this later than mess too much with the buffers in this
patch.  I think we may want to do it the other way around and have
buffers offer a reserve_space and done_with_space pair of callbacks
where the first saves the room and passes back a pointer.  Then demux
can occur directly into there rather than the bounce buffer.

Still, same effective result!  So not now in my view.
> 
> 	This looks a bit like an open-coded for_each_set_bit
Indeed.  Will clean that up.
> 
>> +		in_ind = find_next_bit(indio_dev->active_scan_mask,
>> +				       indio_dev->masklength,
>> +				       in_ind + 1);
>> +		while (in_ind != out_ind) {
>> +			in_ind = find_next_bit(indio_dev->active_scan_mask,
>> +					       indio_dev->masklength,
>> +					       in_ind + 1);
> 
> same here for_each_set_bit(in_ind, indio->active_scan_mask, out_ind)
close but not quite.  It only counts bits above the previous in_ind
(which is also the previous out_ind).  Need a for_each_set_bit_after
function for this.
> 
>> +			ch = iio_find_channel_from_si(indio_dev, in_ind);
>> +			length = ch->scan_type.storagebits/8;
>> +			/* Make sure we are aligned */
>> +			in_loc += length;
>> +			if (in_loc % length)
>> +				in_loc += length - in_loc % length;
>> +		}
>> +		p = kmalloc(sizeof(*p), GFP_KERNEL);
>> +		if (p == NULL) {
>> +			ret = -ENOMEM;
>> +			goto error_clear_mux_table;
>> +		}
>> +		ch = iio_find_channel_from_si(indio_dev, in_ind);
>> +		length = ch->scan_type.storagebits/8;
>> +		if (out_loc % length)
>> +			out_loc += length - out_loc % length;
>> +		if (in_loc % length)
>> +			in_loc += length - in_loc % length;
>> +		p->from = in_loc;
>> +		p->to = out_loc;
>> +		p->length = length;
>> +		list_add_tail(&p->l, &buffer->demux_list);
>> +		out_loc += length;
>> +		in_loc += length;
>> +		out_ind = find_next_bit(buffer->scan_mask,
>> +					indio_dev->masklength,
>> +					out_ind + 1);
>> +	}
>> +	/* Relies on scan_timestamp being last */
>> +	if (buffer->scan_timestamp) {
>> +		p = kmalloc(sizeof(*p), GFP_KERNEL);
>> +		if (p == NULL) {
>> +			ret = -ENOMEM;
>> +			goto error_clear_mux_table;
>> +		}
>> +		ch = iio_find_channel_from_si(indio_dev,
>> +			buffer->scan_index_timestamp);
>> +		length = ch->scan_type.storagebits/8;
>> +		if (out_loc % length)
>> +			out_loc += length - out_loc % length;
>> +		if (in_loc % length)
>> +			in_loc += length - in_loc % length;
>> +		p->from = in_loc;
>> +		p->to = out_loc;
>> +		p->length = length;
>> +		list_add_tail(&p->l, &buffer->demux_list);
>> +		out_loc += length;
>> +		in_loc += length;
>> +	}
>> +	buffer->demux_bounce = kzalloc(out_loc, GFP_KERNEL);
>> +	if (buffer->demux_bounce == NULL) {
>> +		ret = -ENOMEM;
>> +		goto error_clear_mux_table;
>> +	}
>> +	return 0;
>> +
>> +error_clear_mux_table:
>> +	list_for_each_entry_safe(p, q, &buffer->demux_list, l) {
>> +		list_del(&p->l);
>> +		kfree(p);
>> +	}
>> +	return ret;
>> +}
>> +EXPORT_SYMBOL_GPL(iio_update_demux);
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 2/7] staging:iio:buffer add a cache of the timestamp scan index.
  2011-12-05 21:37 [PATCH V3 0/7] Add scan demux unit and use it in max1363 Jonathan Cameron
@ 2011-12-05 21:37 ` Jonathan Cameron
  0 siblings, 0 replies; 14+ messages in thread
From: Jonathan Cameron @ 2011-12-05 21:37 UTC (permalink / raw)
  To: linux-iio, greg; +Cc: lars, Jonathan Cameron

From: Jonathan Cameron <jic23@cam.ac.uk>

Basically avoids looking it up lots of times.

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/buffer.h              |    1 +
 drivers/staging/iio/industrialio-buffer.c |    3 +++
 2 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/iio/buffer.h b/drivers/staging/iio/buffer.h
index 9de581e..4b8f619 100644
--- a/drivers/staging/iio/buffer.h
+++ b/drivers/staging/iio/buffer.h
@@ -106,6 +106,7 @@ struct iio_buffer {
 	int					scan_count;
 	long					*scan_mask;
 	bool					scan_timestamp;
+	unsigned				scan_index_timestamp;
 	const struct iio_buffer_access_funcs	*access;
 	const struct iio_buffer_setup_ops		*setup_ops;
 	struct list_head			scan_el_dev_attr_list;
diff --git a/drivers/staging/iio/industrialio-buffer.c b/drivers/staging/iio/industrialio-buffer.c
index 8c55980..b2cf3e3 100644
--- a/drivers/staging/iio/industrialio-buffer.c
+++ b/drivers/staging/iio/industrialio-buffer.c
@@ -313,6 +313,9 @@ int iio_buffer_register(struct iio_dev *indio_dev,
 			if (ret < 0)
 				goto error_cleanup_dynamic;
 			attrcount += ret;
+			if (channels[i].type == IIO_TIMESTAMP)
+				buffer->scan_index_timestamp =
+					channels[i].scan_index;
 		}
 		if (indio_dev->masklength && buffer->scan_mask == NULL) {
 			buffer->scan_mask = kcalloc(BITS_TO_LONGS(indio_dev->masklength),
-- 
1.7.7.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/7] staging:iio:buffer add a cache of the timestamp scan index.
  2011-12-04 20:56 [PATCH V2 0/7] Add scan demux unit and use it in max1363 Jonathan Cameron
@ 2011-12-04 20:56 ` Jonathan Cameron
  0 siblings, 0 replies; 14+ messages in thread
From: Jonathan Cameron @ 2011-12-04 20:56 UTC (permalink / raw)
  To: linux-iio; +Cc: lars, Jonathan Cameron

From: Jonathan Cameron <jic23@cam.ac.uk>

Basically avoids looking it up lots of times.

Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
 drivers/staging/iio/buffer.h              |    1 +
 drivers/staging/iio/industrialio-buffer.c |    3 +++
 2 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/iio/buffer.h b/drivers/staging/iio/buffer.h
index 9de581e..4b8f619 100644
--- a/drivers/staging/iio/buffer.h
+++ b/drivers/staging/iio/buffer.h
@@ -106,6 +106,7 @@ struct iio_buffer {
 	int					scan_count;
 	long					*scan_mask;
 	bool					scan_timestamp;
+	unsigned				scan_index_timestamp;
 	const struct iio_buffer_access_funcs	*access;
 	const struct iio_buffer_setup_ops		*setup_ops;
 	struct list_head			scan_el_dev_attr_list;
diff --git a/drivers/staging/iio/industrialio-buffer.c b/drivers/staging/iio/industrialio-buffer.c
index 8c55980..b2cf3e3 100644
--- a/drivers/staging/iio/industrialio-buffer.c
+++ b/drivers/staging/iio/industrialio-buffer.c
@@ -313,6 +313,9 @@ int iio_buffer_register(struct iio_dev *indio_dev,
 			if (ret < 0)
 				goto error_cleanup_dynamic;
 			attrcount += ret;
+			if (channels[i].type == IIO_TIMESTAMP)
+				buffer->scan_index_timestamp =
+					channels[i].scan_index;
 		}
 		if (indio_dev->masklength && buffer->scan_mask == NULL) {
 			buffer->scan_mask = kcalloc(BITS_TO_LONGS(indio_dev->masklength),
-- 
1.7.7.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2011-12-05 21:37 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-11-27 13:10 [PATCH 0/7] Add scan demux unit and use it in max1363 Jonathan Cameron
2011-11-27 13:10 ` [PATCH 1/7] staging:iio:find iio channel from scan index util function Jonathan Cameron
2011-11-27 13:10 ` [PATCH 2/7] staging:iio:buffer add a cache of the timestamp scan index Jonathan Cameron
2011-11-27 13:10 ` [PATCH 3/7] staging:iio: add hook to allow core to perform scan related config Jonathan Cameron
2011-11-27 13:10 ` [PATCH 4/7] staging:iio: make iio_sw_buffer_preenable much more general Jonathan Cameron
2011-11-28  9:23   ` Lars-Peter Clausen
2011-12-01 21:17     ` Jonathan Cameron
2011-11-27 13:10 ` [PATCH 5/7] staging:iio: add demux optionally to path from device to buffer Jonathan Cameron
2011-11-28  9:39   ` Lars-Peter Clausen
2011-12-01 21:34     ` Jonathan Cameron
2011-11-27 13:10 ` [PATCH 6/7] staging:iio:adc:max1363 use new demuxing support Jonathan Cameron
2011-11-27 13:10 ` [PATCH 7/7] staging:iio:adc:max1363 correctly set channels as big endian Jonathan Cameron
2011-12-04 20:56 [PATCH V2 0/7] Add scan demux unit and use it in max1363 Jonathan Cameron
2011-12-04 20:56 ` [PATCH 2/7] staging:iio:buffer add a cache of the timestamp scan index Jonathan Cameron
2011-12-05 21:37 [PATCH V3 0/7] Add scan demux unit and use it in max1363 Jonathan Cameron
2011-12-05 21:37 ` [PATCH 2/7] staging:iio:buffer add a cache of the timestamp scan index Jonathan Cameron

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.