Skip to contentSkip to conversation

kernel-doc: add support for documenting vars

PATCH Superseded Mauro Carvalho Chehab 3 participants 10 messages Nov 16, 2025 – Nov 21, 2025

Subsystems (2)

v3 of 7 Superseded Latest is v7 →

lore
Share & tools
lore
#0 lore raw

v3 cover kernel-doc: add support for documenting vars

Hi Jon,

As suggested and discussed with Randy, this small series add support for documenting variables using kernel-doc.

The first patch adds support for it.
The second one documents two variables from media.

While two documented variables are part of kAPI, I'm documenting them mostly aiming to test the new feature, as those are meant to be used for debugging messages, so we could live without having them documented.

I'm pretty sure we'll likely need to improve the parser regexes to catch everything. For instance, I had to add a logic on v3 due to the choice I did for the vars, which are pointers.

Mauro Carvalho Chehab (2):
kernel-doc: add support for handling global variables
docs: media: v4l2-ioctl.h: document two global variables

 include/media/v4l2-ioctl.h      | 15 +++++++++
 scripts/lib/kdoc/kdoc_output.py | 45 ++++++++++++++++++++++++++
 scripts/lib/kdoc/kdoc_parser.py | 56 ++++++++++++++++++++++++++++++++-
 3 files changed, 115 insertions(+), 1 deletion(-)
Signature · 1 line
2.51.1
#1 lore raw

PATCH v3 1/2 kernel-doc: add support for handling global variables

Specially on kAPI, sometimes it is desirable to be able to describe global variables that are part of kAPI.

Documenting vars with Sphinx is simple, as we don't need to parse a data struct. All we need is the variable declaration and use natice C domain ::c:var: to format it for us.

Add support for it.

---
 scripts/lib/kdoc/kdoc_output.py | 45 ++++++++++++++++++++++++++
 scripts/lib/kdoc/kdoc_parser.py | 56 ++++++++++++++++++++++++++++++++-
 2 files changed, 100 insertions(+), 1 deletion(-)
scripts/lib/kdoc/kdoc_output.py +45 -0
index 58f115059e93..1d97a3f2c738 100644
@@ -199,6 +199,10 @@ class OutputFormat:
             self.out_enum(fname, name, args)
             return self.data
 
+        if dtype == "var":
+            self.out_var(fname, name, args)
+            return self.data
+
         if dtype == "typedef":
             self.out_typedef(fname, name, args)
             return self.data
@@ -227,6 +231,9 @@ class OutputFormat:
     def out_enum(self, fname, name, args):
         """Outputs an enum"""
 
+    def out_var(self, fname, name, args):
+        """Outputs a variable"""
+
     def out_typedef(self, fname, name, args):
         """Outputs a typedef"""
 
@@ -472,6 +479,24 @@ class RestFormat(OutputFormat):
         self.lineprefix = oldprefix
         self.out_section(args)
 
+    def out_var(self, fname, name, args):
+        oldprefix = self.lineprefix
+        ln = args.declaration_start_line
+        prototype = args.other_stuff["var_type"]
+
+        self.data += f"\n\n.. c:var:: {prototype}\n\n"
+
+        self.print_lineno(ln)
+        self.lineprefix = "  "
+        self.output_highlight(args.get('purpose', ''))
+        self.data += "\n"
+
+        if args.other_stuff["default_val"]:
+            self.data += f'{self.lineprefix}**Initialization**\n\n'
+            self.output_highlight(f'default: ``{args.other_stuff["default_val"]}``')
+
+        self.out_section(args)
+
     def out_typedef(self, fname, name, args):
 
         oldprefix = self.lineprefix
@@ -773,6 +798,26 @@ class ManFormat(OutputFormat):
             self.data += f'.SH "{section}"' + "\n"
             self.output_highlight(text)
 
