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 |
