diff options
36 files changed, 1382 insertions, 581 deletions
diff --git a/Documentation/devicetree/changesets.txt b/Documentation/devicetree/changesets.txt new file mode 100644 index 000000000000..935ba5acc34e --- /dev/null +++ b/Documentation/devicetree/changesets.txt | |||
@@ -0,0 +1,40 @@ | |||
1 | A DT changeset is a method which allows one to apply changes | ||
2 | in the live tree in such a way that either the full set of changes | ||
3 | will be applied, or none of them will be. If an error occurs partway | ||
4 | through applying the changeset, then the tree will be rolled back to the | ||
5 | previous state. A changeset can also be removed after it has been | ||
6 | applied. | ||
7 | |||
8 | When a changeset is applied, all of the changes get applied to the tree | ||
9 | at once before emitting OF_RECONFIG notifiers. This is so that the | ||
10 | receiver sees a complete and consistent state of the tree when it | ||
11 | receives the notifier. | ||
12 | |||
13 | The sequence of a changeset is as follows. | ||
14 | |||
15 | 1. of_changeset_init() - initializes a changeset | ||
16 | |||
17 | 2. A number of DT tree change calls, of_changeset_attach_node(), | ||
18 | of_changeset_detach_node(), of_changeset_add_property(), | ||
19 | of_changeset_remove_property, of_changeset_update_property() to prepare | ||
20 | a set of changes. No changes to the active tree are made at this point. | ||
21 | All the change operations are recorded in the of_changeset 'entries' | ||
22 | list. | ||
23 | |||
24 | 3. mutex_lock(of_mutex) - starts a changeset; The global of_mutex | ||
25 | ensures there can only be one editor at a time. | ||
26 | |||
27 | 4. of_changeset_apply() - Apply the changes to the tree. Either the | ||
28 | entire changeset will get applied, or if there is an error the tree will | ||
29 | be restored to the previous state | ||
30 | |||
31 | 5. mutex_unlock(of_mutex) - All operations complete, release the mutex | ||
32 | |||
33 | If a successfully applied changeset needs to be removed, it can be done | ||
34 | with the following sequence. | ||
35 | |||
36 | 1. mutex_lock(of_mutex) | ||
37 | |||
38 | 2. of_changeset_revert() | ||
39 | |||
40 | 3. mutex_unlock(of_mutex) | ||
diff --git a/Documentation/devicetree/todo.txt b/Documentation/devicetree/todo.txt new file mode 100644 index 000000000000..c3cf0659bd19 --- /dev/null +++ b/Documentation/devicetree/todo.txt | |||
@@ -0,0 +1,11 @@ | |||
1 | Todo list for devicetree: | ||
2 | |||
3 | === General structure === | ||
4 | - Switch from custom lists to (h)list_head for nodes and properties structure | ||
5 | - Remove of_allnodes list and iterate using list of child nodes alone | ||
6 | |||
7 | === CONFIG_OF_DYNAMIC === | ||
8 | - Switch to RCU for tree updates and get rid of global spinlock | ||
9 | - Document node lifecycle for CONFIG_OF_DYNAMIC | ||
10 | - Always set ->full_name at of_attach_node() time | ||
11 | - pseries: Get rid of open-coded tree modification from arch/powerpc/platforms/pseries/dlpar.c | ||
diff --git a/arch/arm/boot/dts/versatile-ab.dts b/arch/arm/boot/dts/versatile-ab.dts index 36c771a2d765..27d0d9c8adf3 100644 --- a/arch/arm/boot/dts/versatile-ab.dts +++ b/arch/arm/boot/dts/versatile-ab.dts | |||
@@ -15,6 +15,10 @@ | |||
15 | i2c0 = &i2c0; | 15 | i2c0 = &i2c0; |
16 | }; | 16 | }; |
17 | 17 | ||
18 | chosen { | ||
19 | stdout-path = &uart0; | ||
20 | }; | ||
21 | |||
18 | memory { | 22 | memory { |
19 | reg = <0x0 0x08000000>; | 23 | reg = <0x0 0x08000000>; |
20 | }; | 24 | }; |
diff --git a/arch/arm/boot/dts/versatile-pb.dts b/arch/arm/boot/dts/versatile-pb.dts index d025048119d3..e36c1e82fea7 100644 --- a/arch/arm/boot/dts/versatile-pb.dts +++ b/arch/arm/boot/dts/versatile-pb.dts | |||
@@ -56,5 +56,3 @@ | |||
56 | }; | 56 | }; |
57 | }; | 57 | }; |
58 | }; | 58 | }; |
59 | |||
60 | #include <testcases.dtsi> | ||
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 1a3b1055f5eb..4e139f8a69ef 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -818,76 +818,6 @@ int cpu_to_chip_id(int cpu) | |||
818 | } | 818 | } |
819 | EXPORT_SYMBOL(cpu_to_chip_id); | 819 | EXPORT_SYMBOL(cpu_to_chip_id); |
820 | 820 | ||
821 | #ifdef CONFIG_PPC_PSERIES | ||
822 | /* | ||
823 | * Fix up the uninitialized fields in a new device node: | ||
824 | * name, type and pci-specific fields | ||
825 | */ | ||
826 | |||
827 | static int of_finish_dynamic_node(struct device_node *node) | ||
828 | { | ||
829 | struct device_node *parent = of_get_parent(node); | ||
830 | int err = 0; | ||
831 | const phandle *ibm_phandle; | ||
832 | |||
833 | node->name = of_get_property(node, "name", NULL); | ||
834 | node->type = of_get_property(node, "device_type", NULL); | ||
835 | |||
836 | if (!node->name) | ||
837 | node->name = "<NULL>"; | ||
838 | if (!node->type) | ||
839 | node->type = "<NULL>"; | ||
840 | |||
841 | if (!parent) { | ||
842 | err = -ENODEV; | ||
843 | goto out; | ||
844 | } | ||
845 | |||
846 | /* We don't support that function on PowerMac, at least | ||
847 | * not yet | ||
848 | */ | ||
849 | if (machine_is(powermac)) | ||
850 | return -ENODEV; | ||
851 | |||
852 | /* fix up new node's phandle field */ | ||
853 | if ((ibm_phandle = of_get_property(node, "ibm,phandle", NULL))) | ||
854 | node->phandle = *ibm_phandle; | ||
855 | |||
856 | out: | ||
857 | of_node_put(parent); | ||
858 | return err; | ||
859 | } | ||
860 | |||
861 | static int prom_reconfig_notifier(struct notifier_block *nb, | ||
862 | unsigned long action, void *node) | ||
863 | { | ||
864 | int err; | ||
865 | |||
866 | switch (action) { | ||
867 | case OF_RECONFIG_ATTACH_NODE: | ||
868 | err = of_finish_dynamic_node(node); | ||
869 | if (err < 0) | ||
870 | printk(KERN_ERR "finish_node returned %d\n", err); | ||
871 | break; | ||
872 | default: | ||
873 | err = 0; | ||
874 | break; | ||
875 | } | ||
876 | return notifier_from_errno(err); | ||
877 | } | ||
878 | |||
879 | static struct notifier_block prom_reconfig_nb = { | ||
880 | .notifier_call = prom_reconfig_notifier, | ||
881 | .priority = 10, /* This one needs to run first */ | ||
882 | }; | ||
883 | |||
884 | static int __init prom_reconfig_setup(void) | ||
885 | { | ||
886 | return of_reconfig_notifier_register(&prom_reconfig_nb); | ||
887 | } | ||
888 | __initcall(prom_reconfig_setup); | ||
889 | #endif | ||
890 | |||
891 | bool arch_match_cpu_phys_id(int cpu, u64 phys_id) | 821 | bool arch_match_cpu_phys_id(int cpu, u64 phys_id) |
892 | { | 822 | { |
893 | return (int)phys_id == get_hard_smp_processor_id(cpu); | 823 | return (int)phys_id == get_hard_smp_processor_id(cpu); |
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index 1413e72bc2e1..4882bfd90e27 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c | |||
@@ -2805,25 +2805,20 @@ set_initial_features(void) | |||
2805 | /* Enable GMAC for now for PCI probing. It will be disabled | 2805 | /* Enable GMAC for now for PCI probing. It will be disabled |
2806 | * later on after PCI probe | 2806 | * later on after PCI probe |
2807 | */ | 2807 | */ |
2808 | np = of_find_node_by_name(NULL, "ethernet"); | 2808 | for_each_node_by_name(np, "ethernet") |
2809 | while(np) { | ||
2810 | if (of_device_is_compatible(np, "K2-GMAC")) | 2809 | if (of_device_is_compatible(np, "K2-GMAC")) |
2811 | g5_gmac_enable(np, 0, 1); | 2810 | g5_gmac_enable(np, 0, 1); |
2812 | np = of_find_node_by_name(np, "ethernet"); | ||
2813 | } | ||
2814 | 2811 | ||
2815 | /* Enable FW before PCI probe. Will be disabled later on | 2812 | /* Enable FW before PCI probe. Will be disabled later on |
2816 | * Note: We should have a batter way to check that we are | 2813 | * Note: We should have a batter way to check that we are |
2817 | * dealing with uninorth internal cell and not a PCI cell | 2814 | * dealing with uninorth internal cell and not a PCI cell |
2818 | * on the external PCI. The code below works though. | 2815 | * on the external PCI. The code below works though. |
2819 | */ | 2816 | */ |
2820 | np = of_find_node_by_name(NULL, "firewire"); | 2817 | for_each_node_by_name(np, "firewire") { |
2821 | while(np) { | ||
2822 | if (of_device_is_compatible(np, "pci106b,5811")) { | 2818 | if (of_device_is_compatible(np, "pci106b,5811")) { |
2823 | macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; | 2819 | macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; |
2824 | g5_fw_enable(np, 0, 1); | 2820 | g5_fw_enable(np, 0, 1); |
2825 | } | 2821 | } |
2826 | np = of_find_node_by_name(np, "firewire"); | ||
2827 | } | 2822 | } |
2828 | } | 2823 | } |
2829 | #else /* CONFIG_PPC64 */ | 2824 | #else /* CONFIG_PPC64 */ |
@@ -2834,13 +2829,11 @@ set_initial_features(void) | |||
2834 | /* Enable GMAC for now for PCI probing. It will be disabled | 2829 | /* Enable GMAC for now for PCI probing. It will be disabled |
2835 | * later on after PCI probe | 2830 | * later on after PCI probe |
2836 | */ | 2831 | */ |
2837 | np = of_find_node_by_name(NULL, "ethernet"); | 2832 | for_each_node_by_name(np, "ethernet") { |
2838 | while(np) { | ||
2839 | if (np->parent | 2833 | if (np->parent |
2840 | && of_device_is_compatible(np->parent, "uni-north") | 2834 | && of_device_is_compatible(np->parent, "uni-north") |
2841 | && of_device_is_compatible(np, "gmac")) | 2835 | && of_device_is_compatible(np, "gmac")) |
2842 | core99_gmac_enable(np, 0, 1); | 2836 | core99_gmac_enable(np, 0, 1); |
2843 | np = of_find_node_by_name(np, "ethernet"); | ||
2844 | } | 2837 | } |
2845 | 2838 | ||
2846 | /* Enable FW before PCI probe. Will be disabled later on | 2839 | /* Enable FW before PCI probe. Will be disabled later on |
@@ -2848,8 +2841,7 @@ set_initial_features(void) | |||
2848 | * dealing with uninorth internal cell and not a PCI cell | 2841 | * dealing with uninorth internal cell and not a PCI cell |
2849 | * on the external PCI. The code below works though. | 2842 | * on the external PCI. The code below works though. |
2850 | */ | 2843 | */ |
2851 | np = of_find_node_by_name(NULL, "firewire"); | 2844 | for_each_node_by_name(np, "firewire") { |
2852 | while(np) { | ||
2853 | if (np->parent | 2845 | if (np->parent |
2854 | && of_device_is_compatible(np->parent, "uni-north") | 2846 | && of_device_is_compatible(np->parent, "uni-north") |
2855 | && (of_device_is_compatible(np, "pci106b,18") || | 2847 | && (of_device_is_compatible(np, "pci106b,18") || |
@@ -2858,18 +2850,16 @@ set_initial_features(void) | |||
2858 | macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; | 2850 | macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; |
2859 | core99_firewire_enable(np, 0, 1); | 2851 | core99_firewire_enable(np, 0, 1); |
2860 | } | 2852 | } |
2861 | np = of_find_node_by_name(np, "firewire"); | ||
2862 | } | 2853 | } |
2863 | 2854 | ||
2864 | /* Enable ATA-100 before PCI probe. */ | 2855 | /* Enable ATA-100 before PCI probe. */ |
2865 | np = of_find_node_by_name(NULL, "ata-6"); | 2856 | np = of_find_node_by_name(NULL, "ata-6"); |
2866 | while(np) { | 2857 | for_each_node_by_name(np, "ata-6") { |
2867 | if (np->parent | 2858 | if (np->parent |
2868 | && of_device_is_compatible(np->parent, "uni-north") | 2859 | && of_device_is_compatible(np->parent, "uni-north") |
2869 | && of_device_is_compatible(np, "kauai-ata")) { | 2860 | && of_device_is_compatible(np, "kauai-ata")) { |
2870 | core99_ata100_enable(np, 1); | 2861 | core99_ata100_enable(np, 1); |
2871 | } | 2862 | } |
2872 | np = of_find_node_by_name(np, "ata-6"); | ||
2873 | } | 2863 | } |
2874 | 2864 | ||
2875 | /* Switch airport off */ | 2865 | /* Switch airport off */ |
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index cf7009b8c7b6..7e868ccf3b0d 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c | |||
@@ -698,7 +698,7 @@ static void __init fixup_nec_usb2(void) | |||
698 | { | 698 | { |
699 | struct device_node *nec; | 699 | struct device_node *nec; |
700 | 700 | ||
701 | for (nec = NULL; (nec = of_find_node_by_name(nec, "usb")) != NULL;) { | 701 | for_each_node_by_name(nec, "usb") { |
702 | struct pci_controller *hose; | 702 | struct pci_controller *hose; |
703 | u32 data; | 703 | u32 data; |
704 | const u32 *prop; | 704 | const u32 *prop; |
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index 5cbd4d67d5c4..af094ae03dbb 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c | |||
@@ -577,7 +577,7 @@ static void __init smp_core99_setup_i2c_hwsync(int ncpus) | |||
577 | int ok; | 577 | int ok; |
578 | 578 | ||
579 | /* Look for the clock chip */ | 579 | /* Look for the clock chip */ |
580 | while ((cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL) { | 580 | for_each_node_by_name(cc, "i2c-hwclock") { |
581 | p = of_get_parent(cc); | 581 | p = of_get_parent(cc); |
582 | ok = p && of_device_is_compatible(p, "uni-n-i2c"); | 582 | ok = p && of_device_is_compatible(p, "uni-n-i2c"); |
583 | of_node_put(p); | 583 | of_node_put(p); |
diff --git a/arch/powerpc/platforms/powermac/udbg_adb.c b/arch/powerpc/platforms/powermac/udbg_adb.c index 44e0b55a2a02..366bd221edec 100644 --- a/arch/powerpc/platforms/powermac/udbg_adb.c +++ b/arch/powerpc/platforms/powermac/udbg_adb.c | |||
@@ -191,7 +191,7 @@ int __init udbg_adb_init(int force_btext) | |||
191 | * of type "adb". If not, we return a failure, but we keep the | 191 | * of type "adb". If not, we return a failure, but we keep the |
192 | * bext output set for now | 192 | * bext output set for now |
193 | */ | 193 | */ |
194 | for (np = NULL; (np = of_find_node_by_name(np, "keyboard")) != NULL;) { | 194 | for_each_node_by_name(np, "keyboard") { |
195 | struct device_node *parent = of_get_parent(np); | 195 | struct device_node *parent = of_get_parent(np); |
196 | int found = (parent && strcmp(parent->type, "adb") == 0); | 196 | int found = (parent && strcmp(parent->type, "adb") == 0); |
197 | of_node_put(parent); | 197 | of_node_put(parent); |
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index 7995135170a3..ac01e188faef 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c | |||
@@ -194,7 +194,7 @@ static int pseries_update_drconf_memory(struct of_prop_reconfig *pr) | |||
194 | if (!memblock_size) | 194 | if (!memblock_size) |
195 | return -EINVAL; | 195 | return -EINVAL; |
196 | 196 | ||
197 | p = (u32 *)of_get_property(pr->dn, "ibm,dynamic-memory", NULL); | 197 | p = (u32 *) pr->old_prop->value; |
198 | if (!p) | 198 | if (!p) |
199 | return -EINVAL; | 199 | return -EINVAL; |
200 | 200 | ||
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index cfe8a6389a51..e724d3186e73 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -232,8 +232,7 @@ static void __init pseries_discover_pic(void) | |||
232 | struct device_node *np; | 232 | struct device_node *np; |
233 | const char *typep; | 233 | const char *typep; |
234 | 234 | ||
235 | for (np = NULL; (np = of_find_node_by_name(np, | 235 | for_each_node_by_name(np, "interrupt-controller") { |
236 | "interrupt-controller"));) { | ||
237 | typep = of_get_property(np, "compatible", NULL); | 236 | typep = of_get_property(np, "compatible", NULL); |
238 | if (strstr(typep, "open-pic")) { | 237 | if (strstr(typep, "open-pic")) { |
239 | pSeries_mpic_node = of_node_get(np); | 238 | pSeries_mpic_node = of_node_get(np); |
diff --git a/drivers/cpufreq/pmac64-cpufreq.c b/drivers/cpufreq/pmac64-cpufreq.c index 8bc422977b5b..4ff86878727f 100644 --- a/drivers/cpufreq/pmac64-cpufreq.c +++ b/drivers/cpufreq/pmac64-cpufreq.c | |||
@@ -499,8 +499,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpunode) | |||
499 | } | 499 | } |
500 | 500 | ||
501 | /* Lookup the i2c hwclock */ | 501 | /* Lookup the i2c hwclock */ |
502 | for (hwclock = NULL; | 502 | for_each_node_by_name(hwclock, "i2c-hwclock") { |
503 | (hwclock = of_find_node_by_name(hwclock, "i2c-hwclock")) != NULL;){ | ||
504 | const char *loc = of_get_property(hwclock, | 503 | const char *loc = of_get_property(hwclock, |
505 | "hwctrl-location", NULL); | 504 | "hwctrl-location", NULL); |
506 | if (loc == NULL) | 505 | if (loc == NULL) |
diff --git a/drivers/crypto/nx/nx-842.c b/drivers/crypto/nx/nx-842.c index 544f6d327ede..061407d59520 100644 --- a/drivers/crypto/nx/nx-842.c +++ b/drivers/crypto/nx/nx-842.c | |||
@@ -936,28 +936,14 @@ static int nx842_OF_upd(struct property *new_prop) | |||
936 | goto error_out; | 936 | goto error_out; |
937 | } | 937 | } |
938 | 938 | ||
939 | /* Set ptr to new property if provided */ | 939 | /* |
940 | if (new_prop) { | 940 | * If this is a property update, there are only certain properties that |
941 | /* Single property */ | 941 | * we care about. Bail if it isn't in the below list |
942 | if (!strncmp(new_prop->name, "status", new_prop->length)) { | 942 | */ |
943 | status = new_prop; | 943 | if (new_prop && (strncmp(new_prop->name, "status", new_prop->length) || |
944 | 944 | strncmp(new_prop->name, "ibm,max-sg-len", new_prop->length) || | |
945 | } else if (!strncmp(new_prop->name, "ibm,max-sg-len", | 945 | strncmp(new_prop->name, "ibm,max-sync-cop", new_prop->length))) |
946 | new_prop->length)) { | 946 | goto out; |
947 | maxsglen = new_prop; | ||
948 | |||
949 | } else if (!strncmp(new_prop->name, "ibm,max-sync-cop", | ||
950 | new_prop->length)) { | ||
951 | maxsyncop = new_prop; | ||
952 | |||
953 | } else { | ||
954 | /* | ||
955 | * Skip the update, the property being updated | ||
956 | * has no impact. | ||
957 | */ | ||
958 | goto out; | ||
959 | } | ||
960 | } | ||
961 | 947 | ||
962 | /* Perform property updates */ | 948 | /* Perform property updates */ |
963 | ret = nx842_OF_upd_status(new_devdata, status); | 949 | ret = nx842_OF_upd_status(new_devdata, status); |
diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c index 374b57fc596d..a12c8552f6a6 100644 --- a/drivers/edac/cell_edac.c +++ b/drivers/edac/cell_edac.c | |||
@@ -134,8 +134,7 @@ static void cell_edac_init_csrows(struct mem_ctl_info *mci) | |||
134 | int j; | 134 | int j; |
135 | u32 nr_pages; | 135 | u32 nr_pages; |
136 | 136 | ||
137 | for (np = NULL; | 137 | for_each_node_by_name(np, "memory") { |
138 | (np = of_find_node_by_name(np, "memory")) != NULL;) { | ||
139 | struct resource r; | 138 | struct resource r; |
140 | 139 | ||
141 | /* We "know" that the Cell firmware only creates one entry | 140 | /* We "know" that the Cell firmware only creates one entry |
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 2dcb0541012d..5160c4eb73c2 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig | |||
@@ -9,7 +9,8 @@ menu "Device Tree and Open Firmware support" | |||
9 | 9 | ||
10 | config OF_SELFTEST | 10 | config OF_SELFTEST |
11 | bool "Device Tree Runtime self tests" | 11 | bool "Device Tree Runtime self tests" |
12 | depends on OF_IRQ | 12 | depends on OF_IRQ && OF_EARLY_FLATTREE |
13 | select OF_DYNAMIC | ||
13 | help | 14 | help |
14 | This option builds in test cases for the device tree infrastructure | 15 | This option builds in test cases for the device tree infrastructure |
15 | that are executed once at boot time, and the results dumped to the | 16 | that are executed once at boot time, and the results dumped to the |
diff --git a/drivers/of/Makefile b/drivers/of/Makefile index 099b1fb00af4..2b6a7b129d10 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile | |||
@@ -1,11 +1,13 @@ | |||
1 | obj-y = base.o device.o platform.o | 1 | obj-y = base.o device.o platform.o |
2 | obj-$(CONFIG_OF_DYNAMIC) += dynamic.o | ||
2 | obj-$(CONFIG_OF_FLATTREE) += fdt.o | 3 | obj-$(CONFIG_OF_FLATTREE) += fdt.o |
3 | obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o | 4 | obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o |
4 | obj-$(CONFIG_OF_PROMTREE) += pdt.o | 5 | obj-$(CONFIG_OF_PROMTREE) += pdt.o |
5 | obj-$(CONFIG_OF_ADDRESS) += address.o | 6 | obj-$(CONFIG_OF_ADDRESS) += address.o |
6 | obj-$(CONFIG_OF_IRQ) += irq.o | 7 | obj-$(CONFIG_OF_IRQ) += irq.o |
7 | obj-$(CONFIG_OF_NET) += of_net.o | 8 | obj-$(CONFIG_OF_NET) += of_net.o |
8 | obj-$(CONFIG_OF_SELFTEST) += selftest.o | 9 | obj-$(CONFIG_OF_SELFTEST) += of_selftest.o |
10 | of_selftest-objs := selftest.o testcase-data/testcases.dtb.o | ||
9 | obj-$(CONFIG_OF_MDIO) += of_mdio.o | 11 | obj-$(CONFIG_OF_MDIO) += of_mdio.o |
10 | obj-$(CONFIG_OF_PCI) += of_pci.o | 12 | obj-$(CONFIG_OF_PCI) += of_pci.o |
11 | obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o | 13 | obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o |
diff --git a/drivers/of/base.c b/drivers/of/base.c index b9864806e9b8..d8574adf0d62 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -17,6 +17,7 @@ | |||
17 | * as published by the Free Software Foundation; either version | 17 | * as published by the Free Software Foundation; either version |
18 | * 2 of the License, or (at your option) any later version. | 18 | * 2 of the License, or (at your option) any later version. |
19 | */ | 19 | */ |
20 | #include <linux/console.h> | ||
20 | #include <linux/ctype.h> | 21 | #include <linux/ctype.h> |
21 | #include <linux/cpu.h> | 22 | #include <linux/cpu.h> |
22 | #include <linux/module.h> | 23 | #include <linux/module.h> |
@@ -35,15 +36,17 @@ struct device_node *of_allnodes; | |||
35 | EXPORT_SYMBOL(of_allnodes); | 36 | EXPORT_SYMBOL(of_allnodes); |
36 | struct device_node *of_chosen; | 37 | struct device_node *of_chosen; |
37 | struct device_node *of_aliases; | 38 | struct device_node *of_aliases; |
38 | static struct device_node *of_stdout; | 39 | struct device_node *of_stdout; |
39 | 40 | ||
40 | static struct kset *of_kset; | 41 | struct kset *of_kset; |
41 | 42 | ||
42 | /* | 43 | /* |
43 | * Used to protect the of_aliases; but also overloaded to hold off addition of | 44 | * Used to protect the of_aliases, to hold off addition of nodes to sysfs. |
44 | * nodes to sysfs | 45 | * This mutex must be held whenever modifications are being made to the |
46 | * device tree. The of_{attach,detach}_node() and | ||
47 | * of_{add,remove,update}_property() helpers make sure this happens. | ||
45 | */ | 48 | */ |
46 | DEFINE_MUTEX(of_aliases_mutex); | 49 | DEFINE_MUTEX(of_mutex); |
47 | 50 | ||
48 | /* use when traversing tree through the allnext, child, sibling, | 51 | /* use when traversing tree through the allnext, child, sibling, |
49 | * or parent members of struct device_node. | 52 | * or parent members of struct device_node. |
@@ -89,79 +92,7 @@ int __weak of_node_to_nid(struct device_node *np) | |||
89 | } | 92 | } |
90 | #endif | 93 | #endif |
91 | 94 | ||
92 | #if defined(CONFIG_OF_DYNAMIC) | 95 | #ifndef CONFIG_OF_DYNAMIC |
93 | /** | ||
94 | * of_node_get - Increment refcount of a node | ||
95 | * @node: Node to inc refcount, NULL is supported to | ||
96 | * simplify writing of callers | ||
97 | * | ||
98 | * Returns node. | ||
99 | */ | ||
100 | struct device_node *of_node_get(struct device_node *node) | ||
101 | { | ||
102 | if (node) | ||
103 | kobject_get(&node->kobj); | ||
104 | return node; | ||
105 | } | ||
106 | EXPORT_SYMBOL(of_node_get); | ||
107 | |||
108 | static inline struct device_node *kobj_to_device_node(struct kobject *kobj) | ||
109 | { | ||
110 | return container_of(kobj, struct device_node, kobj); | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * of_node_release - release a dynamically allocated node | ||
115 | * @kref: kref element of the node to be released | ||
116 | * | ||
117 | * In of_node_put() this function is passed to kref_put() | ||
118 | * as the destructor. | ||
119 | */ | ||
120 | static void of_node_release(struct kobject *kobj) | ||
121 | { | ||
122 | struct device_node *node = kobj_to_device_node(kobj); | ||
123 | struct property *prop = node->properties; | ||
124 | |||
125 | /* We should never be releasing nodes that haven't been detached. */ | ||
126 | if (!of_node_check_flag(node, OF_DETACHED)) { | ||
127 | pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name); | ||
128 | dump_stack(); | ||
129 | return; | ||
130 | } | ||
131 | |||
132 | if (!of_node_check_flag(node, OF_DYNAMIC)) | ||
133 | return; | ||
134 | |||
135 | while (prop) { | ||
136 | struct property *next = prop->next; | ||
137 | kfree(prop->name); | ||
138 | kfree(prop->value); | ||
139 | kfree(prop); | ||
140 | prop = next; | ||
141 | |||
142 | if (!prop) { | ||
143 | prop = node->deadprops; | ||
144 | node->deadprops = NULL; | ||
145 | } | ||
146 | } | ||
147 | kfree(node->full_name); | ||
148 | kfree(node->data); | ||
149 | kfree(node); | ||
150 | } | ||
151 | |||
152 | /** | ||
153 | * of_node_put - Decrement refcount of a node | ||
154 | * @node: Node to dec refcount, NULL is supported to | ||
155 | * simplify writing of callers | ||
156 | * | ||
157 | */ | ||
158 | void of_node_put(struct device_node *node) | ||
159 | { | ||
160 | if (node) | ||
161 | kobject_put(&node->kobj); | ||
162 | } | ||
163 | EXPORT_SYMBOL(of_node_put); | ||
164 | #else | ||
165 | static void of_node_release(struct kobject *kobj) | 96 | static void of_node_release(struct kobject *kobj) |
166 | { | 97 | { |
167 | /* Without CONFIG_OF_DYNAMIC, no nodes gets freed */ | 98 | /* Without CONFIG_OF_DYNAMIC, no nodes gets freed */ |
@@ -200,13 +131,16 @@ static const char *safe_name(struct kobject *kobj, const char *orig_name) | |||
200 | return name; | 131 | return name; |
201 | } | 132 | } |
202 | 133 | ||
203 | static int __of_add_property_sysfs(struct device_node *np, struct property *pp) | 134 | int __of_add_property_sysfs(struct device_node *np, struct property *pp) |
204 | { | 135 | { |
205 | int rc; | 136 | int rc; |
206 | 137 | ||
207 | /* Important: Don't leak passwords */ | 138 | /* Important: Don't leak passwords */ |
208 | bool secure = strncmp(pp->name, "security-", 9) == 0; | 139 | bool secure = strncmp(pp->name, "security-", 9) == 0; |
209 | 140 | ||
141 | if (!of_kset || !of_node_is_attached(np)) | ||
142 | return 0; | ||
143 | |||
210 | sysfs_bin_attr_init(&pp->attr); | 144 | sysfs_bin_attr_init(&pp->attr); |
211 | pp->attr.attr.name = safe_name(&np->kobj, pp->name); | 145 | pp->attr.attr.name = safe_name(&np->kobj, pp->name); |
212 | pp->attr.attr.mode = secure ? S_IRUSR : S_IRUGO; | 146 | pp->attr.attr.mode = secure ? S_IRUSR : S_IRUGO; |
@@ -218,12 +152,15 @@ static int __of_add_property_sysfs(struct device_node *np, struct property *pp) | |||
218 | return rc; | 152 | return rc; |
219 | } | 153 | } |
220 | 154 | ||
221 | static int __of_node_add(struct device_node *np) | 155 | int __of_attach_node_sysfs(struct device_node *np) |
222 | { | 156 | { |
223 | const char *name; | 157 | const char *name; |
224 | struct property *pp; | 158 | struct property *pp; |
225 | int rc; | 159 | int rc; |
226 | 160 | ||
161 | if (!of_kset) | ||
162 | return 0; | ||
163 | |||
227 | np->kobj.kset = of_kset; | 164 | np->kobj.kset = of_kset; |
228 | if (!np->parent) { | 165 | if (!np->parent) { |
229 | /* Nodes without parents are new top level trees */ | 166 | /* Nodes without parents are new top level trees */ |
@@ -245,59 +182,20 @@ static int __of_node_add(struct device_node *np) | |||
245 | return 0; | 182 | return 0; |
246 | } | 183 | } |
247 | 184 | ||
248 | int of_node_add(struct device_node *np) | ||
249 | { | ||
250 | int rc = 0; | ||
251 | |||
252 | BUG_ON(!of_node_is_initialized(np)); | ||
253 | |||
254 | /* | ||
255 | * Grab the mutex here so that in a race condition between of_init() and | ||
256 | * of_node_add(), node addition will still be consistent. | ||
257 | */ | ||
258 | mutex_lock(&of_aliases_mutex); | ||
259 | if (of_kset) | ||
260 | rc = __of_node_add(np); | ||
261 | else | ||
262 | /* This scenario may be perfectly valid, but report it anyway */ | ||
263 | pr_info("of_node_add(%s) before of_init()\n", np->full_name); | ||
264 | mutex_unlock(&of_aliases_mutex); | ||
265 | return rc; | ||
266 | } | ||
267 | |||
268 | #if defined(CONFIG_OF_DYNAMIC) | ||
269 | static void of_node_remove(struct device_node *np) | ||
270 | { | ||
271 | struct property *pp; | ||
272 | |||
273 | BUG_ON(!of_node_is_initialized(np)); | ||
274 | |||
275 | /* only remove properties if on sysfs */ | ||
276 | if (of_node_is_attached(np)) { | ||
277 | for_each_property_of_node(np, pp) | ||
278 | sysfs_remove_bin_file(&np->kobj, &pp->attr); | ||
279 | kobject_del(&np->kobj); | ||
280 | } | ||
281 | |||
282 | /* finally remove the kobj_init ref */ | ||
283 | of_node_put(np); | ||
284 | } | ||
285 | #endif | ||
286 | |||
287 | static int __init of_init(void) | 185 | static int __init of_init(void) |
288 | { | 186 | { |
289 | struct device_node *np; | 187 | struct device_node *np; |
290 | 188 | ||
291 | /* Create the kset, and register existing nodes */ | 189 | /* Create the kset, and register existing nodes */ |
292 | mutex_lock(&of_aliases_mutex); | 190 | mutex_lock(&of_mutex); |
293 | of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj); | 191 | of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj); |
294 | if (!of_kset) { | 192 | if (!of_kset) { |
295 | mutex_unlock(&of_aliases_mutex); | 193 | mutex_unlock(&of_mutex); |
296 | return -ENOMEM; | 194 | return -ENOMEM; |
297 | } | 195 | } |
298 | for_each_of_allnodes(np) | 196 | for_each_of_allnodes(np) |
299 | __of_node_add(np); | 197 | __of_attach_node_sysfs(np); |
300 | mutex_unlock(&of_aliases_mutex); | 198 | mutex_unlock(&of_mutex); |
301 | 199 | ||
302 | /* Symlink in /proc as required by userspace ABI */ | 200 | /* Symlink in /proc as required by userspace ABI */ |
303 | if (of_allnodes) | 201 | if (of_allnodes) |
@@ -369,8 +267,8 @@ EXPORT_SYMBOL(of_find_all_nodes); | |||
369 | * Find a property with a given name for a given node | 267 | * Find a property with a given name for a given node |
370 | * and return the value. | 268 | * and return the value. |
371 | */ | 269 | */ |
372 | static const void *__of_get_property(const struct device_node *np, | 270 | const void *__of_get_property(const struct device_node *np, |
373 | const char *name, int *lenp) | 271 | const char *name, int *lenp) |
374 | { | 272 | { |
375 | struct property *pp = __of_find_property(np, name, lenp); | 273 | struct property *pp = __of_find_property(np, name, lenp); |
376 | 274 | ||
@@ -1748,32 +1646,10 @@ int of_count_phandle_with_args(const struct device_node *np, const char *list_na | |||
1748 | } | 1646 | } |
1749 | EXPORT_SYMBOL(of_count_phandle_with_args); | 1647 | EXPORT_SYMBOL(of_count_phandle_with_args); |
1750 | 1648 | ||
1751 | #if defined(CONFIG_OF_DYNAMIC) | ||
1752 | static int of_property_notify(int action, struct device_node *np, | ||
1753 | struct property *prop) | ||
1754 | { | ||
1755 | struct of_prop_reconfig pr; | ||
1756 | |||
1757 | /* only call notifiers if the node is attached */ | ||
1758 | if (!of_node_is_attached(np)) | ||
1759 | return 0; | ||
1760 | |||
1761 | pr.dn = np; | ||
1762 | pr.prop = prop; | ||
1763 | return of_reconfig_notify(action, &pr); | ||
1764 | } | ||
1765 | #else | ||
1766 | static int of_property_notify(int action, struct device_node *np, | ||
1767 | struct property *prop) | ||
1768 | { | ||
1769 | return 0; | ||
1770 | } | ||
1771 | #endif | ||
1772 | |||
1773 | /** | 1649 | /** |
1774 | * __of_add_property - Add a property to a node without lock operations | 1650 | * __of_add_property - Add a property to a node without lock operations |
1775 | */ | 1651 | */ |
1776 | static int __of_add_property(struct device_node *np, struct property *prop) | 1652 | int __of_add_property(struct device_node *np, struct property *prop) |
1777 | { | 1653 | { |
1778 | struct property **next; | 1654 | struct property **next; |
1779 | 1655 | ||
@@ -1799,22 +1675,49 @@ int of_add_property(struct device_node *np, struct property *prop) | |||
1799 | unsigned long flags; | 1675 | unsigned long flags; |
1800 | int rc; | 1676 | int rc; |
1801 | 1677 | ||
1802 | rc = of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop); | 1678 | mutex_lock(&of_mutex); |
1803 | if (rc) | ||
1804 | return rc; | ||
1805 | 1679 | ||
1806 | raw_spin_lock_irqsave(&devtree_lock, flags); | 1680 | raw_spin_lock_irqsave(&devtree_lock, flags); |
1807 | rc = __of_add_property(np, prop); | 1681 | rc = __of_add_property(np, prop); |
1808 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | 1682 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
1809 | if (rc) | ||
1810 | return rc; | ||
1811 | 1683 | ||
1812 | if (of_node_is_attached(np)) | 1684 | if (!rc) |
1813 | __of_add_property_sysfs(np, prop); | 1685 | __of_add_property_sysfs(np, prop); |
1814 | 1686 | ||
1687 | mutex_unlock(&of_mutex); | ||
1688 | |||
1689 | if (!rc) | ||
1690 | of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop, NULL); | ||
1691 | |||
1815 | return rc; | 1692 | return rc; |
1816 | } | 1693 | } |
1817 | 1694 | ||
1695 | int __of_remove_property(struct device_node *np, struct property *prop) | ||
1696 | { | ||
1697 | struct property **next; | ||
1698 | |||
1699 | for (next = &np->properties; *next; next = &(*next)->next) { | ||
1700 | if (*next == prop) | ||
1701 | break; | ||
1702 | } | ||
1703 | if (*next == NULL) | ||
1704 | return -ENODEV; | ||
1705 | |||
1706 | /* found the node */ | ||
1707 | *next = prop->next; | ||
1708 | prop->next = np->deadprops; | ||
1709 | np->deadprops = prop; | ||
1710 | |||
1711 | return 0; | ||
1712 | } | ||
1713 | |||
1714 | void __of_remove_property_sysfs(struct device_node *np, struct property *prop) | ||
1715 | { | ||
1716 | /* at early boot, bail here and defer setup to of_init() */ | ||
1717 | if (of_kset && of_node_is_attached(np)) | ||
1718 | sysfs_remove_bin_file(&np->kobj, &prop->attr); | ||
1719 | } | ||
1720 | |||
1818 | /** | 1721 | /** |
1819 | * of_remove_property - Remove a property from a node. | 1722 | * of_remove_property - Remove a property from a node. |
1820 | * | 1723 | * |
@@ -1825,211 +1728,98 @@ int of_add_property(struct device_node *np, struct property *prop) | |||
1825 | */ | 1728 | */ |
1826 | int of_remove_property(struct device_node *np, struct property *prop) | 1729 | int of_remove_property(struct device_node *np, struct property *prop) |
1827 | { | 1730 | { |
1828 | struct property **next; | ||
1829 | unsigned long flags; | 1731 | unsigned long flags; |
1830 | int found = 0; | ||
1831 | int rc; | 1732 | int rc; |
1832 | 1733 | ||
1833 | rc = of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop); | 1734 | mutex_lock(&of_mutex); |
1834 | if (rc) | ||
1835 | return rc; | ||
1836 | 1735 | ||
1837 | raw_spin_lock_irqsave(&devtree_lock, flags); | 1736 | raw_spin_lock_irqsave(&devtree_lock, flags); |
1838 | next = &np->properties; | 1737 | rc = __of_remove_property(np, prop); |
1839 | while (*next) { | ||
1840 | if (*next == prop) { | ||
1841 | /* found the node */ | ||
1842 | *next = prop->next; | ||
1843 | prop->next = np->deadprops; | ||
1844 | np->deadprops = prop; | ||
1845 | found = 1; | ||
1846 | break; | ||
1847 | } | ||
1848 | next = &(*next)->next; | ||
1849 | } | ||
1850 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | 1738 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
1851 | 1739 | ||
1852 | if (!found) | 1740 | if (!rc) |
1853 | return -ENODEV; | 1741 | __of_remove_property_sysfs(np, prop); |
1854 | 1742 | ||
1855 | /* at early boot, bail hear and defer setup to of_init() */ | 1743 | mutex_unlock(&of_mutex); |
1856 | if (!of_kset) | ||
1857 | return 0; | ||
1858 | 1744 | ||
1859 | sysfs_remove_bin_file(&np->kobj, &prop->attr); | 1745 | if (!rc) |
1746 | of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop, NULL); | ||
1860 | 1747 | ||
1861 | return 0; | 1748 | return rc; |
1862 | } | 1749 | } |
1863 | 1750 | ||
1864 | /* | 1751 | int __of_update_property(struct device_node *np, struct property *newprop, |
1865 | * of_update_property - Update a property in a node, if the property does | 1752 | struct property **oldpropp) |
1866 | * not exist, add it. | ||
1867 | * | ||
1868 | * Note that we don't actually remove it, since we have given out | ||
1869 | * who-knows-how-many pointers to the data using get-property. | ||
1870 | * Instead we just move the property to the "dead properties" list, | ||
1871 | * and add the new property to the property list | ||
1872 | */ | ||
1873 | int of_update_property(struct device_node *np, struct property *newprop) | ||
1874 | { | 1753 | { |
1875 | struct property **next, *oldprop; | 1754 | struct property **next, *oldprop; |
1876 | unsigned long flags; | ||
1877 | int rc; | ||
1878 | |||
1879 | rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop); | ||
1880 | if (rc) | ||
1881 | return rc; | ||
1882 | 1755 | ||
1883 | if (!newprop->name) | 1756 | for (next = &np->properties; *next; next = &(*next)->next) { |
1884 | return -EINVAL; | 1757 | if (of_prop_cmp((*next)->name, newprop->name) == 0) |
1758 | break; | ||
1759 | } | ||
1760 | *oldpropp = oldprop = *next; | ||
1885 | 1761 | ||
1886 | raw_spin_lock_irqsave(&devtree_lock, flags); | 1762 | if (oldprop) { |
1887 | next = &np->properties; | ||
1888 | oldprop = __of_find_property(np, newprop->name, NULL); | ||
1889 | if (!oldprop) { | ||
1890 | /* add the new node */ | ||
1891 | rc = __of_add_property(np, newprop); | ||
1892 | } else while (*next) { | ||
1893 | /* replace the node */ | 1763 | /* replace the node */ |
1894 | if (*next == oldprop) { | 1764 | newprop->next = oldprop->next; |
1895 | newprop->next = oldprop->next; | 1765 | *next = newprop; |
1896 | *next = newprop; | 1766 | oldprop->next = np->deadprops; |
1897 | oldprop->next = np->deadprops; | 1767 | np->deadprops = oldprop; |
1898 | np->deadprops = oldprop; | 1768 | } else { |
1899 | break; | 1769 | /* new node */ |
1900 | } | 1770 | newprop->next = NULL; |
1901 | next = &(*next)->next; | 1771 | *next = newprop; |
1902 | } | 1772 | } |
1903 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | ||
1904 | if (rc) | ||
1905 | return rc; | ||
1906 | 1773 | ||
1774 | return 0; | ||
1775 | } | ||
1776 | |||
1777 | void __of_update_property_sysfs(struct device_node *np, struct property *newprop, | ||
1778 | struct property *oldprop) | ||
1779 | { | ||
1907 | /* At early boot, bail out and defer setup to of_init() */ | 1780 | /* At early boot, bail out and defer setup to of_init() */ |
1908 | if (!of_kset) | 1781 | if (!of_kset) |
1909 | return 0; | 1782 | return; |
1910 | 1783 | ||
1911 | /* Update the sysfs attribute */ | ||
1912 | if (oldprop) | 1784 | if (oldprop) |
1913 | sysfs_remove_bin_file(&np->kobj, &oldprop->attr); | 1785 | sysfs_remove_bin_file(&np->kobj, &oldprop->attr); |
1914 | __of_add_property_sysfs(np, newprop); | 1786 | __of_add_property_sysfs(np, newprop); |
1915 | |||
1916 | return 0; | ||
1917 | } | 1787 | } |
1918 | 1788 | ||
1919 | #if defined(CONFIG_OF_DYNAMIC) | ||
1920 | /* | 1789 | /* |
1921 | * Support for dynamic device trees. | 1790 | * of_update_property - Update a property in a node, if the property does |
1791 | * not exist, add it. | ||
1922 | * | 1792 | * |
1923 | * On some platforms, the device tree can be manipulated at runtime. | 1793 | * Note that we don't actually remove it, since we have given out |
1924 | * The routines in this section support adding, removing and changing | 1794 | * who-knows-how-many pointers to the data using get-property. |
1925 | * device tree nodes. | 1795 | * Instead we just move the property to the "dead properties" list, |
1926 | */ | 1796 | * and add the new property to the property list |
1927 | |||
1928 | static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain); | ||
1929 | |||
1930 | int of_reconfig_notifier_register(struct notifier_block *nb) | ||
1931 | { | ||
1932 | return blocking_notifier_chain_register(&of_reconfig_chain, nb); | ||
1933 | } | ||
1934 | EXPORT_SYMBOL_GPL(of_reconfig_notifier_register); | ||
1935 | |||
1936 | int of_reconfig_notifier_unregister(struct notifier_block *nb) | ||
1937 | { | ||
1938 | return blocking_notifier_chain_unregister(&of_reconfig_chain, nb); | ||
1939 | } | ||
1940 | EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister); | ||
1941 | |||
1942 | int of_reconfig_notify(unsigned long action, void *p) | ||
1943 | { | ||
1944 | int rc; | ||
1945 | |||
1946 | rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p); | ||
1947 | return notifier_to_errno(rc); | ||
1948 | } | ||
1949 | |||
1950 | /** | ||
1951 | * of_attach_node - Plug a device node into the tree and global list. | ||
1952 | */ | 1797 | */ |
1953 | int of_attach_node(struct device_node *np) | 1798 | int of_update_property(struct device_node *np, struct property *newprop) |
1954 | { | 1799 | { |
1800 | struct property *oldprop; | ||
1955 | unsigned long flags; | 1801 | unsigned long flags; |
1956 | int rc; | 1802 | int rc; |
1957 | 1803 | ||
1958 | rc = of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, np); | 1804 | if (!newprop->name) |
1959 | if (rc) | 1805 | return -EINVAL; |
1960 | return rc; | ||
1961 | |||
1962 | raw_spin_lock_irqsave(&devtree_lock, flags); | ||
1963 | np->sibling = np->parent->child; | ||
1964 | np->allnext = np->parent->allnext; | ||
1965 | np->parent->allnext = np; | ||
1966 | np->parent->child = np; | ||
1967 | of_node_clear_flag(np, OF_DETACHED); | ||
1968 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | ||
1969 | |||
1970 | of_node_add(np); | ||
1971 | return 0; | ||
1972 | } | ||
1973 | |||
1974 | /** | ||
1975 | * of_detach_node - "Unplug" a node from the device tree. | ||
1976 | * | ||
1977 | * The caller must hold a reference to the node. The memory associated with | ||
1978 | * the node is not freed until its refcount goes to zero. | ||
1979 | */ | ||
1980 | int of_detach_node(struct device_node *np) | ||
1981 | { | ||
1982 | struct device_node *parent; | ||
1983 | unsigned long flags; | ||
1984 | int rc = 0; | ||
1985 | 1806 | ||
1986 | rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np); | 1807 | mutex_lock(&of_mutex); |
1987 | if (rc) | ||
1988 | return rc; | ||
1989 | 1808 | ||
1990 | raw_spin_lock_irqsave(&devtree_lock, flags); | 1809 | raw_spin_lock_irqsave(&devtree_lock, flags); |
1810 | rc = __of_update_property(np, newprop, &oldprop); | ||
1811 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | ||
1991 | 1812 | ||
1992 | if (of_node_check_flag(np, OF_DETACHED)) { | 1813 | if (!rc) |
1993 | /* someone already detached it */ | 1814 | __of_update_property_sysfs(np, newprop, oldprop); |
1994 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | ||
1995 | return rc; | ||
1996 | } | ||
1997 | |||
1998 | parent = np->parent; | ||
1999 | if (!parent) { | ||
2000 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | ||
2001 | return rc; | ||
2002 | } | ||
2003 | 1815 | ||
2004 | if (of_allnodes == np) | 1816 | mutex_unlock(&of_mutex); |
2005 | of_allnodes = np->allnext; | ||
2006 | else { | ||
2007 | struct device_node *prev; | ||
2008 | for (prev = of_allnodes; | ||
2009 | prev->allnext != np; | ||
2010 | prev = prev->allnext) | ||
2011 | ; | ||
2012 | prev->allnext = np->allnext; | ||
2013 | } | ||
2014 | 1817 | ||
2015 | if (parent->child == np) | 1818 | if (!rc) |
2016 | parent->child = np->sibling; | 1819 | of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop, oldprop); |
2017 | else { | ||
2018 | struct device_node *prevsib; | ||
2019 | for (prevsib = np->parent->child; | ||
2020 | prevsib->sibling != np; | ||
2021 | prevsib = prevsib->sibling) | ||
2022 | ; | ||
2023 | prevsib->sibling = np->sibling; | ||
2024 | } | ||
2025 | |||
2026 | of_node_set_flag(np, OF_DETACHED); | ||
2027 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | ||
2028 | 1820 | ||
2029 | of_node_remove(np); | ||
2030 | return rc; | 1821 | return rc; |
2031 | } | 1822 | } |
2032 | #endif /* defined(CONFIG_OF_DYNAMIC) */ | ||
2033 | 1823 | ||
2034 | static void of_alias_add(struct alias_prop *ap, struct device_node *np, | 1824 | static void of_alias_add(struct alias_prop *ap, struct device_node *np, |
2035 | int id, const char *stem, int stem_len) | 1825 | int id, const char *stem, int stem_len) |
@@ -2062,9 +1852,12 @@ void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)) | |||
2062 | of_chosen = of_find_node_by_path("/chosen@0"); | 1852 | of_chosen = of_find_node_by_path("/chosen@0"); |
2063 | 1853 | ||
2064 | if (of_chosen) { | 1854 | if (of_chosen) { |
1855 | /* linux,stdout-path and /aliases/stdout are for legacy compatibility */ | ||
2065 | const char *name = of_get_property(of_chosen, "stdout-path", NULL); | 1856 | const char *name = of_get_property(of_chosen, "stdout-path", NULL); |
2066 | if (!name) | 1857 | if (!name) |
2067 | name = of_get_property(of_chosen, "linux,stdout-path", NULL); | 1858 | name = of_get_property(of_chosen, "linux,stdout-path", NULL); |
1859 | if (IS_ENABLED(CONFIG_PPC) && !name) | ||
1860 | name = of_get_property(of_aliases, "stdout", NULL); | ||
2068 | if (name) | 1861 | if (name) |
2069 | of_stdout = of_find_node_by_path(name); | 1862 | of_stdout = of_find_node_by_path(name); |
2070 | } | 1863 | } |
@@ -2122,7 +1915,7 @@ int of_alias_get_id(struct device_node *np, const char *stem) | |||
2122 | struct alias_prop *app; | 1915 | struct alias_prop *app; |
2123 | int id = -ENODEV; | 1916 | int id = -ENODEV; |
2124 | 1917 | ||
2125 | mutex_lock(&of_aliases_mutex); | 1918 | mutex_lock(&of_mutex); |
2126 | list_for_each_entry(app, &aliases_lookup, link) { | 1919 | list_for_each_entry(app, &aliases_lookup, link) { |
2127 | if (strcmp(app->stem, stem) != 0) | 1920 | if (strcmp(app->stem, stem) != 0) |
2128 | continue; | 1921 | continue; |
@@ -2132,7 +1925,7 @@ int of_alias_get_id(struct device_node *np, const char *stem) | |||
2132 | break; | 1925 | break; |
2133 | } | 1926 | } |
2134 | } | 1927 | } |
2135 | mutex_unlock(&of_aliases_mutex); | 1928 | mutex_unlock(&of_mutex); |
2136 | 1929 | ||
2137 | return id; | 1930 | return id; |
2138 | } | 1931 | } |
@@ -2180,20 +1973,22 @@ const char *of_prop_next_string(struct property *prop, const char *cur) | |||
2180 | EXPORT_SYMBOL_GPL(of_prop_next_string); | 1973 | EXPORT_SYMBOL_GPL(of_prop_next_string); |
2181 | 1974 | ||
2182 | /** | 1975 | /** |
2183 | * of_device_is_stdout_path - check if a device node matches the | 1976 | * of_console_check() - Test and setup console for DT setup |
2184 | * linux,stdout-path property | 1977 | * @dn - Pointer to device node |
2185 | * | 1978 | * @name - Name to use for preferred console without index. ex. "ttyS" |
2186 | * Check if this device node matches the linux,stdout-path property | 1979 | * @index - Index to use for preferred console. |
2187 | * in the chosen node. return true if yes, false otherwise. | 1980 | * |
1981 | * Check if the given device node matches the stdout-path property in the | ||
1982 | * /chosen node. If it does then register it as the preferred console and return | ||
1983 | * TRUE. Otherwise return FALSE. | ||
2188 | */ | 1984 | */ |
2189 | int of_device_is_stdout_path(struct device_node *dn) | 1985 | bool of_console_check(struct device_node *dn, char *name, int index) |
2190 | { | 1986 | { |
2191 | if (!of_stdout) | 1987 | if (!dn || dn != of_stdout || console_set_on_cmdline) |
2192 | return false; | 1988 | return false; |
2193 | 1989 | return add_preferred_console(name, index, NULL); | |
2194 | return of_stdout == dn; | ||
2195 | } | 1990 | } |
2196 | EXPORT_SYMBOL_GPL(of_device_is_stdout_path); | 1991 | EXPORT_SYMBOL_GPL(of_console_check); |
2197 | 1992 | ||
2198 | /** | 1993 | /** |
2199 | * of_find_next_cache_node - Find a node's subsidiary cache | 1994 | * of_find_next_cache_node - Find a node's subsidiary cache |
diff --git a/drivers/of/device.c b/drivers/of/device.c index dafb9736ab9b..46d6c75c1404 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c | |||
@@ -160,7 +160,7 @@ void of_device_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
160 | add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen); | 160 | add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen); |
161 | 161 | ||
162 | seen = 0; | 162 | seen = 0; |
163 | mutex_lock(&of_aliases_mutex); | 163 | mutex_lock(&of_mutex); |
164 | list_for_each_entry(app, &aliases_lookup, link) { | 164 | list_for_each_entry(app, &aliases_lookup, link) { |
165 | if (dev->of_node == app->np) { | 165 | if (dev->of_node == app->np) { |
166 | add_uevent_var(env, "OF_ALIAS_%d=%s", seen, | 166 | add_uevent_var(env, "OF_ALIAS_%d=%s", seen, |
@@ -168,7 +168,7 @@ void of_device_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
168 | seen++; | 168 | seen++; |
169 | } | 169 | } |
170 | } | 170 | } |
171 | mutex_unlock(&of_aliases_mutex); | 171 | mutex_unlock(&of_mutex); |
172 | } | 172 | } |
173 | 173 | ||
174 | int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) | 174 | int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) |
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c new file mode 100644 index 000000000000..54fecc49a1fe --- /dev/null +++ b/drivers/of/dynamic.c | |||
@@ -0,0 +1,660 @@ | |||
1 | /* | ||
2 | * Support for dynamic device trees. | ||
3 | * | ||
4 | * On some platforms, the device tree can be manipulated at runtime. | ||
5 | * The routines in this section support adding, removing and changing | ||
6 | * device tree nodes. | ||
7 | */ | ||
8 | |||
9 | #include <linux/of.h> | ||
10 | #include <linux/spinlock.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/string.h> | ||
13 | #include <linux/proc_fs.h> | ||
14 | |||
15 | #include "of_private.h" | ||
16 | |||
17 | /** | ||
18 | * of_node_get() - Increment refcount of a node | ||
19 | * @node: Node to inc refcount, NULL is supported to simplify writing of | ||
20 | * callers | ||
21 | * | ||
22 | * Returns node. | ||
23 | */ | ||
24 | struct device_node *of_node_get(struct device_node *node) | ||
25 | { | ||
26 | if (node) | ||
27 | kobject_get(&node->kobj); | ||
28 | return node; | ||
29 | } | ||
30 | EXPORT_SYMBOL(of_node_get); | ||
31 | |||
32 | /** | ||
33 | * of_node_put() - Decrement refcount of a node | ||
34 | * @node: Node to dec refcount, NULL is supported to simplify writing of | ||
35 | * callers | ||
36 | */ | ||
37 | void of_node_put(struct device_node *node) | ||
38 | { | ||
39 | if (node) | ||
40 | kobject_put(&node->kobj); | ||
41 | } | ||
42 | EXPORT_SYMBOL(of_node_put); | ||
43 | |||
44 | void __of_detach_node_sysfs(struct device_node *np) | ||
45 | { | ||
46 | struct property *pp; | ||
47 | |||
48 | BUG_ON(!of_node_is_initialized(np)); | ||
49 | if (!of_kset) | ||
50 | return; | ||
51 | |||
52 | /* only remove properties if on sysfs */ | ||
53 | if (of_node_is_attached(np)) { | ||
54 | for_each_property_of_node(np, pp) | ||
55 | sysfs_remove_bin_file(&np->kobj, &pp->attr); | ||
56 | kobject_del(&np->kobj); | ||
57 | } | ||
58 | |||
59 | /* finally remove the kobj_init ref */ | ||
60 | of_node_put(np); | ||
61 | } | ||
62 | |||
63 | static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain); | ||
64 | |||
65 | int of_reconfig_notifier_register(struct notifier_block *nb) | ||
66 | { | ||
67 | return blocking_notifier_chain_register(&of_reconfig_chain, nb); | ||
68 | } | ||
69 | EXPORT_SYMBOL_GPL(of_reconfig_notifier_register); | ||
70 | |||
71 | int of_reconfig_notifier_unregister(struct notifier_block *nb) | ||
72 | { | ||
73 | return blocking_notifier_chain_unregister(&of_reconfig_chain, nb); | ||
74 | } | ||
75 | EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister); | ||
76 | |||
77 | int of_reconfig_notify(unsigned long action, void *p) | ||
78 | { | ||
79 | int rc; | ||
80 | |||
81 | rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p); | ||
82 | return notifier_to_errno(rc); | ||
83 | } | ||
84 | |||
85 | int of_property_notify(int action, struct device_node *np, | ||
86 | struct property *prop, struct property *oldprop) | ||
87 | { | ||
88 | struct of_prop_reconfig pr; | ||
89 | |||
90 | /* only call notifiers if the node is attached */ | ||
91 | if (!of_node_is_attached(np)) | ||
92 | return 0; | ||
93 | |||
94 | pr.dn = np; | ||
95 | pr.prop = prop; | ||
96 | pr.old_prop = oldprop; | ||
97 | return of_reconfig_notify(action, &pr); | ||
98 | } | ||
99 | |||
100 | void __of_attach_node(struct device_node *np) | ||
101 | { | ||
102 | const __be32 *phandle; | ||
103 | int sz; | ||
104 | |||
105 | np->name = __of_get_property(np, "name", NULL) ? : "<NULL>"; | ||
106 | np->type = __of_get_property(np, "device_type", NULL) ? : "<NULL>"; | ||
107 | |||
108 | phandle = __of_get_property(np, "phandle", &sz); | ||
109 | if (!phandle) | ||
110 | phandle = __of_get_property(np, "linux,phandle", &sz); | ||
111 | if (IS_ENABLED(PPC_PSERIES) && !phandle) | ||
112 | phandle = __of_get_property(np, "ibm,phandle", &sz); | ||
113 | np->phandle = (phandle && (sz >= 4)) ? be32_to_cpup(phandle) : 0; | ||
114 | |||
115 | np->child = NULL; | ||
116 | np->sibling = np->parent->child; | ||
117 | np->allnext = np->parent->allnext; | ||
118 | np->parent->allnext = np; | ||
119 | np->parent->child = np; | ||
120 | of_node_clear_flag(np, OF_DETACHED); | ||
121 | } | ||
122 | |||
123 | /** | ||
124 | * of_attach_node() - Plug a device node into the tree and global list. | ||
125 | */ | ||
126 | int of_attach_node(struct device_node *np) | ||
127 | { | ||
128 | unsigned long flags; | ||
129 | |||
130 | mutex_lock(&of_mutex); | ||
131 | raw_spin_lock_irqsave(&devtree_lock, flags); | ||
132 | __of_attach_node(np); | ||
133 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | ||
134 | |||
135 | __of_attach_node_sysfs(np); | ||
136 | mutex_unlock(&of_mutex); | ||
137 | |||
138 | of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, np); | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | void __of_detach_node(struct device_node *np) | ||
144 | { | ||
145 | struct device_node *parent; | ||
146 | |||
147 | if (WARN_ON(of_node_check_flag(np, OF_DETACHED))) | ||
148 | return; | ||
149 | |||
150 | parent = np->parent; | ||
151 | if (WARN_ON(!parent)) | ||
152 | return; | ||
153 | |||
154 | if (of_allnodes == np) | ||
155 | of_allnodes = np->allnext; | ||
156 | else { | ||
157 | struct device_node *prev; | ||
158 | for (prev = of_allnodes; | ||
159 | prev->allnext != np; | ||
160 | prev = prev->allnext) | ||
161 | ; | ||
162 | prev->allnext = np->allnext; | ||
163 | } | ||
164 | |||
165 | if (parent->child == np) | ||
166 | parent->child = np->sibling; | ||
167 | else { | ||
168 | struct device_node *prevsib; | ||
169 | for (prevsib = np->parent->child; | ||
170 | prevsib->sibling != np; | ||
171 | prevsib = prevsib->sibling) | ||
172 | ; | ||
173 | prevsib->sibling = np->sibling; | ||
174 | } | ||
175 | |||
176 | of_node_set_flag(np, OF_DETACHED); | ||
177 | } | ||
178 | |||
179 | /** | ||
180 | * of_detach_node() - "Unplug" a node from the device tree. | ||
181 | * | ||
182 | * The caller must hold a reference to the node. The memory associated with | ||
183 | * the node is not freed until its refcount goes to zero. | ||
184 | */ | ||
185 | int of_detach_node(struct device_node *np) | ||
186 | { | ||
187 | unsigned long flags; | ||
188 | int rc = 0; | ||
189 | |||
190 | mutex_lock(&of_mutex); | ||
191 | raw_spin_lock_irqsave(&devtree_lock, flags); | ||
192 | __of_detach_node(np); | ||
193 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | ||
194 | |||
195 | __of_detach_node_sysfs(np); | ||
196 | mutex_unlock(&of_mutex); | ||
197 | |||
198 | of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np); | ||
199 | |||
200 | return rc; | ||
201 | } | ||
202 | |||
203 | /** | ||
204 | * of_node_release() - release a dynamically allocated node | ||
205 | * @kref: kref element of the node to be released | ||
206 | * | ||
207 | * In of_node_put() this function is passed to kref_put() as the destructor. | ||
208 | */ | ||
209 | void of_node_release(struct kobject *kobj) | ||
210 | { | ||
211 | struct device_node *node = kobj_to_device_node(kobj); | ||
212 | struct property *prop = node->properties; | ||
213 | |||
214 | /* We should never be releasing nodes that haven't been detached. */ | ||
215 | if (!of_node_check_flag(node, OF_DETACHED)) { | ||
216 | pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name); | ||
217 | dump_stack(); | ||
218 | return; | ||
219 | } | ||
220 | |||
221 | if (!of_node_check_flag(node, OF_DYNAMIC)) | ||
222 | return; | ||
223 | |||
224 | while (prop) { | ||
225 | struct property *next = prop->next; | ||
226 | kfree(prop->name); | ||
227 | kfree(prop->value); | ||
228 | kfree(prop); | ||
229 | prop = next; | ||
230 | |||
231 | if (!prop) { | ||
232 | prop = node->deadprops; | ||
233 | node->deadprops = NULL; | ||
234 | } | ||
235 | } | ||
236 | kfree(node->full_name); | ||
237 | kfree(node->data); | ||
238 | kfree(node); | ||
239 | } | ||
240 | |||
241 | /** | ||
242 | * __of_prop_dup - Copy a property dynamically. | ||
243 | * @prop: Property to copy | ||
244 | * @allocflags: Allocation flags (typically pass GFP_KERNEL) | ||
245 | * | ||
246 | * Copy a property by dynamically allocating the memory of both the | ||
247 | * property stucture and the property name & contents. The property's | ||
248 | * flags have the OF_DYNAMIC bit set so that we can differentiate between | ||
249 | * dynamically allocated properties and not. | ||
250 | * Returns the newly allocated property or NULL on out of memory error. | ||
251 | */ | ||
252 | struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags) | ||
253 | { | ||
254 | struct property *new; | ||
255 | |||
256 | new = kzalloc(sizeof(*new), allocflags); | ||
257 | if (!new) | ||
258 | return NULL; | ||
259 | |||
260 | /* | ||
261 | * NOTE: There is no check for zero length value. | ||
262 | * In case of a boolean property, this will allocate a value | ||
263 | * of zero bytes. We do this to work around the use | ||
264 | * of of_get_property() calls on boolean values. | ||
265 | */ | ||
266 | new->name = kstrdup(prop->name, allocflags); | ||
267 | new->value = kmemdup(prop->value, prop->length, allocflags); | ||
268 | new->length = prop->length; | ||
269 | if (!new->name || !new->value) | ||
270 | goto err_free; | ||
271 | |||
272 | /* mark the property as dynamic */ | ||
273 | of_property_set_flag(new, OF_DYNAMIC); | ||
274 | |||
275 | return new; | ||
276 | |||
277 | err_free: | ||
278 | kfree(new->name); | ||
279 | kfree(new->value); | ||
280 | kfree(new); | ||
281 | return NULL; | ||
282 | } | ||
283 | |||
284 | /** | ||
285 | * __of_node_alloc() - Create an empty device node dynamically. | ||
286 | * @full_name: Full name of the new device node | ||
287 | * @allocflags: Allocation flags (typically pass GFP_KERNEL) | ||
288 | * | ||
289 | * Create an empty device tree node, suitable for further modification. | ||
290 | * The node data are dynamically allocated and all the node flags | ||
291 | * have the OF_DYNAMIC & OF_DETACHED bits set. | ||
292 | * Returns the newly allocated node or NULL on out of memory error. | ||
293 | */ | ||
294 | struct device_node *__of_node_alloc(const char *full_name, gfp_t allocflags) | ||
295 | { | ||
296 | struct device_node *node; | ||
297 | |||
298 | node = kzalloc(sizeof(*node), allocflags); | ||
299 | if (!node) | ||
300 | return NULL; | ||
301 | |||
302 | node->full_name = kstrdup(full_name, allocflags); | ||
303 | of_node_set_flag(node, OF_DYNAMIC); | ||
304 | of_node_set_flag(node, OF_DETACHED); | ||
305 | if (!node->full_name) | ||
306 | goto err_free; | ||
307 | |||
308 | of_node_init(node); | ||
309 | |||
310 | return node; | ||
311 | |||
312 | err_free: | ||
313 | kfree(node->full_name); | ||
314 | kfree(node); | ||
315 | return NULL; | ||
316 | } | ||
317 | |||
318 | static void __of_changeset_entry_destroy(struct of_changeset_entry *ce) | ||
319 | { | ||
320 | of_node_put(ce->np); | ||
321 | list_del(&ce->node); | ||
322 | kfree(ce); | ||
323 | } | ||
324 | |||
325 | #ifdef DEBUG | ||
326 | static void __of_changeset_entry_dump(struct of_changeset_entry *ce) | ||
327 | { | ||
328 | switch (ce->action) { | ||
329 | case OF_RECONFIG_ADD_PROPERTY: | ||
330 | pr_debug("%p: %s %s/%s\n", | ||
331 | ce, "ADD_PROPERTY ", ce->np->full_name, | ||
332 | ce->prop->name); | ||
333 | break; | ||
334 | case OF_RECONFIG_REMOVE_PROPERTY: | ||
335 | pr_debug("%p: %s %s/%s\n", | ||
336 | ce, "REMOVE_PROPERTY", ce->np->full_name, | ||
337 | ce->prop->name); | ||
338 | break; | ||
339 | case OF_RECONFIG_UPDATE_PROPERTY: | ||
340 | pr_debug("%p: %s %s/%s\n", | ||
341 | ce, "UPDATE_PROPERTY", ce->np->full_name, | ||
342 | ce->prop->name); | ||
343 | break; | ||
344 | case OF_RECONFIG_ATTACH_NODE: | ||
345 | pr_debug("%p: %s %s\n", | ||
346 | ce, "ATTACH_NODE ", ce->np->full_name); | ||
347 | break; | ||
348 | case OF_RECONFIG_DETACH_NODE: | ||
349 | pr_debug("%p: %s %s\n", | ||
350 | ce, "DETACH_NODE ", ce->np->full_name); | ||
351 | break; | ||
352 | } | ||
353 | } | ||
354 | #else | ||
355 | static inline void __of_changeset_entry_dump(struct of_changeset_entry *ce) | ||
356 | { | ||
357 | /* empty */ | ||
358 | } | ||
359 | #endif | ||
360 | |||
361 | static void __of_changeset_entry_invert(struct of_changeset_entry *ce, | ||
362 | struct of_changeset_entry *rce) | ||
363 | { | ||
364 | memcpy(rce, ce, sizeof(*rce)); | ||
365 | |||
366 | switch (ce->action) { | ||
367 | case OF_RECONFIG_ATTACH_NODE: | ||
368 | rce->action = OF_RECONFIG_DETACH_NODE; | ||
369 | break; | ||
370 | case OF_RECONFIG_DETACH_NODE: | ||
371 | rce->action = OF_RECONFIG_ATTACH_NODE; | ||
372 | break; | ||
373 | case OF_RECONFIG_ADD_PROPERTY: | ||
374 | rce->action = OF_RECONFIG_REMOVE_PROPERTY; | ||
375 | break; | ||
376 | case OF_RECONFIG_REMOVE_PROPERTY: | ||
377 | rce->action = OF_RECONFIG_ADD_PROPERTY; | ||
378 | break; | ||
379 | case OF_RECONFIG_UPDATE_PROPERTY: | ||
380 | rce->old_prop = ce->prop; | ||
381 | rce->prop = ce->old_prop; | ||
382 | break; | ||
383 | } | ||
384 | } | ||
385 | |||
386 | static void __of_changeset_entry_notify(struct of_changeset_entry *ce, bool revert) | ||
387 | { | ||
388 | struct of_changeset_entry ce_inverted; | ||
389 | int ret; | ||
390 | |||
391 | if (revert) { | ||
392 | __of_changeset_entry_invert(ce, &ce_inverted); | ||
393 | ce = &ce_inverted; | ||
394 | } | ||
395 | |||
396 | switch (ce->action) { | ||
397 | case OF_RECONFIG_ATTACH_NODE: | ||
398 | case OF_RECONFIG_DETACH_NODE: | ||
399 | ret = of_reconfig_notify(ce->action, ce->np); | ||
400 | break; | ||
401 | case OF_RECONFIG_ADD_PROPERTY: | ||
402 | case OF_RECONFIG_REMOVE_PROPERTY: | ||
403 | case OF_RECONFIG_UPDATE_PROPERTY: | ||
404 | ret = of_property_notify(ce->action, ce->np, ce->prop, ce->old_prop); | ||
405 | break; | ||
406 | default: | ||
407 | pr_err("%s: invalid devicetree changeset action: %i\n", __func__, | ||
408 | (int)ce->action); | ||
409 | return; | ||
410 | } | ||
411 | |||
412 | if (ret) | ||
413 | pr_err("%s: notifier error @%s\n", __func__, ce->np->full_name); | ||
414 | } | ||
415 | |||
416 | static int __of_changeset_entry_apply(struct of_changeset_entry *ce) | ||
417 | { | ||
418 | struct property *old_prop, **propp; | ||
419 | unsigned long flags; | ||
420 | int ret = 0; | ||
421 | |||
422 | __of_changeset_entry_dump(ce); | ||
423 | |||
424 | raw_spin_lock_irqsave(&devtree_lock, flags); | ||
425 | switch (ce->action) { | ||
426 | case OF_RECONFIG_ATTACH_NODE: | ||
427 | __of_attach_node(ce->np); | ||
428 | break; | ||
429 | case OF_RECONFIG_DETACH_NODE: | ||
430 | __of_detach_node(ce->np); | ||
431 | break; | ||
432 | case OF_RECONFIG_ADD_PROPERTY: | ||
433 | /* If the property is in deadprops then it must be removed */ | ||
434 | for (propp = &ce->np->deadprops; *propp; propp = &(*propp)->next) { | ||
435 | if (*propp == ce->prop) { | ||
436 | *propp = ce->prop->next; | ||
437 | ce->prop->next = NULL; | ||
438 | break; | ||
439 | } | ||
440 | } | ||
441 | |||
442 | ret = __of_add_property(ce->np, ce->prop); | ||
443 | if (ret) { | ||
444 | pr_err("%s: add_property failed @%s/%s\n", | ||
445 | __func__, ce->np->full_name, | ||
446 | ce->prop->name); | ||
447 | break; | ||
448 | } | ||
449 | break; | ||
450 | case OF_RECONFIG_REMOVE_PROPERTY: | ||
451 | ret = __of_remove_property(ce->np, ce->prop); | ||
452 | if (ret) { | ||
453 | pr_err("%s: remove_property failed @%s/%s\n", | ||
454 | __func__, ce->np->full_name, | ||
455 | ce->prop->name); | ||
456 | break; | ||
457 | } | ||
458 | break; | ||
459 | |||
460 | case OF_RECONFIG_UPDATE_PROPERTY: | ||
461 | /* If the property is in deadprops then it must be removed */ | ||
462 | for (propp = &ce->np->deadprops; *propp; propp = &(*propp)->next) { | ||
463 | if (*propp == ce->prop) { | ||
464 | *propp = ce->prop->next; | ||
465 | ce->prop->next = NULL; | ||
466 | break; | ||
467 | } | ||
468 | } | ||
469 | |||
470 | ret = __of_update_property(ce->np, ce->prop, &old_prop); | ||
471 | if (ret) { | ||
472 | pr_err("%s: update_property failed @%s/%s\n", | ||
473 | __func__, ce->np->full_name, | ||
474 | ce->prop->name); | ||
475 | break; | ||
476 | } | ||
477 | break; | ||
478 | default: | ||
479 | ret = -EINVAL; | ||
480 | } | ||
481 | raw_spin_unlock_irqrestore(&devtree_lock, flags); | ||
482 | |||
483 | if (ret) | ||
484 | return ret; | ||
485 | |||
486 | switch (ce->action) { | ||
487 | case OF_RECONFIG_ATTACH_NODE: | ||
488 | __of_attach_node_sysfs(ce->np); | ||
489 | break; | ||
490 | case OF_RECONFIG_DETACH_NODE: | ||
491 | __of_detach_node_sysfs(ce->np); | ||
492 | break; | ||
493 | case OF_RECONFIG_ADD_PROPERTY: | ||
494 | /* ignore duplicate names */ | ||
495 | __of_add_property_sysfs(ce->np, ce->prop); | ||
496 | break; | ||
497 | case OF_RECONFIG_REMOVE_PROPERTY: | ||
498 | __of_remove_property_sysfs(ce->np, ce->prop); | ||
499 | break; | ||
500 | case OF_RECONFIG_UPDATE_PROPERTY: | ||
501 | __of_update_property_sysfs(ce->np, ce->prop, ce->old_prop); | ||
502 | break; | ||
503 | } | ||
504 | |||
505 | return 0; | ||
506 | } | ||
507 | |||
508 | static inline int __of_changeset_entry_revert(struct of_changeset_entry *ce) | ||
509 | { | ||
510 | struct of_changeset_entry ce_inverted; | ||
511 | |||
512 | __of_changeset_entry_invert(ce, &ce_inverted); | ||
513 | return __of_changeset_entry_apply(&ce_inverted); | ||
514 | } | ||
515 | |||
516 | /** | ||
517 | * of_changeset_init - Initialize a changeset for use | ||
518 | * | ||
519 | * @ocs: changeset pointer | ||
520 | * | ||
521 | * Initialize a changeset structure | ||
522 | */ | ||
523 | void of_changeset_init(struct of_changeset *ocs) | ||
524 | { | ||
525 | memset(ocs, 0, sizeof(*ocs)); | ||
526 | INIT_LIST_HEAD(&ocs->entries); | ||
527 | } | ||
528 | |||
529 | /** | ||
530 | * of_changeset_destroy - Destroy a changeset | ||
531 | * | ||
532 | * @ocs: changeset pointer | ||
533 | * | ||
534 | * Destroys a changeset. Note that if a changeset is applied, | ||
535 | * its changes to the tree cannot be reverted. | ||
536 | */ | ||
537 | void of_changeset_destroy(struct of_changeset *ocs) | ||
538 | { | ||
539 | struct of_changeset_entry *ce, *cen; | ||
540 | |||
541 | list_for_each_entry_safe_reverse(ce, cen, &ocs->entries, node) | ||
542 | __of_changeset_entry_destroy(ce); | ||
543 | } | ||
544 | |||
545 | /** | ||
546 | * of_changeset_apply - Applies a changeset | ||
547 | * | ||
548 | * @ocs: changeset pointer | ||
549 | * | ||
550 | * Applies a changeset to the live tree. | ||
551 | * Any side-effects of live tree state changes are applied here on | ||
552 | * sucess, like creation/destruction of devices and side-effects | ||
553 | * like creation of sysfs properties and directories. | ||
554 | * Returns 0 on success, a negative error value in case of an error. | ||
555 | * On error the partially applied effects are reverted. | ||
556 | */ | ||
557 | int of_changeset_apply(struct of_changeset *ocs) | ||
558 | { | ||
559 | struct of_changeset_entry *ce; | ||
560 | int ret; | ||
561 | |||
562 | /* perform the rest of the work */ | ||
563 | pr_debug("of_changeset: applying...\n"); | ||
564 | list_for_each_entry(ce, &ocs->entries, node) { | ||
565 | ret = __of_changeset_entry_apply(ce); | ||
566 | if (ret) { | ||
567 | pr_err("%s: Error applying changeset (%d)\n", __func__, ret); | ||
568 | list_for_each_entry_continue_reverse(ce, &ocs->entries, node) | ||
569 | __of_changeset_entry_revert(ce); | ||
570 | return ret; | ||
571 | } | ||
572 | } | ||
573 | pr_debug("of_changeset: applied, emitting notifiers.\n"); | ||
574 | |||
575 | /* drop the global lock while emitting notifiers */ | ||
576 | mutex_unlock(&of_mutex); | ||
577 | list_for_each_entry(ce, &ocs->entries, node) | ||
578 | __of_changeset_entry_notify(ce, 0); | ||
579 | mutex_lock(&of_mutex); | ||
580 | pr_debug("of_changeset: notifiers sent.\n"); | ||
581 | |||
582 | return 0; | ||
583 | } | ||
584 | |||
585 | /** | ||
586 | * of_changeset_revert - Reverts an applied changeset | ||
587 | * | ||
588 | * @ocs: changeset pointer | ||
589 | * | ||
590 | * Reverts a changeset returning the state of the tree to what it | ||
591 | * was before the application. | ||
592 | * Any side-effects like creation/destruction of devices and | ||
593 | * removal of sysfs properties and directories are applied. | ||
594 | * Returns 0 on success, a negative error value in case of an error. | ||
595 | */ | ||
596 | int of_changeset_revert(struct of_changeset *ocs) | ||
597 | { | ||
598 | struct of_changeset_entry *ce; | ||
599 | int ret; | ||
600 | |||
601 | pr_debug("of_changeset: reverting...\n"); | ||
602 | list_for_each_entry_reverse(ce, &ocs->entries, node) { | ||
603 | ret = __of_changeset_entry_revert(ce); | ||
604 | if (ret) { | ||
605 | pr_err("%s: Error reverting changeset (%d)\n", __func__, ret); | ||
606 | list_for_each_entry_continue(ce, &ocs->entries, node) | ||
607 | __of_changeset_entry_apply(ce); | ||
608 | return ret; | ||
609 | } | ||
610 | } | ||
611 | pr_debug("of_changeset: reverted, emitting notifiers.\n"); | ||
612 | |||
613 | /* drop the global lock while emitting notifiers */ | ||
614 | mutex_unlock(&of_mutex); | ||
615 | list_for_each_entry_reverse(ce, &ocs->entries, node) | ||
616 | __of_changeset_entry_notify(ce, 1); | ||
617 | mutex_lock(&of_mutex); | ||
618 | pr_debug("of_changeset: notifiers sent.\n"); | ||
619 | |||
620 | return 0; | ||
621 | } | ||
622 | |||
623 | /** | ||
624 | * of_changeset_action - Perform a changeset action | ||
625 | * | ||
626 | * @ocs: changeset pointer | ||
627 | * @action: action to perform | ||
628 | * @np: Pointer to device node | ||
629 | * @prop: Pointer to property | ||
630 | * | ||
631 | * On action being one of: | ||
632 | * + OF_RECONFIG_ATTACH_NODE | ||
633 | * + OF_RECONFIG_DETACH_NODE, | ||
634 | * + OF_RECONFIG_ADD_PROPERTY | ||
635 | * + OF_RECONFIG_REMOVE_PROPERTY, | ||
636 | * + OF_RECONFIG_UPDATE_PROPERTY | ||
637 | * Returns 0 on success, a negative error value in case of an error. | ||
638 | */ | ||
639 | int of_changeset_action(struct of_changeset *ocs, unsigned long action, | ||
640 | struct device_node *np, struct property *prop) | ||
641 | { | ||
642 | struct of_changeset_entry *ce; | ||
643 | |||
644 | ce = kzalloc(sizeof(*ce), GFP_KERNEL); | ||
645 | if (!ce) { | ||
646 | pr_err("%s: Failed to allocate\n", __func__); | ||
647 | return -ENOMEM; | ||
648 | } | ||
649 | /* get a reference to the node */ | ||
650 | ce->action = action; | ||
651 | ce->np = of_node_get(np); | ||
652 | ce->prop = prop; | ||
653 | |||
654 | if (action == OF_RECONFIG_UPDATE_PROPERTY && prop) | ||
655 | ce->old_prop = of_find_property(np, prop->name, NULL); | ||
656 | |||
657 | /* add it to the list */ | ||
658 | list_add_tail(&ce->node, &ocs->entries); | ||
659 | return 0; | ||
660 | } | ||
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 9aa012e6ea0a..f46a24ffa3fe 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c | |||
@@ -923,24 +923,24 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, | |||
923 | } | 923 | } |
924 | 924 | ||
925 | #ifdef CONFIG_HAVE_MEMBLOCK | 925 | #ifdef CONFIG_HAVE_MEMBLOCK |
926 | #define MAX_PHYS_ADDR ((phys_addr_t)~0) | ||
927 | |||
926 | void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size) | 928 | void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size) |
927 | { | 929 | { |
928 | const u64 phys_offset = __pa(PAGE_OFFSET); | 930 | const u64 phys_offset = __pa(PAGE_OFFSET); |
929 | base &= PAGE_MASK; | 931 | base &= PAGE_MASK; |
930 | size &= PAGE_MASK; | 932 | size &= PAGE_MASK; |
931 | 933 | ||
932 | if (sizeof(phys_addr_t) < sizeof(u64)) { | 934 | if (base > MAX_PHYS_ADDR) { |
933 | if (base > ULONG_MAX) { | 935 | pr_warning("Ignoring memory block 0x%llx - 0x%llx\n", |
934 | pr_warning("Ignoring memory block 0x%llx - 0x%llx\n", | 936 | base, base + size); |
935 | base, base + size); | 937 | return; |
936 | return; | 938 | } |
937 | } | ||
938 | 939 | ||
939 | if (base + size > ULONG_MAX) { | 940 | if (base + size > MAX_PHYS_ADDR) { |
940 | pr_warning("Ignoring memory range 0x%lx - 0x%llx\n", | 941 | pr_warning("Ignoring memory range 0x%lx - 0x%llx\n", |
941 | ULONG_MAX, base + size); | 942 | ULONG_MAX, base + size); |
942 | size = ULONG_MAX - base; | 943 | size = MAX_PHYS_ADDR - base; |
943 | } | ||
944 | } | 944 | } |
945 | 945 | ||
946 | if (base + size < phys_offset) { | 946 | if (base + size < phys_offset) { |
diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h index ff350c8fa7ac..858e0a5d9a11 100644 --- a/drivers/of/of_private.h +++ b/drivers/of/of_private.h | |||
@@ -31,6 +31,63 @@ struct alias_prop { | |||
31 | char stem[0]; | 31 | char stem[0]; |
32 | }; | 32 | }; |
33 | 33 | ||
34 | extern struct mutex of_aliases_mutex; | 34 | extern struct mutex of_mutex; |
35 | extern struct list_head aliases_lookup; | 35 | extern struct list_head aliases_lookup; |
36 | extern struct kset *of_kset; | ||
37 | |||
38 | |||
39 | static inline struct device_node *kobj_to_device_node(struct kobject *kobj) | ||
40 | { | ||
41 | return container_of(kobj, struct device_node, kobj); | ||
42 | } | ||
43 | |||
44 | #if defined(CONFIG_OF_DYNAMIC) | ||
45 | extern int of_property_notify(int action, struct device_node *np, | ||
46 | struct property *prop, struct property *old_prop); | ||
47 | extern void of_node_release(struct kobject *kobj); | ||
48 | #else /* CONFIG_OF_DYNAMIC */ | ||
49 | static inline int of_property_notify(int action, struct device_node *np, | ||
50 | struct property *prop, struct property *old_prop) | ||
51 | { | ||
52 | return 0; | ||
53 | } | ||
54 | #endif /* CONFIG_OF_DYNAMIC */ | ||
55 | |||
56 | /** | ||
57 | * General utilities for working with live trees. | ||
58 | * | ||
59 | * All functions with two leading underscores operate | ||
60 | * without taking node references, so you either have to | ||
61 | * own the devtree lock or work on detached trees only. | ||
62 | */ | ||
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); | ||
65 | |||
66 | extern const void *__of_get_property(const struct device_node *np, | ||
67 | const char *name, int *lenp); | ||
68 | extern int __of_add_property(struct device_node *np, struct property *prop); | ||
69 | extern int __of_add_property_sysfs(struct device_node *np, | ||
70 | struct property *prop); | ||
71 | extern int __of_remove_property(struct device_node *np, struct property *prop); | ||
72 | extern void __of_remove_property_sysfs(struct device_node *np, | ||
73 | struct property *prop); | ||
74 | extern int __of_update_property(struct device_node *np, | ||
75 | struct property *newprop, struct property **oldprop); | ||
76 | extern void __of_update_property_sysfs(struct device_node *np, | ||
77 | struct property *newprop, struct property *oldprop); | ||
78 | |||
79 | extern void __of_attach_node(struct device_node *np); | ||
80 | extern int __of_attach_node_sysfs(struct device_node *np); | ||
81 | extern void __of_detach_node(struct device_node *np); | ||
82 | extern void __of_detach_node_sysfs(struct device_node *np); | ||
83 | |||
84 | /* iterators for transactions, used for overlays */ | ||
85 | /* forward iterator */ | ||
86 | #define for_each_transaction_entry(_oft, _te) \ | ||
87 | list_for_each_entry(_te, &(_oft)->te_list, node) | ||
88 | |||
89 | /* reverse iterator */ | ||
90 | #define for_each_transaction_entry_reverse(_oft, _te) \ | ||
91 | list_for_each_entry_reverse(_te, &(_oft)->te_list, node) | ||
92 | |||
36 | #endif /* _LINUX_OF_PRIVATE_H */ | 93 | #endif /* _LINUX_OF_PRIVATE_H */ |
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 632aae861375..59fb12e84e6b 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c | |||
@@ -206,8 +206,16 @@ void __init fdt_init_reserved_mem(void) | |||
206 | for (i = 0; i < reserved_mem_count; i++) { | 206 | for (i = 0; i < reserved_mem_count; i++) { |
207 | struct reserved_mem *rmem = &reserved_mem[i]; | 207 | struct reserved_mem *rmem = &reserved_mem[i]; |
208 | unsigned long node = rmem->fdt_node; | 208 | unsigned long node = rmem->fdt_node; |
209 | int len; | ||
210 | const __be32 *prop; | ||
209 | int err = 0; | 211 | int err = 0; |
210 | 212 | ||
213 | prop = of_get_flat_dt_prop(node, "phandle", &len); | ||
214 | if (!prop) | ||
215 | prop = of_get_flat_dt_prop(node, "linux,phandle", &len); | ||
216 | if (prop) | ||
217 | rmem->phandle = of_read_number(prop, len/4); | ||
218 | |||
211 | if (rmem->size == 0) | 219 | if (rmem->size == 0) |
212 | err = __reserved_mem_alloc_size(node, rmem->name, | 220 | err = __reserved_mem_alloc_size(node, rmem->name, |
213 | &rmem->base, &rmem->size); | 221 | &rmem->base, &rmem->size); |
@@ -215,3 +223,65 @@ void __init fdt_init_reserved_mem(void) | |||
215 | __reserved_mem_init_node(rmem); | 223 | __reserved_mem_init_node(rmem); |
216 | } | 224 | } |
217 | } | 225 | } |
226 | |||
227 | static inline struct reserved_mem *__find_rmem(struct device_node *node) | ||
228 | { | ||
229 | unsigned int i; | ||
230 | |||
231 | if (!node->phandle) | ||
232 | return NULL; | ||
233 | |||
234 | for (i = 0; i < reserved_mem_count; i++) | ||
235 | if (reserved_mem[i].phandle == node->phandle) | ||
236 | return &reserved_mem[i]; | ||
237 | return NULL; | ||
238 | } | ||
239 | |||
240 | /** | ||
241 | * of_reserved_mem_device_init() - assign reserved memory region to given device | ||
242 | * | ||
243 | * This function assign memory region pointed by "memory-region" device tree | ||
244 | * property to the given device. | ||
245 | */ | ||
246 | void of_reserved_mem_device_init(struct device *dev) | ||
247 | { | ||
248 | struct reserved_mem *rmem; | ||
249 | struct device_node *np; | ||
250 | |||
251 | np = of_parse_phandle(dev->of_node, "memory-region", 0); | ||
252 | if (!np) | ||
253 | return; | ||
254 | |||
255 | rmem = __find_rmem(np); | ||
256 | of_node_put(np); | ||
257 | |||
258 | if (!rmem || !rmem->ops || !rmem->ops->device_init) | ||
259 | return; | ||
260 | |||
261 | rmem->ops->device_init(rmem, dev); | ||
262 | dev_info(dev, "assigned reserved memory node %s\n", rmem->name); | ||
263 | } | ||
264 | |||
265 | /** | ||
266 | * of_reserved_mem_device_release() - release reserved memory device structures | ||
267 | * | ||
268 | * This function releases structures allocated for memory region handling for | ||
269 | * the given device. | ||
270 | */ | ||
271 | void of_reserved_mem_device_release(struct device *dev) | ||
272 | { | ||
273 | struct reserved_mem *rmem; | ||
274 | struct device_node *np; | ||
275 | |||
276 | np = of_parse_phandle(dev->of_node, "memory-region", 0); | ||
277 | if (!np) | ||
278 | return; | ||
279 | |||
280 | rmem = __find_rmem(np); | ||
281 | of_node_put(np); | ||
282 | |||
283 | if (!rmem || !rmem->ops || !rmem->ops->device_release) | ||
284 | return; | ||
285 | |||
286 | rmem->ops->device_release(rmem, dev); | ||
287 | } | ||
diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 500436f9be7f..0197725e033a 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c | |||
@@ -422,6 +422,7 @@ static int of_platform_bus_create(struct device_node *bus, | |||
422 | break; | 422 | break; |
423 | } | 423 | } |
424 | } | 424 | } |
425 | of_node_set_flag(bus, OF_POPULATED_BUS); | ||
425 | return rc; | 426 | return rc; |
426 | } | 427 | } |
427 | 428 | ||
@@ -508,19 +509,13 @@ EXPORT_SYMBOL_GPL(of_platform_populate); | |||
508 | 509 | ||
509 | static int of_platform_device_destroy(struct device *dev, void *data) | 510 | static int of_platform_device_destroy(struct device *dev, void *data) |
510 | { | 511 | { |
511 | bool *children_left = data; | ||
512 | |||
513 | /* Do not touch devices not populated from the device tree */ | 512 | /* Do not touch devices not populated from the device tree */ |
514 | if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED)) { | 513 | if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED)) |
515 | *children_left = true; | ||
516 | return 0; | 514 | return 0; |
517 | } | ||
518 | 515 | ||
519 | /* Recurse, but don't touch this device if it has any children left */ | 516 | /* Recurse for any nodes that were treated as busses */ |
520 | if (of_platform_depopulate(dev) != 0) { | 517 | if (of_node_check_flag(dev->of_node, OF_POPULATED_BUS)) |
521 | *children_left = true; | 518 | device_for_each_child(dev, NULL, of_platform_device_destroy); |
522 | return 0; | ||
523 | } | ||
524 | 519 | ||
525 | if (dev->bus == &platform_bus_type) | 520 | if (dev->bus == &platform_bus_type) |
526 | platform_device_unregister(to_platform_device(dev)); | 521 | platform_device_unregister(to_platform_device(dev)); |
@@ -528,19 +523,15 @@ static int of_platform_device_destroy(struct device *dev, void *data) | |||
528 | else if (dev->bus == &amba_bustype) | 523 | else if (dev->bus == &amba_bustype) |
529 | amba_device_unregister(to_amba_device(dev)); | 524 | amba_device_unregister(to_amba_device(dev)); |
530 | #endif | 525 | #endif |
531 | else { | ||
532 | *children_left = true; | ||
533 | return 0; | ||
534 | } | ||
535 | 526 | ||
536 | of_node_clear_flag(dev->of_node, OF_POPULATED); | 527 | of_node_clear_flag(dev->of_node, OF_POPULATED); |
537 | 528 | of_node_clear_flag(dev->of_node, OF_POPULATED_BUS); | |
538 | return 0; | 529 | return 0; |
539 | } | 530 | } |
540 | 531 | ||
541 | /** | 532 | /** |
542 | * of_platform_depopulate() - Remove devices populated from device tree | 533 | * of_platform_depopulate() - Remove devices populated from device tree |
543 | * @parent: device which childred will be removed | 534 | * @parent: device which children will be removed |
544 | * | 535 | * |
545 | * Complementary to of_platform_populate(), this function removes children | 536 | * Complementary to of_platform_populate(), this function removes children |
546 | * of the given device (and, recurrently, their children) that have been | 537 | * of the given device (and, recurrently, their children) that have been |
@@ -550,14 +541,9 @@ static int of_platform_device_destroy(struct device *dev, void *data) | |||
550 | * Returns 0 when all children devices have been removed or | 541 | * Returns 0 when all children devices have been removed or |
551 | * -EBUSY when some children remained. | 542 | * -EBUSY when some children remained. |
552 | */ | 543 | */ |
553 | int of_platform_depopulate(struct device *parent) | 544 | void of_platform_depopulate(struct device *parent) |
554 | { | 545 | { |
555 | bool children_left = false; | 546 | device_for_each_child(parent, NULL, of_platform_device_destroy); |
556 | |||
557 | device_for_each_child(parent, &children_left, | ||
558 | of_platform_device_destroy); | ||
559 | |||
560 | return children_left ? -EBUSY : 0; | ||
561 | } | 547 | } |
562 | EXPORT_SYMBOL_GPL(of_platform_depopulate); | 548 | EXPORT_SYMBOL_GPL(of_platform_depopulate); |
563 | 549 | ||
diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c index 077314eebb95..d41002667833 100644 --- a/drivers/of/selftest.c +++ b/drivers/of/selftest.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/errno.h> | 9 | #include <linux/errno.h> |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/of.h> | 11 | #include <linux/of.h> |
12 | #include <linux/of_fdt.h> | ||
12 | #include <linux/of_irq.h> | 13 | #include <linux/of_irq.h> |
13 | #include <linux/of_platform.h> | 14 | #include <linux/of_platform.h> |
14 | #include <linux/list.h> | 15 | #include <linux/list.h> |
@@ -16,11 +17,17 @@ | |||
16 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
17 | #include <linux/device.h> | 18 | #include <linux/device.h> |
18 | 19 | ||
20 | #include "of_private.h" | ||
21 | |||
19 | static struct selftest_results { | 22 | static struct selftest_results { |
20 | int passed; | 23 | int passed; |
21 | int failed; | 24 | int failed; |
22 | } selftest_results; | 25 | } selftest_results; |
23 | 26 | ||
27 | #define NO_OF_NODES 2 | ||
28 | static struct device_node *nodes[NO_OF_NODES]; | ||
29 | static int last_node_index; | ||
30 | |||
24 | #define selftest(result, fmt, ...) { \ | 31 | #define selftest(result, fmt, ...) { \ |
25 | if (!(result)) { \ | 32 | if (!(result)) { \ |
26 | selftest_results.failed++; \ | 33 | selftest_results.failed++; \ |
@@ -266,6 +273,81 @@ static void __init of_selftest_property_match_string(void) | |||
266 | selftest(rc == -EILSEQ, "unterminated string; rc=%i", rc); | 273 | selftest(rc == -EILSEQ, "unterminated string; rc=%i", rc); |
267 | } | 274 | } |
268 | 275 | ||
276 | #define propcmp(p1, p2) (((p1)->length == (p2)->length) && \ | ||
277 | (p1)->value && (p2)->value && \ | ||
278 | !memcmp((p1)->value, (p2)->value, (p1)->length) && \ | ||
279 | !strcmp((p1)->name, (p2)->name)) | ||
280 | static void __init of_selftest_property_copy(void) | ||
281 | { | ||
282 | #ifdef CONFIG_OF_DYNAMIC | ||
283 | struct property p1 = { .name = "p1", .length = 0, .value = "" }; | ||
284 | struct property p2 = { .name = "p2", .length = 5, .value = "abcd" }; | ||
285 | struct property *new; | ||
286 | |||
287 | new = __of_prop_dup(&p1, GFP_KERNEL); | ||
288 | selftest(new && propcmp(&p1, new), "empty property didn't copy correctly\n"); | ||
289 | kfree(new->value); | ||
290 | kfree(new->name); | ||
291 | kfree(new); | ||
292 | |||
293 | new = __of_prop_dup(&p2, GFP_KERNEL); | ||
294 | selftest(new && propcmp(&p2, new), "non-empty property didn't copy correctly\n"); | ||
295 | kfree(new->value); | ||
296 | kfree(new->name); | ||
297 | kfree(new); | ||
298 | #endif | ||
299 | } | ||
300 | |||
301 | static void __init of_selftest_changeset(void) | ||
302 | { | ||
303 | #ifdef CONFIG_OF_DYNAMIC | ||
304 | struct property *ppadd, padd = { .name = "prop-add", .length = 0, .value = "" }; | ||
305 | struct property *ppupdate, pupdate = { .name = "prop-update", .length = 5, .value = "abcd" }; | ||
306 | struct property *ppremove; | ||
307 | struct device_node *n1, *n2, *n21, *nremove, *parent; | ||
308 | struct of_changeset chgset; | ||
309 | |||
310 | of_changeset_init(&chgset); | ||
311 | n1 = __of_node_alloc("/testcase-data/changeset/n1", GFP_KERNEL); | ||
312 | selftest(n1, "testcase setup failure\n"); | ||
313 | n2 = __of_node_alloc("/testcase-data/changeset/n2", GFP_KERNEL); | ||
314 | selftest(n2, "testcase setup failure\n"); | ||
315 | n21 = __of_node_alloc("/testcase-data/changeset/n2/n21", GFP_KERNEL); | ||
316 | selftest(n21, "testcase setup failure %p\n", n21); | ||
317 | nremove = of_find_node_by_path("/testcase-data/changeset/node-remove"); | ||
318 | selftest(nremove, "testcase setup failure\n"); | ||
319 | ppadd = __of_prop_dup(&padd, GFP_KERNEL); | ||
320 | selftest(ppadd, "testcase setup failure\n"); | ||
321 | ppupdate = __of_prop_dup(&pupdate, GFP_KERNEL); | ||
322 | selftest(ppupdate, "testcase setup failure\n"); | ||
323 | parent = nremove->parent; | ||
324 | n1->parent = parent; | ||
325 | n2->parent = parent; | ||
326 | n21->parent = n2; | ||
327 | n2->child = n21; | ||
328 | ppremove = of_find_property(parent, "prop-remove", NULL); | ||
329 | selftest(ppremove, "failed to find removal prop"); | ||
330 | |||
331 | of_changeset_init(&chgset); | ||
332 | selftest(!of_changeset_attach_node(&chgset, n1), "fail attach n1\n"); | ||
333 | selftest(!of_changeset_attach_node(&chgset, n2), "fail attach n2\n"); | ||
334 | selftest(!of_changeset_detach_node(&chgset, nremove), "fail remove node\n"); | ||
335 | selftest(!of_changeset_attach_node(&chgset, n21), "fail attach n21\n"); | ||
336 | selftest(!of_changeset_add_property(&chgset, parent, ppadd), "fail add prop\n"); | ||
337 | selftest(!of_changeset_update_property(&chgset, parent, ppupdate), "fail update prop\n"); | ||
338 | selftest(!of_changeset_remove_property(&chgset, parent, ppremove), "fail remove prop\n"); | ||
339 | mutex_lock(&of_mutex); | ||
340 | selftest(!of_changeset_apply(&chgset), "apply failed\n"); | ||
341 | mutex_unlock(&of_mutex); | ||
342 | |||
343 | mutex_lock(&of_mutex); | ||
344 | selftest(!of_changeset_revert(&chgset), "revert failed\n"); | ||
345 | mutex_unlock(&of_mutex); | ||
346 | |||
347 | of_changeset_destroy(&chgset); | ||
348 | #endif | ||
349 | } | ||
350 | |||
269 | static void __init of_selftest_parse_interrupts(void) | 351 | static void __init of_selftest_parse_interrupts(void) |
270 | { | 352 | { |
271 | struct device_node *np; | 353 | struct device_node *np; |
@@ -517,9 +599,156 @@ static void __init of_selftest_platform_populate(void) | |||
517 | } | 599 | } |
518 | } | 600 | } |
519 | 601 | ||
602 | /** | ||
603 | * update_node_properties - adds the properties | ||
604 | * of np into dup node (present in live tree) and | ||
605 | * updates parent of children of np to dup. | ||
606 | * | ||
607 | * @np: node already present in live tree | ||
608 | * @dup: node present in live tree to be updated | ||
609 | */ | ||
610 | static void update_node_properties(struct device_node *np, | ||
611 | struct device_node *dup) | ||
612 | { | ||
613 | struct property *prop; | ||
614 | struct device_node *child; | ||
615 | |||
616 | for_each_property_of_node(np, prop) | ||
617 | of_add_property(dup, prop); | ||
618 | |||
619 | for_each_child_of_node(np, child) | ||
620 | child->parent = dup; | ||
621 | } | ||
622 | |||
623 | /** | ||
624 | * attach_node_and_children - attaches nodes | ||
625 | * and its children to live tree | ||
626 | * | ||
627 | * @np: Node to attach to live tree | ||
628 | */ | ||
629 | static int attach_node_and_children(struct device_node *np) | ||
630 | { | ||
631 | struct device_node *next, *root = np, *dup; | ||
632 | |||
633 | if (!np) { | ||
634 | pr_warn("%s: No tree to attach; not running tests\n", | ||
635 | __func__); | ||
636 | return -ENODATA; | ||
637 | } | ||
638 | |||
639 | |||
640 | /* skip root node */ | ||
641 | np = np->child; | ||
642 | /* storing a copy in temporary node */ | ||
643 | dup = np; | ||
644 | |||
645 | while (dup) { | ||
646 | nodes[last_node_index++] = dup; | ||
647 | dup = dup->sibling; | ||
648 | } | ||
649 | dup = NULL; | ||
650 | |||
651 | while (np) { | ||
652 | next = np->allnext; | ||
653 | dup = of_find_node_by_path(np->full_name); | ||
654 | if (dup) | ||
655 | update_node_properties(np, dup); | ||
656 | else { | ||
657 | np->child = NULL; | ||
658 | if (np->parent == root) | ||
659 | np->parent = of_allnodes; | ||
660 | of_attach_node(np); | ||
661 | } | ||
662 | np = next; | ||
663 | } | ||
664 | |||
665 | return 0; | ||
666 | } | ||
667 | |||
668 | /** | ||
669 | * selftest_data_add - Reads, copies data from | ||
670 | * linked tree and attaches it to the live tree | ||
671 | */ | ||
672 | static int __init selftest_data_add(void) | ||
673 | { | ||
674 | void *selftest_data; | ||
675 | struct device_node *selftest_data_node; | ||
676 | extern uint8_t __dtb_testcases_begin[]; | ||
677 | extern uint8_t __dtb_testcases_end[]; | ||
678 | const int size = __dtb_testcases_end - __dtb_testcases_begin; | ||
679 | |||
680 | if (!size || !of_allnodes) { | ||
681 | pr_warn("%s: No testcase data to attach; not running tests\n", | ||
682 | __func__); | ||
683 | return -ENODATA; | ||
684 | } | ||
685 | |||
686 | /* creating copy */ | ||
687 | selftest_data = kmemdup(__dtb_testcases_begin, size, GFP_KERNEL); | ||
688 | |||
689 | if (!selftest_data) { | ||
690 | pr_warn("%s: Failed to allocate memory for selftest_data; " | ||
691 | "not running tests\n", __func__); | ||
692 | return -ENOMEM; | ||
693 | } | ||
694 | of_fdt_unflatten_tree(selftest_data, &selftest_data_node); | ||
695 | |||
696 | /* attach the sub-tree to live tree */ | ||
697 | return attach_node_and_children(selftest_data_node); | ||
698 | } | ||
699 | |||
700 | /** | ||
701 | * detach_node_and_children - detaches node | ||
702 | * and its children from live tree | ||
703 | * | ||
704 | * @np: Node to detach from live tree | ||
705 | */ | ||
706 | static void detach_node_and_children(struct device_node *np) | ||
707 | { | ||
708 | while (np->child) | ||
709 | detach_node_and_children(np->child); | ||
710 | |||
711 | while (np->sibling) | ||
712 | detach_node_and_children(np->sibling); | ||
713 | |||
714 | of_detach_node(np); | ||
715 | } | ||
716 | |||
717 | /** | ||
718 | * selftest_data_remove - removes the selftest data | ||
719 | * nodes from the live tree | ||
720 | */ | ||
721 | static void selftest_data_remove(void) | ||
722 | { | ||
723 | struct device_node *np; | ||
724 | struct property *prop; | ||
725 | |||
726 | while (last_node_index >= 0) { | ||
727 | if (nodes[last_node_index]) { | ||
728 | np = of_find_node_by_path(nodes[last_node_index]->full_name); | ||
729 | if (strcmp(np->full_name, "/aliases") != 0) { | ||
730 | detach_node_and_children(np->child); | ||
731 | of_detach_node(np); | ||
732 | } else { | ||
733 | for_each_property_of_node(np, prop) { | ||
734 | if (strcmp(prop->name, "testcase-alias") == 0) | ||
735 | of_remove_property(np, prop); | ||
736 | } | ||
737 | } | ||
738 | } | ||
739 | last_node_index--; | ||
740 | } | ||
741 | } | ||
742 | |||
520 | static int __init of_selftest(void) | 743 | static int __init of_selftest(void) |
521 | { | 744 | { |
522 | struct device_node *np; | 745 | struct device_node *np; |
746 | int res; | ||
747 | |||
748 | /* adding data for selftest */ | ||
749 | res = selftest_data_add(); | ||
750 | if (res) | ||
751 | return res; | ||
523 | 752 | ||
524 | np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a"); | 753 | np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a"); |
525 | if (!np) { | 754 | if (!np) { |
@@ -533,12 +762,18 @@ static int __init of_selftest(void) | |||
533 | of_selftest_dynamic(); | 762 | of_selftest_dynamic(); |
534 | of_selftest_parse_phandle_with_args(); | 763 | of_selftest_parse_phandle_with_args(); |
535 | of_selftest_property_match_string(); | 764 | of_selftest_property_match_string(); |
765 | of_selftest_property_copy(); | ||
766 | of_selftest_changeset(); | ||
536 | of_selftest_parse_interrupts(); | 767 | of_selftest_parse_interrupts(); |
537 | of_selftest_parse_interrupts_extended(); | 768 | of_selftest_parse_interrupts_extended(); |
538 | of_selftest_match_node(); | 769 | of_selftest_match_node(); |
539 | of_selftest_platform_populate(); | 770 | of_selftest_platform_populate(); |
540 | pr_info("end of selftest - %i passed, %i failed\n", | 771 | pr_info("end of selftest - %i passed, %i failed\n", |
541 | selftest_results.passed, selftest_results.failed); | 772 | selftest_results.passed, selftest_results.failed); |
773 | |||
774 | /* removing selftest data from live tree */ | ||
775 | selftest_data_remove(); | ||
776 | |||
542 | return 0; | 777 | return 0; |
543 | } | 778 | } |
544 | late_initcall(of_selftest); | 779 | late_initcall(of_selftest); |
diff --git a/drivers/of/testcase-data/testcases.dts b/drivers/of/testcase-data/testcases.dts new file mode 100644 index 000000000000..219ef9324e9c --- /dev/null +++ b/drivers/of/testcase-data/testcases.dts | |||
@@ -0,0 +1,15 @@ | |||
1 | /dts-v1/; | ||
2 | / { | ||
3 | testcase-data { | ||
4 | changeset { | ||
5 | prop-update = "hello"; | ||
6 | prop-remove = "world"; | ||
7 | node-remove { | ||
8 | }; | ||
9 | }; | ||
10 | }; | ||
11 | }; | ||
12 | #include "tests-phandle.dtsi" | ||
13 | #include "tests-interrupts.dtsi" | ||
14 | #include "tests-match.dtsi" | ||
15 | #include "tests-platform.dtsi" | ||
diff --git a/drivers/of/testcase-data/testcases.dtsi b/drivers/of/testcase-data/testcases.dtsi deleted file mode 100644 index 6d8d980ac858..000000000000 --- a/drivers/of/testcase-data/testcases.dtsi +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | #include "tests-phandle.dtsi" | ||
2 | #include "tests-interrupts.dtsi" | ||
3 | #include "tests-match.dtsi" | ||
4 | #include "tests-platform.dtsi" | ||
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index 93aa29f6d39c..f2945fa73d4f 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c | |||
@@ -375,11 +375,11 @@ static void __exit cleanup_slots(void) | |||
375 | 375 | ||
376 | static int __init rpaphp_init(void) | 376 | static int __init rpaphp_init(void) |
377 | { | 377 | { |
378 | struct device_node *dn = NULL; | 378 | struct device_node *dn; |
379 | 379 | ||
380 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); | 380 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); |
381 | 381 | ||
382 | while ((dn = of_find_node_by_name(dn, "pci"))) | 382 | for_each_node_by_name(dn, "pci") |
383 | rpaphp_add_slot(dn); | 383 | rpaphp_add_slot(dn); |
384 | 384 | ||
385 | return 0; | 385 | return 0; |
diff --git a/drivers/tty/ehv_bytechan.c b/drivers/tty/ehv_bytechan.c index 0419b69e270f..4f485e88f60c 100644 --- a/drivers/tty/ehv_bytechan.c +++ b/drivers/tty/ehv_bytechan.c | |||
@@ -108,55 +108,23 @@ static void disable_tx_interrupt(struct ehv_bc_data *bc) | |||
108 | * | 108 | * |
109 | * The byte channel to be used for the console is specified via a "stdout" | 109 | * The byte channel to be used for the console is specified via a "stdout" |
110 | * property in the /chosen node. | 110 | * property in the /chosen node. |
111 | * | ||
112 | * For compatible with legacy device trees, we also look for a "stdout" alias. | ||
113 | */ | 111 | */ |
114 | static int find_console_handle(void) | 112 | static int find_console_handle(void) |
115 | { | 113 | { |
116 | struct device_node *np, *np2; | 114 | struct device_node *np = of_stdout; |
117 | const char *sprop = NULL; | 115 | const char *sprop = NULL; |
118 | const uint32_t *iprop; | 116 | const uint32_t *iprop; |
119 | 117 | ||
120 | np = of_find_node_by_path("/chosen"); | ||
121 | if (np) | ||
122 | sprop = of_get_property(np, "stdout-path", NULL); | ||
123 | |||
124 | if (!np || !sprop) { | ||
125 | of_node_put(np); | ||
126 | np = of_find_node_by_name(NULL, "aliases"); | ||
127 | if (np) | ||
128 | sprop = of_get_property(np, "stdout", NULL); | ||
129 | } | ||
130 | |||
131 | if (!sprop) { | ||
132 | of_node_put(np); | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | /* We don't care what the aliased node is actually called. We only | 118 | /* We don't care what the aliased node is actually called. We only |
137 | * care if it's compatible with "epapr,hv-byte-channel", because that | 119 | * care if it's compatible with "epapr,hv-byte-channel", because that |
138 | * indicates that it's a byte channel node. We use a temporary | 120 | * indicates that it's a byte channel node. |
139 | * variable, 'np2', because we can't release 'np' until we're done with | ||
140 | * 'sprop'. | ||
141 | */ | 121 | */ |
142 | np2 = of_find_node_by_path(sprop); | 122 | if (!np || !of_device_is_compatible(np, "epapr,hv-byte-channel")) |
143 | of_node_put(np); | ||
144 | np = np2; | ||
145 | if (!np) { | ||
146 | pr_warning("ehv-bc: stdout node '%s' does not exist\n", sprop); | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | /* Is it a byte channel? */ | ||
151 | if (!of_device_is_compatible(np, "epapr,hv-byte-channel")) { | ||
152 | of_node_put(np); | ||
153 | return 0; | 123 | return 0; |
154 | } | ||
155 | 124 | ||
156 | stdout_irq = irq_of_parse_and_map(np, 0); | 125 | stdout_irq = irq_of_parse_and_map(np, 0); |
157 | if (stdout_irq == NO_IRQ) { | 126 | if (stdout_irq == NO_IRQ) { |
158 | pr_err("ehv-bc: no 'interrupts' property in %s node\n", sprop); | 127 | pr_err("ehv-bc: no 'interrupts' property in %s node\n", np->full_name); |
159 | of_node_put(np); | ||
160 | return 0; | 128 | return 0; |
161 | } | 129 | } |
162 | 130 | ||
@@ -167,12 +135,9 @@ static int find_console_handle(void) | |||
167 | if (!iprop) { | 135 | if (!iprop) { |
168 | pr_err("ehv-bc: no 'hv-handle' property in %s node\n", | 136 | pr_err("ehv-bc: no 'hv-handle' property in %s node\n", |
169 | np->name); | 137 | np->name); |
170 | of_node_put(np); | ||
171 | return 0; | 138 | return 0; |
172 | } | 139 | } |
173 | stdout_bc = be32_to_cpu(*iprop); | 140 | stdout_bc = be32_to_cpu(*iprop); |
174 | |||
175 | of_node_put(np); | ||
176 | return 1; | 141 | return 1; |
177 | } | 142 | } |
178 | 143 | ||
diff --git a/drivers/tty/hvc/hvc_opal.c b/drivers/tty/hvc/hvc_opal.c index a585079b4b38..a2cc5f834c63 100644 --- a/drivers/tty/hvc/hvc_opal.c +++ b/drivers/tty/hvc/hvc_opal.c | |||
@@ -342,22 +342,13 @@ static void udbg_init_opal_common(void) | |||
342 | 342 | ||
343 | void __init hvc_opal_init_early(void) | 343 | void __init hvc_opal_init_early(void) |
344 | { | 344 | { |
345 | struct device_node *stdout_node = NULL; | 345 | struct device_node *stdout_node = of_node_get(of_stdout); |
346 | const __be32 *termno; | 346 | const __be32 *termno; |
347 | const char *name = NULL; | ||
348 | const struct hv_ops *ops; | 347 | const struct hv_ops *ops; |
349 | u32 index; | 348 | u32 index; |
350 | 349 | ||
351 | /* find the boot console from /chosen/stdout */ | 350 | /* If the console wasn't in /chosen, try /ibm,opal */ |
352 | if (of_chosen) | 351 | if (!stdout_node) { |
353 | name = of_get_property(of_chosen, "linux,stdout-path", NULL); | ||
354 | if (name) { | ||
355 | stdout_node = of_find_node_by_path(name); | ||
356 | if (!stdout_node) { | ||
357 | pr_err("hvc_opal: Failed to locate default console!\n"); | ||
358 | return; | ||
359 | } | ||
360 | } else { | ||
361 | struct device_node *opal, *np; | 352 | struct device_node *opal, *np; |
362 | 353 | ||
363 | /* Current OPAL takeover doesn't provide the stdout | 354 | /* Current OPAL takeover doesn't provide the stdout |
diff --git a/drivers/tty/hvc/hvc_vio.c b/drivers/tty/hvc/hvc_vio.c index b594abfbf21e..5618b5fc7500 100644 --- a/drivers/tty/hvc/hvc_vio.c +++ b/drivers/tty/hvc/hvc_vio.c | |||
@@ -404,42 +404,35 @@ module_exit(hvc_vio_exit); | |||
404 | 404 | ||
405 | void __init hvc_vio_init_early(void) | 405 | void __init hvc_vio_init_early(void) |
406 | { | 406 | { |
407 | struct device_node *stdout_node; | ||
408 | const __be32 *termno; | 407 | const __be32 *termno; |
409 | const char *name; | 408 | const char *name; |
410 | const struct hv_ops *ops; | 409 | const struct hv_ops *ops; |
411 | 410 | ||
412 | /* find the boot console from /chosen/stdout */ | 411 | /* find the boot console from /chosen/stdout */ |
413 | if (!of_chosen) | 412 | if (!of_stdout) |
414 | return; | 413 | return; |
415 | name = of_get_property(of_chosen, "linux,stdout-path", NULL); | 414 | name = of_get_property(of_stdout, "name", NULL); |
416 | if (name == NULL) | ||
417 | return; | ||
418 | stdout_node = of_find_node_by_path(name); | ||
419 | if (!stdout_node) | ||
420 | return; | ||
421 | name = of_get_property(stdout_node, "name", NULL); | ||
422 | if (!name) { | 415 | if (!name) { |
423 | printk(KERN_WARNING "stdout node missing 'name' property!\n"); | 416 | printk(KERN_WARNING "stdout node missing 'name' property!\n"); |
424 | goto out; | 417 | return; |
425 | } | 418 | } |
426 | 419 | ||
427 | /* Check if it's a virtual terminal */ | 420 | /* Check if it's a virtual terminal */ |
428 | if (strncmp(name, "vty", 3) != 0) | 421 | if (strncmp(name, "vty", 3) != 0) |
429 | goto out; | 422 | return; |
430 | termno = of_get_property(stdout_node, "reg", NULL); | 423 | termno = of_get_property(of_stdout, "reg", NULL); |
431 | if (termno == NULL) | 424 | if (termno == NULL) |
432 | goto out; | 425 | return; |
433 | hvterm_priv0.termno = of_read_number(termno, 1); | 426 | hvterm_priv0.termno = of_read_number(termno, 1); |
434 | spin_lock_init(&hvterm_priv0.buf_lock); | 427 | spin_lock_init(&hvterm_priv0.buf_lock); |
435 | hvterm_privs[0] = &hvterm_priv0; | 428 | hvterm_privs[0] = &hvterm_priv0; |
436 | 429 | ||
437 | /* Check the protocol */ | 430 | /* Check the protocol */ |
438 | if (of_device_is_compatible(stdout_node, "hvterm1")) { | 431 | if (of_device_is_compatible(of_stdout, "hvterm1")) { |
439 | hvterm_priv0.proto = HV_PROTOCOL_RAW; | 432 | hvterm_priv0.proto = HV_PROTOCOL_RAW; |
440 | ops = &hvterm_raw_ops; | 433 | ops = &hvterm_raw_ops; |
441 | } | 434 | } |
442 | else if (of_device_is_compatible(stdout_node, "hvterm-protocol")) { | 435 | else if (of_device_is_compatible(of_stdout, "hvterm-protocol")) { |
443 | hvterm_priv0.proto = HV_PROTOCOL_HVSI; | 436 | hvterm_priv0.proto = HV_PROTOCOL_HVSI; |
444 | ops = &hvterm_hvsi_ops; | 437 | ops = &hvterm_hvsi_ops; |
445 | hvsilib_init(&hvterm_priv0.hvsi, hvc_get_chars, hvc_put_chars, | 438 | hvsilib_init(&hvterm_priv0.hvsi, hvc_get_chars, hvc_put_chars, |
@@ -447,7 +440,7 @@ void __init hvc_vio_init_early(void) | |||
447 | /* HVSI, perform the handshake now */ | 440 | /* HVSI, perform the handshake now */ |
448 | hvsilib_establish(&hvterm_priv0.hvsi); | 441 | hvsilib_establish(&hvterm_priv0.hvsi); |
449 | } else | 442 | } else |
450 | goto out; | 443 | return; |
451 | udbg_putc = udbg_hvc_putc; | 444 | udbg_putc = udbg_hvc_putc; |
452 | udbg_getc = udbg_hvc_getc; | 445 | udbg_getc = udbg_hvc_getc; |
453 | udbg_getc_poll = udbg_hvc_getc_poll; | 446 | udbg_getc_poll = udbg_hvc_getc_poll; |
@@ -456,14 +449,12 @@ void __init hvc_vio_init_early(void) | |||
456 | * backend for HVSI, only do udbg | 449 | * backend for HVSI, only do udbg |
457 | */ | 450 | */ |
458 | if (hvterm_priv0.proto == HV_PROTOCOL_HVSI) | 451 | if (hvterm_priv0.proto == HV_PROTOCOL_HVSI) |
459 | goto out; | 452 | return; |
460 | #endif | 453 | #endif |
461 | /* Check whether the user has requested a different console. */ | 454 | /* Check whether the user has requested a different console. */ |
462 | if (!strstr(cmd_line, "console=")) | 455 | if (!strstr(cmd_line, "console=")) |
463 | add_preferred_console("hvc", 0, NULL); | 456 | add_preferred_console("hvc", 0, NULL); |
464 | hvc_instantiate(0, 0, ops); | 457 | hvc_instantiate(0, 0, ops); |
465 | out: | ||
466 | of_node_put(stdout_node); | ||
467 | } | 458 | } |
468 | 459 | ||
469 | /* call this from early_init() for a working debug console on | 460 | /* call this from early_init() for a working debug console on |
diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c index f7ad5b903055..abbfedb84901 100644 --- a/drivers/tty/serial/pmac_zilog.c +++ b/drivers/tty/serial/pmac_zilog.c | |||
@@ -1653,8 +1653,7 @@ static int __init pmz_probe(void) | |||
1653 | /* | 1653 | /* |
1654 | * Find all escc chips in the system | 1654 | * Find all escc chips in the system |
1655 | */ | 1655 | */ |
1656 | node_p = of_find_node_by_name(NULL, "escc"); | 1656 | for_each_node_by_name(node_p, "escc") { |
1657 | while (node_p) { | ||
1658 | /* | 1657 | /* |
1659 | * First get channel A/B node pointers | 1658 | * First get channel A/B node pointers |
1660 | * | 1659 | * |
@@ -1672,7 +1671,7 @@ static int __init pmz_probe(void) | |||
1672 | of_node_put(node_b); | 1671 | of_node_put(node_b); |
1673 | printk(KERN_ERR "pmac_zilog: missing node %c for escc %s\n", | 1672 | printk(KERN_ERR "pmac_zilog: missing node %c for escc %s\n", |
1674 | (!node_a) ? 'a' : 'b', node_p->full_name); | 1673 | (!node_a) ? 'a' : 'b', node_p->full_name); |
1675 | goto next; | 1674 | continue; |
1676 | } | 1675 | } |
1677 | 1676 | ||
1678 | /* | 1677 | /* |
@@ -1699,11 +1698,9 @@ static int __init pmz_probe(void) | |||
1699 | of_node_put(node_b); | 1698 | of_node_put(node_b); |
1700 | memset(&pmz_ports[count], 0, sizeof(struct uart_pmac_port)); | 1699 | memset(&pmz_ports[count], 0, sizeof(struct uart_pmac_port)); |
1701 | memset(&pmz_ports[count+1], 0, sizeof(struct uart_pmac_port)); | 1700 | memset(&pmz_ports[count+1], 0, sizeof(struct uart_pmac_port)); |
1702 | goto next; | 1701 | continue; |
1703 | } | 1702 | } |
1704 | count += 2; | 1703 | count += 2; |
1705 | next: | ||
1706 | node_p = of_find_node_by_name(node_p, "escc"); | ||
1707 | } | 1704 | } |
1708 | pmz_ports_count = count; | 1705 | pmz_ports_count = count; |
1709 | 1706 | ||
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 8bb19da01639..29a7be47389a 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/console.h> | 28 | #include <linux/console.h> |
29 | #include <linux/of.h> | ||
29 | #include <linux/proc_fs.h> | 30 | #include <linux/proc_fs.h> |
30 | #include <linux/seq_file.h> | 31 | #include <linux/seq_file.h> |
31 | #include <linux/device.h> | 32 | #include <linux/device.h> |
@@ -2611,6 +2612,8 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) | |||
2611 | spin_lock_init(&uport->lock); | 2612 | spin_lock_init(&uport->lock); |
2612 | lockdep_set_class(&uport->lock, &port_lock_key); | 2613 | lockdep_set_class(&uport->lock, &port_lock_key); |
2613 | } | 2614 | } |
2615 | if (uport->cons && uport->dev) | ||
2616 | of_console_check(uport->dev->of_node, uport->cons->name, uport->line); | ||
2614 | 2617 | ||
2615 | uart_configure_port(drv, state, uport); | 2618 | uart_configure_port(drv, state, uport); |
2616 | 2619 | ||
diff --git a/include/linux/of.h b/include/linux/of.h index 196b34c1ef4e..6c4363b8ddc3 100644 --- a/include/linux/of.h +++ b/include/linux/of.h | |||
@@ -74,8 +74,6 @@ struct of_phandle_args { | |||
74 | uint32_t args[MAX_PHANDLE_ARGS]; | 74 | uint32_t args[MAX_PHANDLE_ARGS]; |
75 | }; | 75 | }; |
76 | 76 | ||
77 | extern int of_node_add(struct device_node *node); | ||
78 | |||
79 | /* initialize a node */ | 77 | /* initialize a node */ |
80 | extern struct kobj_type of_node_ktype; | 78 | extern struct kobj_type of_node_ktype; |
81 | static inline void of_node_init(struct device_node *node) | 79 | static inline void of_node_init(struct device_node *node) |
@@ -113,6 +111,7 @@ static inline void of_node_put(struct device_node *node) { } | |||
113 | extern struct device_node *of_allnodes; | 111 | extern struct device_node *of_allnodes; |
114 | extern struct device_node *of_chosen; | 112 | extern struct device_node *of_chosen; |
115 | extern struct device_node *of_aliases; | 113 | extern struct device_node *of_aliases; |
114 | extern struct device_node *of_stdout; | ||
116 | extern raw_spinlock_t devtree_lock; | 115 | extern raw_spinlock_t devtree_lock; |
117 | 116 | ||
118 | static inline bool of_have_populated_dt(void) | 117 | static inline bool of_have_populated_dt(void) |
@@ -204,6 +203,7 @@ static inline unsigned long of_read_ulong(const __be32 *cell, int size) | |||
204 | #define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */ | 203 | #define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */ |
205 | #define OF_DETACHED 2 /* node has been detached from the device tree */ | 204 | #define OF_DETACHED 2 /* node has been detached from the device tree */ |
206 | #define OF_POPULATED 3 /* device already created for the node */ | 205 | #define OF_POPULATED 3 /* device already created for the node */ |
206 | #define OF_POPULATED_BUS 4 /* of_platform_populate recursed to children of this node */ | ||
207 | 207 | ||
208 | #define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags) | 208 | #define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags) |
209 | #define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags) | 209 | #define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags) |
@@ -322,6 +322,7 @@ extern int of_update_property(struct device_node *np, struct property *newprop); | |||
322 | struct of_prop_reconfig { | 322 | struct of_prop_reconfig { |
323 | struct device_node *dn; | 323 | struct device_node *dn; |
324 | struct property *prop; | 324 | struct property *prop; |
325 | struct property *old_prop; | ||
325 | }; | 326 | }; |
326 | 327 | ||
327 | extern int of_reconfig_notifier_register(struct notifier_block *); | 328 | extern int of_reconfig_notifier_register(struct notifier_block *); |
@@ -352,7 +353,7 @@ const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur, | |||
352 | */ | 353 | */ |
353 | const char *of_prop_next_string(struct property *prop, const char *cur); | 354 | const char *of_prop_next_string(struct property *prop, const char *cur); |
354 | 355 | ||
355 | int of_device_is_stdout_path(struct device_node *dn); | 356 | bool of_console_check(struct device_node *dn, char *name, int index); |
356 | 357 | ||
357 | #else /* CONFIG_OF */ | 358 | #else /* CONFIG_OF */ |
358 | 359 | ||
@@ -564,9 +565,9 @@ static inline int of_machine_is_compatible(const char *compat) | |||
564 | return 0; | 565 | return 0; |
565 | } | 566 | } |
566 | 567 | ||
567 | static inline int of_device_is_stdout_path(struct device_node *dn) | 568 | static inline bool of_console_check(const struct device_node *dn, const char *name, int index) |
568 | { | 569 | { |
569 | return 0; | 570 | return false; |
570 | } | 571 | } |
571 | 572 | ||
572 | static inline const __be32 *of_prop_next_u32(struct property *prop, | 573 | static inline const __be32 *of_prop_next_u32(struct property *prop, |
@@ -786,4 +787,80 @@ typedef void (*of_init_fn_1)(struct device_node *); | |||
786 | #define OF_DECLARE_2(table, name, compat, fn) \ | 787 | #define OF_DECLARE_2(table, name, compat, fn) \ |
787 | _OF_DECLARE(table, name, compat, fn, of_init_fn_2) | 788 | _OF_DECLARE(table, name, compat, fn, of_init_fn_2) |
788 | 789 | ||
790 | /** | ||
791 | * struct of_changeset_entry - Holds a changeset entry | ||
792 | * | ||
793 | * @node: list_head for the log list | ||
794 | * @action: notifier action | ||
795 | * @np: pointer to the device node affected | ||
796 | * @prop: pointer to the property affected | ||
797 | * @old_prop: hold a pointer to the original property | ||
798 | * | ||
799 | * Every modification of the device tree during a changeset | ||
800 | * is held in a list of of_changeset_entry structures. | ||
801 | * That way we can recover from a partial application, or we can | ||
802 | * revert the changeset | ||
803 | */ | ||
804 | struct of_changeset_entry { | ||
805 | struct list_head node; | ||
806 | unsigned long action; | ||
807 | struct device_node *np; | ||
808 | struct property *prop; | ||
809 | struct property *old_prop; | ||
810 | }; | ||
811 | |||
812 | /** | ||
813 | * struct of_changeset - changeset tracker structure | ||
814 | * | ||
815 | * @entries: list_head for the changeset entries | ||
816 | * | ||
817 | * changesets are a convenient way to apply bulk changes to the | ||
818 | * live tree. In case of an error, changes are rolled-back. | ||
819 | * changesets live on after initial application, and if not | ||
820 | * destroyed after use, they can be reverted in one single call. | ||
821 | */ | ||
822 | struct of_changeset { | ||
823 | struct list_head entries; | ||
824 | }; | ||
825 | |||
826 | #ifdef CONFIG_OF_DYNAMIC | ||
827 | extern void of_changeset_init(struct of_changeset *ocs); | ||
828 | extern void of_changeset_destroy(struct of_changeset *ocs); | ||
829 | extern int of_changeset_apply(struct of_changeset *ocs); | ||
830 | extern int of_changeset_revert(struct of_changeset *ocs); | ||
831 | extern int of_changeset_action(struct of_changeset *ocs, | ||
832 | unsigned long action, struct device_node *np, | ||
833 | struct property *prop); | ||
834 | |||
835 | static inline int of_changeset_attach_node(struct of_changeset *ocs, | ||
836 | struct device_node *np) | ||
837 | { | ||
838 | return of_changeset_action(ocs, OF_RECONFIG_ATTACH_NODE, np, NULL); | ||
839 | } | ||
840 | |||
841 | static inline int of_changeset_detach_node(struct of_changeset *ocs, | ||
842 | struct device_node *np) | ||
843 | { | ||
844 | return of_changeset_action(ocs, OF_RECONFIG_DETACH_NODE, np, NULL); | ||
845 | } | ||
846 | |||
847 | static inline int of_changeset_add_property(struct of_changeset *ocs, | ||
848 | struct device_node *np, struct property *prop) | ||
849 | { | ||
850 | return of_changeset_action(ocs, OF_RECONFIG_ADD_PROPERTY, np, prop); | ||
851 | } | ||
852 | |||
853 | static inline int of_changeset_remove_property(struct of_changeset *ocs, | ||
854 | struct device_node *np, struct property *prop) | ||
855 | { | ||
856 | return of_changeset_action(ocs, OF_RECONFIG_REMOVE_PROPERTY, np, prop); | ||
857 | } | ||
858 | |||
859 | static inline int of_changeset_update_property(struct of_changeset *ocs, | ||
860 | struct device_node *np, struct property *prop) | ||
861 | { | ||
862 | return of_changeset_action(ocs, OF_RECONFIG_UPDATE_PROPERTY, np, prop); | ||
863 | } | ||
864 | #endif | ||
865 | |||
789 | #endif /* _LINUX_OF_H */ | 866 | #endif /* _LINUX_OF_H */ |
diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h index d96e1badbee0..c2b0627a2317 100644 --- a/include/linux/of_platform.h +++ b/include/linux/of_platform.h | |||
@@ -72,7 +72,7 @@ extern int of_platform_populate(struct device_node *root, | |||
72 | const struct of_device_id *matches, | 72 | const struct of_device_id *matches, |
73 | const struct of_dev_auxdata *lookup, | 73 | const struct of_dev_auxdata *lookup, |
74 | struct device *parent); | 74 | struct device *parent); |
75 | extern int of_platform_depopulate(struct device *parent); | 75 | extern void of_platform_depopulate(struct device *parent); |
76 | #else | 76 | #else |
77 | static inline int of_platform_populate(struct device_node *root, | 77 | static inline int of_platform_populate(struct device_node *root, |
78 | const struct of_device_id *matches, | 78 | const struct of_device_id *matches, |
@@ -81,10 +81,7 @@ static inline int of_platform_populate(struct device_node *root, | |||
81 | { | 81 | { |
82 | return -ENODEV; | 82 | return -ENODEV; |
83 | } | 83 | } |
84 | static inline int of_platform_depopulate(struct device *parent) | 84 | static inline void of_platform_depopulate(struct device *parent) { } |
85 | { | ||
86 | return -ENODEV; | ||
87 | } | ||
88 | #endif | 85 | #endif |
89 | 86 | ||
90 | #endif /* _LINUX_OF_PLATFORM_H */ | 87 | #endif /* _LINUX_OF_PLATFORM_H */ |
diff --git a/include/linux/of_reserved_mem.h b/include/linux/of_reserved_mem.h index 4669ddfdd5af..5b5efae09135 100644 --- a/include/linux/of_reserved_mem.h +++ b/include/linux/of_reserved_mem.h | |||
@@ -8,6 +8,7 @@ struct reserved_mem_ops; | |||
8 | struct reserved_mem { | 8 | struct reserved_mem { |
9 | const char *name; | 9 | const char *name; |
10 | unsigned long fdt_node; | 10 | unsigned long fdt_node; |
11 | unsigned long phandle; | ||
11 | const struct reserved_mem_ops *ops; | 12 | const struct reserved_mem_ops *ops; |
12 | phys_addr_t base; | 13 | phys_addr_t base; |
13 | phys_addr_t size; | 14 | phys_addr_t size; |
@@ -27,10 +28,16 @@ typedef int (*reservedmem_of_init_fn)(struct reserved_mem *rmem); | |||
27 | _OF_DECLARE(reservedmem, name, compat, init, reservedmem_of_init_fn) | 28 | _OF_DECLARE(reservedmem, name, compat, init, reservedmem_of_init_fn) |
28 | 29 | ||
29 | #ifdef CONFIG_OF_RESERVED_MEM | 30 | #ifdef CONFIG_OF_RESERVED_MEM |
31 | void of_reserved_mem_device_init(struct device *dev); | ||
32 | void of_reserved_mem_device_release(struct device *dev); | ||
33 | |||
30 | void fdt_init_reserved_mem(void); | 34 | void fdt_init_reserved_mem(void); |
31 | void fdt_reserved_mem_save_node(unsigned long node, const char *uname, | 35 | void fdt_reserved_mem_save_node(unsigned long node, const char *uname, |
32 | phys_addr_t base, phys_addr_t size); | 36 | phys_addr_t base, phys_addr_t size); |
33 | #else | 37 | #else |
38 | static inline void of_reserved_mem_device_init(struct device *dev) { } | ||
39 | static inline void of_reserved_mem_device_release(struct device *pdev) { } | ||
40 | |||
34 | static inline void fdt_init_reserved_mem(void) { } | 41 | static inline void fdt_init_reserved_mem(void) { } |
35 | static inline void fdt_reserved_mem_save_node(unsigned long node, | 42 | static inline void fdt_reserved_mem_save_node(unsigned long node, |
36 | const char *uname, phys_addr_t base, phys_addr_t size) { } | 43 | const char *uname, phys_addr_t base, phys_addr_t size) { } |
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index 7a43c0c38316..8a431bcb056c 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c | |||
@@ -992,9 +992,9 @@ static int snd_pmac_detect(struct snd_pmac *chip) | |||
992 | return -ENODEV; | 992 | return -ENODEV; |
993 | 993 | ||
994 | if (!sound) { | 994 | if (!sound) { |
995 | sound = of_find_node_by_name(NULL, "sound"); | 995 | for_each_node_by_name(sound, "sound") |
996 | while (sound && sound->parent != chip->node) | 996 | if (sound->parent == chip->node) |
997 | sound = of_find_node_by_name(sound, "sound"); | 997 | break; |
998 | } | 998 | } |
999 | if (! sound) { | 999 | if (! sound) { |
1000 | of_node_put(chip->node); | 1000 | of_node_put(chip->node); |