Commit 3704432f authored by Jonathan Cameron's avatar Jonathan Cameron

iio: refactor info mask and ext_info attribute creation.

Introduce an enum to specify whether the attribute is separate or
shared.

Factor out the bitmap handling for loop into a separate function.

Tidy up error handling and add a NULL assignment to squish a false
positive warning from GCC.

Change ext_info shared type from boolean to enum and update in all
drivers.
Signed-off-by: default avatarJonathan Cameron <jic23@kernel.org>
Reviewed-by: default avatarLars-Peter Clausen <lars@metafoo.de>
parent 9761696f
...@@ -285,8 +285,9 @@ static const struct iio_chan_spec_ext_info ad5064_ext_info[] = { ...@@ -285,8 +285,9 @@ static const struct iio_chan_spec_ext_info ad5064_ext_info[] = {
.name = "powerdown", .name = "powerdown",
.read = ad5064_read_dac_powerdown, .read = ad5064_read_dac_powerdown,
.write = ad5064_write_dac_powerdown, .write = ad5064_write_dac_powerdown,
.shared = IIO_SEPARATE,
}, },
IIO_ENUM("powerdown_mode", false, &ad5064_powerdown_mode_enum), IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad5064_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5064_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", &ad5064_powerdown_mode_enum),
{ }, { },
}; };
......
...@@ -247,8 +247,10 @@ static struct iio_chan_spec_ext_info ad5380_ext_info[] = { ...@@ -247,8 +247,10 @@ static struct iio_chan_spec_ext_info ad5380_ext_info[] = {
.name = "powerdown", .name = "powerdown",
.read = ad5380_read_dac_powerdown, .read = ad5380_read_dac_powerdown,
.write = ad5380_write_dac_powerdown, .write = ad5380_write_dac_powerdown,
.shared = IIO_SEPARATE,
}, },
IIO_ENUM("powerdown_mode", true, &ad5380_powerdown_mode_enum), IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE,
&ad5380_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5380_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", &ad5380_powerdown_mode_enum),
{ }, { },
}; };
......
...@@ -132,8 +132,9 @@ static const struct iio_chan_spec_ext_info ad5446_ext_info_powerdown[] = { ...@@ -132,8 +132,9 @@ static const struct iio_chan_spec_ext_info ad5446_ext_info_powerdown[] = {
.name = "powerdown", .name = "powerdown",
.read = ad5446_read_dac_powerdown, .read = ad5446_read_dac_powerdown,
.write = ad5446_write_dac_powerdown, .write = ad5446_write_dac_powerdown,
.shared = IIO_SEPARATE,
}, },
IIO_ENUM("powerdown_mode", false, &ad5446_powerdown_mode_enum), IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad5446_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5446_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", &ad5446_powerdown_mode_enum),
{ }, { },
}; };
......
...@@ -248,8 +248,10 @@ static const struct iio_chan_spec_ext_info ad5504_ext_info[] = { ...@@ -248,8 +248,10 @@ static const struct iio_chan_spec_ext_info ad5504_ext_info[] = {
.name = "powerdown", .name = "powerdown",
.read = ad5504_read_dac_powerdown, .read = ad5504_read_dac_powerdown,
.write = ad5504_write_dac_powerdown, .write = ad5504_write_dac_powerdown,
.shared = IIO_SEPARATE,
}, },
IIO_ENUM("powerdown_mode", true, &ad5504_powerdown_mode_enum), IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE,
&ad5504_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5504_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", &ad5504_powerdown_mode_enum),
{ }, { },
}; };
......
...@@ -163,8 +163,10 @@ static const struct iio_chan_spec_ext_info ad5624r_ext_info[] = { ...@@ -163,8 +163,10 @@ static const struct iio_chan_spec_ext_info ad5624r_ext_info[] = {
.name = "powerdown", .name = "powerdown",
.read = ad5624r_read_dac_powerdown, .read = ad5624r_read_dac_powerdown,
.write = ad5624r_write_dac_powerdown, .write = ad5624r_write_dac_powerdown,
.shared = IIO_SEPARATE,
}, },
IIO_ENUM("powerdown_mode", true, &ad5624r_powerdown_mode_enum), IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE,
&ad5624r_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5624r_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", &ad5624r_powerdown_mode_enum),
{ }, { },
}; };
......
...@@ -264,8 +264,9 @@ static const struct iio_chan_spec_ext_info ad5686_ext_info[] = { ...@@ -264,8 +264,9 @@ static const struct iio_chan_spec_ext_info ad5686_ext_info[] = {
.name = "powerdown", .name = "powerdown",
.read = ad5686_read_dac_powerdown, .read = ad5686_read_dac_powerdown,
.write = ad5686_write_dac_powerdown, .write = ad5686_write_dac_powerdown,
.shared = IIO_SEPARATE,
}, },
IIO_ENUM("powerdown_mode", false, &ad5686_powerdown_mode_enum), IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad5686_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5686_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", &ad5686_powerdown_mode_enum),
{ }, { },
}; };
......
...@@ -386,6 +386,7 @@ static const struct iio_chan_spec_ext_info ad5755_ext_info[] = { ...@@ -386,6 +386,7 @@ static const struct iio_chan_spec_ext_info ad5755_ext_info[] = {
.name = "powerdown", .name = "powerdown",
.read = ad5755_read_powerdown, .read = ad5755_read_powerdown,
.write = ad5755_write_powerdown, .write = ad5755_write_powerdown,
.shared = IIO_SEPARATE,
}, },
{ }, { },
}; };
......
...@@ -287,11 +287,12 @@ static int ad5791_read_raw(struct iio_dev *indio_dev, ...@@ -287,11 +287,12 @@ static int ad5791_read_raw(struct iio_dev *indio_dev,
static const struct iio_chan_spec_ext_info ad5791_ext_info[] = { static const struct iio_chan_spec_ext_info ad5791_ext_info[] = {
{ {
.name = "powerdown", .name = "powerdown",
.shared = true, .shared = IIO_SHARED_BY_TYPE,
.read = ad5791_read_dac_powerdown, .read = ad5791_read_dac_powerdown,
.write = ad5791_write_dac_powerdown, .write = ad5791_write_dac_powerdown,
}, },
IIO_ENUM("powerdown_mode", true, &ad5791_powerdown_mode_enum), IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE,
&ad5791_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5791_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", &ad5791_powerdown_mode_enum),
{ }, { },
}; };
......
...@@ -169,6 +169,7 @@ static const struct iio_chan_spec_ext_info ad7303_ext_info[] = { ...@@ -169,6 +169,7 @@ static const struct iio_chan_spec_ext_info ad7303_ext_info[] = {
.name = "powerdown", .name = "powerdown",
.read = ad7303_read_dac_powerdown, .read = ad7303_read_dac_powerdown,
.write = ad7303_write_dac_powerdown, .write = ad7303_write_dac_powerdown,
.shared = IIO_SEPARATE,
}, },
{ }, { },
}; };
......
...@@ -195,8 +195,9 @@ static const struct iio_chan_spec_ext_info mcp4725_ext_info[] = { ...@@ -195,8 +195,9 @@ static const struct iio_chan_spec_ext_info mcp4725_ext_info[] = {
.name = "powerdown", .name = "powerdown",
.read = mcp4725_read_powerdown, .read = mcp4725_read_powerdown,
.write = mcp4725_write_powerdown, .write = mcp4725_write_powerdown,
.shared = IIO_SEPARATE,
}, },
IIO_ENUM("powerdown_mode", false, &mcp4725_powerdown_mode_enum), IIO_ENUM("powerdown_mode", IIO_SEPARATE, &mcp4725_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &mcp4725_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", &mcp4725_powerdown_mode_enum),
{ }, { },
}; };
......
...@@ -351,6 +351,7 @@ static ssize_t adf4350_read(struct iio_dev *indio_dev, ...@@ -351,6 +351,7 @@ static ssize_t adf4350_read(struct iio_dev *indio_dev,
.read = adf4350_read, \ .read = adf4350_read, \
.write = adf4350_write, \ .write = adf4350_write, \
.private = _ident, \ .private = _ident, \
.shared = IIO_SEPARATE, \
} }
static const struct iio_chan_spec_ext_info adf4350_ext_info[] = { static const struct iio_chan_spec_ext_info adf4350_ext_info[] = {
......
...@@ -30,7 +30,7 @@ int __iio_add_chan_devattr(const char *postfix, ...@@ -30,7 +30,7 @@ int __iio_add_chan_devattr(const char *postfix,
const char *buf, const char *buf,
size_t len), size_t len),
u64 mask, u64 mask,
bool generic, enum iio_shared_by shared_by,
struct device *dev, struct device *dev,
struct list_head *attr_list); struct list_head *attr_list);
......
...@@ -208,7 +208,7 @@ static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev, ...@@ -208,7 +208,7 @@ static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev,
&iio_show_scan_index, &iio_show_scan_index,
NULL, NULL,
0, 0,
0, IIO_SEPARATE,
&indio_dev->dev, &indio_dev->dev,
&buffer->scan_el_dev_attr_list); &buffer->scan_el_dev_attr_list);
if (ret) if (ret)
......
...@@ -517,14 +517,15 @@ int __iio_device_attr_init(struct device_attribute *dev_attr, ...@@ -517,14 +517,15 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, const char *buf,
size_t len), size_t len),
bool generic) enum iio_shared_by shared_by)
{ {
int ret; int ret = 0;
char *name_format, *full_postfix; char *name_format = NULL;
char *full_postfix;
sysfs_attr_init(&dev_attr->attr); sysfs_attr_init(&dev_attr->attr);
/* Build up postfix of <extend_name>_<modifier>_postfix */ /* Build up postfix of <extend_name>_<modifier>_postfix */
if (chan->modified && !generic) { if (chan->modified && (shared_by == IIO_SEPARATE)) {
if (chan->extend_name) if (chan->extend_name)
full_postfix = kasprintf(GFP_KERNEL, "%s_%s_%s", full_postfix = kasprintf(GFP_KERNEL, "%s_%s_%s",
iio_modifier_names[chan iio_modifier_names[chan
...@@ -545,53 +546,62 @@ int __iio_device_attr_init(struct device_attribute *dev_attr, ...@@ -545,53 +546,62 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
chan->extend_name, chan->extend_name,
postfix); postfix);
} }
if (full_postfix == NULL) { if (full_postfix == NULL)
ret = -ENOMEM; return -ENOMEM;
goto error_ret;
}
if (chan->differential) { /* Differential can not have modifier */ if (chan->differential) { /* Differential can not have modifier */
if (generic) switch (shared_by) {
case IIO_SHARED_BY_TYPE:
name_format name_format
= kasprintf(GFP_KERNEL, "%s_%s-%s_%s", = kasprintf(GFP_KERNEL, "%s_%s-%s_%s",
iio_direction[chan->output], iio_direction[chan->output],
iio_chan_type_name_spec[chan->type], iio_chan_type_name_spec[chan->type],
iio_chan_type_name_spec[chan->type], iio_chan_type_name_spec[chan->type],
full_postfix); full_postfix);
else if (chan->indexed) break;
case IIO_SEPARATE:
if (!chan->indexed) {
WARN_ON("Differential channels must be indexed\n");
ret = -EINVAL;
goto error_free_full_postfix;
}
name_format name_format
= kasprintf(GFP_KERNEL, "%s_%s%d-%s%d_%s", = kasprintf(GFP_KERNEL,
"%s_%s%d-%s%d_%s",
iio_direction[chan->output], iio_direction[chan->output],
iio_chan_type_name_spec[chan->type], iio_chan_type_name_spec[chan->type],
chan->channel, chan->channel,
iio_chan_type_name_spec[chan->type], iio_chan_type_name_spec[chan->type],
chan->channel2, chan->channel2,
full_postfix); full_postfix);
else { break;
WARN_ON("Differential channels must be indexed\n");
ret = -EINVAL;
goto error_free_full_postfix;
} }
} else { /* Single ended */ } else { /* Single ended */
if (generic) switch (shared_by) {
name_format case IIO_SHARED_BY_TYPE:
= kasprintf(GFP_KERNEL, "%s_%s_%s",
iio_direction[chan->output],
iio_chan_type_name_spec[chan->type],
full_postfix);
else if (chan->indexed)
name_format
= kasprintf(GFP_KERNEL, "%s_%s%d_%s",
iio_direction[chan->output],
iio_chan_type_name_spec[chan->type],
chan->channel,
full_postfix);
else
name_format name_format
= kasprintf(GFP_KERNEL, "%s_%s_%s", = kasprintf(GFP_KERNEL, "%s_%s_%s",
iio_direction[chan->output], iio_direction[chan->output],
iio_chan_type_name_spec[chan->type], iio_chan_type_name_spec[chan->type],
full_postfix); full_postfix);
break;
case IIO_SEPARATE:
if (chan->indexed)
name_format
= kasprintf(GFP_KERNEL, "%s_%s%d_%s",
iio_direction[chan->output],
iio_chan_type_name_spec[chan->type],
chan->channel,
full_postfix);
else
name_format
= kasprintf(GFP_KERNEL, "%s_%s_%s",
iio_direction[chan->output],
iio_chan_type_name_spec[chan->type],
full_postfix);
break;
}
} }
if (name_format == NULL) { if (name_format == NULL) {
ret = -ENOMEM; ret = -ENOMEM;
...@@ -615,16 +625,11 @@ int __iio_device_attr_init(struct device_attribute *dev_attr, ...@@ -615,16 +625,11 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
dev_attr->attr.mode |= S_IWUSR; dev_attr->attr.mode |= S_IWUSR;
dev_attr->store = writefunc; dev_attr->store = writefunc;
} }
kfree(name_format);
kfree(full_postfix);
return 0;
error_free_name_format: error_free_name_format:
kfree(name_format); kfree(name_format);
error_free_full_postfix: error_free_full_postfix:
kfree(full_postfix); kfree(full_postfix);
error_ret:
return ret; return ret;
} }
...@@ -643,7 +648,7 @@ int __iio_add_chan_devattr(const char *postfix, ...@@ -643,7 +648,7 @@ int __iio_add_chan_devattr(const char *postfix,
const char *buf, const char *buf,
size_t len), size_t len),
u64 mask, u64 mask,
bool generic, enum iio_shared_by shared_by,
struct device *dev, struct device *dev,
struct list_head *attr_list) struct list_head *attr_list)
{ {
...@@ -657,7 +662,7 @@ int __iio_add_chan_devattr(const char *postfix, ...@@ -657,7 +662,7 @@ int __iio_add_chan_devattr(const char *postfix,
} }
ret = __iio_device_attr_init(&iio_attr->dev_attr, ret = __iio_device_attr_init(&iio_attr->dev_attr,
postfix, chan, postfix, chan,
readfunc, writefunc, generic); readfunc, writefunc, shared_by);
if (ret) if (ret)
goto error_iio_dev_attr_free; goto error_iio_dev_attr_free;
iio_attr->c = chan; iio_attr->c = chan;
...@@ -665,7 +670,7 @@ int __iio_add_chan_devattr(const char *postfix, ...@@ -665,7 +670,7 @@ int __iio_add_chan_devattr(const char *postfix,
list_for_each_entry(t, attr_list, l) list_for_each_entry(t, attr_list, l)
if (strcmp(t->dev_attr.attr.name, if (strcmp(t->dev_attr.attr.name,
iio_attr->dev_attr.attr.name) == 0) { iio_attr->dev_attr.attr.name) == 0) {
if (!generic) if (shared_by == IIO_SEPARATE)
dev_err(dev, "tried to double register : %s\n", dev_err(dev, "tried to double register : %s\n",
t->dev_attr.attr.name); t->dev_attr.attr.name);
ret = -EBUSY; ret = -EBUSY;
...@@ -683,46 +688,54 @@ int __iio_add_chan_devattr(const char *postfix, ...@@ -683,46 +688,54 @@ int __iio_add_chan_devattr(const char *postfix,
return ret; return ret;
} }
static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, static int iio_device_add_info_mask_type(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan) struct iio_chan_spec const *chan,
enum iio_shared_by shared_by,
const long *infomask)
{ {
int ret, attrcount = 0; int i, ret, attrcount = 0;
int i;
const struct iio_chan_spec_ext_info *ext_info;
if (chan->channel < 0) for_each_set_bit(i, infomask, sizeof(infomask)*8) {
return 0;
for_each_set_bit(i, &chan->info_mask_separate, sizeof(long)*8) {
ret = __iio_add_chan_devattr(iio_chan_info_postfix[i], ret = __iio_add_chan_devattr(iio_chan_info_postfix[i],
chan, chan,
&iio_read_channel_info, &iio_read_channel_info,
&iio_write_channel_info, &iio_write_channel_info,
i, i,
0, shared_by,
&indio_dev->dev, &indio_dev->dev,
&indio_dev->channel_attr_list); &indio_dev->channel_attr_list);
if (ret < 0) if ((ret == -EBUSY) && (shared_by != IIO_SEPARATE))
goto error_ret;
attrcount++;
}
for_each_set_bit(i, &chan->info_mask_shared_by_type, sizeof(long)*8) {
ret = __iio_add_chan_devattr(iio_chan_info_postfix[i],
chan,
&iio_read_channel_info,
&iio_write_channel_info,
i,
1,
&indio_dev->dev,
&indio_dev->channel_attr_list);
if (ret == -EBUSY) {
ret = 0;
continue; continue;
} else if (ret < 0) { else if (ret < 0)
goto error_ret; return ret;
}
attrcount++; attrcount++;
} }
return attrcount;
}
static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan)
{
int ret, attrcount = 0;
const struct iio_chan_spec_ext_info *ext_info;
if (chan->channel < 0)
return 0;
ret = iio_device_add_info_mask_type(indio_dev, chan,
IIO_SEPARATE,
&chan->info_mask_separate);
if (ret < 0)
return ret;
attrcount += ret;
ret = iio_device_add_info_mask_type(indio_dev, chan,
IIO_SHARED_BY_TYPE,
&chan->info_mask_shared_by_type);
if (ret < 0)
return ret;
attrcount += ret;
if (chan->ext_info) { if (chan->ext_info) {
unsigned int i = 0; unsigned int i = 0;
for (ext_info = chan->ext_info; ext_info->name; ext_info++) { for (ext_info = chan->ext_info; ext_info->name; ext_info++) {
...@@ -741,15 +754,13 @@ static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, ...@@ -741,15 +754,13 @@ static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
continue; continue;
if (ret) if (ret)
goto error_ret; return ret;
attrcount++; attrcount++;
} }
} }
ret = attrcount; return attrcount;
error_ret:
return ret;
} }
static void iio_device_remove_and_free_read_attr(struct iio_dev *indio_dev, static void iio_device_remove_and_free_read_attr(struct iio_dev *indio_dev,
......
...@@ -39,6 +39,11 @@ enum iio_chan_info_enum { ...@@ -39,6 +39,11 @@ enum iio_chan_info_enum {
IIO_CHAN_INFO_INT_TIME, IIO_CHAN_INFO_INT_TIME,
}; };
enum iio_shared_by {
IIO_SEPARATE,
IIO_SHARED_BY_TYPE
};
enum iio_endian { enum iio_endian {
IIO_CPU, IIO_CPU,
IIO_BE, IIO_BE,
...@@ -58,7 +63,7 @@ struct iio_dev; ...@@ -58,7 +63,7 @@ struct iio_dev;
*/ */
struct iio_chan_spec_ext_info { struct iio_chan_spec_ext_info {
const char *name; const char *name;
bool shared; enum iio_shared_by shared;
ssize_t (*read)(struct iio_dev *, uintptr_t private, ssize_t (*read)(struct iio_dev *, uintptr_t private,
struct iio_chan_spec const *, char *buf); struct iio_chan_spec const *, char *buf);
ssize_t (*write)(struct iio_dev *, uintptr_t private, ssize_t (*write)(struct iio_dev *, uintptr_t private,
...@@ -126,7 +131,7 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev, ...@@ -126,7 +131,7 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev,
#define IIO_ENUM_AVAILABLE(_name, _e) \ #define IIO_ENUM_AVAILABLE(_name, _e) \
{ \ { \
.name = (_name "_available"), \ .name = (_name "_available"), \
.shared = true, \ .shared = IIO_SHARED_BY_TYPE, \
.read = iio_enum_available_read, \ .read = iio_enum_available_read, \
.private = (uintptr_t)(_e), \ .private = (uintptr_t)(_e), \
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment