Merge 3.4-rc5 into staging-next
This resolves the conflict in: drivers/staging/vt6656/ioctl.c Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Цей коміт міститься в:
293
drivers/iio/inkern.c
Звичайний файл
293
drivers/iio/inkern.c
Звичайний файл
@@ -0,0 +1,293 @@
|
||||
/* The industrial I/O core in kernel channel mapping
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include <linux/err.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
#include "iio_core.h"
|
||||
#include <linux/iio/machine.h>
|
||||
#include <linux/iio/driver.h>
|
||||
#include <linux/iio/consumer.h>
|
||||
|
||||
struct iio_map_internal {
|
||||
struct iio_dev *indio_dev;
|
||||
struct iio_map *map;
|
||||
struct list_head l;
|
||||
};
|
||||
|
||||
static LIST_HEAD(iio_map_list);
|
||||
static DEFINE_MUTEX(iio_map_list_lock);
|
||||
|
||||
int iio_map_array_register(struct iio_dev *indio_dev, struct iio_map *maps)
|
||||
{
|
||||
int i = 0, ret = 0;
|
||||
struct iio_map_internal *mapi;
|
||||
|
||||
if (maps == NULL)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&iio_map_list_lock);
|
||||
while (maps[i].consumer_dev_name != NULL) {
|
||||
mapi = kzalloc(sizeof(*mapi), GFP_KERNEL);
|
||||
if (mapi == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto error_ret;
|
||||
}
|
||||
mapi->map = &maps[i];
|
||||
mapi->indio_dev = indio_dev;
|
||||
list_add(&mapi->l, &iio_map_list);
|
||||
i++;
|
||||
}
|
||||
error_ret:
|
||||
mutex_unlock(&iio_map_list_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iio_map_array_register);
|
||||
|
||||
|
||||
/* Assumes the exact same array (e.g. memory locations)
|
||||
* used at unregistration as used at registration rather than
|
||||
* more complex checking of contents.
|
||||
*/
|
||||
int iio_map_array_unregister(struct iio_dev *indio_dev,
|
||||
struct iio_map *maps)
|
||||
{
|
||||
int i = 0, ret = 0;
|
||||
bool found_it;
|
||||
struct iio_map_internal *mapi;
|
||||
|
||||
if (maps == NULL)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&iio_map_list_lock);
|
||||
while (maps[i].consumer_dev_name != NULL) {
|
||||
found_it = false;
|
||||
list_for_each_entry(mapi, &iio_map_list, l)
|
||||
if (&maps[i] == mapi->map) {
|
||||
list_del(&mapi->l);
|
||||
kfree(mapi);
|
||||
found_it = true;
|
||||
break;
|
||||
}
|
||||
if (found_it == false) {
|
||||
ret = -ENODEV;
|
||||
goto error_ret;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
error_ret:
|
||||
mutex_unlock(&iio_map_list_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iio_map_array_unregister);
|
||||
|
||||
static const struct iio_chan_spec
|
||||
*iio_chan_spec_from_name(const struct iio_dev *indio_dev,
|
||||
const char *name)
|
||||
{
|
||||
int i;
|
||||
const struct iio_chan_spec *chan = NULL;
|
||||
|
||||
for (i = 0; i < indio_dev->num_channels; i++)
|
||||
if (indio_dev->channels[i].datasheet_name &&
|
||||
strcmp(name, indio_dev->channels[i].datasheet_name) == 0) {
|
||||
chan = &indio_dev->channels[i];
|
||||
break;
|
||||
}
|
||||
return chan;
|
||||
}
|
||||
|
||||
|
||||
struct iio_channel *iio_st_channel_get(const char *name,
|
||||
const char *channel_name)
|
||||
{
|
||||
struct iio_map_internal *c_i = NULL, *c = NULL;
|
||||
struct iio_channel *channel;
|
||||
|
||||
if (name == NULL && channel_name == NULL)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
/* first find matching entry the channel map */
|
||||
mutex_lock(&iio_map_list_lock);
|
||||
list_for_each_entry(c_i, &iio_map_list, l) {
|
||||
if ((name && strcmp(name, c_i->map->consumer_dev_name) != 0) ||
|
||||
(channel_name &&
|
||||
strcmp(channel_name, c_i->map->consumer_channel) != 0))
|
||||
continue;
|
||||
c = c_i;
|
||||
get_device(&c->indio_dev->dev);
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&iio_map_list_lock);
|
||||
if (c == NULL)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
channel = kmalloc(sizeof(*channel), GFP_KERNEL);
|
||||
if (channel == NULL)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
channel->indio_dev = c->indio_dev;
|
||||
|
||||
if (c->map->adc_channel_label)
|
||||
channel->channel =
|
||||
iio_chan_spec_from_name(channel->indio_dev,
|
||||
c->map->adc_channel_label);
|
||||
|
||||
return channel;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iio_st_channel_get);
|
||||
|
||||
void iio_st_channel_release(struct iio_channel *channel)
|
||||
{
|
||||
put_device(&channel->indio_dev->dev);
|
||||
kfree(channel);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iio_st_channel_release);
|
||||
|
||||
struct iio_channel *iio_st_channel_get_all(const char *name)
|
||||
{
|
||||
struct iio_channel *chans;
|
||||
struct iio_map_internal *c = NULL;
|
||||
int nummaps = 0;
|
||||
int mapind = 0;
|
||||
int i, ret;
|
||||
|
||||
if (name == NULL)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
mutex_lock(&iio_map_list_lock);
|
||||
/* first count the matching maps */
|
||||
list_for_each_entry(c, &iio_map_list, l)
|
||||
if (name && strcmp(name, c->map->consumer_dev_name) != 0)
|
||||
continue;
|
||||
else
|
||||
nummaps++;
|
||||
|
||||
if (nummaps == 0) {
|
||||
ret = -ENODEV;
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
/* NULL terminated array to save passing size */
|
||||
chans = kzalloc(sizeof(*chans)*(nummaps + 1), GFP_KERNEL);
|
||||
if (chans == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
/* for each map fill in the chans element */
|
||||
list_for_each_entry(c, &iio_map_list, l) {
|
||||
if (name && strcmp(name, c->map->consumer_dev_name) != 0)
|
||||
continue;
|
||||
chans[mapind].indio_dev = c->indio_dev;
|
||||
chans[mapind].channel =
|
||||
iio_chan_spec_from_name(chans[mapind].indio_dev,
|
||||
c->map->adc_channel_label);
|
||||
if (chans[mapind].channel == NULL) {
|
||||
ret = -EINVAL;
|
||||
put_device(&chans[mapind].indio_dev->dev);
|
||||
goto error_free_chans;
|
||||
}
|
||||
get_device(&chans[mapind].indio_dev->dev);
|
||||
mapind++;
|
||||
}
|
||||
mutex_unlock(&iio_map_list_lock);
|
||||
if (mapind == 0) {
|
||||
ret = -ENODEV;
|
||||
goto error_free_chans;
|
||||
}
|
||||
return chans;
|
||||
|
||||
error_free_chans:
|
||||
for (i = 0; i < nummaps; i++)
|
||||
if (chans[i].indio_dev)
|
||||
put_device(&chans[i].indio_dev->dev);
|
||||
kfree(chans);
|
||||
error_ret:
|
||||
mutex_unlock(&iio_map_list_lock);
|
||||
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iio_st_channel_get_all);
|
||||
|
||||
void iio_st_channel_release_all(struct iio_channel *channels)
|
||||
{
|
||||
struct iio_channel *chan = &channels[0];
|
||||
|
||||
while (chan->indio_dev) {
|
||||
put_device(&chan->indio_dev->dev);
|
||||
chan++;
|
||||
}
|
||||
kfree(channels);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iio_st_channel_release_all);
|
||||
|
||||
int iio_st_read_channel_raw(struct iio_channel *chan, int *val)
|
||||
{
|
||||
int val2, ret;
|
||||
|
||||
mutex_lock(&chan->indio_dev->info_exist_lock);
|
||||
if (chan->indio_dev->info == NULL) {
|
||||
ret = -ENODEV;
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
ret = chan->indio_dev->info->read_raw(chan->indio_dev, chan->channel,
|
||||
val, &val2, 0);
|
||||
err_unlock:
|
||||
mutex_unlock(&chan->indio_dev->info_exist_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iio_st_read_channel_raw);
|
||||
|
||||
int iio_st_read_channel_scale(struct iio_channel *chan, int *val, int *val2)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&chan->indio_dev->info_exist_lock);
|
||||
if (chan->indio_dev->info == NULL) {
|
||||
ret = -ENODEV;
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
ret = chan->indio_dev->info->read_raw(chan->indio_dev,
|
||||
chan->channel,
|
||||
val, val2,
|
||||
IIO_CHAN_INFO_SCALE);
|
||||
err_unlock:
|
||||
mutex_unlock(&chan->indio_dev->info_exist_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iio_st_read_channel_scale);
|
||||
|
||||
int iio_st_get_channel_type(struct iio_channel *chan,
|
||||
enum iio_chan_type *type)
|
||||
{
|
||||
int ret = 0;
|
||||
/* Need to verify underlying driver has not gone away */
|
||||
|
||||
mutex_lock(&chan->indio_dev->info_exist_lock);
|
||||
if (chan->indio_dev->info == NULL) {
|
||||
ret = -ENODEV;
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
*type = chan->channel->type;
|
||||
err_unlock:
|
||||
mutex_unlock(&chan->indio_dev->info_exist_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iio_st_get_channel_type);
|
Посилання в новій задачі
Заблокувати користувача