From patchwork Tue Feb 18 22:31:18 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Grant Likely X-Patchwork-Id: 24918 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-pa0-f71.google.com (mail-pa0-f71.google.com [209.85.220.71]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 006F4202B2 for ; Tue, 18 Feb 2014 22:31:58 +0000 (UTC) Received: by mail-pa0-f71.google.com with SMTP id kp14sf42469974pab.10 for ; Tue, 18 Feb 2014 14:31:58 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe; bh=vLqphOzwMtATGjJyhsDoC8pw3PuadGTbdM6bE/26R0Q=; b=Z2IfWgwVMF/fIRfPfE1MJIEx4QoTnGN02+OCEp/b3NgMuE15HwASeGesvvBZbOxT3y KXSxuGYDJdeOFXN1HX58YaY0cOAyJvxCJ5FV6oL7FiivDu90H5xKtU+lrynFfPOJVGgK TlkT2q+1cc4yck2ycIKjUcWPqBOmzTOdLDEvQIpaWdpztBN6OH21rOxevezzNi7Yvklc 5vc101tFcztzP7ayPcLfzjh/kQMF+g3jyPPpMiOydu44rBQRgps9SS8P/1OYyGvEV7rS lbZjc8YQtAVEJTqGQg8kCzIPHjF7ULSkikOqPtCDQWSrSh5tOOM6bSWBw9pjfPPlOJxr BCIg== X-Gm-Message-State: ALoCoQnx3zJ87YY6xptyOEqr9JV0MqO8m2LExJ4R8Qghc5pm4M1rVwxs367rzi97mfNnd3lkS6sD X-Received: by 10.66.182.137 with SMTP id ee9mr13660738pac.0.1392762718229; Tue, 18 Feb 2014 14:31:58 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.36.200 with SMTP id p66ls1494377qgp.74.gmail; Tue, 18 Feb 2014 14:31:58 -0800 (PST) X-Received: by 10.220.247.68 with SMTP id mb4mr7255252vcb.37.1392762718116; Tue, 18 Feb 2014 14:31:58 -0800 (PST) Received: from mail-ve0-f169.google.com (mail-ve0-f169.google.com [209.85.128.169]) by mx.google.com with ESMTPS id wz4si1844760vdc.59.2014.02.18.14.31.58 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 18 Feb 2014 14:31:58 -0800 (PST) Received-SPF: neutral (google.com: 209.85.128.169 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.128.169; Received: by mail-ve0-f169.google.com with SMTP id oy12so14181272veb.14 for ; Tue, 18 Feb 2014 14:31:58 -0800 (PST) X-Received: by 10.220.103.141 with SMTP id k13mr18742214vco.25.1392762718005; Tue, 18 Feb 2014 14:31:58 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.220.174.196 with SMTP id u4csp251604vcz; Tue, 18 Feb 2014 14:31:57 -0800 (PST) X-Received: by 10.68.180.97 with SMTP id dn1mr35226114pbc.15.1392762716837; Tue, 18 Feb 2014 14:31:56 -0800 (PST) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id d4si19481012pbj.101.2014.02.18.14.31.56; Tue, 18 Feb 2014 14:31:56 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752427AbaBRWby (ORCPT + 9 others); Tue, 18 Feb 2014 17:31:54 -0500 Received: from mail-we0-f181.google.com ([74.125.82.181]:45356 "EHLO mail-we0-f181.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752095AbaBRWbx (ORCPT ); Tue, 18 Feb 2014 17:31:53 -0500 Received: by mail-we0-f181.google.com with SMTP id w61so11732328wes.26 for ; Tue, 18 Feb 2014 14:31:52 -0800 (PST) X-Received: by 10.180.101.166 with SMTP id fh6mr20063324wib.2.1392762711955; Tue, 18 Feb 2014 14:31:51 -0800 (PST) Received: from trevor.secretlab.ca (host109-153-23-84.range109-153.btcentralplus.com. [109.153.23.84]) by mx.google.com with ESMTPSA id dd3sm48759390wjb.9.2014.02.18.14.31.50 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 18 Feb 2014 14:31:51 -0800 (PST) Received: by trevor.secretlab.ca (Postfix, from userid 1000) id B4CCDC40517; Tue, 18 Feb 2014 22:31:47 +0000 (GMT) From: Grant Likely To: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Kevin Hao , Rob Herring , Sebastian Hesselbarth , Grant Likely Subject: [PATCH 2/4] of: reimplement the matching method for __of_match_node() Date: Tue, 18 Feb 2014 22:31:18 +0000 Message-Id: <1392762680-1498-3-git-send-email-grant.likely@linaro.org> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1392762680-1498-1-git-send-email-grant.likely@linaro.org> References: <1392762680-1498-1-git-send-email-grant.likely@linaro.org> Sender: devicetree-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: devicetree@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: grant.likely@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.128.169 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , From: Kevin Hao In the current implementation of __of_match_node(), it will compare each given match entry against all the 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, we define a following priority order for the match, and then scan all the entries to find the best match. 1. specific compatible && type && name 2. specific compatible && type 3. specific compatible && name 4. specific compatible 5. general compatible && type && name 6. general compatible && type 7. general compatible && name 8. general compatible 9. type && name 10. type 11. name This is based on some pseudo-codes provided by Grant Likely. Signed-off-by: Kevin Hao --- drivers/of/base.c | 87 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 68 insertions(+), 19 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index ba195fbce4c6..6e893f6f19a9 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -342,21 +342,28 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) } EXPORT_SYMBOL(of_get_cpu_node); -/** Checks if the given "compat" string matches one of the strings in - * the device's "compatible" property +/* + * Compare with the __of_device_is_compatible, this will return a score for the + * matching strings. The smaller value indicates the match for the more specific + * compatible string. */ -static int __of_device_is_compatible(const struct device_node *device, - const char *compat) +static int __of_device_is_compatible_score(const struct device_node *device, + const char *compat, unsigned int *pscore) { const char* cp; int cplen, l; + unsigned int score = 0; cp = __of_get_property(device, "compatible", &cplen); if (cp == NULL) return 0; while (cplen > 0) { - if (of_compat_cmp(cp, compat, strlen(compat)) == 0) + score++; + if (of_compat_cmp(cp, compat, strlen(compat)) == 0) { + if (pscore) + *pscore = score; return 1; + } l = strlen(cp) + 1; cp += l; cplen -= l; @@ -368,6 +375,15 @@ static int __of_device_is_compatible(const struct device_node *device, /** Checks if the given "compat" string matches one of the strings in * the device's "compatible" property */ +static int __of_device_is_compatible(const struct device_node *device, + const char *compat) +{ + return __of_device_is_compatible_score(device, compat, NULL); +} + +/** Checks if the given "compat" string matches one of the strings in + * the device's "compatible" property + */ int of_device_is_compatible(const struct device_node *device, const char *compat) { @@ -734,25 +750,46 @@ 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 *best_match = NULL; + unsigned int best_score = ~0; + if (!matches) return NULL; 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 (matches->compatible[0]) - match &= __of_device_is_compatible(node, - matches->compatible); - if (match) - return matches; + unsigned int score = ~0; + + /* + * Matching compatible is better than matching type and name, + * and the specific compatible is better than the general. + */ + if (matches->compatible[0] && + __of_device_is_compatible_score(node, + matches->compatible, &score)) + score *= 4; + + /* + * Matching type is better than matching name, but matching + * both is even better than that. + */ + if (matches->type[0] && node->type && + !strcmp(matches->type, node->type)) + score -= 2; + + /* Matching name is a bit better than not */ + if (matches->name[0] && node->name && + !strcmp(matches->name, node->name)) + score--; + + if (score < best_score) { + best_match = matches; + best_score = score; + } + matches++; } - return NULL; + + return best_match; } /** @@ -760,7 +797,19 @@ 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. The priority order + * for the matching is: + * 1. specific compatible && type && name + * 2. specific compatible && type + * 3. specific compatible && name + * 4. specific compatible + * 5. general compatible && type && name + * 6. general compatible && type + * 7. general compatible && name + * 8. general compatible + * 9. type && name + * 10. type + * 11. name */ const struct of_device_id *of_match_node(const struct of_device_id *matches, const struct device_node *node)