* [PATCH 0/2] of: fix a regression when trying to find the best compatible match @ 2014-02-14 5:22 Kevin Hao [not found] ` < 1392355366-1445-3-git-send-email-haokexin@gmail.com> ` (2 more replies) 0 siblings, 3 replies; 10+ messages in thread From: Kevin Hao @ 2014-02-14 5:22 UTC (permalink / raw) To: devicetree, linuxppc-dev Cc: Grant Likely, Stephen N Chivers, Rob Herring, Kevin Hao, Sebastian Hesselbarth Hi, This fix a regression when trying to find the best compatible match. You can find the detail of the issue reported by Stephen Chivers at: https://lists.ozlabs.org/pipermail/linuxppc-dev/2014-February/115278.html I have made a patch to fix this previously. http://patchwork.ozlabs.org/patch/319624/ This is another respin with the implementation suggested by Rob Herring. Kevin Hao (2): Revert "OF: base: match each node compatible against all given matches first" of: search the best compatible match first in __of_match_node() drivers/of/base.c | 88 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 34 deletions(-) -- 1.8.5.3 ^ permalink raw reply [flat|nested] 10+ messages in thread
[parent not found: < 1392355366-1445-3-git-send-email-haokexin@gmail.com>]
* [PATCH 1/2] Revert "OF: base: match each node compatible against all given matches first" 2014-02-14 5:22 [PATCH 0/2] of: fix a regression when trying to find the best compatible match Kevin Hao [not found] ` < 1392355366-1445-3-git-send-email-haokexin@gmail.com> @ 2014-02-14 5:22 ` Kevin Hao 2014-02-14 5:22 ` [PATCH 2/2] of: search the best compatible match first in __of_match_node() Kevin Hao 2 siblings, 0 replies; 10+ messages in thread From: Kevin Hao @ 2014-02-14 5:22 UTC (permalink / raw) To: devicetree, linuxppc-dev Cc: Grant Likely, Stephen N Chivers, Rob Herring, Kevin Hao, Sebastian Hesselbarth This reverts commit 105353145eafb3ea919f5cdeb652a9d8f270228e. Stephen Chivers reported this is broken as we will get a match entry '.type = "serial"' instead of the '.compatible = "ns16550"' in the following scenario: serial0: serial@4500 { compatible = "fsl,ns16550", "ns16550"; } struct of_device_id of_platform_serial_table[] = { { .compatible = "ns8250", .data = (void *)PORT_8250, }, { .compatible = "ns16450", .data = (void *)PORT_16450, }, { .compatible = "ns16550a", .data = (void *)PORT_16550A, }, { .compatible = "ns16550", .data = (void *)PORT_16550, }, { .compatible = "ns16750", .data = (void *)PORT_16750, }, { .compatible = "ns16850", .data = (void *)PORT_16850, }, ... { .type = "serial", .data = (void *)PORT_UNKNOWN, }, { /* end of list */ }, }; So just revert this patch, we will use another implementation to find the best compatible match in a follow-on patch. Reported-by: Stephen N Chivers <schivers@csc.com.au> Cc: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> Signed-off-by: Kevin Hao <haokexin@gmail.com> --- drivers/of/base.c | 53 ++++++++++++++++------------------------------------- 1 file changed, 16 insertions(+), 37 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index ff85450d5683..ba195fbce4c6 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -734,42 +734,24 @@ 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; - if (!matches) return NULL; - cp = __of_get_property(node, "compatible", &cplen); - do { - const struct of_device_id *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, - strlen(m->compatible)); - if (match) - return m; - m++; - } - - /* Get node's next compatible string */ - if (cp) { - l = strlen(cp) + 1; - cp += l; - cplen -= l; - } - } while (cp && (cplen > 0)); - + 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; + matches++; + } return NULL; } @@ -778,10 +760,7 @@ 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. Matching order - * is to compare each of the node's compatibles with all given matches - * first. This implies node's compatible is sorted from specific to - * generic while matches can be in any order. + * Low level utility function used by device matching. */ const struct of_device_id *of_match_node(const struct of_device_id *matches, const struct device_node *node) -- 1.8.5.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/2] of: search the best compatible match first in __of_match_node() 2014-02-14 5:22 [PATCH 0/2] of: fix a regression when trying to find the best compatible match Kevin Hao [not found] ` < 1392355366-1445-3-git-send-email-haokexin@gmail.com> 2014-02-14 5:22 ` [PATCH 1/2] Revert "OF: base: match each node compatible against all given matches first" Kevin Hao @ 2014-02-14 5:22 ` Kevin Hao 2014-02-14 15:53 ` Rob Herring 2014-02-17 17:58 ` Grant Likely 2 siblings, 2 replies; 10+ messages in thread From: Kevin Hao @ 2014-02-14 5:22 UTC (permalink / raw) To: devicetree, linuxppc-dev Cc: Grant Likely, Stephen N Chivers, Rob Herring, Kevin Hao, Sebastian Hesselbarth 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> --- drivers/of/base.c | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index ba195fbce4c6..10b51106c854 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -730,13 +730,49 @@ out: } EXPORT_SYMBOL(of_find_node_with_property); +static const struct of_device_id * +of_match_compatible(const struct of_device_id *matches, + const struct device_node *node) +{ + const char *cp; + int cplen, l; + const struct of_device_id *m; + + cp = __of_get_property(node, "compatible", &cplen); + while (cp && (cplen > 0)) { + m = matches; + while (m->name[0] || m->type[0] || m->compatible[0]) { + /* Only match for the entries without type and name */ + if (m->name[0] || m->type[0] || + of_compat_cmp(m->compatible, cp, + strlen(m->compatible))) + m++; + else + return m; + } + + /* Get node's next compatible string */ + l = strlen(cp) + 1; + cp += l; + cplen -= l; + } + + return NULL; +} + 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 *m; + if (!matches) return NULL; + m = of_match_compatible(matches, node); + if (m) + return m; + while (matches->name[0] || matches->type[0] || matches->compatible[0]) { int match = 1; if (matches->name[0]) @@ -760,7 +796,12 @@ 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. We have two ways + * of matching: + * - Try to find the best compatible match by comparing each compatible + * string of device node with all the given matches respectively. + * - If the above method failed, then try to match the compatible by using + * __of_device_is_compatible() besides the match in type and name. */ const struct of_device_id *of_match_node(const struct of_device_id *matches, const struct device_node *node) -- 1.8.5.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] of: search the best compatible match first in __of_match_node() 2014-02-14 5:22 ` [PATCH 2/2] of: search the best compatible match first in __of_match_node() Kevin Hao @ 2014-02-14 15:53 ` Rob Herring 2014-02-14 16:19 ` Kumar Gala ` (3 more replies) 2014-02-17 17:58 ` Grant Likely 1 sibling, 4 replies; 10+ messages in thread From: Rob Herring @ 2014-02-14 15:53 UTC (permalink / raw) To: Kevin Hao Cc: devicetree@vger.kernel.org, Stephen N Chivers, Rob Herring, Kumar Gala, Grant Likely, linuxppc-dev, Sebastian Hesselbarth On Thu, Feb 13, 2014 at 11:22 PM, Kevin Hao <haokexin@gmail.com> wrote: > 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> Looks good to me. I'll put this in next for a few days. I'd really like to see some acks and tested-by's before sending to Linus. We could be a bit more strict here and fallback to the old matching if the match table has any entries with name or type. I don't think that should be necessary though. Rob > --- > drivers/of/base.c | 43 ++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 42 insertions(+), 1 deletion(-) > > diff --git a/drivers/of/base.c b/drivers/of/base.c > index ba195fbce4c6..10b51106c854 100644 > --- a/drivers/of/base.c > +++ b/drivers/of/base.c > @@ -730,13 +730,49 @@ out: > } > EXPORT_SYMBOL(of_find_node_with_property); > > +static const struct of_device_id * > +of_match_compatible(const struct of_device_id *matches, > + const struct device_node *node) > +{ > + const char *cp; > + int cplen, l; > + const struct of_device_id *m; > + > + cp = __of_get_property(node, "compatible", &cplen); > + while (cp && (cplen > 0)) { > + m = matches; > + while (m->name[0] || m->type[0] || m->compatible[0]) { > + /* Only match for the entries without type and name */ > + if (m->name[0] || m->type[0] || > + of_compat_cmp(m->compatible, cp, > + strlen(m->compatible))) > + m++; > + else > + return m; > + } > + > + /* Get node's next compatible string */ > + l = strlen(cp) + 1; > + cp += l; > + cplen -= l; > + } > + > + return NULL; > +} > + > 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 *m; > + > if (!matches) > return NULL; > > + m = of_match_compatible(matches, node); > + if (m) > + return m; > + > while (matches->name[0] || matches->type[0] || matches->compatible[0]) { > int match = 1; > if (matches->name[0]) > @@ -760,7 +796,12 @@ 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. We have two ways > + * of matching: > + * - Try to find the best compatible match by comparing each compatible > + * string of device node with all the given matches respectively. > + * - If the above method failed, then try to match the compatible by using > + * __of_device_is_compatible() besides the match in type and name. > */ > const struct of_device_id *of_match_node(const struct of_device_id *matches, > const struct device_node *node) > -- > 1.8.5.3 > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] of: search the best compatible match first in __of_match_node() 2014-02-14 15:53 ` Rob Herring @ 2014-02-14 16:19 ` Kumar Gala 2014-02-14 16:23 ` Kumar Gala ` (2 subsequent siblings) 3 siblings, 0 replies; 10+ messages in thread From: Kumar Gala @ 2014-02-14 16:19 UTC (permalink / raw) To: Rob Herring Cc: devicetree@vger.kernel.org, Kevin Hao, Stephen N Chivers, Rob Herring, Grant Likely, linuxppc-dev, Sebastian Hesselbarth On Feb 14, 2014, at 9:53 AM, Rob Herring <robherring2@gmail.com> wrote: > On Thu, Feb 13, 2014 at 11:22 PM, Kevin Hao <haokexin@gmail.com> = wrote: >> Currently, of_match_node compares each given match against all node's >> compatible strings with of_device_is_compatible. >>=20 >> 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. >>=20 >> 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. >>=20 >> Cc: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> >> Signed-off-by: Kevin Hao <haokexin@gmail.com> >=20 > Looks good to me. I'll put this in next for a few days. I'd really > like to see some acks and tested-by's before sending to Linus. >=20 > We could be a bit more strict here and fallback to the old matching if > the match table has any entries with name or type. I don't think that > should be necessary though. >=20 > Rob Can you push the revert to Linus sooner, since currently a ton of boards = wouldn=92t be working on the PPC side, so at least -rc3 has the = possibility of working for them. - k >=20 >> --- >> drivers/of/base.c | 43 ++++++++++++++++++++++++++++++++++++++++++- >> 1 file changed, 42 insertions(+), 1 deletion(-) >>=20 >> diff --git a/drivers/of/base.c b/drivers/of/base.c >> index ba195fbce4c6..10b51106c854 100644 >> --- a/drivers/of/base.c >> +++ b/drivers/of/base.c >> @@ -730,13 +730,49 @@ out: >> } >> EXPORT_SYMBOL(of_find_node_with_property); >>=20 >> +static const struct of_device_id * >> +of_match_compatible(const struct of_device_id *matches, >> + const struct device_node *node) >> +{ >> + const char *cp; >> + int cplen, l; >> + const struct of_device_id *m; >> + >> + cp =3D __of_get_property(node, "compatible", &cplen); >> + while (cp && (cplen > 0)) { >> + m =3D matches; >> + while (m->name[0] || m->type[0] || m->compatible[0]) = { >> + /* Only match for the entries without type = and name */ >> + if (m->name[0] || m->type[0] || >> + of_compat_cmp(m->compatible, cp, >> + strlen(m->compatible))) >> + m++; >> + else >> + return m; >> + } >> + >> + /* Get node's next compatible string */ >> + l =3D strlen(cp) + 1; >> + cp +=3D l; >> + cplen -=3D l; >> + } >> + >> + return NULL; >> +} >> + >> 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 *m; >> + >> if (!matches) >> return NULL; >>=20 >> + m =3D of_match_compatible(matches, node); >> + if (m) >> + return m; >> + >> while (matches->name[0] || matches->type[0] || = matches->compatible[0]) { >> int match =3D 1; >> if (matches->name[0]) >> @@ -760,7 +796,12 @@ 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. We have = two ways >> + * of matching: >> + * - Try to find the best compatible match by comparing each = compatible >> + * string of device node with all the given matches = respectively. >> + * - If the above method failed, then try to match the = compatible by using >> + * __of_device_is_compatible() besides the match in type and = name. >> */ >> const struct of_device_id *of_match_node(const struct of_device_id = *matches, >> const struct device_node = *node) >> -- >> 1.8.5.3 --=20 Employee of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, = hosted by The Linux Foundation ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] of: search the best compatible match first in __of_match_node() 2014-02-14 15:53 ` Rob Herring 2014-02-14 16:19 ` Kumar Gala @ 2014-02-14 16:23 ` Kumar Gala 2014-02-15 5:19 ` Stephen N Chivers 2014-02-17 17:59 ` Grant Likely 3 siblings, 0 replies; 10+ messages in thread From: Kumar Gala @ 2014-02-14 16:23 UTC (permalink / raw) To: Rob Herring Cc: devicetree@vger.kernel.org, Kevin Hao, Stephen N Chivers, Rob Herring, Grant Likely, linuxppc-dev, Sebastian Hesselbarth On Feb 14, 2014, at 9:53 AM, Rob Herring <robherring2@gmail.com> wrote: > On Thu, Feb 13, 2014 at 11:22 PM, Kevin Hao <haokexin@gmail.com> = wrote: >> Currently, of_match_node compares each given match against all node's >> compatible strings with of_device_is_compatible. >>=20 >> 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. >>=20 >> 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. >>=20 >> Cc: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> >> Signed-off-by: Kevin Hao <haokexin@gmail.com> >=20 > Looks good to me. I'll put this in next for a few days. I'd really > like to see some acks and tested-by's before sending to Linus. >=20 > We could be a bit more strict here and fallback to the old matching if > the match table has any entries with name or type. I don't think that > should be necessary though. >=20 > Rob >=20 Can you push the revert to Linus sooner, since currently a ton of boards = wouldn=92t be working on the PPC side, so at least -rc3 has the = possibility of working for them. - k ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] of: search the best compatible match first in __of_match_node() 2014-02-14 15:53 ` Rob Herring 2014-02-14 16:19 ` Kumar Gala 2014-02-14 16:23 ` Kumar Gala @ 2014-02-15 5:19 ` Stephen N Chivers 2014-02-17 17:59 ` Grant Likely 3 siblings, 0 replies; 10+ messages in thread From: Stephen N Chivers @ 2014-02-15 5:19 UTC (permalink / raw) To: Rob Herring Cc: devicetree@vger.kernel.org, Kevin Hao, Chris Proctor, Stephen N Chivers, Kumar Gala, Grant Likely, linuxppc-dev, Sebastian Hesselbarth Rob Herring <robherring2@gmail.com> wrote on 02/15/2014 02:53:40 AM: > From: Rob Herring <robherring2@gmail.com> > To: Kevin Hao <haokexin@gmail.com> > Cc: "devicetree@vger.kernel.org" <devicetree@vger.kernel.org>, > linuxppc-dev <linuxppc-dev@lists.ozlabs.org>, Sebastian Hesselbarth > <sebastian.hesselbarth@gmail.com>, Stephen N Chivers > <schivers@csc.com.au>, Grant Likely <grant.likely@linaro.org>, Rob > Herring <robh+dt@kernel.org>, Kumar Gala <galak@codeaurora.org> > Date: 02/15/2014 02:53 AM > Subject: Re: [PATCH 2/2] of: search the best compatible match first > in __of_match_node() > > On Thu, Feb 13, 2014 at 11:22 PM, Kevin Hao <haokexin@gmail.com> wrote: > > 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> > > Looks good to me. I'll put this in next for a few days. I'd really > like to see some acks and tested-by's before sending to Linus. > Tested-by: Stephen Chivers <schivers@csc.com> I have tested the patch for the four PowerPC platforms available to me. They are: MPC8349_MITXGP - Works. MVME5100 - Works. MVME4100 - Works. SAM440EP - Works. The MPC8349_MITXGP platform is present in Linux-3.13 and previous releases. The MVME5100 is a "revived" platform that is in Linux-3.14-rc2. The MVME4100 is a work in progress and is the 85xx platform that the original failure report was for. The SAM440EP is present in Linux-3.13 and previous releases. The MPC8349_MITXGP is one of the 49 DTS files with the serial compatible: compatible = "fsl,ns16550", "ns16550"; For the SAM440EP, the patch improves things from Linux-3.13. In that release the same sort of problem as reported in: "Linux-3.14-rc2: Order of serial node compatibles in DTS files." occurs with slightly different symptoms: of_serial ef600300.serial: Port found of_serial ef600300.serial: Port found of_serial ef600300.serial: Unknown serial port found, ignored of_serial ef600400.serial: Port found of_serial ef600400.serial: Port found of_serial ef600400.serial: Unknown serial port found, ignored of_serial ef600500.serial: Port found of_serial ef600500.serial: Port found of_serial ef600500.serial: Unknown serial port found, ignored of_serial ef600600.serial: Port found of_serial ef600600.serial: Port found of_serial ef600600.serial: Unknown serial port found, ignored The SAM440EP has a IBM/AMCC 440EP PowerPC CPU and so simply has "ns16550" as its serial compatible. > We could be a bit more strict here and fallback to the old matching if > the match table has any entries with name or type. I don't think that > should be necessary though. > > Rob Stephen Chivers, CSC Australia Pty. Ltd. > > > --- > > drivers/of/base.c | 43 ++++++++++++++++++++++++++++++++++++++++++- > > 1 file changed, 42 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/of/base.c b/drivers/of/base.c > > index ba195fbce4c6..10b51106c854 100644 > > --- a/drivers/of/base.c > > +++ b/drivers/of/base.c > > @@ -730,13 +730,49 @@ out: > > } > > EXPORT_SYMBOL(of_find_node_with_property); > > > > +static const struct of_device_id * > > +of_match_compatible(const struct of_device_id *matches, > > + const struct device_node *node) > > +{ > > + const char *cp; > > + int cplen, l; > > + const struct of_device_id *m; > > + > > + cp = __of_get_property(node, "compatible", &cplen); > > + while (cp && (cplen > 0)) { > > + m = matches; > > + while (m->name[0] || m->type[0] || m->compatible[0]) { > > + /* Only match for the entries without type > and name */ > > + if (m->name[0] || m->type[0] || > > + of_compat_cmp(m->compatible, cp, > > + strlen(m->compatible))) > > + m++; > > + else > > + return m; > > + } > > + > > + /* Get node's next compatible string */ > > + l = strlen(cp) + 1; > > + cp += l; > > + cplen -= l; > > + } > > + > > + return NULL; > > +} > > + > > 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 *m; > > + > > if (!matches) > > return NULL; > > > > + m = of_match_compatible(matches, node); > > + if (m) > > + return m; > > + > > while (matches->name[0] || matches->type[0] || > matches->compatible[0]) { > > int match = 1; > > if (matches->name[0]) > > @@ -760,7 +796,12 @@ 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. We have two ways > > + * of matching: > > + * - Try to find the best compatible match by comparing each compatible > > + * string of device node with all the given matches respectively. > > + * - If the above method failed, then try to match the > compatible by using > > + * __of_device_is_compatible() besides the match in type and name. > > */ > > const struct of_device_id *of_match_node(const struct > of_device_id *matches, > > const struct device_node *node) > > -- > > 1.8.5.3 > > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] of: search the best compatible match first in __of_match_node() 2014-02-14 15:53 ` Rob Herring ` (2 preceding siblings ...) 2014-02-15 5:19 ` Stephen N Chivers @ 2014-02-17 17:59 ` Grant Likely 3 siblings, 0 replies; 10+ messages in thread From: Grant Likely @ 2014-02-17 17:59 UTC (permalink / raw) To: Rob Herring, Kevin Hao Cc: devicetree@vger.kernel.org, Stephen N Chivers, Rob Herring, Kumar Gala, linuxppc-dev, Sebastian Hesselbarth On Fri, 14 Feb 2014 09:53:40 -0600, Rob Herring <robherring2@gmail.com> wrote: > On Thu, Feb 13, 2014 at 11:22 PM, Kevin Hao <haokexin@gmail.com> wrote: > > 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> > > Looks good to me. I'll put this in next for a few days. I'd really > like to see some acks and tested-by's before sending to Linus. As I commented on the patch, I don't think the new solution is correct either. I've made a suggestion on how to fix it, but in the mean time the revert should be applied and sent to Linus. g. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] of: search the best compatible match first in __of_match_node() 2014-02-14 5:22 ` [PATCH 2/2] of: search the best compatible match first in __of_match_node() Kevin Hao 2014-02-14 15:53 ` Rob Herring @ 2014-02-17 17:58 ` Grant Likely 2014-02-18 5:41 ` Kevin Hao 1 sibling, 1 reply; 10+ messages in thread From: Grant Likely @ 2014-02-17 17:58 UTC (permalink / raw) To: Kevin Hao, devicetree, linuxppc-dev Cc: Stephen N Chivers, Rob Herring, Kevin Hao, Sebastian Hesselbarth On Fri, 14 Feb 2014 13:22:46 +0800, Kevin Hao <haokexin@gmail.com> wrote: > 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> > --- > drivers/of/base.c | 43 ++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 42 insertions(+), 1 deletion(-) > > diff --git a/drivers/of/base.c b/drivers/of/base.c > index ba195fbce4c6..10b51106c854 100644 > --- a/drivers/of/base.c > +++ b/drivers/of/base.c > @@ -730,13 +730,49 @@ out: > } > EXPORT_SYMBOL(of_find_node_with_property); > > +static const struct of_device_id * > +of_match_compatible(const struct of_device_id *matches, > + const struct device_node *node) > +{ > + const char *cp; > + int cplen, l; > + const struct of_device_id *m; > + > + cp = __of_get_property(node, "compatible", &cplen); > + while (cp && (cplen > 0)) { > + m = matches; > + while (m->name[0] || m->type[0] || m->compatible[0]) { > + /* Only match for the entries without type and name */ > + if (m->name[0] || m->type[0] || > + of_compat_cmp(m->compatible, cp, > + strlen(m->compatible))) > + m++; This seems wrong also. The compatible order should be checked for even when m->name or m->type are set. You actually need to score the entries to do this properly. The pseudo-code should look like this: uint best_score = ~0; of_device_id *best_match = NULL; for_each(matches) { uint score = ~0; for_each_compatible(index) { if (match->compatible == compatible[index]) score = index * 10; } /* Matching name is a bit better than not */ if (match->name == node->name) score--; /* Matching type is better than matching name */ /* (but matching both is even better than that */ if (match->type == node->type) score -= 2; if (score < best_score) best_match = match; } return best_match; This is actually very similar to the original code. It is an easy modification. This is very similar to how the of_fdt_is_compatible() function works. g. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] of: search the best compatible match first in __of_match_node() 2014-02-17 17:58 ` Grant Likely @ 2014-02-18 5:41 ` Kevin Hao 0 siblings, 0 replies; 10+ messages in thread From: Kevin Hao @ 2014-02-18 5:41 UTC (permalink / raw) To: Grant Likely Cc: devicetree, Rob Herring, linuxppc-dev, Stephen N Chivers, Sebastian Hesselbarth [-- Attachment #1: Type: text/plain, Size: 1101 bytes --] On Mon, Feb 17, 2014 at 05:58:34PM +0000, Grant Likely wrote: > This seems wrong also. The compatible order should be checked for even > when m->name or m->type are set. You actually need to score the entries > to do this properly. The pseudo-code should look like this: > > uint best_score = ~0; > of_device_id *best_match = NULL; > for_each(matches) { > uint score = ~0; > for_each_compatible(index) { > if (match->compatible == compatible[index]) > score = index * 10; > } > > /* Matching name is a bit better than not */ > if (match->name == node->name) > score--; > > /* Matching type is better than matching name */ > /* (but matching both is even better than that */ > if (match->type == node->type) > score -= 2; > > if (score < best_score) > best_match = match; > } > return best_match; > > This is actually very similar to the original code. It is an easy > modification. This is very similar to how the of_fdt_is_compatible() > function works. I like this idea and will make a new patch based on this. Thanks, Kevin > > g. [-- Attachment #2: Type: application/pgp-signature, Size: 490 bytes --] ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2014-02-18 5:42 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-02-14 5:22 [PATCH 0/2] of: fix a regression when trying to find the best compatible match Kevin Hao [not found] ` < 1392355366-1445-3-git-send-email-haokexin@gmail.com> 2014-02-14 5:22 ` [PATCH 1/2] Revert "OF: base: match each node compatible against all given matches first" Kevin Hao 2014-02-14 5:22 ` [PATCH 2/2] of: search the best compatible match first in __of_match_node() Kevin Hao 2014-02-14 15:53 ` Rob Herring 2014-02-14 16:19 ` Kumar Gala 2014-02-14 16:23 ` Kumar Gala 2014-02-15 5:19 ` Stephen N Chivers 2014-02-17 17:59 ` Grant Likely 2014-02-17 17:58 ` Grant Likely 2014-02-18 5:41 ` Kevin Hao
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).