diff options
| -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 */ |
