diff options
| author | Grant Likely <grant.likely@linaro.org> | 2014-07-16 01:25:43 -0400 |
|---|---|---|
| committer | Grant Likely <grant.likely@linaro.org> | 2014-07-23 19:05:46 -0400 |
| commit | a25095d451ece23b1fef34474f3230100db7aa05 (patch) | |
| tree | 1144ef8101664c7242e27d62b179ec7d9438cefb | |
| parent | 6162dbe49a451f96431a23b4821f05e3bd925bc1 (diff) | |
of: Move dynamic node fixups out of powerpc and into common code
PowerPC does an odd thing with dynamic nodes. It uses a notifier to
catch new node additions and set some of the values like name and type.
This makes no sense since that same code can be put directly into
of_attach_node(). Besides, all dynamic node users need this, not just
powerpc. Fix this problem by moving the logic out of arch/powerpc and
into drivers/of/dynamic.c.
It is also important to remove this notifier because we want to move the
firing of notifiers from before the tree is modified to after so that
the receiver gets a consistent view of the tree, but that is
incompatible with notifiers that modify the node.
Signed-off-by: Grant Likely <grant.likely@linaro.org>
Cc: Nathan Fontenot <nfont@austin.ibm.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
| -rw-r--r-- | arch/powerpc/kernel/prom.c | 70 | ||||
| -rw-r--r-- | drivers/of/base.c | 4 | ||||
| -rw-r--r-- | drivers/of/dynamic.c | 13 | ||||
| -rw-r--r-- | drivers/of/of_private.h | 2 |
4 files changed, 17 insertions, 72 deletions
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index b694b0730971..9e8d8a880d6f 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
| @@ -821,76 +821,6 @@ int cpu_to_chip_id(int cpu) | |||
| 821 | } | 821 | } |
| 822 | EXPORT_SYMBOL(cpu_to_chip_id); | 822 | EXPORT_SYMBOL(cpu_to_chip_id); |
| 823 | 823 | ||
| 824 | #ifdef CONFIG_PPC_PSERIES | ||
| 825 | /* | ||
| 826 | * Fix up the uninitialized fields in a new device node: | ||
| 827 | * name, type and pci-specific fields | ||
| 828 | */ | ||
| 829 | |||
| 830 | static int of_finish_dynamic_node(struct device_node *node) | ||
| 831 | { | ||
| 832 | struct device_node *parent = of_get_parent(node); | ||
| 833 | int err = 0; | ||
| 834 | const phandle *ibm_phandle; | ||
| 835 | |||
| 836 | node->name = of_get_property(node, "name", NULL); | ||
| 837 | node->type = of_get_property(node, "device_type", NULL); | ||
| 838 | |||
| 839 | if (!node->name) | ||
| 840 | node->name = "<NULL>"; | ||
| 841 | if (!node->type) | ||
| 842 | node->type = "<NULL>"; | ||
| 843 | |||
| 844 | if (!parent) { | ||
| 845 | err = -ENODEV; | ||
| 846 | goto out; | ||
| 847 | } | ||
| 848 | |||
| 849 | /* We don't support that function on PowerMac, at least | ||
| 850 | * not yet | ||
| 851 | */ | ||
| 852 | if (machine_is(powermac)) | ||
| 853 | return -ENODEV; | ||
| 854 | |||
| 855 | /* fix up new node's phandle field */ | ||
| 856 | if ((ibm_phandle = of_get_property(node, "ibm,phandle", NULL))) | ||
| 857 | node->phandle = *ibm_phandle; | ||
| 858 | |||
| 859 | out: | ||
| 860 | of_node_put(parent); | ||
| 861 | return err; | ||
| 862 | } | ||
| 863 | |||
| 864 | static int prom_reconfig_notifier(struct notifier_block *nb, | ||
| 865 | unsigned long action, void *node) | ||
| 866 | { | ||
| 867 | int err; | ||
| 868 | |||
| 869 | switch (action) { | ||
| 870 | case OF_RECONFIG_ATTACH_NODE: | ||
| 871 | err = of_finish_dynamic_node(node); | ||
| 872 | if (err < 0) | ||
| 873 | printk(KERN_ERR "finish_node returned %d\n", err); | ||
| 874 | break; | ||
| 875 | default: | ||
| 876 | err = 0; | ||
| 877 | break; | ||
| 878 | } | ||
| 879 | return notifier_from_errno(err); | ||
| 880 | } | ||
| 881 | |||
| 882 | static struct notifier_block prom_reconfig_nb = { | ||
| 883 | .notifier_call = prom_reconfig_notifier, | ||
| 884 | .priority = 10, /* This one needs to run first */ | ||
| 885 | }; | ||
| 886 | |||
| 887 | static int __init prom_reconfig_setup(void) | ||
| 888 | { | ||
| 889 | return of_reconfig_notifier_register(&prom_reconfig_nb); | ||
| 890 | } | ||
| 891 | __initcall(prom_reconfig_setup); | ||
| 892 | #endif | ||
| 893 | |||
| 894 | bool arch_match_cpu_phys_id(int cpu, u64 phys_id) | 824 | bool arch_match_cpu_phys_id(int cpu, u64 phys_id) |
| 895 | { | 825 | { |
| 896 | return (int)phys_id == get_hard_smp_processor_id(cpu); | 826 | return (int)phys_id == get_hard_smp_processor_id(cpu); |
diff --git a/drivers/of/base.c b/drivers/of/base.c index ad4929cbd876..ededf8e33145 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
| @@ -266,8 +266,8 @@ EXPORT_SYMBOL(of_find_all_nodes); | |||
| 266 | * Find a property with a given name for a given node | 266 | * Find a property with a given name for a given node |
| 267 | * and return the value. | 267 | * and return the value. |
| 268 | */ | 268 | */ |
| 269 | static const void *__of_get_property(const struct device_node *np, | 269 | const void *__of_get_property(const struct device_node *np, |
| 270 | const char *name, int *lenp) | 270 | const char *name, int *lenp) |
| 271 | { | 271 | { |
| 272 | struct property *pp = __of_find_property(np, name, lenp); | 272 | struct property *pp = __of_find_property(np, name, lenp); |
| 273 | 273 | ||
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c index b96d83100987..7c020b9a3317 100644 --- a/drivers/of/dynamic.c +++ b/drivers/of/dynamic.c | |||
| @@ -98,6 +98,19 @@ int of_property_notify(int action, struct device_node *np, | |||
| 98 | 98 | ||
| 99 | void __of_attach_node(struct device_node *np) | 99 | void __of_attach_node(struct device_node *np) |
| 100 | { | 100 | { |
| 101 | const __be32 *phandle; | ||
| 102 | int sz; | ||
| 103 | |||
| 104 | np->name = __of_get_property(np, "name", NULL) ? : "<NULL>"; | ||
| 105 | np->type = __of_get_property(np, "device_type", NULL) ? : "<NULL>"; | ||
| 106 | |||
| 107 | phandle = __of_get_property(np, "phandle", &sz); | ||
| 108 | if (!phandle) | ||
| 109 | phandle = __of_get_property(np, "linux,phandle", &sz); | ||
| 110 | if (IS_ENABLED(PPC_PSERIES) && !phandle) | ||
| 111 | phandle = __of_get_property(np, "ibm,phandle", &sz); | ||
| 112 | np->phandle = (phandle && (sz >= 4)) ? be32_to_cpup(phandle) : 0; | ||
| 113 | |||
| 101 | np->child = NULL; | 114 | np->child = NULL; |
| 102 | np->sibling = np->parent->child; | 115 | np->sibling = np->parent->child; |
| 103 | np->allnext = np->parent->allnext; | 116 | np->allnext = np->parent->allnext; |
diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h index 0d99ba8caeed..8129c0e58d70 100644 --- a/drivers/of/of_private.h +++ b/drivers/of/of_private.h | |||
| @@ -63,6 +63,8 @@ static inline int of_property_notify(int action, struct device_node *np, | |||
| 63 | struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags); | 63 | struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags); |
| 64 | struct device_node *__of_node_alloc(const char *full_name, gfp_t allocflags); | 64 | struct device_node *__of_node_alloc(const char *full_name, gfp_t allocflags); |
| 65 | 65 | ||
| 66 | extern const void *__of_get_property(const struct device_node *np, | ||
| 67 | const char *name, int *lenp); | ||
| 66 | extern int __of_add_property(struct device_node *np, struct property *prop); | 68 | extern int __of_add_property(struct device_node *np, struct property *prop); |
| 67 | extern int __of_add_property_sysfs(struct device_node *np, | 69 | extern int __of_add_property_sysfs(struct device_node *np, |
| 68 | struct property *prop); | 70 | struct property *prop); |
