When the device node do have a compatible property, we definitely
prefer the compatible match besides the type and name. Only if
there is no such a match, we then consider the candidate which
doesn't have compatible entry but do match the type or name with
the device node.

This is based on a patch from Sebastian Hesselbarth.
  http://patchwork.ozlabs.org/patch/319434/

I did some code refactoring and also fixed a bug in the original patch.

Cc: Sebastian Hesselbarth <sebastian.hesselba...@gmail.com>
Signed-off-by: Kevin Hao <haoke...@gmail.com>
---
 drivers/of/base.c | 55 +++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 37 insertions(+), 18 deletions(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index ff85450d5683..9d655df458bd 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -730,32 +730,45 @@ out:
 }
 EXPORT_SYMBOL(of_find_node_with_property);
 
+static int of_match_type_or_name(const struct device_node *node,
+                               const struct of_device_id *m)
+{
+       int match = 1;
+
+       if (m->name[0])
+               match &= node->name && !strcmp(m->name, node->name);
+
+       if (m->type[0])
+               match &= node->type && !strcmp(m->type, node->type);
+
+       return match;
+}
+
 static
 const struct of_device_id *__of_match_node(const struct of_device_id *matches,
                                           const struct device_node *node)
 {
        const char *cp;
        int cplen, l;
+       const struct of_device_id *m;
+       int match;
 
        if (!matches)
                return NULL;
 
        cp = __of_get_property(node, "compatible", &cplen);
-       do {
-               const struct of_device_id *m = matches;
+       while (cp && (cplen > 0)) {
+               m = matches;
 
                /* Check against matches with current compatible string */
                while (m->name[0] || m->type[0] || m->compatible[0]) {
-                       int match = 1;
-                       if (m->name[0])
-                               match &= node->name
-                                       && !strcmp(m->name, node->name);
-                       if (m->type[0])
-                               match &= node->type
-                                       && !strcmp(m->type, node->type);
-                       if (m->compatible[0])
-                               match &= cp
-                                       && !of_compat_cmp(m->compatible, cp,
+                       if (!m->compatible[0]) {
+                               m++;
+                               continue;
+                       }
+
+                       match = of_match_type_or_name(node, m);
+                       match &= cp && !of_compat_cmp(m->compatible, cp,
                                                        strlen(m->compatible));
                        if (match)
                                return m;
@@ -763,12 +776,18 @@ const struct of_device_id *__of_match_node(const struct 
of_device_id *matches,
                }
 
                /* Get node's next compatible string */ 
-               if (cp) {
-                       l = strlen(cp) + 1;
-                       cp += l;
-                       cplen -= l;
-               }
-       } while (cp && (cplen > 0));
+               l = strlen(cp) + 1;
+               cp += l;
+               cplen -= l;
+       }
+
+       m = matches;
+       /* Check against matches without compatible string */
+       while (m->name[0] || m->type[0] || m->compatible[0]) {
+               if (!m->compatible[0] && of_match_type_or_name(node, m))
+                       return m;
+               m++;
+       }
 
        return NULL;
 }
-- 
1.8.5.3

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to