From patchwork Wed Jul 18 01:11:52 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Scott Wood X-Patchwork-Id: 171585 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from ozlabs.org (localhost [IPv6:::1]) by ozlabs.org (Postfix) with ESMTP id DA58C2C04A4 for ; Wed, 18 Jul 2012 11:12:45 +1000 (EST) Received: from tx2outboundpool.messaging.microsoft.com (tx2ehsobe004.messaging.microsoft.com [65.55.88.14]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (Client CN "mail.global.frontbridge.com", Issuer "Microsoft Secure Server Authority" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 381D02C00AB; Wed, 18 Jul 2012 11:12:07 +1000 (EST) Received: from mail174-tx2-R.bigfish.com (10.9.14.235) by TX2EHSOBE004.bigfish.com (10.9.40.24) with Microsoft SMTP Server id 14.1.225.23; Wed, 18 Jul 2012 01:12:02 +0000 Received: from mail174-tx2 (localhost [127.0.0.1]) by mail174-tx2-R.bigfish.com (Postfix) with ESMTP id 61787200A1; Wed, 18 Jul 2012 01:12:02 +0000 (UTC) X-Forefront-Antispam-Report: CIP:70.37.183.190; KIP:(null); UIP:(null); IPV:NLI; H:mail.freescale.net; RD:none; EFVD:NLI X-SpamScore: 0 X-BigFish: VS0(zzzz1202hzz8275bhz2dh2a8h668h839h944hd25hf0ah107ah) Received: from mail174-tx2 (localhost.localdomain [127.0.0.1]) by mail174-tx2 (MessageSwitch) id 1342573920317078_27240; Wed, 18 Jul 2012 01:12:00 +0000 (UTC) Received: from TX2EHSMHS033.bigfish.com (unknown [10.9.14.244]) by mail174-tx2.bigfish.com (Postfix) with ESMTP id 3FF1A42011A; Wed, 18 Jul 2012 01:12:00 +0000 (UTC) Received: from mail.freescale.net (70.37.183.190) by TX2EHSMHS033.bigfish.com (10.9.99.133) with Microsoft SMTP Server (TLS) id 14.1.225.23; Wed, 18 Jul 2012 01:11:57 +0000 Received: from tx30smr01.am.freescale.net (10.81.153.31) by 039-SN1MMR1-003.039d.mgd.msft.net (10.84.1.16) with Microsoft SMTP Server (TLS) id 14.2.298.5; Tue, 17 Jul 2012 20:11:57 -0500 Received: from tyr.buserror.net ([10.214.85.211]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id q6I1BqjM032072; Tue, 17 Jul 2012 18:11:53 -0700 Date: Tue, 17 Jul 2012 20:11:52 -0500 From: Scott Wood To: Thierry Reding , Rob Herring Subject: [PATCH] of: require a match on all fields of of_device_id Message-ID: <20120718011151.GA6119@tyr.buserror.net> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-OriginatorOrg: freescale.com Cc: devicetree-discuss@lists.ozlabs.org, linuxppc-dev@lists.ozlabs.org X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" Commit 107a84e61cdd3406c842a0e4be7efffd3a05dba6 ("of: match by compatible property first") breaks the gianfar ethernet driver found on various Freescale PPC chips. 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 --- 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);