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: 8+ 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-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox