From 55aebeb926b6f93a540328e7ac770ef536b09b77 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Mon, 10 Nov 2014 14:45:30 +0200 Subject: iio: core: Introduce IIO_ACTIVITY channel This channel will be used for exposing information about activity composite sensors. Activities supported so far: * running * jogging * walking * still THRESHOLD event is used to signal a change in the activity state. We associate a confidence interval for each activity expressed as a percentage from 0 to 100. * 0, means the sensor IS NOT reporting that activity. * 100, means the sensor IS reporting that activity. Users of this interface have two possible means to gather information about the ongoing activities. 1. Event based, via event file descriptor * sensor may report an event when ENTERING an activity or LEAVING an activity based on a threshold value. * drivers will wake up applications waiting data on the event fd 2. Polling, by reading the sysfs associated attribute files: * /sys/bus/iio/devices/iio:device0/in_activity_running_input expressed as percentage confidence value from 0 to 100. This will offer an interface for Android significant motion composite sensor defined here: http://source.android.com/devices/sensors/composite_sensors.html Activities listed above are supported by Freescale's MMA9553 sensor: http://freescale.com/files/sensors/doc/ref_manual/MMA9553LSWRM.pdf Signed-off-by: Irina Tirdea Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- include/linux/iio/types.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'include/linux/iio') diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index 4a2af8adf874..b3a241d53b54 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -30,6 +30,7 @@ enum iio_chan_type { IIO_CCT, IIO_PRESSURE, IIO_HUMIDITYRELATIVE, + IIO_ACTIVITY, }; enum iio_modifier { @@ -59,7 +60,11 @@ enum iio_modifier { IIO_MOD_NORTH_MAGN, IIO_MOD_NORTH_TRUE, IIO_MOD_NORTH_MAGN_TILT_COMP, - IIO_MOD_NORTH_TRUE_TILT_COMP + IIO_MOD_NORTH_TRUE_TILT_COMP, + IIO_MOD_RUNNING, + IIO_MOD_JOGGING, + IIO_MOD_WALKING, + IIO_MOD_STILL, }; enum iio_event_type { -- cgit v1.2.3 From 1843c2f3def16740eb6d129a9790c32dd21aa5ea Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Mon, 10 Nov 2014 14:45:31 +0200 Subject: iio: core: Introduce IIO_EV_DIR_NONE For some events (e.g.: step detector) a direction does not make sense. Add IIO_EV_DIR_NONE to be used with such events and generate sysfs event attributes that do not contain direction. Signed-off-by: Irina Tirdea Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-event.c | 12 +++++++++--- include/linux/iio/types.h | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'include/linux/iio') diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index 0c1e37e3120a..1290290adcb5 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -327,9 +327,15 @@ static int iio_device_add_event(struct iio_dev *indio_dev, for_each_set_bit(i, mask, sizeof(*mask)*8) { if (i >= ARRAY_SIZE(iio_ev_info_text)) return -EINVAL; - postfix = kasprintf(GFP_KERNEL, "%s_%s_%s", - iio_ev_type_text[type], iio_ev_dir_text[dir], - iio_ev_info_text[i]); + if (dir != IIO_EV_DIR_NONE) + postfix = kasprintf(GFP_KERNEL, "%s_%s_%s", + iio_ev_type_text[type], + iio_ev_dir_text[dir], + iio_ev_info_text[i]); + else + postfix = kasprintf(GFP_KERNEL, "%s_%s", + iio_ev_type_text[type], + iio_ev_info_text[i]); if (postfix == NULL) return -ENOMEM; diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index b3a241d53b54..52cb5329407b 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -86,6 +86,7 @@ enum iio_event_direction { IIO_EV_DIR_EITHER, IIO_EV_DIR_RISING, IIO_EV_DIR_FALLING, + IIO_EV_DIR_NONE, }; #define IIO_VAL_INT 1 -- cgit v1.2.3 From a88bfe78583026eb9f21d4014ba481b22b66cee3 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Mon, 10 Nov 2014 14:45:32 +0200 Subject: iio: core: Introduce STEPS channel, ENABLE mask and INSTANCE event These changes are needed to support the functionality of a pedometer. A pedometer has two basic functionalities: step counter and step detector. The step counter needs to be enabled and then it will count the steps in its hardware register. Whenever the application needs to check the step count, it will read the step counter register. To support the step counter a new channel type STEPS is added. Since the pedometer needs to be enabled first so that the hardware can count and store the steps, we need a specific ENABLE channel info mask. The step detector will generate an interrupt each time a step is detected. To support this functionality we add a new event type INSTANCE. For more information on the Android requirements for step counter and step detector see: http://source.android.com/devices/sensors/composite_sensors.html#counter and http://source.android.com/devices/sensors/composite_sensors.html#detector. A device that has the pedometer functionality this interface needs to support is Freescale's MMA9553L: http://www.freescale.com/files/sensors/doc/ref_manual/MMA9553LSWRM.pdf Signed-off-by: Irina Tirdea Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 22 ++++++++++++++++++++++ drivers/iio/industrialio-core.c | 2 ++ drivers/iio/industrialio-event.c | 1 + include/linux/iio/iio.h | 1 + include/linux/iio/types.h | 2 ++ 5 files changed, 28 insertions(+) (limited to 'include/linux/iio') diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 7bf49ad8fd82..c60b0a1af839 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -856,6 +856,13 @@ Description: number or direction is not specified, applies to all channels of this type. +What: /sys/.../events/in_steps_instance_en +KernelVersion: 3.19 +Contact: linux-iio@vger.kernel.org +Description: + Enables or disables step detection. Each time the user takes a step an + event of this type will be generated. + What: /sys/bus/iio/devices/iio:deviceX/trigger/current_trigger KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org @@ -1095,3 +1102,18 @@ Description: after application of scale and offset. If no offset or scale is present, output should be considered as processed with the unit in milliamps. + +What: /sys/.../iio:deviceX/in_steps_en +KernelVersion: 3.19 +Contact: linux-iio@vger.kernel.org +Description: + Activates the step counter. After activation, the number of steps + taken by the user will be counted in hardware and exported through + in_steps_input. + +What: /sys/.../iio:deviceX/in_steps_input +KernelVersion: 3.19 +Contact: linux-iio@vger.kernel.org +Description: + This attribute is used to read the number of steps taken by the user + since the last reboot while activated. diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index e453ef9e0c36..1e060f390b08 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -71,6 +71,7 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_PRESSURE] = "pressure", [IIO_HUMIDITYRELATIVE] = "humidityrelative", [IIO_ACTIVITY] = "activity", + [IIO_STEPS] = "steps", }; static const char * const iio_modifier_names[] = { @@ -118,6 +119,7 @@ static const char * const iio_chan_info_postfix[] = { [IIO_CHAN_INFO_HARDWAREGAIN] = "hardwaregain", [IIO_CHAN_INFO_HYSTERESIS] = "hysteresis", [IIO_CHAN_INFO_INT_TIME] = "integration_time", + [IIO_CHAN_INFO_ENABLE] = "en", }; /** diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index 1290290adcb5..3f5cee0295c5 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -197,6 +197,7 @@ static const char * const iio_ev_type_text[] = { [IIO_EV_TYPE_ROC] = "roc", [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive", [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive", + [IIO_EV_TYPE_INSTANCE] = "instance", }; static const char * const iio_ev_dir_text[] = { diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 3642ce7ef512..f45a400a5e3e 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -38,6 +38,7 @@ enum iio_chan_info_enum { IIO_CHAN_INFO_HARDWAREGAIN, IIO_CHAN_INFO_HYSTERESIS, IIO_CHAN_INFO_INT_TIME, + IIO_CHAN_INFO_ENABLE, }; enum iio_shared_by { diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index 52cb5329407b..904dcbbf0e6f 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -31,6 +31,7 @@ enum iio_chan_type { IIO_PRESSURE, IIO_HUMIDITYRELATIVE, IIO_ACTIVITY, + IIO_STEPS, }; enum iio_modifier { @@ -73,6 +74,7 @@ enum iio_event_type { IIO_EV_TYPE_ROC, IIO_EV_TYPE_THRESH_ADAPTIVE, IIO_EV_TYPE_MAG_ADAPTIVE, + IIO_EV_TYPE_INSTANCE, }; enum iio_event_info { -- cgit v1.2.3 From bcdf28fb1b8badf3cdba18d349f6251057e36a45 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Mon, 10 Nov 2014 14:45:33 +0200 Subject: iio: core: Introduce IIO_CHAN_INFO_CALIBHEIGHT Some devices need the height of the user to compute various parameters. One of this devices is Freescale's MMA9553L (http://www.freescale.com/files/sensors/doc/ref_manual/MMA9553LSWRM.pdf) that needs the height of the user to compute the stride length which is used further to determine distance, speed and activity type. Signed-off-by: Irina Tirdea Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 8 ++++++++ drivers/iio/industrialio-core.c | 1 + include/linux/iio/iio.h | 1 + 3 files changed, 10 insertions(+) (limited to 'include/linux/iio') diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index c60b0a1af839..4a9e29a3c2dc 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -323,6 +323,14 @@ Description: production inaccuracies). If shared across all channels, _calibscale is used. +What: /sys/bus/iio/devices/iio:deviceX/in_steps_calibheight +KernelVersion: 3.19 +Contact: linux-iio@vger.kernel.org +Description: + Height of the user (in centimeters) used by some pedometers + to compute the stride length, distance, speed and activity + type. + What: /sys/bus/iio/devices/iio:deviceX/in_accel_scale_available What: /sys/.../iio:deviceX/in_voltageX_scale_available What: /sys/.../iio:deviceX/in_voltage-voltage_scale_available diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 1e060f390b08..45bb3a43afac 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -120,6 +120,7 @@ static const char * const iio_chan_info_postfix[] = { [IIO_CHAN_INFO_HYSTERESIS] = "hysteresis", [IIO_CHAN_INFO_INT_TIME] = "integration_time", [IIO_CHAN_INFO_ENABLE] = "en", + [IIO_CHAN_INFO_CALIBHEIGHT] = "calibheight", }; /** diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index f45a400a5e3e..878d861b0610 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -39,6 +39,7 @@ enum iio_chan_info_enum { IIO_CHAN_INFO_HYSTERESIS, IIO_CHAN_INFO_INT_TIME, IIO_CHAN_INFO_ENABLE, + IIO_CHAN_INFO_CALIBHEIGHT, }; enum iio_shared_by { -- cgit v1.2.3 From f9380e7123863a4cb0627d940533be954a0a15df Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Thu, 27 Nov 2014 01:42:45 +0300 Subject: iio: inkern: add iio_write_channel_raw Introduce API for easy in-kernel setting of DAC values. Signed-off-by: Dmitry Eremin-Solenikov Signed-off-by: Jonathan Cameron --- drivers/iio/inkern.c | 25 +++++++++++++++++++++++++ include/linux/iio/consumer.h | 10 ++++++++++ 2 files changed, 35 insertions(+) (limited to 'include/linux/iio') diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index 866fe904cba2..21655fd1465c 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -631,3 +631,28 @@ err_unlock: return ret; } EXPORT_SYMBOL_GPL(iio_get_channel_type); + +static int iio_channel_write(struct iio_channel *chan, int val, int val2, + enum iio_chan_info_enum info) +{ + return chan->indio_dev->info->write_raw(chan->indio_dev, + chan->channel, val, val2, info); +} + +int iio_write_channel_raw(struct iio_channel *chan, int val) +{ + int ret; + + mutex_lock(&chan->indio_dev->info_exist_lock); + if (chan->indio_dev->info == NULL) { + ret = -ENODEV; + goto err_unlock; + } + + ret = iio_channel_write(chan, val, 0, IIO_CHAN_INFO_RAW); +err_unlock: + mutex_unlock(&chan->indio_dev->info_exist_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(iio_write_channel_raw); diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h index 651f9a0e2765..6f64624f329b 100644 --- a/include/linux/iio/consumer.h +++ b/include/linux/iio/consumer.h @@ -150,6 +150,16 @@ int iio_read_channel_average_raw(struct iio_channel *chan, int *val); */ int iio_read_channel_processed(struct iio_channel *chan, int *val); +/** + * iio_write_channel_raw() - write to a given channel + * @chan: The channel being queried. + * @val: Value being written. + * + * Note raw writes to iio channels are in dac counts and hence + * scale will need to be applied if standard units required. + */ +int iio_write_channel_raw(struct iio_channel *chan, int val); + /** * iio_get_channel_type() - get the type of a channel * @channel: The channel being queried. -- cgit v1.2.3 From 217a5cf0a1100264ced523e437e2e22c442dca7c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:09 +0100 Subject: iio: Unexport iio_scan_mask_set() Individual drivers should not be messing with the scan mask that contains the list of enabled channels. This is something that is supposed to be managed by the core. Now that the last few drivers that used it to configure a default scan mask have been updated to not do this anymore we can unexport the function. Note, this patch also requires moving a few functions around so they are all declared before the first internal user. Signed-off-by: Lars-Peter Clausen Reviewed-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-buffer.c | 149 +++++++++++++++++++------------------- include/linux/iio/buffer.h | 9 --- 2 files changed, 74 insertions(+), 84 deletions(-) (limited to 'include/linux/iio') diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index f971f79103ec..f667e4e7ea6d 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -178,6 +178,80 @@ static ssize_t iio_scan_el_show(struct device *dev, return sprintf(buf, "%d\n", ret); } +/* Note NULL used as error indicator as it doesn't make sense. */ +static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks, + unsigned int masklength, + const unsigned long *mask) +{ + if (bitmap_empty(mask, masklength)) + return NULL; + while (*av_masks) { + if (bitmap_subset(mask, av_masks, masklength)) + return av_masks; + av_masks += BITS_TO_LONGS(masklength); + } + return NULL; +} + +static bool iio_validate_scan_mask(struct iio_dev *indio_dev, + const unsigned long *mask) +{ + if (!indio_dev->setup_ops->validate_scan_mask) + return true; + + return indio_dev->setup_ops->validate_scan_mask(indio_dev, mask); +} + +/** + * iio_scan_mask_set() - set particular bit in the scan mask + * @indio_dev: the iio device + * @buffer: the buffer whose scan mask we are interested in + * @bit: the bit to be set. + * + * Note that at this point we have no way of knowing what other + * buffers might request, hence this code only verifies that the + * individual buffers request is plausible. + */ +static int iio_scan_mask_set(struct iio_dev *indio_dev, + struct iio_buffer *buffer, int bit) +{ + const unsigned long *mask; + unsigned long *trialmask; + + trialmask = kmalloc(sizeof(*trialmask)* + BITS_TO_LONGS(indio_dev->masklength), + GFP_KERNEL); + + if (trialmask == NULL) + return -ENOMEM; + if (!indio_dev->masklength) { + WARN_ON("Trying to set scanmask prior to registering buffer\n"); + goto err_invalid_mask; + } + bitmap_copy(trialmask, buffer->scan_mask, indio_dev->masklength); + set_bit(bit, trialmask); + + if (!iio_validate_scan_mask(indio_dev, trialmask)) + goto err_invalid_mask; + + if (indio_dev->available_scan_masks) { + mask = iio_scan_mask_match(indio_dev->available_scan_masks, + indio_dev->masklength, + trialmask); + if (!mask) + goto err_invalid_mask; + } + bitmap_copy(buffer->scan_mask, trialmask, indio_dev->masklength); + + kfree(trialmask); + + return 0; + +err_invalid_mask: + kfree(trialmask); + return -EINVAL; +} + static int iio_scan_mask_clear(struct iio_buffer *buffer, int bit) { clear_bit(bit, buffer->scan_mask); @@ -455,21 +529,6 @@ ssize_t iio_buffer_show_enable(struct device *dev, } EXPORT_SYMBOL(iio_buffer_show_enable); -/* Note NULL used as error indicator as it doesn't make sense. */ -static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks, - unsigned int masklength, - const unsigned long *mask) -{ - if (bitmap_empty(mask, masklength)) - return NULL; - while (*av_masks) { - if (bitmap_subset(mask, av_masks, masklength)) - return av_masks; - av_masks += BITS_TO_LONGS(masklength); - } - return NULL; -} - static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const unsigned long *mask, bool timestamp) { @@ -808,66 +867,6 @@ bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev, } EXPORT_SYMBOL_GPL(iio_validate_scan_mask_onehot); -static bool iio_validate_scan_mask(struct iio_dev *indio_dev, - const unsigned long *mask) -{ - if (!indio_dev->setup_ops->validate_scan_mask) - return true; - - return indio_dev->setup_ops->validate_scan_mask(indio_dev, mask); -} - -/** - * iio_scan_mask_set() - set particular bit in the scan mask - * @indio_dev: the iio device - * @buffer: the buffer whose scan mask we are interested in - * @bit: the bit to be set. - * - * Note that at this point we have no way of knowing what other - * buffers might request, hence this code only verifies that the - * individual buffers request is plausible. - */ -int iio_scan_mask_set(struct iio_dev *indio_dev, - struct iio_buffer *buffer, int bit) -{ - const unsigned long *mask; - unsigned long *trialmask; - - trialmask = kmalloc(sizeof(*trialmask)* - BITS_TO_LONGS(indio_dev->masklength), - GFP_KERNEL); - - if (trialmask == NULL) - return -ENOMEM; - if (!indio_dev->masklength) { - WARN_ON("Trying to set scanmask prior to registering buffer\n"); - goto err_invalid_mask; - } - bitmap_copy(trialmask, buffer->scan_mask, indio_dev->masklength); - set_bit(bit, trialmask); - - if (!iio_validate_scan_mask(indio_dev, trialmask)) - goto err_invalid_mask; - - if (indio_dev->available_scan_masks) { - mask = iio_scan_mask_match(indio_dev->available_scan_masks, - indio_dev->masklength, - trialmask); - if (!mask) - goto err_invalid_mask; - } - bitmap_copy(buffer->scan_mask, trialmask, indio_dev->masklength); - - kfree(trialmask); - - return 0; - -err_invalid_mask: - kfree(trialmask); - return -EINVAL; -} -EXPORT_SYMBOL_GPL(iio_scan_mask_set); - int iio_scan_mask_query(struct iio_dev *indio_dev, struct iio_buffer *buffer, int bit) { diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h index 519392763393..8c8ce611949c 100644 --- a/include/linux/iio/buffer.h +++ b/include/linux/iio/buffer.h @@ -116,15 +116,6 @@ void iio_buffer_init(struct iio_buffer *buffer); int iio_scan_mask_query(struct iio_dev *indio_dev, struct iio_buffer *buffer, int bit); -/** - * iio_scan_mask_set() - set particular bit in the scan mask - * @indio_dev IIO device structure - * @buffer: the buffer whose scan mask we are interested in - * @bit: the bit to be set. - **/ -int iio_scan_mask_set(struct iio_dev *indio_dev, - struct iio_buffer *buffer, int bit); - /** * iio_push_to_buffers() - push to a registered buffer. * @indio_dev: iio_dev structure for device. -- cgit v1.2.3 From 3e1b6c95b990c93f4aa3b17e9f66221e2fa44bee Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:12 +0100 Subject: iio: Move buffer registration to the core Originally device and buffer registration were kept as separate operations in IIO to allow to register two distinct sets of channels for buffered and non-buffered operations. This has since already been further restricted and the channel set registered for the buffer needs to be a subset of the channel set registered for the device. Additionally the possibility to not have a raw (or processed) attribute for a channel which was registered for the device was added a while ago. This means it is possible to not register any device level attributes for a channel even if it is registered for the device. Also if a channel's scan_index is set to -1 and the channel is registered for the buffer it is ignored. So in summary it means it is possible to register the same channel array for both the device and the buffer yet still end up with distinctive sets of channels for both of them. This makes the argument for having to have to manually register the channels for both the device and the buffer invalid. Considering that the vast majority of all drivers want to register the same set of channels for both the buffer and the device it makes sense to move the buffer registration into the core to avoid some boiler-plate code in the device driver setup path. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ti_am335x_adc.c | 9 --------- drivers/iio/iio_core.h | 9 +++++++++ drivers/iio/industrialio-buffer.c | 18 ++++++++++------- drivers/iio/industrialio-core.c | 14 ++++++++++++- drivers/iio/industrialio-triggered-buffer.c | 11 +---------- drivers/staging/iio/accel/lis3l02dq_core.c | 13 +------------ drivers/staging/iio/accel/sca3000_core.c | 10 +--------- drivers/staging/iio/iio_simple_dummy_buffer.c | 8 -------- drivers/staging/iio/impedance-analyzer/ad5933.c | 12 ++---------- drivers/staging/iio/meter/ade7758.h | 1 - drivers/staging/iio/meter/ade7758_core.c | 15 ++------------ drivers/staging/iio/meter/ade7758_ring.c | 5 ----- include/linux/iio/buffer.h | 26 ------------------------- 13 files changed, 40 insertions(+), 111 deletions(-) (limited to 'include/linux/iio') diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index b730864731e8..d550ac7d2365 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -264,16 +264,8 @@ static int tiadc_iio_buffered_hardware_setup(struct iio_dev *indio_dev, indio_dev->setup_ops = setup_ops; indio_dev->modes |= INDIO_BUFFER_HARDWARE; - ret = iio_buffer_register(indio_dev, - indio_dev->channels, - indio_dev->num_channels); - if (ret) - goto error_free_irq; - return 0; -error_free_irq: - free_irq(irq, indio_dev); error_kfifo_free: iio_kfifo_free(indio_dev->buffer); return ret; @@ -285,7 +277,6 @@ static void tiadc_iio_buffered_hardware_remove(struct iio_dev *indio_dev) free_irq(adc_dev->mfd_tscadc->irq, indio_dev); iio_kfifo_free(indio_dev->buffer); - iio_buffer_unregister(indio_dev); } diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h index 5f0ea77fe717..359883525ab7 100644 --- a/drivers/iio/iio_core.h +++ b/drivers/iio/iio_core.h @@ -48,6 +48,8 @@ unsigned int iio_buffer_poll(struct file *filp, ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf, size_t n, loff_t *f_ps); +int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev); +void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev); #define iio_buffer_poll_addr (&iio_buffer_poll) #define iio_buffer_read_first_n_outer_addr (&iio_buffer_read_first_n_outer) @@ -60,6 +62,13 @@ void iio_buffer_wakeup_poll(struct iio_dev *indio_dev); #define iio_buffer_poll_addr NULL #define iio_buffer_read_first_n_outer_addr NULL +static inline int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) +{ + return 0; +} + +static inline void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev) {} + static inline void iio_disable_all_buffers(struct iio_dev *indio_dev) {} static inline void iio_buffer_wakeup_poll(struct iio_dev *indio_dev) {} diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index f667e4e7ea6d..8bb3e64eaf2c 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -385,14 +385,16 @@ static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev, static const char * const iio_scan_elements_group_name = "scan_elements"; -int iio_buffer_register(struct iio_dev *indio_dev, - const struct iio_chan_spec *channels, - int num_channels) +int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) { struct iio_dev_attr *p; struct attribute **attr; struct iio_buffer *buffer = indio_dev->buffer; int ret, i, attrn, attrcount, attrcount_orig = 0; + const struct iio_chan_spec *channels; + + if (!buffer) + return 0; if (buffer->attrs) indio_dev->groups[indio_dev->groupcounter++] = buffer->attrs; @@ -404,9 +406,10 @@ int iio_buffer_register(struct iio_dev *indio_dev, } attrcount = attrcount_orig; INIT_LIST_HEAD(&buffer->scan_el_dev_attr_list); + channels = indio_dev->channels; if (channels) { /* new magic */ - for (i = 0; i < num_channels; i++) { + for (i = 0; i < indio_dev->num_channels; i++) { if (channels[i].scan_index < 0) continue; @@ -463,15 +466,16 @@ error_cleanup_dynamic: return ret; } -EXPORT_SYMBOL(iio_buffer_register); -void iio_buffer_unregister(struct iio_dev *indio_dev) +void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev) { + if (!indio_dev->buffer) + return; + kfree(indio_dev->buffer->scan_mask); kfree(indio_dev->buffer->scan_el_group.attrs); iio_free_chan_devattr_list(&indio_dev->buffer->scan_el_dev_attr_list); } -EXPORT_SYMBOL(iio_buffer_unregister); ssize_t iio_buffer_read_length(struct device *dev, struct device_attribute *attr, diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 45bb3a43afac..ee442ee482ab 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -1158,11 +1158,19 @@ int iio_device_register(struct iio_dev *indio_dev) "Failed to register debugfs interfaces\n"); return ret; } + + ret = iio_buffer_alloc_sysfs_and_mask(indio_dev); + if (ret) { + dev_err(indio_dev->dev.parent, + "Failed to create buffer sysfs interfaces\n"); + goto error_unreg_debugfs; + } + ret = iio_device_register_sysfs(indio_dev); if (ret) { dev_err(indio_dev->dev.parent, "Failed to register sysfs interfaces\n"); - goto error_unreg_debugfs; + goto error_buffer_free_sysfs; } ret = iio_device_register_eventset(indio_dev); if (ret) { @@ -1195,6 +1203,8 @@ error_unreg_eventset: iio_device_unregister_eventset(indio_dev); error_free_sysfs: iio_device_unregister_sysfs(indio_dev); +error_buffer_free_sysfs: + iio_buffer_free_sysfs_and_mask(indio_dev); error_unreg_debugfs: iio_device_unregister_debugfs(indio_dev); return ret; @@ -1223,6 +1233,8 @@ void iio_device_unregister(struct iio_dev *indio_dev) iio_buffer_wakeup_poll(indio_dev); mutex_unlock(&indio_dev->info_exist_lock); + + iio_buffer_free_sysfs_and_mask(indio_dev); } EXPORT_SYMBOL(iio_device_unregister); diff --git a/drivers/iio/industrialio-triggered-buffer.c b/drivers/iio/industrialio-triggered-buffer.c index d6f54930b34a..61a5d0404edf 100644 --- a/drivers/iio/industrialio-triggered-buffer.c +++ b/drivers/iio/industrialio-triggered-buffer.c @@ -32,7 +32,7 @@ static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = { * * This function combines some common tasks which will normally be performed * when setting up a triggered buffer. It will allocate the buffer and the - * pollfunc, as well as register the buffer with the IIO core. + * pollfunc. * * Before calling this function the indio_dev structure should already be * completely initialized, but not yet registered. In practice this means that @@ -78,16 +78,8 @@ int iio_triggered_buffer_setup(struct iio_dev *indio_dev, /* Flag that polled ring buffering is possible */ indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - ret = iio_buffer_register(indio_dev, - indio_dev->channels, - indio_dev->num_channels); - if (ret) - goto error_dealloc_pollfunc; - return 0; -error_dealloc_pollfunc: - iio_dealloc_pollfunc(indio_dev->pollfunc); error_kfifo_free: iio_kfifo_free(indio_dev->buffer); error_ret: @@ -101,7 +93,6 @@ EXPORT_SYMBOL(iio_triggered_buffer_setup); */ void iio_triggered_buffer_cleanup(struct iio_dev *indio_dev) { - iio_buffer_unregister(indio_dev); iio_dealloc_pollfunc(indio_dev->pollfunc); iio_kfifo_free(indio_dev->buffer); } diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c index f5e145caffa9..b78c9c5d5588 100644 --- a/drivers/staging/iio/accel/lis3l02dq_core.c +++ b/drivers/staging/iio/accel/lis3l02dq_core.c @@ -716,14 +716,6 @@ static int lis3l02dq_probe(struct spi_device *spi) if (ret) return ret; - ret = iio_buffer_register(indio_dev, - lis3l02dq_channels, - ARRAY_SIZE(lis3l02dq_channels)); - if (ret) { - dev_err(&spi->dev, "failed to initialize the buffer\n"); - goto error_unreg_buffer_funcs; - } - if (spi->irq) { ret = request_threaded_irq(st->us->irq, &lis3l02dq_th, @@ -732,7 +724,7 @@ static int lis3l02dq_probe(struct spi_device *spi) "lis3l02dq", indio_dev); if (ret) - goto error_uninitialize_buffer; + goto error_unreg_buffer_funcs; ret = lis3l02dq_probe_trigger(indio_dev); if (ret) @@ -756,8 +748,6 @@ error_remove_trigger: error_free_interrupt: if (spi->irq) free_irq(st->us->irq, indio_dev); -error_uninitialize_buffer: - iio_buffer_unregister(indio_dev); error_unreg_buffer_funcs: lis3l02dq_unconfigure_buffer(indio_dev); return ret; @@ -804,7 +794,6 @@ static int lis3l02dq_remove(struct spi_device *spi) free_irq(st->us->irq, indio_dev); lis3l02dq_remove_trigger(indio_dev); - iio_buffer_unregister(indio_dev); lis3l02dq_unconfigure_buffer(indio_dev); return 0; diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index aef8c916e07b..9cd04c7147c8 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -1156,11 +1156,6 @@ static int sca3000_probe(struct spi_device *spi) if (ret < 0) return ret; - ret = iio_buffer_register(indio_dev, indio_dev->channels, - indio_dev->num_channels); - if (ret < 0) - goto error_unregister_dev; - if (spi->irq) { ret = request_threaded_irq(spi->irq, NULL, @@ -1169,7 +1164,7 @@ static int sca3000_probe(struct spi_device *spi) "sca3000", indio_dev); if (ret) - goto error_unregister_ring; + goto error_unregister_dev; } sca3000_register_ring_funcs(indio_dev); ret = sca3000_clean_setup(st); @@ -1180,8 +1175,6 @@ static int sca3000_probe(struct spi_device *spi) error_free_irq: if (spi->irq) free_irq(spi->irq, indio_dev); -error_unregister_ring: - iio_buffer_unregister(indio_dev); error_unregister_dev: iio_device_unregister(indio_dev); return ret; @@ -1215,7 +1208,6 @@ static int sca3000_remove(struct spi_device *spi) if (spi->irq) free_irq(spi->irq, indio_dev); iio_device_unregister(indio_dev); - iio_buffer_unregister(indio_dev); sca3000_unconfigure_ring(indio_dev); return 0; diff --git a/drivers/staging/iio/iio_simple_dummy_buffer.c b/drivers/staging/iio/iio_simple_dummy_buffer.c index 35d60d5045dc..a2d72c102119 100644 --- a/drivers/staging/iio/iio_simple_dummy_buffer.c +++ b/drivers/staging/iio/iio_simple_dummy_buffer.c @@ -172,15 +172,8 @@ int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) */ indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - ret = iio_buffer_register(indio_dev, indio_dev->channels, - indio_dev->num_channels); - if (ret) - goto error_dealloc_pollfunc; - return 0; -error_dealloc_pollfunc: - iio_dealloc_pollfunc(indio_dev->pollfunc); error_free_buffer: iio_kfifo_free(indio_dev->buffer); error_ret: @@ -194,7 +187,6 @@ error_ret: */ void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev) { - iio_buffer_unregister(indio_dev); iio_dealloc_pollfunc(indio_dev->pollfunc); iio_kfifo_free(indio_dev->buffer); } diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index aa6a368506cd..c50b1380b9aa 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -752,23 +752,16 @@ static int ad5933_probe(struct i2c_client *client, if (ret) goto error_disable_reg; - ret = iio_buffer_register(indio_dev, ad5933_channels, - ARRAY_SIZE(ad5933_channels)); - if (ret) - goto error_unreg_ring; - ret = ad5933_setup(st); if (ret) - goto error_uninitialize_ring; + goto error_unreg_ring; ret = iio_device_register(indio_dev); if (ret) - goto error_uninitialize_ring; + goto error_unreg_ring; return 0; -error_uninitialize_ring: - iio_buffer_unregister(indio_dev); error_unreg_ring: iio_kfifo_free(indio_dev->buffer); error_disable_reg: @@ -784,7 +777,6 @@ static int ad5933_remove(struct i2c_client *client) struct ad5933_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - iio_buffer_unregister(indio_dev); iio_kfifo_free(indio_dev->buffer); if (!IS_ERR(st->reg)) regulator_disable(st->reg); diff --git a/drivers/staging/iio/meter/ade7758.h b/drivers/staging/iio/meter/ade7758.h index 07318203a836..762d7dc0e6e2 100644 --- a/drivers/staging/iio/meter/ade7758.h +++ b/drivers/staging/iio/meter/ade7758.h @@ -146,7 +146,6 @@ ssize_t ade7758_read_data_from_ring(struct device *dev, int ade7758_configure_ring(struct iio_dev *indio_dev); void ade7758_unconfigure_ring(struct iio_dev *indio_dev); -void ade7758_uninitialize_ring(struct iio_dev *indio_dev); int ade7758_set_irq(struct device *dev, bool enable); int ade7758_spi_write_reg_8(struct device *dev, diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c index abc60067cd72..6e8b01104a68 100644 --- a/drivers/staging/iio/meter/ade7758_core.c +++ b/drivers/staging/iio/meter/ade7758_core.c @@ -885,23 +885,15 @@ static int ade7758_probe(struct spi_device *spi) if (ret) goto error_free_tx; - ret = iio_buffer_register(indio_dev, - &ade7758_channels[0], - ARRAY_SIZE(ade7758_channels)); - if (ret) { - dev_err(&spi->dev, "failed to initialize the ring\n"); - goto error_unreg_ring_funcs; - } - /* Get the device into a sane initial state */ ret = ade7758_initial_setup(indio_dev); if (ret) - goto error_uninitialize_ring; + goto error_unreg_ring_funcs; if (spi->irq) { ret = ade7758_probe_trigger(indio_dev); if (ret) - goto error_uninitialize_ring; + goto error_unreg_ring_funcs; } ret = iio_device_register(indio_dev); @@ -913,8 +905,6 @@ static int ade7758_probe(struct spi_device *spi) error_remove_trigger: if (spi->irq) ade7758_remove_trigger(indio_dev); -error_uninitialize_ring: - ade7758_uninitialize_ring(indio_dev); error_unreg_ring_funcs: ade7758_unconfigure_ring(indio_dev); error_free_tx: @@ -932,7 +922,6 @@ static int ade7758_remove(struct spi_device *spi) iio_device_unregister(indio_dev); ade7758_stop_device(&indio_dev->dev); ade7758_remove_trigger(indio_dev); - ade7758_uninitialize_ring(indio_dev); ade7758_unconfigure_ring(indio_dev); kfree(st->tx); kfree(st->rx); diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c index c0accf8cce93..27c3ed6ca468 100644 --- a/drivers/staging/iio/meter/ade7758_ring.c +++ b/drivers/staging/iio/meter/ade7758_ring.c @@ -181,8 +181,3 @@ error_iio_kfifo_free: iio_kfifo_free(indio_dev->buffer); return ret; } - -void ade7758_uninitialize_ring(struct iio_dev *indio_dev) -{ - iio_buffer_unregister(indio_dev); -} diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h index 8c8ce611949c..b0e006c3db43 100644 --- a/include/linux/iio/buffer.h +++ b/include/linux/iio/buffer.h @@ -150,22 +150,6 @@ static inline int iio_push_to_buffers_with_timestamp(struct iio_dev *indio_dev, 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 - * @channels: the channel descriptions used to construct buffer - * @num_channels: the number of channels - **/ -int iio_buffer_register(struct iio_dev *indio_dev, - const struct iio_chan_spec *channels, - int num_channels); - -/** - * iio_buffer_unregister() - unregister the buffer from IIO core - * @indio_dev: the device with the buffer to be unregistered - **/ -void iio_buffer_unregister(struct iio_dev *indio_dev); - /** * iio_buffer_read_length() - attr func to get number of datums in the buffer **/ @@ -223,16 +207,6 @@ static inline void iio_device_attach_buffer(struct iio_dev *indio_dev, #else /* CONFIG_IIO_BUFFER */ -static inline int iio_buffer_register(struct iio_dev *indio_dev, - const struct iio_chan_spec *channels, - int num_channels) -{ - return 0; -} - -static inline void iio_buffer_unregister(struct iio_dev *indio_dev) -{} - static inline void iio_buffer_get(struct iio_buffer *buffer) {} static inline void iio_buffer_put(struct iio_buffer *buffer) {} -- cgit v1.2.3 From 616dde2a1ea3df9398b1fcc7d6d6516c5fab6183 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:13 +0100 Subject: iio: Remove get_bytes_per_datum() from iio_buffer_access_funcs There haven't been any users of the get_bytes_per_datum() callback for a while. The core assumes that the number of bytes per datum can be calculated based on the enabled channels and the storage size of the channel and iio_compute_scan_bytes() is used to compute this number. So remove the callback. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/kfifo_buf.c | 6 ------ drivers/staging/iio/Documentation/ring.txt | 4 ++-- drivers/staging/iio/accel/sca3000_ring.c | 7 ------- include/linux/iio/buffer.h | 2 -- 4 files changed, 2 insertions(+), 17 deletions(-) (limited to 'include/linux/iio') diff --git a/drivers/iio/kfifo_buf.c b/drivers/iio/kfifo_buf.c index 7134e8ada09a..1258b4e0a722 100644 --- a/drivers/iio/kfifo_buf.c +++ b/drivers/iio/kfifo_buf.c @@ -66,11 +66,6 @@ static struct attribute_group iio_kfifo_attribute_group = { .name = "buffer", }; -static int iio_get_bytes_per_datum_kfifo(struct iio_buffer *r) -{ - return r->bytes_per_datum; -} - static int iio_mark_update_needed_kfifo(struct iio_buffer *r) { struct iio_kfifo *kf = iio_to_kfifo(r); @@ -159,7 +154,6 @@ static const struct iio_buffer_access_funcs kfifo_access_funcs = { .read_first_n = &iio_read_first_n_kfifo, .data_available = iio_kfifo_buf_data_available, .request_update = &iio_request_update_kfifo, - .get_bytes_per_datum = &iio_get_bytes_per_datum_kfifo, .set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo, .get_length = &iio_get_length_kfifo, .set_length = &iio_set_length_kfifo, diff --git a/drivers/staging/iio/Documentation/ring.txt b/drivers/staging/iio/Documentation/ring.txt index e1da43381d0e..434d63a6123a 100644 --- a/drivers/staging/iio/Documentation/ring.txt +++ b/drivers/staging/iio/Documentation/ring.txt @@ -39,8 +39,8 @@ request_update If parameters have changed that require reinitialization or configuration of the buffer this will trigger it. -get_bytes_per_datum, set_bytes_per_datum - Get/set the number of bytes for a complete scan. (All samples + timestamp) +set_bytes_per_datum + Set the number of bytes for a complete scan. (All samples + timestamp) get_length / set_length Get/set the number of complete scans that may be held by the buffer. diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c index 157827651bfa..aa0e5d85bfe2 100644 --- a/drivers/staging/iio/accel/sca3000_ring.c +++ b/drivers/staging/iio/accel/sca3000_ring.c @@ -135,12 +135,6 @@ static int sca3000_ring_get_length(struct iio_buffer *r) return 64; } -/* only valid if resolution is kept at 11bits */ -static int sca3000_ring_get_bytes_per_datum(struct iio_buffer *r) -{ - return 6; -} - static bool sca3000_ring_buf_data_available(struct iio_buffer *r) { return r->stufftoread; @@ -278,7 +272,6 @@ static void sca3000_ring_release(struct iio_buffer *r) static const struct iio_buffer_access_funcs sca3000_ring_access_funcs = { .read_first_n = &sca3000_read_first_n_hw_rb, .get_length = &sca3000_ring_get_length, - .get_bytes_per_datum = &sca3000_ring_get_bytes_per_datum, .data_available = sca3000_ring_buf_data_available, .release = sca3000_ring_release, }; diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h index b0e006c3db43..79cdb3d1b1bc 100644 --- a/include/linux/iio/buffer.h +++ b/include/linux/iio/buffer.h @@ -25,7 +25,6 @@ struct iio_buffer; * available. * @request_update: if a parameter change has been marked, update underlying * storage. - * @get_bytes_per_datum:get current bytes per datum * @set_bytes_per_datum:set number of bytes per datum * @get_length: get number of datums in buffer * @set_length: set number of datums in buffer @@ -49,7 +48,6 @@ struct iio_buffer_access_funcs { int (*request_update)(struct iio_buffer *buffer); - int (*get_bytes_per_datum)(struct iio_buffer *buffer); int (*set_bytes_per_datum)(struct iio_buffer *buffer, size_t bpd); int (*get_length)(struct iio_buffer *buffer); int (*set_length)(struct iio_buffer *buffer, int length); -- cgit v1.2.3 From 08e7e0adaa17205f86894157d86c4bee3c714330 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:15 +0100 Subject: iio: buffer: Allocate standard attributes in the core All buffers want at least the length and the enable attribute. Move the creation of those attributes to the core instead of having to do this in each individual buffer implementation. This allows us to get rid of some boiler-plate code. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-buffer.c | 59 ++++++++++++++++++++++---------- drivers/iio/kfifo_buf.c | 15 -------- drivers/staging/iio/accel/sca3000_ring.c | 14 ++------ include/linux/iio/buffer.h | 37 ++------------------ 4 files changed, 45 insertions(+), 80 deletions(-) (limited to 'include/linux/iio') diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 8cd89eb269c5..ba89357fc096 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -383,9 +383,9 @@ static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev, return ret; } -ssize_t iio_buffer_read_length(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t iio_buffer_read_length(struct device *dev, + struct device_attribute *attr, + char *buf) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_buffer *buffer = indio_dev->buffer; @@ -396,12 +396,10 @@ ssize_t iio_buffer_read_length(struct device *dev, return 0; } -EXPORT_SYMBOL(iio_buffer_read_length); -ssize_t iio_buffer_write_length(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) +static ssize_t iio_buffer_write_length(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_buffer *buffer = indio_dev->buffer; @@ -428,16 +426,14 @@ ssize_t iio_buffer_write_length(struct device *dev, return ret ? ret : len; } -EXPORT_SYMBOL(iio_buffer_write_length); -ssize_t iio_buffer_show_enable(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t iio_buffer_show_enable(struct device *dev, + struct device_attribute *attr, + char *buf) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); return sprintf(buf, "%d\n", iio_buffer_is_active(indio_dev->buffer)); } -EXPORT_SYMBOL(iio_buffer_show_enable); static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const unsigned long *mask, bool timestamp) @@ -724,10 +720,10 @@ out_unlock: } EXPORT_SYMBOL_GPL(iio_update_buffers); -ssize_t iio_buffer_store_enable(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) +static ssize_t iio_buffer_store_enable(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) { int ret; bool requested_state; @@ -759,10 +755,14 @@ done: mutex_unlock(&indio_dev->mlock); return (ret < 0) ? ret : len; } -EXPORT_SYMBOL(iio_buffer_store_enable); static const char * const iio_scan_elements_group_name = "scan_elements"; +static DEVICE_ATTR(length, S_IRUGO | S_IWUSR, iio_buffer_read_length, + iio_buffer_write_length); +static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, + iio_buffer_show_enable, iio_buffer_store_enable); + int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) { struct iio_dev_attr *p; @@ -774,6 +774,27 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) if (!buffer) return 0; + attrcount = 0; + if (buffer->attrs) { + while (buffer->attrs[attrcount] != NULL) + attrcount++; + } + + buffer->buffer_group.name = "buffer"; + buffer->buffer_group.attrs = kcalloc(attrcount + 3, + sizeof(*buffer->buffer_group.attrs), GFP_KERNEL); + if (!buffer->buffer_group.attrs) + return -ENOMEM; + + buffer->buffer_group.attrs[0] = &dev_attr_length.attr; + buffer->buffer_group.attrs[1] = &dev_attr_enable.attr; + if (buffer->attrs) + memcpy(&buffer->buffer_group.attrs[2], buffer->attrs, + sizeof(*&buffer->buffer_group.attrs) * (attrcount - 2)); + buffer->buffer_group.attrs[attrcount+2] = NULL; + + indio_dev->groups[indio_dev->groupcounter++] = &buffer->buffer_group; + if (buffer->scan_el_attrs != NULL) { attr = buffer->scan_el_attrs->attrs; while (*attr++ != NULL) @@ -838,6 +859,7 @@ error_free_scan_mask: kfree(buffer->scan_mask); error_cleanup_dynamic: iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list); + kfree(indio_dev->buffer->buffer_group.attrs); return ret; } @@ -848,6 +870,7 @@ void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev) return; kfree(indio_dev->buffer->scan_mask); + kfree(indio_dev->buffer->buffer_group.attrs); kfree(indio_dev->buffer->scan_el_group.attrs); iio_free_chan_devattr_list(&indio_dev->buffer->scan_el_dev_attr_list); } diff --git a/drivers/iio/kfifo_buf.c b/drivers/iio/kfifo_buf.c index 1258b4e0a722..3b0a3bc4f0ad 100644 --- a/drivers/iio/kfifo_buf.c +++ b/drivers/iio/kfifo_buf.c @@ -52,20 +52,6 @@ static int iio_get_length_kfifo(struct iio_buffer *r) return r->length; } -static IIO_BUFFER_ENABLE_ATTR; -static IIO_BUFFER_LENGTH_ATTR; - -static struct attribute *iio_kfifo_attributes[] = { - &dev_attr_length.attr, - &dev_attr_enable.attr, - NULL, -}; - -static struct attribute_group iio_kfifo_attribute_group = { - .attrs = iio_kfifo_attributes, - .name = "buffer", -}; - static int iio_mark_update_needed_kfifo(struct iio_buffer *r) { struct iio_kfifo *kf = iio_to_kfifo(r); @@ -169,7 +155,6 @@ struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev) return NULL; kf->update_needed = true; iio_buffer_init(&kf->buffer); - kf->buffer.attrs = &iio_kfifo_attribute_group; kf->buffer.access = &kfifo_access_funcs; kf->buffer.length = 2; mutex_init(&kf->user_lock); diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c index aa0e5d85bfe2..f2f260e01550 100644 --- a/drivers/staging/iio/accel/sca3000_ring.c +++ b/drivers/staging/iio/accel/sca3000_ring.c @@ -140,9 +140,6 @@ static bool sca3000_ring_buf_data_available(struct iio_buffer *r) return r->stufftoread; } -static IIO_BUFFER_ENABLE_ATTR; -static IIO_BUFFER_LENGTH_ATTR; - /** * sca3000_query_ring_int() is the hardware ring status interrupt enabled **/ @@ -232,20 +229,13 @@ static IIO_DEVICE_ATTR(in_accel_scale, * only apply to the ring buffer. At all times full rate and accuracy * is available via direct reading from registers. */ -static struct attribute *sca3000_ring_attributes[] = { - &dev_attr_length.attr, - &dev_attr_enable.attr, +static const struct attribute *sca3000_ring_attributes[] = { &iio_dev_attr_50_percent.dev_attr.attr, &iio_dev_attr_75_percent.dev_attr.attr, &iio_dev_attr_in_accel_scale.dev_attr.attr, NULL, }; -static struct attribute_group sca3000_ring_attr = { - .attrs = sca3000_ring_attributes, - .name = "buffer", -}; - static struct iio_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev) { struct iio_buffer *buf; @@ -258,7 +248,7 @@ static struct iio_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev) ring->private = indio_dev; buf = &ring->buf; buf->stufftoread = 0; - buf->attrs = &sca3000_ring_attr; + buf->attrs = sca3000_ring_attributes; iio_buffer_init(buf); return buf; diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h index 79cdb3d1b1bc..16b7663036f2 100644 --- a/include/linux/iio/buffer.h +++ b/include/linux/iio/buffer.h @@ -83,10 +83,11 @@ struct iio_buffer { bool scan_timestamp; const struct iio_buffer_access_funcs *access; struct list_head scan_el_dev_attr_list; + struct attribute_group buffer_group; struct attribute_group scan_el_group; wait_queue_head_t pollq; bool stufftoread; - const struct attribute_group *attrs; + const struct attribute **attrs; struct list_head demux_list; void *demux_bounce; struct list_head buffer_list; @@ -148,40 +149,6 @@ static inline int iio_push_to_buffers_with_timestamp(struct iio_dev *indio_dev, int iio_update_demux(struct iio_dev *indio_dev); -/** - * iio_buffer_read_length() - attr func to get number of datums in the buffer - **/ -ssize_t iio_buffer_read_length(struct device *dev, - struct device_attribute *attr, - char *buf); -/** - * iio_buffer_write_length() - attr func to set number of datums in the buffer - **/ -ssize_t iio_buffer_write_length(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len); -/** - * iio_buffer_store_enable() - attr to turn the buffer on - **/ -ssize_t iio_buffer_store_enable(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len); -/** - * iio_buffer_show_enable() - attr to see if the buffer is on - **/ -ssize_t iio_buffer_show_enable(struct device *dev, - struct device_attribute *attr, - char *buf); -#define IIO_BUFFER_LENGTH_ATTR DEVICE_ATTR(length, S_IRUGO | S_IWUSR, \ - iio_buffer_read_length, \ - iio_buffer_write_length) - -#define IIO_BUFFER_ENABLE_ATTR DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, \ - iio_buffer_show_enable, \ - iio_buffer_store_enable) - bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev, const unsigned long *mask); -- cgit v1.2.3 From 374956600ecbedf5ca29c76bde114160eb805091 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:17 +0100 Subject: iio: buffer: Drop get_length callback We already do have the length field in the struct iio_buffer which is expected to be in sync with the current size of the buffer. And currently all implementations of the get_length callback either return this field or a constant number. This patch removes the get_length callback and replaces all occurrences in the IIO core with directly accessing the length field of the buffer. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-buffer.c | 11 +++-------- drivers/iio/kfifo_buf.c | 6 ------ drivers/staging/iio/Documentation/ring.txt | 4 ++-- drivers/staging/iio/accel/sca3000_ring.c | 8 +------- include/linux/iio/buffer.h | 2 -- 5 files changed, 6 insertions(+), 25 deletions(-) (limited to 'include/linux/iio') diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 4ca4c0a09923..2bd8d399f2ec 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -390,11 +390,7 @@ static ssize_t iio_buffer_read_length(struct device *dev, struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_buffer *buffer = indio_dev->buffer; - if (buffer->access->get_length) - return sprintf(buf, "%d\n", - buffer->access->get_length(buffer)); - - return 0; + return sprintf(buf, "%d\n", buffer->length); } static ssize_t iio_buffer_write_length(struct device *dev, @@ -410,9 +406,8 @@ static ssize_t iio_buffer_write_length(struct device *dev, if (ret) return ret; - if (buffer->access->get_length) - if (val == buffer->access->get_length(buffer)) - return len; + if (val == buffer->length) + return len; mutex_lock(&indio_dev->mlock); if (iio_buffer_is_active(indio_dev->buffer)) { diff --git a/drivers/iio/kfifo_buf.c b/drivers/iio/kfifo_buf.c index 3b0a3bc4f0ad..b20a9cfbc8ed 100644 --- a/drivers/iio/kfifo_buf.c +++ b/drivers/iio/kfifo_buf.c @@ -47,11 +47,6 @@ static int iio_request_update_kfifo(struct iio_buffer *r) return ret; } -static int iio_get_length_kfifo(struct iio_buffer *r) -{ - return r->length; -} - static int iio_mark_update_needed_kfifo(struct iio_buffer *r) { struct iio_kfifo *kf = iio_to_kfifo(r); @@ -141,7 +136,6 @@ static const struct iio_buffer_access_funcs kfifo_access_funcs = { .data_available = iio_kfifo_buf_data_available, .request_update = &iio_request_update_kfifo, .set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo, - .get_length = &iio_get_length_kfifo, .set_length = &iio_set_length_kfifo, .release = &iio_kfifo_buffer_release, }; diff --git a/drivers/staging/iio/Documentation/ring.txt b/drivers/staging/iio/Documentation/ring.txt index 434d63a6123a..18718fcaf259 100644 --- a/drivers/staging/iio/Documentation/ring.txt +++ b/drivers/staging/iio/Documentation/ring.txt @@ -42,6 +42,6 @@ request_update set_bytes_per_datum Set the number of bytes for a complete scan. (All samples + timestamp) -get_length / set_length - Get/set the number of complete scans that may be held by the buffer. +set_length + Set the number of complete scans that may be held by the buffer. diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c index f2f260e01550..f76a26885808 100644 --- a/drivers/staging/iio/accel/sca3000_ring.c +++ b/drivers/staging/iio/accel/sca3000_ring.c @@ -129,12 +129,6 @@ error_ret: return ret ? ret : num_read; } -/* This is only valid with all 3 elements enabled */ -static int sca3000_ring_get_length(struct iio_buffer *r) -{ - return 64; -} - static bool sca3000_ring_buf_data_available(struct iio_buffer *r) { return r->stufftoread; @@ -248,6 +242,7 @@ static struct iio_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev) ring->private = indio_dev; buf = &ring->buf; buf->stufftoread = 0; + buf->length = 64; buf->attrs = sca3000_ring_attributes; iio_buffer_init(buf); @@ -261,7 +256,6 @@ static void sca3000_ring_release(struct iio_buffer *r) static const struct iio_buffer_access_funcs sca3000_ring_access_funcs = { .read_first_n = &sca3000_read_first_n_hw_rb, - .get_length = &sca3000_ring_get_length, .data_available = sca3000_ring_buf_data_available, .release = sca3000_ring_release, }; diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h index 16b7663036f2..b65850a41127 100644 --- a/include/linux/iio/buffer.h +++ b/include/linux/iio/buffer.h @@ -26,7 +26,6 @@ struct iio_buffer; * @request_update: if a parameter change has been marked, update underlying * storage. * @set_bytes_per_datum:set number of bytes per datum - * @get_length: get number of datums in buffer * @set_length: set number of datums in buffer * @release: called when the last reference to the buffer is dropped, * should free all resources allocated by the buffer. @@ -49,7 +48,6 @@ struct iio_buffer_access_funcs { int (*request_update)(struct iio_buffer *buffer); int (*set_bytes_per_datum)(struct iio_buffer *buffer, size_t bpd); - int (*get_length)(struct iio_buffer *buffer); int (*set_length)(struct iio_buffer *buffer, int length); void (*release)(struct iio_buffer *buffer); -- cgit v1.2.3 From 09546a30632fd35996373146657d5a0296fd37ca Mon Sep 17 00:00:00 2001 From: "Ivan T. Ivanov" Date: Tue, 23 Sep 2014 15:51:42 +0300 Subject: iio: consumer.h: Fix scale factor in function comment 1 milivolt is equal to 1000000 nanovolts. Signed-off-by: Ivan T. Ivanov Signed-off-by: Jonathan Cameron --- include/linux/iio/consumer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux/iio') diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h index 6f64624f329b..26fb8f6342bb 100644 --- a/include/linux/iio/consumer.h +++ b/include/linux/iio/consumer.h @@ -201,7 +201,7 @@ int iio_read_channel_scale(struct iio_channel *chan, int *val, * The scale factor allows to increase the precession of the returned value. For * a scale factor of 1 the function will return the result in the normal IIO * unit for the channel type. E.g. millivolt for voltage channels, if you want - * nanovolts instead pass 1000 as the scale factor. + * nanovolts instead pass 1000000 as the scale factor. */ int iio_convert_raw_to_processed(struct iio_channel *chan, int raw, int *processed, unsigned int scale); -- cgit v1.2.3 From 7ab374a053a43050117eb452306b6cd9dcb58cfd Mon Sep 17 00:00:00 2001 From: Karol Wrona Date: Fri, 19 Dec 2014 18:39:24 +0100 Subject: iio: kfifo: Remove unused argument in iio_kfifo_allocate indio_dev was unused in function body plus some small style fix - add new lines after "if(sth) return sth" and before the last return statement. The argument was removed also in its client. Signed-off-by: Karol Wrona Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ti_am335x_adc.c | 2 +- drivers/iio/industrialio-triggered-buffer.c | 2 +- drivers/iio/kfifo_buf.c | 6 ++++-- drivers/staging/iio/accel/lis3l02dq_ring.c | 2 +- drivers/staging/iio/iio_simple_dummy_buffer.c | 2 +- drivers/staging/iio/impedance-analyzer/ad5933.c | 2 +- drivers/staging/iio/meter/ade7758_ring.c | 2 +- include/linux/iio/kfifo_buf.h | 2 +- 8 files changed, 11 insertions(+), 9 deletions(-) (limited to 'include/linux/iio') diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index d550ac7d2365..5eea299518a3 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -250,7 +250,7 @@ static int tiadc_iio_buffered_hardware_setup(struct iio_dev *indio_dev, struct iio_buffer *buffer; int ret; - buffer = iio_kfifo_allocate(indio_dev); + buffer = iio_kfifo_allocate(); if (!buffer) return -ENOMEM; diff --git a/drivers/iio/industrialio-triggered-buffer.c b/drivers/iio/industrialio-triggered-buffer.c index 61a5d0404edf..15a5341b5e7b 100644 --- a/drivers/iio/industrialio-triggered-buffer.c +++ b/drivers/iio/industrialio-triggered-buffer.c @@ -49,7 +49,7 @@ int iio_triggered_buffer_setup(struct iio_dev *indio_dev, struct iio_buffer *buffer; int ret; - buffer = iio_kfifo_allocate(indio_dev); + buffer = iio_kfifo_allocate(); if (!buffer) { ret = -ENOMEM; goto error_ret; diff --git a/drivers/iio/kfifo_buf.c b/drivers/iio/kfifo_buf.c index b20a9cfbc8ed..7f6fad658e83 100644 --- a/drivers/iio/kfifo_buf.c +++ b/drivers/iio/kfifo_buf.c @@ -140,18 +140,20 @@ static const struct iio_buffer_access_funcs kfifo_access_funcs = { .release = &iio_kfifo_buffer_release, }; -struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev) +struct iio_buffer *iio_kfifo_allocate(void) { struct iio_kfifo *kf; - kf = kzalloc(sizeof *kf, GFP_KERNEL); + kf = kzalloc(sizeof(*kf), GFP_KERNEL); if (!kf) return NULL; + kf->update_needed = true; iio_buffer_init(&kf->buffer); kf->buffer.access = &kfifo_access_funcs; kf->buffer.length = 2; mutex_init(&kf->user_lock); + return &kf->buffer; } EXPORT_SYMBOL(iio_kfifo_allocate); diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c index 9efc77b0ebdd..1fd90090a633 100644 --- a/drivers/staging/iio/accel/lis3l02dq_ring.c +++ b/drivers/staging/iio/accel/lis3l02dq_ring.c @@ -393,7 +393,7 @@ int lis3l02dq_configure_buffer(struct iio_dev *indio_dev) int ret; struct iio_buffer *buffer; - buffer = iio_kfifo_allocate(indio_dev); + buffer = iio_kfifo_allocate(); if (!buffer) return -ENOMEM; diff --git a/drivers/staging/iio/iio_simple_dummy_buffer.c b/drivers/staging/iio/iio_simple_dummy_buffer.c index a2d72c102119..360a4c980722 100644 --- a/drivers/staging/iio/iio_simple_dummy_buffer.c +++ b/drivers/staging/iio/iio_simple_dummy_buffer.c @@ -121,7 +121,7 @@ int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) struct iio_buffer *buffer; /* Allocate a buffer to use - here a kfifo */ - buffer = iio_kfifo_allocate(indio_dev); + buffer = iio_kfifo_allocate(); if (buffer == NULL) { ret = -ENOMEM; goto error_ret; diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index c50b1380b9aa..39f60aca0838 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -626,7 +626,7 @@ static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev) { struct iio_buffer *buffer; - buffer = iio_kfifo_allocate(indio_dev); + buffer = iio_kfifo_allocate(); if (!buffer) return -ENOMEM; diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c index 27c3ed6ca468..782fd9a3bc0d 100644 --- a/drivers/staging/iio/meter/ade7758_ring.c +++ b/drivers/staging/iio/meter/ade7758_ring.c @@ -119,7 +119,7 @@ int ade7758_configure_ring(struct iio_dev *indio_dev) struct iio_buffer *buffer; int ret = 0; - buffer = iio_kfifo_allocate(indio_dev); + buffer = iio_kfifo_allocate(); if (!buffer) { ret = -ENOMEM; return ret; diff --git a/include/linux/iio/kfifo_buf.h b/include/linux/iio/kfifo_buf.h index 25eeac762e84..1a8d57a41738 100644 --- a/include/linux/iio/kfifo_buf.h +++ b/include/linux/iio/kfifo_buf.h @@ -5,7 +5,7 @@ #include #include -struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev); +struct iio_buffer *iio_kfifo_allocate(void); void iio_kfifo_free(struct iio_buffer *r); #endif -- cgit v1.2.3 From 780103fef5c88a97fb9c8d0079bf326ed6147f1f Mon Sep 17 00:00:00 2001 From: Karol Wrona Date: Fri, 19 Dec 2014 18:39:25 +0100 Subject: iio: kfifo: Add resource management devm_iio_kfifo_allocate/free iio kfifo allocate/free gained their devm_ wrappers. Signed-off-by: Karol Wrona Suggested-by: Jonathan Cameron Signed-off-by: Jonathan Cameron --- Documentation/driver-model/devres.txt | 2 ++ drivers/iio/kfifo_buf.c | 54 +++++++++++++++++++++++++++++++++++ include/linux/iio/kfifo_buf.h | 3 ++ 3 files changed, 59 insertions(+) (limited to 'include/linux/iio') diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index b5ab416cd53a..6d1e8eeb5990 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -258,6 +258,8 @@ IIO devm_iio_device_free() devm_iio_device_register() devm_iio_device_unregister() + devm_iio_kfifo_allocate() + devm_iio_kfifo_free() devm_iio_trigger_alloc() devm_iio_trigger_free() diff --git a/drivers/iio/kfifo_buf.c b/drivers/iio/kfifo_buf.c index 7f6fad658e83..b2beea01c49b 100644 --- a/drivers/iio/kfifo_buf.c +++ b/drivers/iio/kfifo_buf.c @@ -164,4 +164,58 @@ void iio_kfifo_free(struct iio_buffer *r) } EXPORT_SYMBOL(iio_kfifo_free); +static void devm_iio_kfifo_release(struct device *dev, void *res) +{ + iio_kfifo_free(*(struct iio_buffer **)res); +} + +static int devm_iio_kfifo_match(struct device *dev, void *res, void *data) +{ + struct iio_buffer **r = res; + + if (WARN_ON(!r || !*r)) + return 0; + + return *r == data; +} + +/** + * devm_iio_fifo_allocate - Resource-managed iio_kfifo_allocate() + * @dev: Device to allocate kfifo buffer for + * + * RETURNS: + * Pointer to allocated iio_buffer on success, NULL on failure. + */ +struct iio_buffer *devm_iio_kfifo_allocate(struct device *dev) +{ + struct iio_buffer **ptr, *r; + + ptr = devres_alloc(devm_iio_kfifo_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return NULL; + + r = iio_kfifo_allocate(); + if (r) { + *ptr = r; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return r; +} +EXPORT_SYMBOL(devm_iio_kfifo_allocate); + +/** + * devm_iio_fifo_free - Resource-managed iio_kfifo_free() + * @dev: Device the buffer belongs to + * @r: The buffer associated with the device + */ +void devm_iio_kfifo_free(struct device *dev, struct iio_buffer *r) +{ + WARN_ON(devres_release(dev, devm_iio_kfifo_release, + devm_iio_kfifo_match, r)); +} +EXPORT_SYMBOL(devm_iio_kfifo_free); + MODULE_LICENSE("GPL"); diff --git a/include/linux/iio/kfifo_buf.h b/include/linux/iio/kfifo_buf.h index 1a8d57a41738..1683bc710d14 100644 --- a/include/linux/iio/kfifo_buf.h +++ b/include/linux/iio/kfifo_buf.h @@ -8,4 +8,7 @@ struct iio_buffer *iio_kfifo_allocate(void); void iio_kfifo_free(struct iio_buffer *r); +struct iio_buffer *devm_iio_kfifo_allocate(struct device *dev); +void devm_iio_kfifo_free(struct device *dev, struct iio_buffer *r); + #endif -- cgit v1.2.3