From: Rob Herring <robherring2@gmail.com>
To: Scott Wood <scottwood@freescale.com>
Cc: devicetree-discuss@lists.ozlabs.org,
Thierry Reding <thierry.reding@avionic-design.de>,
linuxppc-dev@lists.ozlabs.org
Subject: Re: [PATCH] of: require a match on all fields of of_device_id
Date: Tue, 17 Jul 2012 21:38:17 -0500 [thread overview]
Message-ID: <50062199.7090904@gmail.com> (raw)
In-Reply-To: <20120718011151.GA6119@tyr.buserror.net>
On 07/17/2012 08:11 PM, Scott Wood wrote:
> Commit 107a84e61cdd3406c842a0e4be7efffd3a05dba6 ("of: match by compatible
> property first") breaks the gianfar ethernet driver found on various
> Freescale PPC chips.
You do know this is reverted, right?
>
> There are, for unfortunate historical reasons, two nodes with a
> compatible of "gianfar". One has a device_type of "network" and the
> other has device_type of "mdio". The match entries look like this:
>
>> {
>> .type = "mdio",
>> .compatible = "gianfar",
>> },
>
> and
>
>> {
>> .type = "network",
>> .compatible = "gianfar",
>> },
>
> With the above patch, both nodes get probed by the first driver, because
> nothing else in the match struct is looked at if there's a compatible
> match.
>
> Signed-off-by: Scott Wood <scottwood@freescale.com>
Here's my fix (untested) which is a bit simpler. I'm assuming if we care
about which compatible string we are matching to, then we require name
and type are blank and we only care about compatible strings.
diff --git a/drivers/of/base.c b/drivers/of/base.c
index eada3f4..6e10004 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -518,6 +518,9 @@ static const struct of_device_id
*of_match_compat(const struct of_device_id *mat
const char *cp = matches->compatible;
int len = strlen(cp);
+ if (matches->name[0] || matches->type[0])
+ continue;
+
if (len > 0 && of_compat_cmp(compat, cp, len) == 0)
return matches;
@@ -557,7 +560,10 @@ const struct of_device_id *of_match_node(const
struct of_device_id *matches,
if (matches->type[0])
match &= node->type
&& !strcmp(matches->type, node->type);
- if (match && !matches->compatible[0])
+ if (matches->compatible[0])
+ match &= of_device_is_compatible(node,
+ matches->compatible);
+ if (match)
return matches;
matches++;
}
> ---
> drivers/of/base.c | 44 ++++++++++++++++++++++++++++++++------------
> 1 file changed, 32 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index bc86ea2..4e707cc 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -511,14 +511,37 @@ out:
> }
> EXPORT_SYMBOL(of_find_node_with_property);
>
> -static const struct of_device_id *of_match_compat(const struct of_device_id *matches,
> - const char *compat)
> +/*
> + * Tell if an device_node matches the non-compatible fields of
> + * a specific of_match element.
> + */
> +static bool of_match_one_noncompat(const struct of_device_id *match,
> + const struct device_node *node)
> +{
> + bool is_match = true;
> +
> + if (match->name[0])
> + is_match &= node->name && !strcmp(match->name, node->name);
> + if (match->type[0])
> + is_match &= node->type && !strcmp(match->type, node->type);
> +
> + return is_match;
> +}
> +
> +/*
> + * Find an OF match using the supplied compatible string, rather than
> + * the node's entire string list.
> + */
> +static const struct of_device_id *of_match_compat(
> + const struct of_device_id *matches, const char *compat,
> + const struct device_node *node)
> {
> while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
> const char *cp = matches->compatible;
> int len = strlen(cp);
>
> - if (len > 0 && of_compat_cmp(compat, cp, len) == 0)
> + if (len > 0 && of_compat_cmp(compat, cp, len) == 0 &&
> + of_match_one_noncompat(matches, node))
> return matches;
>
> matches++;
> @@ -544,23 +567,20 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches,
> return NULL;
>
> of_property_for_each_string(node, "compatible", prop, cp) {
> - const struct of_device_id *match = of_match_compat(matches, cp);
> + const struct of_device_id *match =
> + of_match_compat(matches, cp, node);
> if (match)
> return match;
> }
>
> while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
> - int match = 1;
> - if (matches->name[0])
> - match &= node->name
> - && !strcmp(matches->name, node->name);
> - if (matches->type[0])
> - match &= node->type
> - && !strcmp(matches->type, node->type);
> - if (match && !matches->compatible[0])
> + if (of_match_one_noncompat(matches, node) &&
> + !matches->compatible[0])
> return matches;
> +
> matches++;
> }
> +
> return NULL;
> }
> EXPORT_SYMBOL(of_match_node);
>
next prev parent reply other threads:[~2012-07-18 2:38 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-07-18 1:11 [PATCH] of: require a match on all fields of of_device_id Scott Wood
2012-07-18 1:57 ` Tabi Timur-B04825
2012-07-18 2:38 ` Rob Herring [this message]
2012-07-18 16:04 ` Scott Wood
2012-07-23 1:56 ` Rob Herring
2012-07-23 15:52 ` Scott Wood
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=50062199.7090904@gmail.com \
--to=robherring2@gmail.com \
--cc=devicetree-discuss@lists.ozlabs.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=scottwood@freescale.com \
--cc=thierry.reding@avionic-design.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).