+    def out_var(self, fname, name, args):
+        out_name = self.arg_name(args, name)
+        prototype = args.other_stuff["var_type"]
+
+        self.data += f'.TH "{self.modulename}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "\n"
+
+        self.data += ".SH NAME\n"
+        self.data += f"{prototype} \\- {args['purpose']}\n"
+
+        self.data += ".SH SYNOPSIS\n"
+        self.data += f"{prototype};\n"
+
+        if args.other_stuff["default_val"]:
+            self.data += f'.SH "Initialization"' + "\n"
+            self.output_highlight(f'default: {args.other_stuff["default_val"]}')
+
+        for section, text in args.sections.items():
+            self.data += f'.SH "{section}"' + "\n"
+            self.output_highlight(text)
+
     def out_typedef(self, fname, name, args):
         module = self.modulename
         purpose = args.get('purpose')
scripts/lib/kdoc/kdoc_parser.py +55 -1

74 lines not on this page · raw message

Signature · 1 line
2.51.1
reviewer
#2 lore raw

Re: [PATCH v3 1/2] kernel-doc: add support for handling global variables

Hi,

Quoted 10 lines · Mauro Carvalho Chehab

Specially on kAPI, sometimes it is desirable to be able to describe global variables that are part of kAPI.

Documenting vars with Sphinx is simple, as we don't need to parse a data struct. All we need is the variable declaration and use natice C domain ::c:var: to format it for us.

Add support for it.

Quoted 7 lines
---
 scripts/lib/kdoc/kdoc_output.py | 45 ++++++++++++++++++++++++++
 scripts/lib/kdoc/kdoc_parser.py | 56 ++++++++++++++++++++++++++++++++-
 2 files changed, 100 insertions(+), 1 deletion(-)

Thanks for the update. It's looking much better. I have a few comments/questions, all about typedefs.

type vs typedef in output (html)

typedefs are usually output as "type":
Example 1:

type func_desc_t

although thp_order_fn_t is output as:
Example 2:

thp_order_fn_t
Typedef: Get the suggested THP orders from a BPF program for allocation
+ more syntax and description.

Is the difference in the 2 examples above just that the first one has no additional description or parameters?

3. typedef struct msi_alloc_info isn't output as a typedef at all, but instead as a struct. But the kernel-doc for this typedef is messed up (as taken from include/asm-generic/msi.h):

/**
* struct msi_alloc_info - Default structure for MSI interrupt allocation.
* @desc: Pointer to msi descriptor
* @hwirq: Associated hw interrupt number in the domain
* @scratchpad: Storage for implementation specific scratch data
*
* Architectures can provide their own implementation by not including
* asm-generic/msi.h into their arch specific header file.
*/

typedef struct msi_alloc_info {
	struct msi_desc			*desc;
	irq_hw_number_t			hwirq;
	unsigned long			flags;
	union {
		unsigned long		ul;
		void			*ptr;
	} scratchpad[NUM_MSI_ALLOC_SCRATCHPAD_REGS];
} msi_alloc_info_t;

a. It's a typedef, not a struct -- but we may want to print the struct (?). b. The first line of the comment should be:
* typedef msi_alloc_info_t - Default structure for MSI interrupt allocation.

Hopefully a warning can be printed for this.

Signature · 1 line
~Randy
#3 lore raw

Re: [PATCH v3 1/2] kernel-doc: add support for handling global variables

Em Mon, 17 Nov 2025 22:59:24 -0800
Randy Dunlap <[email protected]> escreveu:

Quoted 21 lines

Hi,

Quoted 10 lines · Mauro Carvalho Chehab

Specially on kAPI, sometimes it is desirable to be able to describe global variables that are part of kAPI.

Documenting vars with Sphinx is simple, as we don't need to parse a data struct. All we need is the variable declaration and use natice C domain ::c:var: to format it for us.

Add support for it.

Quoted 7 lines
---
 scripts/lib/kdoc/kdoc_output.py | 45 ++++++++++++++++++++++++++
 scripts/lib/kdoc/kdoc_parser.py | 56 ++++++++++++++++++++++++++++++++-
 2 files changed, 100 insertions(+), 1 deletion(-)  
Quoted 1 line

Thanks for the update. It's looking much better.

Great!

Quoted 1 line

I have a few comments/questions, all about typedefs.

