Skip to contentSkip to conversation

IIO: in kernel (as opposed to userspace) pull consumers

PATCH Applied Jonathan Cameron 4 participants 13 messages Feb 15, 2012 – Feb 25, 2012

Subsystems (6)
lore
Share & tools
lore

Jonathan Cameron

author maintainer
#0 lore raw

v6 cover IIO: in kernel (as opposed to userspace) pull consumers

Previously IIO: in kernel pull interfaces.

Changes since the RFC V5. The race condition on exit is avoided by the introduction of the first patch and related modifications later. All in kernel consumers ultimately access the IIO devices through the iio_info structure pointer in the relevant iio_dev structure. Thus (protected by a mutex) we can set this to null on device removal and check it in users. Thus ensuring a clean error is returned if the provider is removed before the consumer has finished with it. Right now there is nothing to even make this hard but we can easily get the module at a later date to cut down on this happening.

Otherwise, I've made the whole thing no longer an option for IIO as suggested by Linus.

Few cleanups beyond that from testing and appopriate updates to the documentation.

Any comments? I'd like to get this out the way so we can move on to the more 'interesting' case of push interfaces (those that are interrupt driven). Patches for that are ready but need cleaning up and are more invasive that these within IIO itself.

Jonathan

Jonathan Cameron (6):
staging:iio:core set the iio_dev.info pointer to null on unregister
under lock.
staging:iio:core add in kernel interface mapping and getting IIO
channels.
staging:iio: move iio data return types into types.h for use by
inkern
staging:iio::hwmon interface client driver. staging:iio:Documentation in kernel pull description.
stargate2: example of map configuration for iio to hwmon example.

 arch/arm/mach-pxa/stargate2.c                  |   24 ++
 drivers/staging/iio/Documentation/inkernel.txt |   58 +++++
 drivers/staging/iio/Kconfig                    |    7 +
 drivers/staging/iio/Makefile                   |    4 +-
 drivers/staging/iio/consumer.h                 |   96 ++++++++
 drivers/staging/iio/driver.h                   |   34 +++
 drivers/staging/iio/iio.h                      |    8 +-
 drivers/staging/iio/iio_hwmon.c                |  232 +++++++++++++++++++
 drivers/staging/iio/industrialio-core.c        |    4 +
 drivers/staging/iio/inkern.c                   |  292 ++++++++++++++++++++++++
 drivers/staging/iio/machine.h                  |   24 ++
 drivers/staging/iio/types.h                    |    4 +
 12 files changed, 780 insertions(+), 7 deletions(-)
 create mode 100644 drivers/staging/iio/Documentation/inkernel.txt
 create mode 100644 drivers/staging/iio/consumer.h
 create mode 100644 drivers/staging/iio/driver.h
 create mode 100644 drivers/staging/iio/iio_hwmon.c
 create mode 100644 drivers/staging/iio/inkern.c
 create mode 100644 drivers/staging/iio/machine.h
Signature · 1 line
1.7.8.4
author maintainer
#1 lore raw

PATCH v6 1/6 staging:iio:core set the iio_dev.info pointer to null on unregister under lock.

This prevents use of provider callbacks after it has been unregistered. Note that all code using this that can be called from a consumer *must* check the pointer before using and hold the info_exist_lock throughout the usage of the callbacks in info.

---
 drivers/staging/iio/iio.h               |    2 ++
 drivers/staging/iio/industrialio-core.c |    4 ++++
 2 files changed, 6 insertions(+), 0 deletions(-)
