Skip to content

Commit 06b29e7

Browse files
haokexinrobherring
authored andcommitted
of: search the best compatible match first in __of_match_node()
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 <sebastian.hesselbarth@gmail.com> Signed-off-by: Kevin Hao <haokexin@gmail.com> Tested-by: Stephen Chivers <schivers@csc.com> Signed-off-by: Rob Herring <robh@kernel.org>
1 parent 4e8ca6e commit 06b29e7

File tree

1 file changed

+42
-1
lines changed

1 file changed

+42
-1
lines changed

drivers/of/base.c

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -730,13 +730,49 @@ struct device_node *of_find_node_with_property(struct device_node *from,
730730
}
731731
EXPORT_SYMBOL(of_find_node_with_property);
732732

733+
static const struct of_device_id *
734+
of_match_compatible(const struct of_device_id *matches,
735+
const struct device_node *node)
736+
{
737+
const char *cp;
738+
int cplen, l;
739+
const struct of_device_id *m;
740+
741+
cp = __of_get_property(node, "compatible", &cplen);
742+
while (cp && (cplen > 0)) {
743+
m = matches;
744+
while (m->name[0] || m->type[0] || m->compatible[0]) {
745+
/* Only match for the entries without type and name */
746+
if (m->name[0] || m->type[0] ||
747+
of_compat_cmp(m->compatible, cp,
748+
strlen(m->compatible)))
749+
m++;
750+
else
751+
return m;
752+
}
753+
754+
/* Get node's next compatible string */
755+
l = strlen(cp) + 1;
756+
cp += l;
757+
cplen -= l;
758+
}
759+
760+
return NULL;
761+
}
762+
733763
static
734764
const struct of_device_id *__of_match_node(const struct of_device_id *matches,
735765
const struct device_node *node)
736766
{
767+
const struct of_device_id *m;
768+
737769
if (!matches)
738770
return NULL;
739771

772+
m = of_match_compatible(matches, node);
773+
if (m)
774+
return m;
775+
740776
while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
741777
int match = 1;
742778
if (matches->name[0])
@@ -760,7 +796,12 @@ const struct of_device_id *__of_match_node(const struct of_device_id *matches,
760796
* @matches: array of of device match structures to search in
761797
* @node: the of device structure to match against
762798
*
763-
* Low level utility function used by device matching.
799+
* Low level utility function used by device matching. We have two ways
800+
* of matching:
801+
* - Try to find the best compatible match by comparing each compatible
802+
* string of device node with all the given matches respectively.
803+
* - If the above method failed, then try to match the compatible by using
804+
* __of_device_is_compatible() besides the match in type and name.
764805
*/
765806
const struct of_device_id *of_match_node(const struct of_device_id *matches,
766807
const struct device_node *node)

0 commit comments

Comments
 (0)