diff mbox series

[v2,1/8] event: signal when livetree has been built

Message ID 20250411-livetree-fixup-v2-1-1236823377bb@linaro.org
State New
Headers show
Series Qualcomm: cleanup OF_LIVE fixup and fix RB1/2 | expand

Commit Message

Caleb Connolly April 11, 2025, 12:47 p.m. UTC
OF_LIVE offers a variety of benefits, one of them being that the live
tree can be modified without caring about the underlying FDT. This is
particularly valuable for working around U-Boot limitations like lacking
USB superspeed support on Qualcomm platforms, no runtime OTG, or
peripherals like the sdcard being broken (and displaying potentially
worrying error messages).

Add an event to signal when the live tree has been built so that we can
apply fixups to it directly before devices are bound.

Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
---
 common/event.c  |  3 +++
 include/event.h | 18 ++++++++++++++++++
 lib/of_live.c   | 11 +++++++++++
 3 files changed, 32 insertions(+)

Comments

Neil Armstrong April 11, 2025, 2:11 p.m. UTC | #1
On 11/04/2025 14:47, Caleb Connolly wrote:
> OF_LIVE offers a variety of benefits, one of them being that the live
> tree can be modified without caring about the underlying FDT. This is
> particularly valuable for working around U-Boot limitations like lacking
> USB superspeed support on Qualcomm platforms, no runtime OTG, or
> peripherals like the sdcard being broken (and displaying potentially
> worrying error messages).
> 
> Add an event to signal when the live tree has been built so that we can
> apply fixups to it directly before devices are bound.
> 
> Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
> ---
>   common/event.c  |  3 +++
>   include/event.h | 18 ++++++++++++++++++
>   lib/of_live.c   | 11 +++++++++++
>   3 files changed, 32 insertions(+)
> 
> diff --git a/common/event.c b/common/event.c
> index dda569d447851f559a83f98fb7b1f3543156eab5..8d7513eb10b61919e1e784481dfdcc076be14986 100644
> --- a/common/event.c
> +++ b/common/event.c
> @@ -47,8 +47,11 @@ const char *const type_name[] = {
>   	"ft_fixup",
>   
>   	/* main loop events */
>   	"main_loop",
> +
> +	/* livetree has been built */
> +	"of_live_init",

"of_live_built" ?

>   };
>   
>   _Static_assert(ARRAY_SIZE(type_name) == EVT_COUNT, "event type_name size");
>   #endif
> diff --git a/include/event.h b/include/event.h
> index 75141a192a48b0931667632f41be8ff4d6139f7c..1d267f1d10547642d381fa287ab4981a2bf03543 100644
> --- a/include/event.h
> +++ b/include/event.h
> @@ -152,8 +152,17 @@ enum event_t {
>   	 * A non-zero return value causes the boot to fail.
>   	 */
>   	EVT_MAIN_LOOP,
>   
> +	/**
> +	 * @EVT_OF_LIVE_BUILT:
> +	 * This event is triggered immediately after the live device tree has been
> +	 * built. This allows for machine specific fixups to be done to the live tree
> +	 * (like disabling known-unsupported devices) before it is used. This
> +	 * event is only available if OF_LIVE is enabled and is only used after relocation.
> +	 */
> +	EVT_OF_LIVE_BUILT,
> +
>   	/**
>   	 * @EVT_COUNT:
>   	 * This constants holds the maximum event number + 1 and is used when
>   	 * looping over all event classes.
> @@ -202,8 +211,17 @@ union event_data {
>   	struct event_ft_fixup {
>   		oftree tree;
>   		struct bootm_headers *images;
>   	} ft_fixup;
> +
> +	/**
> +	 * struct event_of_live_built - livetree has been built
> +	 *
> +	 * @root: The root node of the live device tree
> +	 */
> +	struct event_of_live_built {
> +		struct device_node *root;
> +	} of_live_built;
>   };
>   
>   /**
>    * struct event - an event that can be sent and received
> diff --git a/lib/of_live.c b/lib/of_live.c
> index 90b9459ede313e492e28c8556c730f3bd8aaa9df..c1620616513c2e32448b4a6d156a9162d97c76b7 100644
> --- a/lib/of_live.c
> +++ b/lib/of_live.c
> @@ -10,8 +10,9 @@
>   
>   #define LOG_CATEGORY	LOGC_DT
>   
>   #include <abuf.h>
> +#include <event.h>
>   #include <log.h>
>   #include <linux/libfdt.h>
>   #include <of_live.h>
>   #include <malloc.h>
> @@ -320,8 +321,9 @@ int unflatten_device_tree(const void *blob, struct device_node **mynodes)
>   
>   int of_live_build(const void *fdt_blob, struct device_node **rootp)
>   {
>   	int ret;
> +	union event_data evt;
>   
>   	debug("%s: start\n", __func__);
>   	ret = unflatten_device_tree(fdt_blob, rootp);
>   	if (ret) {
> @@ -334,8 +336,17 @@ int of_live_build(const void *fdt_blob, struct device_node **rootp)
>   		return ret;
>   	}
>   	debug("%s: stop\n", __func__);
>   
> +	if (CONFIG_IS_ENABLED(EVENT)) {
> +		evt.of_live_built.root = *rootp;
> +		ret = event_notify(EVT_OF_LIVE_BUILT, &evt, sizeof(evt));
> +		if (ret) {
> +			log_debug("Failed to notify livetree build event: err=%d\n", ret);
> +			return ret;
> +		}
> +	}
> +
>   	return ret;
>   }
>   
>   void of_live_free(struct device_node *root)
>
Simon Glass April 11, 2025, 6:27 p.m. UTC | #2
Hi Caleb,

On Fri, 11 Apr 2025 at 06:47, Caleb Connolly <caleb.connolly@linaro.org> wrote:
>
> OF_LIVE offers a variety of benefits, one of them being that the live
> tree can be modified without caring about the underlying FDT. This is
> particularly valuable for working around U-Boot limitations like lacking
> USB superspeed support on Qualcomm platforms, no runtime OTG, or
> peripherals like the sdcard being broken (and displaying potentially
> worrying error messages).
>
> Add an event to signal when the live tree has been built so that we can
> apply fixups to it directly before devices are bound.
>
> Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
> ---
>  common/event.c  |  3 +++
>  include/event.h | 18 ++++++++++++++++++
>  lib/of_live.c   | 11 +++++++++++
>  3 files changed, 32 insertions(+)
>
> diff --git a/common/event.c b/common/event.c
> index dda569d447851f559a83f98fb7b1f3543156eab5..8d7513eb10b61919e1e784481dfdcc076be14986 100644
> --- a/common/event.c
> +++ b/common/event.c
> @@ -47,8 +47,11 @@ const char *const type_name[] = {
>         "ft_fixup",
>
>         /* main loop events */
>         "main_loop",
> +
> +       /* livetree has been built */
> +       "of_live_init",
>  };
>
>  _Static_assert(ARRAY_SIZE(type_name) == EVT_COUNT, "event type_name size");
>  #endif
> diff --git a/include/event.h b/include/event.h
> index 75141a192a48b0931667632f41be8ff4d6139f7c..1d267f1d10547642d381fa287ab4981a2bf03543 100644
> --- a/include/event.h
> +++ b/include/event.h
> @@ -152,8 +152,17 @@ enum event_t {
>          * A non-zero return value causes the boot to fail.
>          */
>         EVT_MAIN_LOOP,
>
> +       /**
> +        * @EVT_OF_LIVE_BUILT:
> +        * This event is triggered immediately after the live device tree has been
> +        * built. This allows for machine specific fixups to be done to the live tree
> +        * (like disabling known-unsupported devices) before it is used. This
> +        * event is only available if OF_LIVE is enabled and is only used after relocation.

Add a bit more detail, e.g.: before it is used by U-Boot
post-relocation. This means it is possible to affect the devices bound
by driver model.

You should also note that the flattree is inactive when livetree is
used and any changes may eventually be passed onto the OS, if it
doesn't have its own devicetree. This is the point we were discussing
on the other thread.

> +        */
> +       EVT_OF_LIVE_BUILT,
> +
>         /**
>          * @EVT_COUNT:
>          * This constants holds the maximum event number + 1 and is used when
>          * looping over all event classes.
> @@ -202,8 +211,17 @@ union event_data {
>         struct event_ft_fixup {
>                 oftree tree;
>                 struct bootm_headers *images;
>         } ft_fixup;
> +
> +       /**
> +        * struct event_of_live_built - livetree has been built
> +        *
> +        * @root: The root node of the live device tree
> +        */
> +       struct event_of_live_built {
> +               struct device_node *root;
> +       } of_live_built;
>  };
>
>  /**
>   * struct event - an event that can be sent and received
> diff --git a/lib/of_live.c b/lib/of_live.c
> index 90b9459ede313e492e28c8556c730f3bd8aaa9df..c1620616513c2e32448b4a6d156a9162d97c76b7 100644
> --- a/lib/of_live.c
> +++ b/lib/of_live.c
> @@ -10,8 +10,9 @@
>
>  #define LOG_CATEGORY   LOGC_DT
>
>  #include <abuf.h>
> +#include <event.h>
>  #include <log.h>
>  #include <linux/libfdt.h>
>  #include <of_live.h>
>  #include <malloc.h>
> @@ -320,8 +321,9 @@ int unflatten_device_tree(const void *blob, struct device_node **mynodes)
>
>  int of_live_build(const void *fdt_blob, struct device_node **rootp)
>  {
>         int ret;
> +       union event_data evt;
>
>         debug("%s: start\n", __func__);
>         ret = unflatten_device_tree(fdt_blob, rootp);
>         if (ret) {
> @@ -334,8 +336,17 @@ int of_live_build(const void *fdt_blob, struct device_node **rootp)
>                 return ret;
>         }
>         debug("%s: stop\n", __func__);
>
> +       if (CONFIG_IS_ENABLED(EVENT)) {
> +               evt.of_live_built.root = *rootp;
> +               ret = event_notify(EVT_OF_LIVE_BUILT, &evt, sizeof(evt));
> +               if (ret) {
> +                       log_debug("Failed to notify livetree build event: err=%d\n", ret);
> +                       return ret;
> +               }
> +       }
> +

This should move to the caller of this function. We should also have a
sandbox test for this feature, e.g. catch the event and add a
node/prop and check in a test in test-fdt.c (or similar) that it is
present.

I'm not sure if you need to update test_event_dump.py but since CI
presumably passes, I guess not.

>         return ret;
>  }
>
>  void of_live_free(struct device_node *root)
>
> --
> 2.49.0
>

Regards,
Simon
Caleb Connolly April 14, 2025, 12:33 p.m. UTC | #3
Hi Simon,

On 4/11/25 20:27, Simon Glass wrote:
> Hi Caleb,
> 
> On Fri, 11 Apr 2025 at 06:47, Caleb Connolly <caleb.connolly@linaro.org> wrote:
>>
>> OF_LIVE offers a variety of benefits, one of them being that the live
>> tree can be modified without caring about the underlying FDT. This is
>> particularly valuable for working around U-Boot limitations like lacking
>> USB superspeed support on Qualcomm platforms, no runtime OTG, or
>> peripherals like the sdcard being broken (and displaying potentially
>> worrying error messages).
>>
>> Add an event to signal when the live tree has been built so that we can
>> apply fixups to it directly before devices are bound.
>>
>> Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
>> ---
>>   common/event.c  |  3 +++
>>   include/event.h | 18 ++++++++++++++++++
>>   lib/of_live.c   | 11 +++++++++++
>>   3 files changed, 32 insertions(+)
>>
>> diff --git a/common/event.c b/common/event.c
>> index dda569d447851f559a83f98fb7b1f3543156eab5..8d7513eb10b61919e1e784481dfdcc076be14986 100644
>> --- a/common/event.c
>> +++ b/common/event.c
>> @@ -47,8 +47,11 @@ const char *const type_name[] = {
>>          "ft_fixup",
>>
>>          /* main loop events */
>>          "main_loop",
>> +
>> +       /* livetree has been built */
>> +       "of_live_init",
>>   };
>>
>>   _Static_assert(ARRAY_SIZE(type_name) == EVT_COUNT, "event type_name size");
>>   #endif
>> diff --git a/include/event.h b/include/event.h
>> index 75141a192a48b0931667632f41be8ff4d6139f7c..1d267f1d10547642d381fa287ab4981a2bf03543 100644
>> --- a/include/event.h
>> +++ b/include/event.h
>> @@ -152,8 +152,17 @@ enum event_t {
>>           * A non-zero return value causes the boot to fail.
>>           */
>>          EVT_MAIN_LOOP,
>>
>> +       /**
>> +        * @EVT_OF_LIVE_BUILT:
>> +        * This event is triggered immediately after the live device tree has been
>> +        * built. This allows for machine specific fixups to be done to the live tree
>> +        * (like disabling known-unsupported devices) before it is used. This
>> +        * event is only available if OF_LIVE is enabled and is only used after relocation.
> 
> Add a bit more detail, e.g.: before it is used by U-Boot
> post-relocation. This means it is possible to affect the devices bound
> by driver model.

I think this is really implied and made obvious by context clues. IF 
there comes a time where we build the live tree more than once (e.g. to 
build it as part of the DT_FIXUP_PROTOCOL for some reason) then the 
extra info you propose adding would no longer be correct, where the 
current wording would remain correct.

> 
> You should also note that the flattree is inactive when livetree is
> used and any changes may eventually be passed onto the OS, if it
> doesn't have its own devicetree. This is the point we were discussing
> on the other thread.

This information is totally irrelevant though, and there is no broad 
agreement with your proposed changes. The livetree API is also set up so 
that one could build multiple livetrees (for whatever reason), this 
event is modelled to reflect that (where you can see in my v1 patches 
that the event assumed you would only ever build the global tree).

> 
>> +        */
>> +       EVT_OF_LIVE_BUILT,
>> +
>>          /**
>>           * @EVT_COUNT:
>>           * This constants holds the maximum event number + 1 and is used when
>>           * looping over all event classes.
>> @@ -202,8 +211,17 @@ union event_data {
>>          struct event_ft_fixup {
>>                  oftree tree;
>>                  struct bootm_headers *images;
>>          } ft_fixup;
>> +
>> +       /**
>> +        * struct event_of_live_built - livetree has been built
>> +        *
>> +        * @root: The root node of the live device tree
>> +        */
>> +       struct event_of_live_built {
>> +               struct device_node *root;
>> +       } of_live_built;
>>   };
>>
>>   /**
>>    * struct event - an event that can be sent and received
>> diff --git a/lib/of_live.c b/lib/of_live.c
>> index 90b9459ede313e492e28c8556c730f3bd8aaa9df..c1620616513c2e32448b4a6d156a9162d97c76b7 100644
>> --- a/lib/of_live.c
>> +++ b/lib/of_live.c
>> @@ -10,8 +10,9 @@
>>
>>   #define LOG_CATEGORY   LOGC_DT
>>
>>   #include <abuf.h>
>> +#include <event.h>
>>   #include <log.h>
>>   #include <linux/libfdt.h>
>>   #include <of_live.h>
>>   #include <malloc.h>
>> @@ -320,8 +321,9 @@ int unflatten_device_tree(const void *blob, struct device_node **mynodes)
>>
>>   int of_live_build(const void *fdt_blob, struct device_node **rootp)
>>   {
>>          int ret;
>> +       union event_data evt;
>>
>>          debug("%s: start\n", __func__);
>>          ret = unflatten_device_tree(fdt_blob, rootp);
>>          if (ret) {
>> @@ -334,8 +336,17 @@ int of_live_build(const void *fdt_blob, struct device_node **rootp)
>>                  return ret;
>>          }
>>          debug("%s: stop\n", __func__);
>>
>> +       if (CONFIG_IS_ENABLED(EVENT)) {
>> +               evt.of_live_built.root = *rootp;
>> +               ret = event_notify(EVT_OF_LIVE_BUILT, &evt, sizeof(evt));
>> +               if (ret) {
>> +                       log_debug("Failed to notify livetree build event: err=%d\n", ret);
>> +                       return ret;
>> +               }
>> +       }
>> +
> 
> This should move to the caller of this function. We should also have a

Why move it to the caller? Then every caller would need to signal the 
event and we'd pointlessly duplicate code. The event signals that /a/ 
livetree has been built. Today this only happens once and we make the 
assumption that this livetree is to be used by U-Boot and only U-Boot.

Should this assumption become incorrect in the future, it would be 
trivial to introduce a variable to the event_data that describes what 
the livetree is and/or where it will be used so that anyone catching the 
event can decide what to do.

Since we don't yet know any other usecases, it would be overzealous to 
try and capture this information since we just don't know what's important.

> sandbox test for this feature, e.g. catch the event and add a
> node/prop and check in a test in test-fdt.c (or similar) that it is
> present.

What would this test other than that the event is sent? We already have 
tests for the event framework...

> 
> I'm not sure if you need to update test_event_dump.py but since CI
> presumably passes, I guess not.>
>>          return ret;
>>   }
>>
>>   void of_live_free(struct device_node *root)
>>
>> --
>> 2.49.0
>>
> 
> Regards,
> Simon
diff mbox series

Patch

diff --git a/common/event.c b/common/event.c
index dda569d447851f559a83f98fb7b1f3543156eab5..8d7513eb10b61919e1e784481dfdcc076be14986 100644
--- a/common/event.c
+++ b/common/event.c
@@ -47,8 +47,11 @@  const char *const type_name[] = {
 	"ft_fixup",
 
 	/* main loop events */
 	"main_loop",
+
+	/* livetree has been built */
+	"of_live_init",
 };
 
 _Static_assert(ARRAY_SIZE(type_name) == EVT_COUNT, "event type_name size");
 #endif
diff --git a/include/event.h b/include/event.h
index 75141a192a48b0931667632f41be8ff4d6139f7c..1d267f1d10547642d381fa287ab4981a2bf03543 100644
--- a/include/event.h
+++ b/include/event.h
@@ -152,8 +152,17 @@  enum event_t {
 	 * A non-zero return value causes the boot to fail.
 	 */
 	EVT_MAIN_LOOP,
 
+	/**
+	 * @EVT_OF_LIVE_BUILT:
+	 * This event is triggered immediately after the live device tree has been
+	 * built. This allows for machine specific fixups to be done to the live tree
+	 * (like disabling known-unsupported devices) before it is used. This
+	 * event is only available if OF_LIVE is enabled and is only used after relocation.
+	 */
+	EVT_OF_LIVE_BUILT,
+
 	/**
 	 * @EVT_COUNT:
 	 * This constants holds the maximum event number + 1 and is used when
 	 * looping over all event classes.
@@ -202,8 +211,17 @@  union event_data {
 	struct event_ft_fixup {
 		oftree tree;
 		struct bootm_headers *images;
 	} ft_fixup;
+
+	/**
+	 * struct event_of_live_built - livetree has been built
+	 *
+	 * @root: The root node of the live device tree
+	 */
+	struct event_of_live_built {
+		struct device_node *root;
+	} of_live_built;
 };
 
 /**
  * struct event - an event that can be sent and received
diff --git a/lib/of_live.c b/lib/of_live.c
index 90b9459ede313e492e28c8556c730f3bd8aaa9df..c1620616513c2e32448b4a6d156a9162d97c76b7 100644
--- a/lib/of_live.c
+++ b/lib/of_live.c
@@ -10,8 +10,9 @@ 
 
 #define LOG_CATEGORY	LOGC_DT
 
 #include <abuf.h>
+#include <event.h>
 #include <log.h>
 #include <linux/libfdt.h>
 #include <of_live.h>
 #include <malloc.h>
@@ -320,8 +321,9 @@  int unflatten_device_tree(const void *blob, struct device_node **mynodes)
 
 int of_live_build(const void *fdt_blob, struct device_node **rootp)
 {
 	int ret;
+	union event_data evt;
 
 	debug("%s: start\n", __func__);
 	ret = unflatten_device_tree(fdt_blob, rootp);
 	if (ret) {
@@ -334,8 +336,17 @@  int of_live_build(const void *fdt_blob, struct device_node **rootp)
 		return ret;
 	}
 	debug("%s: stop\n", __func__);
 
+	if (CONFIG_IS_ENABLED(EVENT)) {
+		evt.of_live_built.root = *rootp;
+		ret = event_notify(EVT_OF_LIVE_BUILT, &evt, sizeof(evt));
+		if (ret) {
+			log_debug("Failed to notify livetree build event: err=%d\n", ret);
+			return ret;
+		}
+	}
+
 	return ret;
 }
 
 void of_live_free(struct device_node *root)