From: Sven Peter <sven@kernel.org>
To: Rob Herring <robh@kernel.org>, Saravana Kannan <saravanak@kernel.org>
Cc: Daniel Golle <daniel@makrotopia.org>,
Krzysztof Kozlowski <krzk@kernel.org>,
linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
asahi@lists.linux.dev, Sven Peter <sven@kernel.org>
Subject: [PATCH 1/2] dt-check-style: Handle indented fragments in indent-unit-dts
Date: Sun, 30 Aug 2026 20:24:54 +0200 [thread overview]
Message-ID: <20260830-b4-dts-check-fix-v1-1-e7c1b2774730@kernel.org> (raw)
In-Reply-To: <20260830-b4-dts-check-fix-v1-0-e7c1b2774730@kernel.org>
The multi-die Apple SoCs contain most of their nodes in a file that is
included to instantiate the same nodes across both dies. These included
fragments all have a tabs-only prefix that is correct in the final
composed file. dt-check-style however finds the first line starting with
two (or more) tabs and then indent-unit-dts rejects those correctly
indented files.
Fix that by detecing a tabs-only prefix shared by rootless files and
treat that as a constant offset. Also add fixtures to test this.
Signed-off-by: Sven Peter <sven@kernel.org>
---
scripts/dtc/dt-check-style | 69 +++++++++++++++++-----
.../bad/dts-fragment-missing-prefix.dtsi | 6 ++
.../bad/dts-indented-ref-node.dtsi | 6 ++
.../expected/dts-fragment-missing-prefix.dtsi.txt | 2 +
.../expected/dts-indented-ref-node.dtsi.txt | 2 +
5 files changed, 70 insertions(+), 15 deletions(-)
diff --git a/scripts/dtc/dt-check-style b/scripts/dtc/dt-check-style
index 96deffc0d8a7..2afc05fa6602 100755
--- a/scripts/dtc/dt-check-style
+++ b/scripts/dtc/dt-check-style
@@ -380,12 +380,43 @@ def check_mixed_indent_chars(ctx):
yield (cont.lineno, 'mixed tabs and spaces in indent')
+def detect_fragment_offset(ctx):
+ """Return the indentation inherited from an include context.
+
+ A fragment has neither a root nor top-level reference nodes and all
+ its top-level lines share the same tabs-only indentation.
+ """
+ if ctx.file_type != 'dts':
+ return ''
+ offset = None
+ for dl in ctx.lines:
+ if dl.depth != 0:
+ continue
+ if dl.linetype not in (LineType.NODE_OPEN, LineType.NODE_CLOSE,
+ LineType.PROPERTY):
+ continue
+ if dl.linetype == LineType.NODE_OPEN and \
+ (dl.node_name == '/' or dl.ref_name is not None):
+ return ''
+ if offset is None:
+ offset = dl.indent_str
+ elif dl.indent_str != offset:
+ return ''
+ if not offset:
+ return ''
+ if any(char != '\t' for char in offset):
+ return ''
+ return offset
+
+
def detect_indent_unit(ctx):
"""Find the indent unit used at depth 1 in this block.
Returns tuple of string (one of: ' ' (2 spaces), ' ' (4 spaces),
- '\\t' (tab), or None if depth-1 is empty or ambiguous) and line number when
- detection was made)."""
+ '\\t' (tab), or None if depth-1 is empty or ambiguous), line number when
+ detection was made, and whether the detected fragment prefix is valid.
+ """
+ prefix = detect_fragment_offset(ctx)
for dl in ctx.lines:
if dl.depth != 1:
continue
@@ -395,20 +426,25 @@ def detect_indent_unit(ctx):
continue
if not dl.indent_str:
continue
- if dl.indent_str == '\t':
- return ('\t', dl.lineno)
- if dl.indent_str == ' ':
- return (' ', dl.lineno)
- if dl.indent_str == ' ':
- return (' ', dl.lineno)
+ indent = dl.indent_str
+ if prefix and not indent.startswith(prefix):
+ return (indent, dl.lineno, False)
+ if prefix:
+ indent = indent[len(prefix):]
+ if indent == '\t':
+ return ('\t', dl.lineno, True)
+ if indent == ' ':
+ return (' ', dl.lineno, True)
+ if indent == ' ':
+ return (' ', dl.lineno, True)
# Anything else at depth 1 is non-canonical; flag elsewhere.
- return (dl.indent_str, dl.lineno)
- return (None, None)
+ return (indent, dl.lineno, True)
+ return (None, None, True)
def check_indent_unit_relaxed(ctx):
"""YAML examples: 2 or 4 spaces. Never tabs or other widths."""
- (unit, lineno) = detect_indent_unit(ctx)
+ (unit, lineno, _) = detect_indent_unit(ctx)
if unit is None:
return
if unit not in (' ', ' '):
@@ -417,7 +453,10 @@ def check_indent_unit_relaxed(ctx):
def check_indent_unit_dts(ctx):
"""DTS files: 1 tab per level. Always required."""
- (unit, lineno) = detect_indent_unit(ctx)
+ (unit, lineno, prefix_valid) = detect_indent_unit(ctx)
+ if not prefix_valid:
+ yield (lineno, 'indent does not start with fragment offset')
+ return
if unit is None:
return
if unit != '\t':
@@ -426,7 +465,7 @@ def check_indent_unit_dts(ctx):
def check_indent_unit_strict(ctx):
"""YAML: must be exactly 4 spaces. DTS: 1 tab (same as relaxed)."""
- (unit, lineno) = detect_indent_unit(ctx)
+ (unit, lineno, _) = detect_indent_unit(ctx)
if unit is None:
return
if ctx.file_type == 'yaml':
@@ -437,8 +476,8 @@ def check_indent_unit_strict(ctx):
def check_indent_consistent(ctx):
"""All indented lines must be a multiple of the detected unit."""
- (unit, lineno) = detect_indent_unit(ctx)
- if unit is None:
+ (unit, lineno, prefix_valid) = detect_indent_unit(ctx)
+ if unit is None or not prefix_valid:
return
if ctx.file_type == 'yaml':
if unit not in (' ', ' '):
diff --git a/scripts/dtc/dt-style-selftest/bad/dts-fragment-missing-prefix.dtsi b/scripts/dtc/dt-style-selftest/bad/dts-fragment-missing-prefix.dtsi
new file mode 100644
index 000000000000..a72735e0884b
--- /dev/null
+++ b/scripts/dtc/dt-style-selftest/bad/dts-fragment-missing-prefix.dtsi
@@ -0,0 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+/* Include fragment whose child does not contain the inherited indentation. */
+
+ bus@10000 {
+ compatible = "simple-bus";
+ };
diff --git a/scripts/dtc/dt-style-selftest/bad/dts-indented-ref-node.dtsi b/scripts/dtc/dt-style-selftest/bad/dts-indented-ref-node.dtsi
new file mode 100644
index 000000000000..cabe4ee96d10
--- /dev/null
+++ b/scripts/dtc/dt-style-selftest/bad/dts-indented-ref-node.dtsi
@@ -0,0 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+/* Reference nodes must remain at column zero. */
+
+ &example {
+ status = "okay";
+ };
diff --git a/scripts/dtc/dt-style-selftest/expected/dts-fragment-missing-prefix.dtsi.txt b/scripts/dtc/dt-style-selftest/expected/dts-fragment-missing-prefix.dtsi.txt
new file mode 100644
index 000000000000..eb525dddd904
--- /dev/null
+++ b/scripts/dtc/dt-style-selftest/expected/dts-fragment-missing-prefix.dtsi.txt
@@ -0,0 +1,2 @@
+# mode=relaxed
+bad/dts-fragment-missing-prefix.dtsi:5: [indent-unit-dts] indent does not start with fragment offset
diff --git a/scripts/dtc/dt-style-selftest/expected/dts-indented-ref-node.dtsi.txt b/scripts/dtc/dt-style-selftest/expected/dts-indented-ref-node.dtsi.txt
new file mode 100644
index 000000000000..ed86cc9b36c6
--- /dev/null
+++ b/scripts/dtc/dt-style-selftest/expected/dts-indented-ref-node.dtsi.txt
@@ -0,0 +1,2 @@
+# mode=strict
+bad/dts-indented-ref-node.dtsi:5: [indent-unit-dts] indent unit must be 1 tab in DTS, got '\t\t'
--
2.55.0
next prev parent reply other threads:[~2026-08-30 18:25 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-30 18:24 [PATCH 0/2] dt-check-style support for indented include fragments Sven Peter
2026-08-30 18:24 ` Sven Peter [this message]
2026-09-01 8:21 ` [PATCH 1/2] dt-check-style: Handle indented fragments in indent-unit-dts Krzysztof Kozlowski
2026-08-30 18:24 ` [PATCH 2/2] dt-check-style: Handle indented fragments in indent-consistent Sven Peter
2026-08-30 18:29 ` sashiko-bot
2026-09-01 8:22 ` Krzysztof Kozlowski
2026-09-01 8:49 ` Sven Peter
2026-09-01 9:40 ` Krzysztof Kozlowski
2026-09-01 9:53 ` Krzysztof Kozlowski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260830-b4-dts-check-fix-v1-1-e7c1b2774730@kernel.org \
--to=sven@kernel.org \
--cc=asahi@lists.linux.dev \
--cc=daniel@makrotopia.org \
--cc=devicetree@vger.kernel.org \
--cc=krzk@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=robh@kernel.org \
--cc=saravanak@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.