Commit 94aae1d9 authored by Laurent Pinchart's avatar Laurent Pinchart

Merge tag 'overlay_apply_fdt_v7-for-4.17' of...

Merge tag 'overlay_apply_fdt_v7-for-4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/frowand/linux into drm/next/du

- DT overlay applying rework (Frank Rowand)

Move duplicating and unflattening of an overlay flattened devicetree
(FDT) into the overlay application code.  To accomplish this,
of_overlay_apply() is replaced by of_overlay_fdt_apply().
parents f073d78e e547c003
...@@ -87,8 +87,8 @@ Overlay in-kernel API ...@@ -87,8 +87,8 @@ Overlay in-kernel API
The API is quite easy to use. The API is quite easy to use.
1. Call of_overlay_apply() to create and apply an overlay changeset. The return 1. Call of_overlay_fdt_apply() to create and apply an overlay changeset. The
value is an error or a cookie identifying this overlay. return value is an error or a cookie identifying this overlay.
2. Call of_overlay_remove() to remove and cleanup the overlay changeset 2. Call of_overlay_remove() to remove and cleanup the overlay changeset
previously created via the call to of_overlay_apply(). Removal of an overlay previously created via the call to of_overlay_apply(). Removal of an overlay
......
...@@ -259,7 +259,7 @@ static void __init dtb_apic_setup(void) ...@@ -259,7 +259,7 @@ static void __init dtb_apic_setup(void)
dtb_ioapic_setup(); dtb_ioapic_setup();
} }
#ifdef CONFIG_OF_FLATTREE #ifdef CONFIG_OF_EARLY_FLATTREE
static void __init x86_flattree_get_config(void) static void __init x86_flattree_get_config(void)
{ {
u32 size, map_len; u32 size, map_len;
......
...@@ -92,6 +92,7 @@ config OF_RESOLVE ...@@ -92,6 +92,7 @@ config OF_RESOLVE
config OF_OVERLAY config OF_OVERLAY
bool "Device Tree overlays" bool "Device Tree overlays"
select OF_DYNAMIC select OF_DYNAMIC
select OF_FLATTREE
select OF_RESOLVE select OF_RESOLVE
help help
Overlays are a method to dynamically modify part of the kernel's Overlays are a method to dynamically modify part of the kernel's
......
...@@ -12,10 +12,12 @@ ...@@ -12,10 +12,12 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of_fdt.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/libfdt.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/idr.h> #include <linux/idr.h>
...@@ -33,7 +35,9 @@ struct fragment { ...@@ -33,7 +35,9 @@ struct fragment {
/** /**
* struct overlay_changeset * struct overlay_changeset
* @id: changeset identifier
* @ovcs_list: list on which we are located * @ovcs_list: list on which we are located
* @fdt: FDT that was unflattened to create @overlay_tree
* @overlay_tree: expanded device tree that contains the fragment nodes * @overlay_tree: expanded device tree that contains the fragment nodes
* @count: count of fragment structures * @count: count of fragment structures
* @fragments: fragment nodes in the overlay expanded device tree * @fragments: fragment nodes in the overlay expanded device tree
...@@ -43,6 +47,7 @@ struct fragment { ...@@ -43,6 +47,7 @@ struct fragment {
struct overlay_changeset { struct overlay_changeset {
int id; int id;
struct list_head ovcs_list; struct list_head ovcs_list;
const void *fdt;
struct device_node *overlay_tree; struct device_node *overlay_tree;
int count; int count;
struct fragment *fragments; struct fragment *fragments;
...@@ -483,27 +488,38 @@ static int build_changeset(struct overlay_changeset *ovcs) ...@@ -483,27 +488,38 @@ static int build_changeset(struct overlay_changeset *ovcs)
*/ */
static struct device_node *find_target_node(struct device_node *info_node) static struct device_node *find_target_node(struct device_node *info_node)
{ {
struct device_node *node;
const char *path; const char *path;
u32 val; u32 val;
int ret; int ret;
ret = of_property_read_u32(info_node, "target", &val); ret = of_property_read_u32(info_node, "target", &val);
if (!ret) if (!ret) {
return of_find_node_by_phandle(val); node = of_find_node_by_phandle(val);
if (!node)
pr_err("find target, node: %pOF, phandle 0x%x not found\n",
info_node, val);
return node;
}
ret = of_property_read_string(info_node, "target-path", &path); ret = of_property_read_string(info_node, "target-path", &path);
if (!ret) if (!ret) {
return of_find_node_by_path(path); node = of_find_node_by_path(path);
if (!node)
pr_err("find target, node: %pOF, path '%s' not found\n",
info_node, path);
return node;
}
pr_err("Failed to find target for node %p (%s)\n", pr_err("find target, node: %pOF, no target property\n", info_node);
info_node, info_node->name);
return NULL; return NULL;
} }
/** /**
* init_overlay_changeset() - initialize overlay changeset from overlay tree * init_overlay_changeset() - initialize overlay changeset from overlay tree
* @ovcs Overlay changeset to build * @ovcs: Overlay changeset to build
* @fdt: the FDT that was unflattened to create @tree
* @tree: Contains all the overlay fragments and overlay fixup nodes * @tree: Contains all the overlay fragments and overlay fixup nodes
* *
* Initialize @ovcs. Populate @ovcs->fragments with node information from * Initialize @ovcs. Populate @ovcs->fragments with node information from
...@@ -514,7 +530,7 @@ static struct device_node *find_target_node(struct device_node *info_node) ...@@ -514,7 +530,7 @@ static struct device_node *find_target_node(struct device_node *info_node)
* detected in @tree, or -ENOSPC if idr_alloc() error. * detected in @tree, or -ENOSPC if idr_alloc() error.
*/ */
static int init_overlay_changeset(struct overlay_changeset *ovcs, static int init_overlay_changeset(struct overlay_changeset *ovcs,
struct device_node *tree) const void *fdt, struct device_node *tree)
{ {
struct device_node *node, *overlay_node; struct device_node *node, *overlay_node;
struct fragment *fragment; struct fragment *fragment;
...@@ -535,6 +551,7 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs, ...@@ -535,6 +551,7 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs,
pr_debug("%s() tree is not root\n", __func__); pr_debug("%s() tree is not root\n", __func__);
ovcs->overlay_tree = tree; ovcs->overlay_tree = tree;
ovcs->fdt = fdt;
INIT_LIST_HEAD(&ovcs->ovcs_list); INIT_LIST_HEAD(&ovcs->ovcs_list);
...@@ -606,6 +623,7 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs, ...@@ -606,6 +623,7 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs,
} }
if (!cnt) { if (!cnt) {
pr_err("no fragments or symbols in overlay\n");
ret = -EINVAL; ret = -EINVAL;
goto err_free_fragments; goto err_free_fragments;
} }
...@@ -642,11 +660,24 @@ static void free_overlay_changeset(struct overlay_changeset *ovcs) ...@@ -642,11 +660,24 @@ static void free_overlay_changeset(struct overlay_changeset *ovcs)
} }
kfree(ovcs->fragments); kfree(ovcs->fragments);
/*
* TODO
*
* would like to: kfree(ovcs->overlay_tree);
* but can not since drivers may have pointers into this data
*
* would like to: kfree(ovcs->fdt);
* but can not since drivers may have pointers into this data
*/
kfree(ovcs); kfree(ovcs);
} }
/** /*
* internal documentation
*
* of_overlay_apply() - Create and apply an overlay changeset * of_overlay_apply() - Create and apply an overlay changeset
* @fdt: the FDT that was unflattened to create @tree
* @tree: Expanded overlay device tree * @tree: Expanded overlay device tree
* @ovcs_id: Pointer to overlay changeset id * @ovcs_id: Pointer to overlay changeset id
* *
...@@ -685,21 +716,29 @@ static void free_overlay_changeset(struct overlay_changeset *ovcs) ...@@ -685,21 +716,29 @@ static void free_overlay_changeset(struct overlay_changeset *ovcs)
* id is returned to *ovcs_id. * id is returned to *ovcs_id.
*/ */
int of_overlay_apply(struct device_node *tree, int *ovcs_id) static int of_overlay_apply(const void *fdt, struct device_node *tree,
int *ovcs_id)
{ {
struct overlay_changeset *ovcs; struct overlay_changeset *ovcs;
int ret = 0, ret_revert, ret_tmp; int ret = 0, ret_revert, ret_tmp;
*ovcs_id = 0; /*
* As of this point, fdt and tree belong to the overlay changeset.
* overlay changeset code is responsible for freeing them.
*/
if (devicetree_corrupt()) { if (devicetree_corrupt()) {
pr_err("devicetree state suspect, refuse to apply overlay\n"); pr_err("devicetree state suspect, refuse to apply overlay\n");
kfree(fdt);
kfree(tree);
ret = -EBUSY; ret = -EBUSY;
goto out; goto out;
} }
ovcs = kzalloc(sizeof(*ovcs), GFP_KERNEL); ovcs = kzalloc(sizeof(*ovcs), GFP_KERNEL);
if (!ovcs) { if (!ovcs) {
kfree(fdt);
kfree(tree);
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
...@@ -709,12 +748,17 @@ int of_overlay_apply(struct device_node *tree, int *ovcs_id) ...@@ -709,12 +748,17 @@ int of_overlay_apply(struct device_node *tree, int *ovcs_id)
ret = of_resolve_phandles(tree); ret = of_resolve_phandles(tree);
if (ret) if (ret)
goto err_free_overlay_changeset; goto err_free_tree;
ret = init_overlay_changeset(ovcs, tree); ret = init_overlay_changeset(ovcs, fdt, tree);
if (ret) if (ret)
goto err_free_overlay_changeset; goto err_free_tree;
/*
* after overlay_notify(), ovcs->overlay_tree related pointers may have
* leaked to drivers, so can not kfree() tree, aka ovcs->overlay_tree;
* and can not free fdt, aka ovcs->fdt
*/
ret = overlay_notify(ovcs, OF_OVERLAY_PRE_APPLY); ret = overlay_notify(ovcs, OF_OVERLAY_PRE_APPLY);
if (ret) { if (ret) {
pr_err("overlay changeset pre-apply notify error %d\n", ret); pr_err("overlay changeset pre-apply notify error %d\n", ret);
...@@ -754,6 +798,10 @@ int of_overlay_apply(struct device_node *tree, int *ovcs_id) ...@@ -754,6 +798,10 @@ int of_overlay_apply(struct device_node *tree, int *ovcs_id)
goto out_unlock; goto out_unlock;
err_free_tree:
kfree(fdt);
kfree(tree);
err_free_overlay_changeset: err_free_overlay_changeset:
free_overlay_changeset(ovcs); free_overlay_changeset(ovcs);
...@@ -766,7 +814,63 @@ int of_overlay_apply(struct device_node *tree, int *ovcs_id) ...@@ -766,7 +814,63 @@ int of_overlay_apply(struct device_node *tree, int *ovcs_id)
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(of_overlay_apply);
int of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size,
int *ovcs_id)
{
const void *new_fdt;
int ret;
u32 size;
struct device_node *overlay_root;
*ovcs_id = 0;
ret = 0;
if (overlay_fdt_size < sizeof(struct fdt_header) ||
fdt_check_header(overlay_fdt)) {
pr_err("Invalid overlay_fdt header\n");
return -EINVAL;
}
size = fdt_totalsize(overlay_fdt);
if (overlay_fdt_size < size)
return -EINVAL;
/*
* Must create permanent copy of FDT because of_fdt_unflatten_tree()
* will create pointers to the passed in FDT in the unflattened tree.
*/
new_fdt = kmemdup(overlay_fdt, size, GFP_KERNEL);
if (!new_fdt)
return -ENOMEM;
of_fdt_unflatten_tree(new_fdt, NULL, &overlay_root);
if (!overlay_root) {
pr_err("unable to unflatten overlay_fdt\n");
ret = -EINVAL;
goto out_free_new_fdt;
}
ret = of_overlay_apply(new_fdt, overlay_root, ovcs_id);
if (ret < 0) {
/*
* new_fdt and overlay_root now belong to the overlay
* changeset.
* overlay changeset code is responsible for freeing them.
*/
goto out;
}
return 0;
out_free_new_fdt:
kfree(new_fdt);
out:
return ret;
}
EXPORT_SYMBOL_GPL(of_overlay_fdt_apply);
/* /*
* Find @np in @tree. * Find @np in @tree.
......
...@@ -269,17 +269,11 @@ int of_resolve_phandles(struct device_node *overlay) ...@@ -269,17 +269,11 @@ int of_resolve_phandles(struct device_node *overlay)
goto out; goto out;
} }
#if 0
Temporarily disable check so that old style overlay unittests
do not fail when of_resolve_phandles() is moved into
of_overlay_apply().
if (!of_node_check_flag(overlay, OF_DETACHED)) { if (!of_node_check_flag(overlay, OF_DETACHED)) {
pr_err("overlay not detached\n"); pr_err("overlay not detached\n");
err = -EINVAL; err = -EINVAL;
goto out; goto out;
} }
#endif
phandle_delta = live_tree_max_phandle() + 1; phandle_delta = live_tree_max_phandle() + 1;
adjust_overlay_phandles(overlay, phandle_delta); adjust_overlay_phandles(overlay, phandle_delta);
......
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
DTC_FLAGS_testcases := -Wno-interrupts_property
obj-y += testcases.dtb.o obj-y += testcases.dtb.o
obj-$(CONFIG_OF_OVERLAY) += overlay.dtb.o \ obj-$(CONFIG_OF_OVERLAY) += overlay.dtb.o \
overlay_0.dtb.o \
overlay_1.dtb.o \
overlay_2.dtb.o \
overlay_3.dtb.o \
overlay_4.dtb.o \
overlay_5.dtb.o \
overlay_6.dtb.o \
overlay_7.dtb.o \
overlay_8.dtb.o \
overlay_9.dtb.o \
overlay_10.dtb.o \
overlay_11.dtb.o \
overlay_12.dtb.o \
overlay_13.dtb.o \
overlay_15.dtb.o \
overlay_bad_phandle.dtb.o \ overlay_bad_phandle.dtb.o \
overlay_bad_symbol.dtb.o \ overlay_bad_symbol.dtb.o \
overlay_base.dtb.o overlay_base.dtb.o
...@@ -10,10 +24,14 @@ obj-$(CONFIG_OF_OVERLAY) += overlay.dtb.o \ ...@@ -10,10 +24,14 @@ obj-$(CONFIG_OF_OVERLAY) += overlay.dtb.o \
targets += $(foreach suffix, dtb dtb.S, $(patsubst %.dtb.o,%.$(suffix),$(obj-y))) targets += $(foreach suffix, dtb dtb.S, $(patsubst %.dtb.o,%.$(suffix),$(obj-y)))
# enable creation of __symbols__ node # enable creation of __symbols__ node
DTC_FLAGS_overlay := -@ DTC_FLAGS_overlay += -@
DTC_FLAGS_overlay_bad_phandle := -@ DTC_FLAGS_overlay_bad_phandle += -@
DTC_FLAGS_overlay_bad_symbol := -@ DTC_FLAGS_overlay_bad_symbol += -@
DTC_FLAGS_overlay_base := -@ DTC_FLAGS_overlay_base += -@
DTC_FLAGS_testcases += -@
# suppress warnings about intentional errors
DTC_FLAGS_testcases += -Wno-interrupts_property
.PRECIOUS: \ .PRECIOUS: \
$(obj)/%.dtb.S \ $(obj)/%.dtb.S \
......
...@@ -2,12 +2,8 @@ ...@@ -2,12 +2,8 @@
/dts-v1/; /dts-v1/;
/plugin/; /plugin/;
/ { &electric_1 {
fragment@0 {
target = <&electric_1>;
__overlay__ {
status = "okay"; status = "okay";
hvac_2: hvac-large-1 { hvac_2: hvac-large-1 {
...@@ -15,13 +11,10 @@ hvac_2: hvac-large-1 { ...@@ -15,13 +11,10 @@ hvac_2: hvac-large-1 {
heat-range = < 40 75 >; heat-range = < 40 75 >;
cool-range = < 65 80 >; cool-range = < 65 80 >;
}; };
}; };
};
fragment@1 { &rides_1 {
target = <&rides_1>;
__overlay__ {
#address-cells = <1>; #address-cells = <1>;
#size-cells = <1>; #size-cells = <1>;
status = "okay"; status = "okay";
...@@ -61,17 +54,11 @@ ride_200_right: track@20 { ...@@ -61,17 +54,11 @@ ride_200_right: track@20 {
reg = < 0x00000020 0x10 >; reg = < 0x00000020 0x10 >;
}; };
}; };
}; };
};
fragment@2 { &lights_2 {
target = <&lights_2>;
__overlay__ {
status = "okay"; status = "okay";
color = "purple", "white", "red", "green"; color = "purple", "white", "red", "green";
rate = < 3 256 >; rate = < 3 256 >;
};
};
}; };
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
/plugin/;
/ {
/* overlay_0 - enable using absolute target path */
fragment@0 {
target-path = "/testcase-data/overlay-node/test-bus/test-unittest0";
__overlay__ {
status = "okay";
};
};
};
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
/plugin/;
/ {
/* overlay_1 - disable using absolute target path */
fragment@0 {
target-path = "/testcase-data/overlay-node/test-bus/test-unittest1";
__overlay__ {
status = "disabled";
};
};
};
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
/plugin/;
/* overlay_10 */
/* overlays 8, 9, 10, 11 application and removal in bad sequence */
&unittest_test_bus {
/* suppress DTC warning */
#address-cells = <1>;
#size-cells = <0>;
test-unittest10 {
compatible = "unittest";
status = "okay";
reg = <10>;
#address-cells = <1>;
#size-cells = <0>;
test-unittest101 {
compatible = "unittest";
status = "okay";
reg = <1>;
};
};
};
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
/plugin/;
/* overlay_11 */
/* overlays 8, 9, 10, 11 application and removal in bad sequence */
&unittest_test_bus {
/* suppress DTC warning */
#address-cells = <1>;
#size-cells = <0>;
test-unittest11 {
compatible = "unittest";
status = "okay";
reg = <11>;
#address-cells = <1>;
#size-cells = <0>;
test-unittest111 {
compatible = "unittest";
status = "okay";
reg = <1>;
};
};
};
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
/plugin/;
/ {
/* overlay_12 - enable using absolute target path (i2c) */
fragment@0 {
target-path = "/testcase-data/overlay-node/test-bus/i2c-test-bus/test-unittest12";
__overlay__ {
status = "okay";
};
};
};
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
/plugin/;
/ {
/* overlay_13 - disable using absolute target path (i2c) */
fragment@0 {
target-path = "/testcase-data/overlay-node/test-bus/i2c-test-bus/test-unittest13";
__overlay__ {
status = "disabled";
};
};
};
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
/plugin/;
/* overlay_15 - mux overlay */
&unittest_i2c_test_bus {
#address-cells = <1>;
#size-cells = <0>;
test-unittest15 {
reg = <11>;
compatible = "unittest-i2c-mux";
status = "okay";
#address-cells = <1>;
#size-cells = <0>;
i2c@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
test-mux-dev {
reg = <32>;
compatible = "unittest-i2c-dev";
status = "okay";
};
};
};
};
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
/plugin/;
/* overlay_2 - enable using label */
&unittest2 {
status = "okay";
};
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
/plugin/;
/* overlay_3 - disable using label */
&unittest3 {
status = "disabled";
};
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
/plugin/;
/* overlay_4 - test insertion of a full node */
&unittest_test_bus {
/* suppress DTC warning */
#address-cells = <1>;
#size-cells = <0>;
test-unittest4 {
compatible = "unittest";
status = "okay";
reg = <4>;
};
};
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
/plugin/;
/* overlay_5 - test overlay apply revert */
&unittest5 {
status = "okay";
};
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
/plugin/;
/* overlay_6 */
/* overlays 6, 7 application and removal in sequence */
&unittest6 {
status = "okay";
};
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
/plugin/;
/* overlay_7 */
/* overlays 6, 7 application and removal in sequence */
&unittest7 {
status = "okay";
};
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
/plugin/;
/* overlay_8 */
/* overlays 8, 9, 10, 11 application and removal in bad sequence */
&unittest8 {
status = "okay";
};
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
/plugin/;
/* overlay_9 */
/* overlays 8, 9, 10, 11 application and removal in bad sequence */
&unittest8 {
property-foo = "bar";
};
...@@ -2,12 +2,7 @@ ...@@ -2,12 +2,7 @@
/dts-v1/; /dts-v1/;
/plugin/; /plugin/;
/ { &electric_1 {
fragment@0 {
target = <&electric_1>;
__overlay__ {
// This label should cause an error when the overlay // This label should cause an error when the overlay
// is applied. There is already a phandle value // is applied. There is already a phandle value
...@@ -16,6 +11,4 @@ spin_ctrl_1_conflict: motor-1 { ...@@ -16,6 +11,4 @@ spin_ctrl_1_conflict: motor-1 {
accelerate = < 3 >; accelerate = < 3 >;
decelerate = < 5 >; decelerate = < 5 >;
}; };
};
};
}; };
...@@ -2,12 +2,7 @@ ...@@ -2,12 +2,7 @@
/dts-v1/; /dts-v1/;
/plugin/; /plugin/;
/ { &electric_1 {
fragment@0 {
target = <&electric_1>;
__overlay__ {
// This label should cause an error when the overlay // This label should cause an error when the overlay
// is applied. There is already a symbol hvac_1 // is applied. There is already a symbol hvac_1
...@@ -18,6 +13,4 @@ hvac_1: hvac-medium-2 { ...@@ -18,6 +13,4 @@ hvac_1: hvac-medium-2 {
cool-range = < 60 80 >; cool-range = < 60 80 >;
}; };
};
};
}; };
...@@ -5,7 +5,7 @@ testcase-data { ...@@ -5,7 +5,7 @@ testcase-data {
overlay-node { overlay-node {
/* test bus */ /* test bus */
unittestbus: test-bus { unittest_test_bus: test-bus {
compatible = "simple-bus"; compatible = "simple-bus";
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
...@@ -70,7 +70,7 @@ unittest8: test-unittest8 { ...@@ -70,7 +70,7 @@ unittest8: test-unittest8 {
reg = <8>; reg = <8>;
}; };
i2c-test-bus { unittest_i2c_test_bus: i2c-test-bus {
compatible = "unittest-i2c-bus"; compatible = "unittest-i2c-bus";
status = "okay"; status = "okay";
reg = <50>; reg = <50>;
...@@ -113,218 +113,5 @@ test-mux-dev { ...@@ -113,218 +113,5 @@ test-mux-dev {
}; };
}; };
}; };
/* test enable using absolute target path */
overlay0 {
fragment@0 {
target-path = "/testcase-data/overlay-node/test-bus/test-unittest0";
__overlay__ {
status = "okay";
};
};
};
/* test disable using absolute target path */
overlay1 {
fragment@0 {
target-path = "/testcase-data/overlay-node/test-bus/test-unittest1";
__overlay__ {
status = "disabled";
};
};
};
/* test enable using label */
overlay2 {
fragment@0 {
target = <&unittest2>;
__overlay__ {
status = "okay";
};
};
};
/* test disable using label */
overlay3 {
fragment@0 {
target = <&unittest3>;
__overlay__ {
status = "disabled";
};
};
};
/* test insertion of a full node */
overlay4 {
fragment@0 {
target = <&unittestbus>;
__overlay__ {
/* suppress DTC warning */
#address-cells = <1>;
#size-cells = <0>;
test-unittest4 {
compatible = "unittest";
status = "okay";
reg = <4>;
};
};
};
};
/* test overlay apply revert */
overlay5 {
fragment@0 {
target-path = "/testcase-data/overlay-node/test-bus/test-unittest5";
__overlay__ {
status = "okay";
};
};
};
/* test overlays application and removal in sequence */
overlay6 {
fragment@0 {
target-path = "/testcase-data/overlay-node/test-bus/test-unittest6";
__overlay__ {
status = "okay";
};
};
};
overlay7 {
fragment@0 {
target-path = "/testcase-data/overlay-node/test-bus/test-unittest7";
__overlay__ {
status = "okay";
};
};
};
/* test overlays application and removal in bad sequence */
overlay8 {
fragment@0 {
target-path = "/testcase-data/overlay-node/test-bus/test-unittest8";
__overlay__ {
status = "okay";
};
};
};
overlay9 {
fragment@0 {
target-path = "/testcase-data/overlay-node/test-bus/test-unittest8";
__overlay__ {
property-foo = "bar";
};
};
};
overlay10 {
fragment@0 {
target-path = "/testcase-data/overlay-node/test-bus";
__overlay__ {
/* suppress DTC warning */
#address-cells = <1>;
#size-cells = <0>;
test-unittest10 {
compatible = "unittest";
status = "okay";
reg = <10>;
#address-cells = <1>;
#size-cells = <0>;
test-unittest101 {
compatible = "unittest";
status = "okay";
reg = <1>;
};
};
};
};
};
overlay11 {
fragment@0 {
target-path = "/testcase-data/overlay-node/test-bus";
__overlay__ {
/* suppress DTC warning */
#address-cells = <1>;
#size-cells = <0>;
test-unittest11 {
compatible = "unittest";
status = "okay";
reg = <11>;
#address-cells = <1>;
#size-cells = <0>;
test-unittest111 {
compatible = "unittest";
status = "okay";
reg = <1>;
};
};
};
};
};
/* test enable using absolute target path (i2c) */
overlay12 {
fragment@0 {
target-path = "/testcase-data/overlay-node/test-bus/i2c-test-bus/test-unittest12";
__overlay__ {
status = "okay";
};
};
};
/* test disable using absolute target path (i2c) */
overlay13 {
fragment@0 {
target-path = "/testcase-data/overlay-node/test-bus/i2c-test-bus/test-unittest13";
__overlay__ {
status = "disabled";
};
};
};
/* test mux overlay */
overlay15 {
fragment@0 {
target-path = "/testcase-data/overlay-node/test-bus/i2c-test-bus";
__overlay__ {
#address-cells = <1>;
#size-cells = <0>;
test-unittest15 {
reg = <11>;
compatible = "unittest-i2c-mux";
status = "okay";
#address-cells = <1>;
#size-cells = <0>;
i2c@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
test-mux-dev {
reg = <32>;
compatible = "unittest-i2c-dev";
status = "okay";
};
};
};
};
};
};
}; };
}; };
This diff is collapsed.
...@@ -1359,8 +1359,8 @@ struct of_overlay_notify_data { ...@@ -1359,8 +1359,8 @@ struct of_overlay_notify_data {
#ifdef CONFIG_OF_OVERLAY #ifdef CONFIG_OF_OVERLAY
/* ID based overlays; the API for external users */ int of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size,
int of_overlay_apply(struct device_node *tree, int *ovcs_id); int *ovcs_id);
int of_overlay_remove(int *ovcs_id); int of_overlay_remove(int *ovcs_id);
int of_overlay_remove_all(void); int of_overlay_remove_all(void);
...@@ -1369,7 +1369,7 @@ int of_overlay_notifier_unregister(struct notifier_block *nb); ...@@ -1369,7 +1369,7 @@ int of_overlay_notifier_unregister(struct notifier_block *nb);
#else #else
static inline int of_overlay_apply(struct device_node *tree, int *ovcs_id) static inline int of_overlay_fdt_apply(void *overlay_fdt, int *ovcs_id)
{ {
return -ENOTSUPP; return -ENOTSUPP;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment