Linux Documentation
 help / color / mirror / Atom feed
* Re: [PATCH v3 4/5] watchdog: Separate kind of documentation
From: Guenter Roeck @ 2026-05-05 13:11 UTC (permalink / raw)
  To: Philipp Hahn
  Cc: Wim Van Sebroeck, Philipp Hahn, linux-watchdog, linux-doc,
	linux-kernel
In-Reply-To: <7d1b722205bab83603832e66750f7b5f1f73eaa5.1777972790.git.phahn-oss@avm.de>

On Tue, May 05, 2026 at 11:26:15AM +0200, Philipp Hahn wrote:
> From: Philipp Hahn <phahn-oss@avm.de>
> 
> Currently there are several (sub-)documents for "Generic kernel
> infrastructure API" and several "driver specific" documents. Put each
> one into its own sub-section.
> 
> Signed-off-by: Philipp Hahn <phahn-oss@avm.de>

Applied to my watchdog-next branch

Thanks,
Guenter

^ permalink raw reply

* Re: [PATCH v3 5/5] watchdog: Prefix WDT with ICS for clarity
From: Guenter Roeck @ 2026-05-05 13:12 UTC (permalink / raw)
  To: Philipp Hahn
  Cc: Wim Van Sebroeck, Philipp Hahn, linux-watchdog, linux-doc,
	linux-kernel
In-Reply-To: <5a71979d8e8ab8e0a30de33f6aa2540b3b5dc1ee.1777972790.git.phahn-oss@avm.de>

On Tue, May 05, 2026 at 11:26:16AM +0200, Philipp Hahn wrote:
> From: Philipp Hahn <phahn-oss@avm.de>
> 
> `wdt.rst` is only about the Watchdog from "Industrial Computer Source"
> (ICS). Change the title and rename the file to better express this.
> 
> Add missing SPDX license identifier `GPL-2.0-or-later` same as code to
> silence `checkpatch`.
> 
> Fix wrong link to sample driver in drivers/watchdog/smsc37b787_wdt.c.
> 
> Signed-off-by: Philipp Hahn <phahn-oss@avm.de>

Applied to my watchdog-next branch.

Thanks,
Guenter

^ permalink raw reply

* [PATCH net-next v5 2/5] net: add dev->bql flag to allow BQL sysfs for IFF_NO_QUEUE devices
From: hawk @ 2026-05-05 13:21 UTC (permalink / raw)
  To: netdev
  Cc: hawk, kernel-team, Jonas Köppeler, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Jonathan Corbet, Shuah Khan, Kuniyuki Iwashima,
	Stanislav Fomichev, Christian Brauner, Yury Norov, Krishna Kumar,
	Yajun Deng, linux-doc, linux-kernel
In-Reply-To: <20260505132159.241305-1-hawk@kernel.org>

From: Jesper Dangaard Brouer <hawk@kernel.org>

Virtual devices with IFF_NO_QUEUE or lltx are excluded from BQL sysfs
by netdev_uses_bql(), since they traditionally lack real hardware
queues. However, some virtual devices like veth implement a real
ptr_ring FIFO with NAPI processing and benefit from BQL to limit
in-flight bytes and reduce latency.

Add a per-device 'bql' bitfield boolean in the priv_flags_slow section
of struct net_device. When set, it overrides the IFF_NO_QUEUE/lltx
exclusion and exposes BQL sysfs entries (/sys/class/net/<dev>/queues/
tx-<n>/byte_queue_limits/). The flag is still gated on CONFIG_BQL.

This allows drivers that use BQL despite being IFF_NO_QUEUE to opt in
to sysfs visibility for monitoring and debugging.

Signed-off-by: Jesper Dangaard Brouer <hawk@kernel.org>
Tested-by: Jonas Köppeler <j.koeppeler@tu-berlin.de>
---
 Documentation/networking/net_cachelines/net_device.rst | 1 +
 include/linux/netdevice.h                              | 2 ++
 net/core/net-sysfs.c                                   | 8 +++++++-
 3 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/Documentation/networking/net_cachelines/net_device.rst b/Documentation/networking/net_cachelines/net_device.rst
index 1c19bb7705df..b775d3235a2d 100644
--- a/Documentation/networking/net_cachelines/net_device.rst
+++ b/Documentation/networking/net_cachelines/net_device.rst
@@ -170,6 +170,7 @@ unsigned_long:1                     see_all_hwtstamp_requests
 unsigned_long:1                     change_proto_down
 unsigned_long:1                     netns_immutable
 unsigned_long:1                     fcoe_mtu
+unsigned_long:1                     bql                                                                 netdev_uses_bql(net-sysfs.c)
 struct list_head                    net_notifier_list
 struct macsec_ops*                  macsec_ops
 struct udp_tunnel_nic_info*         udp_tunnel_nic_info
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 744ffa243501..d4c7b020b6a7 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2065,6 +2065,7 @@ enum netdev_reg_state {
  *	@change_proto_down: device supports setting carrier via IFLA_PROTO_DOWN
  *	@netns_immutable: interface can't change network namespaces
  *	@fcoe_mtu:	device supports maximum FCoE MTU, 2158 bytes
+ *	@bql:		device uses BQL (DQL sysfs) despite having IFF_NO_QUEUE
  *
  *	@net_notifier_list:	List of per-net netdev notifier block
  *				that follow this device when it is moved
@@ -2479,6 +2480,7 @@ struct net_device {
 	unsigned long		change_proto_down:1;
 	unsigned long		netns_immutable:1;
 	unsigned long		fcoe_mtu:1;
+	unsigned long		bql:1;
 
 	struct list_head	net_notifier_list;
 
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 3318b5666e43..82833e5dae03 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -1945,10 +1945,16 @@ static const struct kobj_type netdev_queue_ktype = {
 
 static bool netdev_uses_bql(const struct net_device *dev)
 {
+	if (!IS_ENABLED(CONFIG_BQL))
+		return false;
+
+	if (dev->bql)
+		return true;
+
 	if (dev->lltx || (dev->priv_flags & IFF_NO_QUEUE))
 		return false;
 
-	return IS_ENABLED(CONFIG_BQL);
+	return true;
 }
 
 static int netdev_queue_add_kobject(struct net_device *dev, int index)
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH v9 2/6] iio: adc: ad4691: add initial driver for AD4691 family
From: Jonathan Cameron @ 2026-05-05 13:23 UTC (permalink / raw)
  To: Radu Sabau via B4 Relay
  Cc: radu.sabau, Lars-Peter Clausen, Michael Hennerich, David Lechner,
	Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Uwe Kleine-König, Liam Girdwood, Mark Brown,
	Linus Walleij, Bartosz Golaszewski, Philipp Zabel,
	Jonathan Corbet, Shuah Khan, linux-iio, devicetree, linux-kernel,
	linux-pwm, linux-gpio, linux-doc
In-Reply-To: <20260430-ad4692-multichannel-sar-adc-driver-v9-2-33e439e4fb87@analog.com>

On Thu, 30 Apr 2026 13:16:44 +0300
Radu Sabau via B4 Relay <devnull+radu.sabau.analog.com@kernel.org> wrote:

> From: Radu Sabau <radu.sabau@analog.com>
> 
> Add support for the Analog Devices AD4691 family of high-speed,
> low-power multichannel SAR ADCs: AD4691 (16-ch, 500 kSPS),
> AD4692 (16-ch, 1 MSPS), AD4693 (8-ch, 500 kSPS) and
> AD4694 (8-ch, 1 MSPS).
> 
> The driver implements a custom regmap layer over raw SPI to handle the
> device's mixed 1/2/3/4-byte register widths and uses the standard IIO
> read_raw/write_raw interface for single-channel reads.
> 
> The chip idles in Autonomous Mode so that single-shot read_raw can use
> the internal oscillator without disturbing the hardware configuration.
> 
> Three voltage supply domains are managed: avdd (required), vio, and a
> reference supply on either the REF pin (ref-supply, external buffer)
> or the REFIN pin (refin-supply, uses the on-chip reference buffer;
> REFBUF_EN is set accordingly). Hardware reset is performed via
> the reset controller framework; a software reset through SPI_CONFIG_A
> is used as fallback when no hardware reset is available.
> 
> Accumulator channel masking for single-shot reads uses ACC_MASK_REG via
> an ADDR_DESCENDING SPI write, which covers both mask bytes in a single
> 16-bit transfer.
> 
> Reviewed-by: David Lechner <dlechner@baylibre.com>
> Signed-off-by: Radu Sabau <radu.sabau@analog.com>
Hi Radu

Just one query that Sashiko raised that made me look 
closer at how you are handling different register sizes.
https://sashiko.dev/#/patchset/20260430-ad4692-multichannel-sar-adc-driver-v9-0-33e439e4fb87%40analog.com

There was also a question about whether the sampling frequency control would
be better described as shared by all.

> diff --git a/drivers/iio/adc/ad4691.c b/drivers/iio/adc/ad4691.c
> new file mode 100644
> index 000000000000..05826b762c7f
> --- /dev/null
> +++ b/drivers/iio/adc/ad4691.c


> +static int ad4691_reg_read(void *context, unsigned int reg, unsigned int *val)
> +{
> +	struct spi_device *spi = context;
> +	u8 tx[2], rx[4];
> +	int ret;
> +
> +	/* Set bit 15 to mark the operation as READ. */
> +	put_unaligned_be16(0x8000 | reg, tx);
> +
> +	switch (reg) {
> +	case 0 ... AD4691_OSC_FREQ_REG:
> +	case AD4691_SPARE_CONTROL ... AD4691_ACC_SAT_OVR_REG(15):

Sashiko raised a query here.
"Will this result in a truncated 1-byte read for AD4691_ACC_MASK_REG (0x185)?
AD4691_ACC_MASK_REG falls into the range between AD4691_SPARE_CONTROL and
AD4691_ACC_SAT_OVR_REG(15). In ad4691_reg_write(), AD4691_ACC_MASK_REG is
handled explicitly alongside AD4691_STD_SEQ_CONFIG to perform a 16-bit
write, but it seems missing from the 2-byte read block here."

Just to check - the reasoning behind not just treating these as
fixed sized registers and using bulk reads and writes is the statement
about them being invalid if partially written?

The ACK_MASK_REG is documented as two separate 8 bit registers so why
attempt to treat it as a larger one?


> +		ret = spi_write_then_read(spi, tx, sizeof(tx), rx, 1);
> +		if (ret)
> +			return ret;
> +		*val = rx[0];
> +		return 0;
> +	case AD4691_STD_SEQ_CONFIG:
> +	case AD4691_AVG_IN(0) ... AD4691_AVG_IN(15):
> +		ret = spi_write_then_read(spi, tx, sizeof(tx), rx, 2);
> +		if (ret)
> +			return ret;
> +		*val = get_unaligned_be16(rx);
> +		return 0;
> +	case AD4691_AVG_STS_IN(0) ... AD4691_AVG_STS_IN(15):
> +	case AD4691_ACC_IN(0) ... AD4691_ACC_IN(15):
> +		ret = spi_write_then_read(spi, tx, sizeof(tx), rx, 3);
> +		if (ret)
> +			return ret;
> +		*val = get_unaligned_be24(rx);
> +		return 0;
> +	case AD4691_ACC_STS_DATA(0) ... AD4691_ACC_STS_DATA(15):
> +		ret = spi_write_then_read(spi, tx, sizeof(tx), rx, 4);
> +		if (ret)
> +			return ret;
> +		*val = get_unaligned_be32(rx);
> +		return 0;
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +
> +static int ad4691_reg_write(void *context, unsigned int reg, unsigned int val)
> +{
> +	struct spi_device *spi = context;
> +	u8 tx[4];
> +
> +	put_unaligned_be16(reg, tx);
> +
> +	switch (reg) {
> +	case 0 ... AD4691_OSC_FREQ_REG:
> +	case AD4691_SPARE_CONTROL ... AD4691_ACC_MASK_REG - 1:
> +	case AD4691_ACC_MASK_REG + 1 ... AD4691_GPIO_MODE2_REG:
> +		if (val > U8_MAX)
> +			return -EINVAL;
> +		tx[2] = val;
> +		return spi_write_then_read(spi, tx, 3, NULL, 0);
> +	case AD4691_ACC_MASK_REG:
> +	case AD4691_STD_SEQ_CONFIG:
> +		if (val > U16_MAX)
> +			return -EINVAL;
> +		put_unaligned_be16(val, &tx[2]);
> +		return spi_write_then_read(spi, tx, 4, NULL, 0);
> +	default:
> +		return -EINVAL;
> +	}
> +}


^ permalink raw reply

* [PATCH v2 01/11] docs: maintainers_include: keep hidden TOC sorted
From: Mauro Carvalho Chehab @ 2026-05-05 13:25 UTC (permalink / raw)
  To: Jonathan Corbet, Linux Doc Mailing List, Mauro Carvalho Chehab
  Cc: Mauro Carvalho Chehab, linux-kernel, rust-for-linux, Shuah Khan
In-Reply-To: <cover.1777987027.git.mchehab+huawei@kernel.org>

There's no practical difference on keeping it sorted, but
it helps a lot when checking for differences after patches
to the tool.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
 Documentation/sphinx/maintainers_include.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/sphinx/maintainers_include.py b/Documentation/sphinx/maintainers_include.py
index 436e7ac42ffc..694cdbdc4caf 100755
--- a/Documentation/sphinx/maintainers_include.py
+++ b/Documentation/sphinx/maintainers_include.py
@@ -265,7 +265,7 @@ class MaintainersProfile(Include):
         output += "\n.. toctree::\n"
         output += "   :hidden:\n\n"
 
-        for fname in maint_parser.profile_toc:
+        for fname in sorted(maint_parser.profile_toc):
             output += f"   {fname}\n"
 
         output += "\n"
-- 
2.54.0


^ permalink raw reply related

* [PATCH v2 00/11] Improve process/maintainers output
From: Mauro Carvalho Chehab @ 2026-05-05 13:25 UTC (permalink / raw)
  To: Benno Lossin, Gary Guo, Jonathan Corbet, Mauro Carvalho Chehab,
	Miguel Ojeda
  Cc: Mauro Carvalho Chehab, linux-doc, linux-kernel, rust-for-linux,
	Björn Roy Baron, Alice Ryhl, Andreas Hindborg, Andrew Morton,
	Boqun Feng, Danilo Krummrich, Joe Perches, Matteo Croce,
	Shuah Khan, Trevor Gross

Hi Jon,

This series improve the output at process/maintainers: instead of a
pure enriched text, the maintainer's file content is now converted
to a table, and has gained a javascript to allow filtering entries.

The initial patches change the logic to split parsing from
output generation. Then, everything is stored into a dict at
the parsing phase, and ona header description variable.

This way, it is easier to adjust the output handler to produce
a more structured document. Right now, the entries are sorted
alphabetically, per subsystem's name(*).

(*) Currently, MAINTAINERS file has several entries not sorted.
    One has to run:

	 scripts/parse-maintainers.pl --input MAINTAINERS --output MAINTAINERS.new

    to sort it.

-

v2:
  - now, entries are sorted internally, instead of trusting that
    MAINTAINERS is already sorted;
  - file fields inside the description are now showing as literals;
  - Added a change in MAINTAINERS for rust-init profile;
  - Make it clearer at MAINTAINERS description that "P" expects
    a rst file;
  - fixed several bugs related to using or not O=DOCS.

Mauro Carvalho Chehab (11):
  docs: maintainers_include: keep hidden TOC sorted
  docs: maintainers_include: split state machine on multiple funcs
  docs: maintainers_include: cleanup the code
  docs: maintainers_include: clean most SPHINXDIRS=process warnings
  docs: maintainers_include: do some coding style cleanups
  docs: maintainers_include: store maintainers entries on a dict
  docs: maintainers_include: properly handle file patterns
  docs: maintainers_include: add a filtering javascript
  docs: maintainers_include: don't ignore invalid profile entries
  MAINTAINERS: make clearer about what's expected for "P" field
  MAINTAINERS: use a URL for pin-init maintainer's profile entry

 Documentation/sphinx/maintainers_include.py | 414 ++++++++++++--------
 MAINTAINERS                                 |   4 +-
 rust/pin-init/CONTRIBUTING.md               |  72 ----
 3 files changed, 256 insertions(+), 234 deletions(-)
 delete mode 100644 rust/pin-init/CONTRIBUTING.md

-- 
2.54.0


^ permalink raw reply

* [PATCH v2 04/11] docs: maintainers_include: clean most SPHINXDIRS=process warnings
From: Mauro Carvalho Chehab @ 2026-05-05 13:25 UTC (permalink / raw)
  To: Jonathan Corbet, Linux Doc Mailing List, Mauro Carvalho Chehab
  Cc: Mauro Carvalho Chehab, linux-kernel, rust-for-linux, Shuah Khan
In-Reply-To: <cover.1777987027.git.mchehab+huawei@kernel.org>

building docs with SPHINXDIRS=process is too noisy, as it
generates lots of undefined refs. Fixing it is easy: just let
linkify generate html URLs for the broken links when SPHINXDIRS
is used.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
 Documentation/sphinx/maintainers_include.py | 44 +++++++++++++++------
 1 file changed, 32 insertions(+), 12 deletions(-)

diff --git a/Documentation/sphinx/maintainers_include.py b/Documentation/sphinx/maintainers_include.py
index 615af227a8f8..d3ad01e5309e 100755
--- a/Documentation/sphinx/maintainers_include.py
+++ b/Documentation/sphinx/maintainers_include.py
@@ -58,8 +58,8 @@ class MaintainersParser:
         self.field_content = ""
         self.subsystem_name = None
 
-        self.app_dir = app_dir
-        self.base_dir, self.doc_dir, self.sphinx_dir = app_dir.partition("Documentation")
+        self.app_dir = os.path.abspath(app_dir)
+        self.base_dir, _, self.sphinx_dir = self.app_dir.partition("Documentation")
 
         self.re_doc = re.compile(r'(Documentation/([^\s\?\*]*)\.rst)')
 
@@ -104,10 +104,25 @@ class MaintainersParser:
 
     def linkify(self, text):
         """Linkify all non-wildcard refs to ReST files in Documentation/"""
+
         m = self.re_doc.search(text)
         if m:
-            # maintainers.rst is in a subdirectory, so include "../".
-            text = self.re_doc.sub(':doc:`%s <../%s>`' % (m.group(2), m.group(2)), text)
+            fname = m.group(1)
+            ename = m.group(2)
+
+            entry = os.path.relpath(self.base_dir + fname, self.app_dir)
+            entry = entry.removesuffix(".rst")
+
+            #
+            # When SPHINXDIRS is used, it will try to reference files
+            # outside srctree, causing warnings. To avoid that, point
+            # to the latest official documentation
+            #
+            if entry.startswith("../"):
+                html = KERNELDOC_URL + ename + ".html"
+                text = self.re_doc.sub(f'`{ename} <{html}>`_', text)
+            else:
+                text = self.re_doc.sub(f':doc:`{ename} </{entry}>`', text)
 
         return text
 
@@ -176,27 +191,32 @@ class MaintainersParser:
         if field == "P":
             match = self.re_doc.match(details)
             if match:
-                name = "".join(match.groups())
-                entry = os.path.relpath(self.base_dir + name, self.app_dir)
+                fname = match.group(1)
+                ename = match.group(2)
 
-                full_name = os.path.join(self.base_dir, name)
-                path = os.path.relpath(full_name, self.app_dir)
+                entry = os.path.relpath(self.base_dir + fname, self.app_dir)
+                entry = entry.removesuffix(".rst")
                 #
                 # When SPHINXDIRS is used, it will try to reference files
                 # outside srctree, causing warnings. To avoid that, point
                 # to the latest official documentation
                 #
-                if path.startswith("../"):
-                    entry = KERNELDOC_URL + "/" + match.group(2) + ".html"
+
+                if entry.startswith("../"):
+                    entry = KERNELDOC_URL + ename + ".html"
                 else:
                     entry = "/" + entry
 
                 if "*" in entry:
                     for e in glob(entry):
-                        self.profile_toc.add(e)
+                        if "html" not in e:
+                            self.profile_toc.add(e)
+
                         self.profile_entries[self.subsystem_name] = e
                 else:
-                    self.profile_toc.add(entry)
+                    if "html" not in entry:
+                        self.profile_toc.add(entry)
+
                     self.profile_entries[self.subsystem_name] = entry
             else:
                 match = re.match(r"(https?://.*)", details)
-- 
2.54.0


^ permalink raw reply related

* [PATCH v2 02/11] docs: maintainers_include: split state machine on multiple funcs
From: Mauro Carvalho Chehab @ 2026-05-05 13:25 UTC (permalink / raw)
  To: Jonathan Corbet, Linux Doc Mailing List, Mauro Carvalho Chehab
  Cc: Mauro Carvalho Chehab, linux-kernel, rust-for-linux, Shuah Khan
In-Reply-To: <cover.1777987027.git.mchehab+huawei@kernel.org>

Instead of one big __init__ code, split the MaintainersParser
code in a way that the state machine remains on __init__, but
the actual parser for descriptions and subsystems are moved
to separate functions.

To make parser easier, instead storing parsed results on a list,
place them directly on a string.

That granted 15% of performance increase(*) with Python 3.14 and
made the logic simpler.

(*) measured by creating a new directory under Documentation/,
    and placing justmaintainers.rst and an index file there,
    building it via sphinx-build-wrapper.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
 Documentation/sphinx/maintainers_include.py | 297 +++++++++++---------
 1 file changed, 158 insertions(+), 139 deletions(-)

diff --git a/Documentation/sphinx/maintainers_include.py b/Documentation/sphinx/maintainers_include.py
index 694cdbdc4caf..6d47d55f5b73 100755
--- a/Documentation/sphinx/maintainers_include.py
+++ b/Documentation/sphinx/maintainers_include.py
@@ -47,167 +47,186 @@ class MaintainersParser:
         self.profile_toc = set()
         self.profile_entries = {}
 
-        result = list()
-        result.append(".. _maintainers:")
-        result.append("")
+        self.output = ".. _maintainers:\n\n"
 
         # Poor man's state machine.
-        descriptions = False
-        maintainers = False
-        subsystems = False
+        self.descriptions = False
+        self.maintainers = False
+        self.subsystems = False
 
         # Field letter to field name mapping.
-        field_letter = None
-        fields = dict()
+        self.field_letter = None
+        self.fields = dict()
+
+        self.field_prev = ""
+        self.field_content = ""
+        self.subsystem_name = None
+
+        self.app_dir = app_dir
+        self.base_dir, self.doc_dir, self.sphinx_dir = app_dir.partition("Documentation")
+
+        self.re_doc = re.compile(r'(Documentation/([^\s\?\*]*)\.rst)')
 
         prev = None
-        field_prev = ""
-        field_content = ""
-        subsystem_name = None
-
-        base_dir, doc_dir, sphinx_dir = app_dir.partition("Documentation")
-
         for line in open(path):
-            # Have we reached the end of the preformatted Descriptions text?
-            if descriptions and line.startswith('Maintainers'):
-                descriptions = False
-                # Ensure a blank line following the last "|"-prefixed line.
-                result.append("")
-
-            # Start subsystem processing? This is to skip processing the text
-            # between the Maintainers heading and the first subsystem name.
-            if maintainers and not subsystems:
+            if self.descriptions:
+                self.parse_descriptions(line)
+            elif self.maintainers and not self.subsystems:
                 if re.search('^[A-Z0-9]', line):
-                    subsystems = True
-
-            # Drop needless input whitespace.
-            line = line.rstrip()
-
-            #
-            # Handle profile entries - either as files or as https refs
-            #
-            match = re.match(rf"P:\s*({doc_dir})(/\S+)\.rst", line)
-            if match:
-                name = "".join(match.groups())
-                entry = os.path.relpath(base_dir + name, app_dir)
-
-                full_name = os.path.join(base_dir, name)
-                path = os.path.relpath(full_name, app_dir)
-                #
-                # When SPHINXDIRS is used, it will try to reference files
-                # outside srctree, causing warnings. To avoid that, point
-                # to the latest official documentation
-                #
-                if path.startswith("../"):
-                    entry = KERNELDOC_URL + match.group(2) + ".html"
+                    self.subsystems = True
+                    self.parse_subsystems(line)
                 else:
-                    entry = "/" + entry
-
-                if "*" in entry:
-                    for e in glob(entry):
-                        self.profile_toc.add(e)
-                        self.profile_entries[subsystem_name] = e
-                else:
-                    self.profile_toc.add(entry)
-                    self.profile_entries[subsystem_name] = entry
-            else:
-                match = re.match(r"P:\s*(https?://.*)", line)
-                if match:
-                    entry = match.group(1).strip()
-                    self.profile_entries[subsystem_name] = entry
-
-            # Linkify all non-wildcard refs to ReST files in Documentation/.
-            pat = r'(Documentation/([^\s\?\*]*)\.rst)'
-            m = re.search(pat, line)
-            if m:
-                # maintainers.rst is in a subdirectory, so include "../".
-                line = re.sub(pat, ':doc:`%s <../%s>`' % (m.group(2), m.group(2)), line)
-
-            # Check state machine for output rendering behavior.
-            output = None
-            if descriptions:
-                # Escape the escapes in preformatted text.
-                output = "| %s" % (line.replace("\\", "\\\\"))
-                # Look for and record field letter to field name mappings:
-                #   R: Designated *reviewer*: FullName <address@domain>
-                m = re.search(r"\s(\S):\s", line)
-                if m:
-                    field_letter = m.group(1)
-                if field_letter and not field_letter in fields:
-                    m = re.search(r"\*([^\*]+)\*", line)
-                    if m:
-                        fields[field_letter] = m.group(1)
-            elif subsystems:
-                # Skip empty lines: subsystem parser adds them as needed.
-                if len(line) == 0:
-                    continue
-                # Subsystem fields are batched into "field_content"
-                if line[1] != ':':
-                    # Render a subsystem entry as:
-                    #   SUBSYSTEM NAME
-                    #   ~~~~~~~~~~~~~~
-
-                    # Flush pending field content.
-                    output = field_content + "\n\n"
-                    field_content = ""
-
-                    subsystem_name = line.title()
-
-                    # Collapse whitespace in subsystem name.
-                    heading = re.sub(r"\s+", " ", line)
-                    output = output + "%s\n%s" % (heading, "~" * len(heading))
-                    field_prev = ""
-                else:
-                    # Render a subsystem field as:
-                    #   :Field: entry
-                    #           entry...
-                    field, details = line.split(':', 1)
-                    details = details.strip()
-
-                    # Mark paths (and regexes) as literal text for improved
-                    # readability and to escape any escapes.
-                    if field in ['F', 'N', 'X', 'K']:
-                        # But only if not already marked :)
-                        if not ':doc:' in details:
-                            details = '``%s``' % (details)
-
-                    # Comma separate email field continuations.
-                    if field == field_prev and field_prev in ['M', 'R', 'L']:
-                        field_content = field_content + ","
-
-                    # Do not repeat field names, so that field entries
-                    # will be collapsed together.
-                    if field != field_prev:
-                        output = field_content + "\n"
-                        field_content = ":%s:" % (fields.get(field, field))
-                    field_content = field_content + "\n\t%s" % (details)
-                    field_prev = field
+                    self.output += line
+            elif self.subsystems:
+                self.parse_subsystems(line)
             else:
-                output = line
-
-            # Re-split on any added newlines in any above parsing.
-            if output != None:
-                for separated in output.split('\n'):
-                    result.append(separated)
+                self.output += line
 
             # Update the state machine when we find heading separators.
             if line.startswith('----------'):
                 if prev.startswith('Descriptions'):
-                    descriptions = True
+                    self.descriptions = True
                 if prev.startswith('Maintainers'):
-                    maintainers = True
+                    self.maintainers = True
 
             # Retain previous line for state machine transitions.
             prev = line
 
         # Flush pending field contents.
-        if field_content != "":
-            for separated in field_content.split('\n'):
-                result.append(separated)
+        if self.field_content:
+            self.output += self.field_content + "\n\n"
 
-        self.output = "\n".join(result)
+        self.output = self.output.rstrip()
+
+    def parse_descriptions(self, line):
+        """Handle contents of the descriptions section."""
+
+        # Have we reached the end of the preformatted Descriptions text?
+        if line.startswith('Maintainers'):
+            self.descriptions = False
+            self.output += "\n" + line
+            return
+
+        # Linkify all non-wildcard refs to ReST files in Documentation/.
+        m = self.re_doc.search(line)
+        if m:
+            # maintainers.rst is in a subdirectory, so include "../".
+            line = self.re_doc.sub(':doc:`%s <../%s>`' % (m.group(2), m.group(2)), line)
+
+        # Escape the escapes in preformatted text.
+        output = "| %s" % (line.replace("\\", "\\\\"))
+
+        # Look for and record field letter to field name mappings:
+        #   R: Designated *reviewer*: FullName <address@domain>
+        m = re.search(r"\s(\S):\s", line)
+        if m:
+            self.field_letter = m.group(1)
+
+        if self.field_letter and self.field_letter not in self.fields:
+            m = re.search(r"\*([^\*]+)\*", line)
+            if m:
+                self.fields[self.field_letter] = m.group(1)
+
+        # Append parsed content to self.output
+        self.output += output
+
+    def parse_subsystems(self, line):
+        """Handle contents of the per-subsystem sections."""
+
+        # Drop needless input whitespace.
+        line = line.rstrip()
+
+        #
+        # Handle profile entries - either as files or as https refs
+        #
+        match = re.match(rf"P:\s*({self.doc_dir})(/\S+)\.rst", line)
+        if match:
+            name = "".join(match.groups())
+            entry = os.path.relpath(self.base_dir + name, self.app_dir)
+
+            full_name = os.path.join(self.base_dir, name)
+            path = os.path.relpath(full_name, self.app_dir)
+            #
+            # When SPHINXDIRS is used, it will try to reference files
+            # outside srctree, causing warnings. To avoid that, point
+            # to the latest official documentation
+            #
+            if path.startswith("../"):
+                entry = KERNELDOC_URL + match.group(2) + ".html"
+            else:
+                entry = "/" + entry
+
+            if "*" in entry:
+                for e in glob(entry):
+                    self.profile_toc.add(e)
+                    self.profile_entries[self.subsystem_name] = e
+            else:
+                self.profile_toc.add(entry)
+                self.profile_entries[self.subsystem_name] = entry
+        else:
+            match = re.match(r"P:\s*(https?://.*)", line)
+            if match:
+                entry = match.group(1).strip()
+                self.profile_entries[self.subsystem_name] = entry
+
+        # Linkify all non-wildcard refs to ReST files in Documentation/.
+        m = self.re_doc.search(line)
+        if m:
+            # maintainers.rst is in a subdirectory, so include "../".
+            line = self.re_doc.sub(':doc:`%s <../%s>`' % (m.group(2), m.group(2)), line)
+
+        # Check state machine for output rendering behavior.
+        output = None
+        if self.subsystems:
+            # Skip empty lines: subsystem parser adds them as needed.
+            if len(line) == 0:
+                return
+            # Subsystem fields are batched into "field_content"
+            if line[1] != ':':
+                # Render a subsystem entry as:
+                #   SUBSYSTEM NAME
+                #   ~~~~~~~~~~~~~~
+                # Flush pending field content.
+                output = self.field_content + "\n\n"
+                self.field_content = ""
+
+                self.subsystem_name = line.title()
+
+                # Collapse whitespace in subsystem name.
+                heading = re.sub(r"\s+", " ", line)
+                output = output + "%s\n%s" % (heading, "~" * len(heading))
+                self.field_prev = ""
+            else:
+                # Render a subsystem field as:
+                #   :Field: entry
+                #           entry...
+                field, details = line.split(':', 1)
+                details = details.strip()
+
+                # Mark paths (and regexes) as literal text for improved
+                # readability and to escape any escapes.
+                if field in ['F', 'N', 'X', 'K']:
+                    # But only if not already marked :)
+                    if not ':doc:' in details:
+                        details = '``%s``' % (details)
+
+                # Comma separate email field continuations.
+                if field == self.field_prev and self.field_prev in ['M', 'R', 'L']:
+                    self.field_content = self.field_content + ","
+
+                # Do not repeat field names, so that field entries
+                # will be collapsed together.
+                if field != self.field_prev:
+                    output = self.field_content + "\n"
+                    self.field_content = ":%s:" % (self.fields.get(field, field))
+                self.field_content = self.field_content + "\n\t%s" % (details)
+                self.field_prev = field
+        elif not self.descriptions:
+            output = line
+
+        if output is not None:
+            self.output += output + "\n"
 
-        # Create a TOC class
 
 class MaintainersInclude(Include):
     """MaintainersInclude (``maintainers-include``) directive"""
-- 
2.54.0


^ permalink raw reply related

* [PATCH v2 03/11] docs: maintainers_include: cleanup the code
From: Mauro Carvalho Chehab @ 2026-05-05 13:25 UTC (permalink / raw)
  To: Jonathan Corbet, Linux Doc Mailing List, Mauro Carvalho Chehab
  Cc: Mauro Carvalho Chehab, linux-kernel, rust-for-linux, Shuah Khan
In-Reply-To: <cover.1777987027.git.mchehab+huawei@kernel.org>

Simplify the logic without affecting the output result.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
 Documentation/sphinx/maintainers_include.py | 184 ++++++++++----------
 1 file changed, 91 insertions(+), 93 deletions(-)

diff --git a/Documentation/sphinx/maintainers_include.py b/Documentation/sphinx/maintainers_include.py
index 6d47d55f5b73..615af227a8f8 100755
--- a/Documentation/sphinx/maintainers_include.py
+++ b/Documentation/sphinx/maintainers_include.py
@@ -44,10 +44,6 @@ class MaintainersParser:
 
     def __init__(self, app_dir, path):
         self.path = path
-        self.profile_toc = set()
-        self.profile_entries = {}
-
-        self.output = ".. _maintainers:\n\n"
 
         # Poor man's state machine.
         self.descriptions = False
@@ -67,6 +63,13 @@ class MaintainersParser:
 
         self.re_doc = re.compile(r'(Documentation/([^\s\?\*]*)\.rst)')
 
+        #
+        # Output variables with maintainers content to be stored
+        #
+        self.profile_toc = set()
+        self.profile_entries = {}
+        self.output = ".. _maintainers:\n\n"
+
         prev = None
         for line in open(path):
             if self.descriptions:
@@ -98,6 +101,16 @@ class MaintainersParser:
 
         self.output = self.output.rstrip()
 
+
+    def linkify(self, text):
+        """Linkify all non-wildcard refs to ReST files in Documentation/"""
+        m = self.re_doc.search(text)
+        if m:
+            # maintainers.rst is in a subdirectory, so include "../".
+            text = self.re_doc.sub(':doc:`%s <../%s>`' % (m.group(2), m.group(2)), text)
+
+        return text
+
     def parse_descriptions(self, line):
         """Handle contents of the descriptions section."""
 
@@ -107,14 +120,8 @@ class MaintainersParser:
             self.output += "\n" + line
             return
 
-        # Linkify all non-wildcard refs to ReST files in Documentation/.
-        m = self.re_doc.search(line)
-        if m:
-            # maintainers.rst is in a subdirectory, so include "../".
-            line = self.re_doc.sub(':doc:`%s <../%s>`' % (m.group(2), m.group(2)), line)
-
         # Escape the escapes in preformatted text.
-        output = "| %s" % (line.replace("\\", "\\\\"))
+        self.output += "| " + self.linkify(line).replace("\\", "\\\\")
 
         # Look for and record field letter to field name mappings:
         #   R: Designated *reviewer*: FullName <address@domain>
@@ -127,105 +134,96 @@ class MaintainersParser:
             if m:
                 self.fields[self.field_letter] = m.group(1)
 
-        # Append parsed content to self.output
-        self.output += output
-
     def parse_subsystems(self, line):
         """Handle contents of the per-subsystem sections."""
 
         # Drop needless input whitespace.
         line = line.rstrip()
 
+        # Skip empty lines: subsystem parser adds them as needed.
+        if not line:
+            return
+
+        # Subsystem fields are batched into "field_content"
+        if line[1] != ':':
+            line = self.linkify(line)
+
+            # Render a subsystem entry as:
+            #   SUBSYSTEM NAME
+            #   ~~~~~~~~~~~~~~
+            # Flush pending field content.
+            self.output += self.field_content + "\n\n"
+            self.field_content = ""
+
+            self.subsystem_name = line.title()
+
+            # Collapse whitespace in subsystem name.
+            heading = re.sub(r"\s+", " ", line)
+            self.output += "%s\n%s" % (heading, "~" * len(heading)) + "\n"
+            self.field_prev = ""
+
+            return
+
+        # Render a subsystem field as:
+        #   :Field: entry
+        #           entry...
+        field, details = line.split(':', 1)
+        details = details.strip()
+
         #
         # Handle profile entries - either as files or as https refs
         #
-        match = re.match(rf"P:\s*({self.doc_dir})(/\S+)\.rst", line)
-        if match:
-            name = "".join(match.groups())
-            entry = os.path.relpath(self.base_dir + name, self.app_dir)
-
-            full_name = os.path.join(self.base_dir, name)
-            path = os.path.relpath(full_name, self.app_dir)
-            #
-            # When SPHINXDIRS is used, it will try to reference files
-            # outside srctree, causing warnings. To avoid that, point
-            # to the latest official documentation
-            #
-            if path.startswith("../"):
-                entry = KERNELDOC_URL + match.group(2) + ".html"
-            else:
-                entry = "/" + entry
-
-            if "*" in entry:
-                for e in glob(entry):
-                    self.profile_toc.add(e)
-                    self.profile_entries[self.subsystem_name] = e
-            else:
-                self.profile_toc.add(entry)
-                self.profile_entries[self.subsystem_name] = entry
-        else:
-            match = re.match(r"P:\s*(https?://.*)", line)
+        if field == "P":
+            match = self.re_doc.match(details)
             if match:
-                entry = match.group(1).strip()
-                self.profile_entries[self.subsystem_name] = entry
+                name = "".join(match.groups())
+                entry = os.path.relpath(self.base_dir + name, self.app_dir)
 
-        # Linkify all non-wildcard refs to ReST files in Documentation/.
-        m = self.re_doc.search(line)
-        if m:
-            # maintainers.rst is in a subdirectory, so include "../".
-            line = self.re_doc.sub(':doc:`%s <../%s>`' % (m.group(2), m.group(2)), line)
+                full_name = os.path.join(self.base_dir, name)
+                path = os.path.relpath(full_name, self.app_dir)
+                #
+                # When SPHINXDIRS is used, it will try to reference files
+                # outside srctree, causing warnings. To avoid that, point
+                # to the latest official documentation
+                #
+                if path.startswith("../"):
+                    entry = KERNELDOC_URL + "/" + match.group(2) + ".html"
+                else:
+                    entry = "/" + entry
 
-        # Check state machine for output rendering behavior.
-        output = None
-        if self.subsystems:
-            # Skip empty lines: subsystem parser adds them as needed.
-            if len(line) == 0:
-                return
-            # Subsystem fields are batched into "field_content"
-            if line[1] != ':':
-                # Render a subsystem entry as:
-                #   SUBSYSTEM NAME
-                #   ~~~~~~~~~~~~~~
-                # Flush pending field content.
-                output = self.field_content + "\n\n"
-                self.field_content = ""
-
-                self.subsystem_name = line.title()
-
-                # Collapse whitespace in subsystem name.
-                heading = re.sub(r"\s+", " ", line)
-                output = output + "%s\n%s" % (heading, "~" * len(heading))
-                self.field_prev = ""
+                if "*" in entry:
+                    for e in glob(entry):
+                        self.profile_toc.add(e)
+                        self.profile_entries[self.subsystem_name] = e
+                else:
+                    self.profile_toc.add(entry)
+                    self.profile_entries[self.subsystem_name] = entry
             else:
-                # Render a subsystem field as:
-                #   :Field: entry
-                #           entry...
-                field, details = line.split(':', 1)
-                details = details.strip()
+                match = re.match(r"(https?://.*)", details)
+                if match:
+                    entry = match.group(1).strip()
+                    self.profile_entries[self.subsystem_name] = entry
 
-                # Mark paths (and regexes) as literal text for improved
-                # readability and to escape any escapes.
-                if field in ['F', 'N', 'X', 'K']:
-                    # But only if not already marked :)
-                    if not ':doc:' in details:
-                        details = '``%s``' % (details)
+        details = self.linkify(details)
 
-                # Comma separate email field continuations.
-                if field == self.field_prev and self.field_prev in ['M', 'R', 'L']:
-                    self.field_content = self.field_content + ","
+        # Mark paths (and regexes) as literal text for improved
+        # readability and to escape any escapes.
+        if field in ['F', 'N', 'X', 'K']:
+            # But only if not already marked :)
+            if not ':doc:' in details:
+                details = '``%s``' % (details)
 
-                # Do not repeat field names, so that field entries
-                # will be collapsed together.
-                if field != self.field_prev:
-                    output = self.field_content + "\n"
-                    self.field_content = ":%s:" % (self.fields.get(field, field))
-                self.field_content = self.field_content + "\n\t%s" % (details)
-                self.field_prev = field
-        elif not self.descriptions:
-            output = line
+        # Comma separate email field continuations.
+        if field == self.field_prev and self.field_prev in ['M', 'R', 'L']:
+            self.field_content = self.field_content + ","
 
-        if output is not None:
-            self.output += output + "\n"
+        # Do not repeat field names, so that field entries
+        # will be collapsed together.
+        if field != self.field_prev:
+            self.output += self.field_content + "\n\n"
+            self.field_content = ":%s:" % (self.fields.get(field, field))
+        self.field_content = self.field_content + "\n\t%s" % (details)
+        self.field_prev = field
 
 
 class MaintainersInclude(Include):
-- 
2.54.0


^ permalink raw reply related

* [PATCH v2 05/11] docs: maintainers_include: do some coding style cleanups
From: Mauro Carvalho Chehab @ 2026-05-05 13:25 UTC (permalink / raw)
  To: Jonathan Corbet, Linux Doc Mailing List, Mauro Carvalho Chehab
  Cc: Mauro Carvalho Chehab, linux-kernel, rust-for-linux, Shuah Khan
In-Reply-To: <cover.1777987027.git.mchehab+huawei@kernel.org>

Minor coding style adjustments to use the style most python
doc scripts are following.

No functional changes.

Assisted-by: pylint, black
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
 Documentation/sphinx/maintainers_include.py | 101 ++++++++++----------
 1 file changed, 51 insertions(+), 50 deletions(-)

diff --git a/Documentation/sphinx/maintainers_include.py b/Documentation/sphinx/maintainers_include.py
index d3ad01e5309e..7edda808ef99 100755
--- a/Documentation/sphinx/maintainers_include.py
+++ b/Documentation/sphinx/maintainers_include.py
@@ -1,30 +1,25 @@
 #!/usr/bin/env python
 # SPDX-License-Identifier: GPL-2.0
 # -*- coding: utf-8; mode: python -*-
-# pylint: disable=R0903, C0330, R0914, R0912, E0401
+# pylint: disable=C0209, C0301, E0401, R0022, R0902, R0903, R0912, R0914
 
 """
-    maintainers-include
-    ~~~~~~~~~~~~~~~~~~~
+Implementation of the ``maintainers-include`` reST-directive.
 
-    Implementation of the ``maintainers-include`` reST-directive.
+:copyright:  Copyright (C) 2019  Kees Cook <keescook@chromium.org>
+:license:    GPL Version 2, June 1991 see linux/COPYING for details.
 
-    :copyright:  Copyright (C) 2019  Kees Cook <keescook@chromium.org>
-    :license:    GPL Version 2, June 1991 see linux/COPYING for details.
-
-    The ``maintainers-include`` reST-directive performs extensive parsing
-    specific to the Linux kernel's standard "MAINTAINERS" file, in an
-    effort to avoid needing to heavily mark up the original plain text.
+The ``maintainers-include`` reST-directive performs extensive parsing
+specific to the Linux kernel's standard "MAINTAINERS" file, in an
+effort to avoid needing to heavily mark up the original plain text.
 """
 
-import sys
-import re
 import os.path
+import re
 
 from glob import glob
 
 from docutils import statemachine
-from docutils.parsers.rst import Directive
 from docutils.parsers.rst.directives.misc import Include
 
 #
@@ -32,12 +27,14 @@ from docutils.parsers.rst.directives.misc import Include
 #
 KERNELDOC_URL = "https://docs.kernel.org/"
 
-def ErrorString(exc):  # Shamelessly stolen from docutils
-    return f'{exc.__class__.__name}: {exc}'
+__version__ = "1.0"
 
-__version__  = '1.0'
+maint_parser = None  # pylint: disable=C0103
 
-maint_parser = None
+
+# Shamelessly stolen from docutils
+def ErrorString(exc):  # pylint: disable=C0103, C0116
+    return f"{exc.__class__.__name}: {exc}"  # pylint: disable=W0212
 
 class MaintainersParser:
     """Parse MAINTAINERS file(s) content"""
@@ -52,7 +49,7 @@ class MaintainersParser:
 
         # Field letter to field name mapping.
         self.field_letter = None
-        self.fields = dict()
+        self.fields = {}
 
         self.field_prev = ""
         self.field_content = ""
@@ -71,29 +68,30 @@ class MaintainersParser:
         self.output = ".. _maintainers:\n\n"
 
         prev = None
-        for line in open(path):
-            if self.descriptions:
-                self.parse_descriptions(line)
-            elif self.maintainers and not self.subsystems:
-                if re.search('^[A-Z0-9]', line):
-                    self.subsystems = True
+        with open(path, "r", encoding="utf-8") as fp:
+            for line in fp:
+                if self.descriptions:
+                    self.parse_descriptions(line)
+                elif self.maintainers and not self.subsystems:
+                    if re.search('^[A-Z0-9]', line):
+                        self.subsystems = True
+                        self.parse_subsystems(line)
+                    else:
+                        self.output += line
+                elif self.subsystems:
                     self.parse_subsystems(line)
                 else:
                     self.output += line
-            elif self.subsystems:
-                self.parse_subsystems(line)
-            else:
-                self.output += line
 
-            # Update the state machine when we find heading separators.
-            if line.startswith('----------'):
-                if prev.startswith('Descriptions'):
-                    self.descriptions = True
-                if prev.startswith('Maintainers'):
-                    self.maintainers = True
+                # Update the state machine when we find heading separators.
+                if line.startswith("----------"):
+                    if prev.startswith("Descriptions"):
+                        self.descriptions = True
+                    if prev.startswith("Maintainers"):
+                        self.maintainers = True
 
-            # Retain previous line for state machine transitions.
-            prev = line
+                # Retain previous line for state machine transitions.
+                prev = line
 
         # Flush pending field contents.
         if self.field_content:
@@ -130,7 +128,7 @@ class MaintainersParser:
         """Handle contents of the descriptions section."""
 
         # Have we reached the end of the preformatted Descriptions text?
-        if line.startswith('Maintainers'):
+        if line.startswith("Maintainers"):
             self.descriptions = False
             self.output += "\n" + line
             return
@@ -182,7 +180,7 @@ class MaintainersParser:
         # Render a subsystem field as:
         #   :Field: entry
         #           entry...
-        field, details = line.split(':', 1)
+        field, details = line.split(":", 1)
         details = details.strip()
 
         #
@@ -248,12 +246,11 @@ class MaintainersParser:
 
 class MaintainersInclude(Include):
     """MaintainersInclude (``maintainers-include``) directive"""
+
     required_arguments = 0
 
     def emit(self):
         """Parse all the MAINTAINERS lines into ReST for human-readability"""
-        global maint_parser
-
         path = maint_parser.path
         output = maint_parser.output
 
@@ -269,20 +266,21 @@ class MaintainersInclude(Include):
             raise self.warning('"%s" directive disabled.' % self.name)
 
         try:
-            lines = self.emit()
+            self.emit()
         except IOError as error:
             raise self.severe('Problems with "%s" directive path:\n%s.' %
                       (self.name, ErrorString(error)))
 
         return []
 
+
 class MaintainersProfile(Include):
+    """Generate a list with all maintainer's profiles"""
+
     required_arguments = 0
 
     def emit(self):
         """Parse all the MAINTAINERS lines looking for profile entries"""
-        global maint_parser
-
         path = maint_parser.path
 
         #
@@ -316,15 +314,17 @@ class MaintainersProfile(Include):
             raise self.warning('"%s" directive disabled.' % self.name)
 
         try:
-            lines = self.emit()
+            self.emit()
         except IOError as error:
             raise self.severe('Problems with "%s" directive path:\n%s.' %
                       (self.name, ErrorString(error)))
 
         return []
 
+
 def setup(app):
-    global maint_parser
+    """Setup Sphinx exension"""
+    global maint_parser  # pylint: disable=W0603
 
     #
     # NOTE: we're using os.fspath() here because of a Sphinx warning:
@@ -338,8 +338,9 @@ def setup(app):
 
     app.add_directive("maintainers-include", MaintainersInclude)
     app.add_directive("maintainers-profile-toc", MaintainersProfile)
-    return dict(
-        version = __version__,
-        parallel_read_safe = True,
-        parallel_write_safe = True
-    )
+
+    return {
+        "version": __version__,
+        "parallel_read_safe": True,
+        "parallel_write_safe": True,
+    }
-- 
2.54.0


^ permalink raw reply related

* [PATCH v2 07/11] docs: maintainers_include: properly handle file patterns
From: Mauro Carvalho Chehab @ 2026-05-05 13:25 UTC (permalink / raw)
  To: Jonathan Corbet, Linux Doc Mailing List, Mauro Carvalho Chehab
  Cc: Mauro Carvalho Chehab, linux-kernel, rust-for-linux,
	Andrew Morton, Joe Perches, Matteo Croce, Shuah Khan,
	Matteo Croce
In-Reply-To: <cover.1777987027.git.mchehab+huawei@kernel.org>

handling asterisks inside file patterns atdescription part is
problematic, as ReST has special meaning for them. Due to
that, convert such patterns to literal strings.

Reported-by: Matteo Croce <teknoraver@meta.com>
Fixes: 420849332f9f ("get_maintainer: add ** glob pattern support")
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
 Documentation/sphinx/maintainers_include.py | 26 ++++++++++-----------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/Documentation/sphinx/maintainers_include.py b/Documentation/sphinx/maintainers_include.py
index 6f1bcbde90c4..8916d3512e0d 100755
--- a/Documentation/sphinx/maintainers_include.py
+++ b/Documentation/sphinx/maintainers_include.py
@@ -47,9 +47,6 @@ class MaintainersParser:
         self.maintainers = False
         self.subsystems = False
 
-        # Field letter to field name mapping.
-        self.field_letter = None
-
         self.subsystem_name = None
 
         self.app_dir = os.path.abspath(app_dir)
@@ -125,19 +122,22 @@ class MaintainersParser:
             self.header += "\n" + line
             return
 
-        # Escape the escapes in preformatted text.
-        self.header += "| " + self.linkify(line).replace("\\", "\\\\")
-
         # Look for and record field letter to field name mappings:
         #   R: Designated *reviewer*: FullName <address@domain>
-        m = re.search(r"\s(\S):\s", line)
+        m = re.match(r"\s+(\S):\s+(\S+)", line)
         if m:
-            self.field_letter = m.group(1)
+            field = m.group(1)
+            details = m.group(2)
+
+            if field not in self.fields:
+                m = re.search(r"\*([^\*]+)\*", line)
+                if m:
+                    self.fields[field] = m.group(1)
+            elif field in ['F', 'N', 'X', 'K']:
+                line = line.replace(details, f'``{details}``')
+
+        self.header += "| " + self.linkify(line)
 
-        if self.field_letter and self.field_letter not in self.fields:
-            m = re.search(r"\*([^\*]+)\*", line)
-            if m:
-                self.fields[self.field_letter] = m.group(1)
 
     def parse_subsystems(self, line):
         """Handle contents of the per-subsystem sections."""
@@ -206,7 +206,7 @@ class MaintainersParser:
         #
         if field in ['F', 'N', 'X', 'K']:
             # But only if not already marked :)
-            if not ':doc:' in details:
+            if ':doc:' not in details and "http" not in details:
                 details = '``%s``' % (details)
 
         if self.subsystem_name not in self.maint_entries:
-- 
2.54.0


^ permalink raw reply related

* [PATCH v2 06/11] docs: maintainers_include: store maintainers entries on a dict
From: Mauro Carvalho Chehab @ 2026-05-05 13:25 UTC (permalink / raw)
  To: Jonathan Corbet, Linux Doc Mailing List, Mauro Carvalho Chehab
  Cc: Mauro Carvalho Chehab, linux-kernel, rust-for-linux, Shuah Khan
In-Reply-To: <cover.1777987027.git.mchehab+huawei@kernel.org>

Instead of creating just a big output data, store entries inside
a dictionary. Doing that simplifies the parser a little bit
and make the code clearer.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
 Documentation/sphinx/maintainers_include.py | 70 +++++++++------------
 1 file changed, 28 insertions(+), 42 deletions(-)

diff --git a/Documentation/sphinx/maintainers_include.py b/Documentation/sphinx/maintainers_include.py
index 7edda808ef99..6f1bcbde90c4 100755
--- a/Documentation/sphinx/maintainers_include.py
+++ b/Documentation/sphinx/maintainers_include.py
@@ -49,10 +49,7 @@ class MaintainersParser:
 
         # Field letter to field name mapping.
         self.field_letter = None
-        self.fields = {}
 
-        self.field_prev = ""
-        self.field_content = ""
         self.subsystem_name = None
 
         self.app_dir = os.path.abspath(app_dir)
@@ -65,7 +62,9 @@ class MaintainersParser:
         #
         self.profile_toc = set()
         self.profile_entries = {}
-        self.output = ".. _maintainers:\n\n"
+        self.header = ".. _maintainers:\n\n"
+        self.maint_entries = {}
+        self.fields = {}
 
         prev = None
         with open(path, "r", encoding="utf-8") as fp:
@@ -77,11 +76,11 @@ class MaintainersParser:
                         self.subsystems = True
                         self.parse_subsystems(line)
                     else:
-                        self.output += line
+                        self.header += line
                 elif self.subsystems:
                     self.parse_subsystems(line)
                 else:
-                    self.output += line
+                    self.header += line
 
                 # Update the state machine when we find heading separators.
                 if line.startswith("----------"):
@@ -93,13 +92,6 @@ class MaintainersParser:
                 # Retain previous line for state machine transitions.
                 prev = line
 
-        # Flush pending field contents.
-        if self.field_content:
-            self.output += self.field_content + "\n\n"
-
-        self.output = self.output.rstrip()
-
-
     def linkify(self, text):
         """Linkify all non-wildcard refs to ReST files in Documentation/"""
 
@@ -130,11 +122,11 @@ class MaintainersParser:
         # Have we reached the end of the preformatted Descriptions text?
         if line.startswith("Maintainers"):
             self.descriptions = False
-            self.output += "\n" + line
+            self.header += "\n" + line
             return
 
         # Escape the escapes in preformatted text.
-        self.output += "| " + self.linkify(line).replace("\\", "\\\\")
+        self.header += "| " + self.linkify(line).replace("\\", "\\\\")
 
         # Look for and record field letter to field name mappings:
         #   R: Designated *reviewer*: FullName <address@domain>
@@ -157,24 +149,8 @@ class MaintainersParser:
         if not line:
             return
 
-        # Subsystem fields are batched into "field_content"
         if line[1] != ':':
-            line = self.linkify(line)
-
-            # Render a subsystem entry as:
-            #   SUBSYSTEM NAME
-            #   ~~~~~~~~~~~~~~
-            # Flush pending field content.
-            self.output += self.field_content + "\n\n"
-            self.field_content = ""
-
-            self.subsystem_name = line.title()
-
-            # Collapse whitespace in subsystem name.
-            heading = re.sub(r"\s+", " ", line)
-            self.output += "%s\n%s" % (heading, "~" * len(heading)) + "\n"
-            self.field_prev = ""
-
+            self.subsystem_name = re.sub(r"\s+", " ", self.linkify(line))
             return
 
         # Render a subsystem field as:
@@ -224,23 +200,23 @@ class MaintainersParser:
 
         details = self.linkify(details)
 
+        #
         # Mark paths (and regexes) as literal text for improved
         # readability and to escape any escapes.
+        #
         if field in ['F', 'N', 'X', 'K']:
             # But only if not already marked :)
             if not ':doc:' in details:
                 details = '``%s``' % (details)
 
-        # Comma separate email field continuations.
-        if field == self.field_prev and self.field_prev in ['M', 'R', 'L']:
-            self.field_content = self.field_content + ","
+        if self.subsystem_name not in self.maint_entries:
+            self.maint_entries[self.subsystem_name] = {}
+
+        if field not in self.maint_entries[self.subsystem_name]:
+            self.maint_entries[self.subsystem_name][field] = []
+
+        self.maint_entries[self.subsystem_name][field].append(details)
 
-        # Do not repeat field names, so that field entries
-        # will be collapsed together.
-        if field != self.field_prev:
-            self.output += self.field_content + "\n\n"
-            self.field_content = ":%s:" % (self.fields.get(field, field))
-        self.field_content = self.field_content + "\n\t%s" % (details)
         self.field_prev = field
 
 
@@ -252,7 +228,15 @@ class MaintainersInclude(Include):
     def emit(self):
         """Parse all the MAINTAINERS lines into ReST for human-readability"""
         path = maint_parser.path
-        output = maint_parser.output
+        output = maint_parser.header
+
+        for name, fields in sorted(maint_parser.maint_entries.items()):
+            output += "\n" + name + "\n"
+            output += "~" * len(name) + "\n"
+
+            for field, lines in fields.items():
+                field_name = maint_parser.fields.get(field, field)
+                output += f":{field_name}:\n\t" + ",\n\t".join(lines) + "\n\n"
 
         # For debugging the pre-rendered results...
         #print(output, file=open("/tmp/MAINTAINERS.rst", "w"))
@@ -288,6 +272,8 @@ class MaintainersProfile(Include):
         #
         output = ""
         for profile, entry in sorted(maint_parser.profile_entries.items()):
+            profile = profile.title()
+
             if entry.startswith("http"):
                 output += f"- `{profile} <{entry}>`_\n"
             else:
-- 
2.54.0


^ permalink raw reply related

* [PATCH v2 08/11] docs: maintainers_include: add a filtering javascript
From: Mauro Carvalho Chehab @ 2026-05-05 13:25 UTC (permalink / raw)
  To: Jonathan Corbet, Linux Doc Mailing List, Mauro Carvalho Chehab
  Cc: Mauro Carvalho Chehab, linux-kernel, rust-for-linux, Shuah Khan
In-Reply-To: <cover.1777987027.git.mchehab+huawei@kernel.org>

The maintainers table is big. Add a javascript to allow filtering
it. Such script is only added at the page which contains the
maintainers-include tag.

I opted to keep the search case-sensitive, as, this way,
upper case searches at subsystem.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
 Documentation/sphinx/maintainers_include.py | 78 +++++++++++++++++++--
 1 file changed, 72 insertions(+), 6 deletions(-)

diff --git a/Documentation/sphinx/maintainers_include.py b/Documentation/sphinx/maintainers_include.py
index 8916d3512e0d..572c382db2c2 100755
--- a/Documentation/sphinx/maintainers_include.py
+++ b/Documentation/sphinx/maintainers_include.py
@@ -31,6 +31,49 @@ __version__ = "1.0"
 
 maint_parser = None  # pylint: disable=C0103
 
+JS_FILTER = """
+(function() {
+  function filterTable(table) {
+    const filter = document.getElementById("filter-table").value.trim();
+    const rows = table.querySelectorAll("tbody tr");
+    for (let i = 0; i < rows.length; i++) {
+      const tds = rows[i].getElementsByTagName("td");
+      let match = false;
+      for (let j = 0; j < tds.length; j++) {
+        const cellText = (tds[j].textContent || tds[j].innerText);
+        if (cellText.includes(filter)) {
+          match = true;
+          break;
+        }
+      }
+      rows[i].style.display = match ? "table-row" : "none";
+    }
+  }
+  function addInput() {
+    const table = document.getElementById("maintainers-table");
+    if (!table) return;
+    let input = document.getElementById("filter-table");
+    if (!input) {
+      const filt_div = document.createElement('div');
+      filt_div.innerHTML = `
+        <p>Filter:
+          <input type="search" id="filter-table" placeholder="search string"/>
+          subsystem or property (case-sensitive)
+        </p>
+      `;
+      table.parentNode.insertBefore(filt_div, table);
+      const input = document.getElementById("filter-table")
+      input.addEventListener('input', () => filterTable(table));
+    }
+  }
+  if (document.readyState === 'loading') {
+    document.addEventListener('DOMContentLoaded', addInput);
+  } else {
+    addInput();
+  }
+})();
+"""
+
 
 # Shamelessly stolen from docutils
 def ErrorString(exc):  # pylint: disable=C0103, C0116
@@ -59,7 +102,7 @@ class MaintainersParser:
         #
         self.profile_toc = set()
         self.profile_entries = {}
-        self.header = ".. _maintainers:\n\n"
+        self.header = ""
         self.maint_entries = {}
         self.fields = {}
 
@@ -228,15 +271,28 @@ class MaintainersInclude(Include):
     def emit(self):
         """Parse all the MAINTAINERS lines into ReST for human-readability"""
         path = maint_parser.path
-        output = maint_parser.header
+        output = ".. _maintainers:\n\n"
+        output += maint_parser.header
+
+        output += ".. _maintainers_table:\n\n"
+        output += ".. flat-table::\n"
+        output += "  :header-rows: 1\n\n"
+        output += "  * - Subsystem\n"
+        output += "    - Properties\n\n"
+
+        self.state.document['maintainers_included'] = True
 
         for name, fields in sorted(maint_parser.maint_entries.items()):
-            output += "\n" + name + "\n"
-            output += "~" * len(name) + "\n"
-
+            output += f"  * - {name}\n"
+            tag = "-"
             for field, lines in fields.items():
                 field_name = maint_parser.fields.get(field, field)
-                output += f":{field_name}:\n\t" + ",\n\t".join(lines) + "\n\n"
+
+                output += f"    {tag} :{field_name}:\n        "
+                output += ",\n        ".join(lines) + "\n"
+                tag = " "
+
+            output += "\n"
 
         # For debugging the pre-rendered results...
         #print(output, file=open("/tmp/MAINTAINERS.rst", "w"))
@@ -308,6 +364,14 @@ class MaintainersProfile(Include):
         return []
 
 
+# pylint: disable=W0613
+def add_filter_script(app, pagename, templatename, context, doctree):
+    """Add Filter javascript only to maintainers page"""
+
+    if doctree and doctree.get('maintainers_included'):
+        app.add_js_file(None, body=JS_FILTER)
+
+
 def setup(app):
     """Setup Sphinx exension"""
     global maint_parser  # pylint: disable=W0603
@@ -325,6 +389,8 @@ def setup(app):
     app.add_directive("maintainers-include", MaintainersInclude)
     app.add_directive("maintainers-profile-toc", MaintainersProfile)
 
+    app.connect("html-page-context", add_filter_script)
+
     return {
         "version": __version__,
         "parallel_read_safe": True,
-- 
2.54.0


^ permalink raw reply related

* [PATCH v2 09/11] docs: maintainers_include: don't ignore invalid profile entries
From: Mauro Carvalho Chehab @ 2026-05-05 13:25 UTC (permalink / raw)
  To: Jonathan Corbet, Linux Doc Mailing List, Mauro Carvalho Chehab
  Cc: Mauro Carvalho Chehab, linux-kernel, rust-for-linux,
	Björn Roy Baron, Alice Ryhl, Andreas Hindborg, Benno Lossin,
	Boqun Feng, Danilo Krummrich, Gary Guo, Miguel Ojeda, Shuah Khan,
	Trevor Gross
In-Reply-To: <cover.1777987027.git.mchehab+huawei@kernel.org>

Currently, there is a "P" entry for Rust pin-init that is
neither a valid ReST file inside Documentation nor an URL.

A proper fix is to either convert/move the file or point to
a URL. Yet, the parser should be able to pick what's there and
show on its output.

Add a logic to display such files at maintainers-handbook.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
 Documentation/sphinx/maintainers_include.py | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/sphinx/maintainers_include.py b/Documentation/sphinx/maintainers_include.py
index 572c382db2c2..74082bf5d4a4 100755
--- a/Documentation/sphinx/maintainers_include.py
+++ b/Documentation/sphinx/maintainers_include.py
@@ -240,6 +240,8 @@ class MaintainersParser:
                 if match:
                     entry = match.group(1).strip()
                     self.profile_entries[self.subsystem_name] = entry
+                else:
+                    self.profile_entries[self.subsystem_name] = f"``{details}``"
 
         details = self.linkify(details)
 
@@ -332,6 +334,8 @@ class MaintainersProfile(Include):
 
             if entry.startswith("http"):
                 output += f"- `{profile} <{entry}>`_\n"
+            elif entry.startswith("`"):
+                output += f"- {profile}: {entry}\n"
             else:
                 output += f"- :doc:`{profile} <{entry}>`\n"
 
-- 
2.54.0


^ permalink raw reply related

* [PATCH v2 11/11] MAINTAINERS: use a URL for pin-init maintainer's profile entry
From: Mauro Carvalho Chehab @ 2026-05-05 13:25 UTC (permalink / raw)
  To: Benno Lossin, Jonathan Corbet, Linux Doc Mailing List
  Cc: Mauro Carvalho Chehab, linux-kernel, rust-for-linux,
	Björn Roy Baron, Alice Ryhl, Andreas Hindborg, Boqun Feng,
	Danilo Krummrich, Gary Guo, Miguel Ojeda, Trevor Gross
In-Reply-To: <cover.1777987027.git.mchehab+huawei@kernel.org>

This maintainer's entry is not inside documentation nor is
ReST, preventing Sphinx to create a hyperlink to it.

Change it to point to the already-formatted URL.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
 MAINTAINERS                   |  2 +-
 rust/pin-init/CONTRIBUTING.md | 72 -----------------------------------
 2 files changed, 1 insertion(+), 73 deletions(-)
 delete mode 100644 rust/pin-init/CONTRIBUTING.md

diff --git a/MAINTAINERS b/MAINTAINERS
index 8700472b3ae3..b16c8f85d099 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -23402,7 +23402,7 @@ S:	Maintained
 W:	https://rust-for-linux.com/pin-init
 B:	https://github.com/Rust-for-Linux/pin-init/issues
 C:	zulip://rust-for-linux.zulipchat.com
-P:	rust/pin-init/CONTRIBUTING.md
+P:	https://github.com/Rust-for-Linux/pin-init/blob/main/CONTRIBUTING.md
 T:	git https://github.com/Rust-for-Linux/linux.git pin-init-next
 F:	rust/kernel/init.rs
 F:	rust/pin-init/
diff --git a/rust/pin-init/CONTRIBUTING.md b/rust/pin-init/CONTRIBUTING.md
deleted file mode 100644
index 16c899a7ae0b..000000000000
--- a/rust/pin-init/CONTRIBUTING.md
+++ /dev/null
@@ -1,72 +0,0 @@
-# Contributing to `pin-init`
-
-Thanks for showing interest in contributing to `pin-init`! This document outlines the guidelines for
-contributing to `pin-init`.
-
-All contributions are double-licensed under Apache 2.0 and MIT. You can find the respective licenses
-in the `LICENSE-APACHE` and `LICENSE-MIT` files.
-
-## Non-Code Contributions
-
-### Bug Reports
-
-For any type of bug report, please submit an issue using the bug report issue template.
-
-If the issue is a soundness issue, please privately report it as a security vulnerability via the
-GitHub web interface.
-
-### Feature Requests
-
-If you have any feature requests, please submit an issue using the feature request issue template.
-
-### Questions and Getting Help
-
-You can ask questions in the Discussions page of the GitHub repository. If you're encountering
-problems or just have questions related to `pin-init` in the Linux kernel, you can also ask your
-questions in the [Rust-for-Linux Zulip](https://rust-for-linux.zulipchat.com/) or see
-<https://rust-for-linux.com/contact>.
-
-## Contributing Code
-
-### Linux Kernel
-
-`pin-init` is used by the Linux kernel and all commits are synchronized to it. For this reason, the
-same requirements for commits apply to `pin-init`. See [the kernel's documentation] for details. The
-rest of this document will also cover some of the rules listed there and additional ones.
-
-[the kernel's documentation]: https://docs.kernel.org/process/submitting-patches.html
-
-Contributions to `pin-init` ideally go through the [GitHub repository], because that repository runs
-a CI with lots of tests not present in the kernel. However, patches are also accepted (though not
-preferred). Do note that there are some files that are only present in the GitHub repository such as
-tests, licenses and cargo related files. Making changes to them can only happen via GitHub.
-
-[GitHub repository]: https://github.com/Rust-for-Linux/pin-init
-
-### Commit Style
-
-Everything must compile without errors or warnings and all tests must pass after **every commit**.
-This is important for bisection and also required by the kernel.
-
-Each commit should be a single, logically cohesive change. Of course it's best to keep the changes
-small and digestible, but logically linked changes should be made in the same commit. For example,
-when fixing typos, create a single commit that fixes all of them instead of one commit per typo.
-
-Commits must have a meaningful commit title. Commits with changes to files in the `internal`
-directory should have a title prefixed with `internal:`. The commit message should explain the
-change and its rationale. You also have to add your `Signed-off-by` tag, see [Developer's
-Certificate of Origin]. This has to be done for both mailing list submissions as well as GitHub
-submissions.
-
-[Developer's Certificate of Origin]: https://docs.kernel.org/process/submitting-patches.html#sign-your-work-the-developer-s-certificate-of-origin
-
-Any changes made to public APIs must be documented not only in the commit message, but also in the
-`CHANGELOG.md` file. This is especially important for breaking changes, as those warrant a major
-version bump.
-
-If you make changes to the top-level crate documentation, you also need to update the `README.md`
-via `cargo rdme`.
-
-Some of these rules can be ignored if the change is done solely to files that are not present in the
-kernel version of this library. Those files are documented in the `sync-kernel.sh` script at the
-very bottom in the `--exclude` flag given to the `git am` command.
-- 
2.54.0


^ permalink raw reply related

* [PATCH v2 10/11] MAINTAINERS: make clearer about what's expected for "P" field
From: Mauro Carvalho Chehab @ 2026-05-05 13:25 UTC (permalink / raw)
  To: Jonathan Corbet, Linux Doc Mailing List
  Cc: Mauro Carvalho Chehab, linux-kernel, rust-for-linux
In-Reply-To: <cover.1777987027.git.mchehab+huawei@kernel.org>

The "P" field is meant to point to a subsystem maintainer's
profile, stored either at the Kernel documentation or on an
extenal site. Make it clearer.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
 MAINTAINERS | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 2fb1c75afd16..8700472b3ae3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -25,7 +25,7 @@ Descriptions of section entries and preferred order
 	C: URI for *chat* protocol, server and channel where developers
 	   usually hang out, for example irc://server/channel.
 	P: *Subsystem Profile* document for more details submitting
-	   patches to the given subsystem. This is either an in-tree file,
+	   patches to the given subsystem. This is either an in-tree .rst file,
 	   or a URI. See Documentation/maintainer/maintainer-entry-profile.rst
 	   for details.
 	T: *SCM* tree type and location.
-- 
2.54.0


^ permalink raw reply related

* Re: [PATCH v4 1/2] dt-bindings: hwmon: pmbus: add max20830
From: Guenter Roeck @ 2026-05-05 13:26 UTC (permalink / raw)
  To: Alexis Czezar Torreno
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jonathan Corbet,
	Shuah Khan, linux-hwmon, devicetree, linux-kernel, linux-doc,
	Conor Dooley
In-Reply-To: <20260505-dev_max20830-v4-1-4343dcbfd7d7@analog.com>

On Tue, May 05, 2026 at 05:25:05PM +0800, Alexis Czezar Torreno wrote:
> Add device tree documentation for MAX20830 step-down DC-DC switching
> regulator with PMBus interface.
> 
> Acked-by: Conor Dooley <conor.dooley@microchip.com>
> Signed-off-by: Alexis Czezar Torreno <alexisczezar.torreno@analog.com>

Applied.

Thanks,
Guenter

^ permalink raw reply

* Re: [PATCH v9 3/6] iio: adc: ad4691: add triggered buffer support
From: Jonathan Cameron @ 2026-05-05 13:26 UTC (permalink / raw)
  To: Sabau, Radu bogdan
  Cc: Andy Shevchenko, Lars-Peter Clausen, Hennerich, Michael,
	David Lechner, Sa, Nuno, Andy Shevchenko, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Uwe Kleine-König,
	Liam Girdwood, Mark Brown, Linus Walleij, Bartosz Golaszewski,
	Philipp Zabel, Jonathan Corbet, Shuah Khan,
	linux-iio@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-pwm@vger.kernel.org,
	linux-gpio@vger.kernel.org, linux-doc@vger.kernel.org
In-Reply-To: <LV9PR03MB841441B282275F8F36FD12C1F7312@LV9PR03MB8414.namprd03.prod.outlook.com>


> 
> > > +	for (i = 0; i < ARRAY_SIZE(ad4691_gp_names); i++) {
> > > +		irq = fwnode_irq_get_byname(dev_fwnode(dev),
> > > +					    ad4691_gp_names[i]);
> > > +		if (irq > 0)
> > > +			break;  
> > 
> > This is problematic in case the above returns EPROBE_DEFER. Can you confirm
> > it
> > may not ever happen? (Note, I don't know the answer.)
> >   
> 
> You are right, thanks for this!
I'm missing something. Why is that a problem?  Driver will return
the error and a dev_err_probe() is used so it won't print anything.
So probe will fail which is exactly what we want.

Jonathan

> 


^ permalink raw reply

* Re: [PATCH v4 2/2] hwmon: (pmbus/max20830) add driver for max20830
From: Guenter Roeck @ 2026-05-05 13:28 UTC (permalink / raw)
  To: Alexis Czezar Torreno
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jonathan Corbet,
	Shuah Khan, linux-hwmon, devicetree, linux-kernel, linux-doc
In-Reply-To: <20260505-dev_max20830-v4-2-4343dcbfd7d7@analog.com>

On Tue, May 05, 2026 at 05:25:06PM +0800, Alexis Czezar Torreno wrote:
> Add support for MAX20830 step-down DC-DC switching regulator with
> PMBus interface. It allows monitoring of input/output voltage,
> output current and temperature through the PMBus serial interface.
> 
> Signed-off-by: Alexis Czezar Torreno <alexisczezar.torreno@analog.com>

Applied, after fixing the formatting issues found by checkpatch.

Thanks,
Guenter

^ permalink raw reply

* [PATCH RFC] printk: remove BOOT_PRINTK_DELAY
From: Andrew Murray @ 2026-05-05 13:45 UTC (permalink / raw)
  To: Jonathan Corbet, Shuah Khan, Russell King, Florian Fainelli,
	Ray Jui, Scott Branden, Broadcom internal kernel review list,
	Petr Mladek, Steven Rostedt, John Ogness, Sergey Senozhatsky,
	Andrew Morton, Sebastian Andrzej Siewior, Clark Williams
  Cc: linux-doc, linux-kernel, linux-arm-kernel, linux-rpi-kernel,
	linux-rt-devel, Andrew Murray

The CONFIG_BOOT_PRINTK_DELAY option enables support for the boot_delay
kernel parameter, this allows for a configurable delay to be added before
each and every printk is emitted. This is DEBUG_KERNEL option that is
helpful for debugging as kernel output can be slowed down during boot
allowing messages to be seen before scrolling off the screen, or to
correlate timing between some physical event and console output.

However, since the introduction of nbcon and the legacy printer thread for
PREEMPT_RT kernels, printk records are now emited to the console
asynchronously to the caller of printk and its boot_delay. The delay added
by boot_delay continues to slow down the calling process, but may not have
any impact to the rate in which records are emited to the console. For
example, if delay_use is set to 100ms, and the printer thread has a
backlog of more than 100ms, perhaps due to a slow serial console, then the
records will appear to be printed without any delay between them.

It would be unhelpful to add a delay to the printer thread, and it would
not be possible to disallow selection of CONFIG_BOOT_PRINTK_DELAY at build
time as it's not possible to detect which consoles are nbcon enabled at
build time. Therefore, let's remove this feature.

Signed-off-by: Andrew Murray <amurray@thegoodpenguin.co.uk>
---
 Documentation/admin-guide/kernel-parameters.txt |  8 ---
 Documentation/admin-guide/sysctl/kernel.rst     |  8 ---
 arch/arm/configs/bcm2835_defconfig              |  1 -
 include/linux/printk.h                          |  1 -
 kernel/printk/printk.c                          | 73 -------------------------
 kernel/printk/sysctl.c                          |  9 ---
 lib/Kconfig.debug                               | 18 ------
 7 files changed, 118 deletions(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 4d0f545fb3ec5a1750d9112a851deb8fd976d32d..afdf443094fc3d74c0220548357c000fafadcb19 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -654,14 +654,6 @@ Kernel parameters
 			embedded devices based on command line input.
 			See Documentation/block/cmdline-partition.rst
 
-	boot_delay=	[KNL,EARLY]
-			Milliseconds to delay each printk during boot.
-			Only works if CONFIG_BOOT_PRINTK_DELAY is enabled,
-			and you may also have to specify "lpj=".  Boot_delay
-			values larger than 10 seconds (10000) are assumed
-			erroneous and ignored.
-			Format: integer
-
 	bootconfig	[KNL,EARLY]
 			Extended command line options can be added to an initrd
 			and this will cause the kernel to look for it.
diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst
index c6994e55d1411b1a3b708b3e2439144bac814e6a..fa1ca90105ab58a2143c3b223c023eb429371474 100644
--- a/Documentation/admin-guide/sysctl/kernel.rst
+++ b/Documentation/admin-guide/sysctl/kernel.rst
@@ -1125,14 +1125,6 @@ default_console_loglevel default value for console_loglevel
 ======================== =====================================
 
 
-printk_delay
-============
-
-Delay each printk message in ``printk_delay`` milliseconds
-
-Value from 0 - 10000 is allowed.
-
-
 printk_ratelimit
 ================
 
diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig
index 4a8ac09843d73280cc42dbbf63fe3cc9f31dacd2..51a1e94d5aa6c22202778082b877a202a6b9c04d 100644
--- a/arch/arm/configs/bcm2835_defconfig
+++ b/arch/arm/configs/bcm2835_defconfig
@@ -174,7 +174,6 @@ CONFIG_NLS_UTF8=y
 CONFIG_DMA_CMA=y
 CONFIG_CMA_SIZE_MBYTES=32
 CONFIG_PRINTK_TIME=y
-CONFIG_BOOT_PRINTK_DELAY=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
 # CONFIG_ENABLE_MUST_CHECK is not set
diff --git a/include/linux/printk.h b/include/linux/printk.h
index f594c1266bfd411f2238b45374e8a71222f0407c..8885e11367d50ea1cd7642249852d011e589adb4 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -188,7 +188,6 @@ extern int __printk_ratelimit(const char *func);
 extern bool printk_timed_ratelimit(unsigned long *caller_jiffies,
 				   unsigned int interval_msec);
 
-extern int printk_delay_msec;
 extern int dmesg_restrict;
 
 extern void wake_up_klogd(void);
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 0323149548f6a4dbcdd80029478b809d44de9b62..47c38575176c944b231f47c034a0c1ff899cbec8 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -1289,61 +1289,6 @@ static bool suppress_message_printing(int level)
 	return (level >= console_loglevel && !ignore_loglevel);
 }
 
-#ifdef CONFIG_BOOT_PRINTK_DELAY
-
-static int boot_delay; /* msecs delay after each printk during bootup */
-static unsigned long long loops_per_msec;	/* based on boot_delay */
-
-static int __init boot_delay_setup(char *str)
-{
-	unsigned long lpj;
-
-	lpj = preset_lpj ? preset_lpj : 1000000;	/* some guess */
-	loops_per_msec = (unsigned long long)lpj / 1000 * HZ;
-
-	get_option(&str, &boot_delay);
-	if (boot_delay > 10 * 1000)
-		boot_delay = 0;
-
-	pr_debug("boot_delay: %u, preset_lpj: %ld, lpj: %lu, "
-		"HZ: %d, loops_per_msec: %llu\n",
-		boot_delay, preset_lpj, lpj, HZ, loops_per_msec);
-	return 0;
-}
-early_param("boot_delay", boot_delay_setup);
-
-static void boot_delay_msec(int level)
-{
-	unsigned long long k;
-	unsigned long timeout;
-	bool suppress = !is_printk_force_console() &&
-			suppress_message_printing(level);
-
-	if ((boot_delay == 0 || system_state >= SYSTEM_RUNNING) || suppress)
-		return;
-
-	k = (unsigned long long)loops_per_msec * boot_delay;
-
-	timeout = jiffies + msecs_to_jiffies(boot_delay);
-	while (k) {
-		k--;
-		cpu_relax();
-		/*
-		 * use (volatile) jiffies to prevent
-		 * compiler reduction; loop termination via jiffies
-		 * is secondary and may or may not happen.
-		 */
-		if (time_after(jiffies, timeout))
-			break;
-		touch_nmi_watchdog();
-	}
-}
-#else
-static inline void boot_delay_msec(int level)
-{
-}
-#endif
-
 static bool printk_time = IS_ENABLED(CONFIG_PRINTK_TIME);
 module_param_named(time, printk_time, bool, S_IRUGO | S_IWUSR);
 
@@ -2117,22 +2062,6 @@ static u8 *__printk_recursion_counter(void)
 		local_irq_restore(flags);		\
 	} while (0)
 
-int printk_delay_msec __read_mostly;
-
-static inline void printk_delay(int level)
-{
-	boot_delay_msec(level);
-
-	if (unlikely(printk_delay_msec)) {
-		int m = printk_delay_msec;
-
-		while (m--) {
-			mdelay(1);
-			touch_nmi_watchdog();
-		}
-	}
-}
-
 #define CALLER_ID_MASK 0x80000000
 
 static inline u32 printk_caller_id(void)
@@ -2450,8 +2379,6 @@ asmlinkage int vprintk_emit(int facility, int level,
 		ft.legacy_direct = false;
 	}
 
-	printk_delay(level);
-
 	printed_len = vprintk_store(facility, level, dev_info, fmt, args);
 
 	if (ft.nbcon_atomic)
diff --git a/kernel/printk/sysctl.c b/kernel/printk/sysctl.c
index f15732e93c2e9c0865c42e4af9cb6458d4402c0a..5178540b2643d1b1a51dfef3f0444414889d7a3e 100644
--- a/kernel/printk/sysctl.c
+++ b/kernel/printk/sysctl.c
@@ -41,15 +41,6 @@ static const struct ctl_table printk_sysctls[] = {
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec,
 	},
-	{
-		.procname	= "printk_delay",
-		.data		= &printk_delay_msec,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= proc_dointvec_minmax,
-		.extra1		= SYSCTL_ZERO,
-		.extra2		= (void *)&ten_thousand,
-	},
 	{
 		.procname	= "printk_devkmsg",
 		.data		= devkmsg_log_str,
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 8ff5adcfe1e0a2f13893c92c3b95498fedb83855..fa82d76e7de45e05e5c0d578eaa2e5807bca39d1 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -99,24 +99,6 @@ config MESSAGE_LOGLEVEL_DEFAULT
 	  by default. To change that, use loglevel=<x> in the kernel bootargs,
 	  or pick a different CONSOLE_LOGLEVEL_DEFAULT configuration value.
 
-config BOOT_PRINTK_DELAY
-	bool "Delay each boot printk message by N milliseconds"
-	depends on DEBUG_KERNEL && PRINTK && GENERIC_CALIBRATE_DELAY
-	help
-	  This build option allows you to read kernel boot messages
-	  by inserting a short delay after each one.  The delay is
-	  specified in milliseconds on the kernel command line,
-	  using "boot_delay=N".
-
-	  It is likely that you would also need to use "lpj=M" to preset
-	  the "loops per jiffy" value.
-	  See a previous boot log for the "lpj" value to use for your
-	  system, and then set "lpj=M" before setting "boot_delay=N".
-	  NOTE:  Using this option may adversely affect SMP systems.
-	  I.e., processors other than the first one may not boot up.
-	  BOOT_PRINTK_DELAY also may cause LOCKUP_DETECTOR to detect
-	  what it believes to be lockup conditions.
-
 config DYNAMIC_DEBUG
 	bool "Enable dynamic printk() support"
 	default n

---
base-commit: 7fd2df204f342fc17d1a0bfcd474b24232fb0f32
change-id: 20260505-printk_delay-78884daa7eb8

Best regards,
-- 
Andrew Murray <amurray@thegoodpenguin.co.uk>


^ permalink raw reply related

* Re: [PATCH v2 11/11] MAINTAINERS: use a URL for pin-init maintainer's profile entry
From: Gary Guo @ 2026-05-05 13:49 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Benno Lossin, Jonathan Corbet,
	Linux Doc Mailing List
  Cc: linux-kernel, rust-for-linux, Björn Roy Baron, Alice Ryhl,
	Andreas Hindborg, Boqun Feng, Danilo Krummrich, Gary Guo,
	Miguel Ojeda, Trevor Gross
In-Reply-To: <1bceee886b9027d66bbb48d9d6c8d1250ce8dbcb.1777987028.git.mchehab+huawei@kernel.org>

On Tue May 5, 2026 at 2:25 PM BST, Mauro Carvalho Chehab wrote:
> This maintainer's entry is not inside documentation nor is
> ReST, preventing Sphinx to create a hyperlink to it.
>
> Change it to point to the already-formatted URL.
>
> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
> ---
>  MAINTAINERS                   |  2 +-
>  rust/pin-init/CONTRIBUTING.md | 72 -----------------------------------
>  2 files changed, 1 insertion(+), 73 deletions(-)
>  delete mode 100644 rust/pin-init/CONTRIBUTING.md
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 8700472b3ae3..b16c8f85d099 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -23402,7 +23402,7 @@ S:	Maintained
>  W:	https://rust-for-linux.com/pin-init
>  B:	https://github.com/Rust-for-Linux/pin-init/issues
>  C:	zulip://rust-for-linux.zulipchat.com
> -P:	rust/pin-init/CONTRIBUTING.md
> +P:	https://github.com/Rust-for-Linux/pin-init/blob/main/CONTRIBUTING.md
>  T:	git https://github.com/Rust-for-Linux/linux.git pin-init-next
>  F:	rust/kernel/init.rs
>  F:	rust/pin-init/
> diff --git a/rust/pin-init/CONTRIBUTING.md b/rust/pin-init/CONTRIBUTING.md
> deleted file mode 100644
> index 16c899a7ae0b..000000000000
> --- a/rust/pin-init/CONTRIBUTING.md
> +++ /dev/null

This file is part of the bidirectional source sync.

I think this file is still meaningful in its present location even if not
rendered, so people touching the code would be able to see it and be aware. The
presence of file is more visible than a P entry in the MAINTAINERS file.

That said, if Miguel and/or Benno think it's fine to not have this file, I'm
also okay with it being removed.

Best,
Gary

> @@ -1,72 +0,0 @@
> -# Contributing to `pin-init`
> -
> -Thanks for showing interest in contributing to `pin-init`! This document outlines the guidelines for
> -contributing to `pin-init`.
> -
> -All contributions are double-licensed under Apache 2.0 and MIT. You can find the respective licenses
> -in the `LICENSE-APACHE` and `LICENSE-MIT` files.
> -
> -## Non-Code Contributions
> -
> -### Bug Reports
> -
> -For any type of bug report, please submit an issue using the bug report issue template.
> -
> -If the issue is a soundness issue, please privately report it as a security vulnerability via the
> -GitHub web interface.
> -
> -### Feature Requests
> -
> -If you have any feature requests, please submit an issue using the feature request issue template.
> -compare
> -### Questions and Getting Help
> -
> -You can ask questions in the Discussions page of the GitHub repository. If you're encountering
> -problems or just have questions related to `pin-init` in the Linux kernel, you can also ask your
> -questions in the [Rust-for-Linux Zulip](https://rust-for-linux.zulipchat.com/) or see
> -<https://rust-for-linux.com/contact>.
> -
> -## Contributing Code
> -
> -### Linux Kernel
> -
> -`pin-init` is used by the Linux kernel and all commits are synchronized to it. For this reason, the
> -same requirements for commits apply to `pin-init`. See [the kernel's documentation] for details. The
> -rest of this document will also cover some of the rules listed there and additional ones.
> -
> -[the kernel's documentation]: https://docs.kernel.org/process/submitting-patches.html
> -
> -Contributions to `pin-init` ideally go through the [GitHub repository], because that repository runs
> -a CI with lots of tests not present in the kernel. However, patches are also accepted (though not
> -preferred). Do note that there are some files that are only present in the GitHub repository such as
> -tests, licenses and cargo related files. Making changes to them can only happen via GitHub.
> -
> -[GitHub repository]: https://github.com/Rust-for-Linux/pin-init
> -
> -### Commit Style
> -
> -Everything must compile without errors or warnings and all tests must pass after **every commit**.
> -This is important for bisection and also required by the kernel.
> -
> -Each commit should be a single, logically cohesive change. Of course it's best to keep the changes
> -small and digestible, but logically linked changes should be made in the same commit. For example,
> -when fixing typos, create a single commit that fixes all of them instead of one commit per typo.
> -
> -Commits must have a meaningful commit title. Commits with changes to files in the `internal`
> -directory should have a title prefixed with `internal:`. The commit message should explain the
> -change and its rationale. You also have to add your `Signed-off-by` tag, see [Developer's
> -Certificate of Origin]. This has to be done for both mailing list submissions as well as GitHub
> -submissions.
> -
> -[Developer's Certificate of Origin]: https://docs.kernel.org/process/submitting-patches.html#sign-your-work-the-developer-s-certificate-of-origin
> -
> -Any changes made to public APIs must be documented not only in the commit message, but also in the
> -`CHANGELOG.md` file. This is especially important for breaking changes, as those warrant a major
> -version bump.
> -
> -If you make changes to the top-level crate documentation, you also need to update the `README.md`
> -via `cargo rdme`.
> -
> -Some of these rules can be ignored if the change is done solely to files that are not present in the
> -kernel version of this library. Those files are documented in the `sync-kernel.sh` script at the
> -very bottom in the `--exclude` flag given to the `git am` command.


^ permalink raw reply

* Re: [PATCH v9 3/6] iio: adc: ad4691: add triggered buffer support
From: Jonathan Cameron @ 2026-05-05 14:04 UTC (permalink / raw)
  To: Radu Sabau via B4 Relay
  Cc: radu.sabau, Lars-Peter Clausen, Michael Hennerich, David Lechner,
	Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Uwe Kleine-König, Liam Girdwood, Mark Brown,
	Linus Walleij, Bartosz Golaszewski, Philipp Zabel,
	Jonathan Corbet, Shuah Khan, linux-iio, devicetree, linux-kernel,
	linux-pwm, linux-gpio, linux-doc
In-Reply-To: <20260430-ad4692-multichannel-sar-adc-driver-v9-3-33e439e4fb87@analog.com>

On Thu, 30 Apr 2026 13:16:45 +0300
Radu Sabau via B4 Relay <devnull+radu.sabau.analog.com@kernel.org> wrote:

> From: Radu Sabau <radu.sabau@analog.com>
> 
> Add buffered capture support using the IIO triggered buffer framework.
> 
> CNV Burst Mode: the GP pin identified by interrupt-names in the device
> tree is configured as DATA_READY output. The IRQ handler stops
> conversions and fires the IIO trigger; the trigger handler executes a
> pre-built SPI message that reads all active channels from the AVG_IN
> accumulator registers and then resets accumulator state and restarts
> conversions for the next cycle.
> 
> Manual Mode: CNV is tied to SPI CS so each transfer simultaneously
> reads the previous result and starts the next conversion (pipelined
> N+1 scheme). At preenable time a pre-built, optimised SPI message of
> N+1 transfers is constructed (N channel reads plus one NOOP to drain
> the pipeline). The trigger handler executes the message in a single
> spi_sync() call and collects the results. An external trigger (e.g.
> iio-trig-hrtimer) is required to drive the trigger at the desired
> sample rate.
> 
> Both modes share the same trigger handler and push a complete scan —
> one u16 slot per channel at its scan_index position, followed by a
> timestamp — to the IIO buffer via iio_push_to_buffers_with_ts().
> 
> The CNV Burst Mode sampling frequency (PWM period) is exposed as a
> buffer-level attribute via IIO_DEVICE_ATTR.
> 
> Signed-off-by: Radu Sabau <radu.sabau@analog.com>
Hi Radu

I haven't chased it through but Sashiko is raising concerns around the
irq enabling / disable tricks this pulling and they may well be correct.
Please take a close look at what happens in the remove path. We may
need some local driver logic to avoid a double disable.

https://sashiko.dev/#/patchset/20260430-ad4692-multichannel-sar-adc-driver-v9-0-33e439e4fb87%40analog.com

> diff --git a/drivers/iio/adc/ad4691.c b/drivers/iio/adc/ad4691.c
> index 05826b762c7f..c1e3406fef18 100644
> --- a/drivers/iio/adc/ad4691.c
> +++ b/drivers/iio/adc/ad4691.c


> +
> +static irqreturn_t ad4691_irq(int irq, void *private)
> +{
> +	struct iio_dev *indio_dev = private;
> +	struct ad4691_state *st = iio_priv(indio_dev);
> +
> +	iio_trigger_poll(indio_dev->trig);
> +	/*
> +	 * Keep the DATA_READY IRQ disabled until the trigger handler has
> +	 * finished reading the scan, to prevent a new assertion mid-transfer.
> +	 * The PWM continues running uninterrupted; the IRQ is re-enabled in
> +	 * ad4691_trigger_handler once spi_sync completes.
> +	 *
> +	 * IRQF_ONESHOT already masks the hardware line during this threaded
> +	 * handler, so disable_irq_nosync here ensures the IRQ stays disabled
> +	 * even after IRQF_ONESHOT unmasks on return.
> +	 */
> +	disable_irq_nosync(st->irq);
> +
> +	return IRQ_HANDLED;
> +}

> +
> +static irqreturn_t ad4691_trigger_handler(int irq, void *p)
> +{
> +	struct iio_poll_func *pf = p;
> +	struct iio_dev *indio_dev = pf->indio_dev;
> +	struct ad4691_state *st = iio_priv(indio_dev);
> +
> +	ad4691_read_scan(indio_dev, pf->timestamp);
> +	if (!st->manual_mode)
> +		enable_irq(st->irq);

I think this should be in the reenable_trigger callback rather than here.
That's ultimately fired by iio_trigger_notify_done.

Sashiko had quite a bit to say about the problem paths around the buffer
being disabled between the interrupt and the trigger handler. I don't think
using the reenable trigger solves that though :(  We might be able
to fix that centrally by always reenabling the trigger before
disconnecting it but that's rather ugly. There is a note for the async
trigger reenabling about a driver possibly needing to be careful
to not reenable if the whole trigger was disabled in the meantime but
this particular race isn't covered.


Terrible though it is we may need to have some extra infrastructure
to avoid the double disable (assuming it is real).


> +	iio_trigger_notify_done(indio_dev->trig);
> +	return IRQ_HANDLED;
> +}



^ permalink raw reply

* [PATCH 0/8] drm/panthor: Protected mode support for Mali CSF GPUs
From: Ketil Johnsen @ 2026-05-05 14:05 UTC (permalink / raw)
  To: David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Jonathan Corbet, Shuah Khan, Sumit Semwal,
	Benjamin Gaignard, Brian Starkey, John Stultz, T.J. Mercier,
	Christian König, Boris Brezillon, Steven Price, Liviu Dudau,
	Daniel Almeida, Alice Ryhl, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: dri-devel, linux-doc, linux-kernel, linux-media, linaro-mm-sig,
	linux-arm-kernel, linux-mediatek, Ketil Johnsen

Hi,

This is a patch series covering the support for protected mode execution in
Mali Panthor CSF kernel driver.

It builds on the initial RFC posted by Florent Tomasin back in January of 2025.

The initial RFC can be found here:
https://lore.kernel.org/lkml/cover.1738228114.git.florent.tomasin@arm.com/

The Mali CSF GPUs come with the support for protected mode execution at the
HW level. This feature requires two main changes in the kernel driver:

1) Configure the GPU with a protected buffer. The system must provide a DMA
   heap from which the driver can allocate a protected buffer.
   It can be a carved-out memory or dynamically allocated protected memory region.
   Some system includes a trusted FW which is in charge of the protected memory.
   Since this problem is integration specific, the Mali Panthor CSF kernel
   driver must import the protected memory from a device specific exporter.

2) Handle enter and exit of the GPU HW from normal to protected mode of execution.
   FW sends a request for protected mode entry to the kernel driver.
   The acknowledgment of that request is a scheduling decision. Effectively,
   protected mode execution should not overrule normal mode of execution.
   A fair distribution of execution time will guaranty the overall performance
   of the device, including the UI (usually executing in normal mode),
   will not regress when a protected mode job is submitted by an application.


Background
----------

Current Mali Panthor CSF driver does not allow a user space application to
execute protected jobs on the GPU. This use case is quite common on end-user-device.
A user may want to watch a video or render content that is under a "Digital Right
Management" protection, or launch an application with user private data.

1) User-space:

   In order for an application to execute protected jobs on a Mali CSF GPU the
   user space application must submit jobs to the GPU within a "protected regions"
   (range of commands to execute in protected mode).

   Find here an example of a command buffer that contains protected commands:

```
          <--- Normal mode ---><--- Protected mode ---><--- Normal mode --->
   +-------------------------------------------------------------------------+
   | ... | CMD_0 | ... | CMD_N | PROT_REGION | CMD_N+1 | ... | CMD_N+M | ... |
   +-------------------------------------------------------------------------+
```

   The PROT_REGION command acts as a barrier to notify the HW of upcoming
   protected jobs. It also defines the number of commands to execute in protected
   mode.

   The Mesa definition of the opcode can be found here:

     https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/src/panfrost/lib/genxml/v10.xml?ref_type=heads#L763

2) Kernel-space:

   When loading the FW image, the Kernel driver must also load the data section of
   CSF FW that comes from the protected memory, in order to allow FW to execute in
   protected mode.

   Important: this memory is not owned by any process. It is a GPU device level
              protected memory.

   In addition, when a CSG (group) is created, it must have a protected suspend buffer.
   This memory is allocated within the kernel but bound to a specific CSG that belongs
   to a process. The kernel owns this allocation and does not allow user space mapping.
   The format of the data in this buffer is only known by the FW and does not need to
   be shared with other entities. The purpose of this buffer is the same as the normal
   suspend buffer but for protected mode. FW will use it to suspend the execution of
   PROT_REGION before returning to normal mode of execution.


Design decisions
----------------

The Mali Panthor CSF kernel driver will allocate protected DMA buffers
using a global protected DMA heap. The name of the heap can vary on
the system and is integration specific. Therefore, the kernel driver
will retrieve it using the DTB entry: "protected-heap-name".

The Mali Panthor CSF kernel driver will handle enter/exit of protected
mode with a fair consideration of the job scheduling.

If the system integrator does not provide a protected DMA heap, the driver
will not allow any protected mode execution.


Patch series
------------

[PATCHES 1-2]:
  Thees patches comes from the following patch series:
  https://lore.kernel.org/lkml/20240720071606.27930-1-yunfei.dong@mediatek.com/

  These extend the DMA-buf heap API to allow other kernel drivers to Find
  and allocate memory from dma heaps.

  Note: This patch series do not include a protected DMA heap, as this is
  platform specific.

  * dma-heap: Add proper kref handling on dma-buf heaps
  * dma-heap: Provide accessors so that in-kernel drivers can allocate dmabufs from specific heaps

[PATCHES 3, 5 and 6]:
  These are refactoring to aid the implementation of the protected rendering
  feature itself.

* drm/panthor: De-duplicate FW memory section sync
* drm/panthor: Minor scheduler refactoring
* drm/panthor: Explicit expansion of locked VM region

[Patch 4]:
  This introduces allocation of protected memory inside the Panthor driver.
  It also ensures the protected FW sections are loaded.

  * drm/panthor: Add support for protected memory allocation in panthor

[PATCH 7]:
  This patch implements the logic to handle enter/exit of the GPU protected
  mode in Panthor CSF driver.

  Note: to prevent scheduler priority inversion, only a single CSG is allowed
        to execute while in protected mode. It must be the top priority one.

  * drm/panthor: Add support for entering and exiting protected mode

[PATCH 8]:
  The final patch exposes this feature via the uAPI.

  * drm/panthor: Expose protected rendering features

Testing
-------

1) Platform and development environment

   Any platform containing a Mali CSF type of GPU and a protected memory allocator
   that is based on DMA Heap can be used. For example, it can be a physical platform
   or a simulator such as Arm Total Compute FVPs platforms. Reference to the latter:

     https://developer.arm.com/Tools%20and%20Software/Fixed%20Virtual%20Platforms/Total%20Compute%20FVPs

2) Mesa:

PanVK support can be found here:
https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40044

This is still work in progress.

Constraints
-----------

At the time of developing the feature, Linux kernel does not have a generic
way of implementing protected DMA heaps. The patch series relies on previous
work to expose the DMA heap API to the kernel drivers.

The Mali CSF GPU requires device level allocated protected memory, which do
not belong to a process. The current Linux implementation of DMA heap only
allows a user space program to allocate from such heap. Having the ability
to allocate this memory at the kernel level via the DMA heap API would allow
support for protected mode on Mali CSF GPUs.



Florent Tomasin (3):
  drm/panthor: Add support for protected memory allocation in panthor
  drm/panthor: Minor scheduler refactoring
  drm/panthor: Add support for entering and exiting protected mode

John Stultz (2):
  dma-heap: Add proper kref handling on dma-buf heaps
  dma-heap: Provide accessors so that in-kernel drivers can allocate dmabufs from specific heaps

Ketil Johnsen (3):
  drm/panthor: De-duplicate FW memory section sync
  drm/panthor: Explicit expansion of locked VM region
  drm/panthor: Expose protected rendering features

 Documentation/gpu/panthor.rst            |  47 +++
 drivers/dma-buf/dma-heap.c               | 109 ++++++-
 drivers/gpu/drm/panthor/Kconfig          |   1 +
 drivers/gpu/drm/panthor/panthor_device.c |  29 +-
 drivers/gpu/drm/panthor/panthor_device.h |  15 +
 drivers/gpu/drm/panthor/panthor_drv.c    |  21 +-
 drivers/gpu/drm/panthor/panthor_fw.c     | 137 ++++++--
 drivers/gpu/drm/panthor/panthor_fw.h     |   7 +
 drivers/gpu/drm/panthor/panthor_gem.c    |  77 ++++-
 drivers/gpu/drm/panthor/panthor_gem.h    |  16 +-
 drivers/gpu/drm/panthor/panthor_gpu.c    |  14 +-
 drivers/gpu/drm/panthor/panthor_gpu.h    |   6 +
 drivers/gpu/drm/panthor/panthor_heap.c   |   2 +
 drivers/gpu/drm/panthor/panthor_mmu.c    |  79 +++--
 drivers/gpu/drm/panthor/panthor_sched.c  | 387 ++++++++++++++++++-----
 include/linux/dma-heap.h                 |   8 +
 include/uapi/drm/panthor_drm.h           |  45 ++-
 17 files changed, 864 insertions(+), 136 deletions(-)

-- 
2.43.0


^ permalink raw reply

* [PATCH 1/8] dma-heap: Add proper kref handling on dma-buf heaps
From: Ketil Johnsen @ 2026-05-05 14:05 UTC (permalink / raw)
  To: David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Jonathan Corbet, Shuah Khan, Sumit Semwal,
	Benjamin Gaignard, Brian Starkey, John Stultz, T.J. Mercier,
	Christian König, Boris Brezillon, Steven Price, Liviu Dudau,
	Daniel Almeida, Alice Ryhl, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: dri-devel, linux-doc, linux-kernel, linux-media, linaro-mm-sig,
	linux-arm-kernel, linux-mediatek, Yong Wu, Yunfei Dong,
	Florent Tomasin, Ketil Johnsen
In-Reply-To: <20260505140516.1372388-1-ketil.johnsen@arm.com>

From: John Stultz <jstultz@google.com>

Add proper reference counting on the dma_heap structure. While
existing heaps are built-in, we may eventually have heaps loaded
from modules, and we'll need to be able to properly handle the
references to the heaps

Signed-off-by: John Stultz <jstultz@google.com>
Signed-off-by: T.J. Mercier <tjmercier@google.com>
Signed-off-by: Yong Wu <yong.wu@mediatek.com>
[Yong: Just add comment for "minor" and "refcount"]
Signed-off-by: Yunfei Dong <yunfei.dong@mediatek.com>
[Yunfei: Change reviewer's comments]
Signed-off-by: Florent Tomasin <florent.tomasin@arm.com>
[Florent: Rebase]
Signed-off-by: Ketil Johnsen <ketil.johnsen@arm.com>
[Ketil: Rebase]
---
 drivers/dma-buf/dma-heap.c | 29 +++++++++++++++++++++++++++++
 include/linux/dma-heap.h   |  2 ++
 2 files changed, 31 insertions(+)

diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index ac5f8685a6494..9fd365ddbd517 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -12,6 +12,7 @@
 #include <linux/dma-heap.h>
 #include <linux/err.h>
 #include <linux/export.h>
+#include <linux/kref.h>
 #include <linux/list.h>
 #include <linux/nospec.h>
 #include <linux/syscalls.h>
@@ -31,6 +32,7 @@
  * @heap_devt:		heap device node
  * @list:		list head connecting to list of heaps
  * @heap_cdev:		heap char device
+ * @refcount:		reference counter for this heap device
  *
  * Represents a heap of memory from which buffers can be made.
  */
@@ -41,6 +43,7 @@ struct dma_heap {
 	dev_t heap_devt;
 	struct list_head list;
 	struct cdev heap_cdev;
+	struct kref refcount;
 };
 
 static LIST_HEAD(heap_list);
@@ -248,6 +251,7 @@ struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info)
 	if (!heap)
 		return ERR_PTR(-ENOMEM);
 
+	kref_init(&heap->refcount);
 	heap->name = exp_info->name;
 	heap->ops = exp_info->ops;
 	heap->priv = exp_info->priv;
@@ -313,6 +317,31 @@ struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info)
 }
 EXPORT_SYMBOL_NS_GPL(dma_heap_add, "DMA_BUF_HEAP");
 
+static void dma_heap_release(struct kref *ref)
+{
+	struct dma_heap *heap = container_of(ref, struct dma_heap, refcount);
+	unsigned int minor = MINOR(heap->heap_devt);
+
+	mutex_lock(&heap_list_lock);
+	list_del(&heap->list);
+	mutex_unlock(&heap_list_lock);
+
+	device_destroy(dma_heap_class, heap->heap_devt);
+	cdev_del(&heap->heap_cdev);
+	xa_erase(&dma_heap_minors, minor);
+
+	kfree(heap);
+}
+
+/**
+ * dma_heap_put - drops a reference to a dmabuf heap, potentially freeing it
+ * @heap: DMA-Heap whose reference count to decrement
+ */
+void dma_heap_put(struct dma_heap *heap)
+{
+	kref_put(&heap->refcount, dma_heap_release);
+}
+
 static char *dma_heap_devnode(const struct device *dev, umode_t *mode)
 {
 	return kasprintf(GFP_KERNEL, "dma_heap/%s", dev_name(dev));
diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h
index 648328a64b27e..ff57741700f5f 100644
--- a/include/linux/dma-heap.h
+++ b/include/linux/dma-heap.h
@@ -46,6 +46,8 @@ const char *dma_heap_get_name(struct dma_heap *heap);
 
 struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info);
 
+void dma_heap_put(struct dma_heap *heap);
+
 extern bool mem_accounting;
 
 #endif /* _DMA_HEAPS_H */
-- 
2.43.0


^ permalink raw reply related

* [PATCH 2/8] dma-heap: Provide accessors so that in-kernel drivers can allocate dmabufs from specific heaps
From: Ketil Johnsen @ 2026-05-05 14:05 UTC (permalink / raw)
  To: David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Jonathan Corbet, Shuah Khan, Sumit Semwal,
	Benjamin Gaignard, Brian Starkey, John Stultz, T.J. Mercier,
	Christian König, Boris Brezillon, Steven Price, Liviu Dudau,
	Daniel Almeida, Alice Ryhl, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: dri-devel, linux-doc, linux-kernel, linux-media, linaro-mm-sig,
	linux-arm-kernel, linux-mediatek, Yong Wu, Yunfei Dong,
	Florent Tomasin, Ketil Johnsen
In-Reply-To: <20260505140516.1372388-1-ketil.johnsen@arm.com>

From: John Stultz <jstultz@google.com>

This allows drivers who don't want to create their own
DMA-BUF exporter to be able to allocate DMA-BUFs directly
from existing DMA-BUF Heaps.

There is some concern that the premise of DMA-BUF heaps is
that userland knows better about what type of heap memory
is needed for a pipeline, so it would likely be best for
drivers to import and fill DMA-BUFs allocated by userland
instead of allocating one themselves, but this is still
up for debate.

Signed-off-by: John Stultz <jstultz@google.com>
Signed-off-by: T.J. Mercier <tjmercier@google.com>
Signed-off-by: Yong Wu <yong.wu@mediatek.com>
[Yong: Fix the checkpatch alignment warning]
Signed-off-by: Yunfei Dong <yunfei.dong@mediatek.com>
Signed-off-by: Florent Tomasin <florent.tomasin@arm.com>
[Florent: Rebase]
Signed-off-by: Ketil Johnsen <ketil.johnsen@arm.com>
[Ketil: Rebase]
---
 drivers/dma-buf/dma-heap.c | 80 ++++++++++++++++++++++++++++++--------
 include/linux/dma-heap.h   |  6 +++
 2 files changed, 70 insertions(+), 16 deletions(-)

diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index 9fd365ddbd517..854d40d789ff2 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -57,12 +57,24 @@ module_param(mem_accounting, bool, 0444);
 MODULE_PARM_DESC(mem_accounting,
 		 "Enable cgroup-based memory accounting for dma-buf heap allocations (default=false).");
 
-static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len,
-				 u32 fd_flags,
-				 u64 heap_flags)
+/**
+ * dma_heap_buffer_alloc - Allocate dma-buf from a dma_heap
+ * @heap:	DMA-Heap to allocate from
+ * @len:	size to allocate in bytes
+ * @fd_flags:	flags to set on returned dma-buf fd
+ * @heap_flags: flags to pass to the dma heap
+ *
+ * This is for internal dma-buf allocations only. Free returned buffers with dma_buf_put().
+ */
+struct dma_buf *dma_heap_buffer_alloc(struct dma_heap *heap, size_t len,
+				      u32 fd_flags,
+				      u64 heap_flags)
 {
-	struct dma_buf *dmabuf;
-	int fd;
+	if (fd_flags & ~DMA_HEAP_VALID_FD_FLAGS)
+		return ERR_PTR(-EINVAL);
+
+	if (heap_flags & ~DMA_HEAP_VALID_HEAP_FLAGS)
+		return ERR_PTR(-EINVAL);
 
 	/*
 	 * Allocations from all heaps have to begin
@@ -70,9 +82,20 @@ static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len,
 	 */
 	len = PAGE_ALIGN(len);
 	if (!len)
-		return -EINVAL;
+		return ERR_PTR(-EINVAL);
+
+	return heap->ops->allocate(heap, len, fd_flags, heap_flags);
+}
+EXPORT_SYMBOL_NS_GPL(dma_heap_buffer_alloc, "DMA_BUF_HEAP");
 
-	dmabuf = heap->ops->allocate(heap, len, fd_flags, heap_flags);
+static int dma_heap_bufferfd_alloc(struct dma_heap *heap, size_t len,
+				   u32 fd_flags,
+				   u64 heap_flags)
+{
+	struct dma_buf *dmabuf;
+	int fd;
+
+	dmabuf = dma_heap_buffer_alloc(heap, len, fd_flags, heap_flags);
 	if (IS_ERR(dmabuf))
 		return PTR_ERR(dmabuf);
 
@@ -110,15 +133,9 @@ static long dma_heap_ioctl_allocate(struct file *file, void *data)
 	if (heap_allocation->fd)
 		return -EINVAL;
 
-	if (heap_allocation->fd_flags & ~DMA_HEAP_VALID_FD_FLAGS)
-		return -EINVAL;
-
-	if (heap_allocation->heap_flags & ~DMA_HEAP_VALID_HEAP_FLAGS)
-		return -EINVAL;
-
-	fd = dma_heap_buffer_alloc(heap, heap_allocation->len,
-				   heap_allocation->fd_flags,
-				   heap_allocation->heap_flags);
+	fd = dma_heap_bufferfd_alloc(heap, heap_allocation->len,
+				     heap_allocation->fd_flags,
+				     heap_allocation->heap_flags);
 	if (fd < 0)
 		return fd;
 
@@ -317,6 +334,36 @@ struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info)
 }
 EXPORT_SYMBOL_NS_GPL(dma_heap_add, "DMA_BUF_HEAP");
 
+/**
+ * dma_heap_find - get the heap registered with the specified name
+ * @name: Name of the DMA-Heap to find
+ *
+ * Returns:
+ * The DMA-Heap with the provided name.
+ *
+ * NOTE: DMA-Heaps returned from this function MUST be released using
+ * dma_heap_put() when the user is done to enable the heap to be unloaded.
+ */
+struct dma_heap *dma_heap_find(const char *name)
+{
+	struct dma_heap *h;
+
+	mutex_lock(&heap_list_lock);
+	list_for_each_entry(h, &heap_list, list) {
+		if (!kref_get_unless_zero(&h->refcount))
+			continue;
+
+		if (!strcmp(h->name, name)) {
+			mutex_unlock(&heap_list_lock);
+			return h;
+		}
+		dma_heap_put(h);
+	}
+	mutex_unlock(&heap_list_lock);
+	return NULL;
+}
+EXPORT_SYMBOL_NS_GPL(dma_heap_find, "DMA_BUF_HEAP");
+
 static void dma_heap_release(struct kref *ref)
 {
 	struct dma_heap *heap = container_of(ref, struct dma_heap, refcount);
@@ -341,6 +388,7 @@ void dma_heap_put(struct dma_heap *heap)
 {
 	kref_put(&heap->refcount, dma_heap_release);
 }
+EXPORT_SYMBOL_NS_GPL(dma_heap_put, "DMA_BUF_HEAP");
 
 static char *dma_heap_devnode(const struct device *dev, umode_t *mode)
 {
diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h
index ff57741700f5f..c3351f8a1f8cf 100644
--- a/include/linux/dma-heap.h
+++ b/include/linux/dma-heap.h
@@ -46,8 +46,14 @@ const char *dma_heap_get_name(struct dma_heap *heap);
 
 struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info);
 
+struct dma_heap *dma_heap_find(const char *name);
+
 void dma_heap_put(struct dma_heap *heap);
 
+struct dma_buf *dma_heap_buffer_alloc(struct dma_heap *heap, size_t len,
+				      u32 fd_flags,
+				      u64 heap_flags);
+
 extern bool mem_accounting;
 
 #endif /* _DMA_HEAPS_H */
-- 
2.43.0


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox