Skip to content

Commit

Permalink
of: search the best compatible match first in __of_match_node()
Browse files Browse the repository at this point in the history
Currently, of_match_node compares each given match against all node's
compatible strings with of_device_is_compatible.

To achieve multiple compatible strings per node with ordering from
specific to generic, this requires given matches to be ordered from
specific to generic. For most of the drivers this is not true and also
an alphabetical ordering is more sane there.

Therefore, this patch introduces a function to match each of the node's
compatible strings against all given compatible matches without type and
name first, before checking the next compatible string. This implies
that node's compatibles are ordered from specific to generic while
given matches can be in any order. If we fail to find such a match
entry, then fall-back to the old method in order to keep compatibility.

Cc: Sebastian Hesselbarth <[email protected]>
Signed-off-by: Kevin Hao <[email protected]>
Tested-by: Stephen Chivers <[email protected]>
Signed-off-by: Rob Herring <[email protected]>
  • Loading branch information
haokexin authored and robherring committed Feb 16, 2014
1 parent 4e8ca6e commit 06b29e7
Showing 1 changed file with 42 additions and 1 deletion.
43 changes: 42 additions & 1 deletion drivers/of/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -730,13 +730,49 @@ struct device_node *of_find_node_with_property(struct device_node *from,
}
EXPORT_SYMBOL(of_find_node_with_property);

static const struct of_device_id *
of_match_compatible(const struct of_device_id *matches,
const struct device_node *node)
{
const char *cp;
int cplen, l;
const struct of_device_id *m;

cp = __of_get_property(node, "compatible", &cplen);
while (cp && (cplen > 0)) {
m = matches;
while (m->name[0] || m->type[0] || m->compatible[0]) {
/* Only match for the entries without type and name */
if (m->name[0] || m->type[0] ||
of_compat_cmp(m->compatible, cp,
strlen(m->compatible)))
m++;
else
return m;
}

/* Get node's next compatible string */
l = strlen(cp) + 1;
cp += l;
cplen -= l;
}

return NULL;
}

static
const struct of_device_id *__of_match_node(const struct of_device_id *matches,
const struct device_node *node)
{
const struct of_device_id *m;

if (!matches)
return NULL;

m = of_match_compatible(matches, node);
if (m)
return m;

while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
int match = 1;
if (matches->name[0])
Expand All @@ -760,7 +796,12 @@ const struct of_device_id *__of_match_node(const struct of_device_id *matches,
* @matches: array of of device match structures to search in
* @node: the of device structure to match against
*
* Low level utility function used by device matching.
* Low level utility function used by device matching. We have two ways
* of matching:
* - Try to find the best compatible match by comparing each compatible
* string of device node with all the given matches respectively.
* - If the above method failed, then try to match the compatible by using
* __of_device_is_compatible() besides the match in type and name.
*/
const struct of_device_id *of_match_node(const struct of_device_id *matches,
const struct device_node *node)
Expand Down

0 comments on commit 06b29e7

Please sign in to comment.