diff --git a/Documentation/netlink/genetlink-legacy.yaml b/Documentation/netlink/genetlink-legacy.yaml
index 938703088306..6cb50e2cc021 100644
--- a/Documentation/netlink/genetlink-legacy.yaml
+++ b/Documentation/netlink/genetlink-legacy.yaml
@@ -200,7 +200,8 @@ properties:
                 description: The netlink attribute type
                 enum: [ unused, pad, flag, binary, bitfield32,
                         uint, sint, u8, u16, u32, u64, s32, s64,
-                        string, nest, array-nest, nest-type-value ]
+                        string, nest, array-nest, nest-type-value,
+                        sub-message ]
               doc:
                 description: Documentation of the attribute.
                 type: string
@@ -261,6 +262,15 @@ properties:
               struct:
                 description: Name of the struct type used for the attribute.
                 type: string
+              sub-message:
+                description: |
+                  Name of the sub-message definition to use for the attribute.
+                type: string
+              selector:
+                description: |
+                  Name of the attribute to use for dynamic selection of sub-message
+                  format specifier.
+                type: string
               # End genetlink-legacy
 
       # Make sure name-prefix does not appear in subsets (subsets inherit naming)
@@ -284,6 +294,41 @@ properties:
             items:
               required: [ type ]
 
+  sub-messages:
+    description: Definition of sub message attributes
+    type: array
+    items:
+      type: object
+      additionalProperties: False
+      required: [ name, formats ]
+      properties:
+        name:
+          description: Name of the sub-message definition
+          type: string
+        formats:
+          description: Dynamically selected format specifiers
+          type: array
+          items:
+            type: object
+            additionalProperties: False
+            required: [ value ]
+            properties:
+              value:
+                description: |
+                  Value to match for dynamic selection of sub-message format
+                  specifier.
+                type: string
+              fixed-header:
+                description: |
+                  Name of the struct definition to use as the fixed header
+                  for the sub message.
+                type: string
+              attribute-set:
+                description: |
+                  Name of the attribute space from which to resolve attributes
+                  in the sub message.
+                type: string
+
   operations:
     description: Operations supported by the protocol.
     type: object
diff --git a/Documentation/netlink/netlink-raw.yaml b/Documentation/netlink/netlink-raw.yaml
index ac4e05415f2f..cc38b026c451 100644
--- a/Documentation/netlink/netlink-raw.yaml
+++ b/Documentation/netlink/netlink-raw.yaml
@@ -280,8 +280,6 @@ properties:
               struct:
                 description: Name of the struct type used for the attribute.
                 type: string
-              # End genetlink-legacy
-              # Start netlink-raw
               sub-message:
                 description: |
                   Name of the sub-message definition to use for the attribute.
@@ -291,7 +289,7 @@ properties:
                   Name of the attribute to use for dynamic selection of sub-message
                   format specifier.
                 type: string
-              # End netlink-raw
+              # End genetlink-legacy
 
       # Make sure name-prefix does not appear in subsets (subsets inherit naming)
       dependencies:
@@ -314,7 +312,6 @@ properties:
             items:
               required: [ type ]
 
-  # Start netlink-raw
   sub-messages:
     description: Definition of sub message attributes
     type: array
@@ -349,7 +346,6 @@ properties:
                   Name of the attribute space from which to resolve attributes
                   in the sub message.
                 type: string
-  # End netlink-raw
 
   operations:
     description: Operations supported by the protocol.
diff --git a/Documentation/userspace-api/netlink/genetlink-legacy.rst b/Documentation/userspace-api/netlink/genetlink-legacy.rst
index 70a77387f6c4..7126b650090e 100644
--- a/Documentation/userspace-api/netlink/genetlink-legacy.rst
+++ b/Documentation/userspace-api/netlink/genetlink-legacy.rst
@@ -280,3 +280,104 @@ At the spec level we can define a ``dumps`` property for the ``do``,
 perhaps with values of ``combine`` and ``multi-object`` depending
 on how the parsing should be implemented (parse into a single reply
 vs list of objects i.e. pretty much a dump).
