public inbox for drm-ai-reviews@public-inbox.freedesktop.org
 help / color / mirror / Atom feed
* [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y
@ 2026-03-13 13:19 Jim Cromie
  2026-03-13 13:19 ` [PATCH v11 01/65] dyndbg: fix NULL ptr on i386 due to section alignment Jim Cromie
                   ` (65 more replies)
  0 siblings, 66 replies; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh
  Cc: Jim Cromie, mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, linux-kernel, intel-gfx, amd-gfx

resend - apologies, faf'g with --cc-cover & to: lists

The drm subsystem has *lots* of debug statements, in 11 categories

 $> ack '\w*_dbg' drivers/gpu/drm/ | wc
    5532   29318  553806
 $> ack 'DRM_DEBUG\w*' drivers/gpu/drm/ | wc
    2208   12856  212035

All of these are bit-tests on __drm_debug, exposed to users as
/sys/module/drm/parameters/debug.  Many of these are done often,
vblank is done ~100/sec for some displays.  Over the uptime of many
boxes, this is a lot of cpu cycles, on bits that are almost always
off.

Dynamic-debug excels at replacing such tests with NOOPS.  Classmaps
was devised to bring that 0-off-cost to drm's categories.

Classmaps-v1 went into the kernel in Sept 2022, in 2 chunks:
  b7b4eebdba7b..6ea3bf466ac6    # core dyndbg changes
  0406faf25fb1..ee7d633f2dfb    # drm adoption

Sadly DRM-CI found a regression during init with drm.debug=<initval>;
the static-keys underneath the drm-dbgs in drm.ko got enabled, but
those in drivers & helpers did not.

Root Problem:

DECLARE_DYNDBG_CLASSMAP defined the classmap, but it repeated use in
both core and drivers violated a K&R rule "define once, refer
afterwards".  This flaw resulted in a regression; with drm.debug=0xFF
boot arg, drm-core got enabled, but drivers,etc did not.

So in feb 2023, this resulted in:
commit bb2ff6c27bc9 ("drm: Disable dynamic debug as broken")

This patchset replaces it with DYNDBG_CLASSMAP_DEFINE (invoked once in
drm-core) and DYNDBG_CLASSMAP_USE (invoked repeatedly, in drivers &
helpers).

_DEFINE exports the classmap it creates (in drm.ko), other modules
_USE the classmap.  The _USE adds a record ref'g the _DEFINEd (&
exported) classmap, in a 2nd __dyndbg_class_users section.

So now at modprobe, dyndbg scans the new section after the 1st
__dyndbg_class_maps section, follows the linkage to the _DEFINEr
module, finds the (optional) kernel-param controlling the classmap,
examines its drm.debug=<initval>, and applies it to the module being
initialized.

Savings effect:

No real effort was made to quantify the savings; bit-tests are almost
unmeasurable individually, and [1] DRM_USE_DYNAMIC_DEBUG=y purposely
depends upon JUMP_LABEL to avoid its use where it cannot help.

That said, Ive booted one box with drm.debug=0x1ff on the boot-line,
with a script run by systemd to turn it off once boot completes. It
issued ~25k messages in that time.

Status-v11:

Now rebased on drm-misc-next, to allow grinding on DRM-CI.
https://gitlab.freedesktop.org/jim.cromie/kernel-drm-next-dd/-/pipelines/1622778

DRM-CI revealed 2 bugs, fixes now included:
1. drm_buddy had 32bit truncation error, causing unexpected pass
2. drm_printer_debug_fn disregarded drm.debug, spewing msgs, causing timeout.

Also tuned vblank* to avoid drm_debug_enabled() bit-test.
Probably should defer this until [1]=y is default. It isnt yet.

Up to this point, classmaps-v2 has been stuck, straddled on the fence
between drm and dynamic-debug; it needs a little help towards one side
or the other.  ISTM that drm is the actual user, and the acid-test of
its proper function; the dyndbg selftest recaps the 2-module scenario,
but this cannot finally prove anything absent drm.

Verification: DRM-CI Pipeline #1622778
  - KUnit (arm32, arm64, x86_64): All 621 tests PASSED.
    Specifically confirms the 64-bit truncation fixes in drm_buddy.
  - i915-CML: 370 tests PASSED, 0 FAIL.
    Confirms the quelling of the UART storm in shared print callbacks.
  - Overall: No regressions found in dyndbg or buddy allocator logic.

Future:

Lukas Bartosik has been patiently waiting for classmaps to land, so he
can add dyndbg-to-ftrace functionality.  This new feature will allow
steering any/all drm.debug messages to a private ftrace buffer, and
also to mix in other pr_debug messages.  Other ftrace streams could
also be sent there (possibly w/o code changes, tbd).  It could be a
big step towards a featureful crash-buffer.

Ive also cobbled together a maple-tree based replacement for the
__dyndbg_descriptors linker section; it copies the section contents
into 3 maple trees, then drops the section in __init.  By eliminating
the redundant columns (module, file, function) it reduces the storage
needed by 40%.  Early measurements show no net runtime costs, maple
trees make good furniture.

Given that progress, I also hacked up a maple-tree based dynamic
prefix cache.  Currently the dynamic-prefix is re-written for every
prefixed callsite; this can get expensive.  By careful keying (flags
on top, descriptor address underneath), a single prefix string can
span an entire range (smallest of enabled module, file, function).

That last one doesn't help DRM, cuz it doesnt use dynamic-prefixes,
but with this optimization in place, it could be adapted to do so.

Lastly, I have an RFC jump-label patchset that dramatically cuts IPIs,
currently 1 per pr_debug (to ~1/140), by sorting the (existing) queue,
rather than flushing it when a non-increasing patch-addr is queued.

I'd like to move forward with all these, but I anticipate a "fix
classmaps 1st" response.

Jim Cromie (65):
  dyndbg: fix NULL ptr on i386 due to section alignment
  dyndbg: factor ddebug_match_desc out from ddebug_change
  dyndbg: add stub macro for DECLARE_DYNDBG_CLASSMAP
  docs/dyndbg: update examples \012 to \n
  docs/dyndbg: explain flags parse 1st
  test-dyndbg: fixup CLASSMAP usage error
  dyndbg: reword "class unknown," to "class:_UNKNOWN_"
  dyndbg: make ddebug_class_param union members same size
  dyndbg: drop NUM_TYPE_ARRAY
  dyndbg: tweak pr_fmt to avoid expansion conflicts
  dyndbg: reduce verbose/debug clutter
  dyndbg: refactor param_set_dyndbg_classes and below
  dyndbg: tighten fn-sig of ddebug_apply_class_bitmap
  dyndbg: replace classmap list with a vector
  dyndbg: macrofy a 2-index for-loop pattern
  dyndbg,module: make proper substructs in _ddebug_info
  dyndbg: hoist classmap-filter-by-modname up to ddebug_add_module
  dyndbg: move mod_name down from struct ddebug_table to _ddebug_info
  dyndbg-API: remove DD_CLASS_TYPE_(DISJOINT|LEVEL)_NAMES and code
  selftests-dyndbg: add a dynamic_debug run_tests target
  dyndbg: change __dynamic_func_call_cls* macros into expressions
  dyndbg-API: replace DECLARE_DYNDBG_CLASSMAP
  dyndbg: detect class_id reservation conflicts
  dyndbg: check DYNAMIC_DEBUG_CLASSMAP_DEFINE args at compile-time
  dyndbg-test: change do_prints testpoint to accept a loopct
  dyndbg-API: promote DYNAMIC_DEBUG_CLASSMAP_PARAM to API
  dyndbg: treat comma as a token separator
  dyndbg: split multi-query strings with %
  selftests-dyndbg: add test_mod_submod
  dyndbg: resolve "protection" of class'd pr_debug
  dyndbg: add DYNAMIC_DEBUG_CLASSMAP_USE_(dd_class_name, offset)
  dyndbg: Harden classmap and callsite validation
  docs/dyndbg: add classmap info to howto
  drm: use correct ccflags-y spelling
  drm-dyndbg: adapt drm core to use dyndbg classmaps-v2
  drm-dyndbg: adapt DRM to invoke DYNAMIC_DEBUG_CLASSMAP_PARAM
  drm-print: modernize an archaic comment
  drm-print: fix config-dependent unused variable
  drm-dyndbg: DRM_CLASSMAP_USE in amdgpu driver
  drm-dyndbg: DRM_CLASSMAP_USE in i915 driver
  drm-dyndbg: DRM_CLASSMAP_USE in drm_crtc_helper
  drm-dyndbg: DRM_CLASSMAP_USE in drm_dp_helper
  drm-dyndbg: DRM_CLASSMAP_USE in nouveau
  drm-dyndbg: add DRM_CLASSMAP_USE to Xe driver
  drm-dyndbg: add DRM_CLASSMAP_USE to virtio_gpu
  drm-dyndbg: add DRM_CLASSMAP_USE to simpledrm
  drm-dyndbg: add DRM_CLASSMAP_USE to bochs
  drm-dyndbg: add DRM_CLASSMAP_USE to etnaviv
  drm-dyndbg: add DRM_CLASSMAP_USE to gma500 driver
  drm-dyndbg: add DRM_CLASSMAP_USE to radeon
  drm-dyndbg: add DRM_CLASSMAP_USE to vmwgfx driver
  drm-dyndbg: add DRM_CLASSMAP_USE to vkms driver
  drm-dyndbg: add DRM_CLASSMAP_USE to udl driver
  drm-dyndbg: add DRM_CLASSMAP_USE to mgag200 driver
  drm-dyndbg: add DRM_CLASSMAP_USE to the gud driver
  drm-dyndbg: add DRM_CLASSMAP_USE to the qxl driver
  drm-dyndbg: add DRM_CLASSMAP_USE to the drm_gem_shmem_helper driver
  accel: add -DDYNAMIC_DEBUG_MODULE to subdir-ccflags
  accel/ivpu: implement IVPU_DBG_* as a dyndbg classmap
  drm: restore CONFIG_DRM_USE_DYNAMIC_DEBUG un-BROKEN
  accel/ethosu: enable drm.debug control
  accel/rocket: enable drm.debug control
  drm_buddy: fix 64-bit truncation in power-of-2 rounding
  drm_print: fix drm_printer dynamic debug bypass
  drm_vblank: use dyndbg's static-key to avoid flag-check

 .../admin-guide/dynamic-debug-howto.rst       | 184 +++-
 MAINTAINERS                                   |   3 +-
 drivers/accel/Makefile                        |   7 +-
 drivers/accel/ethosu/ethosu_drv.c             |   3 +
 drivers/accel/ivpu/ivpu_drv.c                 |  27 +-
 drivers/accel/ivpu/ivpu_drv.h                 |  45 +-
 drivers/accel/rocket/rocket_gem.c             |   2 +
 drivers/gpu/buddy.c                           |   4 +-
 drivers/gpu/drm/Kconfig.debug                 |   1 -
 drivers/gpu/drm/Makefile                      |   3 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c       |  12 +-
 drivers/gpu/drm/display/drm_dp_helper.c       |  12 +-
 drivers/gpu/drm/drm_crtc_helper.c             |  12 +-
 drivers/gpu/drm/drm_gem_shmem_helper.c        |   1 +
 drivers/gpu/drm/drm_print.c                   |  38 +-
 drivers/gpu/drm/drm_vblank.c                  |  10 +-
 drivers/gpu/drm/etnaviv/etnaviv_drv.c         |   2 +
 drivers/gpu/drm/gma500/psb_drv.c              |   2 +
 drivers/gpu/drm/gud/gud_drv.c                 |   2 +
 drivers/gpu/drm/i915/i915_params.c            |  12 +-
 drivers/gpu/drm/mgag200/mgag200_drv.c         |   2 +
 drivers/gpu/drm/nouveau/nouveau_drm.c         |  12 +-
 drivers/gpu/drm/qxl/qxl_drv.c                 |   2 +
 drivers/gpu/drm/radeon/radeon_drv.c           |   2 +
 drivers/gpu/drm/sysfb/simpledrm.c             |   2 +
 drivers/gpu/drm/tiny/bochs.c                  |   2 +
 drivers/gpu/drm/udl/udl_main.c                |   2 +
 drivers/gpu/drm/virtio/virtgpu_drv.c          |   2 +
 drivers/gpu/drm/vkms/vkms_drv.c               |   2 +
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c           |   2 +
 drivers/gpu/drm/xe/xe_drm_client.c            |   2 +
 include/asm-generic/vmlinux.lds.h             |  19 +-
 include/drm/drm_print.h                       |  22 +-
 include/linux/dynamic_debug.h                 | 304 +++++--
 kernel/module/main.c                          |  15 +-
 lib/Kconfig.debug                             |  24 +-
 lib/Makefile                                  |   5 +
 lib/dynamic_debug.c                           | 814 ++++++++++++------
 lib/test_dynamic_debug.c                      | 198 +++--
 lib/test_dynamic_debug_submod.c               |  21 +
 tools/testing/selftests/Makefile              |   1 +
 .../testing/selftests/dynamic_debug/Makefile  |   9 +
 tools/testing/selftests/dynamic_debug/config  |   7 +
 .../dynamic_debug/dyndbg_selftest.sh          | 373 ++++++++
 44 files changed, 1665 insertions(+), 561 deletions(-)
 create mode 100644 lib/test_dynamic_debug_submod.c
 create mode 100644 tools/testing/selftests/dynamic_debug/Makefile
 create mode 100644 tools/testing/selftests/dynamic_debug/config
 create mode 100755 tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh

-- 
2.53.0


^ permalink raw reply	[flat|nested] 114+ messages in thread

* [PATCH v11 01/65] dyndbg: fix NULL ptr on i386 due to section alignment
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 02/65] dyndbg: factor ddebug_match_desc out from ddebug_change Jim Cromie
                   ` (64 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Arnd Bergmann, linux-arch,
	linux-kernel
  Cc: Jim Cromie, mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx, kernel test robot

When dyndbg classmaps get used (later in this series), the
__dyndbg_classes section (which has 28 byte structs on i386), causes
mis-alignment of the following __dyndbg section, resulting in a NULL
pointer deref in dynamic_debug_init().

To fix this, employ belt + suspenders:

1. move __dyndbg section above __dyndbg_classes.  This restores it to
its original position directly after the ALIGN(8), and fixes the
immediate problem.

2. add ALIGN(8) to the BOUNDED_SECTION* macros.  This aligns all
existing sections using the macro, and also fixes a future
dyndbg_class_* addition which would suffer the same misalignment on
i386.  Many of the existing macro uses already have a preceding ALIGN,
these are now redundant, but are harmless, so are left to avoid churn.

3. remove BOUNDED_SECTION* uses in ORC_UNWINDER sections.  These have
smaller alignments, *and* scripts/sorttable.c does not tolerate the
added ALIGN(8) padding.

Reported-by: kernel test robot <oliver.sang@intel.com>
Closes: https://lore.kernel.org/oe-lkp/202601211325.7e1f336-lkp@intel.com
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 include/asm-generic/vmlinux.lds.h | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index eeb070f330bd..a2ba7e3d9994 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -212,11 +212,13 @@
 #endif
 
 #define BOUNDED_SECTION_PRE_LABEL(_sec_, _label_, _BEGIN_, _END_)	\
+	. = ALIGN(8);							\
 	_BEGIN_##_label_ = .;						\
 	KEEP(*(_sec_))							\
 	_END_##_label_ = .;
 
 #define BOUNDED_SECTION_POST_LABEL(_sec_, _label_, _BEGIN_, _END_)	\
+	. = ALIGN(8);							\
 	_label_##_BEGIN_ = .;						\
 	KEEP(*(_sec_))							\
 	_label_##_END_ = .;
@@ -383,8 +385,8 @@
 	*(__tracepoints)						\
 	/* implement dynamic printk debug */				\
 	. = ALIGN(8);							\
-	BOUNDED_SECTION_BY(__dyndbg_classes, ___dyndbg_classes)		\
 	BOUNDED_SECTION_BY(__dyndbg, ___dyndbg)				\
+	BOUNDED_SECTION_BY(__dyndbg_classes, ___dyndbg_classes)		\
 	CODETAG_SECTIONS()						\
 	LIKELY_PROFILE()		       				\
 	BRANCH_PROFILE()						\
@@ -867,15 +869,21 @@
 #ifdef CONFIG_UNWINDER_ORC
 #define ORC_UNWIND_TABLE						\
 	.orc_header : AT(ADDR(.orc_header) - LOAD_OFFSET) {		\
-		BOUNDED_SECTION_BY(.orc_header, _orc_header)		\
+		__start_orc_header = .;					\
+		KEEP(*(.orc_header))					\
+		__stop_orc_header = .;					\
 	}								\
 	. = ALIGN(4);							\
 	.orc_unwind_ip : AT(ADDR(.orc_unwind_ip) - LOAD_OFFSET) {	\
-		BOUNDED_SECTION_BY(.orc_unwind_ip, _orc_unwind_ip)	\
+		__start_orc_unwind_ip = .;				\
+		KEEP(*(.orc_unwind_ip))					\
+		__stop_orc_unwind_ip = .;				\
 	}								\
 	. = ALIGN(2);							\
 	.orc_unwind : AT(ADDR(.orc_unwind) - LOAD_OFFSET) {		\
-		BOUNDED_SECTION_BY(.orc_unwind, _orc_unwind)		\
+		__start_orc_unwind = .;					\
+		KEEP(*(.orc_unwind))					\
+		__stop_orc_unwind = .;					\
 	}								\
 	text_size = _etext - _stext;					\
 	. = ALIGN(4);							\
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 02/65] dyndbg: factor ddebug_match_desc out from ddebug_change
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
  2026-03-13 13:19 ` [PATCH v11 01/65] dyndbg: fix NULL ptr on i386 due to section alignment Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 03/65] dyndbg: add stub macro for DECLARE_DYNDBG_CLASSMAP Jim Cromie
                   ` (63 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Andrew Morton, Jim Cromie,
	linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

ddebug_change() is a big (~100 lines) function with a nested for loop.

The outer loop walks the per-module ddebug_tables list, and does
module stuff: it filters on a query's "module FOO*" and "class BAR",
failures here skip the entire inner loop.

The inner loop (60 lines) scans a module's descriptors.  It starts
with a long block of filters on function, line, format, and the
validated "BAR" class (or the legacy/_DPRINTK_CLASS_DFLT).

These filters "continue" past pr_debugs that don't match the query
criteria, before it falls through the code below that counts matches,
then adjusts the flags and static-keys.  This is unnecessarily hard to
think about.

So move the per-descriptor filter-block into a boolean function:
ddebug_match_desc(desc), and change each "continue" to "return false".
This puts a clear interface in place, so any future changes are either
inside, outside, or across this interface.

also fix checkpatch complaints about spaces and braces.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 lib/dynamic_debug.c | 83 +++++++++++++++++++++++++--------------------
 1 file changed, 47 insertions(+), 36 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 18a71a9108d3..6b1e983cfedc 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -172,6 +172,52 @@ static struct ddebug_class_map *ddebug_find_valid_class(struct ddebug_table cons
  * callsites, normally the same as number of changes.  If verbose,
  * logs the changes.  Takes ddebug_lock.
  */
+static bool ddebug_match_desc(const struct ddebug_query *query,
+			      struct _ddebug *dp,
+			      int valid_class)
+{
+	/* match site against query-class */
+	if (dp->class_id != valid_class)
+		return false;
+
+	/* match against the source filename */
+	if (query->filename &&
+	    !match_wildcard(query->filename, dp->filename) &&
+	    !match_wildcard(query->filename,
+			    kbasename(dp->filename)) &&
+	    !match_wildcard(query->filename,
+			    trim_prefix(dp->filename)))
+		return false;
+
+	/* match against the function */
+	if (query->function &&
+	    !match_wildcard(query->function, dp->function))
+		return false;
+
+	/* match against the format */
+	if (query->format) {
+		if (*query->format == '^') {
+			char *p;
+			/* anchored search. match must be at beginning */
+			p = strstr(dp->format, query->format + 1);
+			if (p != dp->format)
+				return false;
+		} else if (!strstr(dp->format, query->format)) {
+			return false;
+		}
+	}
+
+	/* match against the line number range */
+	if (query->first_lineno &&
+	    dp->lineno < query->first_lineno)
+		return false;
+	if (query->last_lineno &&
+	    dp->lineno > query->last_lineno)
+		return false;
+
+	return true;
+}
+
 static int ddebug_change(const struct ddebug_query *query,
 			 struct flag_settings *modifiers)
 {
@@ -204,42 +250,7 @@ static int ddebug_change(const struct ddebug_query *query,
 		for (i = 0; i < dt->num_ddebugs; i++) {
 			struct _ddebug *dp = &dt->ddebugs[i];
 
-			/* match site against query-class */
-			if (dp->class_id != valid_class)
-				continue;
-
-			/* match against the source filename */
-			if (query->filename &&
-			    !match_wildcard(query->filename, dp->filename) &&
-			    !match_wildcard(query->filename,
-					   kbasename(dp->filename)) &&
-			    !match_wildcard(query->filename,
-					   trim_prefix(dp->filename)))
-				continue;
-
-			/* match against the function */
-			if (query->function &&
-			    !match_wildcard(query->function, dp->function))
-				continue;
-
-			/* match against the format */
-			if (query->format) {
-				if (*query->format == '^') {
-					char *p;
-					/* anchored search. match must be at beginning */
-					p = strstr(dp->format, query->format+1);
-					if (p != dp->format)
-						continue;
-				} else if (!strstr(dp->format, query->format))
-					continue;
-			}
-
-			/* match against the line number range */
-			if (query->first_lineno &&
-			    dp->lineno < query->first_lineno)
-				continue;
-			if (query->last_lineno &&
-			    dp->lineno > query->last_lineno)
+			if (!ddebug_match_desc(query, dp, valid_class))
 				continue;
 
 			nfound++;
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 03/65] dyndbg: add stub macro for DECLARE_DYNDBG_CLASSMAP
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
  2026-03-13 13:19 ` [PATCH v11 01/65] dyndbg: fix NULL ptr on i386 due to section alignment Jim Cromie
  2026-03-13 13:19 ` [PATCH v11 02/65] dyndbg: factor ddebug_match_desc out from ddebug_change Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 04/65] docs/dyndbg: update examples \012 to \n Jim Cromie
                   ` (62 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jim Cromie, linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

Add the stub macro for !DYNAMIC_DEBUG builds, after moving the
original macro-defn down under the big ifdef.  Do it now so future
changes have a cleaner starting point.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 include/linux/dynamic_debug.h | 43 ++++++++++++++++++-----------------
 1 file changed, 22 insertions(+), 21 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 05743900a116..a10adac8e8f0 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -93,27 +93,6 @@ struct ddebug_class_map {
 	enum class_map_type map_type;
 };
 
-/**
- * DECLARE_DYNDBG_CLASSMAP - declare classnames known by a module
- * @_var:   a struct ddebug_class_map, passed to module_param_cb
- * @_type:  enum class_map_type, chooses bits/verbose, numeric/symbolic
- * @_base:  offset of 1st class-name. splits .class_id space
- * @classes: class-names used to control class'd prdbgs
- */
-#define DECLARE_DYNDBG_CLASSMAP(_var, _maptype, _base, ...)		\
-	static const char *_var##_classnames[] = { __VA_ARGS__ };	\
-	static struct ddebug_class_map __aligned(8) __used		\
-		__section("__dyndbg_classes") _var = {			\
-		.mod = THIS_MODULE,					\
-		.mod_name = KBUILD_MODNAME,				\
-		.base = _base,						\
-		.map_type = _maptype,					\
-		.length = NUM_TYPE_ARGS(char*, __VA_ARGS__),		\
-		.class_names = _var##_classnames,			\
-	}
-#define NUM_TYPE_ARGS(eltype, ...)				\
-        (sizeof((eltype[]){__VA_ARGS__}) / sizeof(eltype))
-
 /* encapsulate linker provided built-in (or module) dyndbg data */
 struct _ddebug_info {
 	struct _ddebug *descs;
@@ -138,6 +117,27 @@ struct ddebug_class_param {
 #if defined(CONFIG_DYNAMIC_DEBUG) || \
 	(defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
 
+/**
+ * DECLARE_DYNDBG_CLASSMAP - declare classnames known by a module
+ * @_var:   a struct ddebug_class_map, passed to module_param_cb
+ * @_type:  enum class_map_type, chooses bits/verbose, numeric/symbolic
+ * @_base:  offset of 1st class-name. splits .class_id space
+ * @classes: class-names used to control class'd prdbgs
+ */
+#define DECLARE_DYNDBG_CLASSMAP(_var, _maptype, _base, ...)		\
+	static const char *_var##_classnames[] = { __VA_ARGS__ };	\
+	static struct ddebug_class_map __aligned(8) __used		\
+		__section("__dyndbg_classes") _var = {			\
+		.mod = THIS_MODULE,					\
+		.mod_name = KBUILD_MODNAME,				\
+		.base = _base,						\
+		.map_type = _maptype,					\
+		.length = NUM_TYPE_ARGS(char*, __VA_ARGS__),		\
+		.class_names = _var##_classnames,			\
+	}
+#define NUM_TYPE_ARGS(eltype, ...)				\
+	(sizeof((eltype[]) {__VA_ARGS__}) / sizeof(eltype))
+
 extern __printf(2, 3)
 void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
 
@@ -314,6 +314,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 
 #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)
 #define DYNAMIC_DEBUG_BRANCH(descriptor) false
+#define DECLARE_DYNDBG_CLASSMAP(...)
 
 #define dynamic_pr_debug(fmt, ...)					\
 	no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 04/65] docs/dyndbg: update examples \012 to \n
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (2 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 03/65] dyndbg: add stub macro for DECLARE_DYNDBG_CLASSMAP Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 05/65] docs/dyndbg: explain flags parse 1st Jim Cromie
                   ` (61 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jonathan Corbet, Shuah Khan,
	linux-doc, linux-kernel
  Cc: Jim Cromie, mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

commit 47ea6f99d06e ("dyndbg: use ESCAPE_SPACE for cat control")
changed the control-file to display format strings with "\n" rather
than "\012".  Update the docs to match the new reality.

Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Tested-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 .../admin-guide/dynamic-debug-howto.rst       | 20 +++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst b/Documentation/admin-guide/dynamic-debug-howto.rst
index 095a63892257..4b14d9fd0300 100644
--- a/Documentation/admin-guide/dynamic-debug-howto.rst
+++ b/Documentation/admin-guide/dynamic-debug-howto.rst
@@ -38,12 +38,12 @@ You can view the currently configured behaviour in the *prdbg* catalog::
 
   :#> head -n7 /proc/dynamic_debug/control
   # filename:lineno [module]function flags format
-  init/main.c:1179 [main]initcall_blacklist =_ "blacklisting initcall %s\012
-  init/main.c:1218 [main]initcall_blacklisted =_ "initcall %s blacklisted\012"
-  init/main.c:1424 [main]run_init_process =_ "  with arguments:\012"
-  init/main.c:1426 [main]run_init_process =_ "    %s\012"
-  init/main.c:1427 [main]run_init_process =_ "  with environment:\012"
-  init/main.c:1429 [main]run_init_process =_ "    %s\012"
+  init/main.c:1179 [main]initcall_blacklist =_ "blacklisting initcall %s\n"
+  init/main.c:1218 [main]initcall_blacklisted =_ "initcall %s blacklisted\n"
+  init/main.c:1424 [main]run_init_process =_ "  with arguments:\n"
+  init/main.c:1426 [main]run_init_process =_ "    %s\n"
+  init/main.c:1427 [main]run_init_process =_ "  with environment:\n"
+  init/main.c:1429 [main]run_init_process =_ "    %s\n"
 
 The 3rd space-delimited column shows the current flags, preceded by
 a ``=`` for easy use with grep/cut. ``=p`` shows enabled callsites.
@@ -59,10 +59,10 @@ query/commands to the control file.  Example::
 
   :#> ddcmd '-p; module main func run* +p'
   :#> grep =p /proc/dynamic_debug/control
-  init/main.c:1424 [main]run_init_process =p "  with arguments:\012"
-  init/main.c:1426 [main]run_init_process =p "    %s\012"
-  init/main.c:1427 [main]run_init_process =p "  with environment:\012"
-  init/main.c:1429 [main]run_init_process =p "    %s\012"
+  init/main.c:1424 [main]run_init_process =p "  with arguments:\n"
+  init/main.c:1426 [main]run_init_process =p "    %s\n"
+  init/main.c:1427 [main]run_init_process =p "  with environment:\n"
+  init/main.c:1429 [main]run_init_process =p "    %s\n"
 
 Error messages go to console/syslog::
 
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 05/65] docs/dyndbg: explain flags parse 1st
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (3 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 04/65] docs/dyndbg: update examples \012 to \n Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 06/65] test-dyndbg: fixup CLASSMAP usage error Jim Cromie
                   ` (60 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jonathan Corbet, Shuah Khan,
	linux-doc, linux-kernel
  Cc: Jim Cromie, mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

When writing queries to >control, flags are parsed 1st, since they are
the only required field, and they require specific compositions.  So
if the flags draw an error (on those specifics), then keyword errors
aren't reported.  This can be mildly confusing/annoying, so explain it
instead.

cc: linux-doc@vger.kernel.org
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 .../admin-guide/dynamic-debug-howto.rst         | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst b/Documentation/admin-guide/dynamic-debug-howto.rst
index 4b14d9fd0300..9c2f096ed1d8 100644
--- a/Documentation/admin-guide/dynamic-debug-howto.rst
+++ b/Documentation/admin-guide/dynamic-debug-howto.rst
@@ -109,10 +109,19 @@ The match-spec's select *prdbgs* from the catalog, upon which to apply
 the flags-spec, all constraints are ANDed together.  An absent keyword
 is the same as keyword "*".
 
-
-A match specification is a keyword, which selects the attribute of
-the callsite to be compared, and a value to compare against.  Possible
-keywords are:::
+Note that since the match-spec can be empty, the flags are checked 1st,
+then the pairs of keyword and value.  Flag errs will hide keyword errs::
+
+  bash-5.2# ddcmd mod bar +foo
+  dyndbg: read 13 bytes from userspace
+  dyndbg: query 0: "mod bar +foo" mod:*
+  dyndbg: unknown flag 'o'
+  dyndbg: flags parse failed
+  dyndbg: processed 1 queries, with 0 matches, 1 errs
+
+So a match-spec is a keyword, which selects the attribute of the
+callsite to be compared, and a value to compare against.  Possible
+keywords are::
 
   match-spec ::= 'func' string |
 		 'file' string |
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 06/65] test-dyndbg: fixup CLASSMAP usage error
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (4 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 05/65] docs/dyndbg: explain flags parse 1st Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 07/65] dyndbg: reword "class unknown, " to "class:_UNKNOWN_" Jim Cromie
                   ` (59 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jim Cromie, Andrew Morton,
	linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

commit 6ea3bf466ac6 ("dyndbg: test DECLARE_DYNDBG_CLASSMAP, sysfs nodes")

A closer look at test_dynamic_debug.ko logging output reveals a macro
usage error:

lib/test_dynamic_debug.c:105 [test_dynamic_debug]do_cats =p "LOW msg\n" class:MID
lib/test_dynamic_debug.c:106 [test_dynamic_debug]do_cats =p "MID msg\n" class:HI
lib/test_dynamic_debug.c:107 [test_dynamic_debug]do_cats =_ "HI msg\n" class unknown, _id:13

107 says: HI is unknown, and 105,106 have a LOW/MID and MID/HI skew.

DECLARE_DYNDBG_CLASSMAP() _base arg must equal the enum's 1st value,
in this case it was _base + 1.  This leaves HI class un-selectable.

NB: the macro could better validate its arguments.

Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Tested-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 lib/test_dynamic_debug.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/test_dynamic_debug.c b/lib/test_dynamic_debug.c
index 77c2a669b6af..396144cf351b 100644
--- a/lib/test_dynamic_debug.c
+++ b/lib/test_dynamic_debug.c
@@ -75,7 +75,7 @@ DD_SYS_WRAP(disjoint_bits, p);
 DD_SYS_WRAP(disjoint_bits, T);
 
 /* symbolic input, independent bits */
-enum cat_disjoint_names { LOW = 11, MID, HI };
+enum cat_disjoint_names { LOW = 10, MID, HI };
 DECLARE_DYNDBG_CLASSMAP(map_disjoint_names, DD_CLASS_TYPE_DISJOINT_NAMES, 10,
 			"LOW", "MID", "HI");
 DD_SYS_WRAP(disjoint_names, p);
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 07/65] dyndbg: reword "class unknown, " to "class:_UNKNOWN_"
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (5 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 06/65] test-dyndbg: fixup CLASSMAP usage error Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 08/65] dyndbg: make ddebug_class_param union members same size Jim Cromie
                   ` (58 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jim Cromie, Andrew Morton,
	linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

When a dyndbg classname is unknown to a kernel module (as before
previous patch), the callsite is un-addressable via >control queries.

The control-file displays this condition as "class unknown,"
currently.  That spelling is sub-optimal/too-generic, so change it to
"class:_UNKNOWN_" to loudly announce the erroneous situation, and to
make it uniquely greppable.

Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 lib/dynamic_debug.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 6b1e983cfedc..a9caf84ddb22 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -1166,7 +1166,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
 		if (class)
 			seq_printf(m, " class:%s", class);
 		else
-			seq_printf(m, " class unknown, _id:%d", dp->class_id);
+			seq_printf(m, " class:_UNKNOWN_ _id:%d", dp->class_id);
 	}
 	seq_putc(m, '\n');
 
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 08/65] dyndbg: make ddebug_class_param union members same size
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (6 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 07/65] dyndbg: reword "class unknown, " to "class:_UNKNOWN_" Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 09/65] dyndbg: drop NUM_TYPE_ARRAY Jim Cromie
                   ` (57 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jim Cromie, Andrew Morton,
	linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

struct ddebug_class_param keeps a ref to the state-storage of the
param; make both class-types use the same unsigned long storage type.

ISTM this is simpler and safer; it avoids an irrelevant difference,
and if 2 users somehow get class-type mixed up (or refer to the wrong
union member), at least they will both see the same value.

Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 include/linux/dynamic_debug.h | 2 +-
 lib/dynamic_debug.c           | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index a10adac8e8f0..441305277914 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -104,7 +104,7 @@ struct _ddebug_info {
 struct ddebug_class_param {
 	union {
 		unsigned long *bits;
-		unsigned int *lvl;
+		unsigned long *lvl;
 	};
 	char flags[8];
 	const struct ddebug_class_map *map;
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index a9caf84ddb22..ffa1cf7c2c72 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -811,7 +811,7 @@ int param_get_dyndbg_classes(char *buffer, const struct kernel_param *kp)
 
 	case DD_CLASS_TYPE_LEVEL_NAMES:
 	case DD_CLASS_TYPE_LEVEL_NUM:
-		return scnprintf(buffer, PAGE_SIZE, "%d\n", *dcp->lvl);
+		return scnprintf(buffer, PAGE_SIZE, "%ld\n", *dcp->lvl);
 	default:
 		return -1;
 	}
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 09/65] dyndbg: drop NUM_TYPE_ARRAY
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (7 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 08/65] dyndbg: make ddebug_class_param union members same size Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 10/65] dyndbg: tweak pr_fmt to avoid expansion conflicts Jim Cromie
                   ` (56 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jim Cromie, linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

ARRAY_SIZE works here, since array decl is complete.

no functional change

Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 include/linux/dynamic_debug.h | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 441305277914..92627a03b4d1 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -132,11 +132,9 @@ struct ddebug_class_param {
 		.mod_name = KBUILD_MODNAME,				\
 		.base = _base,						\
 		.map_type = _maptype,					\
-		.length = NUM_TYPE_ARGS(char*, __VA_ARGS__),		\
+		.length = ARRAY_SIZE(_var##_classnames),		\
 		.class_names = _var##_classnames,			\
 	}
-#define NUM_TYPE_ARGS(eltype, ...)				\
-	(sizeof((eltype[]) {__VA_ARGS__}) / sizeof(eltype))
 
 extern __printf(2, 3)
 void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 10/65] dyndbg: tweak pr_fmt to avoid expansion conflicts
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (8 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 09/65] dyndbg: drop NUM_TYPE_ARRAY Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 11/65] dyndbg: reduce verbose/debug clutter Jim Cromie
                   ` (55 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Andrew Morton, Jim Cromie,
	linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

Disambiguate pr_fmt(fmt) arg, by changing it to _FMT_, to avoid naming
confusion with many later macros also using that argname.

no functional change

Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 lib/dynamic_debug.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index ffa1cf7c2c72..9575b92a8deb 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -11,7 +11,7 @@
  * Copyright (C) 2013 Du, Changbin <changbin.du@gmail.com>
  */
 
-#define pr_fmt(fmt) "dyndbg: " fmt
+#define pr_fmt(_FMT_) "dyndbg: " _FMT_
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 11/65] dyndbg: reduce verbose/debug clutter
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (9 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 10/65] dyndbg: tweak pr_fmt to avoid expansion conflicts Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 12/65] dyndbg: refactor param_set_dyndbg_classes and below Jim Cromie
                   ` (54 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jim Cromie, Andrew Morton,
	linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

currently, for verbose=3, these are logged (blank lines for clarity):

 dyndbg: query 0: "class DRM_UT_CORE +p" mod:*
 dyndbg: split into words: "class" "DRM_UT_CORE" "+p"

 dyndbg: op='+'
 dyndbg: flags=0x1
 dyndbg: *flagsp=0x1 *maskp=0xffffffff

 dyndbg: parsed: func="" file="" module="" format="" lineno=0-0 class=...
 dyndbg: no matches for query
 dyndbg: no-match: func="" file="" module="" format="" lineno=0-0 class=...
 dyndbg: processed 1 queries, with 0 matches, 0 errs

That is excessive, so this patch:
 - shrinks 3 lines of 2nd stanza to single line
 - drops 1st 2 lines of 3rd stanza
   3rd line is like 1st, with result, not procedure.
   2nd line is just status, retold in 4th, with more info.

New output:

 dyndbg: query 0: "class DRM_UT_CORE +p" mod:*
 dyndbg: split into words: "class" "DRM_UT_CORE" "+p"
 dyndbg: op='+' flags=0x1 *flagsp=0x1 *maskp=0xffffffff
 dyndbg: no-match: func="" file="" module="" format="" lineno=0-0 class=...
 dyndbg: processed 1 queries, with 0 matches, 0 errs

Also reduce verbose=3 messages in ddebug_add_module

When modprobing a module, dyndbg currently logs/says "add-module", and
then "skipping" if the module has no prdbgs.  Instead just check 1st
and return quietly.

no functional change

Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 lib/dynamic_debug.c | 21 ++++++---------------
 1 file changed, 6 insertions(+), 15 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 9575b92a8deb..3ae9ecabdad1 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -276,9 +276,6 @@ static int ddebug_change(const struct ddebug_query *query,
 	}
 	mutex_unlock(&ddebug_lock);
 
-	if (!nfound && verbose)
-		pr_info("no matches for query\n");
-
 	return nfound;
 }
 
@@ -511,7 +508,6 @@ static int ddebug_parse_flags(const char *str, struct flag_settings *modifiers)
 		pr_err("bad flag-op %c, at start of %s\n", *str, str);
 		return -EINVAL;
 	}
-	v3pr_info("op='%c'\n", op);
 
 	for (; *str ; ++str) {
 		for (i = ARRAY_SIZE(opt_array) - 1; i >= 0; i--) {
@@ -525,7 +521,6 @@ static int ddebug_parse_flags(const char *str, struct flag_settings *modifiers)
 			return -EINVAL;
 		}
 	}
-	v3pr_info("flags=0x%x\n", modifiers->flags);
 
 	/* calculate final flags, mask based upon op */
 	switch (op) {
@@ -541,7 +536,7 @@ static int ddebug_parse_flags(const char *str, struct flag_settings *modifiers)
 		modifiers->flags = 0;
 		break;
 	}
-	v3pr_info("*flagsp=0x%x *maskp=0x%x\n", modifiers->flags, modifiers->mask);
+	v3pr_info("op='%c' flags=0x%x maskp=0x%x\n", op, modifiers->flags, modifiers->mask);
 
 	return 0;
 }
@@ -551,7 +546,7 @@ static int ddebug_exec_query(char *query_string, const char *modname)
 	struct flag_settings modifiers = {};
 	struct ddebug_query query = {};
 #define MAXWORDS 9
-	int nwords, nfound;
+	int nwords;
 	char *words[MAXWORDS];
 
 	nwords = ddebug_tokenize(query_string, words, MAXWORDS);
@@ -569,10 +564,7 @@ static int ddebug_exec_query(char *query_string, const char *modname)
 		return -EINVAL;
 	}
 	/* actually go and implement the change */
-	nfound = ddebug_change(&query, &modifiers);
-	vpr_info_dq(&query, nfound ? "applied" : "no-match");
-
-	return nfound;
+	return ddebug_change(&query, &modifiers);
 }
 
 /* handle multiple queries in query string, continue on error, return
@@ -1246,11 +1238,10 @@ static int ddebug_add_module(struct _ddebug_info *di, const char *modname)
 {
 	struct ddebug_table *dt;
 
-	v3pr_info("add-module: %s.%d sites\n", modname, di->num_descs);
-	if (!di->num_descs) {
-		v3pr_info(" skip %s\n", modname);
+	if (!di->num_descs)
 		return 0;
-	}
+
+	v3pr_info("add-module: %s %d sites\n", modname, di->num_descs);
 
 	dt = kzalloc_obj(*dt);
 	if (dt == NULL) {
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 12/65] dyndbg: refactor param_set_dyndbg_classes and below
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (10 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 11/65] dyndbg: reduce verbose/debug clutter Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 13/65] dyndbg: tighten fn-sig of ddebug_apply_class_bitmap Jim Cromie
                   ` (53 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jim Cromie, Andrew Morton,
	linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

Refactor callchain below param_set_dyndbg_classes(1) to allow mod-name
specific settings.  Split (1) into upper/lower fns, adding modname
param to lower, and passing NULL in from upper.  Below that, add the
same param to ddebug_apply_class_bitmap(), and pass it thru to
_ddebug_queries(), replacing NULL with the param.

This allows the callchain to update the classmap in just one module,
vs just all as currently done.  While the sysfs param is unlikely to
ever update just one module, the callchain will be used for modprobe
handling, which should update only that just-probed module.

In ddebug_apply_class_bitmap(), also check for actual changes to the
bits before announcing them, to declutter logs.

No functional change.

Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 lib/dynamic_debug.c | 65 ++++++++++++++++++++++++++++-----------------
 1 file changed, 40 insertions(+), 25 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 3ae9ecabdad1..4313c8803007 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -605,9 +605,10 @@ static int ddebug_exec_queries(char *query, const char *modname)
 	return nfound;
 }
 
-/* apply a new bitmap to the sys-knob's current bit-state */
+/* apply a new class-param setting */
 static int ddebug_apply_class_bitmap(const struct ddebug_class_param *dcp,
-				     unsigned long *new_bits, unsigned long *old_bits)
+				     unsigned long *new_bits, unsigned long *old_bits,
+				     const char *query_modname)
 {
 #define QUERY_SIZE 128
 	char query[QUERY_SIZE];
@@ -615,7 +616,9 @@ static int ddebug_apply_class_bitmap(const struct ddebug_class_param *dcp,
 	int matches = 0;
 	int bi, ct;
 
-	v2pr_info("apply: 0x%lx to: 0x%lx\n", *new_bits, *old_bits);
+	if (*new_bits != *old_bits)
+		v2pr_info("apply bitmap: 0x%lx to: 0x%lx for %s\n", *new_bits,
+			  *old_bits, query_modname ?: "'*'");
 
 	for (bi = 0; bi < map->length; bi++) {
 		if (test_bit(bi, new_bits) == test_bit(bi, old_bits))
@@ -624,12 +627,16 @@ static int ddebug_apply_class_bitmap(const struct ddebug_class_param *dcp,
 		snprintf(query, QUERY_SIZE, "class %s %c%s", map->class_names[bi],
 			 test_bit(bi, new_bits) ? '+' : '-', dcp->flags);
 
-		ct = ddebug_exec_queries(query, NULL);
+		ct = ddebug_exec_queries(query, query_modname);
 		matches += ct;
 
 		v2pr_info("bit_%d: %d matches on class: %s -> 0x%lx\n", bi,
 			  ct, map->class_names[bi], *new_bits);
 	}
+	if (*new_bits != *old_bits)
+		v2pr_info("applied bitmap: 0x%lx to: 0x%lx for %s\n", *new_bits,
+			  *old_bits, query_modname ?: "'*'");
+
 	return matches;
 }
 
@@ -684,7 +691,7 @@ static int param_set_dyndbg_classnames(const char *instr, const struct kernel_pa
 				continue;
 			}
 			curr_bits ^= BIT(cls_id);
-			totct += ddebug_apply_class_bitmap(dcp, &curr_bits, dcp->bits);
+			totct += ddebug_apply_class_bitmap(dcp, &curr_bits, dcp->bits, NULL);
 			*dcp->bits = curr_bits;
 			v2pr_info("%s: changed bit %d:%s\n", KP_NAME(kp), cls_id,
 				  map->class_names[cls_id]);
@@ -694,7 +701,7 @@ static int param_set_dyndbg_classnames(const char *instr, const struct kernel_pa
 			old_bits = CLASSMAP_BITMASK(*dcp->lvl);
 			curr_bits = CLASSMAP_BITMASK(cls_id + (wanted ? 1 : 0 ));
 
-			totct += ddebug_apply_class_bitmap(dcp, &curr_bits, &old_bits);
+			totct += ddebug_apply_class_bitmap(dcp, &curr_bits, &old_bits, NULL);
 			*dcp->lvl = (cls_id + (wanted ? 1 : 0));
 			v2pr_info("%s: changed bit-%d: \"%s\" %lx->%lx\n", KP_NAME(kp), cls_id,
 				  map->class_names[cls_id], old_bits, curr_bits);
@@ -708,18 +715,9 @@ static int param_set_dyndbg_classnames(const char *instr, const struct kernel_pa
 	return 0;
 }
 
-/**
- * param_set_dyndbg_classes - class FOO >control
- * @instr: string echo>d to sysfs, input depends on map_type
- * @kp:    kp->arg has state: bits/lvl, map, map_type
- *
- * Enable/disable prdbgs by their class, as given in the arguments to
- * DECLARE_DYNDBG_CLASSMAP.  For LEVEL map-types, enforce relative
- * levels by bitpos.
- *
- * Returns: 0 or <0 if error.
- */
-int param_set_dyndbg_classes(const char *instr, const struct kernel_param *kp)
+static int param_set_dyndbg_module_classes(const char *instr,
+					   const struct kernel_param *kp,
+					   const char *mod_name)
 {
 	const struct ddebug_class_param *dcp = kp->arg;
 	const struct ddebug_class_map *map = dcp->map;
@@ -756,8 +754,8 @@ int param_set_dyndbg_classes(const char *instr, const struct kernel_param *kp)
 				KP_NAME(kp), inrep, CLASSMAP_BITMASK(map->length));
 			inrep &= CLASSMAP_BITMASK(map->length);
 		}
-		v2pr_info("bits:%lx > %s\n", inrep, KP_NAME(kp));
-		totct += ddebug_apply_class_bitmap(dcp, &inrep, dcp->bits);
+		v2pr_info("bits:0x%lx > %s.%s\n", inrep, mod_name ?: "*", KP_NAME(kp));
+		totct += ddebug_apply_class_bitmap(dcp, &inrep, dcp->bits, mod_name);
 		*dcp->bits = inrep;
 		break;
 	case DD_CLASS_TYPE_LEVEL_NUM:
@@ -770,7 +768,7 @@ int param_set_dyndbg_classes(const char *instr, const struct kernel_param *kp)
 		old_bits = CLASSMAP_BITMASK(*dcp->lvl);
 		new_bits = CLASSMAP_BITMASK(inrep);
 		v2pr_info("lvl:%ld bits:0x%lx > %s\n", inrep, new_bits, KP_NAME(kp));
-		totct += ddebug_apply_class_bitmap(dcp, &new_bits, &old_bits);
+		totct += ddebug_apply_class_bitmap(dcp, &new_bits, &old_bits, mod_name);
 		*dcp->lvl = inrep;
 		break;
 	default:
@@ -779,16 +777,33 @@ int param_set_dyndbg_classes(const char *instr, const struct kernel_param *kp)
 	vpr_info("%s: total matches: %d\n", KP_NAME(kp), totct);
 	return 0;
 }
+
+/**
+ * param_set_dyndbg_classes - classmap kparam setter
+ * @instr: string echo>d to sysfs, input depends on map_type
+ * @kp:    kp->arg has state: bits/lvl, map, map_type
+ *
+ * enable/disable all class'd pr_debugs in the classmap. For LEVEL
+ * map-types, enforce * relative levels by bitpos.
+ *
+ * Returns: 0 or <0 if error.
+ */
+int param_set_dyndbg_classes(const char *instr, const struct kernel_param *kp)
+{
+	return param_set_dyndbg_module_classes(instr, kp, NULL);
+}
 EXPORT_SYMBOL(param_set_dyndbg_classes);
 
 /**
- * param_get_dyndbg_classes - classes reader
+ * param_get_dyndbg_classes - classmap kparam getter
  * @buffer: string description of controlled bits -> classes
  * @kp:     kp->arg has state: bits, map
  *
- * Reads last written state, underlying prdbg state may have been
- * altered by direct >control.  Displays 0x for DISJOINT, 0-N for
- * LEVEL Returns: #chars written or <0 on error
+ * Reads last written state, underlying pr_debug states may have been
+ * altered by direct >control.  Displays 0x for DISJOINT classmap
+ * types, 0-N for LEVEL types.
+ *
+ * Returns: ct of chars written or <0 on error
  */
 int param_get_dyndbg_classes(char *buffer, const struct kernel_param *kp)
 {
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 13/65] dyndbg: tighten fn-sig of ddebug_apply_class_bitmap
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (11 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 12/65] dyndbg: refactor param_set_dyndbg_classes and below Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 14/65] dyndbg: replace classmap list with a vector Jim Cromie
                   ` (52 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Andrew Morton, Jim Cromie,
	linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

old_bits arg is currently a pointer to the input bits, but this could
allow inadvertent changes to the input by the fn.  Disallow this.
And constify new_bits while here.

Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 lib/dynamic_debug.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 4313c8803007..a18f4bc63473 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -607,7 +607,8 @@ static int ddebug_exec_queries(char *query, const char *modname)
 
 /* apply a new class-param setting */
 static int ddebug_apply_class_bitmap(const struct ddebug_class_param *dcp,
-				     unsigned long *new_bits, unsigned long *old_bits,
+				     const unsigned long *new_bits,
+				     const unsigned long old_bits,
 				     const char *query_modname)
 {
 #define QUERY_SIZE 128
@@ -616,12 +617,12 @@ static int ddebug_apply_class_bitmap(const struct ddebug_class_param *dcp,
 	int matches = 0;
 	int bi, ct;
 
-	if (*new_bits != *old_bits)
+	if (*new_bits != old_bits)
 		v2pr_info("apply bitmap: 0x%lx to: 0x%lx for %s\n", *new_bits,
-			  *old_bits, query_modname ?: "'*'");
+			  old_bits, query_modname ?: "'*'");
 
 	for (bi = 0; bi < map->length; bi++) {
-		if (test_bit(bi, new_bits) == test_bit(bi, old_bits))
+		if (test_bit(bi, new_bits) == test_bit(bi, &old_bits))
 			continue;
 
 		snprintf(query, QUERY_SIZE, "class %s %c%s", map->class_names[bi],
@@ -633,9 +634,9 @@ static int ddebug_apply_class_bitmap(const struct ddebug_class_param *dcp,
 		v2pr_info("bit_%d: %d matches on class: %s -> 0x%lx\n", bi,
 			  ct, map->class_names[bi], *new_bits);
 	}
-	if (*new_bits != *old_bits)
+	if (*new_bits != old_bits)
 		v2pr_info("applied bitmap: 0x%lx to: 0x%lx for %s\n", *new_bits,
-			  *old_bits, query_modname ?: "'*'");
+			  old_bits, query_modname ?: "'*'");
 
 	return matches;
 }
@@ -691,7 +692,7 @@ static int param_set_dyndbg_classnames(const char *instr, const struct kernel_pa
 				continue;
 			}
 			curr_bits ^= BIT(cls_id);
-			totct += ddebug_apply_class_bitmap(dcp, &curr_bits, dcp->bits, NULL);
+			totct += ddebug_apply_class_bitmap(dcp, &curr_bits, *dcp->bits, NULL);
 			*dcp->bits = curr_bits;
 			v2pr_info("%s: changed bit %d:%s\n", KP_NAME(kp), cls_id,
 				  map->class_names[cls_id]);
@@ -701,7 +702,7 @@ static int param_set_dyndbg_classnames(const char *instr, const struct kernel_pa
 			old_bits = CLASSMAP_BITMASK(*dcp->lvl);
 			curr_bits = CLASSMAP_BITMASK(cls_id + (wanted ? 1 : 0 ));
 
-			totct += ddebug_apply_class_bitmap(dcp, &curr_bits, &old_bits, NULL);
+			totct += ddebug_apply_class_bitmap(dcp, &curr_bits, old_bits, NULL);
 			*dcp->lvl = (cls_id + (wanted ? 1 : 0));
 			v2pr_info("%s: changed bit-%d: \"%s\" %lx->%lx\n", KP_NAME(kp), cls_id,
 				  map->class_names[cls_id], old_bits, curr_bits);
@@ -755,7 +756,7 @@ static int param_set_dyndbg_module_classes(const char *instr,
 			inrep &= CLASSMAP_BITMASK(map->length);
 		}
 		v2pr_info("bits:0x%lx > %s.%s\n", inrep, mod_name ?: "*", KP_NAME(kp));
-		totct += ddebug_apply_class_bitmap(dcp, &inrep, dcp->bits, mod_name);
+		totct += ddebug_apply_class_bitmap(dcp, &inrep, *dcp->bits, mod_name);
 		*dcp->bits = inrep;
 		break;
 	case DD_CLASS_TYPE_LEVEL_NUM:
@@ -768,7 +769,7 @@ static int param_set_dyndbg_module_classes(const char *instr,
 		old_bits = CLASSMAP_BITMASK(*dcp->lvl);
 		new_bits = CLASSMAP_BITMASK(inrep);
 		v2pr_info("lvl:%ld bits:0x%lx > %s\n", inrep, new_bits, KP_NAME(kp));
-		totct += ddebug_apply_class_bitmap(dcp, &new_bits, &old_bits, mod_name);
+		totct += ddebug_apply_class_bitmap(dcp, &new_bits, old_bits, mod_name);
 		*dcp->lvl = inrep;
 		break;
 	default:
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 14/65] dyndbg: replace classmap list with a vector
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (12 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 13/65] dyndbg: tighten fn-sig of ddebug_apply_class_bitmap Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 15/65] dyndbg: macrofy a 2-index for-loop pattern Jim Cromie
                   ` (51 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jim Cromie, Andrew Morton,
	linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

Classmaps are stored in an elf section/array, but currently are
individually list-linked onto dyndbg's per-module ddebug_table for
operation. This is unnecessary.

Just like dyndbg's descriptors, classes are packed in compile order;
so even with many builtin modules employing multiple classmaps, each
modules' maps are packed contiguously, and can be treated as a
array-start-address & array-length.

So this drops the whole list building operation done in
ddebug_attach_module_classes(), and removes the list-head members.
The "select-by-modname" condition is reused to find the start,end of
the subrange.

NOTE: This "filter-by-modname" on classmaps should really be done in
ddebug_add_module(1); ie at least one step closer to ddebug_init(2),
which already splits up pr-debug descriptors into subranges by
modname, then calls (1) on each.  (2) knows nothing of classmaps
currently, and doesn't need to.  For now, just add comment.

Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 include/linux/dynamic_debug.h |  1 -
 lib/dynamic_debug.c           | 62 ++++++++++++++++++-----------------
 2 files changed, 32 insertions(+), 31 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 92627a03b4d1..9fd36339db52 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -84,7 +84,6 @@ enum class_map_type {
 };
 
 struct ddebug_class_map {
-	struct list_head link;
 	struct module *mod;
 	const char *mod_name;	/* needed for builtins */
 	const char **class_names;
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index a18f4bc63473..94a66c8537ab 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -45,10 +45,11 @@ extern struct ddebug_class_map __start___dyndbg_classes[];
 extern struct ddebug_class_map __stop___dyndbg_classes[];
 
 struct ddebug_table {
-	struct list_head link, maps;
+	struct list_head link;
 	const char *mod_name;
-	unsigned int num_ddebugs;
 	struct _ddebug *ddebugs;
+	struct ddebug_class_map *classes;
+	unsigned int num_ddebugs, num_classes;
 };
 
 struct ddebug_query {
@@ -149,12 +150,13 @@ static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
 }
 
 static struct ddebug_class_map *ddebug_find_valid_class(struct ddebug_table const *dt,
-							  const char *class_string, int *class_id)
+							const char *class_string,
+							int *class_id)
 {
 	struct ddebug_class_map *map;
-	int idx;
+	int i, idx;
 
-	list_for_each_entry(map, &dt->maps, link) {
+	for (map = dt->classes, i = 0; i < dt->num_classes; i++, map++) {
 		idx = match_string(map->class_names, map->length, class_string);
 		if (idx >= 0) {
 			*class_id = idx + map->base;
@@ -165,7 +167,6 @@ static struct ddebug_class_map *ddebug_find_valid_class(struct ddebug_table cons
 	return NULL;
 }
 
-#define __outvar /* filled by callee */
 /*
  * Search the tables for _ddebug's which match the given `query' and
  * apply the `flags' and `mask' to them.  Returns number of matching
@@ -227,7 +228,7 @@ static int ddebug_change(const struct ddebug_query *query,
 	unsigned int nfound = 0;
 	struct flagsbuf fbuf, nbuf;
 	struct ddebug_class_map *map = NULL;
-	int __outvar valid_class;
+	int valid_class;
 
 	/* search for matching ddebugs */
 	mutex_lock(&ddebug_lock);
@@ -1134,9 +1135,10 @@ static void *ddebug_proc_next(struct seq_file *m, void *p, loff_t *pos)
 
 static const char *ddebug_class_name(struct ddebug_iter *iter, struct _ddebug *dp)
 {
-	struct ddebug_class_map *map;
+	struct ddebug_class_map *map = iter->table->classes;
+	int i, nc = iter->table->num_classes;
 
-	list_for_each_entry(map, &iter->table->maps, link)
+	for (i = 0; i < nc; i++, map++)
 		if (class_in_range(dp->class_id, map))
 			return map->class_names[dp->class_id - map->base];
 
@@ -1220,30 +1222,31 @@ static const struct proc_ops proc_fops = {
 	.proc_write = ddebug_proc_write
 };
 
-static void ddebug_attach_module_classes(struct ddebug_table *dt,
-					 struct ddebug_class_map *classes,
-					 int num_classes)
+static void ddebug_attach_module_classes(struct ddebug_table *dt, struct _ddebug_info *di)
 {
 	struct ddebug_class_map *cm;
-	int i, j, ct = 0;
+	int i, nc = 0;
 
-	for (cm = classes, i = 0; i < num_classes; i++, cm++) {
+	/*
+	 * Find this module's classmaps in a subrange/wholerange of
+	 * the builtin/modular classmap vector/section.  Save the start
+	 * and length of the subrange at its edges.
+	 */
+	for (cm = di->classes, i = 0; i < di->num_classes; i++, cm++) {
 
 		if (!strcmp(cm->mod_name, dt->mod_name)) {
-
-			v2pr_info("class[%d]: module:%s base:%d len:%d ty:%d\n", i,
-				  cm->mod_name, cm->base, cm->length, cm->map_type);
-
-			for (j = 0; j < cm->length; j++)
-				v3pr_info(" %d: %d %s\n", j + cm->base, j,
-					  cm->class_names[j]);
-
-			list_add(&cm->link, &dt->maps);
-			ct++;
+			if (!nc) {
+				v2pr_info("start subrange, class[%d]: module:%s base:%d len:%d ty:%d\n",
+					  i, cm->mod_name, cm->base, cm->length, cm->map_type);
+				dt->classes = cm;
+			}
+			nc++;
 		}
 	}
-	if (ct)
-		vpr_info("module:%s attached %d classes\n", dt->mod_name, ct);
+	if (nc) {
+		dt->num_classes = nc;
+		vpr_info("module:%s attached %d classes\n", dt->mod_name, nc);
+	}
 }
 
 /*
@@ -1275,10 +1278,9 @@ static int ddebug_add_module(struct _ddebug_info *di, const char *modname)
 	dt->num_ddebugs = di->num_descs;
 
 	INIT_LIST_HEAD(&dt->link);
-	INIT_LIST_HEAD(&dt->maps);
 
 	if (di->classes && di->num_classes)
-		ddebug_attach_module_classes(dt, di->classes, di->num_classes);
+		ddebug_attach_module_classes(dt, di);
 
 	mutex_lock(&ddebug_lock);
 	list_add_tail(&dt->link, &ddebug_tables);
@@ -1391,8 +1393,8 @@ static void ddebug_remove_all_tables(void)
 	mutex_lock(&ddebug_lock);
 	while (!list_empty(&ddebug_tables)) {
 		struct ddebug_table *dt = list_entry(ddebug_tables.next,
-						      struct ddebug_table,
-						      link);
+						     struct ddebug_table,
+						     link);
 		ddebug_table_free(dt);
 	}
 	mutex_unlock(&ddebug_lock);
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 15/65] dyndbg: macrofy a 2-index for-loop pattern
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (13 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 14/65] dyndbg: replace classmap list with a vector Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 16/65] dyndbg, module: make proper substructs in _ddebug_info Jim Cromie
                   ` (50 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jim Cromie, Andrew Morton,
	linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

dynamic-debug currently has 2 __sections (__dyndbg, __dyndb_classes),
struct _ddebug_info keeps track of them both, with 2 members each:
_vec and _vec#_len.

We need to loop over these sections, with index and record pointer,
making ref to both _vec and _vec_len.  This is already fiddly and
error-prone, and will get worse as we add a 3rd section.

Lets instead embed/abstract the fiddly-ness in the `for_subvec()`
macro, and avoid repeating it going forward.

This is a for-loop macro expander, so it syntactically expects to
precede either a single statement or a { block } of them, and the
usual typeof or do-while-0 tricks are unavailable to fix the
multiple-expansion warning.

The macro needs a lot from its caller: it needs 2 local vars, 1 of
which is a ref to a contained struct with named members.  To support
these requirements, add:

1. __ASSERT_IS_LVALUE(_X):
   ie: ((void)sizeof((void)0, &(x)))

2. __ASSERT_HAS_VEC_MEMBERS(_X, _Y):
   compile-time check that the _Y "vector" exists
   ie: _X->_Y and _X->num##_Y are lvalues.

The for_subvec() macro then invokes these before the for-loop itself;
they disappear at runtime.  They do cause a "complex macro" CHECK from
checkpatch --strict.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 lib/dynamic_debug.c | 27 ++++++++++++++++++++++++---
 1 file changed, 24 insertions(+), 3 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 94a66c8537ab..cb7bfe8729a7 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -129,6 +129,28 @@ do {								\
 #define v3pr_info(fmt, ...)	vnpr_info(3, fmt, ##__VA_ARGS__)
 #define v4pr_info(fmt, ...)	vnpr_info(4, fmt, ##__VA_ARGS__)
 
+/*
+ * simplify a repeated for-loop pattern walking N steps in a T _vec
+ * member inside a struct _box.  It expects int i and T *_sp to be
+ * declared in the caller.
+ * @_i:  caller provided counter.
+ * @_sp: cursor into _vec, to examine each item.
+ * @_box: ptr to a struct containing @_vec member
+ * @_vec: name of a member in @_box
+ */
+#define __ASSERT_IS_LVALUE(x) ((void)sizeof((void)0, &(x)))
+#define __ASSERT_HAS_VEC_MEMBER(_box, _vec) \
+	((void)sizeof((_box)->_vec + (_box)->num##_vec))
+
+#define for_subvec(_i, _sp, _box, _vec)			\
+	for (__ASSERT_IS_LVALUE(_i),			\
+		__ASSERT_IS_LVALUE(_sp),		\
+		__ASSERT_HAS_VEC_MEMBER(_box, _vec),	\
+		(_i) = 0,				\
+		(_sp) = (_box)->_vec;			\
+	     (_i) < (_box)->num##_vec;			\
+	     (_i)++, (_sp)++)		/* { block } */
+
 static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
 {
 	/* trim any trailing newlines */
@@ -156,7 +178,7 @@ static struct ddebug_class_map *ddebug_find_valid_class(struct ddebug_table cons
 	struct ddebug_class_map *map;
 	int i, idx;
 
-	for (map = dt->classes, i = 0; i < dt->num_classes; i++, map++) {
+	for_subvec(i, map, dt, classes) {
 		idx = match_string(map->class_names, map->length, class_string);
 		if (idx >= 0) {
 			*class_id = idx + map->base;
@@ -1232,8 +1254,7 @@ static void ddebug_attach_module_classes(struct ddebug_table *dt, struct _ddebug
 	 * the builtin/modular classmap vector/section.  Save the start
 	 * and length of the subrange at its edges.
 	 */
-	for (cm = di->classes, i = 0; i < di->num_classes; i++, cm++) {
-
+	for_subvec(i, cm, di, classes) {
 		if (!strcmp(cm->mod_name, dt->mod_name)) {
 			if (!nc) {
 				v2pr_info("start subrange, class[%d]: module:%s base:%d len:%d ty:%d\n",
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 16/65] dyndbg, module: make proper substructs in _ddebug_info
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (14 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 15/65] dyndbg: macrofy a 2-index for-loop pattern Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 17/65] dyndbg: hoist classmap-filter-by-modname up to ddebug_add_module Jim Cromie
                   ` (49 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Arnd Bergmann, Jim Cromie,
	Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
	Aaron Tomlin, Andrew Morton, linux-arch, linux-kernel,
	linux-modules
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

recompose struct _ddebug_info, inserting proper sub-structs.

The struct _ddebug_info has 2 pairs of _vec, num##_vec fields, for
descs and classes respectively.  for_subvec() makes walking these
vectors less cumbersome, now lets move those field pairs into their
own "vec" structs: _ddebug_descs & _ddebug_class_maps, and re-compose
struct _ddebug_info to contain them cleanly.  This also lets us rid
for_subvec() of its num##_vec paste-up.

Also recompose struct ddebug_table to contain a _ddebug_info.  This
reinforces its use as a cursor into relevant data for a builtin
module, and access to the full _ddebug state for modules.

NOTES:

Invariant: These vectors ref a contiguous subrange of __section memory
in builtin/DATA or in loadable modules via mod->dyndbg_info; with
guaranteed life-time for us.

Fixup names: Normalize all struct names to "struct _ddebug_*"
eliminating the minor/stupid variations created in classmaps-v1.
Also normalize the __section names to "__dyndbg_*".

struct module contains a _ddebug_info field and module/main.c sets it
up, so that gets adjusted rather obviously.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 include/asm-generic/vmlinux.lds.h |   4 +-
 include/linux/dynamic_debug.h     |  42 +++++++----
 kernel/module/main.c              |  12 +--
 lib/dynamic_debug.c               | 120 +++++++++++++++---------------
 lib/test_dynamic_debug.c          |   2 +-
 5 files changed, 96 insertions(+), 84 deletions(-)

diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index a2ba7e3d9994..62fc2b0e8d1c 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -385,8 +385,8 @@
 	*(__tracepoints)						\
 	/* implement dynamic printk debug */				\
 	. = ALIGN(8);							\
-	BOUNDED_SECTION_BY(__dyndbg, ___dyndbg)				\
-	BOUNDED_SECTION_BY(__dyndbg_classes, ___dyndbg_classes)		\
+	BOUNDED_SECTION_BY(__dyndbg_descriptors, ___dyndbg_descs)	\
+	BOUNDED_SECTION_BY(__dyndbg_class_maps, ___dyndbg_class_maps)	\
 	CODETAG_SECTIONS()						\
 	LIKELY_PROFILE()		       				\
 	BRANCH_PROFILE()						\
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 9fd36339db52..b84518b70a6e 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -83,30 +83,42 @@ enum class_map_type {
 	 */
 };
 
-struct ddebug_class_map {
-	struct module *mod;
-	const char *mod_name;	/* needed for builtins */
+struct _ddebug_class_map {
+	struct module *mod;	/* NULL for builtins */
+	const char *mod_name;
 	const char **class_names;
 	const int length;
 	const int base;		/* index of 1st .class_id, allows split/shared space */
 	enum class_map_type map_type;
 };
 
-/* encapsulate linker provided built-in (or module) dyndbg data */
+/*
+ * @_ddebug_info: gathers module/builtin dyndbg_* __sections together.
+ * For builtins, it is used as a cursor, with the inner structs
+ * marking sub-vectors of the builtin __sections in DATA.
+ */
+struct _ddebug_descs {
+	struct _ddebug *start;
+	int len;
+};
+
+struct _ddebug_class_maps {
+	struct _ddebug_class_map *start;
+	int len;
+};
+
 struct _ddebug_info {
-	struct _ddebug *descs;
-	struct ddebug_class_map *classes;
-	unsigned int num_descs;
-	unsigned int num_classes;
+	struct _ddebug_descs descs;
+	struct _ddebug_class_maps maps;
 };
 
-struct ddebug_class_param {
+struct _ddebug_class_param {
 	union {
 		unsigned long *bits;
 		unsigned long *lvl;
 	};
 	char flags[8];
-	const struct ddebug_class_map *map;
+	const struct _ddebug_class_map *map;
 };
 
 /*
@@ -125,8 +137,8 @@ struct ddebug_class_param {
  */
 #define DECLARE_DYNDBG_CLASSMAP(_var, _maptype, _base, ...)		\
 	static const char *_var##_classnames[] = { __VA_ARGS__ };	\
-	static struct ddebug_class_map __aligned(8) __used		\
-		__section("__dyndbg_classes") _var = {			\
+	static struct _ddebug_class_map __aligned(8) __used		\
+		__section("__dyndbg_class_maps") _var = {		\
 		.mod = THIS_MODULE,					\
 		.mod_name = KBUILD_MODNAME,				\
 		.base = _base,						\
@@ -166,7 +178,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 
 #define DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, cls, fmt)	\
 	static struct _ddebug  __aligned(8)			\
-	__section("__dyndbg") name = {				\
+	__section("__dyndbg_descriptors") name = {		\
 		.modname = KBUILD_MODNAME,			\
 		.function = __func__,				\
 		.filename = __FILE__,				\
@@ -253,7 +265,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
  * macro.
  */
 #define _dynamic_func_call_cls(cls, fmt, func, ...)			\
-	__dynamic_func_call_cls(__UNIQUE_ID(ddebug), cls, fmt, func, ##__VA_ARGS__)
+	__dynamic_func_call_cls(__UNIQUE_ID(_ddebug), cls, fmt, func, ##__VA_ARGS__)
 #define _dynamic_func_call(fmt, func, ...)				\
 	_dynamic_func_call_cls(_DPRINTK_CLASS_DFLT, fmt, func, ##__VA_ARGS__)
 
@@ -263,7 +275,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
  * with precisely the macro's varargs.
  */
 #define _dynamic_func_call_cls_no_desc(cls, fmt, func, ...)		\
-	__dynamic_func_call_cls_no_desc(__UNIQUE_ID(ddebug), cls, fmt,	\
+	__dynamic_func_call_cls_no_desc(__UNIQUE_ID(_ddebug), cls, fmt,	\
 					func, ##__VA_ARGS__)
 #define _dynamic_func_call_no_desc(fmt, func, ...)			\
 	_dynamic_func_call_cls_no_desc(_DPRINTK_CLASS_DFLT, fmt,	\
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 2bac4c7cd019..49f7b12c9776 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -2710,12 +2710,12 @@ static int find_module_sections(struct module *mod, struct load_info *info)
 		pr_warn("%s: Ignoring obsolete parameters\n", mod->name);
 
 #ifdef CONFIG_DYNAMIC_DEBUG_CORE
-	mod->dyndbg_info.descs = section_objs(info, "__dyndbg",
-					      sizeof(*mod->dyndbg_info.descs),
-					      &mod->dyndbg_info.num_descs);
-	mod->dyndbg_info.classes = section_objs(info, "__dyndbg_classes",
-						sizeof(*mod->dyndbg_info.classes),
-						&mod->dyndbg_info.num_classes);
+	mod->dyndbg_info.descs.start = section_objs(info, "__dyndbg_descriptors",
+						    sizeof(*mod->dyndbg_info.descs.start),
+						    &mod->dyndbg_info.descs.len);
+	mod->dyndbg_info.maps.start = section_objs(info, "__dyndbg_class_maps",
+						   sizeof(*mod->dyndbg_info.maps.start),
+						   &mod->dyndbg_info.maps.len);
 #endif
 
 	return 0;
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index cb7bfe8729a7..f47fdb769d7a 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -39,17 +39,15 @@
 
 #include <rdma/ib_verbs.h>
 
-extern struct _ddebug __start___dyndbg[];
-extern struct _ddebug __stop___dyndbg[];
-extern struct ddebug_class_map __start___dyndbg_classes[];
-extern struct ddebug_class_map __stop___dyndbg_classes[];
+extern struct _ddebug __start___dyndbg_descs[];
+extern struct _ddebug __stop___dyndbg_descs[];
+extern struct _ddebug_class_map __start___dyndbg_class_maps[];
+extern struct _ddebug_class_map __stop___dyndbg_class_maps[];
 
 struct ddebug_table {
 	struct list_head link;
 	const char *mod_name;
-	struct _ddebug *ddebugs;
-	struct ddebug_class_map *classes;
-	unsigned int num_ddebugs, num_classes;
+	struct _ddebug_info info;
 };
 
 struct ddebug_query {
@@ -136,19 +134,19 @@ do {								\
  * @_i:  caller provided counter.
  * @_sp: cursor into _vec, to examine each item.
  * @_box: ptr to a struct containing @_vec member
- * @_vec: name of a member in @_box
+ * @_vec: name of a vector member in @_box
  */
 #define __ASSERT_IS_LVALUE(x) ((void)sizeof((void)0, &(x)))
 #define __ASSERT_HAS_VEC_MEMBER(_box, _vec) \
-	((void)sizeof((_box)->_vec + (_box)->num##_vec))
+	((void)sizeof((_box)->_vec.start + (_box)->_vec.len))
 
 #define for_subvec(_i, _sp, _box, _vec)			\
 	for (__ASSERT_IS_LVALUE(_i),			\
 		__ASSERT_IS_LVALUE(_sp),		\
 		__ASSERT_HAS_VEC_MEMBER(_box, _vec),	\
 		(_i) = 0,				\
-		(_sp) = (_box)->_vec;			\
-	     (_i) < (_box)->num##_vec;			\
+		(_sp) = (_box)->_vec.start;		\
+	     (_i) < (_box)->_vec.len;			\
 	     (_i)++, (_sp)++)		/* { block } */
 
 static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
@@ -171,14 +169,14 @@ static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
 		  query->first_lineno, query->last_lineno, query->class_string);
 }
 
-static struct ddebug_class_map *ddebug_find_valid_class(struct ddebug_table const *dt,
+static struct _ddebug_class_map *ddebug_find_valid_class(struct ddebug_table const *dt,
 							const char *class_string,
 							int *class_id)
 {
-	struct ddebug_class_map *map;
+	struct _ddebug_class_map *map;
 	int i, idx;
 
-	for_subvec(i, map, dt, classes) {
+	for_subvec(i, map, &dt->info, maps) {
 		idx = match_string(map->class_names, map->length, class_string);
 		if (idx >= 0) {
 			*class_id = idx + map->base;
@@ -249,7 +247,7 @@ static int ddebug_change(const struct ddebug_query *query,
 	unsigned int newflags;
 	unsigned int nfound = 0;
 	struct flagsbuf fbuf, nbuf;
-	struct ddebug_class_map *map = NULL;
+	struct _ddebug_class_map *map = NULL;
 	int valid_class;
 
 	/* search for matching ddebugs */
@@ -270,8 +268,8 @@ static int ddebug_change(const struct ddebug_query *query,
 			valid_class = _DPRINTK_CLASS_DFLT;
 		}
 
-		for (i = 0; i < dt->num_ddebugs; i++) {
-			struct _ddebug *dp = &dt->ddebugs[i];
+		for (i = 0; i < dt->info.descs.len; i++) {
+			struct _ddebug *dp = &dt->info.descs.start[i];
 
 			if (!ddebug_match_desc(query, dp, valid_class))
 				continue;
@@ -629,14 +627,14 @@ static int ddebug_exec_queries(char *query, const char *modname)
 }
 
 /* apply a new class-param setting */
-static int ddebug_apply_class_bitmap(const struct ddebug_class_param *dcp,
+static int ddebug_apply_class_bitmap(const struct _ddebug_class_param *dcp,
 				     const unsigned long *new_bits,
 				     const unsigned long old_bits,
 				     const char *query_modname)
 {
 #define QUERY_SIZE 128
 	char query[QUERY_SIZE];
-	const struct ddebug_class_map *map = dcp->map;
+	const struct _ddebug_class_map *map = dcp->map;
 	int matches = 0;
 	int bi, ct;
 
@@ -672,8 +670,8 @@ static int ddebug_apply_class_bitmap(const struct ddebug_class_param *dcp,
 /* accept comma-separated-list of [+-] classnames */
 static int param_set_dyndbg_classnames(const char *instr, const struct kernel_param *kp)
 {
-	const struct ddebug_class_param *dcp = kp->arg;
-	const struct ddebug_class_map *map = dcp->map;
+	const struct _ddebug_class_param *dcp = kp->arg;
+	const struct _ddebug_class_map *map = dcp->map;
 	unsigned long curr_bits, old_bits;
 	char *cl_str, *p, *tmp;
 	int cls_id, totct = 0;
@@ -743,8 +741,8 @@ static int param_set_dyndbg_module_classes(const char *instr,
 					   const struct kernel_param *kp,
 					   const char *mod_name)
 {
-	const struct ddebug_class_param *dcp = kp->arg;
-	const struct ddebug_class_map *map = dcp->map;
+	const struct _ddebug_class_param *dcp = kp->arg;
+	const struct _ddebug_class_map *map = dcp->map;
 	unsigned long inrep, new_bits, old_bits;
 	int rc, totct = 0;
 
@@ -831,8 +829,8 @@ EXPORT_SYMBOL(param_set_dyndbg_classes);
  */
 int param_get_dyndbg_classes(char *buffer, const struct kernel_param *kp)
 {
-	const struct ddebug_class_param *dcp = kp->arg;
-	const struct ddebug_class_map *map = dcp->map;
+	const struct _ddebug_class_param *dcp = kp->arg;
+	const struct _ddebug_class_map *map = dcp->map;
 
 	switch (map->map_type) {
 
@@ -1083,8 +1081,8 @@ static struct _ddebug *ddebug_iter_first(struct ddebug_iter *iter)
 	}
 	iter->table = list_entry(ddebug_tables.next,
 				 struct ddebug_table, link);
-	iter->idx = iter->table->num_ddebugs;
-	return &iter->table->ddebugs[--iter->idx];
+	iter->idx = iter->table->info.descs.len;
+	return &iter->table->info.descs.start[--iter->idx];
 }
 
 /*
@@ -1105,10 +1103,10 @@ static struct _ddebug *ddebug_iter_next(struct ddebug_iter *iter)
 		}
 		iter->table = list_entry(iter->table->link.next,
 					 struct ddebug_table, link);
-		iter->idx = iter->table->num_ddebugs;
+		iter->idx = iter->table->info.descs.len;
 		--iter->idx;
 	}
-	return &iter->table->ddebugs[iter->idx];
+	return &iter->table->info.descs.start[iter->idx];
 }
 
 /*
@@ -1152,16 +1150,19 @@ static void *ddebug_proc_next(struct seq_file *m, void *p, loff_t *pos)
 	return dp;
 }
 
-#define class_in_range(class_id, map)					\
-	(class_id >= map->base && class_id < map->base + map->length)
+static bool ddebug_class_in_range(const int class_id, const struct _ddebug_class_map *map)
+{
+	return (class_id >= map->base &&
+		class_id < map->base + map->length);
+}
 
-static const char *ddebug_class_name(struct ddebug_iter *iter, struct _ddebug *dp)
+static const char *ddebug_class_name(struct ddebug_table *dt, struct _ddebug *dp)
 {
-	struct ddebug_class_map *map = iter->table->classes;
-	int i, nc = iter->table->num_classes;
+	struct _ddebug_class_map *map;
+	int i;
 
-	for (i = 0; i < nc; i++, map++)
-		if (class_in_range(dp->class_id, map))
+	for_subvec(i, map, &dt->info, maps)
+		if (ddebug_class_in_range(dp->class_id, map))
 			return map->class_names[dp->class_id - map->base];
 
 	return NULL;
@@ -1194,7 +1195,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
 	seq_putc(m, '"');
 
 	if (dp->class_id != _DPRINTK_CLASS_DFLT) {
-		class = ddebug_class_name(iter, dp);
+		class = ddebug_class_name(iter->table, dp);
 		if (class)
 			seq_printf(m, " class:%s", class);
 		else
@@ -1246,7 +1247,7 @@ static const struct proc_ops proc_fops = {
 
 static void ddebug_attach_module_classes(struct ddebug_table *dt, struct _ddebug_info *di)
 {
-	struct ddebug_class_map *cm;
+	struct _ddebug_class_map *cm;
 	int i, nc = 0;
 
 	/*
@@ -1254,18 +1255,18 @@ static void ddebug_attach_module_classes(struct ddebug_table *dt, struct _ddebug
 	 * the builtin/modular classmap vector/section.  Save the start
 	 * and length of the subrange at its edges.
 	 */
-	for_subvec(i, cm, di, classes) {
+	for_subvec(i, cm, di, maps) {
 		if (!strcmp(cm->mod_name, dt->mod_name)) {
 			if (!nc) {
 				v2pr_info("start subrange, class[%d]: module:%s base:%d len:%d ty:%d\n",
 					  i, cm->mod_name, cm->base, cm->length, cm->map_type);
-				dt->classes = cm;
+				dt->info.maps.start = cm;
 			}
 			nc++;
 		}
 	}
 	if (nc) {
-		dt->num_classes = nc;
+		dt->info.maps.len = nc;
 		vpr_info("module:%s attached %d classes\n", dt->mod_name, nc);
 	}
 }
@@ -1278,10 +1279,10 @@ static int ddebug_add_module(struct _ddebug_info *di, const char *modname)
 {
 	struct ddebug_table *dt;
 
-	if (!di->num_descs)
+	if (!di->descs.len)
 		return 0;
 
-	v3pr_info("add-module: %s %d sites\n", modname, di->num_descs);
+	v3pr_info("add-module: %s %d sites\n", modname, di->descs.len);
 
 	dt = kzalloc_obj(*dt);
 	if (dt == NULL) {
@@ -1295,19 +1296,18 @@ static int ddebug_add_module(struct _ddebug_info *di, const char *modname)
 	 * this struct ddebug_table.
 	 */
 	dt->mod_name = modname;
-	dt->ddebugs = di->descs;
-	dt->num_ddebugs = di->num_descs;
+	dt->info = *di;
 
 	INIT_LIST_HEAD(&dt->link);
 
-	if (di->classes && di->num_classes)
+	if (di->maps.len)
 		ddebug_attach_module_classes(dt, di);
 
 	mutex_lock(&ddebug_lock);
 	list_add_tail(&dt->link, &ddebug_tables);
 	mutex_unlock(&ddebug_lock);
 
-	vpr_info("%3u debug prints in module %s\n", di->num_descs, modname);
+	vpr_info("%3u debug prints in module %s\n", di->descs.len, modname);
 	return 0;
 }
 
@@ -1454,10 +1454,10 @@ static int __init dynamic_debug_init(void)
 	char *cmdline;
 
 	struct _ddebug_info di = {
-		.descs = __start___dyndbg,
-		.classes = __start___dyndbg_classes,
-		.num_descs = __stop___dyndbg - __start___dyndbg,
-		.num_classes = __stop___dyndbg_classes - __start___dyndbg_classes,
+		.descs.start = __start___dyndbg_descs,
+		.maps.start  = __start___dyndbg_class_maps,
+		.descs.len = __stop___dyndbg_descs - __start___dyndbg_descs,
+		.maps.len  = __stop___dyndbg_class_maps - __start___dyndbg_class_maps,
 	};
 
 #ifdef CONFIG_MODULES
@@ -1468,7 +1468,7 @@ static int __init dynamic_debug_init(void)
 	}
 #endif /* CONFIG_MODULES */
 
-	if (&__start___dyndbg == &__stop___dyndbg) {
+	if (&__start___dyndbg_descs == &__stop___dyndbg_descs) {
 		if (IS_ENABLED(CONFIG_DYNAMIC_DEBUG)) {
 			pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build\n");
 			return 1;
@@ -1478,16 +1478,16 @@ static int __init dynamic_debug_init(void)
 		return 0;
 	}
 
-	iter = iter_mod_start = __start___dyndbg;
+	iter = iter_mod_start = __start___dyndbg_descs;
 	modname = iter->modname;
 	i = mod_sites = mod_ct = 0;
 
-	for (; iter < __stop___dyndbg; iter++, i++, mod_sites++) {
+	for (; iter < __stop___dyndbg_descs; iter++, i++, mod_sites++) {
 
 		if (strcmp(modname, iter->modname)) {
 			mod_ct++;
-			di.num_descs = mod_sites;
-			di.descs = iter_mod_start;
+			di.descs.len = mod_sites;
+			di.descs.start = iter_mod_start;
 			ret = ddebug_add_module(&di, modname);
 			if (ret)
 				goto out_err;
@@ -1497,8 +1497,8 @@ static int __init dynamic_debug_init(void)
 			iter_mod_start = iter;
 		}
 	}
-	di.num_descs = mod_sites;
-	di.descs = iter_mod_start;
+	di.descs.len = mod_sites;
+	di.descs.start = iter_mod_start;
 	ret = ddebug_add_module(&di, modname);
 	if (ret)
 		goto out_err;
@@ -1508,8 +1508,8 @@ static int __init dynamic_debug_init(void)
 		 i, mod_ct, (int)((mod_ct * sizeof(struct ddebug_table)) >> 10),
 		 (int)((i * sizeof(struct _ddebug)) >> 10));
 
-	if (di.num_classes)
-		v2pr_info("  %d builtin ddebug class-maps\n", di.num_classes);
+	if (di.maps.len)
+		v2pr_info("  %d builtin ddebug class-maps\n", di.maps.len);
 
 	/* now that ddebug tables are loaded, process all boot args
 	 * again to find and activate queries given in dyndbg params.
diff --git a/lib/test_dynamic_debug.c b/lib/test_dynamic_debug.c
index 396144cf351b..8434f70b51bb 100644
--- a/lib/test_dynamic_debug.c
+++ b/lib/test_dynamic_debug.c
@@ -41,7 +41,7 @@ module_param_cb(do_prints, &param_ops_do_prints, NULL, 0600);
  */
 #define DD_SYS_WRAP(_model, _flags)					\
 	static unsigned long bits_##_model;				\
-	static struct ddebug_class_param _flags##_model = {		\
+	static struct _ddebug_class_param _flags##_model = {		\
 		.bits = &bits_##_model,					\
 		.flags = #_flags,					\
 		.map = &map_##_model,					\
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 17/65] dyndbg: hoist classmap-filter-by-modname up to ddebug_add_module
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (15 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 16/65] dyndbg, module: make proper substructs in _ddebug_info Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 18/65] dyndbg: move mod_name down from struct ddebug_table to _ddebug_info Jim Cromie
                   ` (48 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Andrew Morton, Jim Cromie,
	linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

The body of ddebug_attach_module_classes() is dominated by a
code-block that finds the contiguous subrange of classmaps matching on
modname, and saves it into the ddebug_table's info record.

Implement this block in a macro to accommodate different component
vectors in the "box" (as named in the for_subvec macro).  We will
reuse this macro shortly.

And hoist its invocation out of ddebug_attach_module_classes() up into
ddebug_add_module().  This moves the filtering step up closer to
dynamic_debug_init(), which already segments the builtin pr_debug
descriptors on their mod_name boundaries.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
reordered params to match kdoc
---
 lib/dynamic_debug.c | 57 ++++++++++++++++++++++++++-------------------
 1 file changed, 33 insertions(+), 24 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index f47fdb769d7a..df7223532cf5 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -170,8 +170,8 @@ static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
 }
 
 static struct _ddebug_class_map *ddebug_find_valid_class(struct ddebug_table const *dt,
-							const char *class_string,
-							int *class_id)
+							 const char *class_string,
+							 int *class_id)
 {
 	struct _ddebug_class_map *map;
 	int i, idx;
@@ -1247,30 +1247,35 @@ static const struct proc_ops proc_fops = {
 
 static void ddebug_attach_module_classes(struct ddebug_table *dt, struct _ddebug_info *di)
 {
-	struct _ddebug_class_map *cm;
-	int i, nc = 0;
-
-	/*
-	 * Find this module's classmaps in a subrange/wholerange of
-	 * the builtin/modular classmap vector/section.  Save the start
-	 * and length of the subrange at its edges.
-	 */
-	for_subvec(i, cm, di, maps) {
-		if (!strcmp(cm->mod_name, dt->mod_name)) {
-			if (!nc) {
-				v2pr_info("start subrange, class[%d]: module:%s base:%d len:%d ty:%d\n",
-					  i, cm->mod_name, cm->base, cm->length, cm->map_type);
-				dt->info.maps.start = cm;
-			}
-			nc++;
-		}
-	}
-	if (nc) {
-		dt->info.maps.len = nc;
-		vpr_info("module:%s attached %d classes\n", dt->mod_name, nc);
-	}
+	vpr_info("module:%s attached %d classes\n", dt->mod_name, dt->info.maps.len);
 }
 
+/*
+ * Walk the @_box->@_vec member, over @_vec.start[0..len], and find
+ * the contiguous subrange of elements matching on ->mod_name.  Copy
+ * the subrange into @_dst.  This depends on vars defd by caller.
+ *
+ * @_i:   caller provided counter var, init'd by macro
+ * @_sp:  cursor into @_vec.
+ * @_box: contains member named @_vec
+ * @_vec: member-name of a type with: .start .len fields.
+ * @_dst: an array-ref: to remember the module's subrange
+ */
+#define dd_mark_vector_subrange(_i, _sp, _box, _vec, _dst) ({		\
+	typeof(_dst) __dst = (_dst);					\
+	int __nc = 0;							\
+	for_subvec(_i, _sp, _box, _vec) {				\
+		if (!strcmp((_sp)->mod_name, (_dst)->mod_name)) {	\
+			if (!__nc++)					\
+				(__dst)->info._vec.start = (_sp);	\
+		} else {						\
+			if (__nc)					\
+				break; /* end of consecutive matches */ \
+		}							\
+	}								\
+	(__dst)->info._vec.len = __nc;					\
+})
+
 /*
  * Allocate a new ddebug_table for the given module
  * and add it to the global list.
@@ -1278,6 +1283,8 @@ static void ddebug_attach_module_classes(struct ddebug_table *dt, struct _ddebug
 static int ddebug_add_module(struct _ddebug_info *di, const char *modname)
 {
 	struct ddebug_table *dt;
+	struct _ddebug_class_map *cm;
+	int i;
 
 	if (!di->descs.len)
 		return 0;
@@ -1300,6 +1307,8 @@ static int ddebug_add_module(struct _ddebug_info *di, const char *modname)
 
 	INIT_LIST_HEAD(&dt->link);
 
+	dd_mark_vector_subrange(i, cm, di, maps, dt);
+
 	if (di->maps.len)
 		ddebug_attach_module_classes(dt, di);
 
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 18/65] dyndbg: move mod_name down from struct ddebug_table to _ddebug_info
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (16 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 17/65] dyndbg: hoist classmap-filter-by-modname up to ddebug_add_module Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 19/65] dyndbg-API: remove DD_CLASS_TYPE_(DISJOINT|LEVEL)_NAMES and code Jim Cromie
                   ` (47 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jim Cromie, Andrew Morton,
	linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

struct _ddebug_info already has most of dyndbg's info for a module;
push debug_table.mod_name down into it, finishing the encapsulation.

This allows refactoring several callchains, passing &_ddebug_info
instead of &ddebug_table, and hoisting the "&dt->info" deref up
instead of repeating it thru the callchans

ddebug_table contains a _ddebug_info member, so its users keep access
to mod_name, just now with "->info." added in.

In static ddebug_add_module(&di), reinforce the cursor-model by
dropping the modname arg, and setting di->mod_name at each caller.

Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 include/linux/dynamic_debug.h |  1 +
 lib/dynamic_debug.c           | 50 ++++++++++++++++++-----------------
 2 files changed, 27 insertions(+), 24 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index b84518b70a6e..34dbca0beaf8 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -108,6 +108,7 @@ struct _ddebug_class_maps {
 };
 
 struct _ddebug_info {
+	const char *mod_name;
 	struct _ddebug_descs descs;
 	struct _ddebug_class_maps maps;
 };
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index df7223532cf5..34297f658bc8 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -46,7 +46,6 @@ extern struct _ddebug_class_map __stop___dyndbg_class_maps[];
 
 struct ddebug_table {
 	struct list_head link;
-	const char *mod_name;
 	struct _ddebug_info info;
 };
 
@@ -253,10 +252,11 @@ static int ddebug_change(const struct ddebug_query *query,
 	/* search for matching ddebugs */
 	mutex_lock(&ddebug_lock);
 	list_for_each_entry(dt, &ddebug_tables, link) {
+		struct _ddebug_info *di = &dt->info;
 
 		/* match against the module name */
 		if (query->module &&
-		    !match_wildcard(query->module, dt->mod_name))
+		    !match_wildcard(query->module, di->mod_name))
 			continue;
 
 		if (query->class_string) {
@@ -268,8 +268,8 @@ static int ddebug_change(const struct ddebug_query *query,
 			valid_class = _DPRINTK_CLASS_DFLT;
 		}
 
-		for (i = 0; i < dt->info.descs.len; i++) {
-			struct _ddebug *dp = &dt->info.descs.start[i];
+		for (i = 0; i < di->descs.len; i++) {
+			struct _ddebug *dp = &di->descs.start[i];
 
 			if (!ddebug_match_desc(query, dp, valid_class))
 				continue;
@@ -289,7 +289,7 @@ static int ddebug_change(const struct ddebug_query *query,
 #endif
 			v4pr_info("changed %s:%d [%s]%s %s => %s\n",
 				  trim_prefix(dp->filename), dp->lineno,
-				  dt->mod_name, dp->function,
+				  di->mod_name, dp->function,
 				  ddebug_describe_flags(dp->flags, &fbuf),
 				  ddebug_describe_flags(newflags, &nbuf));
 			dp->flags = newflags;
@@ -1156,12 +1156,12 @@ static bool ddebug_class_in_range(const int class_id, const struct _ddebug_class
 		class_id < map->base + map->length);
 }
 
-static const char *ddebug_class_name(struct ddebug_table *dt, struct _ddebug *dp)
+static const char *ddebug_class_name(struct _ddebug_info *di, struct _ddebug *dp)
 {
 	struct _ddebug_class_map *map;
 	int i;
 
-	for_subvec(i, map, &dt->info, maps)
+	for_subvec(i, map, di, maps)
 		if (ddebug_class_in_range(dp->class_id, map))
 			return map->class_names[dp->class_id - map->base];
 
@@ -1189,13 +1189,13 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
 
 	seq_printf(m, "%s:%u [%s]%s =%s \"",
 		   trim_prefix(dp->filename), dp->lineno,
-		   iter->table->mod_name, dp->function,
+		   iter->table->info.mod_name, dp->function,
 		   ddebug_describe_flags(dp->flags, &flags));
 	seq_escape_str(m, dp->format, ESCAPE_SPACE, "\t\r\n\"");
 	seq_putc(m, '"');
 
 	if (dp->class_id != _DPRINTK_CLASS_DFLT) {
-		class = ddebug_class_name(iter->table, dp);
+		class = ddebug_class_name(&iter->table->info, dp);
 		if (class)
 			seq_printf(m, " class:%s", class);
 		else
@@ -1247,7 +1247,7 @@ static const struct proc_ops proc_fops = {
 
 static void ddebug_attach_module_classes(struct ddebug_table *dt, struct _ddebug_info *di)
 {
-	vpr_info("module:%s attached %d classes\n", dt->mod_name, dt->info.maps.len);
+	vpr_info("module:%s attached %d classes\n", dt->info.mod_name, dt->info.maps.len);
 }
 
 /*
@@ -1265,7 +1265,7 @@ static void ddebug_attach_module_classes(struct ddebug_table *dt, struct _ddebug
 	typeof(_dst) __dst = (_dst);					\
 	int __nc = 0;							\
 	for_subvec(_i, _sp, _box, _vec) {				\
-		if (!strcmp((_sp)->mod_name, (_dst)->mod_name)) {	\
+		if (!strcmp((_sp)->mod_name, (__dst)->info.mod_name)) {	\
 			if (!__nc++)					\
 				(__dst)->info._vec.start = (_sp);	\
 		} else {						\
@@ -1280,7 +1280,7 @@ static void ddebug_attach_module_classes(struct ddebug_table *dt, struct _ddebug
  * Allocate a new ddebug_table for the given module
  * and add it to the global list.
  */
-static int ddebug_add_module(struct _ddebug_info *di, const char *modname)
+static int ddebug_add_module(struct _ddebug_info *di)
 {
 	struct ddebug_table *dt;
 	struct _ddebug_class_map *cm;
@@ -1289,20 +1289,19 @@ static int ddebug_add_module(struct _ddebug_info *di, const char *modname)
 	if (!di->descs.len)
 		return 0;
 
-	v3pr_info("add-module: %s %d sites\n", modname, di->descs.len);
+	v3pr_info("add-module: %s %d sites\n", di->mod_name, di->descs.len);
 
 	dt = kzalloc_obj(*dt);
 	if (dt == NULL) {
-		pr_err("error adding module: %s\n", modname);
+		pr_err("error adding module: %s\n", di->mod_name);
 		return -ENOMEM;
 	}
 	/*
-	 * For built-in modules, name lives in .rodata and is
-	 * immortal. For loaded modules, name points at the name[]
-	 * member of struct module, which lives at least as long as
-	 * this struct ddebug_table.
+	 * For built-in modules, name (as supplied in di by its
+	 * callers) lives in .rodata and is immortal. For loaded
+	 * modules, name points at the name[] member of struct module,
+	 * which lives at least as long as this struct ddebug_table.
 	 */
-	dt->mod_name = modname;
 	dt->info = *di;
 
 	INIT_LIST_HEAD(&dt->link);
@@ -1316,7 +1315,7 @@ static int ddebug_add_module(struct _ddebug_info *di, const char *modname)
 	list_add_tail(&dt->link, &ddebug_tables);
 	mutex_unlock(&ddebug_lock);
 
-	vpr_info("%3u debug prints in module %s\n", di->descs.len, modname);
+	vpr_info("%3u debug prints in module %s\n", di->descs.len, di->mod_name);
 	return 0;
 }
 
@@ -1379,7 +1378,7 @@ static int ddebug_remove_module(const char *mod_name)
 
 	mutex_lock(&ddebug_lock);
 	list_for_each_entry_safe(dt, nextdt, &ddebug_tables, link) {
-		if (dt->mod_name == mod_name) {
+		if (dt->info.mod_name == mod_name) {
 			ddebug_table_free(dt);
 			ret = 0;
 			break;
@@ -1399,7 +1398,8 @@ static int ddebug_module_notify(struct notifier_block *self, unsigned long val,
 
 	switch (val) {
 	case MODULE_STATE_COMING:
-		ret = ddebug_add_module(&mod->dyndbg_info, mod->name);
+		mod->dyndbg_info.mod_name = mod->name;
+		ret = ddebug_add_module(&mod->dyndbg_info);
 		if (ret)
 			WARN(1, "Failed to allocate memory: dyndbg may not work properly.\n");
 		break;
@@ -1497,7 +1497,8 @@ static int __init dynamic_debug_init(void)
 			mod_ct++;
 			di.descs.len = mod_sites;
 			di.descs.start = iter_mod_start;
-			ret = ddebug_add_module(&di, modname);
+			di.mod_name = modname;
+			ret = ddebug_add_module(&di);
 			if (ret)
 				goto out_err;
 
@@ -1508,7 +1509,8 @@ static int __init dynamic_debug_init(void)
 	}
 	di.descs.len = mod_sites;
 	di.descs.start = iter_mod_start;
-	ret = ddebug_add_module(&di, modname);
+	di.mod_name = modname;
+	ret = ddebug_add_module(&di);
 	if (ret)
 		goto out_err;
 
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 19/65] dyndbg-API: remove DD_CLASS_TYPE_(DISJOINT|LEVEL)_NAMES and code
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (17 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 18/65] dyndbg: move mod_name down from struct ddebug_table to _ddebug_info Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 20/65] selftests-dyndbg: add a dynamic_debug run_tests target Jim Cromie
                   ` (46 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jim Cromie, Andrew Morton,
	linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

Remove the DD_CLASS_TYPE_*_NAMES classmap types and code.

These 2 classmap types accept class names at the PARAM interface, for
example:

  echo +DRM_UT_CORE,-DRM_UT_KMS > /sys/module/drm/parameters/debug_names

The code works, but its only used by test-dynamic-debug, and wasn't
asked for by anyone else, so reduce LOC & test-surface; simplify things.

Also rename enum class_map_type to enum ddebug_class_map_type.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 include/linux/dynamic_debug.h |  23 ++------
 lib/dynamic_debug.c           | 102 +++-------------------------------
 lib/test_dynamic_debug.c      |  26 ---------
 3 files changed, 14 insertions(+), 137 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 34dbca0beaf8..b6198ecc854d 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -59,27 +59,16 @@ struct _ddebug {
 #endif
 } __attribute__((aligned(8)));
 
-enum class_map_type {
+enum ddebug_class_map_type {
 	DD_CLASS_TYPE_DISJOINT_BITS,
 	/**
-	 * DD_CLASS_TYPE_DISJOINT_BITS: classes are independent, one per bit.
-	 * expecting hex input. Built for drm.debug, basis for other types.
+	 * DD_CLASS_TYPE_DISJOINT_BITS: classes are independent, mapped to bits[0..N].
+	 * Expects hex input. Built for drm.debug, basis for other types.
 	 */
 	DD_CLASS_TYPE_LEVEL_NUM,
 	/**
-	 * DD_CLASS_TYPE_LEVEL_NUM: input is numeric level, 0-N.
-	 * N turns on just bits N-1 .. 0, so N=0 turns all bits off.
-	 */
-	DD_CLASS_TYPE_DISJOINT_NAMES,
-	/**
-	 * DD_CLASS_TYPE_DISJOINT_NAMES: input is a CSV of [+-]CLASS_NAMES,
-	 * classes are independent, like _DISJOINT_BITS.
-	 */
-	DD_CLASS_TYPE_LEVEL_NAMES,
-	/**
-	 * DD_CLASS_TYPE_LEVEL_NAMES: input is a CSV of [+-]CLASS_NAMES,
-	 * intended for names like: INFO,DEBUG,TRACE, with a module prefix
-	 * avoid EMERG,ALERT,CRIT,ERR,WARNING: they're not debug
+	 * DD_CLASS_TYPE_LEVEL_NUM: input is numeric level, 0..N.
+	 * Input N turns on bits 0..N-1
 	 */
 };
 
@@ -89,7 +78,7 @@ struct _ddebug_class_map {
 	const char **class_names;
 	const int length;
 	const int base;		/* index of 1st .class_id, allows split/shared space */
-	enum class_map_type map_type;
+	enum ddebug_class_map_type map_type;
 };
 
 /*
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 34297f658bc8..e8ffc2b5b330 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -667,76 +667,6 @@ static int ddebug_apply_class_bitmap(const struct _ddebug_class_param *dcp,
 
 #define CLASSMAP_BITMASK(width) ((1UL << (width)) - 1)
 
-/* accept comma-separated-list of [+-] classnames */
-static int param_set_dyndbg_classnames(const char *instr, const struct kernel_param *kp)
-{
-	const struct _ddebug_class_param *dcp = kp->arg;
-	const struct _ddebug_class_map *map = dcp->map;
-	unsigned long curr_bits, old_bits;
-	char *cl_str, *p, *tmp;
-	int cls_id, totct = 0;
-	bool wanted;
-
-	cl_str = tmp = kstrdup_and_replace(instr, '\n', '\0', GFP_KERNEL);
-	if (!tmp)
-		return -ENOMEM;
-
-	/* start with previously set state-bits, then modify */
-	curr_bits = old_bits = *dcp->bits;
-	vpr_info("\"%s\" > %s:0x%lx\n", cl_str, KP_NAME(kp), curr_bits);
-
-	for (; cl_str; cl_str = p) {
-		p = strchr(cl_str, ',');
-		if (p)
-			*p++ = '\0';
-
-		if (*cl_str == '-') {
-			wanted = false;
-			cl_str++;
-		} else {
-			wanted = true;
-			if (*cl_str == '+')
-				cl_str++;
-		}
-		cls_id = match_string(map->class_names, map->length, cl_str);
-		if (cls_id < 0) {
-			pr_err("%s unknown to %s\n", cl_str, KP_NAME(kp));
-			continue;
-		}
-
-		/* have one or more valid class_ids of one *_NAMES type */
-		switch (map->map_type) {
-		case DD_CLASS_TYPE_DISJOINT_NAMES:
-			/* the +/- pertains to a single bit */
-			if (test_bit(cls_id, &curr_bits) == wanted) {
-				v3pr_info("no change on %s\n", cl_str);
-				continue;
-			}
-			curr_bits ^= BIT(cls_id);
-			totct += ddebug_apply_class_bitmap(dcp, &curr_bits, *dcp->bits, NULL);
-			*dcp->bits = curr_bits;
-			v2pr_info("%s: changed bit %d:%s\n", KP_NAME(kp), cls_id,
-				  map->class_names[cls_id]);
-			break;
-		case DD_CLASS_TYPE_LEVEL_NAMES:
-			/* cls_id = N in 0..max. wanted +/- determines N or N-1 */
-			old_bits = CLASSMAP_BITMASK(*dcp->lvl);
-			curr_bits = CLASSMAP_BITMASK(cls_id + (wanted ? 1 : 0 ));
-
-			totct += ddebug_apply_class_bitmap(dcp, &curr_bits, old_bits, NULL);
-			*dcp->lvl = (cls_id + (wanted ? 1 : 0));
-			v2pr_info("%s: changed bit-%d: \"%s\" %lx->%lx\n", KP_NAME(kp), cls_id,
-				  map->class_names[cls_id], old_bits, curr_bits);
-			break;
-		default:
-			pr_err("illegal map-type value %d\n", map->map_type);
-		}
-	}
-	kfree(tmp);
-	vpr_info("total matches: %d\n", totct);
-	return 0;
-}
-
 static int param_set_dyndbg_module_classes(const char *instr,
 					   const struct kernel_param *kp,
 					   const char *mod_name)
@@ -745,29 +675,17 @@ static int param_set_dyndbg_module_classes(const char *instr,
 	const struct _ddebug_class_map *map = dcp->map;
 	unsigned long inrep, new_bits, old_bits;
 	int rc, totct = 0;
-
-	switch (map->map_type) {
-
-	case DD_CLASS_TYPE_DISJOINT_NAMES:
-	case DD_CLASS_TYPE_LEVEL_NAMES:
-		/* handle [+-]classnames list separately, we are done here */
-		return param_set_dyndbg_classnames(instr, kp);
-
-	case DD_CLASS_TYPE_DISJOINT_BITS:
-	case DD_CLASS_TYPE_LEVEL_NUM:
-		/* numeric input, accept and fall-thru */
-		rc = kstrtoul(instr, 0, &inrep);
-		if (rc) {
-			pr_err("expecting numeric input: %s > %s\n", instr, KP_NAME(kp));
-			return -EINVAL;
-		}
-		break;
-	default:
-		pr_err("%s: bad map type: %d\n", KP_NAME(kp), map->map_type);
+	char *nl;
+
+	rc = kstrtoul(instr, 0, &inrep);
+	if (rc) {
+		nl = strchr(instr, '\n');
+		if (nl)
+			*nl = '\0';
+		pr_err("expecting numeric input, not: %s > %s\n", instr, KP_NAME(kp));
 		return -EINVAL;
 	}
 
-	/* only _BITS,_NUM (numeric) map-types get here */
 	switch (map->map_type) {
 	case DD_CLASS_TYPE_DISJOINT_BITS:
 		/* expect bits. mask and warn if too many */
@@ -833,12 +751,8 @@ int param_get_dyndbg_classes(char *buffer, const struct kernel_param *kp)
 	const struct _ddebug_class_map *map = dcp->map;
 
 	switch (map->map_type) {
-
-	case DD_CLASS_TYPE_DISJOINT_NAMES:
 	case DD_CLASS_TYPE_DISJOINT_BITS:
 		return scnprintf(buffer, PAGE_SIZE, "0x%lx\n", *dcp->bits);
-
-	case DD_CLASS_TYPE_LEVEL_NAMES:
 	case DD_CLASS_TYPE_LEVEL_NUM:
 		return scnprintf(buffer, PAGE_SIZE, "%ld\n", *dcp->lvl);
 	default:
diff --git a/lib/test_dynamic_debug.c b/lib/test_dynamic_debug.c
index 8434f70b51bb..9c3e53cd26bd 100644
--- a/lib/test_dynamic_debug.c
+++ b/lib/test_dynamic_debug.c
@@ -74,13 +74,6 @@ DECLARE_DYNDBG_CLASSMAP(map_disjoint_bits, DD_CLASS_TYPE_DISJOINT_BITS, 0,
 DD_SYS_WRAP(disjoint_bits, p);
 DD_SYS_WRAP(disjoint_bits, T);
 
-/* symbolic input, independent bits */
-enum cat_disjoint_names { LOW = 10, MID, HI };
-DECLARE_DYNDBG_CLASSMAP(map_disjoint_names, DD_CLASS_TYPE_DISJOINT_NAMES, 10,
-			"LOW", "MID", "HI");
-DD_SYS_WRAP(disjoint_names, p);
-DD_SYS_WRAP(disjoint_names, T);
-
 /* numeric verbosity, V2 > V1 related */
 enum cat_level_num { V0 = 14, V1, V2, V3, V4, V5, V6, V7 };
 DECLARE_DYNDBG_CLASSMAP(map_level_num, DD_CLASS_TYPE_LEVEL_NUM, 14,
@@ -88,13 +81,6 @@ DECLARE_DYNDBG_CLASSMAP(map_level_num, DD_CLASS_TYPE_LEVEL_NUM, 14,
 DD_SYS_WRAP(level_num, p);
 DD_SYS_WRAP(level_num, T);
 
-/* symbolic verbosity */
-enum cat_level_names { L0 = 22, L1, L2, L3, L4, L5, L6, L7 };
-DECLARE_DYNDBG_CLASSMAP(map_level_names, DD_CLASS_TYPE_LEVEL_NAMES, 22,
-			"L0", "L1", "L2", "L3", "L4", "L5", "L6", "L7");
-DD_SYS_WRAP(level_names, p);
-DD_SYS_WRAP(level_names, T);
-
 /* stand-in for all pr_debug etc */
 #define prdbg(SYM) __pr_debug_cls(SYM, #SYM " msg\n")
 
@@ -102,10 +88,6 @@ static void do_cats(void)
 {
 	pr_debug("doing categories\n");
 
-	prdbg(LOW);
-	prdbg(MID);
-	prdbg(HI);
-
 	prdbg(D2_CORE);
 	prdbg(D2_DRIVER);
 	prdbg(D2_KMS);
@@ -129,14 +111,6 @@ static void do_levels(void)
 	prdbg(V5);
 	prdbg(V6);
 	prdbg(V7);
-
-	prdbg(L1);
-	prdbg(L2);
-	prdbg(L3);
-	prdbg(L4);
-	prdbg(L5);
-	prdbg(L6);
-	prdbg(L7);
 }
 
 static void do_prints(void)
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 20/65] selftests-dyndbg: add a dynamic_debug run_tests target
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (18 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 19/65] dyndbg-API: remove DD_CLASS_TYPE_(DISJOINT|LEVEL)_NAMES and code Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 21/65] dyndbg: change __dynamic_func_call_cls* macros into expressions Jim Cromie
                   ` (45 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Shuah Khan, Jim Cromie,
	linux-kernel, linux-kselftest
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

Add a selftest script for dynamic-debug.  The config requires
CONFIG_TEST_DYNAMIC_DEBUG=m and CONFIG_TEST_DYNAMIC_DEBUG_SUBMOD=m,
which tacitly requires either CONFIG_DYNAMIC_DEBUG=y or
CONFIG_DYNAMIC_DEBUG_CORE=y

ATM this has just basic_tests(), which modify pr_debug() flags in the
builtin params module.  This means they're available to manipulate and
observe the effects in "cat control".

This is backported from another feature branch; the support-fns (thx
Lukas) have unused features at the moment, they'll get used shortly.

The script enables simple virtme-ng testing:

   [jimc@gandalf b0-ftrace]$ vrun_t
   virtme-ng 1.32+115.g07b109d
   doing: vng --name v6.14-rc4-60-gd5f48427de0c \
	  --user root -v -p 4 -a dynamic_debug.verbose=3 V=1 \
	  -- ../tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh
   virtme: waiting for virtiofsd to start
   ..

And add dynamic_debug to TARGETS, so `make run_tests` sees it properly
For the impatient, set TARGETS explicitly:

  [root@v6 selftests]# make TARGETS=dynamic_debug run_tests
  make[1]: Nothing to be done for 'all'.
  TAP version 13
  1..1
  # timeout set to 45
  # selftests: dynamic_debug: dyndbg_selftest.sh
  # # BASIC_TESTS    95.422122] dyndbg: query 0: 0"=_" mod:*
  ...

NOTES

check KCONFIG_CONFIG to avoid silly fails

Several tests are dependent upon config choices. Lets avoid failing
where that is noise.

The KCONFIG_CONFIG var exists to convey the config-file around.  If
the var names a file, read it and extract the relevant CONFIG items,
and use them to skip the dependent tests, thus avoiding the fails that
would follow, and the disruption to whatever CI is running these
selftests.

If the envar doesn't name a config-file, ".config" is assumed.

CONFIG_DYNAMIC_DEBUG=y:

basic-tests() and comma-terminator-tests() test for the presence of
the builtin pr_debugs in module/main.c, which I deemed stable and
therefore safe to count.  That said, the test fails if only
CONFIG_DYNAMIC_DEBUG_CORE=y is set.  It could be rewritten to test
against test-dynamic-debug.ko, but that just trades one config
dependence for another.

CONFIG_TEST_DYNAMIC_DEBUG=m

As written, test_percent_splitting() modprobes test_dynamic_debug,
enables several classes, and counts them.  It could be re-written to
work for the builtin module also, but builtin test modules are not a
common or desirable build/config.

Co-developed-by: Łukasz Bartosik <ukaszb@chromium.org>
Signed-off-by: Łukasz Bartosik <ukaszb@chromium.org>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 MAINTAINERS                                   |   1 +
 tools/testing/selftests/Makefile              |   1 +
 .../testing/selftests/dynamic_debug/Makefile  |   9 +
 tools/testing/selftests/dynamic_debug/config  |   7 +
 .../dynamic_debug/dyndbg_selftest.sh          | 257 ++++++++++++++++++
 5 files changed, 275 insertions(+)
 create mode 100644 tools/testing/selftests/dynamic_debug/Makefile
 create mode 100644 tools/testing/selftests/dynamic_debug/config
 create mode 100755 tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh

diff --git a/MAINTAINERS b/MAINTAINERS
index 35c1edb67551..af1d3f246962 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9047,6 +9047,7 @@ S:	Maintained
 F:	include/linux/dynamic_debug.h
 F:	lib/dynamic_debug.c
 F:	lib/test_dynamic_debug.c
+F:	tools/testing/selftests/dynamic_debug/*
 
 DYNAMIC INTERRUPT MODERATION
 M:	Tal Gilboa <talgi@nvidia.com>
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 450f13ba4cca..e4fc4dd80cf9 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -27,6 +27,7 @@ TARGETS += drivers/net/team
 TARGETS += drivers/net/virtio_net
 TARGETS += drivers/platform/x86/intel/ifs
 TARGETS += dt
+TARGETS += dynamic_debug
 TARGETS += efivarfs
 TARGETS += exec
 TARGETS += fchmodat2
diff --git a/tools/testing/selftests/dynamic_debug/Makefile b/tools/testing/selftests/dynamic_debug/Makefile
new file mode 100644
index 000000000000..6d06fa7f1040
--- /dev/null
+++ b/tools/testing/selftests/dynamic_debug/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0-only
+# borrowed from Makefile for user memory selftests
+
+# No binaries, but make sure arg-less "make" doesn't trigger "run_tests"
+all:
+
+TEST_PROGS := dyndbg_selftest.sh
+
+include ../lib.mk
diff --git a/tools/testing/selftests/dynamic_debug/config b/tools/testing/selftests/dynamic_debug/config
new file mode 100644
index 000000000000..0f906ff53908
--- /dev/null
+++ b/tools/testing/selftests/dynamic_debug/config
@@ -0,0 +1,7 @@
+
+# basic tests ref the builtin params module
+CONFIG_DYNAMIC_DEBUG=m
+
+# more testing is possible with these
+# CONFIG_TEST_DYNAMIC_DEBUG=m
+# CONFIG_TEST_DYNAMIC_DEBUG_SUBMOD=m
diff --git a/tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh b/tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh
new file mode 100755
index 000000000000..465fad3f392c
--- /dev/null
+++ b/tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh
@@ -0,0 +1,257 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-only
+
+V=${V:=0}  # invoke as V=1 $0  for global verbose
+RED="\033[0;31m"
+GREEN="\033[0;32m"
+YELLOW="\033[0;33m"
+BLUE="\033[0;34m"
+MAGENTA="\033[0;35m"
+CYAN="\033[0;36m"
+NC="\033[0;0m"
+error_msg=""
+
+[ -e /proc/dynamic_debug/control ] || {
+    echo -e "${RED}: this test requires CONFIG_DYNAMIC_DEBUG=y ${NC}"
+    exit 0 # nothing to test here, no good reason to fail.
+}
+
+# need info to avoid failures due to untestable configs
+
+[ -f "$KCONFIG_CONFIG" ] || KCONFIG_CONFIG=".config"
+if [ -f "$KCONFIG_CONFIG" ]; then
+    echo "# consulting KCONFIG_CONFIG: $KCONFIG_CONFIG"
+    grep -q "CONFIG_DYNAMIC_DEBUG=y" $KCONFIG_CONFIG ; LACK_DD_BUILTIN=$?
+    grep -q "CONFIG_TEST_DYNAMIC_DEBUG=m" $KCONFIG_CONFIG ; LACK_TMOD=$?
+    grep -q "CONFIG_TEST_DYNAMIC_DEBUG_SUBMOD=m" $KCONFIG_CONFIG ; LACK_TMOD_SUBMOD=$?
+    if [ $V -eq 1 ]; then
+	echo LACK_DD_BUILTIN: $LACK_DD_BUILTIN
+	echo LACK_TMOD: $LACK_TMOD
+	echo LACK_TMOD_SUBMOD: $LACK_TMOD_SUBMOD
+    fi
+else
+    LACK_DD_BUILTIN=0
+    LACK_TMOD=0
+    LACK_TMOD_SUBMOD=0
+fi
+
+function vx () {
+    echo $1 > /sys/module/dynamic_debug/parameters/verbose
+}
+
+function ddgrep () {
+    grep $1 /proc/dynamic_debug/control
+}
+
+function doprints () {
+    cat /sys/module/test_dynamic_debug/parameters/do_prints
+}
+
+function ddcmd () {
+    exp_exit_code=0
+    num_args=$#
+    if [ "${@:$#}" = "pass" ]; then
+	num_args=$#-1
+    elif [ "${@:$#}" = "fail" ]; then
+        num_args=$#-1
+	exp_exit_code=1
+    fi
+    args=${@:1:$num_args}
+    output=$((echo "$args" > /proc/dynamic_debug/control) 2>&1)
+    exit_code=$?
+    error_msg=$(echo $output | cut -d ":" -f 5 | sed -e 's/^[[:space:]]*//')
+    handle_exit_code $BASH_LINENO $FUNCNAME $exit_code $exp_exit_code
+}
+
+function handle_exit_code() {
+    local exp_exit_code=0
+    [ $# == 4 ] && exp_exit_code=$4
+    if [ $3 -ne $exp_exit_code ]; then
+        echo -e "${RED}: $BASH_SOURCE:$1 $2() expected to exit with code $exp_exit_code"
+	[ $3 == 1 ] && echo "Error: '$error_msg'"
+        exit
+    fi
+}
+
+# $1 - pattern to match, pattern in $1 is enclosed by spaces for a match ""\s$1\s"
+# $2 - number of times the pattern passed in $1 is expected to match
+# $3 - optional can be set either to "-r" or "-v"
+#       "-r" means relaxed matching in this case pattern provided in $1 is passed
+#       as is without enclosing it with spaces
+#       "-v" prints matching lines
+# $4 - optional when $3 is set to "-r" then $4 can be used to pass "-v"
+function check_match_ct {
+    pattern="\s$1\s"
+    exp_cnt=0
+
+    [ "$3" == "-r" ] && pattern="$1"
+    let cnt=$(ddgrep "$pattern" | wc -l)
+    if [ $V -eq 1 ] || [ "$3" == "-v" ] || [ "$4" == "-v" ]; then
+        echo -ne "${BLUE}" && ddgrep $pattern && echo -ne "${NC}"
+    fi
+    [ $# -gt 1 ] && exp_cnt=$2
+    if [ $cnt -ne $exp_cnt ]; then
+        echo -e "${RED}: $BASH_SOURCE:$BASH_LINENO check failed expected $exp_cnt on $1, got $cnt"
+        exit
+    else
+        echo ": $cnt matches on $1"
+    fi
+}
+
+# $1 - trace instance name
+# #2 - if > 0 then directory is expected to exist, if <= 0 then otherwise
+# $3 - "-v" for verbose
+function check_trace_instance_dir {
+    if [ -e /sys/kernel/tracing/instances/$1 ]; then
+        if [ "$3" == "-v" ] ; then
+            echo "ls -l /sys/kernel/tracing/instances/$1: "
+            ls -l /sys/kernel/tracing/instances/$1
+        fi
+	if [ $2 -le 0 ]; then
+            echo -e "${RED}: $BASH_SOURCE:$BASH_LINENO error trace instance \
+		    '/sys/kernel/tracing/instances/$1' does exist"
+	    exit
+	fi
+    else
+	if [ $2 -gt 0 ]; then
+            echo -e "${RED}: $BASH_SOURCE:$BASH_LINENO error trace instance \
+		    '/sys/kernel/tracing/instances/$1' does not exist"
+	    exit
+        fi
+    fi
+}
+
+function tmark {
+    echo $* > /sys/kernel/tracing/trace_marker
+}
+
+# $1 - trace instance name
+# $2 - line number
+# $3 - if > 0 then the instance is expected to be opened, otherwise
+# the instance is expected to be closed
+function check_trace_instance {
+    output=$(tail -n9 /proc/dynamic_debug/control | grep ": Opened trace instances" \
+	    | xargs -n1 | grep $1)
+    if [ "$output" != $1 ] && [ $3 -gt 0 ]; then
+        echo -e "${RED}: $BASH_SOURCE:$2 trace instance $1 is not opened"
+        exit
+    fi
+    if [ "$output" == $1 ] && [ $3 -le 0 ]; then
+        echo -e "${RED}: $BASH_SOURCE:$2 trace instance $1 is not closed"
+        exit
+    fi
+}
+
+function is_trace_instance_opened {
+    check_trace_instance $1 $BASH_LINENO 1
+}
+
+function is_trace_instance_closed {
+    check_trace_instance $1 $BASH_LINENO 0
+}
+
+# $1 - trace instance directory to delete
+# $2 - if > 0 then directory is expected to be deleted successfully, if <= 0 then otherwise
+function del_trace_instance_dir() {
+    exp_exit_code=1
+    [ $2 -gt 0 ] && exp_exit_code=0
+    output=$((rmdir /sys/kernel/debug/tracing/instances/$1) 2>&1)
+    exit_code=$?
+    error_msg=$(echo $output | cut -d ":" -f 3 | sed -e 's/^[[:space:]]*//')
+    handle_exit_code $BASH_LINENO $FUNCNAME $exit_code $exp_exit_code
+}
+
+function error_log_ref {
+    # to show what I got
+    : echo "# error-log-ref: $1"
+    : echo cat \$2
+}
+
+function ifrmmod {
+    lsmod | grep $1 2>&1>/dev/null && rmmod $1
+}
+
+# $1 - text to search for
+function search_trace() {
+    search_trace_name 0 1 $1
+}
+
+# $1 - trace instance name, 0 for global event trace
+# $2 - line number counting from the bottom
+# $3 - text to search for
+function search_trace_name() {
+	if [ "$1" = "0" ]; then
+	    buf=$(cat /sys/kernel/debug/tracing/trace)
+	    line=$(tail -$2 /sys/kernel/debug/tracing/trace | head -1 | sed -e 's/^[[:space:]]*//')
+	else
+	    buf=$(cat /sys/kernel/debug/tracing/instances/$1/trace)
+	    line=$(tail -$2 /sys/kernel/debug/tracing/instances/$1/trace | head -1 | \
+		   sed -e 's/^[[:space:]]*//')
+	fi
+	if [ $2 = 0 ]; then
+	    # whole-buf check
+	    output=$(echo $buf | grep "$3")
+	else
+	    output=$(echo $line | grep "$3")
+	fi
+	if [ "$output" = "" ]; then
+            echo -e "${RED}: $BASH_SOURCE:$BASH_LINENO search for '$3' failed \
+		    in line '$line' or '$buf'"
+	    exit
+	fi
+	if [ $V = 1 ]; then
+	    echo -e "${MAGENTA}: search_trace_name in $1 found: \n$output \nin:${BLUE} $buf ${NC}"
+        fi
+}
+
+# $1 - error message to check
+function check_err_msg() {
+    if [ "$error_msg" != "$1" ]; then
+        echo -e "${RED}: $BASH_SOURCE:$BASH_LINENO error message '$error_msg' \
+		does not match with '$1'"
+        exit
+    fi
+}
+
+function basic_tests {
+    echo -e "${GREEN}# BASIC_TESTS ${NC}"
+    if [ $LACK_DD_BUILTIN -eq 1 ]; then
+	echo "SKIP"
+	return
+    fi
+    ddcmd =_ # zero everything
+    check_match_ct =p 0
+
+    # module params are builtin to handle boot args
+    check_match_ct '\[params\]' 4 -r
+    ddcmd module params +mpf
+    check_match_ct =pmf 4
+
+    # multi-cmd input, newline separated, with embedded comments
+    cat <<"EOF" > /proc/dynamic_debug/control
+      module params =_				# clear params
+      module params +mf				# set flags
+      module params func parse_args +sl		# other flags
+EOF
+    check_match_ct =mf 3
+    check_match_ct =mfsl 1
+    ddcmd =_
+}
+
+tests_list=(
+    basic_tests
+)
+
+# Run tests
+
+ifrmmod test_dynamic_debug_submod
+ifrmmod test_dynamic_debug
+
+for test in "${tests_list[@]}"
+do
+    $test
+    echo ""
+done
+echo -en "${GREEN}# Done on: "
+date
+echo -en "${NC}"
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 21/65] dyndbg: change __dynamic_func_call_cls* macros into expressions
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (19 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 20/65] selftests-dyndbg: add a dynamic_debug run_tests target Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 22/65] dyndbg-API: replace DECLARE_DYNDBG_CLASSMAP Jim Cromie
                   ` (44 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jim Cromie, linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

The Xe driver's XE_IOCTL_DBG macro calls drm_dbg() from inside an if
(expression).  This breaks when CONFIG_DRM_USE_DYNAMIC_DEBUG=y because
the invoked macro has a do-while-0 wrapper, and is not an expression.

   if (cond && (drm_dbg("expr-form"),1)) {
      ... do some more stuff
   }

Fix for this usage by changing __dynamic_func_call_cls{,_no_desc}
macros into expressions, by replacing the do-while-0s with a ({ })
wrapper.  In the common usage, the trailing ';' converts the
expression into a statement.

   drm_dbg("statement form");

Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 include/linux/dynamic_debug.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index b6198ecc854d..80160028461a 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -224,24 +224,24 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
  * (|_cls):	adds in _DPRINT_CLASS_DFLT as needed
  * (|_no_desc):	former gets callsite descriptor as 1st arg (for prdbgs)
  */
-#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {	\
+#define __dynamic_func_call_cls(id, cls, fmt, func, ...) ({	\
 	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);	\
 	if (DYNAMIC_DEBUG_BRANCH(id)) {				\
 		func(&id, ##__VA_ARGS__);			\
 		__dynamic_dump_stack(id);			\
 	}							\
-} while (0)
+})
 #define __dynamic_func_call(id, fmt, func, ...)				\
 	__dynamic_func_call_cls(id, _DPRINTK_CLASS_DFLT, fmt,		\
 				func, ##__VA_ARGS__)
 
-#define __dynamic_func_call_cls_no_desc(id, cls, fmt, func, ...) do {	\
+#define __dynamic_func_call_cls_no_desc(id, cls, fmt, func, ...) ({	\
 	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);		\
 	if (DYNAMIC_DEBUG_BRANCH(id)) {					\
 		func(__VA_ARGS__);					\
 		__dynamic_dump_stack(id);				\
 	}								\
-} while (0)
+})
 #define __dynamic_func_call_no_desc(id, fmt, func, ...)			\
 	__dynamic_func_call_cls_no_desc(id, _DPRINTK_CLASS_DFLT,	\
 					fmt, func, ##__VA_ARGS__)
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 22/65] dyndbg-API: replace DECLARE_DYNDBG_CLASSMAP
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (20 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 21/65] dyndbg: change __dynamic_func_call_cls* macros into expressions Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 23/65] dyndbg: detect class_id reservation conflicts Jim Cromie
                   ` (43 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Arnd Bergmann, Jim Cromie,
	Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
	Aaron Tomlin, Andrew Morton, linux-kernel, linux-arch,
	linux-modules
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx, linux-doc

commit aad0214f3026 ("dyndbg: add DECLARE_DYNDBG_CLASSMAP macro")

DECLARE_DYNDBG_CLASSMAP() has a design error; its usage fails a
basic K&R rule: "define once, refer many times".

When CONFIG_DRM_USE_DYNAMIC_DEBUG=y, it is used across DRM core &
drivers; each invocation allocates/inits the classmap understood by
that module.  They *all* must match for the DRM modules to respond
consistently when drm.debug categories are enabled.  This is at least
a maintenance hassle.

Worse, its the root-cause of the CONFIG_DRM_USE_DYNAMIC_DEBUG=Y
regression; its use in both core & drivers obfuscates the 2 roles,
muddling the design, yielding an incomplete initialization when
modprobing drivers:

1st drm.ko loads, and dyndbg initializes its drm.debug callsites, then
a drm-driver loads, but too late for the drm.debug enablement.

And that gave us:
commit bb2ff6c27bc9 ("drm: Disable dynamic debug as broken")

So retire it, replace with 2 macros:
  DYNAMIC_DEBUG_CLASSMAP_DEFINE - invoked once from core - drm.ko
  DYNAMIC_DEBUG_CLASSMAP_USE    - from all drm drivers and helpers.
  NB: name-space de-noise

DYNAMIC_DEBUG_CLASSMAP_DEFINE: this reworks DECLARE_DYNDBG_CLASSMAP,
basically by dropping the static qualifier on the classmap, and
exporting it instead.

DYNAMIC_DEBUG_CLASSMAP_USE: then refers to the exported var by name:
  used from drivers, helper-mods
  lets us drop the repetitive "classname" declarations
  fixes 2nd-defn problem
  creates a ddebug_class_user record in new __dyndbg_class_users section
  new section is scanned "differently"

DECLARE_DYNDBG_CLASSMAP is preserved temporarily, to decouple DRM
adaptation work and avoid compile-errs before its done.

The DEFINE,USE distinction, and the separate classmap-use record,
allows dyndbg to initialize the driver's & helper's drm.debug
callsites separately after each is modprobed.

Basically, the classmap initial scan is repeated for classmap-users.

dyndbg's existing __dyndbg_classes[] section does:

. catalogs the module's classmaps
. tells dyndbg about them, allowing >control
. DYNAMIC_DEBUG_CLASSMAP_DEFINE creates section records.
. we rename it to: __dyndbg_class_maps[]

this patch adds __dyndbg_class_users[] section:

. catalogs users of classmap definitions from elsewhere
. authorizes dyndbg to >control user's class'd prdbgs
. DYNAMIC_DEBUG_CLASSMAP_USE() creates section records.

Now ddebug_add_module(etal) can handle classmap-uses similar to (and
after) classmaps; when a dependent module is loaded, if it has
classmap-uses (to a classmap-def in another module), that module's
kernel params are scanned to find if it has a kparam that is wired to
dyndbg's param-ops, and whose classmap is the one being ref'd.

To support this, theres a few data/header changes:

new struct ddebug_class_user
  contains: user-module-name, &classmap-defn
  it records drm-driver's use of a classmap in the section, allowing lookup

struct ddebug_info gets 2 new fields for the new sections:
  class_users, num_class_users.
  set by dynamic_debug_init() for builtins.
  or by kernel/module/main:load_info() for loadable modules.

vmlinux.lds.h: Add new BOUNDED_SECTION for __dyndbg_class_users.  this
creates start,len C symbol-names for the section.

TLDR ?

dynamic_debug.c: 2 changes from ddebug_add_module() & ddebug_change():

ddebug_add_module():

ddebug_attach_module_classes() is reworked/renamed/split into
debug_apply_class_maps(), ddebug_apply_class_users(), which both call
ddebug_apply_params().

ddebug_apply_params(new fn):

It scans module's/builtin kernel-params, calls ddebug_match_apply_kparam
for each to find any params/sysfs-nodes which may be wired to a classmap.

ddebug_match_apply_kparam(new fn):

1st, it tests the kernel-param.ops is dyndbg's; this guarantees that
the attached arg is a struct ddebug_class_param, which has a ref to
the param's state, and to the classmap defining the param's handling.

2nd, it requires that the classmap ref'd by the kparam is the one
we've been called for; modules can use many separate classmaps (as
test_dynamic_debug does).

Then apply the "parent" kparam's setting to the dependent module,
using ddebug_apply_class_bitmap().

ddebug_change(and callees) also gets adjustments:

ddebug_find_valid_class(): This does a search over the module's
classmaps, looking for the class FOO echo'd to >control.  So now it
searches over __dyndbg_class_users[] after __dyndbg_classes[].

ddebug_class_name(): return class-names for defined OR used classes.

test_dynamic_debug.c, test_dynamic_debug_submod.c:

This demonstrates the 2 types of classmaps & sysfs-params, following
the 4-part recipe:

0. define an enum for the classmap's class_ids
   drm.debug gives us DRM_UT_<*> (aka <T>)
   multiple classmaps in a module(s) must share 0-62 classid space.

1. DYNAMIC_DEBUG_CLASSMAP_DEFINE(classmap_name, .. "<T>")
   names the classes, maps them to consecutive class-ids.
   convention here is stringified ENUM_SYMBOLS
   these become API/ABI if 2 is done.

2. DYNAMIC_DEBUG_CLASSMAP_PARAM* (classmap_name)
   adds a controlling kparam to the class

3. DYNAMIC_DEBUG_CLASSMAP_USE(classmap_name)
   for subsystem/group/drivers to use extern created by 1.

Move all the enum declarations together, to better explain how they
share the 0..62 class-id space available to a module (non-overlapping
subranges).

reorg macros 2,3 by name.  This gives a tabular format, making it easy
to see the pattern of repetition, and the points of change.

And extend the test to replicate the 2-module (parent & dependent)
scenario which caused the CONFIG_DRM_USE_DYNAMIC_DEBUG=y regression
seen in drm & drivers.

The _submod.c is a 2-line file: #define _SUBMOD, #include parent.

This gives identical complements of prdbgs in parent & _submod, and
thus identical print behavior when all of: >control, >params, and
parent->_submod propagation are working correctly.

It also puts all the parent/_submod declarations together in the same
source; the new ifdef _SUBMOD block invokes DYNAMIC_DEBUG_CLASSMAP_USE
for the 2 test-interfaces.  I think this is clearer.

These 2 modules are both tristate, allowing 3 super/sub combos: Y/Y,
Y/M, M/M (not N/Y, since this is disallowed by dependence).

Y/Y, Y/M testing once exposed a missing __align(8) in the _METADATA
macro, which M/M didn't see, probably because the module-loader memory
placement constrained it from misalignment.

Fixes: aad0214f3026 ("dyndbg: add DECLARE_DYNDBG_CLASSMAP macro")
cc: linux-doc@vger.kernel.org
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
replace di with &dt->info, since di becomes stale
fix dd_mark_vector_subrange macro param ordering to match kdoc
s/base/offset/ in _ddebug_class_user, to reduce later churn
---
 MAINTAINERS                       |   2 +-
 include/asm-generic/vmlinux.lds.h |   1 +
 include/linux/dynamic_debug.h     | 138 +++++++++++++++++++++---
 kernel/module/main.c              |   3 +
 lib/Kconfig.debug                 |  24 ++++-
 lib/Makefile                      |   5 +
 lib/dynamic_debug.c               | 172 +++++++++++++++++++++++++-----
 lib/test_dynamic_debug.c          | 132 ++++++++++++++++-------
 lib/test_dynamic_debug_submod.c   |  14 +++
 9 files changed, 412 insertions(+), 79 deletions(-)
 create mode 100644 lib/test_dynamic_debug_submod.c

diff --git a/MAINTAINERS b/MAINTAINERS
index af1d3f246962..67da16e209c5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9046,7 +9046,7 @@ M:	Jim Cromie <jim.cromie@gmail.com>
 S:	Maintained
 F:	include/linux/dynamic_debug.h
 F:	lib/dynamic_debug.c
-F:	lib/test_dynamic_debug.c
+F:	lib/test_dynamic_debug*.c
 F:	tools/testing/selftests/dynamic_debug/*
 
 DYNAMIC INTERRUPT MODERATION
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 62fc2b0e8d1c..c29bf967ad03 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -387,6 +387,7 @@
 	. = ALIGN(8);							\
 	BOUNDED_SECTION_BY(__dyndbg_descriptors, ___dyndbg_descs)	\
 	BOUNDED_SECTION_BY(__dyndbg_class_maps, ___dyndbg_class_maps)	\
+	BOUNDED_SECTION_BY(__dyndbg_class_users, ___dyndbg_class_users)	\
 	CODETAG_SECTIONS()						\
 	LIKELY_PROFILE()		       				\
 	BRANCH_PROFILE()						\
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 80160028461a..74ed18a038bd 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -72,8 +72,11 @@ enum ddebug_class_map_type {
 	 */
 };
 
+/*
+ * map @class_names 0..N to consecutive constants starting at @base.
+ */
 struct _ddebug_class_map {
-	struct module *mod;	/* NULL for builtins */
+	const struct module *mod;	/* NULL for builtins */
 	const char *mod_name;
 	const char **class_names;
 	const int length;
@@ -81,10 +84,18 @@ struct _ddebug_class_map {
 	enum ddebug_class_map_type map_type;
 };
 
+struct _ddebug_class_user {
+	char *mod_name;
+	struct _ddebug_class_map *map;
+	const int offset;	/* user offset to re-number the used map */
+};
+
 /*
- * @_ddebug_info: gathers module/builtin dyndbg_* __sections together.
+ * @_ddebug_info: gathers module/builtin __dyndbg_<T> __sections
+ * together, each is a vec_<T>: a struct { struct T start[], int len }.
+ *
  * For builtins, it is used as a cursor, with the inner structs
- * marking sub-vectors of the builtin __sections in DATA.
+ * marking sub-vectors of the builtin __sections in DATA_DATA
  */
 struct _ddebug_descs {
 	struct _ddebug *start;
@@ -96,10 +107,16 @@ struct _ddebug_class_maps {
 	int len;
 };
 
+struct _ddebug_class_users {
+	struct _ddebug_class_user *start;
+	int len;
+};
+
 struct _ddebug_info {
 	const char *mod_name;
 	struct _ddebug_descs descs;
 	struct _ddebug_class_maps maps;
+	struct _ddebug_class_users users;
 };
 
 struct _ddebug_class_param {
@@ -118,12 +135,81 @@ struct _ddebug_class_param {
 #if defined(CONFIG_DYNAMIC_DEBUG) || \
 	(defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
 
+/*
+ * dyndbg classmaps is modelled closely upon drm.debug:
+ *
+ *  1. run-time control via sysfs node (api/abi)
+ *  2. each bit 0..N controls a single "category"
+ *  3. a pr_debug can have only 1 category, not several.
+ *  4. "kind" is a compile-time constant: 0..N or BIT() thereof
+ *  5. macro impls - give compile-time resolution or fail.
+ *
+ * dyndbg classmaps design axioms/constraints:
+ *
+ *  . optimizing compilers use 1-5 above, so preserve them.
+ *  . classmaps.class_id *is* the category.
+ *  . classmap definers/users are modules.
+ *  . every user wants 0..N
+ *  . 0..N exposes as ABI
+ *  . no 1 use-case wants N > 32, 16 is more usable
+ *  . N <= 64 in *all* cases
+ *  . modules/subsystems make category/classmap decisions
+ *  . ie an enum: DRM has DRM_UT_CORE..DRM_UT_DRMRES
+ *  . some categories are exposed to user: ABI
+ *  . making modules change their numbering is bogus, avoid if possible
+ *
+ * We can solve for all these at once:
+ *  A: map class-names to a .class_id range at compile-time
+ *  B: allow only "class NAME" changes to class'd callsites at run-time
+ *  C: users/modules must manage 0..62 hardcoded .class_id range limit.
+ *  D: existing pr_debugs get CLASS_DFLT=63
+ *
+ * By mapping class-names at >control to class-ids underneath, and
+ * responding only to class-names DEFINEd or USEd by the module, we
+ * can private-ize the class-id, and adjust class'd pr_debugs only by
+ * their names.
+ *
+ * This give us:
+ *  E: class_ids without classnames are unreachable
+ *  F: user modules opt-in by DEFINEing a classmap and/or USEing another
+ *
+ * Multi-classmap modules/groups are supported, if the classmaps share
+ * the class_id space [0..62] without overlap/conflict.
+ *
+ * NOTE: Due to the integer class_id, this api cannot disallow these:
+ * __pr_debug_cls(0, "fake CORE msg");  works only if a classmap maps 0.
+ * __pr_debug_cls(22, "no such class"); compiles but is not reachable
+ */
+
 /**
- * DECLARE_DYNDBG_CLASSMAP - declare classnames known by a module
- * @_var:   a struct ddebug_class_map, passed to module_param_cb
- * @_type:  enum class_map_type, chooses bits/verbose, numeric/symbolic
- * @_base:  offset of 1st class-name. splits .class_id space
- * @classes: class-names used to control class'd prdbgs
+ * DYNAMIC_DEBUG_CLASSMAP_DEFINE - define debug classes used by a module.
+ * @_var:   name of the classmap, exported for other modules coordinated use.
+ * @_mapty: enum ddebug_class_map_type: 0:DISJOINT - independent, 1:LEVEL - v2>v1
+ * @_base:  reserve N classids starting at _base, to split 0..62 classid space
+ * @classes: names of the N classes.
+ *
+ * This tells dyndbg what class_ids the module is using: _base..+N, by
+ * mapping names onto them.  This qualifies "class NAME" >controls on
+ * the defining module, ignoring unknown names.
+ */
+#define DYNAMIC_DEBUG_CLASSMAP_DEFINE(_var, _mapty, _base, ...)		\
+	static const char *_var##_classnames[] = { __VA_ARGS__ };	\
+	extern struct _ddebug_class_map _var;				\
+	struct _ddebug_class_map __aligned(8) __used			\
+		__section("__dyndbg_class_maps") _var = {		\
+		.mod = THIS_MODULE,					\
+		.mod_name = KBUILD_MODNAME,				\
+		.base = (_base),					\
+		.map_type = (_mapty),					\
+		.length = ARRAY_SIZE(_var##_classnames),		\
+		.class_names = _var##_classnames,			\
+	};								\
+	EXPORT_SYMBOL(_var)
+
+/*
+ * XXX: keep this until DRM adapts to use the DEFINE/USE api, it
+ * differs from DYNAMIC_DEBUG_CLASSMAP_DEFINE by the lack of the
+ * extern/EXPORT on the struct init, and cascading thinkos.
  */
 #define DECLARE_DYNDBG_CLASSMAP(_var, _maptype, _base, ...)		\
 	static const char *_var##_classnames[] = { __VA_ARGS__ };	\
@@ -137,6 +223,25 @@ struct _ddebug_class_param {
 		.class_names = _var##_classnames,			\
 	}
 
+/**
+ * DYNAMIC_DEBUG_CLASSMAP_USE - refer to a classmap, DEFINEd elsewhere.
+ * @_var: name of the exported classmap var
+ *
+ * This tells dyndbg that the module has prdbgs with classids defined
+ * in the named classmap.  This qualifies "class NAME" >controls on
+ * the user module, and ignores unknown names.
+ */
+#define DYNAMIC_DEBUG_CLASSMAP_USE(_var)				\
+	DYNAMIC_DEBUG_CLASSMAP_USE_(_var, 0, __UNIQUE_ID(_ddebug_class_user))
+#define DYNAMIC_DEBUG_CLASSMAP_USE_(_var, _offset, _uname)		\
+	extern struct _ddebug_class_map _var;				\
+	static struct _ddebug_class_user __aligned(8) __used		\
+	__section("__dyndbg_class_users") _uname = {			\
+		.mod_name = KBUILD_MODNAME,				\
+		.map = &(_var),						\
+		.offset = _offset					\
+	}
+
 extern __printf(2, 3)
 void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
 
@@ -298,12 +403,18 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 				   KERN_DEBUG, prefix_str, prefix_type,	\
 				   rowsize, groupsize, buf, len, ascii)
 
-/* for test only, generally expect drm.debug style macro wrappers */
-#define __pr_debug_cls(cls, fmt, ...) do {			\
+/*
+ * This is the "model" class variant of pr_debug.  It is not really
+ * intended for direct use; I'd encourage DRM-style drm_dbg_<T>
+ * macros for the interface, along with an enum for the <T>
+ *
+ * __printf(2, 3) would apply.
+ */
+#define __pr_debug_cls(cls, fmt, ...) ({			\
 	BUILD_BUG_ON_MSG(!__builtin_constant_p(cls),		\
 			 "expecting constant class int/enum");	\
 	dynamic_pr_debug_cls(cls, fmt, ##__VA_ARGS__);		\
-	} while (0)
+})
 
 #else /* !(CONFIG_DYNAMIC_DEBUG || (CONFIG_DYNAMIC_DEBUG_CORE && DYNAMIC_DEBUG_MODULE)) */
 
@@ -311,6 +422,8 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 #include <linux/errno.h>
 #include <linux/printk.h>
 
+#define DYNAMIC_DEBUG_CLASSMAP_DEFINE(_var, _mapty, _base, ...)
+#define DYNAMIC_DEBUG_CLASSMAP_USE(_var)
 #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)
 #define DYNAMIC_DEBUG_BRANCH(descriptor) false
 #define DECLARE_DYNDBG_CLASSMAP(...)
@@ -357,8 +470,7 @@ static inline int param_set_dyndbg_classes(const char *instr, const struct kerne
 static inline int param_get_dyndbg_classes(char *buffer, const struct kernel_param *kp)
 { return 0; }
 
-#endif
-
+#endif /* !CONFIG_DYNAMIC_DEBUG_CORE */
 
 extern const struct kernel_param_ops param_ops_dyndbg_classes;
 
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 49f7b12c9776..bfff5b849966 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -2716,6 +2716,9 @@ static int find_module_sections(struct module *mod, struct load_info *info)
 	mod->dyndbg_info.maps.start = section_objs(info, "__dyndbg_class_maps",
 						   sizeof(*mod->dyndbg_info.maps.start),
 						   &mod->dyndbg_info.maps.len);
+	mod->dyndbg_info.users.start = section_objs(info, "__dyndbg_class_users",
+						   sizeof(*mod->dyndbg_info.users.start),
+						   &mod->dyndbg_info.users.len);
 #endif
 
 	return 0;
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 93f356d2b3d9..302bb2656682 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -3106,12 +3106,26 @@ config TEST_STATIC_KEYS
 	  If unsure, say N.
 
 config TEST_DYNAMIC_DEBUG
-	tristate "Test DYNAMIC_DEBUG"
-	depends on DYNAMIC_DEBUG
+	tristate "Build test-dynamic-debug module"
+	depends on DYNAMIC_DEBUG || DYNAMIC_DEBUG_CORE
 	help
-	  This module registers a tracer callback to count enabled
-	  pr_debugs in a 'do_debugging' function, then alters their
-	  enablements, calls the function, and compares counts.
+	  This module exercises/demonstrates dyndbg's classmap API, by
+	  creating 2 classes: a DISJOINT classmap (supporting DRM.debug)
+	  and a LEVELS/VERBOSE classmap (like verbose2 > verbose1).
+
+	  If unsure, say N.
+
+config TEST_DYNAMIC_DEBUG_SUBMOD
+	tristate "Build test-dynamic-debug submodule"
+	default m
+	depends on DYNAMIC_DEBUG || DYNAMIC_DEBUG_CORE
+	depends on TEST_DYNAMIC_DEBUG
+	help
+	  This sub-module uses a classmap defined and exported by the
+	  parent module, recapitulating drm & driver's shared use of
+	  drm.debug to control enabled debug-categories.
+	  It is tristate, independent of parent, to allow testing all
+	  proper combinations of parent=y/m submod=y/m.
 
 	  If unsure, say N.
 
diff --git a/lib/Makefile b/lib/Makefile
index 1b9ee167517f..19ab40903436 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -83,6 +83,9 @@ obj-$(CONFIG_TEST_RHASHTABLE) += test_rhashtable.o
 obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_keys.o
 obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_key_base.o
 obj-$(CONFIG_TEST_DYNAMIC_DEBUG) += test_dynamic_debug.o
+obj-$(CONFIG_TEST_DYNAMIC_DEBUG_SUBMOD) += test_dynamic_debug_submod.o
+obj-$(CONFIG_TEST_PRINTF) += test_printf.o
+obj-$(CONFIG_TEST_SCANF) += test_scanf.o
 
 obj-$(CONFIG_TEST_BITMAP) += test_bitmap.o
 ifeq ($(CONFIG_CC_IS_CLANG)$(CONFIG_KASAN),yy)
@@ -206,6 +209,8 @@ obj-$(CONFIG_ARCH_NEED_CMPXCHG_1_EMU) += cmpxchg-emu.o
 obj-$(CONFIG_DYNAMIC_DEBUG_CORE) += dynamic_debug.o
 #ensure exported functions have prototypes
 CFLAGS_dynamic_debug.o := -DDYNAMIC_DEBUG_MODULE
+CFLAGS_test_dynamic_debug.o := -DDYNAMIC_DEBUG_MODULE
+CFLAGS_test_dynamic_debug_submod.o := -DDYNAMIC_DEBUG_MODULE
 
 obj-$(CONFIG_SYMBOLIC_ERRNAME) += errname.o
 
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index e8ffc2b5b330..66f4bfe39e89 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -29,6 +29,7 @@
 #include <linux/string_helpers.h>
 #include <linux/uaccess.h>
 #include <linux/dynamic_debug.h>
+
 #include <linux/debugfs.h>
 #include <linux/slab.h>
 #include <linux/jump_label.h>
@@ -43,6 +44,8 @@ extern struct _ddebug __start___dyndbg_descs[];
 extern struct _ddebug __stop___dyndbg_descs[];
 extern struct _ddebug_class_map __start___dyndbg_class_maps[];
 extern struct _ddebug_class_map __stop___dyndbg_class_maps[];
+extern struct _ddebug_class_user __start___dyndbg_class_users[];
+extern struct _ddebug_class_user __stop___dyndbg_class_users[];
 
 struct ddebug_table {
 	struct list_head link;
@@ -168,20 +171,37 @@ static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
 		  query->first_lineno, query->last_lineno, query->class_string);
 }
 
-static struct _ddebug_class_map *ddebug_find_valid_class(struct ddebug_table const *dt,
-							 const char *class_string,
-							 int *class_id)
+#define vpr_di_info(di_p, msg_p, ...) ({				\
+	struct _ddebug_info const *_di = di_p;				\
+	v2pr_info(msg_p "module:%s nd:%d nc:%d nu:%d\n", ##__VA_ARGS__, \
+		  _di->mod_name, _di->descs.len, _di->maps.len,		\
+		  _di->users.len);					\
+	})
+
+static struct _ddebug_class_map *
+ddebug_find_valid_class(struct _ddebug_info const *di, const char *query_class, int *class_id)
 {
 	struct _ddebug_class_map *map;
+	struct _ddebug_class_user *cli;
 	int i, idx;
 
-	for_subvec(i, map, &dt->info, maps) {
-		idx = match_string(map->class_names, map->length, class_string);
+	for_subvec(i, map, di, maps) {
+		idx = match_string(map->class_names, map->length, query_class);
 		if (idx >= 0) {
+			vpr_di_info(di, "good-class: %s.%s ", map->mod_name, query_class);
 			*class_id = idx + map->base;
 			return map;
 		}
 	}
+	for_subvec(i, cli, di, users) {
+		idx = match_string(cli->map->class_names, cli->map->length, query_class);
+		if (idx >= 0) {
+			vpr_di_info(di, "class-ref: %s -> %s.%s ",
+				    cli->mod_name, cli->map->mod_name, query_class);
+			*class_id = idx + cli->map->base;
+			return cli->map;
+		}
+	}
 	*class_id = -ENOENT;
 	return NULL;
 }
@@ -238,8 +258,7 @@ static bool ddebug_match_desc(const struct ddebug_query *query,
 	return true;
 }
 
-static int ddebug_change(const struct ddebug_query *query,
-			 struct flag_settings *modifiers)
+static int ddebug_change(const struct ddebug_query *query, struct flag_settings *modifiers)
 {
 	int i;
 	struct ddebug_table *dt;
@@ -260,7 +279,8 @@ static int ddebug_change(const struct ddebug_query *query,
 			continue;
 
 		if (query->class_string) {
-			map = ddebug_find_valid_class(dt, query->class_string, &valid_class);
+			map = ddebug_find_valid_class(&dt->info, query->class_string,
+						      &valid_class);
 			if (!map)
 				continue;
 		} else {
@@ -590,7 +610,7 @@ static int ddebug_exec_query(char *query_string, const char *modname)
 
 /* handle multiple queries in query string, continue on error, return
    last error or number of matching callsites.  Module name is either
-   in param (for boot arg) or perhaps in query string.
+   in the modname arg (for boot args) or perhaps in query string.
 */
 static int ddebug_exec_queries(char *query, const char *modname)
 {
@@ -721,7 +741,7 @@ static int param_set_dyndbg_module_classes(const char *instr,
 /**
  * param_set_dyndbg_classes - classmap kparam setter
  * @instr: string echo>d to sysfs, input depends on map_type
- * @kp:    kp->arg has state: bits/lvl, map, map_type
+ * @kp:    kp->arg has state: bits/lvl, classmap, map_type
  *
  * enable/disable all class'd pr_debugs in the classmap. For LEVEL
  * map-types, enforce * relative levels by bitpos.
@@ -758,6 +778,7 @@ int param_get_dyndbg_classes(char *buffer, const struct kernel_param *kp)
 	default:
 		return -1;
 	}
+	return 0;
 }
 EXPORT_SYMBOL(param_get_dyndbg_classes);
 
@@ -1073,12 +1094,17 @@ static bool ddebug_class_in_range(const int class_id, const struct _ddebug_class
 static const char *ddebug_class_name(struct _ddebug_info *di, struct _ddebug *dp)
 {
 	struct _ddebug_class_map *map;
+	struct _ddebug_class_user *cli;
 	int i;
 
 	for_subvec(i, map, di, maps)
 		if (ddebug_class_in_range(dp->class_id, map))
 			return map->class_names[dp->class_id - map->base];
 
+	for_subvec(i, cli, di, users)
+		if (ddebug_class_in_range(dp->class_id, cli->map))
+			return cli->map->class_names[dp->class_id - cli->map->base];
+
 	return NULL;
 }
 
@@ -1159,9 +1185,85 @@ static const struct proc_ops proc_fops = {
 	.proc_write = ddebug_proc_write
 };
 
-static void ddebug_attach_module_classes(struct ddebug_table *dt, struct _ddebug_info *di)
+#define vpr_cm_info(cm_p, msg_fmt, ...) ({				\
+	struct _ddebug_class_map const *_cm = cm_p;			\
+	v2pr_info(msg_fmt "%s [%d..%d] %s..%s\n", ##__VA_ARGS__,	\
+		  _cm->mod_name, _cm->base, _cm->base + _cm->length,	\
+		  _cm->class_names[0], _cm->class_names[_cm->length - 1]); \
+	})
+
+static void ddebug_sync_classbits(const struct kernel_param *kp, const char *modname)
+{
+	const struct _ddebug_class_param *dcp = kp->arg;
+
+	/* clamp initial bitvec, mask off hi-bits */
+	if (*dcp->bits & ~CLASSMAP_BITMASK(dcp->map->length)) {
+		*dcp->bits &= CLASSMAP_BITMASK(dcp->map->length);
+		v2pr_info("preset classbits: %lx\n", *dcp->bits);
+	}
+	/* force class'd prdbgs (in USEr module) to match (DEFINEr module) class-param */
+	ddebug_apply_class_bitmap(dcp, dcp->bits, ~0, modname);
+	ddebug_apply_class_bitmap(dcp, dcp->bits, 0, modname);
+}
+
+static void ddebug_match_apply_kparam(const struct kernel_param *kp,
+				      const struct _ddebug_class_map *map,
+				      const char *mod_name)
+{
+	struct _ddebug_class_param *dcp;
+
+	if (kp->ops != &param_ops_dyndbg_classes)
+		return;
+
+	dcp = (struct _ddebug_class_param *)kp->arg;
+
+	if (map == dcp->map) {
+		v2pr_info(" kp:%s.%s =0x%lx", mod_name, kp->name, *dcp->bits);
+		vpr_cm_info(map, " %s maps ", mod_name);
+		ddebug_sync_classbits(kp, mod_name);
+	}
+}
+
+static void ddebug_apply_params(const struct _ddebug_class_map *cm, const char *mod_name)
+{
+	const struct kernel_param *kp;
+#if IS_ENABLED(CONFIG_MODULES)
+	int i;
+
+	if (cm->mod) {
+		vpr_cm_info(cm, "loaded classmap: %s ", mod_name);
+		/* ifdef protects the cm->mod->kp deref */
+		for (i = 0, kp = cm->mod->kp; i < cm->mod->num_kp; i++, kp++)
+			ddebug_match_apply_kparam(kp, cm, mod_name);
+	}
+#endif
+	if (!cm->mod) {
+		vpr_cm_info(cm, "builtin classmap: %s ", mod_name);
+		for (kp = __start___param; kp < __stop___param; kp++)
+			ddebug_match_apply_kparam(kp, cm, mod_name);
+	}
+}
+
+static void ddebug_apply_class_maps(const struct _ddebug_info *di)
 {
-	vpr_info("module:%s attached %d classes\n", dt->info.mod_name, dt->info.maps.len);
+	struct _ddebug_class_map *cm;
+	int i;
+
+	for_subvec(i, cm, di, maps)
+		ddebug_apply_params(cm, cm->mod_name);
+
+	vpr_di_info(di, "attached %d class-maps to ", i);
+}
+
+static void ddebug_apply_class_users(const struct _ddebug_info *di)
+{
+	struct _ddebug_class_user *cli;
+	int i;
+
+	for_subvec(i, cli, di, users)
+		ddebug_apply_params(cli->map, cli->mod_name);
+
+	vpr_di_info(di, "attached %d class-users to ", i);
 }
 
 /*
@@ -1190,6 +1292,22 @@ static void ddebug_attach_module_classes(struct ddebug_table *dt, struct _ddebug
 	(__dst)->info._vec.len = __nc;					\
 })
 
+static int __maybe_unused
+ddebug_class_range_overlap(struct _ddebug_class_map *cm,
+			   u64 *reserved_ids)
+{
+	u64 range = (((1ULL << cm->length) - 1) << cm->base);
+
+	if (range & *reserved_ids) {
+		pr_err("[%d..%d] on %s conflicts with %llx\n", cm->base,
+		       cm->base + cm->length - 1, cm->class_names[0],
+		       *reserved_ids);
+		return -EINVAL;
+	}
+	*reserved_ids |= range;
+	return 0;
+}
+
 /*
  * Allocate a new ddebug_table for the given module
  * and add it to the global list.
@@ -1198,6 +1316,7 @@ static int ddebug_add_module(struct _ddebug_info *di)
 {
 	struct ddebug_table *dt;
 	struct _ddebug_class_map *cm;
+	struct _ddebug_class_user *cli;
 	int i;
 
 	if (!di->descs.len)
@@ -1210,26 +1329,29 @@ static int ddebug_add_module(struct _ddebug_info *di)
 		pr_err("error adding module: %s\n", di->mod_name);
 		return -ENOMEM;
 	}
+	INIT_LIST_HEAD(&dt->link);
 	/*
-	 * For built-in modules, name (as supplied in di by its
-	 * callers) lives in .rodata and is immortal. For loaded
-	 * modules, name points at the name[] member of struct module,
-	 * which lives at least as long as this struct ddebug_table.
+	 * For built-in modules, di-> referents live in .*data and are
+	 * immortal. For loaded modules, di points at the dyndbg_info
+	 * member of its struct module, which lives at least as
+	 * long as this struct ddebug_table.
 	 */
 	dt->info = *di;
-
-	INIT_LIST_HEAD(&dt->link);
-
-	dd_mark_vector_subrange(i, cm, di, maps, dt);
-
-	if (di->maps.len)
-		ddebug_attach_module_classes(dt, di);
+	dd_mark_vector_subrange(i, cm, &dt->info, maps, dt);
+	dd_mark_vector_subrange(i, cli, &dt->info, users, dt);
+	/* now di is stale */
 
 	mutex_lock(&ddebug_lock);
 	list_add_tail(&dt->link, &ddebug_tables);
 	mutex_unlock(&ddebug_lock);
 
-	vpr_info("%3u debug prints in module %s\n", di->descs.len, di->mod_name);
+	if (dt->info.maps.len)
+		ddebug_apply_class_maps(&dt->info);
+	if (dt->info.users.len)
+		ddebug_apply_class_users(&dt->info);
+
+	vpr_info("%3u debug prints in module %s\n",
+		 dt->info.descs.len, dt->info.mod_name);
 	return 0;
 }
 
@@ -1379,8 +1501,10 @@ static int __init dynamic_debug_init(void)
 	struct _ddebug_info di = {
 		.descs.start = __start___dyndbg_descs,
 		.maps.start  = __start___dyndbg_class_maps,
+		.users.start = __start___dyndbg_class_users,
 		.descs.len = __stop___dyndbg_descs - __start___dyndbg_descs,
 		.maps.len  = __stop___dyndbg_class_maps - __start___dyndbg_class_maps,
+		.users.len = __stop___dyndbg_class_users - __start___dyndbg_class_users,
 	};
 
 #ifdef CONFIG_MODULES
diff --git a/lib/test_dynamic_debug.c b/lib/test_dynamic_debug.c
index 9c3e53cd26bd..6c4548f63512 100644
--- a/lib/test_dynamic_debug.c
+++ b/lib/test_dynamic_debug.c
@@ -6,11 +6,30 @@
  *      Jim Cromie	<jim.cromie@gmail.com>
  */
 
-#define pr_fmt(fmt) "test_dd: " fmt
+/*
+ * This file is built 2x, also making test_dynamic_debug_submod.ko,
+ * whose 2-line src file #includes this file.  This gives us a _submod
+ * clone with identical pr_debugs, without further maintenance.
+ *
+ * If things are working properly, they should operate identically
+ * when printed or adjusted by >control.  This eases visual perusal of
+ * the logs, and simplifies testing, by easing the proper accounting
+ * of expectations.
+ *
+ * It also puts both halves of the subsystem _DEFINE & _USE use case
+ * together, and integrates the common ENUM providing both class_ids
+ * and class-names to both _DEFINErs and _USERs.  I think this makes
+ * the usage clearer.
+ */
+#if defined(TEST_DYNAMIC_DEBUG_SUBMOD)
+  #define pr_fmt(fmt) "test_dd_submod: " fmt
+#else
+  #define pr_fmt(fmt) "test_dd: " fmt
+#endif
 
 #include <linux/module.h>
 
-/* run tests by reading or writing sysfs node: do_prints */
+/* re-gen output by reading or writing sysfs node: do_prints */
 
 static void do_prints(void); /* device under test */
 static int param_set_do_prints(const char *instr, const struct kernel_param *kp)
@@ -29,24 +48,39 @@ static const struct kernel_param_ops param_ops_do_prints = {
 };
 module_param_cb(do_prints, &param_ops_do_prints, NULL, 0600);
 
-/*
- * Using the CLASSMAP api:
- * - classmaps must have corresponding enum
- * - enum symbols must match/correlate with class-name strings in the map.
- * - base must equal enum's 1st value
- * - multiple maps must set their base to share the 0-30 class_id space !!
- *   (build-bug-on tips welcome)
- * Additionally, here:
- * - tie together sysname, mapname, bitsname, flagsname
- */
-#define DD_SYS_WRAP(_model, _flags)					\
-	static unsigned long bits_##_model;				\
-	static struct _ddebug_class_param _flags##_model = {		\
+#define CLASSMAP_BITMASK(width, base) (((1UL << (width)) - 1) << (base))
+
+/* sysfs param wrapper, proto-API */
+#define DYNAMIC_DEBUG_CLASSMAP_PARAM_(_model, _flags, _init)		\
+	static unsigned long bits_##_model = _init;			\
+	static struct _ddebug_class_param _flags##_##_model = {		\
 		.bits = &bits_##_model,					\
 		.flags = #_flags,					\
 		.map = &map_##_model,					\
 	};								\
-	module_param_cb(_flags##_##_model, &param_ops_dyndbg_classes, &_flags##_model, 0600)
+	module_param_cb(_flags##_##_model, &param_ops_dyndbg_classes,	\
+			&_flags##_##_model, 0600)
+#ifdef DEBUG
+#define DYNAMIC_DEBUG_CLASSMAP_PARAM(_model, _flags)		\
+	DYNAMIC_DEBUG_CLASSMAP_PARAM_(_model, _flags, ~0)
+#else
+#define DYNAMIC_DEBUG_CLASSMAP_PARAM(_model, _flags)		\
+	DYNAMIC_DEBUG_CLASSMAP_PARAM_(_model, _flags, 0)
+#endif
+
+/*
+ * Demonstrate/test DISJOINT & LEVEL typed classmaps with a sys-param.
+ *
+ * To comport with DRM debug-category (an int), classmaps map names to
+ * ids (also an int).  So a classmap starts with an enum; DRM has enum
+ * debug_category: with DRM_UT_<CORE,DRIVER,KMS,etc>.  We use the enum
+ * values as class-ids, and stringified enum-symbols as classnames.
+ *
+ * Modules with multiple CLASSMAPS must have enums with distinct
+ * value-ranges, as arranged below with explicit enum_sym = X inits.
+ * To clarify this sharing, declare the 2 enums now, for the 2
+ * different classmap types
+ */
 
 /* numeric input, independent bits */
 enum cat_disjoint_bits {
@@ -60,26 +94,51 @@ enum cat_disjoint_bits {
 	D2_LEASE,
 	D2_DP,
 	D2_DRMRES };
-DECLARE_DYNDBG_CLASSMAP(map_disjoint_bits, DD_CLASS_TYPE_DISJOINT_BITS, 0,
-			"D2_CORE",
-			"D2_DRIVER",
-			"D2_KMS",
-			"D2_PRIME",
-			"D2_ATOMIC",
-			"D2_VBL",
-			"D2_STATE",
-			"D2_LEASE",
-			"D2_DP",
-			"D2_DRMRES");
-DD_SYS_WRAP(disjoint_bits, p);
-DD_SYS_WRAP(disjoint_bits, T);
-
-/* numeric verbosity, V2 > V1 related */
-enum cat_level_num { V0 = 14, V1, V2, V3, V4, V5, V6, V7 };
-DECLARE_DYNDBG_CLASSMAP(map_level_num, DD_CLASS_TYPE_LEVEL_NUM, 14,
-		       "V0", "V1", "V2", "V3", "V4", "V5", "V6", "V7");
-DD_SYS_WRAP(level_num, p);
-DD_SYS_WRAP(level_num, T);
+
+/* numeric verbosity, V2 > V1 related.  V0 is > D2_DRMRES */
+enum cat_level_num { V0 = 16, V1, V2, V3, V4, V5, V6, V7 };
+
+/* recapitulate DRM's multi-classmap setup */
+#if !defined(TEST_DYNAMIC_DEBUG_SUBMOD)
+/*
+ * In single user, or parent / coordinator (drm.ko) modules, define
+ * classmaps on the client enums above, and then declares the PARAMS
+ * ref'g the classmaps.  Each is exported.
+ */
+DYNAMIC_DEBUG_CLASSMAP_DEFINE(map_disjoint_bits, DD_CLASS_TYPE_DISJOINT_BITS,
+			      D2_CORE,
+			      "D2_CORE",
+			      "D2_DRIVER",
+			      "D2_KMS",
+			      "D2_PRIME",
+			      "D2_ATOMIC",
+			      "D2_VBL",
+			      "D2_STATE",
+			      "D2_LEASE",
+			      "D2_DP",
+			      "D2_DRMRES");
+
+DYNAMIC_DEBUG_CLASSMAP_DEFINE(map_level_num, DD_CLASS_TYPE_LEVEL_NUM,
+			      V0, "V0", "V1", "V2", "V3", "V4", "V5", "V6", "V7");
+
+/*
+ * now add the sysfs-params
+ */
+
+DYNAMIC_DEBUG_CLASSMAP_PARAM(disjoint_bits, p);
+DYNAMIC_DEBUG_CLASSMAP_PARAM(level_num, p);
+
+#else /* TEST_DYNAMIC_DEBUG_SUBMOD */
+
+/*
+ * in submod/drm-drivers, use the classmaps defined in top/parent
+ * module above.
+ */
+
+DYNAMIC_DEBUG_CLASSMAP_USE(map_disjoint_bits);
+DYNAMIC_DEBUG_CLASSMAP_USE(map_level_num);
+
+#endif
 
 /* stand-in for all pr_debug etc */
 #define prdbg(SYM) __pr_debug_cls(SYM, #SYM " msg\n")
@@ -115,6 +174,7 @@ static void do_levels(void)
 
 static void do_prints(void)
 {
+	pr_debug("do_prints:\n");
 	do_cats();
 	do_levels();
 }
diff --git a/lib/test_dynamic_debug_submod.c b/lib/test_dynamic_debug_submod.c
new file mode 100644
index 000000000000..672aabf40160
--- /dev/null
+++ b/lib/test_dynamic_debug_submod.c
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Kernel module for testing dynamic_debug
+ *
+ * Authors:
+ *      Jim Cromie	<jim.cromie@gmail.com>
+ */
+
+/*
+ * clone the parent, inherit all the properties, for consistency and
+ * simpler accounting in test expectations.
+ */
+#define TEST_DYNAMIC_DEBUG_SUBMOD
+#include "test_dynamic_debug.c"
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 23/65] dyndbg: detect class_id reservation conflicts
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (21 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 22/65] dyndbg-API: replace DECLARE_DYNDBG_CLASSMAP Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 24/65] dyndbg: check DYNAMIC_DEBUG_CLASSMAP_DEFINE args at compile-time Jim Cromie
                   ` (42 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jim Cromie, Andrew Morton,
	linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

If a module _DEFINEs 2 or more classmaps, it must devise them to share
the per-module 0..62 class-id space; ie their respective base,+length
reservations cannot overlap.

To detect conflicts at modprobe, add ddebug_class_range_overlap(),
call it from ddebug_add_module(), and WARN and return -EINVAL when
they're detected.

This insures that class_id -> classname lookup has just 1 answer, so
the 1st-found search in find-class-name works properly.

test_dynamic_debug.c:

If built with -DFORCE_CLASSID_CONFLICT, the test-modules invoke 2
conflicting DYNAMIC_DEBUG_CLASSMAP_DEFINE() declarations, into parent
and the _submod.  These conflict with one of the good ones in the
parent (D2_CORE..etc), causing the modprobe(s) to warn

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
v9 - fix WARN() by adding new 1st arg 1.
---
 lib/dynamic_debug.c      | 10 ++++++++++
 lib/test_dynamic_debug.c |  8 ++++++++
 2 files changed, 18 insertions(+)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 66f4bfe39e89..ec0d1c427d59 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -1317,6 +1317,7 @@ static int ddebug_add_module(struct _ddebug_info *di)
 	struct ddebug_table *dt;
 	struct _ddebug_class_map *cm;
 	struct _ddebug_class_user *cli;
+	u64 reserved_ids = 0;
 	int i;
 
 	if (!di->descs.len)
@@ -1341,6 +1342,11 @@ static int ddebug_add_module(struct _ddebug_info *di)
 	dd_mark_vector_subrange(i, cli, &dt->info, users, dt);
 	/* now di is stale */
 
+	/* insure 2+ classmaps share the per-module 0..62 class_id space */
+	for_subvec(i, cm, &dt->info, maps)
+		if (ddebug_class_range_overlap(cm, &reserved_ids))
+			goto cleanup;
+
 	mutex_lock(&ddebug_lock);
 	list_add_tail(&dt->link, &ddebug_tables);
 	mutex_unlock(&ddebug_lock);
@@ -1353,6 +1359,10 @@ static int ddebug_add_module(struct _ddebug_info *di)
 	vpr_info("%3u debug prints in module %s\n",
 		 dt->info.descs.len, dt->info.mod_name);
 	return 0;
+cleanup:
+	WARN_ONCE(1, "dyndbg multi-classmap conflict in %s\n", di->mod_name);
+	kfree(dt);
+	return -EINVAL;
 }
 
 /* helper for ddebug_dyndbg_(boot|module)_param_cb */
diff --git a/lib/test_dynamic_debug.c b/lib/test_dynamic_debug.c
index 6c4548f63512..1ba4be9a403a 100644
--- a/lib/test_dynamic_debug.c
+++ b/lib/test_dynamic_debug.c
@@ -128,6 +128,14 @@ DYNAMIC_DEBUG_CLASSMAP_DEFINE(map_level_num, DD_CLASS_TYPE_LEVEL_NUM,
 DYNAMIC_DEBUG_CLASSMAP_PARAM(disjoint_bits, p);
 DYNAMIC_DEBUG_CLASSMAP_PARAM(level_num, p);
 
+#ifdef FORCE_CLASSID_CONFLICT
+/*
+ * Enable with -Dflag on compile to test overlapping class-id range
+ * detection.  This should warn on modprobes.
+ */
+DYNDBG_CLASSMAP_DEFINE(classid_range_conflict, 0, D2_CORE + 1, "D3_CORE");
+#endif
+
 #else /* TEST_DYNAMIC_DEBUG_SUBMOD */
 
 /*
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 24/65] dyndbg: check DYNAMIC_DEBUG_CLASSMAP_DEFINE args at compile-time
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (22 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 23/65] dyndbg: detect class_id reservation conflicts Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 25/65] dyndbg-test: change do_prints testpoint to accept a loopct Jim Cromie
                   ` (41 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jim Cromie, Andrew Morton,
	linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

Add __DYNAMIC_DEBUG_CLASSMAP_CHECK to implement the following
arg-checks at compile-time:

	0 <= _base < 63
	class_names is not empty
	class_names[0] is a string
	(class_names.length + _base) < 63

These compile-time checks will prevent several simple misuses, and
will issue obvious errors if violated.

4 such examples are added to test_dynamic_debug_submod.ko, and will
fail compilation if -DDD_MACRO_ARGCHECK is added to cflags.  This
wouldn't be a useful CONFIG_ item, since it breaks the build.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 include/linux/dynamic_debug.h |  9 +++++++++
 lib/test_dynamic_debug.c      | 13 ++++++++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 74ed18a038bd..d3889173abf3 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -181,6 +181,14 @@ struct _ddebug_class_param {
  * __pr_debug_cls(22, "no such class"); compiles but is not reachable
  */
 
+#define __DYNAMIC_DEBUG_CLASSMAP_CHECK(_clnames, _base)			\
+	static_assert(((_base) >= 0 && (_base) < _DPRINTK_CLASS_DFLT),	\
+		      "_base must be in 0..62");			\
+	static_assert(ARRAY_SIZE(_clnames) > 0,				\
+		      "classnames array size must be > 0");		\
+	static_assert((ARRAY_SIZE(_clnames) + (_base)) < _DPRINTK_CLASS_DFLT, \
+		      "_base + classnames.length exceeds range")
+
 /**
  * DYNAMIC_DEBUG_CLASSMAP_DEFINE - define debug classes used by a module.
  * @_var:   name of the classmap, exported for other modules coordinated use.
@@ -194,6 +202,7 @@ struct _ddebug_class_param {
  */
 #define DYNAMIC_DEBUG_CLASSMAP_DEFINE(_var, _mapty, _base, ...)		\
 	static const char *_var##_classnames[] = { __VA_ARGS__ };	\
+	__DYNAMIC_DEBUG_CLASSMAP_CHECK(_var##_classnames, (_base));	\
 	extern struct _ddebug_class_map _var;				\
 	struct _ddebug_class_map __aligned(8) __used			\
 		__section("__dyndbg_class_maps") _var = {		\
diff --git a/lib/test_dynamic_debug.c b/lib/test_dynamic_debug.c
index 1ba4be9a403a..b2bdfdfb6ba1 100644
--- a/lib/test_dynamic_debug.c
+++ b/lib/test_dynamic_debug.c
@@ -133,7 +133,7 @@ DYNAMIC_DEBUG_CLASSMAP_PARAM(level_num, p);
  * Enable with -Dflag on compile to test overlapping class-id range
  * detection.  This should warn on modprobes.
  */
-DYNDBG_CLASSMAP_DEFINE(classid_range_conflict, 0, D2_CORE + 1, "D3_CORE");
+DYNAMIC_DEBUG_CLASSMAP_DEFINE(classid_range_conflict, 0, D2_CORE + 1, "D3_CORE");
 #endif
 
 #else /* TEST_DYNAMIC_DEBUG_SUBMOD */
@@ -146,8 +146,19 @@ DYNDBG_CLASSMAP_DEFINE(classid_range_conflict, 0, D2_CORE + 1, "D3_CORE");
 DYNAMIC_DEBUG_CLASSMAP_USE(map_disjoint_bits);
 DYNAMIC_DEBUG_CLASSMAP_USE(map_level_num);
 
+#if defined(DD_MACRO_ARGCHECK)
+/*
+ * Exersize compile-time arg-checks in DYNAMIC_DEBUG_CLASSMAP_DEFINE.
+ * These will break compilation.
+ */
+DYNAMIC_DEBUG_CLASSMAP_DEFINE(fail_base_neg, 0, -1, "NEGATIVE_BASE_ARG");
+DYNAMIC_DEBUG_CLASSMAP_DEFINE(fail_base_big, 0, 100, "TOOBIG_BASE_ARG");
+DYNAMIC_DEBUG_CLASSMAP_DEFINE(fail_str_type, 0, 0, 1 /* not a string */);
+DYNAMIC_DEBUG_CLASSMAP_DEFINE(fail_emptyclass, 0, 0 /* ,empty */);
 #endif
 
+#endif /* TEST_DYNAMIC_DEBUG_SUBMOD */
+
 /* stand-in for all pr_debug etc */
 #define prdbg(SYM) __pr_debug_cls(SYM, #SYM " msg\n")
 
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 25/65] dyndbg-test: change do_prints testpoint to accept a loopct
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (23 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 24/65] dyndbg: check DYNAMIC_DEBUG_CLASSMAP_DEFINE args at compile-time Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 26/65] dyndbg-API: promote DYNAMIC_DEBUG_CLASSMAP_PARAM to API Jim Cromie
                   ` (40 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jim Cromie, Andrew Morton,
	linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

echo 1000 > /sys/module/test_dynamic_debug/parameters/do_prints

This allows its use as a scriptable load generator, to generate
dynamic-prefix-emits for flag combinations vs undecorated messages.
This will make it easy to assess the cost of the prefixing.

Reading the ./do_prints node also prints messages (once) to the-log.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 lib/test_dynamic_debug.c | 32 +++++++++++++++++++++-----------
 1 file changed, 21 insertions(+), 11 deletions(-)

diff --git a/lib/test_dynamic_debug.c b/lib/test_dynamic_debug.c
index b2bdfdfb6ba1..fa81177e8089 100644
--- a/lib/test_dynamic_debug.c
+++ b/lib/test_dynamic_debug.c
@@ -29,18 +29,25 @@
 
 #include <linux/module.h>
 
-/* re-gen output by reading or writing sysfs node: do_prints */
-
-static void do_prints(void); /* device under test */
+/* re-trigger debug output by reading or writing sysfs node: do_prints */
+static void do_prints(unsigned int); /* device under test */
 static int param_set_do_prints(const char *instr, const struct kernel_param *kp)
 {
-	do_prints();
+	int rc;
+	unsigned int ct;
+
+	rc = kstrtouint(instr, 0, &ct);
+	if (rc) {
+		pr_err("expecting numeric input, using 1 instead\n");
+		ct = 1;
+	}
+	do_prints(ct);
 	return 0;
 }
 static int param_get_do_prints(char *buffer, const struct kernel_param *kp)
 {
-	do_prints();
-	return scnprintf(buffer, PAGE_SIZE, "did do_prints\n");
+	do_prints(1);
+	return scnprintf(buffer, PAGE_SIZE, "did 1 do_prints\n");
 }
 static const struct kernel_param_ops param_ops_do_prints = {
 	.set = param_set_do_prints,
@@ -191,17 +198,20 @@ static void do_levels(void)
 	prdbg(V7);
 }
 
-static void do_prints(void)
+static void do_prints(unsigned int ct)
 {
-	pr_debug("do_prints:\n");
-	do_cats();
-	do_levels();
+	/* maybe clamp this */
+	pr_debug("do-prints %d times:\n", ct);
+	for (; ct; ct--) {
+		do_cats();
+		do_levels();
+	}
 }
 
 static int __init test_dynamic_debug_init(void)
 {
 	pr_debug("init start\n");
-	do_prints();
+	do_prints(1);
 	pr_debug("init done\n");
 	return 0;
 }
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 26/65] dyndbg-API: promote DYNAMIC_DEBUG_CLASSMAP_PARAM to API
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (24 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 25/65] dyndbg-test: change do_prints testpoint to accept a loopct Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 27/65] dyndbg: treat comma as a token separator Jim Cromie
                   ` (39 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jim Cromie, Andrew Morton,
	linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx, linux-doc

move the DYNAMIC_DEBUG_CLASSMAP_PARAM macro from test-dynamic-debug.c into
the header, and refine it, by distinguishing the 2 use cases:

1.DYNAMIC_DEBUG_CLASSMAP_PARAM_REF
    for DRM, to pass in extern __drm_debug by name.
    dyndbg keeps bits in it, so drm can still use it as before

2.DYNAMIC_DEBUG_CLASSMAP_PARAM
    new user (test_dynamic_debug) doesn't need to share state,
    decls a static long unsigned int to store the bitvec.

__DYNAMIC_DEBUG_CLASSMAP_PARAM
   bottom layer - allocate,init a ddebug-class-param, module-param-cb.

Modify ddebug_sync_classbits() argtype deref inside the fn, to give
access to all kp members.

Also add stub macros, clean up and improve comments in test-code, and
add MODULE_DESCRIPTIONs.

cc: linux-doc@vger.kernel.org
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 include/linux/dynamic_debug.h   | 40 ++++++++++++++++++++++
 lib/dynamic_debug.c             | 60 ++++++++++++++++++++++-----------
 lib/test_dynamic_debug.c        | 47 ++++++++++----------------
 lib/test_dynamic_debug_submod.c |  9 ++++-
 4 files changed, 106 insertions(+), 50 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index d3889173abf3..4c36c2a4801a 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -251,6 +251,44 @@ struct _ddebug_class_param {
 		.offset = _offset					\
 	}
 
+/**
+ * DYNAMIC_DEBUG_CLASSMAP_PARAM - control a ddebug-classmap from a sys-param
+ * @_name:  sysfs node name
+ * @_var:   name of the classmap var defining the controlled classes/bits
+ * @_flags: flags to be toggled, typically just 'p'
+ *
+ * Creates a sysfs-param to control the classes defined by the
+ * exported classmap, with bits 0..N-1 mapped to the classes named.
+ * This version keeps class-state in a private long int.
+ */
+#define DYNAMIC_DEBUG_CLASSMAP_PARAM(_name, _var, _flags)		\
+	static unsigned long _name##_bvec;				\
+	__DYNAMIC_DEBUG_CLASSMAP_PARAM(_name, _name##_bvec, _var, _flags)
+
+/**
+ * DYNAMIC_DEBUG_CLASSMAP_PARAM_REF - wrap a classmap with a controlling sys-param
+ * @_name:  sysfs node name
+ * @_bits:  name of the module's unsigned long bit-vector, ex: __drm_debug
+ * @_var:   name of the (exported) classmap var defining the classes/bits
+ * @_flags: flags to be toggled, typically just 'p'
+ *
+ * Creates a sysfs-param to control the classes defined by the
+ * exported clasmap, with bits 0..N-1 mapped to the classes named.
+ * This version keeps class-state in user @_bits.  This lets drm check
+ * __drm_debug elsewhere too.
+ */
+#define DYNAMIC_DEBUG_CLASSMAP_PARAM_REF(_name, _bits, _var, _flags)	\
+	__DYNAMIC_DEBUG_CLASSMAP_PARAM(_name, _bits, _var, _flags)
+
+#define __DYNAMIC_DEBUG_CLASSMAP_PARAM(_name, _bits, _var, _flags)	\
+	static struct _ddebug_class_param _name##_##_flags = {		\
+		.bits = &(_bits),					\
+		.flags = #_flags,					\
+		.map = &(_var),						\
+	};								\
+	module_param_cb(_name, &param_ops_dyndbg_classes,		\
+			&_name##_##_flags, 0600)
+
 extern __printf(2, 3)
 void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
 
@@ -433,6 +471,8 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 
 #define DYNAMIC_DEBUG_CLASSMAP_DEFINE(_var, _mapty, _base, ...)
 #define DYNAMIC_DEBUG_CLASSMAP_USE(_var)
+#define DYNAMIC_DEBUG_CLASSMAP_PARAM(_name, _var, _flags)
+#define DYNAMIC_DEBUG_CLASSMAP_PARAM_REF(_name, _var, _flags)
 #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)
 #define DYNAMIC_DEBUG_BRANCH(descriptor) false
 #define DECLARE_DYNDBG_CLASSMAP(...)
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index ec0d1c427d59..e383e93dc784 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -687,6 +687,30 @@ static int ddebug_apply_class_bitmap(const struct _ddebug_class_param *dcp,
 
 #define CLASSMAP_BITMASK(width) ((1UL << (width)) - 1)
 
+static void ddebug_class_param_clamp_input(unsigned long *inrep, const struct kernel_param *kp)
+{
+	const struct _ddebug_class_param *dcp = kp->arg;
+	const struct _ddebug_class_map *map = dcp->map;
+
+	switch (map->map_type) {
+	case DD_CLASS_TYPE_DISJOINT_BITS:
+		/* expect bits. mask and warn if too many */
+		if (*inrep & ~CLASSMAP_BITMASK(map->length)) {
+			pr_warn("%s: input: 0x%lx exceeds mask: 0x%lx, masking\n",
+				KP_NAME(kp), *inrep, CLASSMAP_BITMASK(map->length));
+			*inrep &= CLASSMAP_BITMASK(map->length);
+		}
+		break;
+	case DD_CLASS_TYPE_LEVEL_NUM:
+		/* input is bitpos, of highest verbosity to be enabled */
+		if (*inrep > map->length) {
+			pr_warn("%s: level:%ld exceeds max:%d, clamping\n",
+				KP_NAME(kp), *inrep, map->length);
+			*inrep = map->length;
+		}
+		break;
+	}
+}
 static int param_set_dyndbg_module_classes(const char *instr,
 					   const struct kernel_param *kp,
 					   const char *mod_name)
@@ -705,26 +729,15 @@ static int param_set_dyndbg_module_classes(const char *instr,
 		pr_err("expecting numeric input, not: %s > %s\n", instr, KP_NAME(kp));
 		return -EINVAL;
 	}
+	ddebug_class_param_clamp_input(&inrep, kp);
 
 	switch (map->map_type) {
 	case DD_CLASS_TYPE_DISJOINT_BITS:
-		/* expect bits. mask and warn if too many */
-		if (inrep & ~CLASSMAP_BITMASK(map->length)) {
-			pr_warn("%s: input: 0x%lx exceeds mask: 0x%lx, masking\n",
-				KP_NAME(kp), inrep, CLASSMAP_BITMASK(map->length));
-			inrep &= CLASSMAP_BITMASK(map->length);
-		}
 		v2pr_info("bits:0x%lx > %s.%s\n", inrep, mod_name ?: "*", KP_NAME(kp));
 		totct += ddebug_apply_class_bitmap(dcp, &inrep, *dcp->bits, mod_name);
 		*dcp->bits = inrep;
 		break;
 	case DD_CLASS_TYPE_LEVEL_NUM:
-		/* input is bitpos, of highest verbosity to be enabled */
-		if (inrep > map->length) {
-			pr_warn("%s: level:%ld exceeds max:%d, clamping\n",
-				KP_NAME(kp), inrep, map->length);
-			inrep = map->length;
-		}
 		old_bits = CLASSMAP_BITMASK(*dcp->lvl);
 		new_bits = CLASSMAP_BITMASK(inrep);
 		v2pr_info("lvl:%ld bits:0x%lx > %s\n", inrep, new_bits, KP_NAME(kp));
@@ -1195,15 +1208,24 @@ static const struct proc_ops proc_fops = {
 static void ddebug_sync_classbits(const struct kernel_param *kp, const char *modname)
 {
 	const struct _ddebug_class_param *dcp = kp->arg;
+	unsigned long new_bits;
 
-	/* clamp initial bitvec, mask off hi-bits */
-	if (*dcp->bits & ~CLASSMAP_BITMASK(dcp->map->length)) {
-		*dcp->bits &= CLASSMAP_BITMASK(dcp->map->length);
-		v2pr_info("preset classbits: %lx\n", *dcp->bits);
+	ddebug_class_param_clamp_input(dcp->bits, kp);
+
+	switch (dcp->map->map_type) {
+	case DD_CLASS_TYPE_DISJOINT_BITS:
+		v2pr_info("  %s: classbits: 0x%lx\n", KP_NAME(kp), *dcp->bits);
+		ddebug_apply_class_bitmap(dcp, dcp->bits, 0UL, modname);
+		break;
+	case DD_CLASS_TYPE_LEVEL_NUM:
+		new_bits = CLASSMAP_BITMASK(*dcp->lvl);
+		v2pr_info("  %s: lvl:%ld bits:0x%lx\n", KP_NAME(kp), *dcp->lvl, new_bits);
+		ddebug_apply_class_bitmap(dcp, &new_bits, 0UL, modname);
+		break;
+	default:
+		pr_err("bad map type %d\n", dcp->map->map_type);
+		return;
 	}
-	/* force class'd prdbgs (in USEr module) to match (DEFINEr module) class-param */
-	ddebug_apply_class_bitmap(dcp, dcp->bits, ~0, modname);
-	ddebug_apply_class_bitmap(dcp, dcp->bits, 0, modname);
 }
 
 static void ddebug_match_apply_kparam(const struct kernel_param *kp,
diff --git a/lib/test_dynamic_debug.c b/lib/test_dynamic_debug.c
index fa81177e8089..83c4d571a8c9 100644
--- a/lib/test_dynamic_debug.c
+++ b/lib/test_dynamic_debug.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Kernel module for testing dynamic_debug
+ * Kernel module to test/demonstrate dynamic_debug features,
+ * particularly classmaps and their support for subsystems like DRM.
  *
  * Authors:
  *      Jim Cromie	<jim.cromie@gmail.com>
@@ -57,24 +58,6 @@ module_param_cb(do_prints, &param_ops_do_prints, NULL, 0600);
 
 #define CLASSMAP_BITMASK(width, base) (((1UL << (width)) - 1) << (base))
 
-/* sysfs param wrapper, proto-API */
-#define DYNAMIC_DEBUG_CLASSMAP_PARAM_(_model, _flags, _init)		\
-	static unsigned long bits_##_model = _init;			\
-	static struct _ddebug_class_param _flags##_##_model = {		\
-		.bits = &bits_##_model,					\
-		.flags = #_flags,					\
-		.map = &map_##_model,					\
-	};								\
-	module_param_cb(_flags##_##_model, &param_ops_dyndbg_classes,	\
-			&_flags##_##_model, 0600)
-#ifdef DEBUG
-#define DYNAMIC_DEBUG_CLASSMAP_PARAM(_model, _flags)		\
-	DYNAMIC_DEBUG_CLASSMAP_PARAM_(_model, _flags, ~0)
-#else
-#define DYNAMIC_DEBUG_CLASSMAP_PARAM(_model, _flags)		\
-	DYNAMIC_DEBUG_CLASSMAP_PARAM_(_model, _flags, 0)
-#endif
-
 /*
  * Demonstrate/test DISJOINT & LEVEL typed classmaps with a sys-param.
  *
@@ -105,12 +88,15 @@ enum cat_disjoint_bits {
 /* numeric verbosity, V2 > V1 related.  V0 is > D2_DRMRES */
 enum cat_level_num { V0 = 16, V1, V2, V3, V4, V5, V6, V7 };
 
-/* recapitulate DRM's multi-classmap setup */
+/*
+ * use/demonstrate multi-module-group classmaps, as for DRM
+ */
 #if !defined(TEST_DYNAMIC_DEBUG_SUBMOD)
 /*
- * In single user, or parent / coordinator (drm.ko) modules, define
- * classmaps on the client enums above, and then declares the PARAMS
- * ref'g the classmaps.  Each is exported.
+ * For module-groups of 1+, define classmaps with names (stringified
+ * enum-symbols) copied from above. 1-to-1 mapping is recommended.
+ * The classmap is exported, so that other modules in the group can
+ * link to it and control their prdbgs.
  */
 DYNAMIC_DEBUG_CLASSMAP_DEFINE(map_disjoint_bits, DD_CLASS_TYPE_DISJOINT_BITS,
 			      D2_CORE,
@@ -129,11 +115,13 @@ DYNAMIC_DEBUG_CLASSMAP_DEFINE(map_level_num, DD_CLASS_TYPE_LEVEL_NUM,
 			      V0, "V0", "V1", "V2", "V3", "V4", "V5", "V6", "V7");
 
 /*
- * now add the sysfs-params
+ * for use-cases that want it, provide a sysfs-param to set the
+ * classes in the classmap.  It is at this interface where the
+ * "v3>v2" property is applied to DD_CLASS_TYPE_LEVEL_NUM inputs.
  */
 
-DYNAMIC_DEBUG_CLASSMAP_PARAM(disjoint_bits, p);
-DYNAMIC_DEBUG_CLASSMAP_PARAM(level_num, p);
+DYNAMIC_DEBUG_CLASSMAP_PARAM(p_disjoint_bits,	map_disjoint_bits, p);
+DYNAMIC_DEBUG_CLASSMAP_PARAM(p_level_num,	map_level_num, p);
 
 #ifdef FORCE_CLASSID_CONFLICT
 /*
@@ -144,12 +132,10 @@ DYNAMIC_DEBUG_CLASSMAP_DEFINE(classid_range_conflict, 0, D2_CORE + 1, "D3_CORE")
 #endif
 
 #else /* TEST_DYNAMIC_DEBUG_SUBMOD */
-
 /*
- * in submod/drm-drivers, use the classmaps defined in top/parent
- * module above.
+ * the +1 members of a multi-module group refer to the classmap
+ * DEFINEd (and exported) above.
  */
-
 DYNAMIC_DEBUG_CLASSMAP_USE(map_disjoint_bits);
 DYNAMIC_DEBUG_CLASSMAP_USE(map_level_num);
 
@@ -224,6 +210,7 @@ static void __exit test_dynamic_debug_exit(void)
 module_init(test_dynamic_debug_init);
 module_exit(test_dynamic_debug_exit);
 
+MODULE_DESCRIPTION("test/demonstrate dynamic-debug features");
 MODULE_AUTHOR("Jim Cromie <jim.cromie@gmail.com>");
 MODULE_DESCRIPTION("Kernel module for testing dynamic_debug");
 MODULE_LICENSE("GPL");
diff --git a/lib/test_dynamic_debug_submod.c b/lib/test_dynamic_debug_submod.c
index 672aabf40160..3adf3925fb86 100644
--- a/lib/test_dynamic_debug_submod.c
+++ b/lib/test_dynamic_debug_submod.c
@@ -1,6 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Kernel module for testing dynamic_debug
+ * Kernel module to test/demonstrate dynamic_debug features,
+ * particularly classmaps and their support for subsystems, like DRM,
+ * which defines its drm_debug classmap in drm module, and uses it in
+ * helpers & drivers.
  *
  * Authors:
  *      Jim Cromie	<jim.cromie@gmail.com>
@@ -12,3 +15,7 @@
  */
 #define TEST_DYNAMIC_DEBUG_SUBMOD
 #include "test_dynamic_debug.c"
+
+MODULE_DESCRIPTION("test/demonstrate dynamic-debug subsystem support");
+MODULE_AUTHOR("Jim Cromie <jim.cromie@gmail.com>");
+MODULE_LICENSE("GPL");
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 27/65] dyndbg: treat comma as a token separator
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (25 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 26/65] dyndbg-API: promote DYNAMIC_DEBUG_CLASSMAP_PARAM to API Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 28/65] dyndbg: split multi-query strings with % Jim Cromie
                   ` (38 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jonathan Corbet, Shuah Khan,
	Andrew Morton, Jim Cromie, linux-doc, linux-kernel,
	linux-kselftest
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

Treat comma as a token terminator, just like a space.  This allows a
user to avoid quoting hassles when spaces are otherwise needed:

 :#> modprobe drm dyndbg=class,DRM_UT_CORE,+p\;class,DRM_UT_KMS,+p

or as a boot arg:

 drm.dyndbg=class,DRM_UT_CORE,+p  # todo: support multi-query here

Given the many ways a boot-line +args can be assembled and then passed
in/down/around shell based tools, this may allow side-stepping all
sorts of quoting hassles thru those layers.

existing query format:

 modprobe test_dynamic_debug dyndbg="class D2_CORE +p"

new format:

 modprobe test_dynamic_debug dyndbg=class,D2_CORE,+p

ALSO

selftests-dyndbg: add comma_terminator_tests

New fn validates parsing and effect of queries using combinations of
commas and spaces to delimit the tokens.

It manipulates pr-debugs in builtin module/params, so might have deps
I havent foreseen on odd configurations.

Co-developed-by: Łukasz Bartosik <ukaszb@chromium.org>
Signed-off-by: Łukasz Bartosik <ukaszb@chromium.org>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 .../admin-guide/dynamic-debug-howto.rst       |  9 +++++---
 lib/dynamic_debug.c                           | 17 +++++++++++----
 .../dynamic_debug/dyndbg_selftest.sh          | 21 ++++++++++++++++++-
 3 files changed, 39 insertions(+), 8 deletions(-)

diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst b/Documentation/admin-guide/dynamic-debug-howto.rst
index 9c2f096ed1d8..dbf901150587 100644
--- a/Documentation/admin-guide/dynamic-debug-howto.rst
+++ b/Documentation/admin-guide/dynamic-debug-howto.rst
@@ -78,11 +78,12 @@ Command Language Reference
 ==========================
 
 At the basic lexical level, a command is a sequence of words separated
-by spaces or tabs.  So these are all equivalent::
+by spaces, tabs, or commas.  So these are all equivalent::
 
   :#> ddcmd file svcsock.c line 1603 +p
   :#> ddcmd "file svcsock.c line 1603 +p"
   :#> ddcmd '  file   svcsock.c     line  1603 +p  '
+  :#> ddcmd file,svcsock.c,line,1603,+p
 
 Command submissions are bounded by a write() system call.
 Multiple commands can be written together, separated by ``;`` or ``\n``::
@@ -167,9 +168,11 @@ module
     The given string is compared against the module name
     of each callsite.  The module name is the string as
     seen in ``lsmod``, i.e. without the directory or the ``.ko``
-    suffix and with ``-`` changed to ``_``.  Examples::
+    suffix and with ``-`` changed to ``_``.
 
-	module sunrpc
+    Examples::
+
+	module,sunrpc	# with ',' as token separator
 	module nfsd
 	module drm*	# both drm, drm_kms_helper
 
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index e383e93dc784..a77c6e9ff90c 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -320,6 +320,14 @@ static int ddebug_change(const struct ddebug_query *query, struct flag_settings
 	return nfound;
 }
 
+static char *skip_spaces_and_commas(const char *str)
+{
+	str = skip_spaces(str);
+	while (*str == ',')
+		str = skip_spaces(++str);
+	return (char *)str;
+}
+
 /*
  * Split the buffer `buf' into space-separated words.
  * Handles simple " and ' quoting, i.e. without nested,
@@ -333,8 +341,8 @@ static int ddebug_tokenize(char *buf, char *words[], int maxwords)
 	while (*buf) {
 		char *end;
 
-		/* Skip leading whitespace */
-		buf = skip_spaces(buf);
+		/* Skip leading whitespace and comma */
+		buf = skip_spaces_and_commas(buf);
 		if (!*buf)
 			break;	/* oh, it was trailing whitespace */
 		if (*buf == '#')
@@ -350,7 +358,7 @@ static int ddebug_tokenize(char *buf, char *words[], int maxwords)
 				return -EINVAL;	/* unclosed quote */
 			}
 		} else {
-			for (end = buf; *end && !isspace(*end); end++)
+			for (end = buf; *end && !isspace(*end) && *end != ','; end++)
 				;
 			if (end == buf) {
 				pr_err("parse err after word:%d=%s\n", nwords,
@@ -622,7 +630,8 @@ static int ddebug_exec_queries(char *query, const char *modname)
 		if (split)
 			*split++ = '\0';
 
-		query = skip_spaces(query);
+		query = skip_spaces_and_commas(query);
+
 		if (!query || !*query || *query == '#')
 			continue;
 
diff --git a/tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh b/tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh
index 465fad3f392c..c7bf521f36ee 100755
--- a/tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh
+++ b/tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh
@@ -216,7 +216,7 @@ function check_err_msg() {
 function basic_tests {
     echo -e "${GREEN}# BASIC_TESTS ${NC}"
     if [ $LACK_DD_BUILTIN -eq 1 ]; then
-	echo "SKIP"
+	echo "SKIP - test requires params, which is a builtin module"
 	return
     fi
     ddcmd =_ # zero everything
@@ -238,8 +238,27 @@ EOF
     ddcmd =_
 }
 
+function comma_terminator_tests {
+    echo -e "${GREEN}# COMMA_TERMINATOR_TESTS ${NC}"
+    if [ $LACK_DD_BUILTIN -eq 1 ]; then
+	echo "SKIP - test requires params, which is a builtin module"
+	return
+    fi
+    # try combos of spaces & commas
+    check_match_ct '\[params\]' 4 -r
+    ddcmd module,params,=_		# commas as spaces
+    ddcmd module,params,+mpf		# turn on module's pr-debugs
+    check_match_ct =pmf 4
+    ddcmd ,module ,, ,  params, -p
+    check_match_ct =mf 4
+    ddcmd " , module ,,, ,  params, -m"	#
+    check_match_ct =f 4
+    ddcmd =_
+}
+
 tests_list=(
     basic_tests
+    comma_terminator_tests
 )
 
 # Run tests
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 28/65] dyndbg: split multi-query strings with %
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (26 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 27/65] dyndbg: treat comma as a token separator Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 29/65] selftests-dyndbg: add test_mod_submod Jim Cromie
                   ` (37 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jonathan Corbet, Shuah Khan,
	Andrew Morton, Jim Cromie, linux-doc, linux-kernel,
	linux-kselftest
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

Since commit
85f7f6c0edb8 ("dynamic_debug: process multiple debug-queries on a line")

Multi-query commands have been allowed:

  modprobe drm dyndbg="class DRM_UT_CORE +p; class DRM_UT_KMS +p"
  modprobe drm dyndbg=<<EOX
     class DRM_UT_CORE +p
     class DRM_UT_KMS +p
  EOX

More recently, the need for quoting was avoided by treating a comma
like a space/token-terminator:

  modprobe drm dyndbg=class,DRM_UT_CORE,+p\;class,DRM_UT_KMS,+p

That works, but it needs the escaped semicolon, which is a shell
special-char (one of the bash control operators), so it is brittle
when passed in/down/around scripts.  In particular, it fails when
passed to vng (virtme-ng).

So this patch adds '%' to the existing ';' and '\n' multi-command
separators, which is more shell-friendly, so you can more fully avoid
quoting and escaping hassles.

NOTE: it does break format matching on '%' patterns:

bash-5.2# ddcmd 'format "find-me: %foo" +p'
[  203.900581] dyndbg: read 26 bytes from userspace
[  203.900883] dyndbg: query 0: "format "find-me: " mod:*
[  203.901118] dyndbg: unclosed quote: find-me:
[  203.901355] dyndbg: tokenize failed
[  203.901529] dyndbg: query 1: "foo" +p" mod:*
[  203.901957] dyndbg: split into words: "foo"" "+p"
[  203.902243] dyndbg: op='+' flags=0x1 maskp=0xffffffff
[  203.902458] dyndbg: expecting pairs of match-spec <value>
[  203.902703] dyndbg: query parse failed
[  203.902871] dyndbg: processed 2 queries, with 0 matches, 2 errs
bash: echo: write error: Invalid argument

The '%' splits the input into 2 queries, and both fail.  Given the
limited utility of matching against the working parts of a format
string "foo: %d bar %s", nothing is actually lost here.

selftests-dyndbg: test_percent_splitting

This does basic testing of classmaps using '%' separated
multi-queries.  It modprobes test_dynamic_debug with several classes
enabled, and counts to verify that the expected sites show the
enablement in the control file.

Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 .../admin-guide/dynamic-debug-howto.rst       |  8 ++++---
 lib/dynamic_debug.c                           |  2 +-
 .../dynamic_debug/dyndbg_selftest.sh          | 24 +++++++++++++++++++
 3 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst b/Documentation/admin-guide/dynamic-debug-howto.rst
index dbf901150587..0a42b9de55ac 100644
--- a/Documentation/admin-guide/dynamic-debug-howto.rst
+++ b/Documentation/admin-guide/dynamic-debug-howto.rst
@@ -85,10 +85,12 @@ by spaces, tabs, or commas.  So these are all equivalent::
   :#> ddcmd '  file   svcsock.c     line  1603 +p  '
   :#> ddcmd file,svcsock.c,line,1603,+p
 
-Command submissions are bounded by a write() system call.
-Multiple commands can be written together, separated by ``;`` or ``\n``::
+Command submissions are bounded by a write() system call.  Multiple
+commands can be written together, separated by ``%``, ``;`` or ``\n``::
 
-  :#> ddcmd "func pnpacpi_get_resources +p; func pnp_assign_mem +p"
+  :#> ddcmd func foo +p % func bar +p
+  :#> ddcmd func foo +p \; func bar +p
+  :#> ddcmd "func foo +p ; func bar +p"
   :#> ddcmd <<"EOC"
   func pnpacpi_get_resources +p
   func pnp_assign_mem +p
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index a77c6e9ff90c..a1c3141372d1 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -626,7 +626,7 @@ static int ddebug_exec_queries(char *query, const char *modname)
 	int i, errs = 0, exitcode = 0, rc, nfound = 0;
 
 	for (i = 0; query; query = split) {
-		split = strpbrk(query, ";\n");
+		split = strpbrk(query, "%;\n");
 		if (split)
 			*split++ = '\0';
 
diff --git a/tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh b/tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh
index c7bf521f36ee..513f6cb1db1d 100755
--- a/tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh
+++ b/tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh
@@ -256,9 +256,33 @@ function comma_terminator_tests {
     ddcmd =_
 }
 
+function test_percent_splitting {
+    echo -e "${GREEN}# TEST_PERCENT_SPLITTING - multi-command splitting on % ${NC}"
+    if [ $LACK_TMOD -eq 1 ]; then
+	echo "SKIP - test requires test-dynamic-debug.ko"
+	return
+    fi
+    ifrmmod test_dynamic_debug_submod
+    ifrmmod test_dynamic_debug
+    ddcmd =_
+    modprobe test_dynamic_debug dyndbg=class,D2_CORE,+pf%class,D2_KMS,+pt%class,D2_ATOMIC,+pm
+    check_match_ct =pf 1
+    check_match_ct =pt 1
+    check_match_ct =pm 1
+    check_match_ct test_dynamic_debug 23 -r
+    # add flags to those callsites
+    ddcmd class,D2_CORE,+mf%class,D2_KMS,+lt%class,D2_ATOMIC,+ml
+    check_match_ct =pmf 1
+    check_match_ct =plt 1
+    check_match_ct =pml 1
+    check_match_ct test_dynamic_debug 23 -r
+    ifrmmod test_dynamic_debug
+}
+
 tests_list=(
     basic_tests
     comma_terminator_tests
+    test_percent_splitting
 )
 
 # Run tests
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 29/65] selftests-dyndbg: add test_mod_submod
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (27 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 28/65] dyndbg: split multi-query strings with % Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 30/65] dyndbg: resolve "protection" of class'd pr_debug Jim Cromie
                   ` (36 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jim Cromie, Shuah Khan,
	linux-kselftest, linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

This new test-fn runs 3 module/submodule modprobe scenarios, variously
using both the generic dyndbg=<queries> modprobe arg, and the
test-module's classmap-params to manipulate the test-mod*'s pr_debugs.
In all cases, the current flag-settings are counted and tested vs
expectations.

The 3rd scenario recapitulates the DRM_USE_DYNAMIC_DEBUG=y failure.

1. 2 modprobes (super then sub), with separate dyndbg=class-settings
   check module specific flag settings

2. modprobe submod, supermod is auto-loaded
   set supermod class-params
   check expected enablements in super & submod

3. modprobe super, with param=setting (like drm.debug=0x1ef)
   modprobe submod
   validate submod's class'd pr_debugs get properly enabled

The test uses multi-queries, with both commas and percents (to avoid
spaces and quoting).  This is the main reason the test wasn't earlier
in the patchset, closer to the classmap patches its validating.

With some tedium, the tests could be refactored to split out early
tests which avoid multi-cmds, and test only the class-params.

Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 .../dynamic_debug/dyndbg_selftest.sh          | 73 +++++++++++++++++++
 1 file changed, 73 insertions(+)

diff --git a/tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh b/tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh
index 513f6cb1db1d..09937dca3056 100755
--- a/tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh
+++ b/tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh
@@ -279,10 +279,83 @@ function test_percent_splitting {
     ifrmmod test_dynamic_debug
 }
 
+function test_mod_submod {
+    echo -e "${GREEN}# TEST_MOD_SUBMOD ${NC}"
+    if [ $LACK_TMOD -eq 1 ]; then
+	echo "SKIP - test requires test-dynamic-debug.ko"
+	return
+    fi
+    ifrmmod test_dynamic_debug_submod
+    ifrmmod test_dynamic_debug
+    ddcmd =_
+
+    # modprobe with class enablements
+    modprobe test_dynamic_debug \
+	dyndbg=class,D2_CORE,+pf%class,D2_KMS,+pt%class,D2_ATOMIC,+pm
+
+    check_match_ct '\[test_dynamic_debug\]' 23 -r
+    check_match_ct =pf 1
+    check_match_ct =pt 1
+    check_match_ct =pm 1
+
+    modprobe test_dynamic_debug_submod
+    check_match_ct test_dynamic_debug_submod 23 -r
+    check_match_ct '\[test_dynamic_debug\]' 23 -r
+    check_match_ct test_dynamic_debug 46 -r
+
+    # no enablements propagate here
+    check_match_ct =pf 1
+    check_match_ct =pt 1
+    check_match_ct =pm 1
+
+    # change classes again, this time submod too
+    ddcmd class,D2_CORE,+mf%class,D2_KMS,+lt%class,D2_ATOMIC,+ml "# add some prefixes"
+    check_match_ct =pmf 1
+    check_match_ct =plt 1
+    check_match_ct =pml 1
+    #  submod changed too
+    check_match_ct =mf 1
+    check_match_ct =lt 1
+    check_match_ct =ml 1
+
+    # now work the classmap-params
+    # fresh start, to clear all above flags (test-fn limits)
+    ifrmmod test_dynamic_debug_submod
+    ifrmmod test_dynamic_debug
+    modprobe test_dynamic_debug_submod # get supermod too
+
+    echo 1 > /sys/module/test_dynamic_debug/parameters/p_disjoint_bits
+    echo 4 > /sys/module/test_dynamic_debug/parameters/p_level_num
+    # 2 mods * ( V1-3 + D2_CORE )
+    check_match_ct =p 8
+    echo 3 > /sys/module/test_dynamic_debug/parameters/p_disjoint_bits
+    echo 0 > /sys/module/test_dynamic_debug/parameters/p_level_num
+    # 2 mods * ( D2_CORE, D2_DRIVER )
+    check_match_ct =p 4
+    echo 0x16 > /sys/module/test_dynamic_debug/parameters/p_disjoint_bits
+    echo 0 > /sys/module/test_dynamic_debug/parameters/p_level_num
+    # 2 mods * ( D2_DRIVER, D2_KMS, D2_ATOMIC )
+    check_match_ct =p 6
+
+    # recap DRM_USE_DYNAMIC_DEBUG regression
+    ifrmmod test_dynamic_debug_submod
+    ifrmmod test_dynamic_debug
+    # set super-mod params
+    modprobe test_dynamic_debug p_disjoint_bits=0x16 p_level_num=5
+    check_match_ct =p 7
+    modprobe test_dynamic_debug_submod
+    # see them picked up by submod
+    check_match_ct =p 14
+    ifrmmod test_dynamic_debug_submod
+    ifrmmod test_dynamic_debug
+}
+
 tests_list=(
     basic_tests
+    # these require test_dynamic_debug*.ko
     comma_terminator_tests
     test_percent_splitting
+    test_mod_submod
 )
 
 # Run tests
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 30/65] dyndbg: resolve "protection" of class'd pr_debug
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (28 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 29/65] selftests-dyndbg: add test_mod_submod Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 31/65] dyndbg: add DYNAMIC_DEBUG_CLASSMAP_USE_(dd_class_name, offset) Jim Cromie
                   ` (35 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jim Cromie, Andrew Morton,
	linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

classmap-v1 code protected class'd pr_debugs from unintended
changes by unclassed/_DFLT queries:

  # - to declutter examples:
  alias ddcmd='echo $* > /proc/dynamic_debug/control'

  # IOW, this should NOT alter drm.debug settings
  ddcmd -p

  # Instead, you must name the class to change it.
  # Protective but tedious
  ddcmd class DRM_UT_CORE +p

  # Or do it the (old school) subsystem way
  # This is ABI !!
  echo 1 > /sys/module/drm/parameters/debug

Since the debug sysfs-node is ABI, if dyndbg is going to implement it,
it must also honor its settings; it must at least protect against
accidental changes to its classes from legacy queries.

The protection allows all previously conceived queries to work the way
they always have; ie select the same set of pr_debugs, despite the
inclusion of whole new classes of pr_debugs.

But that choice has 2 downsides:

1. "name the class to change it" makes a tedious long-winded
interface, needing many commands to set DRM_UT_* one at a time.

2. It makes the class keyword special in some sense; the other
keywords skip only on query mismatch, otherwise the code falls thru to
adjust the pr-debug site.

 Jason Baron	didn't like v1 on point 2.
 Louis Chauvet	didn't like recent rev on point 1 tedium.

But that said: /sys/ is ABI, so this must be reliable:

  #> echo 0x1f > /sys/module/drm/parameters/debug

It 'just works' without dyndbg underneath; we must deliver that same
stability.  Convenience is secondary.

The new resolution:

If ABI is the blocking issue, then no ABI means no blocking issue.
IOW, if the classmap has no presence under /sys/*, ie no PARAM, there
is no ABI to guard, and no reason to enforce a tedious interface.

In the future, if DRM wants to alter this protection, that is
practical, but I think default-on is the correct mode.

So atm classes without a PARAM are unprotected at >control, allowing
admins their shortcuts.  I think this could satisfy all viewpoints.

That said, theres also a possibility of wildcard classes:

   #> ddcmd class '*' +p

Currently, the query-class is exact-matched against each module's
classmaps.names.  This gives precise behavior, a good basis.

But class wildcards are possible, they just did'nt appear useful for
DRM, whose classmap names are a flat DRM_UT_* namespace.

IOW, theres no useful selectivity there:

   #> ddcmd class "DRM_*" +p		# these enable every DRM_* class
   #> ddcmd class "DRM_UT_*" +p

   #> ddcmd class "DRM_UT_V*" +p	# finally select just 1: DRM_UT_VBL
   #> ddcmd class "DRM_UT_D*" +p	# but this gets 3

   #> ddcmd class "D*V*" +p		# here be dragons

But there is debatable utility in the feature.

   #> ddcmd class __DEFAULT__ -p	# what about this ?
   #> ddcmd -p				# thats what this does. automatically

Anyway, this patch does:

1. adds link field from _ddebug_class_map to the .controlling_param

2. sets it in ddebug_match_apply_kparam(), during modprobe/init,
   when options like drm.debug=VAL are handled.

3. ddebug_class_has_param() now checks .controlling_param

4. ddebug_class_wants_protection() macro renames 3.
   this frames it as a separable policy decision

5. ddebug_match_desc() gets the most attention:

a. move classmap consideration to the bottom
   this insures all other constraints act 1st.
   allows simpler 'final' decisions.

b. split class choices cleanly on query:
   class FOO vs none, and class'd vs _DPRINTK_CLASS_DFLT site.

c. calls 4 when applying a class-less query to a class'd pr_debug
   here we need a new fn to find the classmap with this .class_id

d. calls new ddebug_find_classmap_by_class_id().
   when class-less query looks at a class'd pr_debug.
   finds classmap, which can then decide, currently by PARAM existence.

NOTES:

protection is only against class-less queries, explicit "class FOO"
adjustments are allowed (that is the mechanism).

The drm.debug sysfs-node heavily under-specifies the class'd pr_debugs
it controls; none of the +mfls prefixing flags have any effect, and
each callsite remains individually controllable. drm.debug just
toggles the +p flag for all the modules' class'd pr_debugs.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 include/linux/dynamic_debug.h |  14 ++--
 lib/dynamic_debug.c           | 128 +++++++++++++++++++++++++++-------
 2 files changed, 111 insertions(+), 31 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 4c36c2a4801a..a1454db1bcb0 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -76,6 +76,7 @@ enum ddebug_class_map_type {
  * map @class_names 0..N to consecutive constants starting at @base.
  */
 struct _ddebug_class_map {
+	struct _ddebug_class_param *controlling_param;
 	const struct module *mod;	/* NULL for builtins */
 	const char *mod_name;
 	const char **class_names;
@@ -259,7 +260,12 @@ struct _ddebug_class_param {
  *
  * Creates a sysfs-param to control the classes defined by the
  * exported classmap, with bits 0..N-1 mapped to the classes named.
- * This version keeps class-state in a private long int.
+ *
+ * Since sysfs-params are ABI, this also protects the classmap'd
+ * pr_debugs from un-class'd `echo -p > /proc/dynamic_debug/control`
+ * changes.
+ *
+ * This keeps class-state in a private long int.
  */
 #define DYNAMIC_DEBUG_CLASSMAP_PARAM(_name, _var, _flags)		\
 	static unsigned long _name##_bvec;				\
@@ -272,10 +278,8 @@ struct _ddebug_class_param {
  * @_var:   name of the (exported) classmap var defining the classes/bits
  * @_flags: flags to be toggled, typically just 'p'
  *
- * Creates a sysfs-param to control the classes defined by the
- * exported clasmap, with bits 0..N-1 mapped to the classes named.
- * This version keeps class-state in user @_bits.  This lets drm check
- * __drm_debug elsewhere too.
+ * Like DYNAMIC_DEBUG_CLASSMAP_PARAM, but maintains param-state in
+ * extern @_bits.  This lets DRM check __drm_debug elsewhere too.
  */
 #define DYNAMIC_DEBUG_CLASSMAP_PARAM_REF(_name, _bits, _var, _flags)	\
 	__DYNAMIC_DEBUG_CLASSMAP_PARAM(_name, _bits, _var, _flags)
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index a1c3141372d1..e9fa0c8868db 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -206,6 +206,50 @@ ddebug_find_valid_class(struct _ddebug_info const *di, const char *query_class,
 	return NULL;
 }
 
+static bool ddebug_class_in_range(const int class_id, const struct _ddebug_class_map *map)
+{
+	return (class_id >= map->base &&
+		class_id < map->base + map->length);
+}
+
+static struct _ddebug_class_map *
+ddebug_find_map_by_class_id(struct _ddebug_info *di, int class_id)
+{
+	struct _ddebug_class_map *map;
+	struct _ddebug_class_user *cli;
+	int i;
+
+	for_subvec(i, map, di, maps)
+		if (ddebug_class_in_range(class_id, map))
+			return map;
+
+	for_subvec(i, cli, di, users)
+		if (ddebug_class_in_range(class_id, cli->map))
+			return cli->map;
+
+	return NULL;
+}
+
+/*
+ * classmaps-V1 protected classes from changes by legacy commands
+ * (those selecting _DPRINTK_CLASS_DFLT by omission).  This had the
+ * downside that saying "class FOO" for every change can get tedious.
+ *
+ * V2 is smarter, it protects class-maps if the defining module also
+ * calls DYNAMIC_DEBUG_CLASSMAP_PARAM to create a sysfs parameter.
+ * Since the author wants the knob, we should assume they intend to
+ * use it (in preference to "class FOO +p" >control), and want to
+ * trust its settings.  This gives protection when its useful, and not
+ * when its just tedious.
+ */
+static inline bool ddebug_class_has_param(const struct _ddebug_class_map *map)
+{
+	return !!(map->controlling_param);
+}
+
+/* re-framed as a policy choice */
+#define ddebug_class_wants_protection(map) (ddebug_class_has_param(map))
+
 /*
  * Search the tables for _ddebug's which match the given `query' and
  * apply the `flags' and `mask' to them.  Returns number of matching
@@ -214,11 +258,10 @@ ddebug_find_valid_class(struct _ddebug_info const *di, const char *query_class,
  */
 static bool ddebug_match_desc(const struct ddebug_query *query,
 			      struct _ddebug *dp,
-			      int valid_class)
+			      struct _ddebug_info *di,
+			      int selected_class)
 {
-	/* match site against query-class */
-	if (dp->class_id != valid_class)
-		return false;
+	struct _ddebug_class_map *site_map;
 
 	/* match against the source filename */
 	if (query->filename &&
@@ -255,7 +298,29 @@ static bool ddebug_match_desc(const struct ddebug_query *query,
 	    dp->lineno > query->last_lineno)
 		return false;
 
-	return true;
+	/*
+	 * above are all satisfied, so we can make final decisions:
+	 * 1- class FOO or implied class __DEFAULT__
+	 * 2- site.is_classed or not
+	 */
+	if (query->class_string) {
+		/* class FOO given, exact match required */
+		return (dp->class_id == selected_class);
+	}
+	/* query class __DEFAULT__ by omission. */
+	if (dp->class_id == _DPRINTK_CLASS_DFLT) {
+		/* un-classed site */
+		return true;
+	}
+	/* site is class'd */
+	site_map = ddebug_find_map_by_class_id(di, dp->class_id);
+	if (!site_map) {
+		WARN_ONCE(1, "unknown class_id %d, check %s's CLASSMAP definitions",
+			  dp->class_id, di->mod_name);
+		return false;
+	}
+	/* module(-param) decides protection */
+	return !ddebug_class_wants_protection(site_map);
 }
 
 static int ddebug_change(const struct ddebug_query *query, struct flag_settings *modifiers)
@@ -265,33 +330,31 @@ static int ddebug_change(const struct ddebug_query *query, struct flag_settings
 	unsigned int newflags;
 	unsigned int nfound = 0;
 	struct flagsbuf fbuf, nbuf;
-	struct _ddebug_class_map *map = NULL;
-	int valid_class;
+	int selected_class;
 
 	/* search for matching ddebugs */
 	mutex_lock(&ddebug_lock);
 	list_for_each_entry(dt, &ddebug_tables, link) {
 		struct _ddebug_info *di = &dt->info;
+		struct _ddebug_class_map *mods_map;
 
 		/* match against the module name */
 		if (query->module &&
 		    !match_wildcard(query->module, di->mod_name))
 			continue;
 
+		selected_class = _DPRINTK_CLASS_DFLT;
 		if (query->class_string) {
-			map = ddebug_find_valid_class(&dt->info, query->class_string,
-						      &valid_class);
-			if (!map)
+			mods_map = ddebug_find_valid_class(di, query->class_string,
+							   &selected_class);
+			if (!mods_map)
 				continue;
-		} else {
-			/* constrain query, do not touch class'd callsites */
-			valid_class = _DPRINTK_CLASS_DFLT;
 		}
 
 		for (i = 0; i < di->descs.len; i++) {
 			struct _ddebug *dp = &di->descs.start[i];
 
-			if (!ddebug_match_desc(query, dp, valid_class))
+			if (!ddebug_match_desc(query, dp, di, selected_class))
 				continue;
 
 			nfound++;
@@ -656,6 +719,7 @@ static int ddebug_exec_queries(char *query, const char *modname)
 }
 
 /* apply a new class-param setting */
+
 static int ddebug_apply_class_bitmap(const struct _ddebug_class_param *dcp,
 				     const unsigned long *new_bits,
 				     const unsigned long old_bits,
@@ -1107,12 +1171,6 @@ static void *ddebug_proc_next(struct seq_file *m, void *p, loff_t *pos)
 	return dp;
 }
 
-static bool ddebug_class_in_range(const int class_id, const struct _ddebug_class_map *map)
-{
-	return (class_id >= map->base &&
-		class_id < map->base + map->length);
-}
-
 static const char *ddebug_class_name(struct _ddebug_info *di, struct _ddebug *dp)
 {
 	struct _ddebug_class_map *map;
@@ -1237,25 +1295,36 @@ static void ddebug_sync_classbits(const struct kernel_param *kp, const char *mod
 	}
 }
 
-static void ddebug_match_apply_kparam(const struct kernel_param *kp,
-				      const struct _ddebug_class_map *map,
-				      const char *mod_name)
+static struct _ddebug_class_param *
+ddebug_get_classmap_kparam(const struct kernel_param *kp,
+			   const struct _ddebug_class_map *map)
 {
 	struct _ddebug_class_param *dcp;
 
 	if (kp->ops != &param_ops_dyndbg_classes)
-		return;
+		return NULL;
 
 	dcp = (struct _ddebug_class_param *)kp->arg;
 
-	if (map == dcp->map) {
+	return (map == dcp->map)
+		? dcp : (struct _ddebug_class_param *)NULL;
+}
+
+static void ddebug_match_apply_kparam(const struct kernel_param *kp,
+				      struct _ddebug_class_map *map,
+				      const char *mod_name)
+{
+	struct _ddebug_class_param *dcp = ddebug_get_classmap_kparam(kp, map);
+
+	if (dcp) {
+		map->controlling_param = dcp;
 		v2pr_info(" kp:%s.%s =0x%lx", mod_name, kp->name, *dcp->bits);
 		vpr_cm_info(map, " %s maps ", mod_name);
 		ddebug_sync_classbits(kp, mod_name);
 	}
 }
 
-static void ddebug_apply_params(const struct _ddebug_class_map *cm, const char *mod_name)
+static void ddebug_apply_params(struct _ddebug_class_map *cm, const char *mod_name)
 {
 	const struct kernel_param *kp;
 #if IS_ENABLED(CONFIG_MODULES)
@@ -1275,6 +1344,13 @@ static void ddebug_apply_params(const struct _ddebug_class_map *cm, const char *
 	}
 }
 
+/*
+ * called from add_module, ie early. it can find controlling kparams,
+ * which can/does? enable protection of this classmap from class-less
+ * queries, on the grounds that the user created the kparam, means to
+ * use it, and expects it to reflect reality.  We should oblige him,
+ * and protect those classmaps from classless "-p" changes.
+ */
 static void ddebug_apply_class_maps(const struct _ddebug_info *di)
 {
 	struct _ddebug_class_map *cm;
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 31/65] dyndbg: add DYNAMIC_DEBUG_CLASSMAP_USE_(dd_class_name, offset)
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (29 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 30/65] dyndbg: resolve "protection" of class'd pr_debug Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 32/65] dyndbg: Harden classmap and callsite validation Jim Cromie
                   ` (34 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jim Cromie, Andrew Morton,
	linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

Allow a module to use 2 classmaps together that would otherwise have a
class_id range conflict.

Suppose a drm-driver does:

  DYNAMIC_DEBUG_CLASSMAP_USE(drm_debug_classes);
  DYNAMIC_DEBUG_CLASSMAP_USE(drm_accel_xfer_debug);

If (for some reason) drm-accel cannot define their constants to avoid
DRM's drm_debug_category 0..10 reservations, we would have a conflict
with reserved-ids.

In this case a driver needing to use both would _USE_ one of them with
an offset to avoid the conflict.  This will handle most foreseeable
cases; perhaps a 3-X-3 of classmap-defns X classmap-users would get
too awkward and fiddly.

This is an untested interface extension, so drop this patch if it
feels too speculative, knowing theres at least a notional solution
should the situation arise.

NB: this gets a checkpatch warning about unused _offset arg,
apparently because the arg is 5 lines down, and out of the chunk
context window.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 include/linux/dynamic_debug.h | 27 ++++++++++++++++++++++-----
 lib/dynamic_debug.c           | 19 ++++++++++++-------
 2 files changed, 34 insertions(+), 12 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index a1454db1bcb0..0d1245aefc69 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -88,7 +88,7 @@ struct _ddebug_class_map {
 struct _ddebug_class_user {
 	char *mod_name;
 	struct _ddebug_class_map *map;
-	const int offset;	/* user offset to re-number the used map */
+	const int offset;	/* offset from map->base */
 };
 
 /*
@@ -239,11 +239,28 @@ struct _ddebug_class_param {
  *
  * This tells dyndbg that the module has prdbgs with classids defined
  * in the named classmap.  This qualifies "class NAME" >controls on
- * the user module, and ignores unknown names.
+ * the user module, and ignores unknown names. This is a wrapper for
+ * DYNAMIC_DEBUG_CLASSMAP_USE_() with a base offset of 0.
  */
-#define DYNAMIC_DEBUG_CLASSMAP_USE(_var)				\
-	DYNAMIC_DEBUG_CLASSMAP_USE_(_var, 0, __UNIQUE_ID(_ddebug_class_user))
-#define DYNAMIC_DEBUG_CLASSMAP_USE_(_var, _offset, _uname)		\
+#define DYNAMIC_DEBUG_CLASSMAP_USE(_var) \
+	DYNAMIC_DEBUG_CLASSMAP_USE_(_var, 0)
+
+/**
+ * DYNAMIC_DEBUG_CLASSMAP_USE_ - refer to a classmap with a manual offset.
+ * @_var:   name of the exported classmap var to use.
+ * @_offset:  an integer offset to add to the class IDs of the used map.
+ *
+ * This is an extended version of DYNAMIC_DEBUG_CLASSMAP_USE(). It should
+ * only be used to resolve class ID conflicts when a module uses multiple
+ * classmaps that have overlapping ID ranges.
+ *
+ * The final class IDs for the used map will be calculated as:
+ * original_map_base + class_index + @_offset.
+ */
+#define DYNAMIC_DEBUG_CLASSMAP_USE_(_var, _offset)			\
+	__DYNAMIC_DEBUG_CLASSMAP_USE(_var, _offset, __UNIQUE_ID(_ddebug_class_user))
+
+#define __DYNAMIC_DEBUG_CLASSMAP_USE(_var, _offset, _uname)		\
 	extern struct _ddebug_class_map _var;				\
 	static struct _ddebug_class_user __aligned(8) __used		\
 	__section("__dyndbg_class_users") _uname = {			\
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index e9fa0c8868db..2083a8546460 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -198,7 +198,7 @@ ddebug_find_valid_class(struct _ddebug_info const *di, const char *query_class,
 		if (idx >= 0) {
 			vpr_di_info(di, "class-ref: %s -> %s.%s ",
 				    cli->mod_name, cli->map->mod_name, query_class);
-			*class_id = idx + cli->map->base;
+			*class_id = idx + cli->map->base - cli->offset;
 			return cli->map;
 		}
 	}
@@ -206,12 +206,17 @@ ddebug_find_valid_class(struct _ddebug_info const *di, const char *query_class,
 	return NULL;
 }
 
-static bool ddebug_class_in_range(const int class_id, const struct _ddebug_class_map *map)
+static bool ddebug_class_map_in_range(const int class_id, const struct _ddebug_class_map *map)
 {
 	return (class_id >= map->base &&
 		class_id < map->base + map->length);
 }
 
+static bool ddebug_class_user_in_range(const int class_id, const struct _ddebug_class_user *user)
+{
+	return ddebug_class_map_in_range(class_id - user->offset, user->map);
+}
+
 static struct _ddebug_class_map *
 ddebug_find_map_by_class_id(struct _ddebug_info *di, int class_id)
 {
@@ -220,11 +225,11 @@ ddebug_find_map_by_class_id(struct _ddebug_info *di, int class_id)
 	int i;
 
 	for_subvec(i, map, di, maps)
-		if (ddebug_class_in_range(class_id, map))
+		if (ddebug_class_map_in_range(class_id, map))
 			return map;
 
 	for_subvec(i, cli, di, users)
-		if (ddebug_class_in_range(class_id, cli->map))
+		if (ddebug_class_user_in_range(class_id, cli))
 			return cli->map;
 
 	return NULL;
@@ -1178,12 +1183,12 @@ static const char *ddebug_class_name(struct _ddebug_info *di, struct _ddebug *dp
 	int i;
 
 	for_subvec(i, map, di, maps)
-		if (ddebug_class_in_range(dp->class_id, map))
+		if (ddebug_class_map_in_range(dp->class_id, map))
 			return map->class_names[dp->class_id - map->base];
 
 	for_subvec(i, cli, di, users)
-		if (ddebug_class_in_range(dp->class_id, cli->map))
-			return cli->map->class_names[dp->class_id - cli->map->base];
+		if (ddebug_class_user_in_range(dp->class_id, cli))
+			return cli->map->class_names[dp->class_id - cli->map->base - cli->offset];
 
 	return NULL;
 }
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 32/65] dyndbg: Harden classmap and callsite validation
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (30 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 31/65] dyndbg: add DYNAMIC_DEBUG_CLASSMAP_USE_(dd_class_name, offset) Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 33/65] docs/dyndbg: add classmap info to howto Jim Cromie
                   ` (33 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jim Cromie, Andrew Morton,
	linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

Dynamic debug classmaps allow modules to _DEFINE or _USE classmaps,
which map classnames to a range of class-IDs (0..62) that they are
using.  This names => IDs mapping allows many modules to use 0..N
independently, and even allows (carefully) shared classnames.

Previously, class validation only caught some violations in _DEFINEd
classmaps; 0..62 range checks, overlaps among _DEFINEd classmaps, but
left blind spots in _USEs, for out of bounds manual offsets,
overlapping _USEd classmaps, unknown map types, and orphaned callsite
IDs. These oversights could lead to ambiguous routing or spammy
warnings during control query execution.

This commit hardens classmap and descriptor validation:

- Mirror the compile-time limits of _DEFINE by adding a static_assert
  to validate the _offset value passed to DYNAMIC_DEBUG_CLASSMAP_USE_.
- Add run-time overlap checks for _USEd classmaps in ddebug_add_module()
  to prevent collisions between private maps and imported APIs.
- Validate that module classmaps use known enum map types.
- Scan module descriptors at load time to print a single warning per
  missing class_id, rather than waiting for a user query to trip over it.
- Downgrade the global WARN_ONCE in ddebug_match_desc() to a
  pr_warn_ratelimited, since orphaned class IDs are now tracked and
  warned about early at module load.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 include/linux/dynamic_debug.h |  2 ++
 lib/dynamic_debug.c           | 52 +++++++++++++++++++++++++++++++----
 2 files changed, 48 insertions(+), 6 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 0d1245aefc69..28684cfc0937 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -262,6 +262,8 @@ struct _ddebug_class_param {
 
 #define __DYNAMIC_DEBUG_CLASSMAP_USE(_var, _offset, _uname)		\
 	extern struct _ddebug_class_map _var;				\
+	static_assert((_offset) >= 0 && (_offset) < _DPRINTK_CLASS_DFLT, \
+		      "classmap use offset must be in 0..62");		\
 	static struct _ddebug_class_user __aligned(8) __used		\
 	__section("__dyndbg_class_users") _uname = {			\
 		.mod_name = KBUILD_MODNAME,				\
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 2083a8546460..635df6edb4cf 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -320,7 +320,7 @@ static bool ddebug_match_desc(const struct ddebug_query *query,
 	/* site is class'd */
 	site_map = ddebug_find_map_by_class_id(di, dp->class_id);
 	if (!site_map) {
-		WARN_ONCE(1, "unknown class_id %d, check %s's CLASSMAP definitions",
+		pr_warn_ratelimited("unknown class_id %d, check %s's CLASSMAP definitions\n",
 			  dp->class_id, di->mod_name);
 		return false;
 	}
@@ -1404,9 +1404,8 @@ static void ddebug_apply_class_users(const struct _ddebug_info *di)
 	(__dst)->info._vec.len = __nc;					\
 })
 
-static int __maybe_unused
-ddebug_class_range_overlap(struct _ddebug_class_map *cm,
-			   u64 *reserved_ids)
+static int ddebug_class_range_overlap(struct _ddebug_class_map *cm,
+				      u64 *reserved_ids)
 {
 	u64 range = (((1ULL << cm->length) - 1) << cm->base);
 
@@ -1420,6 +1419,23 @@ ddebug_class_range_overlap(struct _ddebug_class_map *cm,
 	return 0;
 }
 
+static int ddebug_class_user_overlap(struct _ddebug_class_user *cli,
+				     u64 *reserved_ids)
+{
+	struct _ddebug_class_map *cm = cli->map;
+	int base = cm->base + cli->offset;
+	u64 range = (((1ULL << cm->length) - 1) << base);
+
+	if (range & *reserved_ids) {
+		pr_err("[%d..%d] (from %s) conflicts with %llx\n", base,
+		       base + cm->length - 1, cm->class_names[0],
+		       *reserved_ids);
+		return -EINVAL;
+	}
+	*reserved_ids |= range;
+	return 0;
+}
+
 /*
  * Allocate a new ddebug_table for the given module
  * and add it to the global list.
@@ -1430,6 +1446,7 @@ static int ddebug_add_module(struct _ddebug_info *di)
 	struct _ddebug_class_map *cm;
 	struct _ddebug_class_user *cli;
 	u64 reserved_ids = 0;
+	u64 bad_ids = 0;
 	int i;
 
 	if (!di->descs.len)
@@ -1454,10 +1471,33 @@ static int ddebug_add_module(struct _ddebug_info *di)
 	dd_mark_vector_subrange(i, cli, &dt->info, users, dt);
 	/* now di is stale */
 
-	/* insure 2+ classmaps share the per-module 0..62 class_id space */
-	for_subvec(i, cm, &dt->info, maps)
+	/* validate class map types and the per-module 0..62 class_id space */
+	for_subvec(i, cm, &dt->info, maps) {
+		if (cm->map_type > DD_CLASS_TYPE_LEVEL_NUM) {
+			pr_err("module %s has unknown classmap type %d\n", dt->info.mod_name, cm->map_type);
+			goto cleanup;
+		}
 		if (ddebug_class_range_overlap(cm, &reserved_ids))
 			goto cleanup;
+	}
+
+	for_subvec(i, cli, &dt->info, users)
+		if (ddebug_class_user_overlap(cli, &reserved_ids))
+			goto cleanup;
+
+	/* validate all class_ids against module's classmaps/users */
+	for (i = 0; i < dt->info.descs.len; i++) {
+		struct _ddebug *dp = &dt->info.descs.start[i];
+
+		if (dp->class_id == _DPRINTK_CLASS_DFLT)
+			continue;
+		if (bad_ids & (1ULL << dp->class_id))
+			continue;
+		if (!ddebug_find_map_by_class_id(&dt->info, dp->class_id)) {
+			pr_warn("module %s uses unknown class_id %d\n", dt->info.mod_name, dp->class_id);
+			bad_ids |= (1ULL << dp->class_id);
+		}
+	}
 
 	mutex_lock(&ddebug_lock);
 	list_add_tail(&dt->link, &ddebug_tables);
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 33/65] docs/dyndbg: add classmap info to howto
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (31 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 32/65] dyndbg: Harden classmap and callsite validation Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:19 ` [PATCH v11 34/65] drm: use correct ccflags-y spelling Jim Cromie
                   ` (32 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jonathan Corbet, Shuah Khan,
	linux-doc, linux-kernel
  Cc: Jim Cromie, mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, pmladek, ukaszb,
	dri-devel, intel-gfx, amd-gfx

Describe the 3 API macros providing dynamic_debug's classmaps

DYNAMIC_DEBUG_CLASSMAP_DEFINE - create & export a classmap
DYNAMIC_DEBUG_CLASSMAP_USE    - refer to exported map
DYNAMIC_DEBUG_CLASSMAP_PARAM  - bind control param to the classmap
DYNAMIC_DEBUG_CLASSMAP_PARAM_REF + use module's storage - __drm_debug

NB: The _DEFINE & _USE model makes the user dependent on the definer,
just like EXPORT_SYMBOL(__drm_debug) already does.

cc: linux-doc@vger.kernel.org
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 .../admin-guide/dynamic-debug-howto.rst       | 132 ++++++++++++++++--
 1 file changed, 122 insertions(+), 10 deletions(-)

diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst b/Documentation/admin-guide/dynamic-debug-howto.rst
index 0a42b9de55ac..734be0b5fe9a 100644
--- a/Documentation/admin-guide/dynamic-debug-howto.rst
+++ b/Documentation/admin-guide/dynamic-debug-howto.rst
@@ -146,6 +146,9 @@ keywords are::
   "1-30" is valid range but "1 - 30" is not.
 
 
+Keywords
+--------
+
 The meanings of each keyword are:
 
 func
@@ -194,16 +197,6 @@ format
 	format "nfsd: SETATTR"  // a neater way to match a format with whitespace
 	format 'nfsd: SETATTR'  // yet another way to match a format with whitespace
 
-class
-    The given class_name is validated against each module, which may
-    have declared a list of known class_names.  If the class_name is
-    found for a module, callsite & class matching and adjustment
-    proceeds.  Examples::
-
-	class DRM_UT_KMS	# a DRM.debug category
-	class JUNK		# silent non-match
-	// class TLD_*		# NOTICE: no wildcard in class names
-
 line
     The given line number or range of line numbers is compared
     against the line number of each ``pr_debug()`` callsite.  A single
@@ -218,6 +211,25 @@ line
 	line -1605          // the 1605 lines from line 1 to line 1605
 	line 1600-          // all lines from line 1600 to the end of the file
 
+class
+
+    The given class_name is validated against each module, which may
+    have declared a list of class_names it accepts.  If the class_name
+    accepted by a module, callsite & class matching and adjustment
+    proceeds.  Examples::
+
+	class DRM_UT_KMS	# a drm.debug category
+	class JUNK		# silent non-match
+	// class TLD_*		# NOTICE: no wildcard in class names
+
+.. note::
+
+    Unlike other keywords, classes are "name-to-change", not
+    "omitting-constraint-allows-change".  See Dynamic Debug Classmaps
+
+Flags
+-----
+
 The flags specification comprises a change operation followed
 by one or more flag characters.  The change operation is one
 of the characters::
@@ -239,6 +251,11 @@ The flags are::
   l    Include line number
   d    Include call trace
 
+.. note::
+
+   * To query without changing	``+_`` or ``-_``.
+   * To clear all flags		``=_`` or ``-fslmpt``.
+
 For ``print_hex_dump_debug()`` and ``print_hex_dump_bytes()``, only
 the ``p`` flag has meaning, other flags are ignored.
 
@@ -395,3 +412,98 @@ just a shortcut for ``print_hex_dump(KERN_DEBUG)``.
 For ``print_hex_dump_debug()``/``print_hex_dump_bytes()``, format string is
 its ``prefix_str`` argument, if it is constant string; or ``hexdump``
 in case ``prefix_str`` is built dynamically.
+
+.. _dyndbg-classmaps:
+
+Dynamic Debug Classmaps
+=======================
+
+The "class" keyword selects prdbgs based on author supplied,
+domain-oriented names.  This complements the nested-scope keywords:
+module, file, function, line.
+
+The main difference from the others: classes must be named to be
+changed.  This protects them from unintended overwrite::
+
+  # IOW this cannot undo any drm.debug settings
+  :#> ddcmd -p
+
+This protection is needed; /sys/module/drm/parameters/debug is ABI.
+drm.debug is authoritative when dyndbg is not used, dyndbg-under-DRM
+is an implementation detail, and must not behave erratically, just
+because another admin fed >control something unrelated.
+
+So each class must be enabled individually (no wildcards)::
+
+  :#> ddcmd class DRM_UT_CORE +p
+  :#> ddcmd class DRM_UT_KMS +p
+  # or more selectively
+  :#> ddcmd class DRM_UT_CORE module drm +p
+
+That makes direct >control wordy and annoying, but it is a secondary
+interface; it is not intended to replace the ABI, just slide in
+underneath and reimplement the guaranteed behavior.  So DRM would keep
+using the convenient way, and be able to trust it::
+
+  :#> echo 0x1ff > /sys/module/drm/parameters/debug
+
+That said, since the sysfs/kparam is the ABI, if the author omits the
+CLASSMAP_PARAM, theres no ABI to guard, and he probably wants a less
+pedantic >control interface.  In this case, protection is dropped.
+
+Dynamic Debug Classmap API
+==========================
+
+DYNAMIC_DEBUG_CLASSMAP_DEFINE(clname,type,_base,classnames) - this maps
+classnames (a list of strings) onto class-ids consecutively, starting
+at _base.
+
+DYNAMIC_DEBUG_CLASSMAP_USE(clname) & _USE_(clname,_base) - modules
+call this to refer to the var _DEFINEd elsewhere (and exported).
+
+DYNAMIC_DEBUG_CLASSMAP_PARAM(clname) - creates the sysfs/kparam,
+maps/exposes bits 0..N as class-names.
+
+Classmaps are opt-in: modules invoke _DEFINE or _USE to authorize
+dyndbg to update those named classes.  "class FOO" queries are
+validated against the classes defined or used by the module, this
+finds the classid to alter; classes are not directly selectable by
+their classid.
+
+Classnames are global in scope, so subsystems (module-groups) should
+prepend a subsystem name; unqualified names like "CORE" are discouraged.
+
+NB: It is an inherent API limitation (due to class_id's int type) that
+the following are possible:
+
+  // these errors should be caught in review
+  __pr_debug_cls(0, "fake DRM_UT_CORE msg");  // this works
+  __pr_debug_cls(62, "un-known classid msg"); // this compiles, does nothing
+
+There are 2 types of classmaps:
+
+* DD_CLASS_TYPE_DISJOINT_BITS: classes are independent, like drm.debug
+* DD_CLASS_TYPE_LEVEL_NUM: classes are relative, ordered (V3 > V2)
+
+DYNAMIC_DEBUG_CLASSMAP_PARAM - modelled after module_param_cb, it
+refers to a DEFINEd classmap, and associates it to the param's
+data-store.  This state is then applied to DEFINEr and USEr modules
+when they're modprobed.
+
+The PARAM interface also enforces the DD_CLASS_TYPE_LEVEL_NUM relation
+amongst the contained classnames; all classes are independent in the
+control parser itself.  There is no implied meaning in names like "V4"
+or "PL_ERROR" vs "PL_WARNING".
+
+Modules or subsystems (drm & drivers) can define multiple classmaps,
+as long as they (all the classmaps) share the limited 0..62
+per-module-group _class_id range, without overlap.
+
+If a module encounters a conflict between 2 classmaps it is _USEing or
+_DEFINEing, it can invoke the extended _USE_(name,_base) macro to
+de-conflict the respective ranges.
+
+``#define DEBUG`` will enable all pr_debugs in scope, including any
+class'd ones.  This won't be reflected in the PARAM readback value,
+but the class'd pr_debug callsites can be forced off by toggling the
+classmap-kparam all-on then all-off.
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 34/65] drm: use correct ccflags-y spelling
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (32 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 33/65] docs/dyndbg: add classmap info to howto Jim Cromie
@ 2026-03-13 13:19 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:20 ` [PATCH v11 35/65] drm-dyndbg: adapt drm core to use dyndbg classmaps-v2 Jim Cromie
                   ` (31 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:19 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Jim Cromie, dri-devel, linux-kernel
  Cc: jani.nikula, ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	intel-gfx, amd-gfx

Incorrectly spelled CFLAGS- failed to add -DDYNAMIC_DEBUG_MODULE,
which disabled dynamic-debug in modules built with:

CONFIG_DYNAMIC_DEBUG=n		# 1
CONFIG_DYNAMIC_DEBUG_CORE=y	# 2
CONFIG_DRM_USE_DYNAMIC_DEBUG=y	# 3

NB: this adds the flag (when 3) more often than strictly needed;
modules built with CONFIG_DYNAMIC_DEBUG=y (!1) don't need the flag.

Fixes: 84ec67288c10 ("drm_print: wrap drm_*_dbg in dyndbg descriptor factory macro")
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 drivers/gpu/drm/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index aba4bf542a35..02e244688b48 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -3,7 +3,8 @@
 # Makefile for the drm device driver.  This driver provides support for the
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
-CFLAGS-$(CONFIG_DRM_USE_DYNAMIC_DEBUG)	+= -DDYNAMIC_DEBUG_MODULE
+ccflags-$(CONFIG_DRM_USE_DYNAMIC_DEBUG)		+= -DDYNAMIC_DEBUG_MODULE
+subdir-ccflags-$(CONFIG_DRM_USE_DYNAMIC_DEBUG)	+= -DDYNAMIC_DEBUG_MODULE
 
 # Unconditionally enable W=1 warnings locally
 # --- begin copy-paste W=1 warnings from scripts/Makefile.warn
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 35/65] drm-dyndbg: adapt drm core to use dyndbg classmaps-v2
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (33 preceding siblings ...)
  2026-03-13 13:19 ` [PATCH v11 34/65] drm: use correct ccflags-y spelling Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:20 ` [PATCH v11 36/65] drm-dyndbg: adapt DRM to invoke DYNAMIC_DEBUG_CLASSMAP_PARAM Jim Cromie
                   ` (30 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, dri-devel, linux-kernel
  Cc: Jim Cromie, jani.nikula, ville.syrjala, christian.koenig,
	matthew.auld, arunpravin.paneerselvam, louis.chauvet, skhan,
	pmladek, ukaszb, intel-gfx, amd-gfx

dyndbg's CLASSMAP-v1 api was broken; DECLARE_DYNDBG_CLASSMAP tried to
do too much.  Its replaced by DYNAMIC_DEBUG_CLASSMAP_DEFINE which
creates & EXPORTs a classmap, and DYNAMIC_DEBUG_CLASSMAP_USE which
refers to that exported classmap, creating a module dependency.  DRM
gets DRM_CLASSMAP_* wrappers to hide the DRM_USE_DYNAMIC_DEBUG ifdef.

The drivers still use DECLARE_DYNDBG_CLASSMAP for now, so they still
redundantly re-declare the classmap, but we can convert the drivers
later to DYNDBG_CLASSMAP_USE, at which point they'll respond to the
echo class FOO >control commands.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
this ignored a checkpatch
 WARNING: Argument 'name' is not used in function-like macro
 #70: FILE: include/drm/drm_print.h:148:
 +#define DRM_CLASSMAP_USE(name)

the macro is empty, and correct. only 1 arg is expected.

v++: fix old CLASSBITS/CLASSMAP comment
---
 drivers/gpu/drm/drm_print.c | 25 +++++++++++++------------
 include/drm/drm_print.h     | 13 ++++++++++++-
 2 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c
index ded9461df5f2..d07e7953c9fc 100644
--- a/drivers/gpu/drm/drm_print.c
+++ b/drivers/gpu/drm/drm_print.c
@@ -56,18 +56,19 @@ MODULE_PARM_DESC(debug, "Enable debug output, where each bit enables a debug cat
 #if !defined(CONFIG_DRM_USE_DYNAMIC_DEBUG)
 module_param_named(debug, __drm_debug, ulong, 0600);
 #else
-/* classnames must match vals of enum drm_debug_category */
-DECLARE_DYNDBG_CLASSMAP(drm_debug_classes, DD_CLASS_TYPE_DISJOINT_BITS, 0,
-			"DRM_UT_CORE",
-			"DRM_UT_DRIVER",
-			"DRM_UT_KMS",
-			"DRM_UT_PRIME",
-			"DRM_UT_ATOMIC",
-			"DRM_UT_VBL",
-			"DRM_UT_STATE",
-			"DRM_UT_LEASE",
-			"DRM_UT_DP",
-			"DRM_UT_DRMRES");
+/* classnames must match value-symbols of enum drm_debug_category */
+DRM_CLASSMAP_DEFINE(drm_debug_classes, DD_CLASS_TYPE_DISJOINT_BITS,
+		    DRM_UT_CORE,
+		    "DRM_UT_CORE",
+		    "DRM_UT_DRIVER",
+		    "DRM_UT_KMS",
+		    "DRM_UT_PRIME",
+		    "DRM_UT_ATOMIC",
+		    "DRM_UT_VBL",
+		    "DRM_UT_STATE",
+		    "DRM_UT_LEASE",
+		    "DRM_UT_DP",
+		    "DRM_UT_DRMRES");
 
 static struct ddebug_class_param drm_debug_bitmap = {
 	.bits = &__drm_debug,
diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h
index ab017b05e175..b743ee3f8f5e 100644
--- a/include/drm/drm_print.h
+++ b/include/drm/drm_print.h
@@ -96,7 +96,10 @@ extern unsigned long __drm_debug;
  *
  */
 enum drm_debug_category {
-	/* These names must match those in DYNAMIC_DEBUG_CLASSBITS */
+	/*
+	 * These enum-names are reused in DRM_CLASSMAP_DEFINE to
+	 * expose them as classes in /proc/dynamic_debug/control
+	 */
 	/**
 	 * @DRM_UT_CORE: Used in the generic drm code: drm_ioctl.c, drm_mm.c,
 	 * drm_memory.c, ...
@@ -141,6 +144,14 @@ enum drm_debug_category {
 	DRM_UT_DRMRES
 };
 
+#ifdef CONFIG_DRM_USE_DYNAMIC_DEBUG
+#define DRM_CLASSMAP_DEFINE(...)    DYNAMIC_DEBUG_CLASSMAP_DEFINE(__VA_ARGS__)
+#define DRM_CLASSMAP_USE(name)      DYNAMIC_DEBUG_CLASSMAP_USE(name)
+#else
+#define DRM_CLASSMAP_DEFINE(...)
+#define DRM_CLASSMAP_USE(name)
+#endif
+
 static inline bool drm_debug_enabled_raw(enum drm_debug_category category)
 {
 	return unlikely(__drm_debug & BIT(category));
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 36/65] drm-dyndbg: adapt DRM to invoke DYNAMIC_DEBUG_CLASSMAP_PARAM
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (34 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 35/65] drm-dyndbg: adapt drm core to use dyndbg classmaps-v2 Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:20 ` [PATCH v11 37/65] drm-print: modernize an archaic comment Jim Cromie
                   ` (29 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, dri-devel, linux-kernel
  Cc: Jim Cromie, jani.nikula, ville.syrjala, christian.koenig,
	matthew.auld, arunpravin.paneerselvam, louis.chauvet, skhan,
	pmladek, ukaszb, intel-gfx, amd-gfx

Invoke DYNAMIC_DEBUG_CLASSMAP_PARAM to hook drm.debug (__drm_debug) to the
DRM_UT_* classmap, replacing the ad-hoc wiring previously doing it.

Add DRM_CLASSMAP_* adapter macros to selectively use
DYNAMIC_DEBUG_CLASSMAP_* when DRM_USE_DYNAMIC_DEBUG=y is configured.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/drm_print.c | 8 ++------
 include/drm/drm_print.h     | 4 ++++
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c
index d07e7953c9fc..93dd714d4533 100644
--- a/drivers/gpu/drm/drm_print.c
+++ b/drivers/gpu/drm/drm_print.c
@@ -70,12 +70,8 @@ DRM_CLASSMAP_DEFINE(drm_debug_classes, DD_CLASS_TYPE_DISJOINT_BITS,
 		    "DRM_UT_DP",
 		    "DRM_UT_DRMRES");
 
-static struct ddebug_class_param drm_debug_bitmap = {
-	.bits = &__drm_debug,
-	.flags = "p",
-	.map = &drm_debug_classes,
-};
-module_param_cb(debug, &param_ops_dyndbg_classes, &drm_debug_bitmap, 0600);
+DRM_CLASSMAP_PARAM_REF(debug, __drm_debug, drm_debug_classes, p);
+
 #endif
 
 void __drm_puts_coredump(struct drm_printer *p, const char *str)
diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h
index b743ee3f8f5e..94064ec6c229 100644
--- a/include/drm/drm_print.h
+++ b/include/drm/drm_print.h
@@ -147,9 +147,13 @@ enum drm_debug_category {
 #ifdef CONFIG_DRM_USE_DYNAMIC_DEBUG
 #define DRM_CLASSMAP_DEFINE(...)    DYNAMIC_DEBUG_CLASSMAP_DEFINE(__VA_ARGS__)
 #define DRM_CLASSMAP_USE(name)      DYNAMIC_DEBUG_CLASSMAP_USE(name)
+#define DRM_CLASSMAP_PARAM_REF(...) DYNAMIC_DEBUG_CLASSMAP_PARAM_REF(__VA_ARGS__)
+#define DRM_CLASSMAP_PARAM(...)     DYNAMIC_DEBUG_CLASSMAP_PARAM(__VA_ARGS__)
 #else
 #define DRM_CLASSMAP_DEFINE(...)
 #define DRM_CLASSMAP_USE(name)
+#define DRM_CLASSMAP_PARAM_REF(...)
+#define DRM_CLASSMAP_PARAM(...)
 #endif
 
 static inline bool drm_debug_enabled_raw(enum drm_debug_category category)
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 37/65] drm-print: modernize an archaic comment
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (35 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 36/65] drm-dyndbg: adapt DRM to invoke DYNAMIC_DEBUG_CLASSMAP_PARAM Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:20 ` [PATCH v11 38/65] drm-print: fix config-dependent unused variable Jim Cromie
                   ` (28 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, dri-devel, linux-kernel
  Cc: Jim Cromie, jani.nikula, ville.syrjala, christian.koenig,
	matthew.auld, arunpravin.paneerselvam, louis.chauvet, skhan,
	pmladek, ukaszb, intel-gfx, amd-gfx

In the year 2025 it is no longer noteworthy that drm.debug logging is
adjustable at runtime, via sysfs node.  Simplify the statement.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 include/drm/drm_print.h | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h
index 94064ec6c229..c3df2f3f47d8 100644
--- a/include/drm/drm_print.h
+++ b/include/drm/drm_print.h
@@ -89,10 +89,9 @@ extern unsigned long __drm_debug;
  *  - ...
  *  - drm.debug=0x1ff will enable all messages
  *
- * An interesting feature is that it's possible to enable verbose logging at
- * run-time by echoing the debug value in its sysfs node::
+ * You can also alter the logged categories at run-time:
  *
- *   # echo 0xf > /sys/module/drm/parameters/debug
+ *   #> echo 0xf > /sys/module/drm/parameters/debug
  *
  */
 enum drm_debug_category {
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 38/65] drm-print: fix config-dependent unused variable
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (36 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 37/65] drm-print: modernize an archaic comment Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:20 ` [PATCH v11 39/65] drm-dyndbg: DRM_CLASSMAP_USE in amdgpu driver Jim Cromie
                   ` (27 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, dri-devel, linux-kernel
  Cc: Jim Cromie, jani.nikula, ville.syrjala, christian.koenig,
	matthew.auld, arunpravin.paneerselvam, louis.chauvet, skhan,
	pmladek, ukaszb, intel-gfx, amd-gfx

With CONFIG_DRM_USE_DYNAMIC_DEBUG=y, __drm_printfn_dbg() gets an
unused variable warning/error on 'category', even though the usage
follows immediately, in drm_debug_enabled(category).

For static-key optimized dyndbg, the macro doesn't actually check the
category var, since the static-key patches in the proper state.  The
compiler evidently sees this lack of reference and complains.

So this drops the local var and refs the field directly in the
macro-call, which avoids the warning/error.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/drm_print.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c
index 93dd714d4533..ceede094ff13 100644
--- a/drivers/gpu/drm/drm_print.c
+++ b/drivers/gpu/drm/drm_print.c
@@ -213,9 +213,8 @@ void __drm_printfn_dbg(struct drm_printer *p, struct va_format *vaf)
 {
 	const struct drm_device *drm = p->arg;
 	const struct device *dev = drm ? drm->dev : NULL;
-	enum drm_debug_category category = p->category;
 
-	if (!__drm_debug_enabled(category))
+	if (!__drm_debug_enabled(p->category))
 		return;
 
 	__drm_dev_vprintk(dev, KERN_DEBUG, p->origin, p->prefix, vaf);
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 39/65] drm-dyndbg: DRM_CLASSMAP_USE in amdgpu driver
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (37 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 38/65] drm-print: fix config-dependent unused variable Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 13:20 ` [PATCH v11 40/65] drm-dyndbg: DRM_CLASSMAP_USE in i915 driver Jim Cromie
                   ` (26 subsequent siblings)
  65 siblings, 0 replies; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Alex Deucher,
	Christian König, Jim Cromie, amd-gfx, dri-devel,
	linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, matthew.auld, arunpravin.paneerselvam,
	louis.chauvet, skhan, pmladek, ukaszb, intel-gfx

Following the dyndbg-api-fix, replace DECLARE_DYNDBG_CLASSMAP with
DRM_CLASSMAP_USE.  This refs the defined & exported classmap, rather
than re-declaring it redundantly, and error-prone-ly.

This resolves the appearance of "class:_UNKNOWN_" in the control file
for the driver's drm_dbg()s.

Fixes: f158936b60a7 ("drm: POC drm on dyndbg - use in core, 2 helpers, 3 drivers.")

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 95d26f086d54..e5dd051eeba9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -249,17 +249,7 @@ int amdgpu_rebar = -1; /* auto */
 int amdgpu_user_queue = -1;
 uint amdgpu_hdmi_hpd_debounce_delay_ms;
 
-DECLARE_DYNDBG_CLASSMAP(drm_debug_classes, DD_CLASS_TYPE_DISJOINT_BITS, 0,
-			"DRM_UT_CORE",
-			"DRM_UT_DRIVER",
-			"DRM_UT_KMS",
-			"DRM_UT_PRIME",
-			"DRM_UT_ATOMIC",
-			"DRM_UT_VBL",
-			"DRM_UT_STATE",
-			"DRM_UT_LEASE",
-			"DRM_UT_DP",
-			"DRM_UT_DRMRES");
+DRM_CLASSMAP_USE(drm_debug_classes);
 
 struct amdgpu_mgpu_info mgpu_info = {
 	.mutex = __MUTEX_INITIALIZER(mgpu_info.mutex),
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 40/65] drm-dyndbg: DRM_CLASSMAP_USE in i915 driver
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (38 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 39/65] drm-dyndbg: DRM_CLASSMAP_USE in amdgpu driver Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 13:20 ` [PATCH v11 41/65] drm-dyndbg: DRM_CLASSMAP_USE in drm_crtc_helper Jim Cromie
                   ` (25 subsequent siblings)
  65 siblings, 0 replies; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Jani Nikula, Joonas Lahtinen,
	Rodrigo Vivi, Tvrtko Ursulin, Jim Cromie, intel-gfx, dri-devel,
	linux-kernel
  Cc: mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	amd-gfx

Following the dyndbg-api-fix, replace DECLARE_DYNDBG_CLASSMAP with
DRM_CLASSMAP_USE.  This refs the defined & exported classmap, rather
than re-declaring it redundantly, and error-prone-ly.

This resolves the appearance of "class:_UNKNOWN_" in the control file
for the driver's drm_dbg()s.

Fixes: f158936b60a7 ("drm: POC drm on dyndbg - use in core, 2 helpers, 3 drivers.")

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/i915/i915_params.c | 12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index 34ed82bb1b1a..40c5e0014686 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -29,17 +29,7 @@
 #include "i915_params.h"
 #include "i915_drv.h"
 
-DECLARE_DYNDBG_CLASSMAP(drm_debug_classes, DD_CLASS_TYPE_DISJOINT_BITS, 0,
-			"DRM_UT_CORE",
-			"DRM_UT_DRIVER",
-			"DRM_UT_KMS",
-			"DRM_UT_PRIME",
-			"DRM_UT_ATOMIC",
-			"DRM_UT_VBL",
-			"DRM_UT_STATE",
-			"DRM_UT_LEASE",
-			"DRM_UT_DP",
-			"DRM_UT_DRMRES");
+DRM_CLASSMAP_USE(drm_debug_classes);
 
 #define i915_param_named(name, T, perm, desc) \
 	module_param_named(name, i915_modparams.name, T, perm); \
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 41/65] drm-dyndbg: DRM_CLASSMAP_USE in drm_crtc_helper
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (39 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 40/65] drm-dyndbg: DRM_CLASSMAP_USE in i915 driver Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 13:20 ` [PATCH v11 42/65] drm-dyndbg: DRM_CLASSMAP_USE in drm_dp_helper Jim Cromie
                   ` (24 subsequent siblings)
  65 siblings, 0 replies; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Jim Cromie, dri-devel, linux-kernel
  Cc: jani.nikula, ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	intel-gfx, amd-gfx

Following the dyndbg-api-fix, replace DECLARE_DYNDBG_CLASSMAP with
DRM_CLASSMAP_USE.  This refs the defined & exported classmap, rather
than re-declaring it redundantly, and error-prone-ly.

This resolves the appearance of "class:_UNKNOWN_" in the control file
for the driver's drm_dbg()s.

Fixes: f158936b60a7 ("drm: POC drm on dyndbg - use in core, 2 helpers, 3 drivers.")

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/drm_crtc_helper.c | 12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 5de9aaa5ba04..31c5294b252c 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -50,17 +50,7 @@
 
 #include "drm_crtc_helper_internal.h"
 
-DECLARE_DYNDBG_CLASSMAP(drm_debug_classes, DD_CLASS_TYPE_DISJOINT_BITS, 0,
-			"DRM_UT_CORE",
-			"DRM_UT_DRIVER",
-			"DRM_UT_KMS",
-			"DRM_UT_PRIME",
-			"DRM_UT_ATOMIC",
-			"DRM_UT_VBL",
-			"DRM_UT_STATE",
-			"DRM_UT_LEASE",
-			"DRM_UT_DP",
-			"DRM_UT_DRMRES");
+DRM_CLASSMAP_USE(drm_debug_classes);
 
 /**
  * DOC: overview
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 42/65] drm-dyndbg: DRM_CLASSMAP_USE in drm_dp_helper
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (40 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 41/65] drm-dyndbg: DRM_CLASSMAP_USE in drm_crtc_helper Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 13:20 ` [PATCH v11 43/65] drm-dyndbg: DRM_CLASSMAP_USE in nouveau Jim Cromie
                   ` (23 subsequent siblings)
  65 siblings, 0 replies; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Jim Cromie, dri-devel, linux-kernel
  Cc: jani.nikula, ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	intel-gfx, amd-gfx

Following the dyndbg-api-fix, replace DECLARE_DYNDBG_CLASSMAP with
DRM_CLASSMAP_USE.  This refs the defined & exported classmap, rather
than re-declaring it redundantly, and error-prone-ly.

This resolves the appearance of "class:_UNKNOWN_" in the control file
for the driver's drm_dbg()s.

Fixes: f158936b60a7 ("drm: POC drm on dyndbg - use in core, 2 helpers, 3 drivers.")

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
 drivers/gpu/drm/display/drm_dp_helper.c | 12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c
index a697cc227e28..308083e244d4 100644
--- a/drivers/gpu/drm/display/drm_dp_helper.c
+++ b/drivers/gpu/drm/display/drm_dp_helper.c
@@ -45,17 +45,7 @@
 
 #include "drm_dp_helper_internal.h"
 
-DECLARE_DYNDBG_CLASSMAP(drm_debug_classes, DD_CLASS_TYPE_DISJOINT_BITS, 0,
-			"DRM_UT_CORE",
-			"DRM_UT_DRIVER",
-			"DRM_UT_KMS",
-			"DRM_UT_PRIME",
-			"DRM_UT_ATOMIC",
-			"DRM_UT_VBL",
-			"DRM_UT_STATE",
-			"DRM_UT_LEASE",
-			"DRM_UT_DP",
-			"DRM_UT_DRMRES");
+DRM_CLASSMAP_USE(drm_debug_classes);
 
 struct dp_aux_backlight {
 	struct backlight_device *base;
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 43/65] drm-dyndbg: DRM_CLASSMAP_USE in nouveau
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (41 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 42/65] drm-dyndbg: DRM_CLASSMAP_USE in drm_dp_helper Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 13:20 ` [PATCH v11 44/65] drm-dyndbg: add DRM_CLASSMAP_USE to Xe driver Jim Cromie
                   ` (22 subsequent siblings)
  65 siblings, 0 replies; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Lyude Paul, Danilo Krummrich,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Jim Cromie,
	dri-devel, nouveau, linux-kernel
  Cc: jani.nikula, ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	intel-gfx, amd-gfx

Following the dyndbg-api-fix, replace DECLARE_DYNDBG_CLASSMAP with
DRM_CLASSMAP_USE.  This refs the defined & exported classmap, rather
than re-declaring it redundantly, and error-prone-ly.

This resolves the appearance of "class:_UNKNOWN_" in the control file
for the driver's drm_dbg()s.

Fixes: f158936b60a7 ("drm: POC drm on dyndbg - use in core, 2 helpers, 3 drivers.")

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 drivers/gpu/drm/nouveau/nouveau_drm.c | 12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 5d8475e4895e..d205b58aff70 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -74,17 +74,7 @@
 #include "nouveau_uvmm.h"
 #include "nouveau_sched.h"
 
-DECLARE_DYNDBG_CLASSMAP(drm_debug_classes, DD_CLASS_TYPE_DISJOINT_BITS, 0,
-			"DRM_UT_CORE",
-			"DRM_UT_DRIVER",
-			"DRM_UT_KMS",
-			"DRM_UT_PRIME",
-			"DRM_UT_ATOMIC",
-			"DRM_UT_VBL",
-			"DRM_UT_STATE",
-			"DRM_UT_LEASE",
-			"DRM_UT_DP",
-			"DRM_UT_DRMRES");
+DRM_CLASSMAP_USE(drm_debug_classes);
 
 MODULE_PARM_DESC(config, "option string to pass to driver core");
 static char *nouveau_config;
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 44/65] drm-dyndbg: add DRM_CLASSMAP_USE to Xe driver
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (42 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 43/65] drm-dyndbg: DRM_CLASSMAP_USE in nouveau Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 13:20 ` [PATCH v11 45/65] drm-dyndbg: add DRM_CLASSMAP_USE to virtio_gpu Jim Cromie
                   ` (21 subsequent siblings)
  65 siblings, 0 replies; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Matthew Brost,
	Thomas Hellström, Rodrigo Vivi, intel-xe, dri-devel,
	linux-kernel
  Cc: Jim Cromie, mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	intel-gfx, amd-gfx

Invoke DRM_CLASSMAP_USE from xe_drm_client.c.  When built with
CONFIG_DRM_USE_DYNAMIC_DEBUG=y, this tells dydnbg that Xe has
drm.debug callsites.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 drivers/gpu/drm/xe/xe_drm_client.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/xe/xe_drm_client.c b/drivers/gpu/drm/xe/xe_drm_client.c
index 84b66147bf49..3af476f0449f 100644
--- a/drivers/gpu/drm/xe/xe_drm_client.c
+++ b/drivers/gpu/drm/xe/xe_drm_client.c
@@ -21,6 +21,8 @@
 #include "xe_pm.h"
 #include "xe_trace.h"
 
+DRM_CLASSMAP_USE(drm_debug_classes);
+
 /**
  * DOC: DRM Client usage stats
  *
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 45/65] drm-dyndbg: add DRM_CLASSMAP_USE to virtio_gpu
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (43 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 44/65] drm-dyndbg: add DRM_CLASSMAP_USE to Xe driver Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 13:20 ` [PATCH v11 46/65] drm-dyndbg: add DRM_CLASSMAP_USE to simpledrm Jim Cromie
                   ` (20 subsequent siblings)
  65 siblings, 0 replies; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, David Airlie, Gerd Hoffmann,
	Dmitry Osipenko, Gurchetan Singh, Chia-I Wu, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, dri-devel, virtualization,
	linux-kernel
  Cc: Jim Cromie, jani.nikula, ville.syrjala, christian.koenig,
	matthew.auld, arunpravin.paneerselvam, louis.chauvet, skhan,
	pmladek, ukaszb, intel-gfx, amd-gfx

virtio_gpu has 10 DRM_UT_CORE debugs, make them controllable when
CONFIG_DRM_USE_DYNAMIC_DEBUG=y by telling dyndbg that the module has
class'd debugs.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 drivers/gpu/drm/virtio/virtgpu_drv.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c
index a5ce96fb8a1d..aea4c117b006 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.c
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.c
@@ -49,6 +49,8 @@ static const struct drm_driver driver;
 
 static int virtio_gpu_modeset = -1;
 
+DRM_CLASSMAP_USE(drm_debug_classes);
+
 MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
 module_param_named(modeset, virtio_gpu_modeset, int, 0400);
 
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 46/65] drm-dyndbg: add DRM_CLASSMAP_USE to simpledrm
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (44 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 45/65] drm-dyndbg: add DRM_CLASSMAP_USE to virtio_gpu Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 13:20 ` [PATCH v11 47/65] drm-dyndbg: add DRM_CLASSMAP_USE to bochs Jim Cromie
                   ` (19 subsequent siblings)
  65 siblings, 0 replies; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Thomas Zimmermann,
	Javier Martinez Canillas, Maarten Lankhorst, Maxime Ripard,
	dri-devel, linux-kernel
  Cc: Jim Cromie, jani.nikula, ville.syrjala, christian.koenig,
	matthew.auld, arunpravin.paneerselvam, louis.chauvet, skhan,
	pmladek, ukaszb, intel-gfx, amd-gfx

tiny/simpledrm has 3 DRM_UT_DRIVER debugs, make them controllable when
CONFIG_DRM_USE_DYNAMIC_DEBUG=y by telling dyndbg that the module has
class'd debugs.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 drivers/gpu/drm/sysfb/simpledrm.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/sysfb/simpledrm.c b/drivers/gpu/drm/sysfb/simpledrm.c
index 7a95d2dacd9d..8958e115abc1 100644
--- a/drivers/gpu/drm/sysfb/simpledrm.c
+++ b/drivers/gpu/drm/sysfb/simpledrm.c
@@ -35,6 +35,8 @@
 #define DRIVER_MAJOR	1
 #define DRIVER_MINOR	0
 
+DRM_CLASSMAP_USE(drm_debug_classes);
+
 /*
  * Helpers for simplefb
  */
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 47/65] drm-dyndbg: add DRM_CLASSMAP_USE to bochs
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (45 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 46/65] drm-dyndbg: add DRM_CLASSMAP_USE to simpledrm Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 13:20 ` [PATCH v11 48/65] drm-dyndbg: add DRM_CLASSMAP_USE to etnaviv Jim Cromie
                   ` (18 subsequent siblings)
  65 siblings, 0 replies; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Gerd Hoffmann, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, virtualization, dri-devel,
	linux-kernel
  Cc: Jim Cromie, jani.nikula, ville.syrjala, christian.koenig,
	matthew.auld, arunpravin.paneerselvam, louis.chauvet, skhan,
	pmladek, ukaszb, intel-gfx, amd-gfx

tiny/bochs has 5 DRM_UT_* debugs, make them controllable when
CONFIG_DRM_USE_DYNAMIC_DEBUG=y by telling dyndbg that the module has
class'd debugs.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 drivers/gpu/drm/tiny/bochs.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/tiny/bochs.c b/drivers/gpu/drm/tiny/bochs.c
index 222e4ae1abbd..8f04666e7def 100644
--- a/drivers/gpu/drm/tiny/bochs.c
+++ b/drivers/gpu/drm/tiny/bochs.c
@@ -63,6 +63,8 @@ static int bochs_modeset = -1;
 static int defx = 1024;
 static int defy = 768;
 
+DRM_CLASSMAP_USE(drm_debug_classes);
+
 module_param_named(modeset, bochs_modeset, int, 0444);
 MODULE_PARM_DESC(modeset, "enable/disable kernel modesetting");
 
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 48/65] drm-dyndbg: add DRM_CLASSMAP_USE to etnaviv
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (46 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 47/65] drm-dyndbg: add DRM_CLASSMAP_USE to bochs Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 13:20 ` [PATCH v11 49/65] drm-dyndbg: add DRM_CLASSMAP_USE to gma500 driver Jim Cromie
                   ` (17 subsequent siblings)
  65 siblings, 0 replies; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Lucas Stach, Russell King,
	Christian Gmeiner, etnaviv, dri-devel, linux-kernel
  Cc: Jim Cromie, mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	intel-gfx, amd-gfx

etnaviv has 5 DRM_UT_CORE debugs, make them controllable when
CONFIG_DRM_USE_DYNAMIC_DEBUG=y by telling dyndbg that the module has
class'd debugs as well as plain-old pr_debug()s

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 drivers/gpu/drm/etnaviv/etnaviv_drv.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index 08aca9035fc1..ef4423d4987f 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -26,6 +26,8 @@
 #include "etnaviv_mmu.h"
 #include "etnaviv_perfmon.h"
 
+DRM_CLASSMAP_USE(drm_debug_classes);
+
 /*
  * DRM operations:
  */
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 49/65] drm-dyndbg: add DRM_CLASSMAP_USE to gma500 driver
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (47 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 48/65] drm-dyndbg: add DRM_CLASSMAP_USE to etnaviv Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 13:20 ` [PATCH v11 50/65] drm-dyndbg: add DRM_CLASSMAP_USE to radeon Jim Cromie
                   ` (16 subsequent siblings)
  65 siblings, 0 replies; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Patrik Jakobsson,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, dri-devel,
	linux-kernel
  Cc: Jim Cromie, jani.nikula, ville.syrjala, christian.koenig,
	matthew.auld, arunpravin.paneerselvam, louis.chauvet, skhan,
	pmladek, ukaszb, intel-gfx, amd-gfx

The gma500 has 126 DRM_UT_* debugs, make them controllable when
CONFIG_DRM_USE_DYNAMIC_DEBUG=y by telling dyndbg that the module has
class'd debugs.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 drivers/gpu/drm/gma500/psb_drv.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c
index 005ab7f5355f..92b18c76b44e 100644
--- a/drivers/gpu/drm/gma500/psb_drv.c
+++ b/drivers/gpu/drm/gma500/psb_drv.c
@@ -41,6 +41,8 @@
 static const struct drm_driver driver;
 static int psb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
 
+DRM_CLASSMAP_USE(drm_debug_classes);
+
 /*
  * The table below contains a mapping of the PCI vendor ID and the PCI Device ID
  * to the different groups of PowerVR 5-series chip designs
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 50/65] drm-dyndbg: add DRM_CLASSMAP_USE to radeon
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (48 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 49/65] drm-dyndbg: add DRM_CLASSMAP_USE to gma500 driver Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 13:20 ` [PATCH v11 51/65] drm-dyndbg: add DRM_CLASSMAP_USE to vmwgfx driver Jim Cromie
                   ` (15 subsequent siblings)
  65 siblings, 0 replies; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Alex Deucher,
	Christian König, amd-gfx, dri-devel, linux-kernel
  Cc: Jim Cromie, mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, matthew.auld, arunpravin.paneerselvam,
	louis.chauvet, skhan, pmladek, ukaszb, intel-gfx

radeon has some DRM_UT_* debugs, make them controllable when
CONFIG_DRM_USE_DYNAMIC_DEBUG=y by telling dyndbg about its use of
the class'd debugs.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 drivers/gpu/drm/radeon/radeon_drv.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 87fd6255c114..a7133fb6377d 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -254,6 +254,8 @@ static const struct pci_device_id pciidlist[] = {
 };
 MODULE_DEVICE_TABLE(pci, pciidlist);
 
+DRM_CLASSMAP_USE(drm_debug_classes);
+
 static const struct drm_driver kms_driver;
 
 static bool radeon_support_enabled(struct device *dev,
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 51/65] drm-dyndbg: add DRM_CLASSMAP_USE to vmwgfx driver
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (49 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 50/65] drm-dyndbg: add DRM_CLASSMAP_USE to radeon Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 13:20 ` [PATCH v11 52/65] drm-dyndbg: add DRM_CLASSMAP_USE to vkms driver Jim Cromie
                   ` (14 subsequent siblings)
  65 siblings, 0 replies; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Zack Rusin,
	Broadcom internal kernel review list, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, dri-devel, linux-kernel
  Cc: Jim Cromie, jani.nikula, ville.syrjala, christian.koenig,
	matthew.auld, arunpravin.paneerselvam, louis.chauvet, skhan,
	pmladek, ukaszb, intel-gfx, amd-gfx

The vmwgfx driver has a number of DRM_UT_* debugs, make them
controllable when CONFIG_DRM_USE_DYNAMIC_DEBUG=y by telling dyndbg
that the module uses them.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 0f101aedb49a..d877d0a8c830 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -259,6 +259,8 @@ static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
 static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
 			      void *ptr);
 
+DRM_CLASSMAP_USE(drm_debug_classes);
+
 MODULE_PARM_DESC(restrict_iommu, "Try to limit IOMMU usage for TTM pages");
 module_param_named(restrict_iommu, vmw_restrict_iommu, int, 0600);
 MODULE_PARM_DESC(force_coherent, "Force coherent TTM pages");
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 52/65] drm-dyndbg: add DRM_CLASSMAP_USE to vkms driver
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (50 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 51/65] drm-dyndbg: add DRM_CLASSMAP_USE to vmwgfx driver Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 13:20 ` [PATCH v11 53/65] drm-dyndbg: add DRM_CLASSMAP_USE to udl driver Jim Cromie
                   ` (13 subsequent siblings)
  65 siblings, 0 replies; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Louis Chauvet, Haneen Mohammed,
	Melissa Wen, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	dri-devel, linux-kernel
  Cc: Jim Cromie, jani.nikula, ville.syrjala, christian.koenig,
	matthew.auld, arunpravin.paneerselvam, skhan, pmladek, ukaszb,
	intel-gfx, amd-gfx

The vkms driver has a number of DRM_UT_* debugs, make them
controllable when CONFIG_DRM_USE_DYNAMIC_DEBUG=y by telling dyndbg
that the module uses them.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 drivers/gpu/drm/vkms/vkms_drv.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c
index 95020765c4c2..e22c15f045d1 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.c
+++ b/drivers/gpu/drm/vkms/vkms_drv.c
@@ -40,6 +40,8 @@
 
 static struct vkms_config *default_config;
 
+DRM_CLASSMAP_USE(drm_debug_classes);
+
 static bool enable_cursor = true;
 module_param_named(enable_cursor, enable_cursor, bool, 0444);
 MODULE_PARM_DESC(enable_cursor, "Enable/Disable cursor support");
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 53/65] drm-dyndbg: add DRM_CLASSMAP_USE to udl driver
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (51 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 52/65] drm-dyndbg: add DRM_CLASSMAP_USE to vkms driver Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 13:20 ` [PATCH v11 54/65] drm-dyndbg: add DRM_CLASSMAP_USE to mgag200 driver Jim Cromie
                   ` (12 subsequent siblings)
  65 siblings, 0 replies; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Dave Airlie, Sean Paul,
	Thomas Zimmermann, Maarten Lankhorst, Maxime Ripard, dri-devel,
	linux-kernel
  Cc: Jim Cromie, jani.nikula, ville.syrjala, christian.koenig,
	matthew.auld, arunpravin.paneerselvam, louis.chauvet, skhan,
	pmladek, ukaszb, intel-gfx, amd-gfx

The udl driver has a number of DRM_UT_* debugs, make them
controllable when CONFIG_DRM_USE_DYNAMIC_DEBUG=y by telling dyndbg
that the module uses them.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 drivers/gpu/drm/udl/udl_main.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c
index 08a0e9480d70..58fea20a1e81 100644
--- a/drivers/gpu/drm/udl/udl_main.c
+++ b/drivers/gpu/drm/udl/udl_main.c
@@ -21,6 +21,8 @@
 
 #define NR_USB_REQUEST_CHANNEL 0x12
 
+DRM_CLASSMAP_USE(drm_debug_classes);
+
 #define MAX_TRANSFER (PAGE_SIZE*16 - BULK_SIZE)
 #define WRITES_IN_FLIGHT (20)
 #define MAX_VENDOR_DESCRIPTOR_SIZE 256
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 54/65] drm-dyndbg: add DRM_CLASSMAP_USE to mgag200 driver
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (52 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 53/65] drm-dyndbg: add DRM_CLASSMAP_USE to udl driver Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 13:20 ` [PATCH v11 55/65] drm-dyndbg: add DRM_CLASSMAP_USE to the gud driver Jim Cromie
                   ` (11 subsequent siblings)
  65 siblings, 0 replies; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Dave Airlie, Thomas Zimmermann,
	Jocelyn Falempe, Maarten Lankhorst, Maxime Ripard, dri-devel,
	linux-kernel
  Cc: Jim Cromie, jani.nikula, ville.syrjala, christian.koenig,
	matthew.auld, arunpravin.paneerselvam, louis.chauvet, skhan,
	pmladek, ukaszb, intel-gfx, amd-gfx

The mgag200 driver has a number of DRM_UT_* debugs, make them
controllable when CONFIG_DRM_USE_DYNAMIC_DEBUG=y by telling dyndbg
that the module uses them.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 drivers/gpu/drm/mgag200/mgag200_drv.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c
index a32be27c39e8..02a703e5de80 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.c
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.c
@@ -28,6 +28,8 @@ static int mgag200_modeset = -1;
 MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
 module_param_named(modeset, mgag200_modeset, int, 0400);
 
+DRM_CLASSMAP_USE(drm_debug_classes);
+
 int mgag200_init_pci_options(struct pci_dev *pdev, u32 option, u32 option2)
 {
 	struct device *dev = &pdev->dev;
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 55/65] drm-dyndbg: add DRM_CLASSMAP_USE to the gud driver
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (53 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 54/65] drm-dyndbg: add DRM_CLASSMAP_USE to mgag200 driver Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 13:20 ` [PATCH v11 56/65] drm-dyndbg: add DRM_CLASSMAP_USE to the qxl driver Jim Cromie
                   ` (10 subsequent siblings)
  65 siblings, 0 replies; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Ruben Wauters, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, dri-devel, linux-kernel
  Cc: Jim Cromie, jani.nikula, ville.syrjala, christian.koenig,
	matthew.auld, arunpravin.paneerselvam, louis.chauvet, skhan,
	pmladek, ukaszb, intel-gfx, amd-gfx

The gud driver has a number of DRM_UT_* debugs, make them
controllable when CONFIG_DRM_USE_DYNAMIC_DEBUG=y by telling dyndbg
that the module uses them.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 drivers/gpu/drm/gud/gud_drv.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/gud/gud_drv.c b/drivers/gpu/drm/gud/gud_drv.c
index d0122d477610..cf2692d89bc5 100644
--- a/drivers/gpu/drm/gud/gud_drv.c
+++ b/drivers/gpu/drm/gud/gud_drv.c
@@ -32,6 +32,8 @@
 
 #include "gud_internal.h"
 
+DRM_CLASSMAP_USE(drm_debug_classes);
+
 /* Only used internally */
 static const struct drm_format_info gud_drm_format_r1 = {
 	.format = GUD_DRM_FORMAT_R1,
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 56/65] drm-dyndbg: add DRM_CLASSMAP_USE to the qxl driver
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (54 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 55/65] drm-dyndbg: add DRM_CLASSMAP_USE to the gud driver Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 13:20 ` [PATCH v11 57/65] drm-dyndbg: add DRM_CLASSMAP_USE to the drm_gem_shmem_helper driver Jim Cromie
                   ` (9 subsequent siblings)
  65 siblings, 0 replies; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Dave Airlie, Gerd Hoffmann,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	virtualization, spice-devel, dri-devel, linux-kernel
  Cc: Jim Cromie, jani.nikula, ville.syrjala, christian.koenig,
	matthew.auld, arunpravin.paneerselvam, louis.chauvet, skhan,
	pmladek, ukaszb, intel-gfx, amd-gfx

The qxl driver has a number of DRM_UT_* debugs, make them
controllable when CONFIG_DRM_USE_DYNAMIC_DEBUG=y by telling dyndbg
that the module uses them.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 drivers/gpu/drm/qxl/qxl_drv.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c
index 2bbb1168a3ff..73998bb331d9 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.c
+++ b/drivers/gpu/drm/qxl/qxl_drv.c
@@ -67,6 +67,8 @@ module_param_named(modeset, qxl_modeset, int, 0400);
 MODULE_PARM_DESC(num_heads, "Number of virtual crtcs to expose (default 4)");
 module_param_named(num_heads, qxl_num_crtc, int, 0400);
 
+DRM_CLASSMAP_USE(drm_debug_classes);
+
 static struct drm_driver qxl_driver;
 static struct pci_driver qxl_pci_driver;
 
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 57/65] drm-dyndbg: add DRM_CLASSMAP_USE to the drm_gem_shmem_helper driver
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (55 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 56/65] drm-dyndbg: add DRM_CLASSMAP_USE to the qxl driver Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 13:20 ` [PATCH v11 58/65] accel: add -DDYNAMIC_DEBUG_MODULE to subdir-ccflags Jim Cromie
                   ` (8 subsequent siblings)
  65 siblings, 0 replies; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, dri-devel, linux-kernel
  Cc: Jim Cromie, jani.nikula, ville.syrjala, christian.koenig,
	matthew.auld, arunpravin.paneerselvam, louis.chauvet, skhan,
	pmladek, ukaszb, intel-gfx, amd-gfx

The drm_gem_shmem_helper driver has a number of DRM_UT_* debugs, make
them controllable when CONFIG_DRM_USE_DYNAMIC_DEBUG=y by telling
dyndbg that the module uses them.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 drivers/gpu/drm/drm_gem_shmem_helper.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c
index 4500deef4127..a0bb6110ad83 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -26,6 +26,7 @@
 #include <drm/drm_print.h>
 
 MODULE_IMPORT_NS("DMA_BUF");
+DRM_CLASSMAP_USE(drm_debug_classes);
 
 /**
  * DOC: overview
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 58/65] accel: add -DDYNAMIC_DEBUG_MODULE to subdir-ccflags
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (56 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 57/65] drm-dyndbg: add DRM_CLASSMAP_USE to the drm_gem_shmem_helper driver Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:20 ` [PATCH v11 59/65] accel/ivpu: implement IVPU_DBG_* as a dyndbg classmap Jim Cromie
                   ` (7 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Oded Gabbay, dri-devel,
	linux-kernel
  Cc: Jim Cromie, mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	intel-gfx, amd-gfx

With CONFIG_DRM_USE_DYNAMIC_DEBUG=y and CONFIG_DYNAMIC_DEBUG=n,
accelerator modules are currently missing the _dynamic_func_call_cls
macro, due to its conditional definition in dynamic_debug.h, which
depends upon -DDYNAMIC_DEBUG_MODULE.

So add that to subir-ccflags for all accels, in accel/Makefile.

Notes:

The added "indirection" allows modules to individually enable
dynamic-debug, where a CONFIG_ option would be global to the build.

Several accelerator modules make drm*dbg() calls, so in effect they
*are* DRM modules.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 drivers/accel/Makefile | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/accel/Makefile b/drivers/accel/Makefile
index 1d3a7251b950..44db786ea223 100644
--- a/drivers/accel/Makefile
+++ b/drivers/accel/Makefile
@@ -1,8 +1,13 @@
 # SPDX-License-Identifier: GPL-2.0-only
 
+# several accel modules use drm*dbg, so they *are* DRM modules.
+# When built with only CONFIG_DYNAMIC_DEBUG_CORE
+# (and not CONFIG_DYNAMIC_DEBUG), they need this flag
+subdir-ccflags-$(CONFIG_DRM_USE_DYNAMIC_DEBUG) += -DDYNAMIC_DEBUG_MODULE
+
 obj-$(CONFIG_DRM_ACCEL_AMDXDNA)		+= amdxdna/
 obj-$(CONFIG_DRM_ACCEL_ARM_ETHOSU)	+= ethosu/
 obj-$(CONFIG_DRM_ACCEL_HABANALABS)	+= habanalabs/
 obj-$(CONFIG_DRM_ACCEL_IVPU)		+= ivpu/
 obj-$(CONFIG_DRM_ACCEL_QAIC)		+= qaic/
-obj-$(CONFIG_DRM_ACCEL_ROCKET)		+= rocket/
\ No newline at end of file
+obj-$(CONFIG_DRM_ACCEL_ROCKET)		+= rocket/
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 59/65] accel/ivpu: implement IVPU_DBG_* as a dyndbg classmap
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (57 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 58/65] accel: add -DDYNAMIC_DEBUG_MODULE to subdir-ccflags Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:20 ` [PATCH v11 60/65] drm: restore CONFIG_DRM_USE_DYNAMIC_DEBUG un-BROKEN Jim Cromie
                   ` (6 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Maciej Falkowski,
	Karol Wachowski, Oded Gabbay, dri-devel, linux-kernel
  Cc: Jim Cromie, mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	intel-gfx, amd-gfx

Invoke DRM_CLASSMAP_DEFINE to create a classmap of
class-ids/categories for ivpu_dbg().

This brings static-key optimized-off benefits to the ivpu_dbg()
callsites.  DRM_CLASSMAP_PARAM_REF wires the sysfs kparam to the
classmap.

This is the 1st real-world example of a module avoiding another
module's classmap's class_id range reservation.

Its also something of an oddity: it "is" a DRM module only cuz

1. CONFIG_DRM_ACCEL_IVPU exists.

2. code therefore uses CONFIG_DRM_USE_DYNAMIC_DEBUG, so must also use
   it's dependent wrappers: DRM_CLASSMAP_*

accel/amdxdna is already using drm.debug via dev_dbg(), so it is more
fully DRM but iirc its a single call.

Anyway, to play nice with DRM, we change all the constants, from
macros calling BIT(X), to an explicit "enum ivpu_dbg_category"
starting at 16 to avoid DRM_UT_CORE..RES.  This is all in an indef to
avoid changing the constants for the non-dyndbg case.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 drivers/accel/ivpu/ivpu_drv.c | 27 +++++++++++++++++++--
 drivers/accel/ivpu/ivpu_drv.h | 45 ++++++++++++++++++++++++++++++-----
 2 files changed, 64 insertions(+), 8 deletions(-)

diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c
index dd3a486df5f1..2d7d290eb8bb 100644
--- a/drivers/accel/ivpu/ivpu_drv.c
+++ b/drivers/accel/ivpu/ivpu_drv.c
@@ -3,6 +3,7 @@
  * Copyright (C) 2020-2025 Intel Corporation
  */
 
+#include <linux/dynamic_debug.h>
 #include <linux/firmware.h>
 #include <linux/module.h>
 #include <linux/pci.h>
@@ -37,8 +38,30 @@
 #define DRIVER_VERSION_STR "1.0.0 " UTS_RELEASE
 #endif
 
-int ivpu_dbg_mask;
-module_param_named(dbg_mask, ivpu_dbg_mask, int, 0644);
+unsigned long ivpu_dbg_mask;
+
+#if !defined(CONFIG_DRM_USE_DYNAMIC_DEBUG)
+
+module_param_named(dbg_mask, ivpu_dbg_mask, ulong, 0644);
+#else
+DRM_CLASSMAP_DEFINE(ivpu_dbg_classes, DD_CLASS_TYPE_DISJOINT_BITS,
+		IVPU_DBG_REG,
+		"IVPU_DBG_REG",
+		"IVPU_DBG_IRQ",
+		"IVPU_DBG_MMU",
+		"IVPU_DBG_FILE",
+		"IVPU_DBG_MISC",
+		"IVPU_DBG_FW_BOOT",
+		"IVPU_DBG_PM",
+		"IVPU_DBG_IPC",
+		"IVPU_DBG_BO",
+		"IVPU_DBG_JOB",
+		"IVPU_DBG_JSM",
+		"IVPU_DBG_KREF",
+		"IVPU_DBG_RPM",
+		"IVPU_DBG_MMU_MAP");
+DRM_CLASSMAP_PARAM_REF(dbg_mask, ivpu_dbg_mask, ivpu_dbg_classes, p);
+#endif
 MODULE_PARM_DESC(dbg_mask, "Driver debug mask. See IVPU_DBG_* macros.");
 
 int ivpu_test_mode;
diff --git a/drivers/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h
index 6378e23e0c97..b59aa0759e26 100644
--- a/drivers/accel/ivpu/ivpu_drv.h
+++ b/drivers/accel/ivpu/ivpu_drv.h
@@ -63,6 +63,10 @@
 
 #define IVPU_SCHED_MODE_AUTO -1
 
+extern unsigned long ivpu_dbg_mask;
+
+#if !defined(CONFIG_DRM_USE_DYNAMIC_DEBUG)
+
 #define IVPU_DBG_REG	 BIT(0)
 #define IVPU_DBG_IRQ	 BIT(1)
 #define IVPU_DBG_MMU	 BIT(2)
@@ -79,6 +83,41 @@
 #define IVPU_DBG_MMU_MAP BIT(13)
 #define IVPU_DBG_IOCTL   BIT(14)
 
+#define ivpu_dbg(vdev, type, fmt, args...) do {				\
+	if (unlikely(IVPU_DBG_##type & ivpu_dbg_mask))			\
+		dev_dbg((vdev)->drm.dev, "[%s] " fmt, #type, ##args);	\
+} while (0)
+
+#else /* !!CONFIG_DRM_USE_DYNAMIC_DEBUG */
+
+enum ivpu_dbg_category {
+	/*
+	 * since accels are drm-devices (CONFIG_DRM_ACCEL_*), adjust
+	 * IVPU_DBG_* to avoid DRMs 0..10 class_id reservations.
+	 */
+	IVPU_DBG_REG = 16,
+	IVPU_DBG_IRQ,
+	IVPU_DBG_MMU,
+	IVPU_DBG_FILE,
+	IVPU_DBG_MISC,
+	IVPU_DBG_FW_BOOT,
+	IVPU_DBG_PM,
+	IVPU_DBG_IPC,
+	IVPU_DBG_BO,
+	IVPU_DBG_JOB,
+	IVPU_DBG_JSM,
+	IVPU_DBG_KREF,
+	IVPU_DBG_RPM,
+	IVPU_DBG_MMU_MAP,
+	IVPU_DBG_IOCTL
+};
+
+#define ivpu_dbg(vdev, type, fmt, ...)                    \
+	_dynamic_func_call_cls(IVPU_DBG_##type, fmt, __dynamic_dev_dbg,	\
+			       (vdev)->drm.dev, fmt, ##__VA_ARGS__)
+
+#endif /* !!CONFIG_DRM_USE_DYNAMIC_DEBUG */
+
 #define ivpu_err(vdev, fmt, ...) \
 	drm_err(&(vdev)->drm, "%s(): " fmt, __func__, ##__VA_ARGS__)
 
@@ -93,11 +132,6 @@
 
 #define ivpu_info(vdev, fmt, ...) drm_info(&(vdev)->drm, fmt, ##__VA_ARGS__)
 
-#define ivpu_dbg(vdev, type, fmt, args...) do {                                \
-	if (unlikely(IVPU_DBG_##type & ivpu_dbg_mask))                         \
-		dev_dbg((vdev)->drm.dev, "[%s] " fmt, #type, ##args);          \
-} while (0)
-
 #define IVPU_WA(wa_name) (vdev->wa.wa_name)
 
 #define IVPU_PRINT_WA(wa_name) do {					\
@@ -208,7 +242,6 @@ struct ivpu_file_priv {
 	bool aborted;
 };
 
-extern int ivpu_dbg_mask;
 extern u8 ivpu_pll_min_ratio;
 extern u8 ivpu_pll_max_ratio;
 extern int ivpu_sched_mode;
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 60/65] drm: restore CONFIG_DRM_USE_DYNAMIC_DEBUG un-BROKEN
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (58 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 59/65] accel/ivpu: implement IVPU_DBG_* as a dyndbg classmap Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:20 ` [PATCH v11 61/65] accel/ethosu: enable drm.debug control Jim Cromie
                   ` (5 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, dri-devel, linux-kernel
  Cc: Jim Cromie, jani.nikula, ville.syrjala, christian.koenig,
	matthew.auld, arunpravin.paneerselvam, louis.chauvet, skhan,
	pmladek, ukaszb, intel-gfx, amd-gfx

Time for some thorough CI.

Also, the previous 18 patches could perhaps be replaced by a single
invocation of DYNDBG_CLASSMAP_USE, from a C-file linked into all drm
drivers & helpers.  I didn't find such a file, nor a drm-client
linkage item in the Makefile.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 drivers/gpu/drm/Kconfig.debug | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/Kconfig.debug b/drivers/gpu/drm/Kconfig.debug
index 3b7886865335..48674fae5958 100644
--- a/drivers/gpu/drm/Kconfig.debug
+++ b/drivers/gpu/drm/Kconfig.debug
@@ -1,7 +1,6 @@
 config DRM_USE_DYNAMIC_DEBUG
 	bool "use dynamic debug to implement drm.debug"
 	default n
-	depends on BROKEN
 	depends on DRM
 	depends on DYNAMIC_DEBUG || DYNAMIC_DEBUG_CORE
 	depends on JUMP_LABEL
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 61/65] accel/ethosu: enable drm.debug control
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (59 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 60/65] drm: restore CONFIG_DRM_USE_DYNAMIC_DEBUG un-BROKEN Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:20 ` [PATCH v11 62/65] accel/rocket: " Jim Cromie
                   ` (4 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Rob Herring (Arm), Tomeu Vizoso,
	Oded Gabbay, dri-devel, linux-kernel
  Cc: Jim Cromie, mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	intel-gfx, amd-gfx

ethosu.ko has several drm*dbg() calls, it must call DRM_CLASSMAP_USE
to tell dynamic-debug what classmap enables them.
Also include drm/drm_print.h explicitly.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 drivers/accel/ethosu/ethosu_drv.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/accel/ethosu/ethosu_drv.c b/drivers/accel/ethosu/ethosu_drv.c
index 9992193d7338..a0b8cb81a359 100644
--- a/drivers/accel/ethosu/ethosu_drv.c
+++ b/drivers/accel/ethosu/ethosu_drv.c
@@ -17,12 +17,15 @@
 #include <drm/drm_gem.h>
 #include <drm/drm_accel.h>
 #include <drm/ethosu_accel.h>
+#include <drm/drm_print.h>
 
 #include "ethosu_drv.h"
 #include "ethosu_device.h"
 #include "ethosu_gem.h"
 #include "ethosu_job.h"
 
+DRM_CLASSMAP_USE(drm_debug_classes);
+
 static int ethosu_ioctl_dev_query(struct drm_device *ddev, void *data,
 				  struct drm_file *file)
 {
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 62/65] accel/rocket: enable drm.debug control
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (60 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 61/65] accel/ethosu: enable drm.debug control Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:20 ` [PATCH v11 63/65] drm_buddy: fix 64-bit truncation in power-of-2 rounding Jim Cromie
                   ` (3 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Tomeu Vizoso, Oded Gabbay,
	dri-devel, linux-kernel
  Cc: Jim Cromie, mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	intel-gfx, amd-gfx

rocket.ko has several drm*dbg() calls, it must call DRM_CLASSMAP_USE
to tell dynamic-debug what classmap enables them.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 drivers/accel/rocket/rocket_gem.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/accel/rocket/rocket_gem.c b/drivers/accel/rocket/rocket_gem.c
index b6a385d2edfc..0d06857b96ad 100644
--- a/drivers/accel/rocket/rocket_gem.c
+++ b/drivers/accel/rocket/rocket_gem.c
@@ -11,6 +11,8 @@
 #include "rocket_drv.h"
 #include "rocket_gem.h"
 
+DRM_CLASSMAP_USE(drm_debug_classes);
+
 static void rocket_gem_bo_free(struct drm_gem_object *obj)
 {
 	struct rocket_gem_object *bo = to_rocket_bo(obj);
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 63/65] drm_buddy: fix 64-bit truncation in power-of-2 rounding
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (61 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 62/65] accel/rocket: " Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:20 ` [PATCH v11 64/65] drm_print: fix drm_printer dynamic debug bypass Jim Cromie
                   ` (2 subsequent siblings)
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Matthew Auld, Arun Pravin,
	Christian Koenig, dri-devel, linux-kernel
  Cc: Jim Cromie, mripard, tzimmermann, maarten.lankhorst, jani.nikula,
	ville.syrjala, louis.chauvet, skhan, pmladek, ukaszb, intel-gfx,
	amd-gfx

The standard roundup_pow_of_two() and rounddown_pow_of_two() macros use
unsigned long internally, which on 32-bit architectures (like arm32) is
a 32-bit type.

drm_test_buddy_alloc_exceeds_max_order() uses the on a u64 value,
where they silently truncate the 10GB allocation, giving unexpected
success in DRM-CI.  (see below the snip).

Fix this by replacing the standard macros with safe 64-bit
power-of-two calculations using ilog2().

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---

    [23:19:40] [PASSED] drm_test_buddy_alloc_clear
    [23:19:40] [PASSED] drm_test_buddy_alloc_range_bias
    [23:19:41] [PASSED] drm_test_buddy_fragmentation_performance
    [23:19:41]     # drm_test_buddy_alloc_exceeds_max_order: EXPECTATION FAILED at drivers/gpu/drm/tests/drm_buddy_test.c:889
    [23:19:41]     Expected err == -22, but
    [23:19:41]         err == 0 (0x0)
    [23:19:41] ------------[ cut here ]------------
    [23:19:41] WARNING: drivers/gpu/drm/drm_buddy.c:405 at drm_buddy_fini+0x114/0x1b8, CPU#0: kunit_try_catch/74
    [23:19:41] CPU: 0 UID: 0 PID: 74 Comm: kunit_try_catch Tainted: G                 N  7.0.0-rc1-gdfb0bcedd08a #1 VOLUNTARY
    [23:19:41] Tainted: [N]=TEST
    [23:19:41] Hardware name: Generic DT based system
    [23:19:41] Call trace:
    [23:19:41]  unwind_backtrace from show_stack+0x10/0x14
    [23:19:41]  show_stack from dump_stack_lvl+0x3c/0x4c
    [23:19:41]  dump_stack_lvl from __warn+0xe8/0x1c4
    [23:19:41]  __warn from warn_slowpath_fmt+0xa4/0xc0
    [23:19:41]  warn_slowpath_fmt from drm_buddy_fini+0x114/0x1b8
    [23:19:41]  drm_buddy_fini from drm_test_buddy_alloc_exceeds_max_order+0x1c8/0x36c
    [23:19:41]  drm_test_buddy_alloc_exceeds_max_order from kunit_try_run_case+0x78/0x1c8
    [23:19:41]  kunit_try_run_case from kunit_generic_run_threadfn_adapter+0x1c/0x34
    [23:19:41]  kunit_generic_run_threadfn_adapter from kthread+0x108/0x134
    [23:19:41]  kthread from ret_from_fork+0x14/0x28
    [23:19:41] Exception stack(0xf0bd5fb0 to 0xf0bd5ff8)
    [23:19:41] 5fa0:                                     00000000 00000000 00000000 00000000
    [23:19:41] 5fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
    [23:19:41] 5fe0: 00000000 00000000 00000000 00000000 00000013 00000000
    [23:19:41] ---[ end trace 0000000000000000 ]---
    [23:19:41]     # drm_test_buddy_alloc_exceeds_max_order: drivers/gpu/drm/drm_buddy.c:406: buddy_fini() root
    [23:19:41] ------------[ cut here ]------------
    [23:19:41] WARNING: drivers/gpu/drm/drm_buddy.c:414 at drm_buddy_fini+0x1b4/0x1b8, CPU#0: kunit_try_catch/74
    [23:19:41] CPU: 0 UID: 0 PID: 74 Comm: kunit_try_catch Tainted: G        W        N  7.0.0-rc1-gdfb0bcedd08a #1 VOLUNTARY
    [23:19:41] Tainted: [W]=WARN, [N]=TEST
    [23:19:41] Hardware name: Generic DT based system
    [23:19:41] Call trace:
    [23:19:41]  unwind_backtrace from show_stack+0x10/0x14
    [23:19:41]  show_stack from dump_stack_lvl+0x3c/0x4c
    [23:19:41]  dump_stack_lvl from __warn+0xe8/0x1c4
    [23:19:41]  __warn from warn_slowpath_fmt+0xa4/0xc0
    [23:19:41]  warn_slowpath_fmt from drm_buddy_fini+0x1b4/0x1b8
    [23:19:41]  drm_buddy_fini from drm_test_buddy_alloc_exceeds_max_order+0x1c8/0x36c
    [23:19:41]  drm_test_buddy_alloc_exceeds_max_order from kunit_try_run_case+0x78/0x1c8
    [23:19:41]  kunit_try_run_case from kunit_generic_run_threadfn_adapter+0x1c/0x34
    [23:19:41]  kunit_generic_run_threadfn_adapter from kthread+0x108/0x134
    [23:19:41]  kthread from ret_from_fork+0x14/0x28
    [23:19:41] Exception stack(0xf0bd5fb0 to 0xf0bd5ff8)
    [23:19:41] 5fa0:                                     00000000 00000000 00000000 00000000
    [23:19:41] 5fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
    [23:19:41] 5fe0: 00000000 00000000 00000000 00000000 00000013 00000000
    [23:19:41] ---[ end trace 0000000000000000 ]---
    [23:19:41] [FAILED] drm_test_buddy_alloc_exceeds_max_order
    [23:19:41]     # drm_buddy: Testing DRM buddy manager, with random_seed=0xacce106c
    [23:19:41]     # module: drm_buddy_test
    [23:19:41] # drm_buddy: pass:8 fail:1 skip:0 total:9
---
 drivers/gpu/buddy.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/buddy.c b/drivers/gpu/buddy.c
index 52686672e99f..ed4d33a30687 100644
--- a/drivers/gpu/buddy.c
+++ b/drivers/gpu/buddy.c
@@ -1091,7 +1091,7 @@ static int __alloc_contig_try_harder(struct gpu_buddy *mm,
 	u64 modify_size;
 	int err;
 
-	modify_size = rounddown_pow_of_two(size);
+	modify_size = 1ULL << ilog2(size);
 	pages = modify_size >> ilog2(mm->chunk_size);
 	order = fls(pages) - 1;
 	if (order == 0)
@@ -1318,7 +1318,7 @@ int gpu_buddy_alloc_blocks(struct gpu_buddy *mm,
 
 	/* Roundup the size to power of 2 */
 	if (flags & GPU_BUDDY_CONTIGUOUS_ALLOCATION) {
-		size = roundup_pow_of_two(size);
+		size = 1ULL << (ilog2(size - 1) + 1);
 		min_block_size = size;
 		/*
 		 * Normalize the requested size to min_block_size for regular allocations.
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 64/65] drm_print: fix drm_printer dynamic debug bypass
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (62 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 63/65] drm_buddy: fix 64-bit truncation in power-of-2 rounding Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 13:20 ` [PATCH v11 65/65] drm_vblank: use dyndbg's static-key to avoid flag-check Jim Cromie
  2026-03-13 21:00 ` Claude review: Fix DRM_USE_DYNAMIC_DEBUG=y Claude Code Review Bot
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Luca Coelho, Jani Nikula, dri-devel,
	linux-kernel
  Cc: Jim Cromie, ville.syrjala, christian.koenig, matthew.auld,
	arunpravin.paneerselvam, louis.chauvet, skhan, pmladek, ukaszb,
	intel-gfx, amd-gfx

drm_debug_enabled([1]) is the canonical bit-test for drm.debug.

Commit 6ce6fae84536 ("drm_print: optimize drm_debug_enabled for
jump-label") did several things:

A- renamed [1] to drm_debug_enabled_raw()

B- introduced __drm_debug_enabled(), which evald to either 'true' or
   _raw([A]), depending upon [2] CONFIG_DRM_USE_DYNAMIC_DEBUG=y/n.

C- altered *dev_dbg() to call __drm_debug_enabled().

D- redefined [1] to drm_debug_enabled_instrumented().  This called
   _raw(), but added a pr_debug() too.  This allowed us to see how
   where and often remaining callsites were called.

When [2]=y, [B] short-circuited the bit-test, since dyndbg's wrapper
macro had already set the callsite reachable/unreachable.

Later, commit 9fd6f61a297e ("drm/print: add drm_dbg_printer() for drm
device specific printer") added __drm_printfn_dbg(), but mistakenly
used the internal bypass __drm_debug_enabled() instead of the
canonical drm_debug_enabled(). This went unnoticed because at the
time, [2]=y was marked BROKEN.

Because __drm_printfn_dbg() is a shared callback where the callpath is
not directly guarded by dyndbg's static-key, checking the bypass macro
caused it to evaluate to 'true' and always print, ignoring the drm.debug
bit-mask entirely.

This results in a flood of messages in environments with slow serial
consoles, as seen in DRM-CI on i915 CML devices. When IGT causes a
mismatch in intel_pipe_config_compare(), the resulting UART storm
causes a hard timeout after 20 minutes (see below the snip).

To fix this, change __drm_printfn_dbg() to use the explicit
drm_debug_enabled_instrumented() instead. This ensures the bit-test is
performed at runtime for this unguarded helper, stopping the UART storm.

[1] drm_debug_enabled
[2] CONFIG_DRM_USE_DYNAMIC_DEBUG

Fixes: 9fd6f61a297e ("drm/print: add drm_dbg_printer() for drm device specific printer")
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---

some of the many:

 i915 0000:00:02.0: [drm:intel_pipe_config_compare [i915]] [CRTC:57:pipe A] fastset requirement not met in hw.adjusted_mode.crtc_vsync_start (expected 0, found 1083)
 i915 0000:00:02.0: [drm:intel_pipe_config_compare [i915]] [CRTC:57:pipe A] fastset requirement not met in hw.adjusted_mode.crtc_vsync_end (expected 0, found 1097)
 i915 0000:00:02.0: [drm:intel_pipe_config_compare [i915]] [CRTC:57:pipe A] fastset requirement not met in hw.adjusted_mode.crtc_vtotal (expected 0, found 1116)
 i915 0000:00:02.0: [drm:intel_pipe_config_compare [i915]] [CRTC:57:pipe A] fastset requirement not met in hw.adjusted_mode.crtc_vblank_end (expected 0, found 1116)
 i915 0000:00:02.0: [drm:intel_pipe_config_compare [i915]] [CRTC:82:pipe B] fastset requirement not met in hw.adjusted_mode.crtc_clock (expected 0, found 112800)
 i915 0000:00:02.0: [drm:intel_pipe_config_compare [i915]] [CRTC:82:pipe B] fastset requirement not met in hw.adjusted_mode.crtc_clock (expected 0, found 141000)
 i915 0000:00:02.0: [drm:intel_pipe_config_compare [i915]] [CRTC:82:pipe B] fastset requirement not met in hw.adjusted_mode.crtc_clock (expected 0, found 141000)
 i915 0000:00:02.0: [drm:intel_pipe_config_compare [i915]] [CRTC:82:pipe B] fastset requirement not met in hw.adjusted_mode.crtc_clock (expected 0, found 61040)
 i915 0000:00:02.0: [drm:intel_pipe_config_compare [i915]] [CRTC:82:pipe B] fastset requirement not met in hw.adjusted_mode.crtc_clock (expected 0, found 76300)
 i915 0000:00:02.0: [drm:intel_pipe_config_compare [i915]] [CRTC:82:pipe B] fastset requirement not met in hw.adjusted_mode.crtc_clock (expected 0, found 76300)
 i915 0000:00:02.0: [drm:intel_pipe_config_compare [i915]] [CRTC:82:pipe B] fastset requirement not met in port_clock (expected 0, found 216000)
 i915 0000:00:02.0: [drm:intel_pipe_config_compare [i915]] [CRTC:82:pipe B] fastset requirement not met in port_clock (expected 0, found 216000)
 i915 0000:00:02.0: [drm:intel_pipe_config_compare [i915]] [CRTC:82:pipe B] fastset requirement not met in port_clock (expected 0, found 270000)
 i915 0000:00:02.0: [drm:intel_pipe_config_compare [i915]] [CRTC:82:pipe B] fastset requirement not met in port_clock (expected 0, found 270000)
---
 drivers/gpu/drm/drm_print.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c
index ceede094ff13..b431881de2c1 100644
--- a/drivers/gpu/drm/drm_print.c
+++ b/drivers/gpu/drm/drm_print.c
@@ -214,7 +214,7 @@ void __drm_printfn_dbg(struct drm_printer *p, struct va_format *vaf)
 	const struct drm_device *drm = p->arg;
 	const struct device *dev = drm ? drm->dev : NULL;
 
-	if (!__drm_debug_enabled(p->category))
+	if (!drm_debug_enabled_instrumented(p->category))
 		return;
 
 	__drm_dev_vprintk(dev, KERN_DEBUG, p->origin, p->prefix, vaf);
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* [PATCH v11 65/65] drm_vblank: use dyndbg's static-key to avoid flag-check
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (63 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 64/65] drm_print: fix drm_printer dynamic debug bypass Jim Cromie
@ 2026-03-13 13:20 ` Jim Cromie
  2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
  2026-03-13 21:00 ` Claude review: Fix DRM_USE_DYNAMIC_DEBUG=y Claude Code Review Bot
  65 siblings, 1 reply; 114+ messages in thread
From: Jim Cromie @ 2026-03-13 13:20 UTC (permalink / raw)
  To: airlied, simona, jbaron, gregkh, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, dri-devel, linux-kernel
  Cc: Jim Cromie, jani.nikula, ville.syrjala, christian.koenig,
	matthew.auld, arunpravin.paneerselvam, louis.chauvet, skhan,
	pmladek, ukaszb, intel-gfx, amd-gfx

drm_crtc_vblank_helper_get_vblank_timestamp_internal() is called about
~100 times per sec, on a single display. It currently calls
drm_debug_enabled(DRM_UT_VBL) to avoid doing ktime_to_timespec64()
conversions when the debug logging is disabled.

When CONFIG_DRM_USE_DYNAMIC_DEBUG=Y, the drm_debug_enabled() is
redundant, because the following drm_dbg_vbl() already carries a
static-key optimization.

So move the ktime conversions into the drm_dbg_vbl() argument list,
then they are guarded natively by the static key. This avoids the
double-check entirely.

TBD: if CONFIG_DRM_USE_DYNAMIC_DEBUG=N, this does the ktime
conversions unconditionally, so this might not be prudent (yet).

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 drivers/gpu/drm/drm_vblank.c | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
index f78bf37f1e0a..0dac7eec2066 100644
--- a/drivers/gpu/drm/drm_vblank.c
+++ b/drivers/gpu/drm/drm_vblank.c
@@ -803,15 +803,11 @@ drm_crtc_vblank_helper_get_vblank_timestamp_internal(
 	 */
 	*vblank_time = ktime_sub_ns(etime, delta_ns);
 
-	if (!drm_debug_enabled(DRM_UT_VBL))
-		return true;
-
-	ts_etime = ktime_to_timespec64(etime);
-	ts_vblank_time = ktime_to_timespec64(*vblank_time);
-
 	drm_dbg_vbl(dev,
 		    "crtc %u : v p(%d,%d)@ %ptSp -> %ptSp [e %d us, %d rep]\n",
-		    pipe, hpos, vpos, &ts_etime, &ts_vblank_time,
+		    pipe, hpos, vpos,
+		    (ts_etime = ktime_to_timespec64(etime), &ts_etime),
+		    (ts_vblank_time = ktime_to_timespec64(*vblank_time), &ts_vblank_time),
 		    duration_ns / 1000, i);
 
 	return true;
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 114+ messages in thread

* Claude review: Fix DRM_USE_DYNAMIC_DEBUG=y
  2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
                   ` (64 preceding siblings ...)
  2026-03-13 13:20 ` [PATCH v11 65/65] drm_vblank: use dyndbg's static-key to avoid flag-check Jim Cromie
@ 2026-03-13 21:00 ` Claude Code Review Bot
  65 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Overall Series Review

Subject: Fix DRM_USE_DYNAMIC_DEBUG=y
Author: Jim Cromie <jim.cromie@gmail.com>
Patches: 66
Reviewed: 2026-03-14T07:00:19.881421

---

This is a v11, 65-patch series by Jim Cromie to fix `CONFIG_DRM_USE_DYNAMIC_DEBUG=y`, which has been marked `BROKEN` since Feb 2023 (commit `bb2ff6c27bc9`). The root cause was that the original `DECLARE_DYNDBG_CLASSMAP` was invoked redundantly in both drm-core and each driver, violating define-once semantics. The fix introduces a `DEFINE`/`USE` split: `DYNAMIC_DEBUG_CLASSMAP_DEFINE` (once in drm.ko) and `DYNAMIC_DEBUG_CLASSMAP_USE` (in each driver/helper).

**Architecture:** The overall design is sound. The DEFINE/USE separation correctly addresses the regression where `drm.debug=0xFF` at boot enabled debug in drm-core but not drivers. The new linker section `__dyndbg_class_users` allows dyndbg to propagate the kernel parameter's initial value to driver modules at load time.

**Concerns:**
- **Series size and ordering:** 65 patches is very large and arrives out of numbered order in the mbox (patches appear in a different sequence than their numbering). This makes review difficult and risks bisectability issues.
- **Patch 23 uses a macro name (`DYNDBG_CLASSMAP_DEFINE`) that doesn't exist until patch 24**, creating a build breakage window in the bisect chain.
- **Maintenance burden:** Each DRM driver needs a `DRM_CLASSMAP_USE()` line. New drivers will silently miss it. A mechanism tied to `drm_dev_register()` or a common C file would be preferable long-term.
- **Several patches mix cleanup with functional changes**, making review harder (e.g., patch 11 claims "no functional change" but alters observable verbose output).
- **Multiple typos in commit messages** and a few actual bugs noted below.

The dyndbg core refactoring (patches 1-18) is generally clean. The API changes (19-33) are the architectural heart and are well-designed. The DRM integration (34-65) is mostly mechanical but includes important bug fixes (drm_buddy, drm_print bypass) that arguably should be separate patches.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg: fix NULL ptr on i386 due to section alignment
  2026-03-13 13:19 ` [PATCH v11 01/65] dyndbg: fix NULL ptr on i386 due to section alignment Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Fixes a real NULL deref caused by `__dyndbg_classes` section misalignment on i386 (28-byte structs). Adding `ALIGN(8)` to `BOUNDED_SECTION*` macros and reordering sections is correct. The ORC sections are manually expanded to preserve their smaller alignment.

No issues. Well-motivated fix.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg: factor ddebug_match_desc out from ddebug_change
  2026-03-13 13:19 ` [PATCH v11 02/65] dyndbg: factor ddebug_match_desc out from ddebug_change Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Clean extraction of per-descriptor matching into `ddebug_match_desc()`. Each `continue` correctly becomes `return false`. No issues.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg: add stub macro for DECLARE_DYNDBG_CLASSMAP
  2026-03-13 13:19 ` [PATCH v11 03/65] dyndbg: add stub macro for DECLARE_DYNDBG_CLASSMAP Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Adds a no-op stub for `!CONFIG_DYNAMIC_DEBUG` builds. Correct and straightforward.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: docs/dyndbg: update examples \012 to \n
  2026-03-13 13:19 ` [PATCH v11 04/65] docs/dyndbg: update examples \012 to \n Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Trivial doc update to match reality after `47ea6f99d06e`. Fine.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: docs/dyndbg: explain flags parse 1st
  2026-03-13 13:19 ` [PATCH v11 05/65] docs/dyndbg: explain flags parse 1st Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Good doc improvement explaining flag-before-keyword parse order. Fine.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: test-dyndbg: fixup CLASSMAP usage error
  2026-03-13 13:19 ` [PATCH v11 06/65] test-dyndbg: fixup CLASSMAP usage error Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Fixes a real off-by-one: enum started at 11 instead of 10, mismatching the classmap base. Correct.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg: reword "class unknown, " to "class:_UNKNOWN_"
  2026-03-13 13:19 ` [PATCH v11 07/65] dyndbg: reword "class unknown, " to "class:_UNKNOWN_" Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Cosmetic improvement to error output for greppability. Fine.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg: make ddebug_class_param union members same size
  2026-03-13 13:19 ` [PATCH v11 08/65] dyndbg: make ddebug_class_param union members same size Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Changes `unsigned int *lvl` to `unsigned long *lvl`. **Minor bug:** The format specifier changes from `%d` to `%ld` but the value is `unsigned long` — should be `%lu`.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg: drop NUM_TYPE_ARRAY
  2026-03-13 13:19 ` [PATCH v11 09/65] dyndbg: drop NUM_TYPE_ARRAY Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Replaces custom `NUM_TYPE_ARGS` with the standard `ARRAY_SIZE` idiom. Clean improvement.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg: tweak pr_fmt to avoid expansion conflicts
  2026-03-13 13:19 ` [PATCH v11 10/65] dyndbg: tweak pr_fmt to avoid expansion conflicts Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Renames `pr_fmt(fmt)` to `pr_fmt(_FMT_)`. Low-value but harmless.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg: reduce verbose/debug clutter
  2026-03-13 13:19 ` [PATCH v11 11/65] dyndbg: reduce verbose/debug clutter Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Removes per-query match logging from `ddebug_exec_query()`. **The commit message says "no functional change" but this removes observable verbose output**, which is a functional change from a debugging perspective. The claim should be corrected.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg: refactor param_set_dyndbg_classes and below
  2026-03-13 13:19 ` [PATCH v11 12/65] dyndbg: refactor param_set_dyndbg_classes and below Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Splits into upper/lower functions with `mod_name` threading. Solid preparation for module-specific class handling. Minor: errant `*` in kdoc comment (`enforce * relative levels`).

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg: tighten fn-sig of ddebug_apply_class_bitmap
  2026-03-13 13:19 ` [PATCH v11 13/65] dyndbg: tighten fn-sig of ddebug_apply_class_bitmap Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Changes `old_bits` from pointer to value, adds `const` to `new_bits`. Correct; the asymmetry (value vs pointer) is intentional.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg: replace classmap list with a vector
  2026-03-13 13:19 ` [PATCH v11 14/65] dyndbg: replace classmap list with a vector Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Replaces `list_head` with array + count. Assumes classmaps are contiguous in the section (true for both builtins and modules). Clean simplification.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg: macrofy a 2-index for-loop pattern
  2026-03-13 13:19 ` [PATCH v11 15/65] dyndbg: macrofy a 2-index for-loop pattern Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Introduces `for_subvec()` macro with compile-time assertions. **Concern:** Only 2 use sites — this may be premature abstraction. The `__ASSERT_IS_LVALUE` / `__ASSERT_HAS_VEC_MEMBER` names use double-underscore prefix reserved for the compiler namespace. Consider renaming.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg, module: make proper substructs in _ddebug_info
  2026-03-13 13:19 ` [PATCH v11 16/65] dyndbg, module: make proper substructs in _ddebug_info Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Large refactoring renaming sections (`__dyndbg` → `__dyndbg_descriptors`, `__dyndbg_classes` → `__dyndbg_class_maps`) and introducing sub-structs. Well-structured but **breaks out-of-tree modules** compiled against old section names. This is inherent to kernel development but worth noting in the commit message.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg: hoist classmap-filter-by-modname up to ddebug_add_module
  2026-03-13 13:19 ` [PATCH v11 17/65] dyndbg: hoist classmap-filter-by-modname up to ddebug_add_module Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Introduces `dd_mark_vector_subrange` statement-expression macro. **The macro is complex** (nested for-loop with break, local variables, references to caller scope). Hard to audit. Works correctly but readability is a concern.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg: move mod_name down from struct ddebug_table to _ddebug_info
  2026-03-13 13:19 ` [PATCH v11 18/65] dyndbg: move mod_name down from struct ddebug_table to _ddebug_info Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Clean encapsulation. **Typo** in commit message: "callchans" → "callchains".

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg-API: remove DD_CLASS_TYPE_(DISJOINT|LEVEL)_NAMES and code
  2026-03-13 13:19 ` [PATCH v11 19/65] dyndbg-API: remove DD_CLASS_TYPE_(DISJOINT|LEVEL)_NAMES and code Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Removes the NAMES variants (only used by test code). Clean simplification. Minor const-correctness concern with `strchr` on `const char *instr` followed by `*nl = '\0'` — works because kernel param buffers are writable, but not ideal.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: selftests-dyndbg: add a dynamic_debug run_tests target
  2026-03-13 13:19 ` [PATCH v11 20/65] selftests-dyndbg: add a dynamic_debug run_tests target Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

**Bug:** The `config` file specifies `CONFIG_DYNAMIC_DEBUG=m` but dynamic_debug cannot be a module — it must be `=y`. The test script's `exit 0` when `/proc/dynamic_debug/control` is missing silently passes, masking configuration problems.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg: change __dynamic_func_call_cls* macros into expressions
  2026-03-13 13:19 ` [PATCH v11 21/65] dyndbg: change __dynamic_func_call_cls* macros into expressions Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Changes `do { } while(0)` to `({ })` statement expressions for the Xe driver's use case. Correct. Has Reviewed-by.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg-API: replace DECLARE_DYNDBG_CLASSMAP
  2026-03-13 13:19 ` [PATCH v11 22/65] dyndbg-API: replace DECLARE_DYNDBG_CLASSMAP Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

The architectural heart of the series — introduces `DYNAMIC_DEBUG_CLASSMAP_DEFINE` and `DYNAMIC_DEBUG_CLASSMAP_USE`. **Bug:** `test_dynamic_debug.c` has duplicate `MODULE_DESCRIPTION()` lines, which will generate a build warning. Dead `return 0;` after `default: return -1;` in `param_get_dyndbg_classes` — harmless but indicates confusion.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg: detect class_id reservation conflicts
  2026-03-13 13:19 ` [PATCH v11 23/65] dyndbg: detect class_id reservation conflicts Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

**Sequencing bug:** Uses `DYNDBG_CLASSMAP_DEFINE` which does not exist until patch 24 renames it. This breaks bisectability between patches 23 and 24. Also: "insures" → "ensures" in commit message and code comment.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg: check DYNAMIC_DEBUG_CLASSMAP_DEFINE args at compile-time
  2026-03-13 13:19 ` [PATCH v11 24/65] dyndbg: check DYNAMIC_DEBUG_CLASSMAP_DEFINE args at compile-time Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Good compile-time validation with `static_assert`. Typo: "Exersize" → "Exercise".

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg-test: change do_prints testpoint to accept a loopct
  2026-03-13 13:19 ` [PATCH v11 25/65] dyndbg-test: change do_prints testpoint to accept a loopct Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

The comment `/* maybe clamp this */` suggests the loop count should be bounded to prevent log flooding via sysfs, but no clamping is implemented. Test module, so low risk.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg-API: promote DYNAMIC_DEBUG_CLASSMAP_PARAM to API
  2026-03-13 13:19 ` [PATCH v11 26/65] dyndbg-API: promote DYNAMIC_DEBUG_CLASSMAP_PARAM to API Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

**Bug:** The `!CONFIG_DYNAMIC_DEBUG` stub for `DYNAMIC_DEBUG_CLASSMAP_PARAM_REF` takes 3 args `(_name, _var, _flags)` but the real macro takes 4 args `(_name, _bits, _var, _flags)`. This will cause compile failures when `CONFIG_DYNAMIC_DEBUG` is disabled.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg: treat comma as a token separator
  2026-03-13 13:19 ` [PATCH v11 27/65] dyndbg: treat comma as a token separator Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Clean change, allows `module,sunrpc` syntax. No issues.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg: split multi-query strings with %
  2026-03-13 13:19 ` [PATCH v11 28/65] dyndbg: split multi-query strings with % Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

**Design concern:** Using `%` as a multi-query separator breaks format string matching. The commit message acknowledges this but downplays it — patterns like `format "error: %s"` are legitimate real-world queries. An alternative separator that doesn't conflict with printf format specifiers should be considered.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: selftests-dyndbg: add test_mod_submod
  2026-03-13 13:19 ` [PATCH v11 29/65] selftests-dyndbg: add test_mod_submod Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Adds the submodule test scenario. Minor comment inaccuracy. Fine.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg: resolve "protection" of class'd pr_debug
  2026-03-13 13:19 ` [PATCH v11 30/65] dyndbg: resolve "protection" of class'd pr_debug Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Introduces the concept of "protected" classmapped pr_debug callsites that can only be controlled via their kernel parameter. **The commit message is excessively long** (reads like a design document). The unnecessary cast `(struct _ddebug_class_param *)NULL` should be just `NULL`.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg: add DYNAMIC_DEBUG_CLASSMAP_USE_(dd_class_name, offset)
  2026-03-13 13:19 ` [PATCH v11 31/65] dyndbg: add DYNAMIC_DEBUG_CLASSMAP_USE_(dd_class_name, offset) Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

**Self-described as untested.** The offset arithmetic in `ddebug_find_valid_class` (`*class_id = idx + cli->map->base - cli->offset`) needs careful verification. The author suggests dropping if too speculative — I agree this should be deferred until tested.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg: Harden classmap and callsite validation
  2026-03-13 13:19 ` [PATCH v11 32/65] dyndbg: Harden classmap and callsite validation Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Good hardening with `bad_ids` bitmask to avoid repeat warnings. The `u64` bitmask correctly covers the 0-62 class_id range. Fine.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: docs/dyndbg: add classmap info to howto
  2026-03-13 13:19 ` [PATCH v11 33/65] docs/dyndbg: add classmap info to howto Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Good documentation. Multiple typos: "theres" → "there's", "did'nt" → "didn't", missing "is" in "If the class_name accepted".

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: drm: use correct ccflags-y spelling
  2026-03-13 13:19 ` [PATCH v11 34/65] drm: use correct ccflags-y spelling Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Important fix — the original `CFLAGS-$(CONFIG_...)` was a kbuild no-op. Correct.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: drm-dyndbg: adapt drm core to use dyndbg classmaps-v2
  2026-03-13 13:20 ` [PATCH v11 35/65] drm-dyndbg: adapt drm core to use dyndbg classmaps-v2 Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Replaces `DECLARE_DYNDBG_CLASSMAP` with `DRM_CLASSMAP_DEFINE`. Clean.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: drm-dyndbg: adapt DRM to invoke DYNAMIC_DEBUG_CLASSMAP_PARAM
  2026-03-13 13:20 ` [PATCH v11 36/65] drm-dyndbg: adapt DRM to invoke DYNAMIC_DEBUG_CLASSMAP_PARAM Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Replaces ad-hoc param setup with `DRM_CLASSMAP_PARAM_REF`. Clean.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: drm-print: modernize an archaic comment
  2026-03-13 13:20 ` [PATCH v11 37/65] drm-print: modernize an archaic comment Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Minor doc cleanup. Fine.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: drm-print: fix config-dependent unused variable
  2026-03-13 13:20 ` [PATCH v11 38/65] drm-print: fix config-dependent unused variable Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Removes local `category` variable, uses `p->category` directly. Correct fix for the unused variable warning.

### PATCHES 39-57: DRM_CLASSMAP_USE in various drivers

All 19 driver patches are consistent, adding a single `DRM_CLASSMAP_USE(drm_debug_classes);` line. Drivers that previously had `DECLARE_DYNDBG_CLASSMAP` replace it; new drivers just add the line. All carry appropriate `Fixes:` tags where applicable. Minor typo in patch 44 (Xe): "dydnbg" → "dyndbg".

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: accel: add -DDYNAMIC_DEBUG_MODULE to subdir-ccflags
  2026-03-13 13:20 ` [PATCH v11 58/65] accel: add -DDYNAMIC_DEBUG_MODULE to subdir-ccflags Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Parallels patch 34 for the accel subtree. Typo in commit message: "subir-ccflags" → "subdir-ccflags".

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: accel/ivpu: implement IVPU_DBG_* as a dyndbg classmap
  2026-03-13 13:20 ` [PATCH v11 59/65] accel/ivpu: implement IVPU_DBG_* as a dyndbg classmap Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

**Bug: `IVPU_DBG_IOCTL` is missing from the `DRM_CLASSMAP_DEFINE` classnames list.** The enum defines 15 categories (REG through IOCTL at lines 13842-13860) but the classmap only lists 14 names (ending at `"IVPU_DBG_MMU_MAP"` at line 13809). `ivpu_dbg(vdev, IOCTL, ...)` calls will reference class_id 30, which has no name in the classmap and won't be controllable.

**Bug: The dyndbg version of `ivpu_dbg()` loses the `[type]` prefix.** The non-dyndbg version formats as:
```c
dev_dbg((vdev)->drm.dev, "[%s] " fmt, #type, ##args);
```
But the dyndbg version just passes `fmt` directly:
```c
_dynamic_func_call_cls(IVPU_DBG_##type, fmt, __dynamic_dev_dbg,
                       (vdev)->drm.dev, fmt, ##__VA_ARGS__)
```
This changes visible log output for ivpu when dyndbg is active.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: drm: restore CONFIG_DRM_USE_DYNAMIC_DEBUG un-BROKEN
  2026-03-13 13:20 ` [PATCH v11 60/65] drm: restore CONFIG_DRM_USE_DYNAMIC_DEBUG un-BROKEN Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Removes `depends on BROKEN`. **Concern:** The per-driver `DRM_CLASSMAP_USE` approach means every new DRM driver using `drm_dbg()` must remember to add this line, or it silently won't participate in dyndbg class control. A mechanism tied to a common linkage point would be more robust long-term.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: accel/ethosu: enable drm.debug control
  2026-03-13 13:20 ` [PATCH v11 61/65] accel/ethosu: enable drm.debug control Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Consistent `DRM_CLASSMAP_USE` addition. Fine.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: accel/rocket: enable drm.debug control
  2026-03-13 13:20 ` [PATCH v11 62/65] accel/rocket: " Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Consistent `DRM_CLASSMAP_USE` addition. Fine.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: drm_buddy: fix 64-bit truncation in power-of-2 rounding
  2026-03-13 13:20 ` [PATCH v11 63/65] drm_buddy: fix 64-bit truncation in power-of-2 rounding Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Replaces `rounddown_pow_of_two(size)` with `1ULL << ilog2(size)` and `roundup_pow_of_two(size)` with `1ULL << (ilog2(size - 1) + 1)`. **This fix is unrelated to the dyndbg series** and should be a separate standalone patch. **Edge case:** if `size == 1`, `ilog2(0)` is undefined — unlikely in practice (sizes are at least chunk_size) but worth a comment.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: drm_print: fix drm_printer dynamic debug bypass
  2026-03-13 13:20 ` [PATCH v11 64/65] drm_print: fix drm_printer dynamic debug bypass Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

**Important fix.** With `CONFIG_DRM_USE_DYNAMIC_DEBUG`, `__drm_debug_enabled()` expands to `true`, so `__drm_printfn_dbg()` (a callback, not guarded by a dyndbg static key) would print unconditionally, causing UART storms. The fix changes to `drm_debug_enabled_instrumented()`.

**Concern:** `drm_debug_enabled_instrumented()` includes a `pr_debug("todo: is this frequent enough to optimize ?\n")` instrumentation probe. In a high-frequency callback path, this adds overhead and noise when pr_debug is enabled. `drm_debug_enabled_raw()` would be more appropriate for a production fix — it does the actual bit-test without the instrumentation probe.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: drm_vblank: use dyndbg's static-key to avoid flag-check
  2026-03-13 13:20 ` [PATCH v11 65/65] drm_vblank: use dyndbg's static-key to avoid flag-check Jim Cromie
@ 2026-03-13 21:00   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:00 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

Moves `ktime_to_timespec64()` into `drm_dbg_vbl()` arguments using comma expressions. **The commit message itself flags the problem:** "TBD: if CONFIG_DRM_USE_DYNAMIC_DEBUG=N, this does the ktime conversions unconditionally." This is a **regression for non-dyndbg configs** — it removes the guard that previously avoided unnecessary ktime conversions. The comma-expression style is also unusual for kernel code. This patch should be deferred until `DRM_USE_DYNAMIC_DEBUG=y` is the default.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

* Claude review: dyndbg: factor ddebug_match_desc out from ddebug_change
  2026-03-13 13:09 ` [PATCH v11 02/65] dyndbg: factor ddebug_match_desc out from ddebug_change Jim Cromie
@ 2026-03-13 21:02   ` Claude Code Review Bot
  0 siblings, 0 replies; 114+ messages in thread
From: Claude Code Review Bot @ 2026-03-13 21:02 UTC (permalink / raw)
  To: dri-devel-reviews

Patch Review

**Commit message quality:** Good. Clearly explains the motivation — extracting the inner-loop filter logic into a separate function for readability.

**Review of the changes:**

This is a straightforward, clean code refactor. The new function:

```c
static bool ddebug_match_desc(const struct ddebug_query *query,
			      struct _ddebug *dp,
			      int valid_class)
```

extracts exactly the per-descriptor matching logic from `ddebug_change()`, converting each `continue` to `return false`. The transformation is correct — each filter condition is preserved identically.

**Minor observations:**

1. The `dp` parameter could be `const`:
```c
			      struct _ddebug *dp,
```
Since `ddebug_match_desc` only reads from `dp`, marking it `const struct _ddebug *dp` would better express intent. This is a nit, not a blocker.

2. The commit message says "also fix checkpatch complaints about spaces and braces." Looking at the diff, the only style change I can see is the spacing around `query->format+1` → `query->format + 1` (line 702 vs the removed line 750). The commit message should either enumerate what style fixes were made or just omit this note if it's a single trivial whitespace change. Mixing style fixes with refactoring in one commit is generally acceptable when the style fix is trivial like this one.

3. The function placement is good — it's placed immediately above `ddebug_change()` where it's called, with the existing block comment acting as a natural separator.

**Verdict:** Clean, correct refactoring. No functional changes. Reviewed-by worthy.

---
Generated by Claude Code Patch Reviewer

^ permalink raw reply	[flat|nested] 114+ messages in thread

end of thread, other threads:[~2026-03-13 21:02 UTC | newest]

Thread overview: 114+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-13 13:19 [PATCH v11 00/65] Fix DRM_USE_DYNAMIC_DEBUG=y Jim Cromie
2026-03-13 13:19 ` [PATCH v11 01/65] dyndbg: fix NULL ptr on i386 due to section alignment Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 02/65] dyndbg: factor ddebug_match_desc out from ddebug_change Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 03/65] dyndbg: add stub macro for DECLARE_DYNDBG_CLASSMAP Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 04/65] docs/dyndbg: update examples \012 to \n Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 05/65] docs/dyndbg: explain flags parse 1st Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 06/65] test-dyndbg: fixup CLASSMAP usage error Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 07/65] dyndbg: reword "class unknown, " to "class:_UNKNOWN_" Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 08/65] dyndbg: make ddebug_class_param union members same size Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 09/65] dyndbg: drop NUM_TYPE_ARRAY Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 10/65] dyndbg: tweak pr_fmt to avoid expansion conflicts Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 11/65] dyndbg: reduce verbose/debug clutter Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 12/65] dyndbg: refactor param_set_dyndbg_classes and below Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 13/65] dyndbg: tighten fn-sig of ddebug_apply_class_bitmap Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 14/65] dyndbg: replace classmap list with a vector Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 15/65] dyndbg: macrofy a 2-index for-loop pattern Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 16/65] dyndbg, module: make proper substructs in _ddebug_info Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 17/65] dyndbg: hoist classmap-filter-by-modname up to ddebug_add_module Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 18/65] dyndbg: move mod_name down from struct ddebug_table to _ddebug_info Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 19/65] dyndbg-API: remove DD_CLASS_TYPE_(DISJOINT|LEVEL)_NAMES and code Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 20/65] selftests-dyndbg: add a dynamic_debug run_tests target Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 21/65] dyndbg: change __dynamic_func_call_cls* macros into expressions Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 22/65] dyndbg-API: replace DECLARE_DYNDBG_CLASSMAP Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 23/65] dyndbg: detect class_id reservation conflicts Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 24/65] dyndbg: check DYNAMIC_DEBUG_CLASSMAP_DEFINE args at compile-time Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 25/65] dyndbg-test: change do_prints testpoint to accept a loopct Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 26/65] dyndbg-API: promote DYNAMIC_DEBUG_CLASSMAP_PARAM to API Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 27/65] dyndbg: treat comma as a token separator Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 28/65] dyndbg: split multi-query strings with % Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 29/65] selftests-dyndbg: add test_mod_submod Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 30/65] dyndbg: resolve "protection" of class'd pr_debug Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 31/65] dyndbg: add DYNAMIC_DEBUG_CLASSMAP_USE_(dd_class_name, offset) Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 32/65] dyndbg: Harden classmap and callsite validation Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 33/65] docs/dyndbg: add classmap info to howto Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:19 ` [PATCH v11 34/65] drm: use correct ccflags-y spelling Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:20 ` [PATCH v11 35/65] drm-dyndbg: adapt drm core to use dyndbg classmaps-v2 Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:20 ` [PATCH v11 36/65] drm-dyndbg: adapt DRM to invoke DYNAMIC_DEBUG_CLASSMAP_PARAM Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:20 ` [PATCH v11 37/65] drm-print: modernize an archaic comment Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:20 ` [PATCH v11 38/65] drm-print: fix config-dependent unused variable Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:20 ` [PATCH v11 39/65] drm-dyndbg: DRM_CLASSMAP_USE in amdgpu driver Jim Cromie
2026-03-13 13:20 ` [PATCH v11 40/65] drm-dyndbg: DRM_CLASSMAP_USE in i915 driver Jim Cromie
2026-03-13 13:20 ` [PATCH v11 41/65] drm-dyndbg: DRM_CLASSMAP_USE in drm_crtc_helper Jim Cromie
2026-03-13 13:20 ` [PATCH v11 42/65] drm-dyndbg: DRM_CLASSMAP_USE in drm_dp_helper Jim Cromie
2026-03-13 13:20 ` [PATCH v11 43/65] drm-dyndbg: DRM_CLASSMAP_USE in nouveau Jim Cromie
2026-03-13 13:20 ` [PATCH v11 44/65] drm-dyndbg: add DRM_CLASSMAP_USE to Xe driver Jim Cromie
2026-03-13 13:20 ` [PATCH v11 45/65] drm-dyndbg: add DRM_CLASSMAP_USE to virtio_gpu Jim Cromie
2026-03-13 13:20 ` [PATCH v11 46/65] drm-dyndbg: add DRM_CLASSMAP_USE to simpledrm Jim Cromie
2026-03-13 13:20 ` [PATCH v11 47/65] drm-dyndbg: add DRM_CLASSMAP_USE to bochs Jim Cromie
2026-03-13 13:20 ` [PATCH v11 48/65] drm-dyndbg: add DRM_CLASSMAP_USE to etnaviv Jim Cromie
2026-03-13 13:20 ` [PATCH v11 49/65] drm-dyndbg: add DRM_CLASSMAP_USE to gma500 driver Jim Cromie
2026-03-13 13:20 ` [PATCH v11 50/65] drm-dyndbg: add DRM_CLASSMAP_USE to radeon Jim Cromie
2026-03-13 13:20 ` [PATCH v11 51/65] drm-dyndbg: add DRM_CLASSMAP_USE to vmwgfx driver Jim Cromie
2026-03-13 13:20 ` [PATCH v11 52/65] drm-dyndbg: add DRM_CLASSMAP_USE to vkms driver Jim Cromie
2026-03-13 13:20 ` [PATCH v11 53/65] drm-dyndbg: add DRM_CLASSMAP_USE to udl driver Jim Cromie
2026-03-13 13:20 ` [PATCH v11 54/65] drm-dyndbg: add DRM_CLASSMAP_USE to mgag200 driver Jim Cromie
2026-03-13 13:20 ` [PATCH v11 55/65] drm-dyndbg: add DRM_CLASSMAP_USE to the gud driver Jim Cromie
2026-03-13 13:20 ` [PATCH v11 56/65] drm-dyndbg: add DRM_CLASSMAP_USE to the qxl driver Jim Cromie
2026-03-13 13:20 ` [PATCH v11 57/65] drm-dyndbg: add DRM_CLASSMAP_USE to the drm_gem_shmem_helper driver Jim Cromie
2026-03-13 13:20 ` [PATCH v11 58/65] accel: add -DDYNAMIC_DEBUG_MODULE to subdir-ccflags Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:20 ` [PATCH v11 59/65] accel/ivpu: implement IVPU_DBG_* as a dyndbg classmap Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:20 ` [PATCH v11 60/65] drm: restore CONFIG_DRM_USE_DYNAMIC_DEBUG un-BROKEN Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:20 ` [PATCH v11 61/65] accel/ethosu: enable drm.debug control Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:20 ` [PATCH v11 62/65] accel/rocket: " Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:20 ` [PATCH v11 63/65] drm_buddy: fix 64-bit truncation in power-of-2 rounding Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:20 ` [PATCH v11 64/65] drm_print: fix drm_printer dynamic debug bypass Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 13:20 ` [PATCH v11 65/65] drm_vblank: use dyndbg's static-key to avoid flag-check Jim Cromie
2026-03-13 21:00   ` Claude review: " Claude Code Review Bot
2026-03-13 21:00 ` Claude review: Fix DRM_USE_DYNAMIC_DEBUG=y Claude Code Review Bot
  -- strict thread matches above, loose matches on Subject: below --
2026-03-13 13:09 [PATCH v11 00/65] " Jim Cromie
2026-03-13 13:09 ` [PATCH v11 02/65] dyndbg: factor ddebug_match_desc out from ddebug_change Jim Cromie
2026-03-13 21:02   ` Claude review: " Claude Code Review Bot

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