* [PATCH] docs: kdoc: handle TRACE_EVENT_FN() family in tracepoint parser
@ 2026-10-02 2:34 Omokefe Emmanuel Onanaroghene
2026-10-02 4:21 ` Randy Dunlap
0 siblings, 1 reply; 14+ messages in thread
From: Omokefe Emmanuel Onanaroghene @ 2026-10-02 2:34 UTC (permalink / raw)
To: linux-doc, linux-kernel
Cc: corbet, skhan, rdunlap, mchehab, aleksandr.loktionov,
Omokefe Emmanuel Onanaroghene
kernel-doc fails to parse tracepoint declarations that use
TRACE_EVENT_FN(), e.g. gpu_power_status:
drivers/gpu/drm/panthor/panthor_trace.h:28 ... Unrecognized
tracepoint format ...
... expecting prototype for gpu_power_status(). Prototype was for
TRACE_EVENT_FN() instead
tracepoint_munge() only matches TRACE_EVENT(), so the macro name is
kept as the prototype and the TP_PROTO() arguments leak into the
parameter list as garbage.
Match TRACE_EVENT_FN(), TRACE_EVENT_FN_COND(),
TRACE_EVENT_CONDITION() and TRACE_EVENT_SYSCALL() the same way as
TRACE_EVENT() and list them explicitly at the call site in
process_proto_function().
Add a regression test for the gpu_power_status declaration.
Signed-off-by: Omokefe Emmanuel Onanaroghene <emmaonana18@gmail.com>
---
tools/lib/python/kdoc/kdoc_parser.py | 18 +++++++++++++++++-
tools/unittests/test_kdoc_parser.py | 28 ++++++++++++++++++++++++++++
2 files changed, 45 insertions(+), 1 deletion(-)
diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py
index d9ad1ddc87dd..28c325665c17 100644
--- a/tools/lib/python/kdoc/kdoc_parser.py
+++ b/tools/lib/python/kdoc/kdoc_parser.py
@@ -1542,6 +1542,22 @@ class KernelDoc:
if r.search(proto):
tracepointname = r.group(1)
+ r = KernRe(r'TRACE_EVENT_FN\((.*?),')
+ if r.search(proto):
+ tracepointname = r.group(1)
+
+ r = KernRe(r'TRACE_EVENT_FN_COND\((.*?),')
+ if r.search(proto):
+ tracepointname = r.group(1)
+
+ r = KernRe(r'TRACE_EVENT_CONDITION\((.*?),')
+ if r.search(proto):
+ tracepointname = r.group(1)
+
+ r = KernRe(r'TRACE_EVENT_SYSCALL\((.*?),')
+ if r.search(proto):
+ tracepointname = r.group(1)
+
r = KernRe(r'DEFINE_SINGLE_EVENT\((.*?),')
if r.search(proto):
tracepointname = r.group(1)
@@ -1601,7 +1617,7 @@ class KernelDoc:
self.entry.prototype = self.syscall_munge(ln,
self.entry.prototype)
else:
- r = KernRe(r'TRACE_EVENT|DEFINE_EVENT|DEFINE_SINGLE_EVENT')
+ r = KernRe(r'TRACE_EVENT|TRACE_EVENT_FN|TRACE_EVENT_FN_COND|TRACE_EVENT_CONDITION|TRACE_EVENT_SYSCALL|DEFINE_EVENT|DEFINE_SINGLE_EVENT')
if r.search(self.entry.prototype):
self.entry.prototype = self.tracepoint_munge(ln,
self.entry.prototype)
diff --git a/tools/unittests/test_kdoc_parser.py b/tools/unittests/test_kdoc_parser.py
index c4a76ed13dbc..398e11a8737e 100755
--- a/tools/unittests/test_kdoc_parser.py
+++ b/tools/unittests/test_kdoc_parser.py
@@ -418,6 +418,34 @@ class TestSelfValidate(GenerateKdocItem):
"""
self.run_test(self.SOURCE, [self.DEFAULT.copy()], self.EXPORTS)
+class TestTraceEventFn(GenerateKdocItem):
+ def test_trace_event_fn_declaration(self):
+ source = """
+ /**
+ * gpu_power_status - called when hardware turns on or off
+ * @dev: pointer to device
+ * @shader_bitmap: bitmap
+ */
+ TRACE_EVENT_FN(gpu_power_status,
+ TP_PROTO(const struct device *dev, u64 shader_bitmap),
+ TP_ARGS(dev, shader_bitmap),
+ TP_STRUCT__entry(__field(u64, shader_bitmap)),
+ TP_fast_assign(__entry->shader_bitmap = shader_bitmap;),
+ TP_printk("%s", __get_str(dev_name)),
+ my_register, my_unregister
+ );
+ """
+
+ kernel_doc = KernelDoc(self.config, "test.c", self.xforms)
+ patcher = patch('builtins.open', new_callable=mock_open,
+ read_data=dedent(source))
+ with patcher:
+ _, entries = kernel_doc.parse_kdoc()
+
+ self.assertEqual(len(entries), 1)
+ self.assertEqual(entries[0].name, "trace_gpu_power_status")
+ self.assertEqual(entries[0].warnings, [])
+
#
# Class and logic to create dynamic tests from YAML
#
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH] docs: kdoc: strip DOMAIN_NS() wrapper in function prototypes
@ 2026-10-02 4:15 Omokefe Emmanuel Onanaroghene
2026-10-02 4:28 ` Randy Dunlap
2026-10-14 17:22 ` Jonathan Corbet
0 siblings, 2 replies; 14+ messages in thread
From: Omokefe Emmanuel Onanaroghene @ 2026-10-02 4:15 UTC (permalink / raw)
To: linux-doc, linux-kernel
Cc: corbet, skhan, rdunlap, mchehab, aleksandr.loktionov, bvanassche,
emmaonana18, tudor.ambarus
kernel-doc fails to parse functions whose names are wrapped in the
DOMAIN_NS() namespace macro, e.g. in
drivers/iommu/generic_pt/iommu_pt.h:217:
... expecting prototype for iova_to_phys(). Prototype was for
DOMAIN_NS() instead
function_xforms is the designated place for unwrapping function-name
macros, but it has no entry for DOMAIN_NS(), so the macro name is kept
as the prototype and the real name leaks into the parameter list.
Add a transform expanding DOMAIN_NS(op) to op, following the existing
DEFINE_IDTENTRY_IRQ precedent.
Add a regression test for the wrapped iova_to_phys() declaration.
Signed-off-by: Omokefe Emmanuel Onanaroghene <emmaonana18@gmail.com>
---
tools/lib/python/kdoc/xforms_lists.py | 6 ++++++
tools/unittests/test_kdoc_parser.py | 22 ++++++++++++++++++++++
2 files changed, 28 insertions(+)
diff --git a/tools/lib/python/kdoc/xforms_lists.py b/tools/lib/python/kdoc/xforms_lists.py
index e3dda2fe8a53..5e8bd9117895 100644
--- a/tools/lib/python/kdoc/xforms_lists.py
+++ b/tools/lib/python/kdoc/xforms_lists.py
@@ -91,6 +91,12 @@ class CTransforms:
(CMatch("__diagnose_as"), ""),
(CMatch("DECL_BUCKET_PARAMS"), r"\1, \2"),
(CMatch("DEFINE_IDTENTRY_IRQ"), r"static void \1(struct pt_regs *regs, u32 vector)"),
+ #
+ # DOMAIN_NS() wraps a function name with a namespace prefix
+ # (see drivers/iommu/generic_pt/iommu_pt.h). Unwrap it so the
+ # real function name is parsed.
+ #
+ (CMatch("DOMAIN_NS"), r"\1"),
(CMatch("__cond_acquires"), ""),
(CMatch("__cond_releases"), ""),
(CMatch("__acquires"), ""),
diff --git a/tools/unittests/test_kdoc_parser.py b/tools/unittests/test_kdoc_parser.py
index c4a76ed13dbc..4b47a858824a 100755
--- a/tools/unittests/test_kdoc_parser.py
+++ b/tools/unittests/test_kdoc_parser.py
@@ -418,6 +418,28 @@ class TestSelfValidate(GenerateKdocItem):
"""
self.run_test(self.SOURCE, [self.DEFAULT.copy()], self.EXPORTS)
+class TestDomainNs(GenerateKdocItem):
+ def test_domain_ns_wrapped_function(self):
+ source = """
+ /**
+ * iova_to_phys() - Return the output address for the given IOVA
+ * @domain: Table to query
+ * @iova: IO virtual address to query
+ */
+ phys_addr_t DOMAIN_NS(iova_to_phys)(struct iommu_domain *domain,
+ dma_addr_t iova);
+ """
+
+ kernel_doc = KernelDoc(self.config, "test.c", self.xforms)
+ patcher = patch('builtins.open', new_callable=mock_open,
+ read_data=dedent(source))
+ with patcher:
+ _, entries = kernel_doc.parse_kdoc()
+
+ self.assertEqual(len(entries), 1)
+ self.assertEqual(entries[0].name, "iova_to_phys")
+ self.assertEqual(entries[0].warnings, [])
+
#
# Class and logic to create dynamic tests from YAML
#
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH] docs: kdoc: handle TRACE_EVENT_FN() family in tracepoint parser
2026-10-02 2:34 [PATCH] docs: kdoc: handle TRACE_EVENT_FN() family in tracepoint parser Omokefe Emmanuel Onanaroghene
@ 2026-10-02 4:21 ` Randy Dunlap
0 siblings, 0 replies; 14+ messages in thread
From: Randy Dunlap @ 2026-10-02 4:21 UTC (permalink / raw)
To: Omokefe Emmanuel Onanaroghene, linux-doc, linux-kernel
Cc: corbet, skhan, mchehab, aleksandr.loktionov
On 10/1/26 7:34 PM, Omokefe Emmanuel Onanaroghene wrote:
> kernel-doc fails to parse tracepoint declarations that use
> TRACE_EVENT_FN(), e.g. gpu_power_status:
>
> drivers/gpu/drm/panthor/panthor_trace.h:28 ... Unrecognized
> tracepoint format ...
> ... expecting prototype for gpu_power_status(). Prototype was for
> TRACE_EVENT_FN() instead
>
> tracepoint_munge() only matches TRACE_EVENT(), so the macro name is
> kept as the prototype and the TP_PROTO() arguments leak into the
> parameter list as garbage.
>
> Match TRACE_EVENT_FN(), TRACE_EVENT_FN_COND(),
> TRACE_EVENT_CONDITION() and TRACE_EVENT_SYSCALL() the same way as
> TRACE_EVENT() and list them explicitly at the call site in
> process_proto_function().
>
> Add a regression test for the gpu_power_status declaration.
>
> Signed-off-by: Omokefe Emmanuel Onanaroghene <emmaonana18@gmail.com>
Tested-by: Randy Dunlap <rdunlap@infradead.org>
Acked-by: Randy Dunlap <rdunlap@infradead.org>
Thanks.
> ---
> tools/lib/python/kdoc/kdoc_parser.py | 18 +++++++++++++++++-
> tools/unittests/test_kdoc_parser.py | 28 ++++++++++++++++++++++++++++
> 2 files changed, 45 insertions(+), 1 deletion(-)
>
> diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py
> index d9ad1ddc87dd..28c325665c17 100644
> --- a/tools/lib/python/kdoc/kdoc_parser.py
> +++ b/tools/lib/python/kdoc/kdoc_parser.py
> @@ -1542,6 +1542,22 @@ class KernelDoc:
> if r.search(proto):
> tracepointname = r.group(1)
>
> + r = KernRe(r'TRACE_EVENT_FN\((.*?),')
> + if r.search(proto):
> + tracepointname = r.group(1)
> +
> + r = KernRe(r'TRACE_EVENT_FN_COND\((.*?),')
> + if r.search(proto):
> + tracepointname = r.group(1)
> +
> + r = KernRe(r'TRACE_EVENT_CONDITION\((.*?),')
> + if r.search(proto):
> + tracepointname = r.group(1)
> +
> + r = KernRe(r'TRACE_EVENT_SYSCALL\((.*?),')
> + if r.search(proto):
> + tracepointname = r.group(1)
> +
> r = KernRe(r'DEFINE_SINGLE_EVENT\((.*?),')
> if r.search(proto):
> tracepointname = r.group(1)
> @@ -1601,7 +1617,7 @@ class KernelDoc:
> self.entry.prototype = self.syscall_munge(ln,
> self.entry.prototype)
> else:
> - r = KernRe(r'TRACE_EVENT|DEFINE_EVENT|DEFINE_SINGLE_EVENT')
> + r = KernRe(r'TRACE_EVENT|TRACE_EVENT_FN|TRACE_EVENT_FN_COND|TRACE_EVENT_CONDITION|TRACE_EVENT_SYSCALL|DEFINE_EVENT|DEFINE_SINGLE_EVENT')
> if r.search(self.entry.prototype):
> self.entry.prototype = self.tracepoint_munge(ln,
> self.entry.prototype)
> diff --git a/tools/unittests/test_kdoc_parser.py b/tools/unittests/test_kdoc_parser.py
> index c4a76ed13dbc..398e11a8737e 100755
> --- a/tools/unittests/test_kdoc_parser.py
> +++ b/tools/unittests/test_kdoc_parser.py
> @@ -418,6 +418,34 @@ class TestSelfValidate(GenerateKdocItem):
> """
> self.run_test(self.SOURCE, [self.DEFAULT.copy()], self.EXPORTS)
>
> +class TestTraceEventFn(GenerateKdocItem):
> + def test_trace_event_fn_declaration(self):
> + source = """
> + /**
> + * gpu_power_status - called when hardware turns on or off
> + * @dev: pointer to device
> + * @shader_bitmap: bitmap
> + */
> + TRACE_EVENT_FN(gpu_power_status,
> + TP_PROTO(const struct device *dev, u64 shader_bitmap),
> + TP_ARGS(dev, shader_bitmap),
> + TP_STRUCT__entry(__field(u64, shader_bitmap)),
> + TP_fast_assign(__entry->shader_bitmap = shader_bitmap;),
> + TP_printk("%s", __get_str(dev_name)),
> + my_register, my_unregister
> + );
> + """
> +
> + kernel_doc = KernelDoc(self.config, "test.c", self.xforms)
> + patcher = patch('builtins.open', new_callable=mock_open,
> + read_data=dedent(source))
> + with patcher:
> + _, entries = kernel_doc.parse_kdoc()
> +
> + self.assertEqual(len(entries), 1)
> + self.assertEqual(entries[0].name, "trace_gpu_power_status")
> + self.assertEqual(entries[0].warnings, [])
> +
> #
> # Class and logic to create dynamic tests from YAML
> #
--
~Randy
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] docs: kdoc: strip DOMAIN_NS() wrapper in function prototypes
2026-10-02 4:15 [PATCH] docs: kdoc: strip DOMAIN_NS() wrapper in function prototypes Omokefe Emmanuel Onanaroghene
@ 2026-10-02 4:28 ` Randy Dunlap
2026-10-14 17:22 ` Jonathan Corbet
1 sibling, 0 replies; 14+ messages in thread
From: Randy Dunlap @ 2026-10-02 4:28 UTC (permalink / raw)
To: Omokefe Emmanuel Onanaroghene, linux-doc, linux-kernel
Cc: corbet, skhan, mchehab, aleksandr.loktionov, bvanassche,
tudor.ambarus
On 10/1/26 9:15 PM, Omokefe Emmanuel Onanaroghene wrote:
> kernel-doc fails to parse functions whose names are wrapped in the
> DOMAIN_NS() namespace macro, e.g. in
> drivers/iommu/generic_pt/iommu_pt.h:217:
>
> ... expecting prototype for iova_to_phys(). Prototype was for
> DOMAIN_NS() instead
>
> function_xforms is the designated place for unwrapping function-name
> macros, but it has no entry for DOMAIN_NS(), so the macro name is kept
> as the prototype and the real name leaks into the parameter list.
>
> Add a transform expanding DOMAIN_NS(op) to op, following the existing
> DEFINE_IDTENTRY_IRQ precedent.
>
> Add a regression test for the wrapped iova_to_phys() declaration.
>
> Signed-off-by: Omokefe Emmanuel Onanaroghene <emmaonana18@gmail.com>
Tested-by: Randy Dunlap <rdunlap@infradead.org>
Acked-by: Randy Dunlap <rdunlap@infradead.org>
Thanks.
> ---
> tools/lib/python/kdoc/xforms_lists.py | 6 ++++++
> tools/unittests/test_kdoc_parser.py | 22 ++++++++++++++++++++++
> 2 files changed, 28 insertions(+)
>
> diff --git a/tools/lib/python/kdoc/xforms_lists.py b/tools/lib/python/kdoc/xforms_lists.py
> index e3dda2fe8a53..5e8bd9117895 100644
> --- a/tools/lib/python/kdoc/xforms_lists.py
> +++ b/tools/lib/python/kdoc/xforms_lists.py
> @@ -91,6 +91,12 @@ class CTransforms:
> (CMatch("__diagnose_as"), ""),
> (CMatch("DECL_BUCKET_PARAMS"), r"\1, \2"),
> (CMatch("DEFINE_IDTENTRY_IRQ"), r"static void \1(struct pt_regs *regs, u32 vector)"),
> + #
> + # DOMAIN_NS() wraps a function name with a namespace prefix
> + # (see drivers/iommu/generic_pt/iommu_pt.h). Unwrap it so the
> + # real function name is parsed.
> + #
> + (CMatch("DOMAIN_NS"), r"\1"),
> (CMatch("__cond_acquires"), ""),
> (CMatch("__cond_releases"), ""),
> (CMatch("__acquires"), ""),
> diff --git a/tools/unittests/test_kdoc_parser.py b/tools/unittests/test_kdoc_parser.py
> index c4a76ed13dbc..4b47a858824a 100755
> --- a/tools/unittests/test_kdoc_parser.py
> +++ b/tools/unittests/test_kdoc_parser.py
> @@ -418,6 +418,28 @@ class TestSelfValidate(GenerateKdocItem):
> """
> self.run_test(self.SOURCE, [self.DEFAULT.copy()], self.EXPORTS)
>
> +class TestDomainNs(GenerateKdocItem):
> + def test_domain_ns_wrapped_function(self):
> + source = """
> + /**
> + * iova_to_phys() - Return the output address for the given IOVA
> + * @domain: Table to query
> + * @iova: IO virtual address to query
> + */
> + phys_addr_t DOMAIN_NS(iova_to_phys)(struct iommu_domain *domain,
> + dma_addr_t iova);
> + """
> +
> + kernel_doc = KernelDoc(self.config, "test.c", self.xforms)
> + patcher = patch('builtins.open', new_callable=mock_open,
> + read_data=dedent(source))
> + with patcher:
> + _, entries = kernel_doc.parse_kdoc()
> +
> + self.assertEqual(len(entries), 1)
> + self.assertEqual(entries[0].name, "iova_to_phys")
> + self.assertEqual(entries[0].warnings, [])
> +
> #
> # Class and logic to create dynamic tests from YAML
> #
--
~Randy
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] docs: kdoc: strip DOMAIN_NS() wrapper in function prototypes
2026-10-02 4:15 [PATCH] docs: kdoc: strip DOMAIN_NS() wrapper in function prototypes Omokefe Emmanuel Onanaroghene
2026-10-02 4:28 ` Randy Dunlap
@ 2026-10-14 17:22 ` Jonathan Corbet
2026-10-14 22:47 ` Omokefe Emmanuel Onanaroghene
1 sibling, 1 reply; 14+ messages in thread
From: Jonathan Corbet @ 2026-10-14 17:22 UTC (permalink / raw)
To: Omokefe Emmanuel Onanaroghene, linux-doc, linux-kernel
Cc: skhan, rdunlap, mchehab, aleksandr.loktionov, bvanassche,
emmaonana18, tudor.ambarus
Omokefe Emmanuel Onanaroghene <emmaonana18@gmail.com> writes:
> kernel-doc fails to parse functions whose names are wrapped in the
> DOMAIN_NS() namespace macro, e.g. in
> drivers/iommu/generic_pt/iommu_pt.h:217:
>
> ... expecting prototype for iova_to_phys(). Prototype was for
> DOMAIN_NS() instead
>
> function_xforms is the designated place for unwrapping function-name
> macros, but it has no entry for DOMAIN_NS(), so the macro name is kept
> as the prototype and the real name leaks into the parameter list.
>
> Add a transform expanding DOMAIN_NS(op) to op, following the existing
> DEFINE_IDTENTRY_IRQ precedent.
>
> Add a regression test for the wrapped iova_to_phys() declaration.
>
> Signed-off-by: Omokefe Emmanuel Onanaroghene <emmaonana18@gmail.com>
> ---
> tools/lib/python/kdoc/xforms_lists.py | 6 ++++++
> tools/unittests/test_kdoc_parser.py | 22 ++++++++++++++++++++++
> 2 files changed, 28 insertions(+)
Neither of these patches applies to docs-next...what did you base them
on?
jon
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] docs: kdoc: strip DOMAIN_NS() wrapper in function prototypes
2026-10-14 17:22 ` Jonathan Corbet
@ 2026-10-14 22:47 ` Omokefe Emmanuel Onanaroghene
2026-10-15 0:53 ` Omokefe Emmanuel Onanaroghene
0 siblings, 1 reply; 14+ messages in thread
From: Omokefe Emmanuel Onanaroghene @ 2026-10-14 22:47 UTC (permalink / raw)
To: Jonathan Corbet
Cc: linux-doc, linux-kernel, skhan, rdunlap, mchehab,
aleksandr.loktionov, bvanassche, tudor.ambarus, emmaonana18
On Wed, 14 Oct 2026 11:22:02 -0600, Jonathan Corbet <corbet@lwn.net> wrote:
> Neither of these patches applies to docs-next...what did you base them
> on?
Hi Jon,
I had based both patches on mainline rather than docs-next. I have
rebased both patches on top of docs-next and sent a v2 for both:
- https://lore.kernel.org/all/20261014223134.14772-1-emmaonana18@gmail.com/
- https://lore.kernel.org/all/20261014223437.16164-1-emmaonana18@gmail.com/
Apologies for the inconvenience.
Thanks,
Omokefe
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] docs: kdoc: strip DOMAIN_NS() wrapper in function prototypes
2026-10-14 22:47 ` Omokefe Emmanuel Onanaroghene
@ 2026-10-15 0:53 ` Omokefe Emmanuel Onanaroghene
2026-10-15 13:00 ` Jonathan Corbet
0 siblings, 1 reply; 14+ messages in thread
From: Omokefe Emmanuel Onanaroghene @ 2026-10-15 0:53 UTC (permalink / raw)
To: Jonathan Corbet
Cc: linux-doc, linux-kernel, skhan, rdunlap, mchehab,
aleksandr.loktionov, bvanassche, tudor.ambarus, emmaonana18
On Wed, 14 Oct 2026 11:22:02 -0600, Jonathan Corbet <corbet@lwn.net> wrote:
>> Neither of these patches applies to docs-next...what did you base them
>> on?
>
> Hi Jon,
>
> I had mistakenly based both patches on mainline rather than docs-next.
> I have rebased both on top of docs-next and sent a v2 for each:
>
> - docs: kdoc: handle TRACE_EVENT_FN() family in tracepoint parser:
> https://lore.kernel.org/all/20261014223134.14772-1-emmaonana18@gmail.com/
>
> - docs: kdoc: strip DOMAIN_NS() wrapper in function prototypes:
> https://lore.kernel.org/all/20261014223437.16164-1-emmaonana18@gmail.com/
>
I just noticed another mistake on my part, because I prepared
the two v2 patches on separate independent branches off docs-next, both
patches add their regression test at the exact same location in
tools/unittests/test_kdoc_parser.py (line 444). Applying them sequentially will
cause a merge conflict
I didn't realize that patches modifying the exact same context in a file
should be stacked sequentially on a single branch as a patch series
rather than developed on separate branches.
Should I respin them as a 2-patch series against docs-next,
or would you prefer to resolve when applying?
Thanks,
Omokefe
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] docs: kdoc: strip DOMAIN_NS() wrapper in function prototypes
2026-10-15 0:53 ` Omokefe Emmanuel Onanaroghene
@ 2026-10-15 13:00 ` Jonathan Corbet
2026-10-15 16:44 ` [PATCH v3 0/2] docs: kdoc: fix TRACE_EVENT_FN and DOMAIN_NS parsing Omokefe Emmanuel Onanaroghene
0 siblings, 1 reply; 14+ messages in thread
From: Jonathan Corbet @ 2026-10-15 13:00 UTC (permalink / raw)
To: Omokefe Emmanuel Onanaroghene
Cc: linux-doc, linux-kernel, skhan, rdunlap, mchehab,
aleksandr.loktionov, bvanassche, tudor.ambarus, emmaonana18
Omokefe Emmanuel Onanaroghene <emmaonana18@gmail.com> writes:
> On Wed, 14 Oct 2026 11:22:02 -0600, Jonathan Corbet <corbet@lwn.net> wrote:
>>> Neither of these patches applies to docs-next...what did you base them
>>> on?
>>
>> Hi Jon,
>>
>> I had mistakenly based both patches on mainline rather than docs-next.
>> I have rebased both on top of docs-next and sent a v2 for each:
>>
>> - docs: kdoc: handle TRACE_EVENT_FN() family in tracepoint parser:
>> https://lore.kernel.org/all/20261014223134.14772-1-emmaonana18@gmail.com/
>>
>> - docs: kdoc: strip DOMAIN_NS() wrapper in function prototypes:
>> https://lore.kernel.org/all/20261014223437.16164-1-emmaonana18@gmail.com/
>>
>
> I just noticed another mistake on my part, because I prepared
> the two v2 patches on separate independent branches off docs-next, both
> patches add their regression test at the exact same location in
> tools/unittests/test_kdoc_parser.py (line 444). Applying them sequentially will
> cause a merge conflict
>
> I didn't realize that patches modifying the exact same context in a file
> should be stacked sequentially on a single branch as a patch series
> rather than developed on separate branches.
>
> Should I respin them as a 2-patch series against docs-next,
> or would you prefer to resolve when applying?
Redo them as a two-patch series if you could.
Thanks,
jon
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v3 0/2] docs: kdoc: fix TRACE_EVENT_FN and DOMAIN_NS parsing
2026-10-15 13:00 ` Jonathan Corbet
@ 2026-10-15 16:44 ` Omokefe Emmanuel Onanaroghene
2026-10-15 16:44 ` [PATCH v3 1/2] docs: kdoc: handle TRACE_EVENT_FN() family in tracepoint parser Omokefe Emmanuel Onanaroghene
2026-10-15 16:44 ` [PATCH v3 2/2] docs: kdoc: strip DOMAIN_NS() wrapper in function prototypes Omokefe Emmanuel Onanaroghene
0 siblings, 2 replies; 14+ messages in thread
From: Omokefe Emmanuel Onanaroghene @ 2026-10-15 16:44 UTC (permalink / raw)
To: Jonathan Corbet
Cc: linux-doc, linux-kernel, skhan, rdunlap, mchehab, paulmck, linusw,
Julia.Lawall, gary, rmk+kernel, hemanth.selam, emmaonana18
This series fixes two kernel-doc parsing failures where the
prototype was misidentified and parameters leaked into garbage:
- TRACE_EVENT_FN() family tracepoints (e.g. gpu_power_status)
- DOMAIN_NS() wrapped function names (e.g. iova_to_phys)
Rebased onto docs-next and stacked as a series per Jon's feedback
to avoid both tests landing at the same spot in
test_kdoc_parser.py.
Omokefe Emmanuel Onanaroghene (2):
docs: kdoc: handle TRACE_EVENT_FN() family in tracepoint parser
docs: kdoc: strip DOMAIN_NS() wrapper in function prototypes
tools/lib/python/kdoc/kdoc_parser.py | 18 +++++++++-
tools/lib/python/kdoc/xforms_lists.py | 6 ++++
tools/unittests/test_kdoc_parser.py | 50 +++++++++++++++++++++++++++
3 files changed, 73 insertions(+), 1 deletion(-)
--
2.43.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v3 1/2] docs: kdoc: handle TRACE_EVENT_FN() family in tracepoint parser
2026-10-15 16:44 ` [PATCH v3 0/2] docs: kdoc: fix TRACE_EVENT_FN and DOMAIN_NS parsing Omokefe Emmanuel Onanaroghene
@ 2026-10-15 16:44 ` Omokefe Emmanuel Onanaroghene
2026-10-15 17:06 ` Mauro Carvalho Chehab
2026-10-15 16:44 ` [PATCH v3 2/2] docs: kdoc: strip DOMAIN_NS() wrapper in function prototypes Omokefe Emmanuel Onanaroghene
1 sibling, 1 reply; 14+ messages in thread
From: Omokefe Emmanuel Onanaroghene @ 2026-10-15 16:44 UTC (permalink / raw)
To: Jonathan Corbet
Cc: linux-doc, linux-kernel, skhan, rdunlap, mchehab, paulmck, linusw,
Julia.Lawall, gary, rmk+kernel, hemanth.selam, emmaonana18
kernel-doc fails to parse tracepoint declarations that use
TRACE_EVENT_FN(), e.g. gpu_power_status:
drivers/gpu/drm/panthor/panthor_trace.h:28 ... Unrecognized
tracepoint format ...
... expecting prototype for gpu_power_status(). Prototype was for
TRACE_EVENT_FN() instead
tracepoint_munge() only matches TRACE_EVENT(), so the macro name is
kept as the prototype and the TP_PROTO() arguments leak into the
parameter list as garbage.
Match TRACE_EVENT_FN(), TRACE_EVENT_FN_COND(),
TRACE_EVENT_CONDITION() and TRACE_EVENT_SYSCALL() the same way as
TRACE_EVENT() and list them explicitly at the call site in
process_proto_function().
Add a regression test for the gpu_power_status declaration.
Signed-off-by: Omokefe Emmanuel Onanaroghene <emmaonana18@gmail.com>
---
tools/lib/python/kdoc/kdoc_parser.py | 18 +++++++++++++++++-
tools/unittests/test_kdoc_parser.py | 28 ++++++++++++++++++++++++++++
2 files changed, 45 insertions(+), 1 deletion(-)
diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py
index 80d4245acd17..a65bda3e81b9 100644
--- a/tools/lib/python/kdoc/kdoc_parser.py
+++ b/tools/lib/python/kdoc/kdoc_parser.py
@@ -1545,6 +1545,22 @@ class KernelDoc:
if r.search(proto):
tracepointname = r.group(1)
+ r = KernRe(r'TRACE_EVENT_FN\((.*?),')
+ if r.search(proto):
+ tracepointname = r.group(1)
+
+ r = KernRe(r'TRACE_EVENT_FN_COND\((.*?),')
+ if r.search(proto):
+ tracepointname = r.group(1)
+
+ r = KernRe(r'TRACE_EVENT_CONDITION\((.*?),')
+ if r.search(proto):
+ tracepointname = r.group(1)
+
+ r = KernRe(r'TRACE_EVENT_SYSCALL\((.*?),')
+ if r.search(proto):
+ tracepointname = r.group(1)
+
r = KernRe(r'DEFINE_SINGLE_EVENT\((.*?),')
if r.search(proto):
tracepointname = r.group(1)
@@ -1604,7 +1620,7 @@ class KernelDoc:
self.entry.prototype = self.syscall_munge(ln,
self.entry.prototype)
else:
- r = KernRe(r'TRACE_EVENT|DEFINE_EVENT|DEFINE_SINGLE_EVENT')
+ r = KernRe(r'TRACE_EVENT|TRACE_EVENT_FN|TRACE_EVENT_FN_COND|TRACE_EVENT_CONDITION|TRACE_EVENT_SYSCALL|DEFINE_EVENT|DEFINE_SINGLE_EVENT')
if r.search(self.entry.prototype):
self.entry.prototype = self.tracepoint_munge(ln,
self.entry.prototype)
diff --git a/tools/unittests/test_kdoc_parser.py b/tools/unittests/test_kdoc_parser.py
index 4baa78ca02b3..04dafae412e4 100755
--- a/tools/unittests/test_kdoc_parser.py
+++ b/tools/unittests/test_kdoc_parser.py
@@ -444,6 +444,34 @@ class TestContextLockStruct(GenerateKdocItem):
self.assertEqual(entries[0].name, "debugfs_cancellation")
self.assertEqual(entries[0].warnings, [])
+class TestTraceEventFn(GenerateKdocItem):
+ def test_trace_event_fn_declaration(self):
+ source = """
+ /**
+ * gpu_power_status - called when hardware turns on or off
+ * @dev: pointer to device
+ * @shader_bitmap: bitmap
+ */
+ TRACE_EVENT_FN(gpu_power_status,
+ TP_PROTO(const struct device *dev, u64 shader_bitmap),
+ TP_ARGS(dev, shader_bitmap),
+ TP_STRUCT__entry(__field(u64, shader_bitmap)),
+ TP_fast_assign(__entry->shader_bitmap = shader_bitmap;),
+ TP_printk("%s", __get_str(dev_name)),
+ my_register, my_unregister
+ );
+ """
+
+ kernel_doc = KernelDoc(self.config, "test.c", self.xforms)
+ patcher = patch('builtins.open', new_callable=mock_open,
+ read_data=dedent(source))
+ with patcher:
+ _, entries = kernel_doc.parse_kdoc()
+
+ self.assertEqual(len(entries), 1)
+ self.assertEqual(entries[0].name, "trace_gpu_power_status")
+ self.assertEqual(entries[0].warnings, [])
+
#
# Class and logic to create dynamic tests from YAML
#
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v3 2/2] docs: kdoc: strip DOMAIN_NS() wrapper in function prototypes
2026-10-15 16:44 ` [PATCH v3 0/2] docs: kdoc: fix TRACE_EVENT_FN and DOMAIN_NS parsing Omokefe Emmanuel Onanaroghene
2026-10-15 16:44 ` [PATCH v3 1/2] docs: kdoc: handle TRACE_EVENT_FN() family in tracepoint parser Omokefe Emmanuel Onanaroghene
@ 2026-10-15 16:44 ` Omokefe Emmanuel Onanaroghene
1 sibling, 0 replies; 14+ messages in thread
From: Omokefe Emmanuel Onanaroghene @ 2026-10-15 16:44 UTC (permalink / raw)
To: Jonathan Corbet
Cc: linux-doc, linux-kernel, skhan, rdunlap, mchehab, paulmck, linusw,
Julia.Lawall, gary, rmk+kernel, hemanth.selam, emmaonana18
kernel-doc fails to parse functions whose names are wrapped in the
DOMAIN_NS() namespace macro, e.g. in
drivers/iommu/generic_pt/iommu_pt.h:217:
... expecting prototype for iova_to_phys(). Prototype was for
DOMAIN_NS() instead
function_xforms is the designated place for unwrapping function-name
macros, but it has no entry for DOMAIN_NS(), so the macro name is kept
as the prototype and the real name leaks into the parameter list.
Add a transform expanding DOMAIN_NS(op) to op, following the existing
DEFINE_IDTENTRY_IRQ precedent.
Add a regression test for the wrapped iova_to_phys() declaration.
Signed-off-by: Omokefe Emmanuel Onanaroghene <emmaonana18@gmail.com>
---
tools/lib/python/kdoc/xforms_lists.py | 6 ++++++
tools/unittests/test_kdoc_parser.py | 22 ++++++++++++++++++++++
2 files changed, 28 insertions(+)
diff --git a/tools/lib/python/kdoc/xforms_lists.py b/tools/lib/python/kdoc/xforms_lists.py
index 15f6f21c7a9e..c9ce9bddebba 100644
--- a/tools/lib/python/kdoc/xforms_lists.py
+++ b/tools/lib/python/kdoc/xforms_lists.py
@@ -92,6 +92,12 @@ class CTransforms:
(CMatch("__diagnose_as"), ""),
(CMatch("DECL_BUCKET_PARAMS"), r"\1, \2"),
(CMatch("DEFINE_IDTENTRY_IRQ"), r"static void \1(struct pt_regs *regs, u32 vector)"),
+ #
+ # DOMAIN_NS() wraps a function name with a namespace prefix
+ # (see drivers/iommu/generic_pt/iommu_pt.h). Unwrap it so the
+ # real function name is parsed.
+ #
+ (CMatch("DOMAIN_NS"), r"\1"),
(CMatch("__cond_acquires"), ""),
(CMatch("__cond_releases"), ""),
(CMatch("__acquires"), ""),
diff --git a/tools/unittests/test_kdoc_parser.py b/tools/unittests/test_kdoc_parser.py
index 04dafae412e4..e4f44535d0dc 100755
--- a/tools/unittests/test_kdoc_parser.py
+++ b/tools/unittests/test_kdoc_parser.py
@@ -472,6 +472,28 @@ class TestTraceEventFn(GenerateKdocItem):
self.assertEqual(entries[0].name, "trace_gpu_power_status")
self.assertEqual(entries[0].warnings, [])
+class TestDomainNs(GenerateKdocItem):
+ def test_domain_ns_wrapped_function(self):
+ source = """
+ /**
+ * iova_to_phys() - Return the output address for the given IOVA
+ * @domain: Table to query
+ * @iova: IO virtual address to query
+ */
+ phys_addr_t DOMAIN_NS(iova_to_phys)(struct iommu_domain *domain,
+ dma_addr_t iova);
+ """
+
+ kernel_doc = KernelDoc(self.config, "test.c", self.xforms)
+ patcher = patch('builtins.open', new_callable=mock_open,
+ read_data=dedent(source))
+ with patcher:
+ _, entries = kernel_doc.parse_kdoc()
+
+ self.assertEqual(len(entries), 1)
+ self.assertEqual(entries[0].name, "iova_to_phys")
+ self.assertEqual(entries[0].warnings, [])
+
#
# Class and logic to create dynamic tests from YAML
#
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v3 1/2] docs: kdoc: handle TRACE_EVENT_FN() family in tracepoint parser
2026-10-15 16:44 ` [PATCH v3 1/2] docs: kdoc: handle TRACE_EVENT_FN() family in tracepoint parser Omokefe Emmanuel Onanaroghene
@ 2026-10-15 17:06 ` Mauro Carvalho Chehab
2026-10-16 20:43 ` [PATCH] " Omokefe Emmanuel Onanaroghene
0 siblings, 1 reply; 14+ messages in thread
From: Mauro Carvalho Chehab @ 2026-10-15 17:06 UTC (permalink / raw)
To: Omokefe Emmanuel Onanaroghene
Cc: Jonathan Corbet, linux-doc, linux-kernel, skhan, rdunlap, mchehab,
paulmck, linusw, Julia.Lawall, gary, rmk+kernel, hemanth.selam
On Thu, 15 Oct 2026 17:44:47 +0100
Omokefe Emmanuel Onanaroghene <emmaonana18@gmail.com> wrote:
> kernel-doc fails to parse tracepoint declarations that use
> TRACE_EVENT_FN(), e.g. gpu_power_status:
>
> drivers/gpu/drm/panthor/panthor_trace.h:28 ... Unrecognized
> tracepoint format ...
> ... expecting prototype for gpu_power_status(). Prototype was for
> TRACE_EVENT_FN() instead
>
> tracepoint_munge() only matches TRACE_EVENT(), so the macro name is
> kept as the prototype and the TP_PROTO() arguments leak into the
> parameter list as garbage.
>
> Match TRACE_EVENT_FN(), TRACE_EVENT_FN_COND(),
> TRACE_EVENT_CONDITION() and TRACE_EVENT_SYSCALL() the same way as
> TRACE_EVENT() and list them explicitly at the call site in
> process_proto_function().
>
> Add a regression test for the gpu_power_status declaration.
>
> Signed-off-by: Omokefe Emmanuel Onanaroghene <emmaonana18@gmail.com>
> ---
> tools/lib/python/kdoc/kdoc_parser.py | 18 +++++++++++++++++-
> tools/unittests/test_kdoc_parser.py | 28 ++++++++++++++++++++++++++++
> 2 files changed, 45 insertions(+), 1 deletion(-)
>
> diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py
> index 80d4245acd17..a65bda3e81b9 100644
> --- a/tools/lib/python/kdoc/kdoc_parser.py
> +++ b/tools/lib/python/kdoc/kdoc_parser.py
> @@ -1545,6 +1545,22 @@ class KernelDoc:
> if r.search(proto):
> tracepointname = r.group(1)
>
> + r = KernRe(r'TRACE_EVENT_FN\((.*?),')
> + if r.search(proto):
> + tracepointname = r.group(1)
> +
> + r = KernRe(r'TRACE_EVENT_FN_COND\((.*?),')
> + if r.search(proto):
> + tracepointname = r.group(1)
> +
> + r = KernRe(r'TRACE_EVENT_CONDITION\((.*?),')
> + if r.search(proto):
> + tracepointname = r.group(1)
> +
> + r = KernRe(r'TRACE_EVENT_SYSCALL\((.*?),')
> + if r.search(proto):
> + tracepointname = r.group(1)
> +
> r = KernRe(r'DEFINE_SINGLE_EVENT\((.*?),')
> if r.search(proto):
> tracepointname = r.group(1)
> @@ -1604,7 +1620,7 @@ class KernelDoc:
> self.entry.prototype = self.syscall_munge(ln,
> self.entry.prototype)
> else:
> - r = KernRe(r'TRACE_EVENT|DEFINE_EVENT|DEFINE_SINGLE_EVENT')
> + r = KernRe(r'TRACE_EVENT|TRACE_EVENT_FN|TRACE_EVENT_FN_COND|TRACE_EVENT_CONDITION|TRACE_EVENT_SYSCALL|DEFINE_EVENT|DEFINE_SINGLE_EVENT')
The best would be instead to move all of them to xforms_lists,
together with SYSCALL_DEFINE.
Regards,
Mauro
> if r.search(self.entry.prototype):
> self.entry.prototype = self.tracepoint_munge(ln,
> self.entry.prototype)
> diff --git a/tools/unittests/test_kdoc_parser.py b/tools/unittests/test_kdoc_parser.py
> index 4baa78ca02b3..04dafae412e4 100755
> --- a/tools/unittests/test_kdoc_parser.py
> +++ b/tools/unittests/test_kdoc_parser.py
> @@ -444,6 +444,34 @@ class TestContextLockStruct(GenerateKdocItem):
> self.assertEqual(entries[0].name, "debugfs_cancellation")
> self.assertEqual(entries[0].warnings, [])
>
> +class TestTraceEventFn(GenerateKdocItem):
> + def test_trace_event_fn_declaration(self):
> + source = """
> + /**
> + * gpu_power_status - called when hardware turns on or off
> + * @dev: pointer to device
> + * @shader_bitmap: bitmap
> + */
> + TRACE_EVENT_FN(gpu_power_status,
> + TP_PROTO(const struct device *dev, u64 shader_bitmap),
> + TP_ARGS(dev, shader_bitmap),
> + TP_STRUCT__entry(__field(u64, shader_bitmap)),
> + TP_fast_assign(__entry->shader_bitmap = shader_bitmap;),
> + TP_printk("%s", __get_str(dev_name)),
> + my_register, my_unregister
> + );
> + """
> +
> + kernel_doc = KernelDoc(self.config, "test.c", self.xforms)
> + patcher = patch('builtins.open', new_callable=mock_open,
> + read_data=dedent(source))
> + with patcher:
> + _, entries = kernel_doc.parse_kdoc()
> +
> + self.assertEqual(len(entries), 1)
> + self.assertEqual(entries[0].name, "trace_gpu_power_status")
> + self.assertEqual(entries[0].warnings, [])
> +
> #
> # Class and logic to create dynamic tests from YAML
> #
Thanks,
Mauro
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH] docs: kdoc: handle TRACE_EVENT_FN() family in tracepoint parser
2026-10-15 17:06 ` Mauro Carvalho Chehab
@ 2026-10-16 20:43 ` Omokefe Emmanuel Onanaroghene
2026-10-16 21:11 ` Mauro Carvalho Chehab
0 siblings, 1 reply; 14+ messages in thread
From: Omokefe Emmanuel Onanaroghene @ 2026-10-16 20:43 UTC (permalink / raw)
To: Mauro Carvalho Chehab, Jonathan Corbet, linux-doc
Cc: linux-kernel, skhan, rdunlap, mchehab, paulmck, linusw,
Julia.Lawall, gary, rmk+kernel, hemanth.selam,
Omokefe Emmanuel Onanaroghene
kernel-doc fails to parse tracepoint declarations that use
TRACE_EVENT_FN(), e.g. gpu_power_status:
drivers/gpu/drm/panthor/panthor_trace.h:28 ... Unrecognized
tracepoint format ...
... expecting prototype for gpu_power_status(). Prototype was for
TRACE_EVENT_FN() instead
tracepoint_munge() only matches TRACE_EVENT(), so the macro name is
kept as the prototype and the TP_PROTO() arguments leak into the
parameter list as garbage.
Match TRACE_EVENT_FN(), TRACE_EVENT_FN_COND(),
TRACE_EVENT_CONDITION() and TRACE_EVENT_SYSCALL() the same way as
TRACE_EVENT()
Add a regression test for the gpu_power_status declaration.
Signed-off-by: Omokefe Emmanuel Onanaroghene <emmaonana18@gmail.com>
---
Move tracepoint handling to xforms_lists, together with SYSCALL_DEFINE
as requested by Mauro.
Question for Mauro: is adding syscall_munge() and
tracepoint_munge() in apply() what you meant, or
did you want a pure CMatch? A pure CMatch looks
like it would need a tokenizer fix for nested
commas, so I'd prefer to keep it this way unless
you want the pure CMatch rework.
tools/lib/python/kdoc/kdoc_parser.py | 110 ++++++--------------------
tools/lib/python/kdoc/xforms_lists.py | 109 +++++++++++++++++++++++++
tools/unittests/test_kdoc_parser.py | 28 +++++++
3 files changed, 159 insertions(+), 88 deletions(-)
diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py
index 80d4245acd17..a274e06b9f23 100644
--- a/tools/lib/python/kdoc/kdoc_parser.py
+++ b/tools/lib/python/kdoc/kdoc_parser.py
@@ -1059,8 +1059,27 @@ class KernelDoc:
#
# Apply the initial transformations.
#
+ # This also handles SYSCALL_DEFINE*() and TRACE_EVENT*()/
+ # DEFINE_EVENT*() via CTransforms (see xforms_lists.py).
+ #
prototype = self.xforms.apply("func", prototype)
+ #
+ # Tracepoints are documented with their short name, e.g.
+ # gpu_power_status for trace_gpu_power_status().
+ # Accept the short name and store the full trace_ name.
+ #
+ r = KernRe(r'\btrace_(\w+)')
+ if r.search(prototype):
+ if self.entry.identifier == r.group(1):
+ self.entry.identifier = f"trace_{self.entry.identifier}"
+
+
+ r = KernRe(r'TRACE_EVENT|DEFINE_EVENT|DEFINE_SINGLE_EVENT')
+ if r.search(prototype):
+ self.emit_msg(ln,
+ f"Unrecognized tracepoint format:\n{prototype}\n")
+
# Yes, this truly is vile. We are looking for:
# 1. Return type (may be nothing if we're looking at a macro)
# 2. Function name
@@ -1493,82 +1512,6 @@ class KernelDoc:
self.entry.add_text(doc_content.group(1))
# else ... ??
- def syscall_munge(self, ln, proto): # pylint: disable=W0613
- """
- Handle syscall definitions.
- """
-
- is_void = False
-
- # Strip newlines/CR's
- proto = re.sub(r'[\r\n]+', ' ', proto)
-
- # Check if it's a SYSCALL_DEFINE0
- if 'SYSCALL_DEFINE0' in proto:
- is_void = True
-
- # Replace SYSCALL_DEFINE with correct return type & function name
- proto = KernRe(r'SYSCALL_DEFINE.*\(').sub('long sys_', proto)
-
- r = KernRe(r'long\s+(sys_.*?),')
- if r.search(proto):
- proto = KernRe(',').sub('(', proto, count=1)
- elif is_void:
- proto = KernRe(r'\)').sub('(void)', proto, count=1)
-
- # Now delete all of the odd-numbered commas in the proto
- # so that argument types & names don't have a comma between them
- count = 0
- length = len(proto)
-
- if is_void:
- length = 0 # skip the loop if is_void
-
- for ix in range(length):
- if proto[ix] == ',':
- count += 1
- if count % 2 == 1:
- proto = proto[:ix] + ' ' + proto[ix + 1:]
-
- return proto
-
- def tracepoint_munge(self, ln, proto):
- """
- Handle tracepoint definitions.
- """
-
- tracepointname = None
- tracepointargs = None
-
- # Match tracepoint name based on different patterns
- r = KernRe(r'TRACE_EVENT\((.*?),')
- if r.search(proto):
- tracepointname = r.group(1)
-
- r = KernRe(r'DEFINE_SINGLE_EVENT\((.*?),')
- if r.search(proto):
- tracepointname = r.group(1)
-
- r = KernRe(r'DEFINE_EVENT\((.*?),(.*?),')
- if r.search(proto):
- tracepointname = r.group(2)
-
- if tracepointname:
- tracepointname = tracepointname.lstrip()
-
- r = KernRe(r'TP_PROTO\((.*?)\)')
- if r.search(proto):
- tracepointargs = r.group(1)
-
- if not tracepointname or not tracepointargs:
- self.emit_msg(ln,
- f"Unrecognized tracepoint format:\n{proto}\n")
- else:
- proto = f"static inline void trace_{tracepointname}({tracepointargs})"
- self.entry.identifier = f"trace_{self.entry.identifier}"
-
- return proto
-
def process_proto_function(self, ln, line, source):
"""Ancillary routine to process a function prototype."""
@@ -1598,18 +1541,9 @@ class KernelDoc:
r = KernRe(r'^(\S+\s+)\(\s*\*(\S+)\)')
self.entry.prototype = r.sub(r'\1\2', self.entry.prototype)
#
- # Handle special declaration syntaxes
- #
- if 'SYSCALL_DEFINE' in self.entry.prototype:
- self.entry.prototype = self.syscall_munge(ln,
- self.entry.prototype)
- else:
- r = KernRe(r'TRACE_EVENT|DEFINE_EVENT|DEFINE_SINGLE_EVENT')
- if r.search(self.entry.prototype):
- self.entry.prototype = self.tracepoint_munge(ln,
- self.entry.prototype)
- #
- # ... and we're done
+ # ... and we're done. SYSCALL_DEFINE*() and TRACE_EVENT*()/
+ # DEFINE_EVENT*() are handled via xforms_lists.CTransforms
+ # inside dump_function().
#
self.dump_function(ln, self.entry.prototype, source)
self.reset_state(ln)
diff --git a/tools/lib/python/kdoc/xforms_lists.py b/tools/lib/python/kdoc/xforms_lists.py
index 15f6f21c7a9e..aa82dc927ef1 100644
--- a/tools/lib/python/kdoc/xforms_lists.py
+++ b/tools/lib/python/kdoc/xforms_lists.py
@@ -17,6 +17,98 @@ class CTransforms:
into something we can parse and generate kdoc for.
"""
+ @staticmethod
+ def syscall_munge(proto):
+ """
+ Handle syscall definitions.
+
+ Turns SYSCALL_DEFINE*() into a plain C prototype, e.g.::
+
+ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval)
+ -> long sys_setpriority(int which, int who, int niceval)
+ """
+
+ is_void = False
+
+ # Strip newlines/CR's
+ proto = re.sub(r'[\r\n]+', ' ', proto)
+
+ # Check if it's a SYSCALL_DEFINE0
+ if 'SYSCALL_DEFINE0' in proto:
+ is_void = True
+
+ # Replace SYSCALL_DEFINE with correct return type & function name
+ proto = KernRe(r'SYSCALL_DEFINE.*\(').sub('long sys_', proto)
+
+ r = KernRe(r'long\s+(sys_.*?),')
+ if r.search(proto):
+ proto = KernRe(',').sub('(', proto, count=1)
+ elif is_void:
+ proto = KernRe(r'\)').sub('(void)', proto, count=1)
+
+ # Now delete all of the odd-numbered commas in the proto
+ # so that argument types & names don't have a comma between them
+ count = 0
+ length = len(proto)
+
+ if is_void:
+ length = 0 # skip the loop if is_void
+
+ for ix in range(length):
+ if proto[ix] == ',':
+ count += 1
+ if count % 2 == 1:
+ proto = proto[:ix] + ' ' + proto[ix + 1:]
+
+ return proto
+
+ @staticmethod
+ def tracepoint_munge(proto):
+ """
+ Handle tracepoint definitions.
+
+ Turns TRACE_EVENT*()/DEFINE_EVENT*() into a plain C prototype,
+ e.g.::
+
+ TRACE_EVENT_FN(gpu_power_status, TP_PROTO(...), ...)
+ -> static inline void trace_gpu_power_status(...)
+
+ Returns the original string if the tracepoint format is not
+ recognized, letting the caller emit a warning.
+ """
+
+ tracepointname = None
+ tracepointargs = None
+
+ # Match tracepoint name based on different patterns.
+ # NOTE: DEFINE_EVENT*() takes a template name first, so the
+ # event name is the second argument.
+ for pattern, group in [
+ (r'TRACE_EVENT\((.*?),', 1),
+ (r'TRACE_EVENT_FN\((.*?),', 1),
+ (r'TRACE_EVENT_FN_COND\((.*?),', 1),
+ (r'TRACE_EVENT_CONDITION\((.*?),', 1),
+ (r'TRACE_EVENT_SYSCALL\((.*?),', 1),
+ (r'DEFINE_SINGLE_EVENT\((.*?),', 1),
+ (r'DEFINE_EVENT\((.*?),(.*?),', 2),
+ ]:
+ r = KernRe(pattern)
+ if r.search(proto):
+ tracepointname = r.group(group)
+
+ if tracepointname:
+ tracepointname = tracepointname.lstrip()
+
+ r = KernRe(r'TP_PROTO\((.*?)\)')
+ if r.search(proto):
+ tracepointargs = r.group(1)
+
+ if not tracepointname or not tracepointargs:
+ return proto
+
+ return f"static inline void trace_{tracepointname}({tracepointargs})"
+
+
#
# NOTE:
# Due to performance reasons, place CMatch rules before KernRe,
@@ -147,6 +239,23 @@ class CTransforms:
if xforms_type not in self.xforms:
return source
+ #
+ # Handle special declaration syntaxes first, so that the
+ # declarative transforms below see plain C prototypes.
+ #
+ if xforms_type == "func":
+ source_str = str(source)
+ if 'SYSCALL_DEFINE' in source_str:
+ source_str = self.syscall_munge(source_str)
+ source = source_str
+ else:
+ r = KernRe(r'TRACE_EVENT|DEFINE_EVENT|DEFINE_SINGLE_EVENT')
+ if r.search(source_str):
+ munged = self.tracepoint_munge(source_str)
+ # tracepoint_munge() returns the input unchanged
+ # when the format is not recognized.
+ source = munged
+
if isinstance(source, str):
source = CTokenizer(source)
diff --git a/tools/unittests/test_kdoc_parser.py b/tools/unittests/test_kdoc_parser.py
index 4baa78ca02b3..04dafae412e4 100755
--- a/tools/unittests/test_kdoc_parser.py
+++ b/tools/unittests/test_kdoc_parser.py
@@ -444,6 +444,34 @@ class TestContextLockStruct(GenerateKdocItem):
self.assertEqual(entries[0].name, "debugfs_cancellation")
self.assertEqual(entries[0].warnings, [])
+class TestTraceEventFn(GenerateKdocItem):
+ def test_trace_event_fn_declaration(self):
+ source = """
+ /**
+ * gpu_power_status - called when hardware turns on or off
+ * @dev: pointer to device
+ * @shader_bitmap: bitmap
+ */
+ TRACE_EVENT_FN(gpu_power_status,
+ TP_PROTO(const struct device *dev, u64 shader_bitmap),
+ TP_ARGS(dev, shader_bitmap),
+ TP_STRUCT__entry(__field(u64, shader_bitmap)),
+ TP_fast_assign(__entry->shader_bitmap = shader_bitmap;),
+ TP_printk("%s", __get_str(dev_name)),
+ my_register, my_unregister
+ );
+ """
+
+ kernel_doc = KernelDoc(self.config, "test.c", self.xforms)
+ patcher = patch('builtins.open', new_callable=mock_open,
+ read_data=dedent(source))
+ with patcher:
+ _, entries = kernel_doc.parse_kdoc()
+
+ self.assertEqual(len(entries), 1)
+ self.assertEqual(entries[0].name, "trace_gpu_power_status")
+ self.assertEqual(entries[0].warnings, [])
+
#
# Class and logic to create dynamic tests from YAML
#
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH] docs: kdoc: handle TRACE_EVENT_FN() family in tracepoint parser
2026-10-16 20:43 ` [PATCH] " Omokefe Emmanuel Onanaroghene
@ 2026-10-16 21:11 ` Mauro Carvalho Chehab
0 siblings, 0 replies; 14+ messages in thread
From: Mauro Carvalho Chehab @ 2026-10-16 21:11 UTC (permalink / raw)
To: Omokefe Emmanuel Onanaroghene
Cc: Jonathan Corbet, linux-doc, linux-kernel, skhan, rdunlap, mchehab,
paulmck, linusw, Julia.Lawall, gary, rmk+kernel, hemanth.selam
On Fri, 16 Oct 2026 21:43:35 +0100
Omokefe Emmanuel Onanaroghene <emmaonana18@gmail.com> wrote:
> kernel-doc fails to parse tracepoint declarations that use
> TRACE_EVENT_FN(), e.g. gpu_power_status:
>
> drivers/gpu/drm/panthor/panthor_trace.h:28 ... Unrecognized
> tracepoint format ...
> ... expecting prototype for gpu_power_status(). Prototype was for
> TRACE_EVENT_FN() instead
>
> tracepoint_munge() only matches TRACE_EVENT(), so the macro name is
> kept as the prototype and the TP_PROTO() arguments leak into the
> parameter list as garbage.
>
> Match TRACE_EVENT_FN(), TRACE_EVENT_FN_COND(),
> TRACE_EVENT_CONDITION() and TRACE_EVENT_SYSCALL() the same way as
> TRACE_EVENT()
>
> Add a regression test for the gpu_power_status declaration.
>
> Signed-off-by: Omokefe Emmanuel Onanaroghene <emmaonana18@gmail.com>
> ---
> Move tracepoint handling to xforms_lists, together with SYSCALL_DEFINE
> as requested by Mauro.
>
> Question for Mauro: is adding syscall_munge() and
> tracepoint_munge() in apply() what you meant, or
> did you want a pure CMatch?
I meant a pure CMatch. One of the hardest things to maintain at
kernel-doc are those complex regex logic spread all over it. The
goal for CMatch and the C tokenizer is to avoid adding more - and
instead - to reduce the existing ones over time.
In the specific case of commas, the tokenizer, ideally double commas
should be generating a singe STRING token and single commas a single
CHAR.
> A pure CMatch looks
> like it would need a tokenizer fix for nested
> commas, so I'd prefer to keep it this way unless
> you want the pure CMatch rework.
If the nested commas logic there is broken, indeed it needs a fix, on a
separate patch.
>
> tools/lib/python/kdoc/kdoc_parser.py | 110 ++++++--------------------
> tools/lib/python/kdoc/xforms_lists.py | 109 +++++++++++++++++++++++++
> tools/unittests/test_kdoc_parser.py | 28 +++++++
> 3 files changed, 159 insertions(+), 88 deletions(-)
>
> diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py
> index 80d4245acd17..a274e06b9f23 100644
> --- a/tools/lib/python/kdoc/kdoc_parser.py
> +++ b/tools/lib/python/kdoc/kdoc_parser.py
> @@ -1059,8 +1059,27 @@ class KernelDoc:
> #
> # Apply the initial transformations.
> #
> + # This also handles SYSCALL_DEFINE*() and TRACE_EVENT*()/
> + # DEFINE_EVENT*() via CTransforms (see xforms_lists.py).
> + #
> prototype = self.xforms.apply("func", prototype)
>
> + #
> + # Tracepoints are documented with their short name, e.g.
> + # gpu_power_status for trace_gpu_power_status().
> + # Accept the short name and store the full trace_ name.
> + #
> + r = KernRe(r'\btrace_(\w+)')
> + if r.search(prototype):
> + if self.entry.identifier == r.group(1):
> + self.entry.identifier = f"trace_{self.entry.identifier}"
> +
> +
> + r = KernRe(r'TRACE_EVENT|DEFINE_EVENT|DEFINE_SINGLE_EVENT')
> + if r.search(prototype):
> + self.emit_msg(ln,
> + f"Unrecognized tracepoint format:\n{prototype}\n")
> +
> # Yes, this truly is vile. We are looking for:
> # 1. Return type (may be nothing if we're looking at a macro)
> # 2. Function name
> @@ -1493,82 +1512,6 @@ class KernelDoc:
> self.entry.add_text(doc_content.group(1))
> # else ... ??
>
> - def syscall_munge(self, ln, proto): # pylint: disable=W0613
> - """
> - Handle syscall definitions.
> - """
> -
> - is_void = False
> -
> - # Strip newlines/CR's
> - proto = re.sub(r'[\r\n]+', ' ', proto)
> -
> - # Check if it's a SYSCALL_DEFINE0
> - if 'SYSCALL_DEFINE0' in proto:
> - is_void = True
> -
> - # Replace SYSCALL_DEFINE with correct return type & function name
> - proto = KernRe(r'SYSCALL_DEFINE.*\(').sub('long sys_', proto)
> -
> - r = KernRe(r'long\s+(sys_.*?),')
> - if r.search(proto):
> - proto = KernRe(',').sub('(', proto, count=1)
> - elif is_void:
> - proto = KernRe(r'\)').sub('(void)', proto, count=1)
> -
> - # Now delete all of the odd-numbered commas in the proto
> - # so that argument types & names don't have a comma between them
> - count = 0
> - length = len(proto)
> -
> - if is_void:
> - length = 0 # skip the loop if is_void
> -
> - for ix in range(length):
> - if proto[ix] == ',':
> - count += 1
> - if count % 2 == 1:
> - proto = proto[:ix] + ' ' + proto[ix + 1:]
> -
> - return proto
> -
> - def tracepoint_munge(self, ln, proto):
> - """
> - Handle tracepoint definitions.
> - """
> -
> - tracepointname = None
> - tracepointargs = None
> -
> - # Match tracepoint name based on different patterns
> - r = KernRe(r'TRACE_EVENT\((.*?),')
> - if r.search(proto):
> - tracepointname = r.group(1)
> -
> - r = KernRe(r'DEFINE_SINGLE_EVENT\((.*?),')
> - if r.search(proto):
> - tracepointname = r.group(1)
> -
> - r = KernRe(r'DEFINE_EVENT\((.*?),(.*?),')
> - if r.search(proto):
> - tracepointname = r.group(2)
> -
> - if tracepointname:
> - tracepointname = tracepointname.lstrip()
> -
> - r = KernRe(r'TP_PROTO\((.*?)\)')
> - if r.search(proto):
> - tracepointargs = r.group(1)
> -
> - if not tracepointname or not tracepointargs:
> - self.emit_msg(ln,
> - f"Unrecognized tracepoint format:\n{proto}\n")
> - else:
> - proto = f"static inline void trace_{tracepointname}({tracepointargs})"
> - self.entry.identifier = f"trace_{self.entry.identifier}"
> -
> - return proto
> -
> def process_proto_function(self, ln, line, source):
> """Ancillary routine to process a function prototype."""
>
> @@ -1598,18 +1541,9 @@ class KernelDoc:
> r = KernRe(r'^(\S+\s+)\(\s*\*(\S+)\)')
> self.entry.prototype = r.sub(r'\1\2', self.entry.prototype)
> #
> - # Handle special declaration syntaxes
> - #
> - if 'SYSCALL_DEFINE' in self.entry.prototype:
> - self.entry.prototype = self.syscall_munge(ln,
> - self.entry.prototype)
> - else:
> - r = KernRe(r'TRACE_EVENT|DEFINE_EVENT|DEFINE_SINGLE_EVENT')
> - if r.search(self.entry.prototype):
> - self.entry.prototype = self.tracepoint_munge(ln,
> - self.entry.prototype)
> - #
> - # ... and we're done
> + # ... and we're done. SYSCALL_DEFINE*() and TRACE_EVENT*()/
> + # DEFINE_EVENT*() are handled via xforms_lists.CTransforms
> + # inside dump_function().
> #
> self.dump_function(ln, self.entry.prototype, source)
> self.reset_state(ln)
> diff --git a/tools/lib/python/kdoc/xforms_lists.py b/tools/lib/python/kdoc/xforms_lists.py
> index 15f6f21c7a9e..aa82dc927ef1 100644
> --- a/tools/lib/python/kdoc/xforms_lists.py
> +++ b/tools/lib/python/kdoc/xforms_lists.py
> @@ -17,6 +17,98 @@ class CTransforms:
> into something we can parse and generate kdoc for.
> """
>
> + @staticmethod
> + def syscall_munge(proto):
> + """
> + Handle syscall definitions.
> +
> + Turns SYSCALL_DEFINE*() into a plain C prototype, e.g.::
> +
> + SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval)
> + -> long sys_setpriority(int which, int who, int niceval)
> + """
> +
> + is_void = False
> +
> + # Strip newlines/CR's
> + proto = re.sub(r'[\r\n]+', ' ', proto)
> +
> + # Check if it's a SYSCALL_DEFINE0
> + if 'SYSCALL_DEFINE0' in proto:
> + is_void = True
> +
> + # Replace SYSCALL_DEFINE with correct return type & function name
> + proto = KernRe(r'SYSCALL_DEFINE.*\(').sub('long sys_', proto)
> +
> + r = KernRe(r'long\s+(sys_.*?),')
> + if r.search(proto):
> + proto = KernRe(',').sub('(', proto, count=1)
> + elif is_void:
> + proto = KernRe(r'\)').sub('(void)', proto, count=1)
> +
> + # Now delete all of the odd-numbered commas in the proto
> + # so that argument types & names don't have a comma between them
> + count = 0
> + length = len(proto)
> +
> + if is_void:
> + length = 0 # skip the loop if is_void
> +
> + for ix in range(length):
> + if proto[ix] == ',':
> + count += 1
> + if count % 2 == 1:
> + proto = proto[:ix] + ' ' + proto[ix + 1:]
> +
> + return proto
> +
> + @staticmethod
> + def tracepoint_munge(proto):
> + """
> + Handle tracepoint definitions.
> +
> + Turns TRACE_EVENT*()/DEFINE_EVENT*() into a plain C prototype,
> + e.g.::
> +
> + TRACE_EVENT_FN(gpu_power_status, TP_PROTO(...), ...)
> + -> static inline void trace_gpu_power_status(...)
> +
> + Returns the original string if the tracepoint format is not
> + recognized, letting the caller emit a warning.
> + """
> +
> + tracepointname = None
> + tracepointargs = None
> +
> + # Match tracepoint name based on different patterns.
> + # NOTE: DEFINE_EVENT*() takes a template name first, so the
> + # event name is the second argument.
> + for pattern, group in [
> + (r'TRACE_EVENT\((.*?),', 1),
> + (r'TRACE_EVENT_FN\((.*?),', 1),
> + (r'TRACE_EVENT_FN_COND\((.*?),', 1),
> + (r'TRACE_EVENT_CONDITION\((.*?),', 1),
> + (r'TRACE_EVENT_SYSCALL\((.*?),', 1),
> + (r'DEFINE_SINGLE_EVENT\((.*?),', 1),
> + (r'DEFINE_EVENT\((.*?),(.*?),', 2),
> + ]:
> + r = KernRe(pattern)
> + if r.search(proto):
> + tracepointname = r.group(group)
> +
> + if tracepointname:
> + tracepointname = tracepointname.lstrip()
> +
> + r = KernRe(r'TP_PROTO\((.*?)\)')
> + if r.search(proto):
> + tracepointargs = r.group(1)
> +
> + if not tracepointname or not tracepointargs:
> + return proto
> +
> + return f"static inline void trace_{tracepointname}({tracepointargs})"
> +
> +
> #
> # NOTE:
> # Due to performance reasons, place CMatch rules before KernRe,
> @@ -147,6 +239,23 @@ class CTransforms:
> if xforms_type not in self.xforms:
> return source
>
> + #
> + # Handle special declaration syntaxes first, so that the
> + # declarative transforms below see plain C prototypes.
> + #
> + if xforms_type == "func":
> + source_str = str(source)
> + if 'SYSCALL_DEFINE' in source_str:
> + source_str = self.syscall_munge(source_str)
> + source = source_str
> + else:
> + r = KernRe(r'TRACE_EVENT|DEFINE_EVENT|DEFINE_SINGLE_EVENT')
> + if r.search(source_str):
> + munged = self.tracepoint_munge(source_str)
> + # tracepoint_munge() returns the input unchanged
> + # when the format is not recognized.
> + source = munged
> +
> if isinstance(source, str):
> source = CTokenizer(source)
>
> diff --git a/tools/unittests/test_kdoc_parser.py b/tools/unittests/test_kdoc_parser.py
> index 4baa78ca02b3..04dafae412e4 100755
> --- a/tools/unittests/test_kdoc_parser.py
> +++ b/tools/unittests/test_kdoc_parser.py
> @@ -444,6 +444,34 @@ class TestContextLockStruct(GenerateKdocItem):
> self.assertEqual(entries[0].name, "debugfs_cancellation")
> self.assertEqual(entries[0].warnings, [])
>
> +class TestTraceEventFn(GenerateKdocItem):
> + def test_trace_event_fn_declaration(self):
> + source = """
> + /**
> + * gpu_power_status - called when hardware turns on or off
> + * @dev: pointer to device
> + * @shader_bitmap: bitmap
> + */
> + TRACE_EVENT_FN(gpu_power_status,
> + TP_PROTO(const struct device *dev, u64 shader_bitmap),
> + TP_ARGS(dev, shader_bitmap),
> + TP_STRUCT__entry(__field(u64, shader_bitmap)),
> + TP_fast_assign(__entry->shader_bitmap = shader_bitmap;),
> + TP_printk("%s", __get_str(dev_name)),
> + my_register, my_unregister
> + );
> + """
> +
> + kernel_doc = KernelDoc(self.config, "test.c", self.xforms)
> + patcher = patch('builtins.open', new_callable=mock_open,
> + read_data=dedent(source))
> + with patcher:
> + _, entries = kernel_doc.parse_kdoc()
> +
> + self.assertEqual(len(entries), 1)
> + self.assertEqual(entries[0].name, "trace_gpu_power_status")
> + self.assertEqual(entries[0].warnings, [])
> +
> #
> # Class and logic to create dynamic tests from YAML
> #
Thanks,
Mauro
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2026-10-16 21:11 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-02 4:15 [PATCH] docs: kdoc: strip DOMAIN_NS() wrapper in function prototypes Omokefe Emmanuel Onanaroghene
2026-10-02 4:28 ` Randy Dunlap
2026-10-14 17:22 ` Jonathan Corbet
2026-10-14 22:47 ` Omokefe Emmanuel Onanaroghene
2026-10-15 0:53 ` Omokefe Emmanuel Onanaroghene
2026-10-15 13:00 ` Jonathan Corbet
2026-10-15 16:44 ` [PATCH v3 0/2] docs: kdoc: fix TRACE_EVENT_FN and DOMAIN_NS parsing Omokefe Emmanuel Onanaroghene
2026-10-15 16:44 ` [PATCH v3 1/2] docs: kdoc: handle TRACE_EVENT_FN() family in tracepoint parser Omokefe Emmanuel Onanaroghene
2026-10-15 17:06 ` Mauro Carvalho Chehab
2026-10-16 20:43 ` [PATCH] " Omokefe Emmanuel Onanaroghene
2026-10-16 21:11 ` Mauro Carvalho Chehab
2026-10-15 16:44 ` [PATCH v3 2/2] docs: kdoc: strip DOMAIN_NS() wrapper in function prototypes Omokefe Emmanuel Onanaroghene
-- strict thread matches above, loose matches on Subject: below --
2026-10-02 2:34 [PATCH] docs: kdoc: handle TRACE_EVENT_FN() family in tracepoint parser Omokefe Emmanuel Onanaroghene
2026-10-02 4:21 ` Randy Dunlap
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.