The new version was made to be bug-compatible with the Perl version, so it just mimics whatever it was there. Both Jon and I verified to be sure that the output was identical (except for whitespaces).

If you look at dump_typedef(), typedefs can be mapped on different ways, depending on its actual meaning:

def dump_typedef(self, ln, proto):
...

# Parse function typedef prototypes
...
self.output_declaration('function', declaration_name,
typedef=True, functiontype=return_type, purpose=self.entry.declaration_purpose)
...

        #
        # Not a function, try to parse a simple typedef.
        #

...
self.output_declaration('typedef', declaration_name,
purpose=self.entry.declaration_purpose)

Also, the actual output is modified by the highlight logic at kdoc_output:

	# match expressions used to find embedded type information
	type_constant = KernRe(r"\b``([^\`]+)``\b", cache=False)
	type_constant2 = KernRe(r"\%([-_*\w]+)", cache=False)
	type_func = KernRe(r"(\w+)\(\)", cache=False)
	type_param_ref = KernRe(r"([\!~\*]?)\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)", cache=False)
	# Special RST handling for func ptr params
	type_fp_param = KernRe(r"\@(\w+)\(\)", cache=False)

	# Special RST handling for structs with func ptr params
	type_fp_param2 = KernRe(r"\@(\w+->\S+)\(\)", cache=False)

	type_env = KernRe(r"(\$\w+)", cache=False)
	type_enum = KernRe(r"\&(enum\s*([_\w]+))", cache=False)
	type_struct = KernRe(r"\&(struct\s*([_\w]+))", cache=False)
	type_typedef = KernRe(r"\&(typedef\s*([_\w]+))", cache=False)
	type_union = KernRe(r"\&(union\s*([_\w]+))", cache=False)
	type_member = KernRe(r"\&([_\w]+)(\.|->)([_\w]+)", cache=False)
	type_fallback = KernRe(r"\&([_\w]+)", cache=False)
	type_member_func = type_member + KernRe(r"\(\)", cache=False)

	highlights = [
	    (type_constant, r"``\1``"),
	    (type_constant2, r"``\1``"),

	    # Note: need to escape () to avoid func matching later
	    (type_member_func, r":c:type:`\1\2\3\\(\\) <\1>`"),
	    (type_member, r":c:type:`\1\2\3 <\1>`"),
	    (type_fp_param, r"**\1\\(\\)**"),
	    (type_fp_param2, r"**\1\\(\\)**"),
	    (type_func, r"\1()"),
	    (type_enum, r":c:type:`\1 <\2>`"),
	    (type_struct, r":c:type:`\1 <\2>`"),
	    (type_typedef, r":c:type:`\1 <\2>`"),
	    (type_union, r":c:type:`\1 <\2>`"),

	    # in rst this can refer to any type
	    (type_fallback, r":c:type:`\1`"),
	    (type_param_ref, r"**\1\2**")
	]

On other words, "normal" typedefs use:

	type_typedef = KernRe(r"\&(typedef\s*([_\w]+))", cache=False)
	(type_typedef, r":c:type:`\1 <\2>`"),

but function typedefs have a different threatment (see out_function) at the RestFormat class.

Quoted 7 lines

type vs typedef in output (html)

typedefs are usually output as "type":
Example 1:

Quoted 8 lines

type func_desc_t

although thp_order_fn_t is output as:
Example 2:

thp_order_fn_t
Typedef: Get the suggested THP orders from a BPF program for allocation
+ more syntax and description.

I was unable to find kernel-doc markups for the above at linux-next or at docs-next.

Hard to tell without seeing the exact kernel-doc markups you're referring to, but see my comments above.

Quoted 27 lines

Is the difference in the 2 examples above just that the first one has no additional description or parameters?

3. typedef struct msi_alloc_info isn't output as a typedef at all, but instead as a struct. But the kernel-doc for this typedef is messed up (as taken from include/asm-generic/msi.h):

/**
* struct msi_alloc_info - Default structure for MSI interrupt allocation.
* @desc: Pointer to msi descriptor
* @hwirq: Associated hw interrupt number in the domain
* @scratchpad: Storage for implementation specific scratch data
*
* Architectures can provide their own implementation by not including
* asm-generic/msi.h into their arch specific header file.
*/

typedef struct msi_alloc_info {
	struct msi_desc			*desc;
	irq_hw_number_t			hwirq;
	unsigned long			flags;
	union {
		unsigned long		ul;
		void			*ptr;
	} scratchpad[NUM_MSI_ALLOC_SCRATCHPAD_REGS];
} msi_alloc_info_t;
Quoted 1 line

a. It's a typedef, not a struct -- but we may want to print the struct (?).

It is both:

struct msi_alloc_info
typedef msi_alloc_info_t

The kernel-doc declaration is for the struct, not for the typedef.

Ok, one could have two kernel-doc markups if this would be declared in separate:

	 /**
	  * struct msi_alloc_info - Default structure for MSI interrupt allocation.
...
	  */
	struct msi_alloc_info {
	 	struct msi_desc			*desc;
	 	irq_hw_number_t			hwirq;
	 	unsigned long			flags;
	 	union {
	 		unsigned long		ul;
	 		void			*ptr;
	 	} scratchpad[NUM_MSI_ALLOC_SCRATCHPAD_REGS];
	};

	 /**
	  * typedef msi_alloc_info_t - Default typedef for MSI interrupt allocation.
...
	  */
	typedef struct msi_alloc_info msi_alloc_info_t;
Quoted 4 lines

b. The first line of the comment should be:
* typedef msi_alloc_info_t - Default structure for MSI interrupt allocation.

Hopefully a warning can be printed for this.

It won't be hard to add a warning, but the point is that, in this specific case, the intent seems to document only the struct to ensure that newer usages won't use typedef anymore.

Also, right now, we don't produce any warning if one does:

	 /**
	  * struct msi_alloc_info - Default structure for MSI interrupt allocation.
...
	  */
	struct msi_alloc_info {
	 	struct msi_desc			*desc;
	 	irq_hw_number_t			hwirq;
	 	unsigned long			flags;
	 	union {
	 		unsigned long		ul;
	 		void			*ptr;
	 	} scratchpad[NUM_MSI_ALLOC_SCRATCHPAD_REGS];
	};

	typedef struct msi_alloc_info msi_alloc_info_t;

So, what's the point of having a warning?

Thanks,
Mauro

reviewer
#4 lore raw

Re: [PATCH v3 1/2] kernel-doc: add support for handling global variables

Quoted 26 lines · Mauro Carvalho Chehab

Em Mon, 17 Nov 2025 22:59:24 -0800
Randy Dunlap <[email protected]> escreveu:

Quoted 21 lines

Hi,

Quoted 10 lines · Mauro Carvalho Chehab

Specially on kAPI, sometimes it is desirable to be able to describe global variables that are part of kAPI.

Documenting vars with Sphinx is simple, as we don't need to parse a data struct. All we need is the variable declaration and use natice C domain ::c:var: to format it for us.

Add support for it.

Quoted 7 lines
---
 scripts/lib/kdoc/kdoc_output.py | 45 ++++++++++++++++++++++++++
 scripts/lib/kdoc/kdoc_parser.py | 56 ++++++++++++++++++++++++++++++++-
 2 files changed, 100 insertions(+), 1 deletion(-)  
Quoted 1 line

Thanks for the update. It's looking much better.

Quoted 7 lines

Great!

Quoted 1 line

I have a few comments/questions, all about typedefs.

The new version was made to be bug-compatible with the Perl version, so it just mimics whatever it was there. Both Jon and I verified to be sure that the output was identical (except for whitespaces).

I see.

Quoted 84 lines

If you look at dump_typedef(), typedefs can be mapped on different ways, depending on its actual meaning:

def dump_typedef(self, ln, proto):
...

# Parse function typedef prototypes
...
self.output_declaration('function', declaration_name,
typedef=True, functiontype=return_type, purpose=self.entry.declaration_purpose)
...

        #
        # Not a function, try to parse a simple typedef.
        #

...
self.output_declaration('typedef', declaration_name,
purpose=self.entry.declaration_purpose)

Also, the actual output is modified by the highlight logic at kdoc_output:

	# match expressions used to find embedded type information
	type_constant = KernRe(r"\b``([^\`]+)``\b", cache=False)
	type_constant2 = KernRe(r"\%([-_*\w]+)", cache=False)
	type_func = KernRe(r"(\w+)\(\)", cache=False)
	type_param_ref = KernRe(r"([\!~\*]?)\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)", cache=False)
	# Special RST handling for func ptr params
	type_fp_param = KernRe(r"\@(\w+)\(\)", cache=False)

	# Special RST handling for structs with func ptr params
	type_fp_param2 = KernRe(r"\@(\w+->\S+)\(\)", cache=False)

	type_env = KernRe(r"(\$\w+)", cache=False)
	type_enum = KernRe(r"\&(enum\s*([_\w]+))", cache=False)
	type_struct = KernRe(r"\&(struct\s*([_\w]+))", cache=False)
	type_typedef = KernRe(r"\&(typedef\s*([_\w]+))", cache=False)
	type_union = KernRe(r"\&(union\s*([_\w]+))", cache=False)
	type_member = KernRe(r"\&([_\w]+)(\.|->)([_\w]+)", cache=False)
	type_fallback = KernRe(r"\&([_\w]+)", cache=False)
	type_member_func = type_member + KernRe(r"\(\)", cache=False)

	highlights = [
	    (type_constant, r"``\1``"),
	    (type_constant2, r"``\1``"),

	    # Note: need to escape () to avoid func matching later
	    (type_member_func, r":c:type:`\1\2\3\\(\\) <\1>`"),
	    (type_member, r":c:type:`\1\2\3 <\1>`"),
	    (type_fp_param, r"**\1\\(\\)**"),
	    (type_fp_param2, r"**\1\\(\\)**"),
	    (type_func, r"\1()"),
	    (type_enum, r":c:type:`\1 <\2>`"),
	    (type_struct, r":c:type:`\1 <\2>`"),
	    (type_typedef, r":c:type:`\1 <\2>`"),
	    (type_union, r":c:type:`\1 <\2>`"),

	    # in rst this can refer to any type
	    (type_fallback, r":c:type:`\1`"),
	    (type_param_ref, r"**\1\2**")
	]

On other words, "normal" typedefs use:

	type_typedef = KernRe(r"\&(typedef\s*([_\w]+))", cache=False)
	(type_typedef, r":c:type:`\1 <\2>`"),

but function typedefs have a different threatment (see out_function) at the RestFormat class.

Quoted 12 lines

type vs typedef in output (html)

typedefs are usually output as "type":
Example 1:

type func_desc_t

although thp_order_fn_t is output as:
Example 2:

Quoted 6 lines
Quoted 3 lines

thp_order_fn_t
Typedef: Get the suggested THP orders from a BPF program for allocation
+ more syntax and description.

I was unable to find kernel-doc markups for the above at linux-next or at docs-next.

Yeah, I couldn't find it in the kernel source tree either. Maybe I took some existing source code and modified it. IDK.

Quoted 30 lines

Hard to tell without seeing the exact kernel-doc markups you're referring to, but see my comments above.

Quoted 27 lines

Is the difference in the 2 examples above just that the first one has no additional description or parameters?

3. typedef struct msi_alloc_info isn't output as a typedef at all, but instead as a struct. But the kernel-doc for this typedef is messed up (as taken from include/asm-generic/msi.h):

/**
* struct msi_alloc_info - Default structure for MSI interrupt allocation.
* @desc: Pointer to msi descriptor
* @hwirq: Associated hw interrupt number in the domain
* @scratchpad: Storage for implementation specific scratch data
*
* Architectures can provide their own implementation by not including
* asm-generic/msi.h into their arch specific header file.
*/

typedef struct msi_alloc_info {
	struct msi_desc			*desc;
	irq_hw_number_t			hwirq;
	unsigned long			flags;
	union {
		unsigned long		ul;
		void			*ptr;
	} scratchpad[NUM_MSI_ALLOC_SCRATCHPAD_REGS];
} msi_alloc_info_t;
Quoted 6 lines
Quoted 1 line

a. It's a typedef, not a struct -- but we may want to print the struct (?).

It is both:

struct msi_alloc_info
typedef msi_alloc_info_t

OK.

Quoted 1 line

The kernel-doc declaration is for the struct, not for the typedef.

Oh.

Quoted 13 lines

Ok, one could have two kernel-doc markups if this would be declared in separate:

	 /**
	  * struct msi_alloc_info - Default structure for MSI interrupt allocation.
...
	  */
	struct msi_alloc_info {
	 	struct msi_desc			*desc;
	 	irq_hw_number_t			hwirq;
	 	unsigned long			flags;
	 	union {
	 		unsigned long		ul;
	 		void			*ptr;
Quoted 11 lines
	 	} scratchpad[NUM_MSI_ALLOC_SCRATCHPAD_REGS];
	};

	 /**
	  * typedef msi_alloc_info_t - Default typedef for MSI interrupt allocation.
...
	  */
	typedef struct msi_alloc_info msi_alloc_info_t;
Quoted 2 lines

b. The first line of the comment should be:
* typedef msi_alloc_info_t - Default structure for MSI interrupt allocation.

OK.

Quoted 24 lines
Quoted 1 line

Hopefully a warning can be printed for this.

It won't be hard to add a warning, but the point is that, in this specific case, the intent seems to document only the struct to ensure that newer usages won't use typedef anymore.

Also, right now, we don't produce any warning if one does:

	 /**
	  * struct msi_alloc_info - Default structure for MSI interrupt allocation.
...
	  */
	struct msi_alloc_info {
	 	struct msi_desc			*desc;
	 	irq_hw_number_t			hwirq;
	 	unsigned long			flags;
	 	union {
	 		unsigned long		ul;
	 		void			*ptr;
	 	} scratchpad[NUM_MSI_ALLOC_SCRATCHPAD_REGS];
	};

	typedef struct msi_alloc_info msi_alloc_info_t;
Quoted 1 line

So, what's the point of having a warning?

I think that you have already explained what's going on, so no point.

Thanks for your assistance.

Signature · 1 line
~Randy
reviewer
#5 lore raw

Re: [PATCH v3 1/2] kernel-doc: add support for handling global variables

In reply to Mauro Carvalho Chehab
Quoted 24 lines · Mauro Carvalho Chehab

Em Mon, 17 Nov 2025 22:59:24 -0800
Randy Dunlap <[email protected]> escreveu:

Quoted 21 lines

Hi,

Quoted 17 lines · Mauro Carvalho Chehab

Specially on kAPI, sometimes it is desirable to be able to describe global variables that are part of kAPI.

Documenting vars with Sphinx is simple, as we don't need to parse a data struct. All we need is the variable declaration and use natice C domain ::c:var: to format it for us.

Add support for it.

---
 scripts/lib/kdoc/kdoc_output.py | 45 ++++++++++++++++++++++++++
 scripts/lib/kdoc/kdoc_parser.py | 56 ++++++++++++++++++++++++++++++++-
 2 files changed, 100 insertions(+), 1 deletion(-)  
Quoted 6 lines
Quoted 1 line

Thanks for the update. It's looking much better.

Great!

Quoted 1 line

I have a few comments/questions, all about typedefs.

Hi Mauro,

I just noticed that in my sample init/kdoc-globals-test.c file (I have s/global/var/ in it), there is one global var that is missing or misparsed:

// from net/core/rtnetlink.c:
/**
* var rtnl_mutex - historical global lock for networking control operations. *
* @rtnl_mutex is used to serialize rtnetlink requests
* and protect all kernel internal data structures related to networking. *
* See Documentation/networking/netdevices.rst for details.
* Often known as the rtnl_lock, although rtnl_lock is a kernel function. */
static DEFINE_MUTEX(rtnl_mutex);

This var is completely missing in the html output. In the man output, it is rendered like this:

NAME
static DEFINE_MUTEX - historical global lock for networking control op‐ erations.

SYNOPSIS

       static DEFINE_MUTEX;

Description
rtnl_mutex is used to serialize rtnetlink requests and protect all ker‐
nel internal data structures related to networking. See Documenta‐
tion/networking/netdevices.rst for details. Often known as the
rtnl_lock, although rtnl_lock is a kernel function.

Signature · 1 line
~Randy
#6 lore raw

Re: [PATCH v3 1/2] kernel-doc: add support for handling global variables

Hi Randy,

Em Tue, 18 Nov 2025 21:18:06 -0800
Randy Dunlap <[email protected]> escreveu:

Quoted 38 lines · Mauro Carvalho Chehab
Quoted 24 lines

Em Mon, 17 Nov 2025 22:59:24 -0800
Randy Dunlap <[email protected]> escreveu:

Quoted 21 lines

Hi,

Quoted 17 lines · Mauro Carvalho Chehab

Specially on kAPI, sometimes it is desirable to be able to describe global variables that are part of kAPI.

Documenting vars with Sphinx is simple, as we don't need to parse a data struct. All we need is the variable declaration and use natice C domain ::c:var: to format it for us.

Add support for it.

---
 scripts/lib/kdoc/kdoc_output.py | 45 ++++++++++++++++++++++++++
 scripts/lib/kdoc/kdoc_parser.py | 56 ++++++++++++++++++++++++++++++++-
 2 files changed, 100 insertions(+), 1 deletion(-)    
Quoted 6 lines
Quoted 1 line

Thanks for the update. It's looking much better.

Great!

Quoted 1 line

I have a few comments/questions, all about typedefs.

Hi Mauro,

I just noticed that in my sample init/kdoc-globals-test.c file (I have s/global/var/ in it), there is one global var that is missing or misparsed:

Quoted 11 lines

// from net/core/rtnetlink.c:
/**
* var rtnl_mutex - historical global lock for networking control operations. *
* @rtnl_mutex is used to serialize rtnetlink requests
* and protect all kernel internal data structures related to networking. *
* See Documentation/networking/netdevices.rst for details.
* Often known as the rtnl_lock, although rtnl_lock is a kernel function. */
static DEFINE_MUTEX(rtnl_mutex);

Just like we have it for functions, we'll need special regex when macros are in use.

I guess we can have a generic one to cover multiple defines, like:

	DEFINE_\w+\((\w+)\)

This should be enough to pick the name of the var. We might try a more generic approach that would be expecting:

	<some macro>(<name>)

but IMHO this could be harder to maintain in long term.

Quoted 1 line

This var is completely missing in the html output.

Now, even if we pick it correctly, Sphinx C domain is not enough for things like this, e.g.:

+ self.data += f"\n\n.. c:var:: {prototype}\n\n"

will fail if prototype is "DEFINE_MUTEX(rtnl_mutex)", as c:var::
will try to parse it without using macros.

See:
https://www.sphinx-doc.org/en/master/usage/domains/c.html

On such case, we'll likely need to use:

	.. c:macro:: {name}

To generate the cross reference and then output the prototype or ":c:type:", which is what we use on several places where the C domain parser won't work.

Maybe an alternate would be to use:

	.. c:macro:: name(arg list)

But it may be hard to see that this is a variable and not a macro declaration.

Hmm... looking at https://www.sphinx-doc.org/en/master/usage/domains/c.html#directive-c-alias
it seems that Sphinx 3.2 and above introduced "c:alias:". Maybe it might
be helpful.

Quoted 2 lines

In the man output,
it is rendered like this:

On man output, we don't need cross-references, so, we can change the logic to output the full prototype before being parsed.

Quoted 4 lines

NAME
static DEFINE_MUTEX - historical global lock for networking control op‐ erations.

Once we get the name properly parsed, this should be easy to fix.

Quoted 3 lines

SYNOPSIS

       static DEFINE_MUTEX;

Yeah, it would need some tweaks for the macro case. Synopsis should be easy to fix: instead of {prototype}, we can use {full_proto}, which is also at the dict.

Quoted 8 lines

Description
rtnl_mutex is used to serialize rtnetlink requests and protect all ker‐
nel internal data structures related to networking. See Documenta‐
tion/networking/netdevices.rst for details. Often known as the
rtnl_lock, although rtnl_lock is a kernel function.

Thanks,
Mauro

#7 lore raw

PATCH v3 2/2 docs: media: v4l2-ioctl.h: document two global variables

In reply to Mauro Carvalho Chehab

The media kAPI has two global variables at v4l2-ioctl.h. Document them.

---
 include/media/v4l2-ioctl.h | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
include/media/v4l2-ioctl.h +15 -0
index 6f7a58350441..ed63841a100c 100644
@@ -663,7 +663,22 @@ void v4l_printk_ioctl(const char *prefix, unsigned int cmd);
 struct video_device;
 
 /* names for fancy debug output */
+
+/**
+ * var v4l2_field_names - Helper array mapping V4L2_FIELD_* to strings.
+ *
+ * Specially when printing debug messages, it is interesting to output
+ * the field order at the V4L2 buffers. This array associates all possible
+ * values of field pix format from V4L2 API into a string.
+ */
 extern const char *v4l2_field_names[];
+
+/**
+ * var v4l2_type_names - Helper array mapping V4L2_BUF_TYPE_* to strings.
+ *
+ * When printing debug messages, it is interesting to output the V4L2 buffer
+ * type number with a name that represents its content.
+ */
 extern const char *v4l2_type_names[];
 
 #ifdef CONFIG_COMPAT
Signature · 1 line
2.51.1
reviewer Tested-by on v3 2/2
#8 lore raw

Re: [PATCH v3 2/2] docs: media: v4l2-ioctl.h: document two global variables

Quoted 4 lines · Mauro Carvalho Chehab

The media kAPI has two global variables at v4l2-ioctl.h. Document them.

LGTM.

Quoted 31 lines
---
 include/media/v4l2-ioctl.h | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
include/media/v4l2-ioctl.h +15 -0
index 6f7a58350441..ed63841a100c 100644
@@ -663,7 +663,22 @@ void v4l_printk_ioctl(const char *prefix, unsigned int cmd);
 struct video_device;
 
 /* names for fancy debug output */
+
+/**
+ * var v4l2_field_names - Helper array mapping V4L2_FIELD_* to strings.
+ *
+ * Specially when printing debug messages, it is interesting to output
+ * the field order at the V4L2 buffers. This array associates all possible
+ * values of field pix format from V4L2 API into a string.
+ */
 extern const char *v4l2_field_names[];
+
+/**
+ * var v4l2_type_names - Helper array mapping V4L2_BUF_TYPE_* to strings.
+ *
+ * When printing debug messages, it is interesting to output the V4L2 buffer
+ * type number with a name that represents its content.
+ */
 extern const char *v4l2_type_names[];
 
 #ifdef CONFIG_COMPAT
Signature · 1 line
~Randy
maintainer
#9 lore raw
In reply to Mauro Carvalho Chehab
Quoted 16 lines · Mauro Carvalho Chehab

Hi Jon,

As suggested and discussed with Randy, this small series add support for documenting variables using kernel-doc.

The first patch adds support for it.
The second one documents two variables from media.

While two documented variables are part of kAPI, I'm documenting them mostly aiming to test the new feature, as those are meant to be used for debugging messages, so we could live without having them documented.

I'm pretty sure we'll likely need to improve the parser regexes to catch everything. For instance, I had to add a logic on v3 due to the choice I did for the vars, which are pointers.

Quoted 8 lines

Mauro Carvalho Chehab (2):
kernel-doc: add support for handling global variables
docs: media: v4l2-ioctl.h: document two global variables

 include/media/v4l2-ioctl.h      | 15 +++++++++
 scripts/lib/kdoc/kdoc_output.py | 45 ++++++++++++++++++++++++++
 scripts/lib/kdoc/kdoc_parser.py | 56 ++++++++++++++++++++++++++++++++-
 3 files changed, 115 insertions(+), 1 deletion(-)

This all seems fine at a first glance ... except I'm missing the update to Documentation/doc-guide/kernel-doc.rst. If we don't document the documentation system, our moral position when we fault others for not using it is ... weak ... :)

Thanks,

jon