+
+Sub-messages
+------------
+
+Several raw netlink families such as
+:doc:`rt_link<../../networking/netlink_spec/rt_link>` and
+:doc:`tc<../../networking/netlink_spec/tc>` use attribute nesting as an
+abstraction to carry module specific information.
+
+Conceptually it looks as follows::
+
+    [OUTER NEST OR MESSAGE LEVEL]
+      [GENERIC ATTR 1]
+      [GENERIC ATTR 2]
+      [GENERIC ATTR 3]
+      [GENERIC ATTR - wrapper]
+        [MODULE SPECIFIC ATTR 1]
+        [MODULE SPECIFIC ATTR 2]
+
+The ``GENERIC ATTRs`` at the outer level are defined in the core (or rt_link or
+core TC), while specific drivers, TC classifiers, qdiscs etc. can carry their
+own information wrapped in the ``GENERIC ATTR - wrapper``. Even though the
+example above shows attributes nesting inside the wrapper, the modules generally
+have full freedom to define the format of the nest. In practice the payload of
+the wrapper attr has very similar characteristics to a netlink message. It may
+contain a fixed header / structure, netlink attributes, or both. Because of
+those shared characteristics we refer to the payload of the wrapper attribute as
+a sub-message.
+
+A sub-message attribute uses the value of another attribute as a selector key to
+choose the right sub-message format. For example if the following attribute has
+already been decoded:
+
+.. code-block:: json
+
+  { "kind": "gre" }
+
+and we encounter the following attribute spec:
+
+.. code-block:: yaml
+
+  -
+    name: data
+    type: sub-message
+    sub-message: linkinfo-data-msg
+    selector: kind
+
+Then we look for a sub-message definition called ``linkinfo-data-msg`` and use
+the value of the ``kind`` attribute i.e. ``gre`` as the key to choose the
+correct format for the sub-message:
+
+.. code-block:: yaml
+
+  sub-messages:
+    name: linkinfo-data-msg
+    formats:
+      -
+        value: bridge
+        attribute-set: linkinfo-bridge-attrs
+      -
+        value: gre
+        attribute-set: linkinfo-gre-attrs
+      -
+        value: geneve
+        attribute-set: linkinfo-geneve-attrs
+
+This would decode the attribute value as a sub-message with the attribute-set
+called ``linkinfo-gre-attrs`` as the attribute space.
+
+A sub-message can have an optional ``fixed-header`` followed by zero or more
+attributes from an ``attribute-set``. For example the following
+``tc-options-msg`` sub-message defines message formats that use a mixture of
+``fixed-header``, ``attribute-set`` or both together:
+
+.. code-block:: yaml
+
+  sub-messages:
+    -
+      name: tc-options-msg
+      formats:
+        -
+          value: bfifo
+          fixed-header: tc-fifo-qopt
+        -
+          value: cake
+          attribute-set: tc-cake-attrs
+        -
+          value: netem
+          fixed-header: tc-netem-qopt
+          attribute-set: tc-netem-attrs
+
+Note that a selector attribute must appear in a netlink message before any
+sub-message attributes that depend on it.
+
+If an attribute such as ``kind`` is defined at more than one nest level, then a
+sub-message selector will be resolved using the value 'closest' to the selector.
+For example, if the same attribute name is defined in a nested ``attribute-set``
+alongside a sub-message selector and also in a top level ``attribute-set``, then
+the selector will be resolved using the value 'closest' to the selector. If the
+value is not present in the message at the same level as defined in the spec
+then this is an error.
diff --git a/Documentation/userspace-api/netlink/netlink-raw.rst b/Documentation/userspace-api/netlink/netlink-raw.rst
index 1990eea772d0..5fb8b7cd6558 100644
--- a/Documentation/userspace-api/netlink/netlink-raw.rst
+++ b/Documentation/userspace-api/netlink/netlink-raw.rst
@@ -58,107 +58,6 @@ group registration.
         name: rtnlgrp-mctp-ifaddr
         value: 34
 
-Sub-messages
-------------
-
-Several raw netlink families such as
-:doc:`rt_link<../../networking/netlink_spec/rt_link>` and
-:doc:`tc<../../networking/netlink_spec/tc>` use attribute nesting as an
-abstraction to carry module specific information.
-
-Conceptually it looks as follows::
-
-    [OUTER NEST OR MESSAGE LEVEL]
-      [GENERIC ATTR 1]
-      [GENERIC ATTR 2]
-      [GENERIC ATTR 3]
-      [GENERIC ATTR - wrapper]
-        [MODULE SPECIFIC ATTR 1]
-        [MODULE SPECIFIC ATTR 2]
-
-The ``GENERIC ATTRs`` at the outer level are defined in the core (or rt_link or
-core TC), while specific drivers, TC classifiers, qdiscs etc. can carry their
-own information wrapped in the ``GENERIC ATTR - wrapper``. Even though the
-example above shows attributes nesting inside the wrapper, the modules generally
-have full freedom to define the format of the nest. In practice the payload of
-the wrapper attr has very similar characteristics to a netlink message. It may
-contain a fixed header / structure, netlink attributes, or both. Because of
-those shared characteristics we refer to the payload of the wrapper attribute as
-a sub-message.
-
-A sub-message attribute uses the value of another attribute as a selector key to
-choose the right sub-message format. For example if the following attribute has
-already been decoded:
-
-.. code-block:: json
-
-  { "kind": "gre" }
-
-and we encounter the following attribute spec:
-
-.. code-block:: yaml
-
-  -
-    name: data
-    type: sub-message
-    sub-message: linkinfo-data-msg
-    selector: kind
-
-Then we look for a sub-message definition called ``linkinfo-data-msg`` and use
-the value of the ``kind`` attribute i.e. ``gre`` as the key to choose the
-correct format for the sub-message:
-
-.. code-block:: yaml
-
-  sub-messages:
-    name: linkinfo-data-msg
-    formats:
-      -
-        value: bridge
-        attribute-set: linkinfo-bridge-attrs
-      -
-        value: gre
-        attribute-set: linkinfo-gre-attrs
-      -
-        value: geneve
-        attribute-set: linkinfo-geneve-attrs
-
-This would decode the attribute value as a sub-message with the attribute-set
-called ``linkinfo-gre-attrs`` as the attribute space.
-
-A sub-message can have an optional ``fixed-header`` followed by zero or more
-attributes from an ``attribute-set``. For example the following
-``tc-options-msg`` sub-message defines message formats that use a mixture of
-``fixed-header``, ``attribute-set`` or both together:
-
-.. code-block:: yaml
-
-  sub-messages:
-    -
-      name: tc-options-msg
-      formats:
-        -
-          value: bfifo
-          fixed-header: tc-fifo-qopt
-        -
-          value: cake
-          attribute-set: tc-cake-attrs
-        -
-          value: netem
-          fixed-header: tc-netem-qopt
-          attribute-set: tc-netem-attrs
-
-Note that a selector attribute must appear in a netlink message before any
-sub-message attributes that depend on it.
-
-If an attribute such as ``kind`` is defined at more than one nest level, then a
-sub-message selector will be resolved using the value 'closest' to the selector.
-For example, if the same attribute name is defined in a nested ``attribute-set``
-alongside a sub-message selector and also in a top level ``attribute-set``, then
-the selector will be resolved using the value 'closest' to the selector. If the
-value is not present in the message at the same level as defined in the spec
-then this is an error.
-
 Nested struct definitions
 -------------------------
 