drivers/staging/iio/iio.h +2 -0
index be6ced3..478dbe5 100644
@@ -310,6 +310,7 @@ struct iio_buffer_setup_ops {
  * @chan_attr_group:	[INTERN] group for all attrs in base directory
  * @name:		[DRIVER] name of the device.
  * @info:		[DRIVER] callbacks and constant info from driver
+ * @info_exist_lock:	[INTERN] lock to prevent use during removal
  * @chrdev:		[INTERN] associated character device
  * @groups:		[INTERN] attribute groups
  * @groupcounter:	[INTERN] index of next attribute group
@@ -340,6 +341,7 @@ struct iio_dev {
 	struct attribute_group		chan_attr_group;
 	const char			*name;
 	const struct iio_info		*info;
+	struct mutex			info_exist_lock;
 	const struct iio_buffer_setup_ops	*setup_ops;
 	struct cdev			chrdev;
 #define IIO_MAX_GROUPS 6
drivers/staging/iio/industrialio-core.c +4 -0
index e4824fe..3a2d080 100644
@@ -594,6 +594,7 @@ struct iio_dev *iio_allocate_device(int sizeof_priv)
 		device_initialize(&dev->dev);
 		dev_set_drvdata(&dev->dev, (void *)dev);
 		mutex_init(&dev->mlock);
+		mutex_init(&dev->info_exist_lock);
 
 		dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL);
 		if (dev->id < 0) {
@@ -718,6 +719,9 @@ EXPORT_SYMBOL(iio_device_register);
 
 void iio_device_unregister(struct iio_dev *indio_dev)
 {
+	mutex_lock(&indio_dev->info_exist_lock);
+	indio_dev->info = NULL;
+	mutex_unlock(&indio_dev->info_exist_lock);
 	device_unregister(&indio_dev->dev);
 }
 EXPORT_SYMBOL(iio_device_unregister);
Signature · 1 line
1.7.8.4
author maintainer
#2 lore raw

PATCH v6 2/6 staging:iio:core add in kernel interface mapping and getting IIO channels.

In reply to Jonathan Cameron

From: Jonathan Cameron <[email protected]>

Lifted from proposal for in kernel interface built on the out of staging branch.

Two elements here:
* Map as defined in "inkern.h"
* Matching code to actually get the iio_dev and channel
that we want from the global list of IIO devices.
V4: Everything now built if iio is built (rather than being optional)
Removal race condition prevented by using info pointer as a check of removal under a lock.
V3: Drop the option of registering / getting channels using dev pointer. Stick to name only as suggested by Mark Brown (this has caused user confusion in the regulator framework.)
V2: As per Greg KH suggestion, move over to registration by passing the tables into the provider drivers (how regulator does it). This does not prevent us using the original more flexible approach if at a later date there is a usecase that demands it.

---
 drivers/staging/iio/Makefile   |    2 +-
 drivers/staging/iio/consumer.h |   96 +++++++++++++
 drivers/staging/iio/driver.h   |   34 +++++
 drivers/staging/iio/inkern.c   |  292 ++++++++++++++++++++++++++++++++++++++++
 drivers/staging/iio/machine.h  |   24 ++++
 5 files changed, 447 insertions(+), 1 deletions(-)
drivers/staging/iio/Makefile +1 -1
index 657710b..ff059d4 100644
@@ -3,7 +3,7 @@
 #
 
 obj-$(CONFIG_IIO) += industrialio.o
-industrialio-y := industrialio-core.o industrialio-event.o
+industrialio-y := industrialio-core.o industrialio-event.o inkern.o
 industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o
 industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o
 
drivers/staging/iio/consumer.h new file +96 -0

96 lines not on this page · raw message

drivers/staging/iio/driver.h new file +34 -0
new file mode 100644
index 0000000..a4f8b2e
@@ -0,0 +1,34 @@
+/*
+ * Industrial I/O in kernel access map interface.
+ *
+ * Copyright (c) 2011 Jonathan Cameron
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#ifndef _IIO_INKERN_H_
+#define _IIO_INKERN_H_
+
+struct iio_map;
+
+/**
+ * iio_map_array_register() - tell the core about inkernel consumers
+ * @indio_dev:	provider device
+ * @map:	array of mappings specifying association of channel with client
+ */
+int iio_map_array_register(struct iio_dev *indio_dev,
+			   struct iio_map *map);
+
+/**
+ * iio_map_array_unregister() - tell the core to remove consumer mappings
+ * @indio_dev:	provider device
+ * @map:	array of mappings to remove. Note these must have same memory
+ *		addresses as those originally added not just equal parameter
+ *		values.
+ */
+int iio_map_array_unregister(struct iio_dev *indio_dev,
+			     struct iio_map *map);
+
+#endif
drivers/staging/iio/inkern.c new file +292 -0

292 lines not on this page · raw message

drivers/staging/iio/machine.h new file +24 -0
new file mode 100644
index 0000000..0b1f19b
@@ -0,0 +1,24 @@
+/*
+ * Industrial I/O in kernel access map definitions for board files.
+ *
+ * Copyright (c) 2011 Jonathan Cameron
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+/**
+ * struct iio_map - description of link between consumer and device channels
+ * @adc_channel_label:	Label used to identify the channel on the provider.
+ *			This is matched against the datasheet_name element
+ *			of struct iio_chan_spec.
+ * @consumer_dev_name:	Name to uniquely identify the consumer device.
+ * @consumer_channel:	Unique name used to idenitify the channel on the
+ *			consumer side.
+ */
+struct iio_map {
+	const char *adc_channel_label;
+	const char *consumer_dev_name;
+	const char *consumer_channel;
+};
Signature · 1 line
1.7.8.4
author maintainer
#3 lore raw

PATCH v6 3/6 staging:iio: move iio data return types into types.h for use by inkern

In reply to Jonathan Cameron

From: Jonathan Cameron <[email protected]>

In kernel interfaces need these, so make them available.

---
 drivers/staging/iio/iio.h   |    6 ------
 drivers/staging/iio/types.h |    4 ++++
 2 files changed, 4 insertions(+), 6 deletions(-)
drivers/staging/iio/iio.h +0 -6
index 478dbe5..9459c17 100644
@@ -197,12 +197,6 @@ static inline s64 iio_get_time_ns(void)
 #define INDIO_ALL_BUFFER_MODES					\
 	(INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE)
 
-/* Vast majority of this is set by the industrialio subsystem on a
- * call to iio_device_register. */
-#define IIO_VAL_INT 1
-#define IIO_VAL_INT_PLUS_MICRO 2
-#define IIO_VAL_INT_PLUS_NANO 3
-
 struct iio_trigger; /* forward declaration */
 struct iio_dev;
 
drivers/staging/iio/types.h +4 -0
index b7d2647..0c32136 100644
@@ -46,4 +46,8 @@ enum iio_modifier {
 	IIO_MOD_LIGHT_IR,
 };
 
+#define IIO_VAL_INT 1
+#define IIO_VAL_INT_PLUS_MICRO 2
+#define IIO_VAL_INT_PLUS_NANO 3
+
 #endif /* _IIO_TYPES_H_ */
Signature · 1 line
1.7.8.4
author maintainer
#4 lore raw

PATCH v6 4/6 staging:iio::hwmon interface client driver.

In reply to Jonathan Cameron

From: Jonathan Cameron <[email protected]>

Direct copy of version proposed for the non staging branch. Needed here to allow testing of more advanced inkernel interface code.

Minimal support of simple in, curr and temp attributes so far.

---
 drivers/staging/iio/Kconfig     |    7 +
 drivers/staging/iio/Makefile    |    2 +
 drivers/staging/iio/iio_hwmon.c |  232 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 241 insertions(+), 0 deletions(-)
drivers/staging/iio/Kconfig +7 -0
index 90162aa..24c6ed9 100644
@@ -11,6 +11,13 @@ menuconfig IIO
 	  number of different physical interfaces (i2c, spi, etc). See
 	  drivers/staging/iio/Documentation for more information.
 if IIO
+config IIO_ST_HWMON
+	tristate "Hwmon driver that uses channels specified via iio maps"
+	depends on HWMON
+	help
+	  This is a platform driver that in combination with a suitable
+	  map allows IIO devices to provide  basic hwmon functionality
+	  for those channels specified in the map.
 
 config IIO_BUFFER
 	bool "Enable buffer support within IIO"
drivers/staging/iio/Makefile +2 -0
index ff059d4..5075291 100644
@@ -17,6 +17,8 @@ iio_dummy-$(CONFIG_IIO_SIMPLE_DUMMY_BUFFER) += iio_simple_dummy_buffer.o
 
 obj-$(CONFIG_IIO_DUMMY_EVGEN) += iio_dummy_evgen.o
 
+obj-$(CONFIG_IIO_ST_HWMON) += iio_hwmon.o
+
 obj-y += accel/
 obj-y += adc/
 obj-y += addac/
drivers/staging/iio/iio_hwmon.c new file +232 -0

232 lines not on this page · raw message

Signature · 1 line
1.7.8.4
author maintainer
#5 lore raw

PATCH v6 5/6 staging:iio:Documentation in kernel pull description.

In reply to Jonathan Cameron

Very basic description of the way iio consumers work and how to use this functionality.

---
 drivers/staging/iio/Documentation/inkernel.txt |   58 ++++++++++++++++++++++++
 1 files changed, 58 insertions(+), 0 deletions(-)
drivers/staging/iio/Documentation/inkernel.txt new file +58 -0
new file mode 100644
index 0000000..a05823e
@@ -0,0 +1,58 @@
+Industrial I/O Subsystem in kernel consumers.
+
+The IIO subsystem can act as a layer under other elements of the kernel
+providing a means of obtaining ADC type readings or of driving DAC type
+signals.  The functionality supported will grow as use cases arise.
+
+Describing the channel mapping (iio/machine.h)
+
+Channel associations are described using:
+
+struct iio_map {
+	const char *adc_channel_label;
+	const char *consumer_dev_name;
+	const char *consumer_channel;
+};
+
+adc_channel_label identifies the channel on the IIO device by being
+matched against the datasheet_name field of the iio_chan_spec.
+
+consumer_dev_name allows identification of the consumer device.
+This are then used to find the channel mapping from the consumer device (see
+below).
+
+Finally consumer_channel is a string identifying the channel to the consumer.
+(Perhaps 'battery_voltage' or similar).
+
+An array of these structures is then passed to the IIO driver.
+
+Supporting in kernel interfaces in the driver (driver.h)
+
+The driver must provide datasheet_name values for its channels and
+must pass the iio_map structures and a pointer to its own iio_dev structure
+ on to the core via a call to iio_map_array_register.  On removal,
+iio_map_array_unregister reverses this process.
+
+The result of this is that the IIO core now has all the information needed
+to associate a given channel with the consumer requesting it.
+
+Acting as an IIO consumer (consumer.h)
+
+The consumer first has to obtain an iio_channel structure from the core
+by calling iio_channel_get().  The correct channel is identified by:
+
+* matching dev or dev_name against consumer_dev and consumer_dev_name
+* matching consumer_channel against consumer_channel in the map
+
+There are then a number of functions that can be used to get information
+about this channel such as it's current reading.
+
+e.g.
+iio_st_read_channel_raw() - get a reading
+iio_st_read_channel_type() - get the type of channel
+
+There is also provision for retrieving all of the channels associated
+with a given consumer.  This is useful for generic drivers such as
+iio_hwmon where the number and naming of channels is not known by the
+consumer driver.  To do this, use iio_st_channel_get_all.
+
Signature · 1 line
1.7.8.4
author maintainer
#6 lore raw

PATCH v6 6/6 stargate2: example of map configuration for iio to hwmon example.

In reply to Jonathan Cameron

From: Jonathan Cameron <[email protected]>

Do not commit.

---
 arch/arm/mach-pxa/stargate2.c |   24 ++++++++++++++++++++++++
 1 files changed, 24 insertions(+), 0 deletions(-)
arch/arm/mach-pxa/stargate2.c +24 -0
index b0656e15..ce7f0a3 100644
@@ -54,6 +54,8 @@
 #include <linux/mfd/da903x.h>
 #include <linux/sht15.h>
 
+#include "../../../drivers/staging/iio/machine.h"
+
 #include "devices.h"
 #include "generic.h"
 
@@ -406,6 +408,25 @@ static struct i2c_pxa_platform_data i2c_pdata = {
 	.fast_mode = 1,
 };
 
+static struct iio_map max1363_consumer_map[] = {
+	{
+		.adc_channel_label = "AIN1",
+		.consumer_dev_name = "iio_hwmon.0",
+		.consumer_channel = "testchan1",
+	}, {
+		.adc_channel_label = "AIN2",
+		.consumer_dev_name = "iio_hwmon.0",
+		.consumer_channel = "testchan2",
+	},
+	{}
+};
+
+static struct platform_device iio_hwmon_test = {
+	.name = "iio_hwmon",
+};
+
+
+
 static void __init imote2_stargate2_init(void)
 {
 
@@ -561,6 +582,7 @@ static struct i2c_board_info __initdata imote2_i2c_board_info[] = {
 		 * pull up resistors are missing.
 		 */
 		.irq = PXA_GPIO_TO_IRQ(99),
+		.platform_data = max1363_consumer_map,
 	}, { /* ITS400 Sensor board only */
 		.type = "tsl2561",
 		.addr = 0x49,
@@ -945,6 +967,7 @@ static struct i2c_board_info __initdata stargate2_i2c_board_info[] = {
 		 * pull up resistors are missing.
 		 */
 		.irq = PXA_GPIO_TO_IRQ(99),
+		.platform_data = max1363_consumer_map,
 	}, { /* ITS400 Sensor board only */
 		.type = "tsl2561",
 		.addr = 0x49,
@@ -977,6 +1000,7 @@ static struct platform_device *stargate2_devices[] = {
 	&stargate2_sram,
 	&smc91x_device,
 	&sht15,
+	&iio_hwmon_test,
 };
 
 static void __init stargate2_init(void)
Signature · 1 line
1.7.8.4
author maintainer
#7 lore raw

Re: [PATCH 6/6] stargate2: example of map configuration for iio to hwmon example.

Quoted 3 lines · Jonathan Cameron

From: Jonathan Cameron <[email protected]>

Do not commit.

Whilst this example was never meant to be committed, the obvious flaw is that max1363 doesn't actually support these interfaces because I left one patch out. Lets call it 5.5 and stick it before this one. Sorry about that.

Quoted 67 lines
---
 arch/arm/mach-pxa/stargate2.c |   24 ++++++++++++++++++++++++
 1 files changed, 24 insertions(+), 0 deletions(-)
arch/arm/mach-pxa/stargate2.c +24 -0
index b0656e15..ce7f0a3 100644
@@ -54,6 +54,8 @@
 #include <linux/mfd/da903x.h>
 #include <linux/sht15.h>
 
+#include "../../../drivers/staging/iio/machine.h"
+
 #include "devices.h"
 #include "generic.h"
 
@@ -406,6 +408,25 @@ static struct i2c_pxa_platform_data i2c_pdata = {
 	.fast_mode = 1,
 };
 
+static struct iio_map max1363_consumer_map[] = {
+	{
+		.adc_channel_label = "AIN1",
+		.consumer_dev_name = "iio_hwmon.0",
+		.consumer_channel = "testchan1",
+	}, {
+		.adc_channel_label = "AIN2",
+		.consumer_dev_name = "iio_hwmon.0",
+		.consumer_channel = "testchan2",
+	},
+	{}
+};
+
+static struct platform_device iio_hwmon_test = {
+	.name = "iio_hwmon",
+};
+
+
+
 static void __init imote2_stargate2_init(void)
 {
 
@@ -561,6 +582,7 @@ static struct i2c_board_info __initdata imote2_i2c_board_info[] = {
 		 * pull up resistors are missing.
 		 */
 		.irq = PXA_GPIO_TO_IRQ(99),
+		.platform_data = max1363_consumer_map,
 	}, { /* ITS400 Sensor board only */
 		.type = "tsl2561",
 		.addr = 0x49,
@@ -945,6 +967,7 @@ static struct i2c_board_info __initdata stargate2_i2c_board_info[] = {
 		 * pull up resistors are missing.
 		 */
 		.irq = PXA_GPIO_TO_IRQ(99),
+		.platform_data = max1363_consumer_map,
 	}, { /* ITS400 Sensor board only */
 		.type = "tsl2561",
 		.addr = 0x49,
@@ -977,6 +1000,7 @@ static struct platform_device *stargate2_devices[] = {
 	&stargate2_sram,
 	&smc91x_device,
 	&sht15,
+	&iio_hwmon_test,
 };
 
 static void __init stargate2_init(void)
maintainer
#8 lore raw

Re: [PATCH 6/6] stargate2: example of map configuration for iio to hwmon example.

Quoted 7 lines · Jonathan Cameron
Quoted 3 lines · Jonathan Cameron

From: Jonathan Cameron <[email protected]>

Do not commit.

Whilst this example was never meant to be committed, the obvious flaw is that max1363 doesn't actually support these interfaces because I left one patch out. Lets call it 5.5 and stick it before this one.

Huh? I don't understand what you mean here, should I not apply this one?

confused,

greg k-h

#9 lore raw

Re: [PATCH 6/6] stargate2: example of map configuration for iio to hwmon example.

Quoted 11 lines · Greg KH
Quoted 7 lines · Jonathan Cameron
Quoted 3 lines · Jonathan Cameron

From: Jonathan Cameron <[email protected]>

Do not commit.

Whilst this example was never meant to be committed, the obvious flaw is that max1363 doesn't actually support these interfaces because I left one patch out. Lets call it 5.5 and stick it before this one.

Huh? I don't understand what you mean here, should I not apply this one?

Sorry, the confusion here comes from the fact that this set was not yet meant to be a merge request but rather had been sent out for review. You were explicitly cc'd because of the issues you had raised with the previous version (that were hopefully fixed to your satisfaction here). This final patch was there to show how things worked, but should obvously not merge as it uses headers in staging from outside (under arch). The board isn't actually wired like this anyway!

Having said that, the only reason I hadn't sent a new version was a nasty cold so thanks for merging the first 5. The 5.5 one was only really required to support this example, so whilst harmless it wasn't important and I'll tack it on the next set I send out.

Thanks again for pulling these. I guess that means you are happy with the new version!

Jonathan

Quoted 4 lines

confused,

greg k-h

author maintainer
#10 lore raw

PATCH 1/1 staging:iio:max1363 enable use with inkernel interfaces.

In reply to Jonathan Cameron

---
Oops patch 6 doesn't make much sense without this driver support.

 drivers/staging/iio/adc/max1363_core.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)
drivers/staging/iio/adc/max1363_core.c +8 -1
index 3a5bd20..29ab0aa 100644
@@ -36,6 +36,7 @@
 #include "../sysfs.h"
 #include "../events.h"
 #include "../buffer.h"
+#include "../driver.h"
 
 #include "max1363.h"
 
@@ -1268,6 +1269,9 @@ static int __devinit max1363_probe(struct i2c_client *client,
 		ret = -ENOMEM;
 		goto error_disable_reg;
 	}
+	ret = iio_map_array_register(indio_dev, client->dev.platform_data);
+	if (ret < 0)
+		goto error_free_device;
 	st = iio_priv(indio_dev);
 	st->reg = reg;
 	/* this is only used for device removal purposes */
@@ -1281,7 +1285,7 @@ static int __devinit max1363_probe(struct i2c_client *client,
 			  (st->chip_info->num_modes + 1), GFP_KERNEL);
 	if (!indio_dev->available_scan_masks) {
 		ret = -ENOMEM;
-		goto error_free_device;
+		goto error_unregister_map;
 	}
 
 	for (i = 0; i < st->chip_info->num_modes; i++)
@@ -1337,6 +1341,8 @@ error_cleanup_ring:
 	max1363_ring_cleanup(indio_dev);
 error_free_available_scan_masks:
 	kfree(indio_dev->available_scan_masks);
+error_unregister_map:
+	iio_map_array_unregister(indio_dev, client->dev.platform_data);
 error_free_device:
 	iio_free_device(indio_dev);
 error_disable_reg:
@@ -1363,6 +1369,7 @@ static int max1363_remove(struct i2c_client *client)
 		regulator_disable(reg);
 		regulator_put(reg);
 	}
+	iio_map_array_unregister(indio_dev, client->dev.platform_data);
 	iio_free_device(indio_dev);
 
 	return 0;
Signature · 1 line
1.7.8.4
maintainer Applied
#12 lore raw
Quoted 6 lines · Linus Walleij
Quoted 1 line · Jonathan Cameron

Any comments?

Just this:

I've applied the first 5, and then I got confused, care to resend the rest if they are needed/wanted?

thanks,

greg k-h