IIO: in kernel (as opposed to userspace) pull consumers
Subsystems (6)
Jonathan Cameron
maintainerv6 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
Jonathan Cameron
maintainerPATCH 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
@@ -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
@@ -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
Jonathan Cameron
maintainerPATCH v6 2/6 staging:iio:core add in kernel interface mapping and getting IIO channels.
In reply to Jonathan CameronFrom: 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
@@ -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
@@ -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
@@ -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
Jonathan Cameron
maintainerPATCH v6 3/6 staging:iio: move iio data return types into types.h for use by inkern
In reply to Jonathan CameronFrom: 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
@@ -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
@@ -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
Jonathan Cameron
maintainerPATCH v6 4/6 staging:iio::hwmon interface client driver.
In reply to Jonathan CameronFrom: 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
@@ -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
@@ -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
Jonathan Cameron
maintainerPATCH v6 5/6 staging:iio:Documentation in kernel pull description.
In reply to Jonathan CameronVery 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
@@ -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
Jonathan Cameron
maintainerPATCH v6 6/6 stargate2: example of map configuration for iio to hwmon example.
In reply to Jonathan CameronFrom: 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
@@ -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
Jonathan Cameron
maintainerRe: [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@@ -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 )
Greg KH
maintainerRe: [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
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
Jonathan Cameron
maintainerPATCH 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
@@ -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
Quoted 1 line · Jonathan Cameron
Any comments?
Just this:
Yours,
Linus Walleij
Quoted 6 lines · Linus Walleij
Quoted 1 line · Jonathan Cameron
Any comments?
Just this:
Acked-by Linus Walleij <[email protected]>
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