diff options
author | Rob Herring <robh@kernel.org> | 2014-05-28 11:54:20 -0400 |
---|---|---|
committer | Rob Herring <robh@kernel.org> | 2014-05-28 11:54:20 -0400 |
commit | aa10537f62f2d508f68195b496d9a9021f5d2eff (patch) | |
tree | 14a8a16ec61dc5f604c3b8abfc87aa58afe76a5d | |
parent | eafd370dfe487facfdef499057f4eac9aa0b4bf5 (diff) | |
parent | 08cf78ed41feaa21017487bad0a5a405c6cede43 (diff) |
Merge tag 'dt-for-robh' of git://git.secretlab.ca/git/linux into for-next
Pull DT changes from Grant Likely:
DT queued up for v3.16
Mostly bug fixes, but also some rework to improve path handling and device naming
-rw-r--r-- | arch/powerpc/include/asm/dcr-mmio.h | 4 | ||||
-rw-r--r-- | arch/powerpc/sysdev/dcr.c | 6 | ||||
-rw-r--r-- | drivers/base/platform.c | 7 | ||||
-rw-r--r-- | drivers/of/base.c | 115 | ||||
-rw-r--r-- | drivers/of/fdt.c | 4 | ||||
-rw-r--r-- | drivers/of/irq.c | 22 | ||||
-rw-r--r-- | drivers/of/of_pci_irq.c | 8 | ||||
-rw-r--r-- | drivers/of/platform.c | 62 | ||||
-rw-r--r-- | drivers/of/selftest.c | 46 | ||||
-rw-r--r-- | drivers/of/testcase-data/tests-phandle.dtsi | 6 | ||||
-rw-r--r-- | include/linux/of_irq.h | 5 | ||||
-rw-r--r-- | include/linux/string.h | 3 | ||||
-rw-r--r-- | lib/string.c | 18 |
13 files changed, 222 insertions, 84 deletions
diff --git a/arch/powerpc/include/asm/dcr-mmio.h b/arch/powerpc/include/asm/dcr-mmio.h index acd491dbd45a..93a68b28e695 100644 --- a/arch/powerpc/include/asm/dcr-mmio.h +++ b/arch/powerpc/include/asm/dcr-mmio.h | |||
@@ -51,10 +51,6 @@ static inline void dcr_write_mmio(dcr_host_mmio_t host, | |||
51 | out_be32(host.token + ((host.base + dcr_n) * host.stride), value); | 51 | out_be32(host.token + ((host.base + dcr_n) * host.stride), value); |
52 | } | 52 | } |
53 | 53 | ||
54 | extern u64 of_translate_dcr_address(struct device_node *dev, | ||
55 | unsigned int dcr_n, | ||
56 | unsigned int *stride); | ||
57 | |||
58 | #endif /* __KERNEL__ */ | 54 | #endif /* __KERNEL__ */ |
59 | #endif /* _ASM_POWERPC_DCR_MMIO_H */ | 55 | #endif /* _ASM_POWERPC_DCR_MMIO_H */ |
60 | 56 | ||
diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c index 1bd0eba4d355..e9056e438575 100644 --- a/arch/powerpc/sysdev/dcr.c +++ b/arch/powerpc/sysdev/dcr.c | |||
@@ -152,9 +152,9 @@ EXPORT_SYMBOL_GPL(dcr_resource_len); | |||
152 | 152 | ||
153 | #ifdef CONFIG_PPC_DCR_MMIO | 153 | #ifdef CONFIG_PPC_DCR_MMIO |
154 | 154 | ||
155 | u64 of_translate_dcr_address(struct device_node *dev, | 155 | static u64 of_translate_dcr_address(struct device_node *dev, |
156 | unsigned int dcr_n, | 156 | unsigned int dcr_n, |
157 | unsigned int *out_stride) | 157 | unsigned int *out_stride) |
158 | { | 158 | { |
159 | struct device_node *dp; | 159 | struct device_node *dp; |
160 | const u32 *p; | 160 | const u32 *p; |
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 5b47210889e0..9e9227e1762d 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -131,9 +131,12 @@ EXPORT_SYMBOL_GPL(platform_get_resource_byname); | |||
131 | */ | 131 | */ |
132 | int platform_get_irq_byname(struct platform_device *dev, const char *name) | 132 | int platform_get_irq_byname(struct platform_device *dev, const char *name) |
133 | { | 133 | { |
134 | struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ, | 134 | struct resource *r; |
135 | name); | 135 | |
136 | if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node) | ||
137 | return of_irq_get_byname(dev->dev.of_node, name); | ||
136 | 138 | ||
139 | r = platform_get_resource_byname(dev, IORESOURCE_IRQ, name); | ||
137 | return r ? r->start : -ENXIO; | 140 | return r ? r->start : -ENXIO; |
138 | } | 141 | } |
139 | EXPORT_SYMBOL_GPL(platform_get_irq_byname); | 142 | EXPORT_SYMBOL_GPL(platform_get_irq_byname); |
diff --git a/drivers/of/base.c b/drivers/of/base.c index 6d4ee22708c9..e67b308819c9 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -695,6 +695,22 @@ struct device_node *of_get_next_parent(struct device_node *node) | |||
695 | } | 695 | } |
696 | EXPORT_SYMBOL(of_get_next_parent); | 696 | EXPORT_SYMBOL(of_get_next_parent); |
697 | 697 | ||
698 | static struct device_node *__of_get_next_child(const struct device_node *node, | ||
699 | struct device_node *prev) | ||
700 | { | ||
701 | struct device_node *next; | ||
702 | |||
703 | next = prev ? prev->sibling : node->child; | ||
704 | for (; next; next = next->sibling) | ||
705 | if (of_node_get(next)) | ||
706 | break; | ||
707 | of_node_put(prev); | ||
708 | return next; | ||
709 | } | ||
710 | #define __for_each_child_of_node(parent, child) \ | ||
711 | for (child = __of_get_next_child(parent, NULL); child != NULL; \ | ||
712 | child = __of_get_next_child(parent, child)) | ||
713 | |||
698 | /** | 714 | /** |
699 | * of_get_next_child - Iterate a node childs | 715 | * of_get_next_child - Iterate a node childs |
700 | * @node: parent node | 716 | * @node: parent node |
@@ -710,11 +726,7 @@ struct device_node *of_get_next_child(const struct device_node *node, | |||
710 | unsigned long flags; | 726 | unsigned long flags; |
711 | 727 | ||
712 | raw_spin_lock_irqsave(&devtree_lock, flags); | 728 | raw_spin_lock_irqsave(&devtree_lock, flags); |
713 | next = prev ? prev->sibling : node->child; | 729 | next = __of_get_next_child(node, prev); |
714 | for (; next; next = next->sibling) | ||
715 | if (of_node_get(next)) | ||
716 | break; | ||
717 | of_node_put(prev); | ||
718 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | 730 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
719 | return next; | 731 | return next; |
720 | } | 732 | } |
@@ -771,23 +783,78 @@ struct device_node *of_get_child_by_name(const struct device_node *node, | |||
771 | } | 783 | } |
772 | EXPORT_SYMBOL(of_get_child_by_name); | 784 | EXPORT_SYMBOL(of_get_child_by_name); |
773 | 785 | ||
786 | static struct device_node *__of_find_node_by_path(struct device_node *parent, | ||
787 | const char *path) | ||
788 | { | ||
789 | struct device_node *child; | ||
790 | int len = strchrnul(path, '/') - path; | ||
791 | |||
792 | if (!len) | ||
793 | return NULL; | ||
794 | |||
795 | __for_each_child_of_node(parent, child) { | ||
796 | const char *name = strrchr(child->full_name, '/'); | ||
797 | if (WARN(!name, "malformed device_node %s\n", child->full_name)) | ||
798 | continue; | ||
799 | name++; | ||
800 | if (strncmp(path, name, len) == 0 && (strlen(name) == len)) | ||
801 | return child; | ||
802 | } | ||
803 | return NULL; | ||
804 | } | ||
805 | |||
774 | /** | 806 | /** |
775 | * of_find_node_by_path - Find a node matching a full OF path | 807 | * of_find_node_by_path - Find a node matching a full OF path |
776 | * @path: The full path to match | 808 | * @path: Either the full path to match, or if the path does not |
809 | * start with '/', the name of a property of the /aliases | ||
810 | * node (an alias). In the case of an alias, the node | ||
811 | * matching the alias' value will be returned. | ||
812 | * | ||
813 | * Valid paths: | ||
814 | * /foo/bar Full path | ||
815 | * foo Valid alias | ||
816 | * foo/bar Valid alias + relative path | ||
777 | * | 817 | * |
778 | * Returns a node pointer with refcount incremented, use | 818 | * Returns a node pointer with refcount incremented, use |
779 | * of_node_put() on it when done. | 819 | * of_node_put() on it when done. |
780 | */ | 820 | */ |
781 | struct device_node *of_find_node_by_path(const char *path) | 821 | struct device_node *of_find_node_by_path(const char *path) |
782 | { | 822 | { |
783 | struct device_node *np = of_allnodes; | 823 | struct device_node *np = NULL; |
824 | struct property *pp; | ||
784 | unsigned long flags; | 825 | unsigned long flags; |
785 | 826 | ||
827 | if (strcmp(path, "/") == 0) | ||
828 | return of_node_get(of_allnodes); | ||
829 | |||
830 | /* The path could begin with an alias */ | ||
831 | if (*path != '/') { | ||
832 | char *p = strchrnul(path, '/'); | ||
833 | int len = p - path; | ||
834 | |||
835 | /* of_aliases must not be NULL */ | ||
836 | if (!of_aliases) | ||
837 | return NULL; | ||
838 | |||
839 | for_each_property_of_node(of_aliases, pp) { | ||
840 | if (strlen(pp->name) == len && !strncmp(pp->name, path, len)) { | ||
841 | np = of_find_node_by_path(pp->value); | ||
842 | break; | ||
843 | } | ||
844 | } | ||
845 | if (!np) | ||
846 | return NULL; | ||
847 | path = p; | ||
848 | } | ||
849 | |||
850 | /* Step down the tree matching path components */ | ||
786 | raw_spin_lock_irqsave(&devtree_lock, flags); | 851 | raw_spin_lock_irqsave(&devtree_lock, flags); |
787 | for (; np; np = np->allnext) { | 852 | if (!np) |
788 | if (np->full_name && (of_node_cmp(np->full_name, path) == 0) | 853 | np = of_node_get(of_allnodes); |
789 | && of_node_get(np)) | 854 | while (np && *path == '/') { |
790 | break; | 855 | path++; /* Increment past '/' delimiter */ |
856 | np = __of_find_node_by_path(np, path); | ||
857 | path = strchrnul(path, '/'); | ||
791 | } | 858 | } |
792 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | 859 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
793 | return np; | 860 | return np; |
@@ -1800,7 +1867,7 @@ int of_update_property(struct device_node *np, struct property *newprop) | |||
1800 | { | 1867 | { |
1801 | struct property **next, *oldprop; | 1868 | struct property **next, *oldprop; |
1802 | unsigned long flags; | 1869 | unsigned long flags; |
1803 | int rc, found = 0; | 1870 | int rc; |
1804 | 1871 | ||
1805 | rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop); | 1872 | rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop); |
1806 | if (rc) | 1873 | if (rc) |
@@ -1809,30 +1876,34 @@ int of_update_property(struct device_node *np, struct property *newprop) | |||
1809 | if (!newprop->name) | 1876 | if (!newprop->name) |
1810 | return -EINVAL; | 1877 | return -EINVAL; |
1811 | 1878 | ||
1812 | oldprop = of_find_property(np, newprop->name, NULL); | ||
1813 | if (!oldprop) | ||
1814 | return of_add_property(np, newprop); | ||
1815 | |||
1816 | raw_spin_lock_irqsave(&devtree_lock, flags); | 1879 | raw_spin_lock_irqsave(&devtree_lock, flags); |
1817 | next = &np->properties; | 1880 | next = &np->properties; |
1818 | while (*next) { | 1881 | oldprop = __of_find_property(np, newprop->name, NULL); |
1882 | if (!oldprop) { | ||
1883 | /* add the new node */ | ||
1884 | rc = __of_add_property(np, newprop); | ||
1885 | } else while (*next) { | ||
1886 | /* replace the node */ | ||
1819 | if (*next == oldprop) { | 1887 | if (*next == oldprop) { |
1820 | /* found the node */ | ||
1821 | newprop->next = oldprop->next; | 1888 | newprop->next = oldprop->next; |
1822 | *next = newprop; | 1889 | *next = newprop; |
1823 | oldprop->next = np->deadprops; | 1890 | oldprop->next = np->deadprops; |
1824 | np->deadprops = oldprop; | 1891 | np->deadprops = oldprop; |
1825 | found = 1; | ||
1826 | break; | 1892 | break; |
1827 | } | 1893 | } |
1828 | next = &(*next)->next; | 1894 | next = &(*next)->next; |
1829 | } | 1895 | } |
1830 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | 1896 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
1831 | if (!found) | 1897 | if (rc) |
1832 | return -ENODEV; | 1898 | return rc; |
1899 | |||
1900 | /* At early boot, bail out and defer setup to of_init() */ | ||
1901 | if (!of_kset) | ||
1902 | return 0; | ||
1833 | 1903 | ||
1834 | /* Update the sysfs attribute */ | 1904 | /* Update the sysfs attribute */ |
1835 | sysfs_remove_bin_file(&np->kobj, &oldprop->attr); | 1905 | if (oldprop) |
1906 | sysfs_remove_bin_file(&np->kobj, &oldprop->attr); | ||
1836 | __of_add_property_sysfs(np, newprop); | 1907 | __of_add_property_sysfs(np, newprop); |
1837 | 1908 | ||
1838 | return 0; | 1909 | return 0; |
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index a6f83ea107ae..17be90f5445f 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c | |||
@@ -324,7 +324,7 @@ static void __unflatten_device_tree(void *blob, | |||
324 | 324 | ||
325 | /* First pass, scan for size */ | 325 | /* First pass, scan for size */ |
326 | start = 0; | 326 | start = 0; |
327 | size = (unsigned long)unflatten_dt_node(blob, 0, &start, NULL, NULL, 0); | 327 | size = (unsigned long)unflatten_dt_node(blob, NULL, &start, NULL, NULL, 0); |
328 | size = ALIGN(size, 4); | 328 | size = ALIGN(size, 4); |
329 | 329 | ||
330 | pr_debug(" size is %lx, allocating...\n", size); | 330 | pr_debug(" size is %lx, allocating...\n", size); |
@@ -748,7 +748,7 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname, | |||
748 | * The longtrail doesn't have a device_type on the | 748 | * The longtrail doesn't have a device_type on the |
749 | * /memory node, so look for the node called /memory@0. | 749 | * /memory node, so look for the node called /memory@0. |
750 | */ | 750 | */ |
751 | if (depth != 1 || strcmp(uname, "memory@0") != 0) | 751 | if (!IS_ENABLED(CONFIG_PPC32) || depth != 1 || strcmp(uname, "memory@0") != 0) |
752 | return 0; | 752 | return 0; |
753 | } else if (strcmp(type, "memory") != 0) | 753 | } else if (strcmp(type, "memory") != 0) |
754 | return 0; | 754 | return 0; |
diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 5aeb89411350..3e06a699352d 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c | |||
@@ -406,6 +406,28 @@ int of_irq_get(struct device_node *dev, int index) | |||
406 | } | 406 | } |
407 | 407 | ||
408 | /** | 408 | /** |
409 | * of_irq_get_byname - Decode a node's IRQ and return it as a Linux irq number | ||
410 | * @dev: pointer to device tree node | ||
411 | * @name: irq name | ||
412 | * | ||
413 | * Returns Linux irq number on success, or -EPROBE_DEFER if the irq domain | ||
414 | * is not yet created, or error code in case of any other failure. | ||
415 | */ | ||
416 | int of_irq_get_byname(struct device_node *dev, const char *name) | ||
417 | { | ||
418 | int index; | ||
419 | |||
420 | if (unlikely(!name)) | ||
421 | return -EINVAL; | ||
422 | |||
423 | index = of_property_match_string(dev, "interrupt-names", name); | ||
424 | if (index < 0) | ||
425 | return index; | ||
426 | |||
427 | return of_irq_get(dev, index); | ||
428 | } | ||
429 | |||
430 | /** | ||
409 | * of_irq_count - Count the number of IRQs a node uses | 431 | * of_irq_count - Count the number of IRQs a node uses |
410 | * @dev: pointer to device tree node | 432 | * @dev: pointer to device tree node |
411 | */ | 433 | */ |
diff --git a/drivers/of/of_pci_irq.c b/drivers/of/of_pci_irq.c index 8736bc7676c5..1710d9dc7fc2 100644 --- a/drivers/of/of_pci_irq.c +++ b/drivers/of/of_pci_irq.c | |||
@@ -18,8 +18,6 @@ int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq | |||
18 | { | 18 | { |
19 | struct device_node *dn, *ppnode; | 19 | struct device_node *dn, *ppnode; |
20 | struct pci_dev *ppdev; | 20 | struct pci_dev *ppdev; |
21 | u32 lspec; | ||
22 | __be32 lspec_be; | ||
23 | __be32 laddr[3]; | 21 | __be32 laddr[3]; |
24 | u8 pin; | 22 | u8 pin; |
25 | int rc; | 23 | int rc; |
@@ -46,7 +44,6 @@ int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq | |||
46 | return -ENODEV; | 44 | return -ENODEV; |
47 | 45 | ||
48 | /* Now we walk up the PCI tree */ | 46 | /* Now we walk up the PCI tree */ |
49 | lspec = pin; | ||
50 | for (;;) { | 47 | for (;;) { |
51 | /* Get the pci_dev of our parent */ | 48 | /* Get the pci_dev of our parent */ |
52 | ppdev = pdev->bus->self; | 49 | ppdev = pdev->bus->self; |
@@ -80,14 +77,13 @@ int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq | |||
80 | /* We can only get here if we hit a P2P bridge with no node, | 77 | /* We can only get here if we hit a P2P bridge with no node, |
81 | * let's do standard swizzling and try again | 78 | * let's do standard swizzling and try again |
82 | */ | 79 | */ |
83 | lspec = pci_swizzle_interrupt_pin(pdev, lspec); | 80 | pin = pci_swizzle_interrupt_pin(pdev, pin); |
84 | pdev = ppdev; | 81 | pdev = ppdev; |
85 | } | 82 | } |
86 | 83 | ||
87 | out_irq->np = ppnode; | 84 | out_irq->np = ppnode; |
88 | out_irq->args_count = 1; | 85 | out_irq->args_count = 1; |
89 | out_irq->args[0] = lspec; | 86 | out_irq->args[0] = pin; |
90 | lspec_be = cpu_to_be32(lspec); | ||
91 | laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8)); | 87 | laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8)); |
92 | laddr[1] = laddr[2] = cpu_to_be32(0); | 88 | laddr[1] = laddr[2] = cpu_to_be32(0); |
93 | return of_irq_parse_raw(laddr, out_irq); | 89 | return of_irq_parse_raw(laddr, out_irq); |
diff --git a/drivers/of/platform.c b/drivers/of/platform.c index d0009b3614af..52780a72d09d 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c | |||
@@ -51,10 +51,6 @@ struct platform_device *of_find_device_by_node(struct device_node *np) | |||
51 | } | 51 | } |
52 | EXPORT_SYMBOL(of_find_device_by_node); | 52 | EXPORT_SYMBOL(of_find_device_by_node); |
53 | 53 | ||
54 | #if defined(CONFIG_PPC_DCR) | ||
55 | #include <asm/dcr.h> | ||
56 | #endif | ||
57 | |||
58 | #ifdef CONFIG_OF_ADDRESS | 54 | #ifdef CONFIG_OF_ADDRESS |
59 | /* | 55 | /* |
60 | * The following routines scan a subtree and registers a device for | 56 | * The following routines scan a subtree and registers a device for |
@@ -68,57 +64,35 @@ EXPORT_SYMBOL(of_find_device_by_node); | |||
68 | * of_device_make_bus_id - Use the device node data to assign a unique name | 64 | * of_device_make_bus_id - Use the device node data to assign a unique name |
69 | * @dev: pointer to device structure that is linked to a device tree node | 65 | * @dev: pointer to device structure that is linked to a device tree node |
70 | * | 66 | * |
71 | * This routine will first try using either the dcr-reg or the reg property | 67 | * This routine will first try using the translated bus address to |
72 | * value to derive a unique name. As a last resort it will use the node | 68 | * derive a unique name. If it cannot, then it will prepend names from |
73 | * name followed by a unique number. | 69 | * parent nodes until a unique name can be derived. |
74 | */ | 70 | */ |
75 | void of_device_make_bus_id(struct device *dev) | 71 | void of_device_make_bus_id(struct device *dev) |
76 | { | 72 | { |
77 | static atomic_t bus_no_reg_magic; | ||
78 | struct device_node *node = dev->of_node; | 73 | struct device_node *node = dev->of_node; |
79 | const __be32 *reg; | 74 | const __be32 *reg; |
80 | u64 addr; | 75 | u64 addr; |
81 | int magic; | ||
82 | 76 | ||
83 | #ifdef CONFIG_PPC_DCR | 77 | /* Construct the name, using parent nodes if necessary to ensure uniqueness */ |
84 | /* | 78 | while (node->parent) { |
85 | * If it's a DCR based device, use 'd' for native DCRs | 79 | /* |
86 | * and 'D' for MMIO DCRs. | 80 | * If the address can be translated, then that is as much |
87 | */ | 81 | * uniqueness as we need. Make it the first component and return |
88 | reg = of_get_property(node, "dcr-reg", NULL); | 82 | */ |
89 | if (reg) { | 83 | reg = of_get_property(node, "reg", NULL); |
90 | #ifdef CONFIG_PPC_DCR_NATIVE | 84 | if (reg && (addr = of_translate_address(node, reg)) != OF_BAD_ADDR) { |
91 | dev_set_name(dev, "d%x.%s", *reg, node->name); | 85 | dev_set_name(dev, dev_name(dev) ? "%llx.%s:%s" : "%llx.%s", |
92 | #else /* CONFIG_PPC_DCR_NATIVE */ | 86 | (unsigned long long)addr, node->name, |
93 | u64 addr = of_translate_dcr_address(node, *reg, NULL); | 87 | dev_name(dev)); |
94 | if (addr != OF_BAD_ADDR) { | ||
95 | dev_set_name(dev, "D%llx.%s", | ||
96 | (unsigned long long)addr, node->name); | ||
97 | return; | 88 | return; |
98 | } | 89 | } |
99 | #endif /* !CONFIG_PPC_DCR_NATIVE */ | ||
100 | } | ||
101 | #endif /* CONFIG_PPC_DCR */ | ||
102 | 90 | ||
103 | /* | 91 | /* format arguments only used if dev_name() resolves to NULL */ |
104 | * For MMIO, get the physical address | 92 | dev_set_name(dev, dev_name(dev) ? "%s:%s" : "%s", |
105 | */ | 93 | strrchr(node->full_name, '/') + 1, dev_name(dev)); |
106 | reg = of_get_property(node, "reg", NULL); | 94 | node = node->parent; |
107 | if (reg) { | ||
108 | addr = of_translate_address(node, reg); | ||
109 | if (addr != OF_BAD_ADDR) { | ||
110 | dev_set_name(dev, "%llx.%s", | ||
111 | (unsigned long long)addr, node->name); | ||
112 | return; | ||
113 | } | ||
114 | } | 95 | } |
115 | |||
116 | /* | ||
117 | * No BusID, use the node name and add a globally incremented | ||
118 | * counter (and pray...) | ||
119 | */ | ||
120 | magic = atomic_add_return(1, &bus_no_reg_magic); | ||
121 | dev_set_name(dev, "%s.%d", node->name, magic - 1); | ||
122 | } | 96 | } |
123 | 97 | ||
124 | /** | 98 | /** |
diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c index 2588faaaa305..077314eebb95 100644 --- a/drivers/of/selftest.c +++ b/drivers/of/selftest.c | |||
@@ -31,6 +31,51 @@ static struct selftest_results { | |||
31 | } \ | 31 | } \ |
32 | } | 32 | } |
33 | 33 | ||
34 | static void __init of_selftest_find_node_by_name(void) | ||
35 | { | ||
36 | struct device_node *np; | ||
37 | |||
38 | np = of_find_node_by_path("/testcase-data"); | ||
39 | selftest(np && !strcmp("/testcase-data", np->full_name), | ||
40 | "find /testcase-data failed\n"); | ||
41 | of_node_put(np); | ||
42 | |||
43 | /* Test if trailing '/' works */ | ||
44 | np = of_find_node_by_path("/testcase-data/"); | ||
45 | selftest(!np, "trailing '/' on /testcase-data/ should fail\n"); | ||
46 | |||
47 | np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a"); | ||
48 | selftest(np && !strcmp("/testcase-data/phandle-tests/consumer-a", np->full_name), | ||
49 | "find /testcase-data/phandle-tests/consumer-a failed\n"); | ||
50 | of_node_put(np); | ||
51 | |||
52 | np = of_find_node_by_path("testcase-alias"); | ||
53 | selftest(np && !strcmp("/testcase-data", np->full_name), | ||
54 | "find testcase-alias failed\n"); | ||
55 | of_node_put(np); | ||
56 | |||
57 | /* Test if trailing '/' works on aliases */ | ||
58 | np = of_find_node_by_path("testcase-alias/"); | ||
59 | selftest(!np, "trailing '/' on testcase-alias/ should fail\n"); | ||
60 | |||
61 | np = of_find_node_by_path("testcase-alias/phandle-tests/consumer-a"); | ||
62 | selftest(np && !strcmp("/testcase-data/phandle-tests/consumer-a", np->full_name), | ||
63 | "find testcase-alias/phandle-tests/consumer-a failed\n"); | ||
64 | of_node_put(np); | ||
65 | |||
66 | np = of_find_node_by_path("/testcase-data/missing-path"); | ||
67 | selftest(!np, "non-existent path returned node %s\n", np->full_name); | ||
68 | of_node_put(np); | ||
69 | |||
70 | np = of_find_node_by_path("missing-alias"); | ||
71 | selftest(!np, "non-existent alias returned node %s\n", np->full_name); | ||
72 | of_node_put(np); | ||
73 | |||
74 | np = of_find_node_by_path("testcase-alias/missing-path"); | ||
75 | selftest(!np, "non-existent alias with relative path returned node %s\n", np->full_name); | ||
76 | of_node_put(np); | ||
77 | } | ||
78 | |||
34 | static void __init of_selftest_dynamic(void) | 79 | static void __init of_selftest_dynamic(void) |
35 | { | 80 | { |
36 | struct device_node *np; | 81 | struct device_node *np; |
@@ -484,6 +529,7 @@ static int __init of_selftest(void) | |||
484 | of_node_put(np); | 529 | of_node_put(np); |
485 | 530 | ||
486 | pr_info("start of selftest - you will see error messages\n"); | 531 | pr_info("start of selftest - you will see error messages\n"); |
532 | of_selftest_find_node_by_name(); | ||
487 | of_selftest_dynamic(); | 533 | of_selftest_dynamic(); |
488 | of_selftest_parse_phandle_with_args(); | 534 | of_selftest_parse_phandle_with_args(); |
489 | of_selftest_property_match_string(); | 535 | of_selftest_property_match_string(); |
diff --git a/drivers/of/testcase-data/tests-phandle.dtsi b/drivers/of/testcase-data/tests-phandle.dtsi index 788a4c24b8f5..ce0fe083d406 100644 --- a/drivers/of/testcase-data/tests-phandle.dtsi +++ b/drivers/of/testcase-data/tests-phandle.dtsi | |||
@@ -1,6 +1,10 @@ | |||
1 | 1 | ||
2 | / { | 2 | / { |
3 | testcase-data { | 3 | aliases { |
4 | testcase-alias = &testcase; | ||
5 | }; | ||
6 | |||
7 | testcase: testcase-data { | ||
4 | security-password = "password"; | 8 | security-password = "password"; |
5 | duplicate-name = "duplicate"; | 9 | duplicate-name = "duplicate"; |
6 | duplicate-name { }; | 10 | duplicate-name { }; |
diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h index 6404253d810d..bfec136a6d1e 100644 --- a/include/linux/of_irq.h +++ b/include/linux/of_irq.h | |||
@@ -45,6 +45,7 @@ extern void of_irq_init(const struct of_device_id *matches); | |||
45 | #ifdef CONFIG_OF_IRQ | 45 | #ifdef CONFIG_OF_IRQ |
46 | extern int of_irq_count(struct device_node *dev); | 46 | extern int of_irq_count(struct device_node *dev); |
47 | extern int of_irq_get(struct device_node *dev, int index); | 47 | extern int of_irq_get(struct device_node *dev, int index); |
48 | extern int of_irq_get_byname(struct device_node *dev, const char *name); | ||
48 | #else | 49 | #else |
49 | static inline int of_irq_count(struct device_node *dev) | 50 | static inline int of_irq_count(struct device_node *dev) |
50 | { | 51 | { |
@@ -54,6 +55,10 @@ static inline int of_irq_get(struct device_node *dev, int index) | |||
54 | { | 55 | { |
55 | return 0; | 56 | return 0; |
56 | } | 57 | } |
58 | static inline int of_irq_get_byname(struct device_node *dev, const char *name) | ||
59 | { | ||
60 | return 0; | ||
61 | } | ||
57 | #endif | 62 | #endif |
58 | 63 | ||
59 | #if defined(CONFIG_OF) | 64 | #if defined(CONFIG_OF) |
diff --git a/include/linux/string.h b/include/linux/string.h index ac889c5ea11b..d36977e029af 100644 --- a/include/linux/string.h +++ b/include/linux/string.h | |||
@@ -52,6 +52,9 @@ extern int strncasecmp(const char *s1, const char *s2, size_t n); | |||
52 | #ifndef __HAVE_ARCH_STRCHR | 52 | #ifndef __HAVE_ARCH_STRCHR |
53 | extern char * strchr(const char *,int); | 53 | extern char * strchr(const char *,int); |
54 | #endif | 54 | #endif |
55 | #ifndef __HAVE_ARCH_STRCHRNUL | ||
56 | extern char * strchrnul(const char *,int); | ||
57 | #endif | ||
55 | #ifndef __HAVE_ARCH_STRNCHR | 58 | #ifndef __HAVE_ARCH_STRNCHR |
56 | extern char * strnchr(const char *, size_t, int); | 59 | extern char * strnchr(const char *, size_t, int); |
57 | #endif | 60 | #endif |
diff --git a/lib/string.c b/lib/string.c index 9b1f9062a202..e0c20eb362f0 100644 --- a/lib/string.c +++ b/lib/string.c | |||
@@ -301,6 +301,24 @@ char *strchr(const char *s, int c) | |||
301 | EXPORT_SYMBOL(strchr); | 301 | EXPORT_SYMBOL(strchr); |
302 | #endif | 302 | #endif |
303 | 303 | ||
304 | #ifndef __HAVE_ARCH_STRCHRNUL | ||
305 | /** | ||
306 | * strchrnul - Find and return a character in a string, or end of string | ||
307 | * @s: The string to be searched | ||
308 | * @c: The character to search for | ||
309 | * | ||
310 | * Returns pointer to first occurrence of 'c' in s. If c is not found, then | ||
311 | * return a pointer to the null byte at the end of s. | ||
312 | */ | ||
313 | char *strchrnul(const char *s, int c) | ||
314 | { | ||
315 | while (*s && *s != (char)c) | ||
316 | s++; | ||
317 | return (char *)s; | ||
318 | } | ||
319 | EXPORT_SYMBOL(strchrnul); | ||
320 | #endif | ||
321 | |||
304 | #ifndef __HAVE_ARCH_STRRCHR | 322 | #ifndef __HAVE_ARCH_STRRCHR |
305 | /** | 323 | /** |
306 | * strrchr - Find the last occurrence of a character in a string | 324 | * strrchr - Find the last occurrence of a character in a string |