diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2010-01-29 07:04:33 -0500 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2010-02-09 10:32:42 -0500 |
commit | fcdeb7fedf89f4bbc2e11959794968080cd8426e (patch) | |
tree | b549ce78d381f6185d10395afdea9ce8f741fd40 | |
parent | 580537140568caddbc8a727d4c2f238d38707f68 (diff) |
of: merge of_attach_node() & of_detach_node()
Merge common code between PowerPC and Microblaze
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Tested-by: Wolfram Sang <w.sang@pengutronix.de>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r-- | arch/microblaze/include/asm/prom.h | 4 | ||||
-rw-r--r-- | arch/microblaze/kernel/prom.c | 59 | ||||
-rw-r--r-- | arch/powerpc/include/asm/prom.h | 4 | ||||
-rw-r--r-- | arch/powerpc/kernel/prom.c | 59 | ||||
-rw-r--r-- | drivers/of/Kconfig | 4 | ||||
-rw-r--r-- | drivers/of/base.c | 71 | ||||
-rw-r--r-- | include/linux/of.h | 6 |
7 files changed, 81 insertions, 126 deletions
diff --git a/arch/microblaze/include/asm/prom.h b/arch/microblaze/include/asm/prom.h index 07d1063f9aae..6c6b386cf3c6 100644 --- a/arch/microblaze/include/asm/prom.h +++ b/arch/microblaze/include/asm/prom.h | |||
@@ -39,10 +39,6 @@ extern struct device_node *of_chosen; | |||
39 | 39 | ||
40 | extern rwlock_t devtree_lock; /* temporary while merging */ | 40 | extern rwlock_t devtree_lock; /* temporary while merging */ |
41 | 41 | ||
42 | /* For updating the device tree at runtime */ | ||
43 | extern void of_attach_node(struct device_node *); | ||
44 | extern void of_detach_node(struct device_node *); | ||
45 | |||
46 | /* Other Prototypes */ | 42 | /* Other Prototypes */ |
47 | extern int early_uartlite_console(void); | 43 | extern int early_uartlite_console(void); |
48 | 44 | ||
diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index cd158ef5b583..8171282a0b0d 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c | |||
@@ -197,65 +197,6 @@ struct device_node *of_find_node_by_phandle(phandle handle) | |||
197 | } | 197 | } |
198 | EXPORT_SYMBOL(of_find_node_by_phandle); | 198 | EXPORT_SYMBOL(of_find_node_by_phandle); |
199 | 199 | ||
200 | /* | ||
201 | * Plug a device node into the tree and global list. | ||
202 | */ | ||
203 | void of_attach_node(struct device_node *np) | ||
204 | { | ||
205 | unsigned long flags; | ||
206 | |||
207 | write_lock_irqsave(&devtree_lock, flags); | ||
208 | np->sibling = np->parent->child; | ||
209 | np->allnext = allnodes; | ||
210 | np->parent->child = np; | ||
211 | allnodes = np; | ||
212 | write_unlock_irqrestore(&devtree_lock, flags); | ||
213 | } | ||
214 | |||
215 | /* | ||
216 | * "Unplug" a node from the device tree. The caller must hold | ||
217 | * a reference to the node. The memory associated with the node | ||
218 | * is not freed until its refcount goes to zero. | ||
219 | */ | ||
220 | void of_detach_node(struct device_node *np) | ||
221 | { | ||
222 | struct device_node *parent; | ||
223 | unsigned long flags; | ||
224 | |||
225 | write_lock_irqsave(&devtree_lock, flags); | ||
226 | |||
227 | parent = np->parent; | ||
228 | if (!parent) | ||
229 | goto out_unlock; | ||
230 | |||
231 | if (allnodes == np) | ||
232 | allnodes = np->allnext; | ||
233 | else { | ||
234 | struct device_node *prev; | ||
235 | for (prev = allnodes; | ||
236 | prev->allnext != np; | ||
237 | prev = prev->allnext) | ||
238 | ; | ||
239 | prev->allnext = np->allnext; | ||
240 | } | ||
241 | |||
242 | if (parent->child == np) | ||
243 | parent->child = np->sibling; | ||
244 | else { | ||
245 | struct device_node *prevsib; | ||
246 | for (prevsib = np->parent->child; | ||
247 | prevsib->sibling != np; | ||
248 | prevsib = prevsib->sibling) | ||
249 | ; | ||
250 | prevsib->sibling = np->sibling; | ||
251 | } | ||
252 | |||
253 | of_node_set_flag(np, OF_DETACHED); | ||
254 | |||
255 | out_unlock: | ||
256 | write_unlock_irqrestore(&devtree_lock, flags); | ||
257 | } | ||
258 | |||
259 | #if defined(CONFIG_DEBUG_FS) && defined(DEBUG) | 200 | #if defined(CONFIG_DEBUG_FS) && defined(DEBUG) |
260 | static struct debugfs_blob_wrapper flat_dt_blob; | 201 | static struct debugfs_blob_wrapper flat_dt_blob; |
261 | 202 | ||
diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h index 2ab9cbd98826..f384db815ea8 100644 --- a/arch/powerpc/include/asm/prom.h +++ b/arch/powerpc/include/asm/prom.h | |||
@@ -34,10 +34,6 @@ extern struct device_node *of_chosen; | |||
34 | 34 | ||
35 | #define HAVE_ARCH_DEVTREE_FIXUPS | 35 | #define HAVE_ARCH_DEVTREE_FIXUPS |
36 | 36 | ||
37 | /* For updating the device tree at runtime */ | ||
38 | extern void of_attach_node(struct device_node *); | ||
39 | extern void of_detach_node(struct device_node *); | ||
40 | |||
41 | #ifdef CONFIG_PPC32 | 37 | #ifdef CONFIG_PPC32 |
42 | /* | 38 | /* |
43 | * PCI <-> OF matching functions | 39 | * PCI <-> OF matching functions |
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 1ed2ec2ea05b..f954c718d7eb 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -817,65 +817,6 @@ struct device_node *of_find_next_cache_node(struct device_node *np) | |||
817 | return NULL; | 817 | return NULL; |
818 | } | 818 | } |
819 | 819 | ||
820 | /* | ||
821 | * Plug a device node into the tree and global list. | ||
822 | */ | ||
823 | void of_attach_node(struct device_node *np) | ||
824 | { | ||
825 | unsigned long flags; | ||
826 | |||
827 | write_lock_irqsave(&devtree_lock, flags); | ||
828 | np->sibling = np->parent->child; | ||
829 | np->allnext = allnodes; | ||
830 | np->parent->child = np; | ||
831 | allnodes = np; | ||
832 | write_unlock_irqrestore(&devtree_lock, flags); | ||
833 | } | ||
834 | |||
835 | /* | ||
836 | * "Unplug" a node from the device tree. The caller must hold | ||
837 | * a reference to the node. The memory associated with the node | ||
838 | * is not freed until its refcount goes to zero. | ||
839 | */ | ||
840 | void of_detach_node(struct device_node *np) | ||
841 | { | ||
842 | struct device_node *parent; | ||
843 | unsigned long flags; | ||
844 | |||
845 | write_lock_irqsave(&devtree_lock, flags); | ||
846 | |||
847 | parent = np->parent; | ||
848 | if (!parent) | ||
849 | goto out_unlock; | ||
850 | |||
851 | if (allnodes == np) | ||
852 | allnodes = np->allnext; | ||
853 | else { | ||
854 | struct device_node *prev; | ||
855 | for (prev = allnodes; | ||
856 | prev->allnext != np; | ||
857 | prev = prev->allnext) | ||
858 | ; | ||
859 | prev->allnext = np->allnext; | ||
860 | } | ||
861 | |||
862 | if (parent->child == np) | ||
863 | parent->child = np->sibling; | ||
864 | else { | ||
865 | struct device_node *prevsib; | ||
866 | for (prevsib = np->parent->child; | ||
867 | prevsib->sibling != np; | ||
868 | prevsib = prevsib->sibling) | ||
869 | ; | ||
870 | prevsib->sibling = np->sibling; | ||
871 | } | ||
872 | |||
873 | of_node_set_flag(np, OF_DETACHED); | ||
874 | |||
875 | out_unlock: | ||
876 | write_unlock_irqrestore(&devtree_lock, flags); | ||
877 | } | ||
878 | |||
879 | #ifdef CONFIG_PPC_PSERIES | 820 | #ifdef CONFIG_PPC_PSERIES |
880 | /* | 821 | /* |
881 | * Fix up the uninitialized fields in a new device node: | 822 | * Fix up the uninitialized fields in a new device node: |
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 462825e03123..7cecc8fea9bd 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig | |||
@@ -2,6 +2,10 @@ config OF_FLATTREE | |||
2 | bool | 2 | bool |
3 | depends on OF | 3 | depends on OF |
4 | 4 | ||
5 | config OF_DYNAMIC | ||
6 | def_bool y | ||
7 | depends on OF && PPC_OF | ||
8 | |||
5 | config OF_DEVICE | 9 | config OF_DEVICE |
6 | def_bool y | 10 | def_bool y |
7 | depends on OF && (SPARC || PPC_OF || MICROBLAZE) | 11 | depends on OF && (SPARC || PPC_OF || MICROBLAZE) |
diff --git a/drivers/of/base.c b/drivers/of/base.c index cf89ee6253f3..2ce58be314af 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -870,3 +870,74 @@ int prom_update_property(struct device_node *np, | |||
870 | 870 | ||
871 | return 0; | 871 | return 0; |
872 | } | 872 | } |
873 | |||
874 | #if defined(CONFIG_OF_DYNAMIC) | ||
875 | /* | ||
876 | * Support for dynamic device trees. | ||
877 | * | ||
878 | * On some platforms, the device tree can be manipulated at runtime. | ||
879 | * The routines in this section support adding, removing and changing | ||
880 | * device tree nodes. | ||
881 | */ | ||
882 | |||
883 | /** | ||
884 | * of_attach_node - Plug a device node into the tree and global list. | ||
885 | */ | ||
886 | void of_attach_node(struct device_node *np) | ||
887 | { | ||
888 | unsigned long flags; | ||
889 | |||
890 | write_lock_irqsave(&devtree_lock, flags); | ||
891 | np->sibling = np->parent->child; | ||
892 | np->allnext = allnodes; | ||
893 | np->parent->child = np; | ||
894 | allnodes = np; | ||
895 | write_unlock_irqrestore(&devtree_lock, flags); | ||
896 | } | ||
897 | |||
898 | /** | ||
899 | * of_detach_node - "Unplug" a node from the device tree. | ||
900 | * | ||
901 | * The caller must hold a reference to the node. The memory associated with | ||
902 | * the node is not freed until its refcount goes to zero. | ||
903 | */ | ||
904 | void of_detach_node(struct device_node *np) | ||
905 | { | ||
906 | struct device_node *parent; | ||
907 | unsigned long flags; | ||
908 | |||
909 | write_lock_irqsave(&devtree_lock, flags); | ||
910 | |||
911 | parent = np->parent; | ||
912 | if (!parent) | ||
913 | goto out_unlock; | ||
914 | |||
915 | if (allnodes == np) | ||
916 | allnodes = np->allnext; | ||
917 | else { | ||
918 | struct device_node *prev; | ||
919 | for (prev = allnodes; | ||
920 | prev->allnext != np; | ||
921 | prev = prev->allnext) | ||
922 | ; | ||
923 | prev->allnext = np->allnext; | ||
924 | } | ||
925 | |||
926 | if (parent->child == np) | ||
927 | parent->child = np->sibling; | ||
928 | else { | ||
929 | struct device_node *prevsib; | ||
930 | for (prevsib = np->parent->child; | ||
931 | prevsib->sibling != np; | ||
932 | prevsib = prevsib->sibling) | ||
933 | ; | ||
934 | prevsib->sibling = np->sibling; | ||
935 | } | ||
936 | |||
937 | of_node_set_flag(np, OF_DETACHED); | ||
938 | |||
939 | out_unlock: | ||
940 | write_unlock_irqrestore(&devtree_lock, flags); | ||
941 | } | ||
942 | #endif /* defined(CONFIG_OF_DYNAMIC) */ | ||
943 | |||
diff --git a/include/linux/of.h b/include/linux/of.h index dbabf86e0b7a..3cc0d7ae290e 100644 --- a/include/linux/of.h +++ b/include/linux/of.h | |||
@@ -184,4 +184,10 @@ extern int of_parse_phandles_with_args(struct device_node *np, | |||
184 | const char *list_name, const char *cells_name, int index, | 184 | const char *list_name, const char *cells_name, int index, |
185 | struct device_node **out_node, const void **out_args); | 185 | struct device_node **out_node, const void **out_args); |
186 | 186 | ||
187 | #if defined(CONFIG_OF_DYNAMIC) | ||
188 | /* For updating the device tree at runtime */ | ||
189 | extern void of_attach_node(struct device_node *); | ||
190 | extern void of_detach_node(struct device_node *); | ||
191 | #endif | ||
192 | |||
187 | #endif /* _LINUX_OF_H */ | 193 | #endif /* _LINUX_OF_H */ |