diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-02-16 14:03:58 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-02-16 14:03:58 -0500 |
commit | 4302a8750d6f1c26eea16f4a202f9adcb2402014 (patch) | |
tree | e3fd62706531d1e4590062a5c3b8aaf4423c5e8e /drivers | |
parent | 946dd683afb611721cce2cc7e76a19e74f58e067 (diff) | |
parent | 06b29e76a74b2373e6f8b5a7938b3630b9ae98b2 (diff) |
Merge tag 'dt-fixes-for-3.14' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux
Pull devicetree fixes from Rob Herring:
"Fix booting on PPC boards. Changes to of_match_node matching caused
the serial port on some PPC boards to stop working. Reverted the
change and reimplement to split matching between new style compatible
only matching and fallback to old matching algorithm"
* tag 'dt-fixes-for-3.14' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux:
of: search the best compatible match first in __of_match_node()
Revert "OF: base: match each node compatible against all given matches first"
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/of/base.c | 88 |
1 files changed, 54 insertions, 34 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c index ff85450d5683..10b51106c854 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -730,46 +730,64 @@ out: | |||
730 | } | 730 | } |
731 | EXPORT_SYMBOL(of_find_node_with_property); | 731 | EXPORT_SYMBOL(of_find_node_with_property); |
732 | 732 | ||
733 | static | 733 | static const struct of_device_id * |
734 | const struct of_device_id *__of_match_node(const struct of_device_id *matches, | 734 | of_match_compatible(const struct of_device_id *matches, |
735 | const struct device_node *node) | 735 | const struct device_node *node) |
736 | { | 736 | { |
737 | const char *cp; | 737 | const char *cp; |
738 | int cplen, l; | 738 | int cplen, l; |
739 | 739 | const struct of_device_id *m; | |
740 | if (!matches) | ||
741 | return NULL; | ||
742 | 740 | ||
743 | cp = __of_get_property(node, "compatible", &cplen); | 741 | cp = __of_get_property(node, "compatible", &cplen); |
744 | do { | 742 | while (cp && (cplen > 0)) { |
745 | const struct of_device_id *m = matches; | 743 | m = matches; |
746 | |||
747 | /* Check against matches with current compatible string */ | ||
748 | while (m->name[0] || m->type[0] || m->compatible[0]) { | 744 | while (m->name[0] || m->type[0] || m->compatible[0]) { |
749 | int match = 1; | 745 | /* Only match for the entries without type and name */ |
750 | if (m->name[0]) | 746 | if (m->name[0] || m->type[0] || |
751 | match &= node->name | 747 | of_compat_cmp(m->compatible, cp, |
752 | && !strcmp(m->name, node->name); | 748 | strlen(m->compatible))) |
753 | if (m->type[0]) | 749 | m++; |
754 | match &= node->type | 750 | else |
755 | && !strcmp(m->type, node->type); | ||
756 | if (m->compatible[0]) | ||
757 | match &= cp | ||
758 | && !of_compat_cmp(m->compatible, cp, | ||
759 | strlen(m->compatible)); | ||
760 | if (match) | ||
761 | return m; | 751 | return m; |
762 | m++; | ||
763 | } | 752 | } |
764 | 753 | ||
765 | /* Get node's next compatible string */ | 754 | /* Get node's next compatible string */ |
766 | if (cp) { | 755 | l = strlen(cp) + 1; |
767 | l = strlen(cp) + 1; | 756 | cp += l; |
768 | cp += l; | 757 | cplen -= l; |
769 | cplen -= l; | 758 | } |
770 | } | 759 | |
771 | } while (cp && (cplen > 0)); | 760 | return NULL; |
761 | } | ||
762 | |||
763 | static | ||
764 | const struct of_device_id *__of_match_node(const struct of_device_id *matches, | ||
765 | const struct device_node *node) | ||
766 | { | ||
767 | const struct of_device_id *m; | ||
772 | 768 | ||
769 | if (!matches) | ||
770 | return NULL; | ||
771 | |||
772 | m = of_match_compatible(matches, node); | ||
773 | if (m) | ||
774 | return m; | ||
775 | |||
776 | while (matches->name[0] || matches->type[0] || matches->compatible[0]) { | ||
777 | int match = 1; | ||
778 | if (matches->name[0]) | ||
779 | match &= node->name | ||
780 | && !strcmp(matches->name, node->name); | ||
781 | if (matches->type[0]) | ||
782 | match &= node->type | ||
783 | && !strcmp(matches->type, node->type); | ||
784 | if (matches->compatible[0]) | ||
785 | match &= __of_device_is_compatible(node, | ||
786 | matches->compatible); | ||
787 | if (match) | ||
788 | return matches; | ||
789 | matches++; | ||
790 | } | ||
773 | return NULL; | 791 | return NULL; |
774 | } | 792 | } |
775 | 793 | ||
@@ -778,10 +796,12 @@ const struct of_device_id *__of_match_node(const struct of_device_id *matches, | |||
778 | * @matches: array of of device match structures to search in | 796 | * @matches: array of of device match structures to search in |
779 | * @node: the of device structure to match against | 797 | * @node: the of device structure to match against |
780 | * | 798 | * |
781 | * Low level utility function used by device matching. Matching order | 799 | * Low level utility function used by device matching. We have two ways |
782 | * is to compare each of the node's compatibles with all given matches | 800 | * of matching: |
783 | * first. This implies node's compatible is sorted from specific to | 801 | * - Try to find the best compatible match by comparing each compatible |
784 | * generic while matches can be in any order. | 802 | * string of device node with all the given matches respectively. |
803 | * - If the above method failed, then try to match the compatible by using | ||
804 | * __of_device_is_compatible() besides the match in type and name. | ||
785 | */ | 805 | */ |
786 | const struct of_device_id *of_match_node(const struct of_device_id *matches, | 806 | const struct of_device_id *of_match_node(const struct of_device_id *matches, |
787 | const struct device_node *node) | 807 | const struct device_node *node) |