of/device: use of_property_for_each_string to parse compatible strings

Instead of directly parsing the compatible property, use the
of_property_for_each_string() helper to iterate over each compatible
string. This reduces the LoC and makes the functions easier to
understand.

Signed-off-by: Rob Herring <robh@kernel.org>
This commit is contained in:
Rob Herring 2017-07-21 15:45:32 -05:00
parent 7c6ffa0b27
commit bc575064d6
1 changed files with 21 additions and 41 deletions

View File

@ -195,9 +195,10 @@ EXPORT_SYMBOL(of_device_get_match_data);
static ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len) static ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len)
{ {
const char *compat; const char *compat, *start = str;
int cplen, i; char *c;
ssize_t tsize, csize, repend; struct property *p;
ssize_t csize;
if ((!dev) || (!dev->of_node)) if ((!dev) || (!dev->of_node))
return -ENODEV; return -ENODEV;
@ -205,42 +206,24 @@ static ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len
/* Name & Type */ /* Name & Type */
csize = snprintf(str, len, "of:N%sT%s", dev->of_node->name, csize = snprintf(str, len, "of:N%sT%s", dev->of_node->name,
dev->of_node->type); dev->of_node->type);
len -= csize;
str += csize;
/* Get compatible property if any */ of_property_for_each_string(dev->of_node, "compatible", p, compat) {
compat = of_get_property(dev->of_node, "compatible", &cplen); if (strlen(compat) + 2 > len)
if (!compat) break;
return csize;
/* Find true end (we tolerate multiple \0 at the end */ csize = snprintf(str, len, "C%s", compat);
for (i = (cplen - 1); i >= 0 && !compat[i]; i--) for (c = str; c; ) {
cplen--; c = strchr(c, ' ');
if (!cplen) if (c)
return csize; *c++ = '_';
cplen++; }
len -= csize;
/* Check space (need cplen+1 chars including final \0) */ str += csize;
tsize = csize + cplen;
repend = tsize;
if (csize >= len) /* @ the limit, all is already filled */
return tsize;
if (tsize >= len) { /* limit compat list */
cplen = len - csize - 1;
repend = len;
} }
/* Copy and do char replacement */ return str - start;
memcpy(&str[csize + 1], compat, cplen);
for (i = csize; i < repend; i++) {
char c = str[i];
if (c == '\0')
str[i] = 'C';
else if (c == ' ')
str[i] = '_';
}
return repend;
} }
int of_device_request_module(struct device *dev) int of_device_request_module(struct device *dev)
@ -288,7 +271,8 @@ void of_device_uevent(struct device *dev, struct kobj_uevent_env *env)
{ {
const char *compat; const char *compat;
struct alias_prop *app; struct alias_prop *app;
int seen = 0, cplen, sl; struct property *p;
int seen = 0;
if ((!dev) || (!dev->of_node)) if ((!dev) || (!dev->of_node))
return; return;
@ -301,12 +285,8 @@ void of_device_uevent(struct device *dev, struct kobj_uevent_env *env)
/* Since the compatible field can contain pretty much anything /* Since the compatible field can contain pretty much anything
* it's not really legal to split it out with commas. We split it * it's not really legal to split it out with commas. We split it
* up using a number of environment variables instead. */ * up using a number of environment variables instead. */
compat = of_get_property(dev->of_node, "compatible", &cplen); of_property_for_each_string(dev->of_node, "compatible", p, compat) {
while (compat && *compat && cplen > 0) {
add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat); add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat);
sl = strlen(compat) + 1;
compat += sl;
cplen -= sl;
seen++; seen++;
} }
add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen); add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen);