diff mbox series

[v2] fdt: Delete nodes of devices removed between boot and CAS

Message ID 158134056935.2963469.11427374783836284547.stgit@bahia.lan
State Accepted
Headers show
Series [v2] fdt: Delete nodes of devices removed between boot and CAS | expand

Commit Message

Greg Kurz Feb. 10, 2020, 1:16 p.m. UTC
We recently fixed node creation at CAS in order to support early hotplug
of devices between boot and CAS. Let's handle node removal now to support
early hot *un*plug of devices.

This is achieved by associating a generation number to each FDT received
from QEMU and tagging all nodes with this number in a "slof,from-fdt"
property. The generation number is kept in the fdt-generation# variable.
It starts at 0 for the initial boot time FDT, and it is incremented at
each subsequent CAS. All boot time nodes hence get "slof,from-fdt" == 0,
all nodes present at CAS get "slof,from-fdt" == 1 and so on in case the
guest calls CAS again. If a device gets hot unplugged before quiesce, we
hence can detect it doesn't have the right generation number and thus
delete the node from the DT. Note that this only affects nodes coming
from the FDT. Nodes created by SLOF don't have the "slof,from-fdt"
property, and therefore cannot be candidates to deletion.

Signed-off-by: Greg Kurz <groug@kaod.org>
---
v2: - global rewrite using a generation number which gets copied to
      a "slof,from-fdt" property
    - delete aliases in a separate loop
---
 board-qemu/slof/fdt.fs |   72 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)

Comments

Alexey Kardashevskiy Feb. 17, 2020, 1:06 a.m. UTC | #1
On 11/02/2020 00:16, Greg Kurz wrote:
> We recently fixed node creation at CAS in order to support early hotplug
> of devices between boot and CAS. Let's handle node removal now to support
> early hot *un*plug of devices.
> 
> This is achieved by associating a generation number to each FDT received
> from QEMU and tagging all nodes with this number in a "slof,from-fdt"
> property. The generation number is kept in the fdt-generation# variable.
> It starts at 0 for the initial boot time FDT, and it is incremented at
> each subsequent CAS. All boot time nodes hence get "slof,from-fdt" == 0,
> all nodes present at CAS get "slof,from-fdt" == 1 and so on in case the
> guest calls CAS again. If a device gets hot unplugged before quiesce, we
> hence can detect it doesn't have the right generation number and thus
> delete the node from the DT. Note that this only affects nodes coming
> from the FDT. Nodes created by SLOF don't have the "slof,from-fdt"
> property, and therefore cannot be candidates to deletion.
> 
> Signed-off-by: Greg Kurz <groug@kaod.org>
> ---
> v2: - global rewrite using a generation number which gets copied to
>       a "slof,from-fdt" property
>     - delete aliases in a separate loop



Thanks, applied.



> ---
>  board-qemu/slof/fdt.fs |   72 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 72 insertions(+)
> 
> diff --git a/board-qemu/slof/fdt.fs b/board-qemu/slof/fdt.fs
> index 66f8fe74d9dd..6a694c17517a 100644
> --- a/board-qemu/slof/fdt.fs
> +++ b/board-qemu/slof/fdt.fs
> @@ -13,6 +13,11 @@
>  1 VALUE fdt-debug
>  TRUE VALUE fdt-cas-fix?
>  0 VALUE fdt-cas-pass
> +0 VALUE fdt-generation#
> +
> +: fdt-update-from-fdt ( -- )
> +  fdt-generation# encode-int s" slof,from-fdt" property
> +;
>  
>  \ Bail out if no fdt
>  fdt-start 0 = IF -1 throw THEN
> @@ -198,6 +203,8 @@ fdt-check-header
>      decode-int dup fdt-create-dec fdt-create-enc 2drop
>    THEN
>  
> +  fdt-update-from-fdt
> +
>    finish-device  
>  ;
>  
> @@ -514,6 +521,9 @@ r> drop
>      swap			( newnode? a1 )
>  
>      fdt-debug IF ." Current  now: " pwd  get-node ."  = " . cr THEN
> +    fdt-cas-pass 0= IF
> +	fdt-update-from-fdt
> +    THEN
>      BEGIN
>  	fdt-next-tag dup OF_DT_END_NODE <>
>      WHILE
> @@ -584,8 +594,70 @@ r> drop
>      THEN
>  ;
>  
> +: alias-dev-path ( xt -- dev-path len )
> +    link> execute decode-string	2swap 2drop
> +;
> +
> +: alias-name ( xt -- alias-name len )
> +    link> >name name>string
> +;
> +
> +: fdt-cas-alias-obsolete? ( xt -- true|false )
> +    alias-dev-path find-node 0=
> +;
> +
> +: (fdt-cas-delete-obsolete-aliases) ( xt -- )
> +    dup IF
> +	dup @
> +	recurse
> +	dup alias-name s" name" str= IF ELSE
> +	    dup fdt-cas-alias-obsolete? IF
> +		fdt-debug IF ." Deleting obsolete alias: " dup alias-name type ."  -> " dup alias-dev-path type cr THEN
> +		dup alias-name
> +		delete-property
> +	    THEN
> +	THEN
> +    THEN
> +    drop
> +;
> +
> +: fdt-cas-delete-obsolete-aliases ( -- )
> +    s" /aliases" find-device
> +    get-node node>properties @ cell+ @ (fdt-cas-delete-obsolete-aliases)
> +    device-end
> +;
> +
> +: fdt-cas-node-obsolete? ( node -- true|false)
> +    s" slof,from-fdt" rot get-package-property IF
> +	\ Not a QEMU originated node
> +	false
> +    ELSE
> +	decode-int nip nip fdt-generation# <
> +    THEN
> +;
> +
> +: (fdt-cas-search-obsolete-nodes) ( start node -- )
> +    dup IF
> +	dup child 2 pick swap recurse
> +	dup peer 2 pick swap recurse
> +
> +	dup fdt-cas-node-obsolete? IF
> +	    fdt-debug IF dup ." Deleting obsolete node: " dup .node ." = " . cr THEN
> +	    dup delete-node
> +	THEN
> +    THEN
> +    2drop
> +;
> +
> +: fdt-cas-delete-obsolete-nodes ( start -- )
> +    s" /" find-device get-node (fdt-cas-search-obsolete-nodes)
> +    fdt-cas-delete-obsolete-aliases
> +;
> +
>  : fdt-fix-cas-node ( start -- )
> +    fdt-generation# 1+ to fdt-generation#
>      0 to fdt-cas-pass dup (fdt-fix-cas-node) drop \ Add phandles
> +    dup fdt-cas-delete-obsolete-nodes             \ Delete removed devices
>      1 to fdt-cas-pass dup (fdt-fix-cas-node) drop \ Patch+add other properties
>      2 to fdt-cas-pass dup (fdt-fix-cas-node) drop \ Delete phandles from pass 0
>      drop
>
diff mbox series

Patch

diff --git a/board-qemu/slof/fdt.fs b/board-qemu/slof/fdt.fs
index 66f8fe74d9dd..6a694c17517a 100644
--- a/board-qemu/slof/fdt.fs
+++ b/board-qemu/slof/fdt.fs
@@ -13,6 +13,11 @@ 
 1 VALUE fdt-debug
 TRUE VALUE fdt-cas-fix?
 0 VALUE fdt-cas-pass
+0 VALUE fdt-generation#
+
+: fdt-update-from-fdt ( -- )
+  fdt-generation# encode-int s" slof,from-fdt" property
+;
 
 \ Bail out if no fdt
 fdt-start 0 = IF -1 throw THEN
@@ -198,6 +203,8 @@  fdt-check-header
     decode-int dup fdt-create-dec fdt-create-enc 2drop
   THEN
 
+  fdt-update-from-fdt
+
   finish-device  
 ;
 
@@ -514,6 +521,9 @@  r> drop
     swap			( newnode? a1 )
 
     fdt-debug IF ." Current  now: " pwd  get-node ."  = " . cr THEN
+    fdt-cas-pass 0= IF
+	fdt-update-from-fdt
+    THEN
     BEGIN
 	fdt-next-tag dup OF_DT_END_NODE <>
     WHILE
@@ -584,8 +594,70 @@  r> drop
     THEN
 ;
 
+: alias-dev-path ( xt -- dev-path len )
+    link> execute decode-string	2swap 2drop
+;
+
+: alias-name ( xt -- alias-name len )
+    link> >name name>string
+;
+
+: fdt-cas-alias-obsolete? ( xt -- true|false )
+    alias-dev-path find-node 0=
+;
+
+: (fdt-cas-delete-obsolete-aliases) ( xt -- )
+    dup IF
+	dup @
+	recurse
+	dup alias-name s" name" str= IF ELSE
+	    dup fdt-cas-alias-obsolete? IF
+		fdt-debug IF ." Deleting obsolete alias: " dup alias-name type ."  -> " dup alias-dev-path type cr THEN
+		dup alias-name
+		delete-property
+	    THEN
+	THEN
+    THEN
+    drop
+;
+
+: fdt-cas-delete-obsolete-aliases ( -- )
+    s" /aliases" find-device
+    get-node node>properties @ cell+ @ (fdt-cas-delete-obsolete-aliases)
+    device-end
+;
+
+: fdt-cas-node-obsolete? ( node -- true|false)
+    s" slof,from-fdt" rot get-package-property IF
+	\ Not a QEMU originated node
+	false
+    ELSE
+	decode-int nip nip fdt-generation# <
+    THEN
+;
+
+: (fdt-cas-search-obsolete-nodes) ( start node -- )
+    dup IF
+	dup child 2 pick swap recurse
+	dup peer 2 pick swap recurse
+
+	dup fdt-cas-node-obsolete? IF
+	    fdt-debug IF dup ." Deleting obsolete node: " dup .node ." = " . cr THEN
+	    dup delete-node
+	THEN
+    THEN
+    2drop
+;
+
+: fdt-cas-delete-obsolete-nodes ( start -- )
+    s" /" find-device get-node (fdt-cas-search-obsolete-nodes)
+    fdt-cas-delete-obsolete-aliases
+;
+
 : fdt-fix-cas-node ( start -- )
+    fdt-generation# 1+ to fdt-generation#
     0 to fdt-cas-pass dup (fdt-fix-cas-node) drop \ Add phandles
+    dup fdt-cas-delete-obsolete-nodes             \ Delete removed devices
     1 to fdt-cas-pass dup (fdt-fix-cas-node) drop \ Patch+add other properties
     2 to fdt-cas-pass dup (fdt-fix-cas-node) drop \ Delete phandles from pass 0
     drop