[PATCH v7 00/25] fix DRM_USE_DYNAMIC_DEBUG=y regression

2023-10-12 Thread Jim Cromie
hi Jason, DRM-folk

This patchest fixes the chicken-egg initialization problem in the 1st
version of ddebug-class-maps, that DRM-CI uncovered.

The root-problem was DECLARE_DYNDBG_CLASSMAP, which broke the K&R rule:
"define once, refer many".  In patch 14 it is replaced by:

 DYNDBG_CLASSMAP_DEFINE - define and export a struct ddebug_class_map
 DYNDBG_CLASSMAP_USE - ref the exported struct

test-dynamic-debug is also extended with a -submod.ko, in order to
recapitulate the drm & drivers initialization scenario.

They're on v6.6-rc5 now, and apply cleanly to drm-tip/drm-tip.

Ive been running recent revs on rc3+, on my desktop and laptop.

The final blocker was a missing __align(8) on the ddebug_class_user
record inserted by DYNDBG_CLASSMAP_USE.  This caused DRM=y (builtin
only) to have a corrupt record for drm_kms_helper (builtin dependent).
Curiously, a clang build did not exhibit this problem.

Heres a part of dmesg, for a DRM=y kernel, booted with
 dynamic_debug.verbose=3 drm.debug=0x10

[0.466747] dyndbg: add-module: drm 406 sites
[0.467569] dyndbg: classes[0]: module:drm base:0 len:10 type:DISJOINT_BITS
[0.467743] dyndbg: module:drm attached 1 classes
[0.468557] dyndbg: builtin class: module:drm base:0 len:10 
type:DISJOINT_BITS
[0.468742] dyndbg:  found kp:drm.debug =0x10
[0.468743] dyndbg:   mapped to: module:drm base:0 len:10 type:DISJOINT_BITS
[0.469742] dyndbg:   drm.debug: classbits: 0x10
[0.470573] dyndbg: apply bitmap: 0x10 to: 0x0 for drm
[0.470743] dyndbg: query 0: "class DRM_UT_ATOMIC +p" mod:drm
[0.471743] dyndbg: split into words: "class" "DRM_UT_ATOMIC" "+p"
[0.472743] dyndbg: op='+' flags=0x1 maskp=0x
[0.473679] dyndbg: parsed: func="" file="" module="drm" format="" 
lineno=0-0 class=DRM_UT_ATOMIC
[0.473749] dyndbg: processed 1 queries, with 0 matches, 0 errs
[0.474742] dyndbg: bit_4: 0 matches on class: DRM_UT_ATOMIC -> 0x10
[0.475742] dyndbg: applied bitmap: 0x10 to: 0x0 for drm
[0.476686] dyndbg: 406 debug prints in module drm
[0.476743] dyndbg: add-module: drm_kms_helper 93 sites
[0.477727] dyndbg: class_ref[0] drm_kms_helper -> drm module:drm base:0 
len:10 type:DISJOINT_BITS
[0.477743] dyndbg: builtin class: module:drm base:0 len:10 
type:DISJOINT_BITS
[0.478742] dyndbg:  found kp:drm.debug =0x10
[0.478743] dyndbg:   mapped to: module:drm base:0 len:10 type:DISJOINT_BITS
[0.479743] dyndbg:   drm.debug: classbits: 0x10
[0.480592] dyndbg: apply bitmap: 0x10 to: 0x0 for drm_kms_helper
[0.480743] dyndbg: query 0: "class DRM_UT_ATOMIC +p" mod:drm_kms_helper
[0.481743] dyndbg: split into words: "class" "DRM_UT_ATOMIC" "+p"
[0.482743] dyndbg: op='+' flags=0x1 maskp=0x
[0.483743] dyndbg: parsed: func="" file="" module="drm_kms_helper" 
format="" lineno=0-0 class=DRM_UT_ATOMIC
[0.484750] dyndbg: class-ref: drm_kms_helper.DRM_UT_ATOMIC  
module:drm_kms_helper nd:93 nc:0 nu:1
[0.485809] dyndbg: processed 1 queries, with 44 matches, 0 errs
[0.486742] dyndbg: bit_4: 44 matches on class: DRM_UT_ATOMIC -> 0x10
[0.487742] dyndbg: applied bitmap: 0x10 to: 0x0 for drm_kms_helper
[0.488743] dyndbg: attach-client-module:  module:drm_kms_helper nd:93 nc:0 
nu:1
[0.489742] dyndbg:  93 debug prints in module drm_kms_helper

Widespread testing is appreciated.
I have scripts if anyone wants them.

I'll forward lkp-robot reports here when I get them.

Jim Cromie (25):
  test-dyndbg: fixup CLASSMAP usage error
  dyndbg: reword "class unknown," to "class:_UNKNOWN_"
  dyndbg: make ddebug_class_param union members same size
  dyndbg: replace classmap list with a vector
  dyndbg: ddebug_apply_class_bitmap - add module arg, select on it
  dyndbg: split param_set_dyndbg_classes to module/wrapper fns
  dyndbg: drop NUM_TYPE_ARRAY
  dyndbg: reduce verbose/debug clutter
  dyndbg: silence debugs with no-change updates
  dyndbg: tighten ddebug_class_name() 1st arg type
  dyndbg: tighten fn-sig of ddebug_apply_class_bitmap
  dyndbg: reduce verbose=3 messages in ddebug_add_module
  dyndbg-API: remove DD_CLASS_TYPE_(DISJOINT|LEVEL)_NAMES and code
  dyndbg-API: fix CONFIG_DRM_USE_DYNAMIC_DEBUG regression
  dyndbg: add for_each_boxed_vector
  dyndbg: refactor ddebug_classparam_clamp_input
  dyndbg-API: promote DYNDBG_CLASSMAP_PARAM to API
  dyndbg-doc: add classmap info to howto
  dyndbg: reserve flag bit _DPRINTK_FLAGS_PREFIX_CACHED
  dyndbg: add _DPRINTK_FLAGS_INCL_LOOKUP
  dyndbg: refactor *dynamic_emit_prefix
  dyndbg: improve err report in attach_user_module_classes
  drm: use correct ccflags-y spelling
  drm-drivers: DRM_CLASSMAP_USE in 2nd batch of drivers, helpers
  drm: restore CONFIG_DRM_USE_DYNAMIC_DEBUG un-BROKEN

 .../adm

[PATCH v7 00/25] fix DRM_USE_DYNAMIC_DEBUG=y regression

2023-10-12 Thread Jim Cromie
hi Jason, DRM-folk

This patchest fixes the chicken-egg initialization problem in the 1st
version of ddebug-class-maps, that DRM-CI uncovered.

The root-problem was DECLARE_DYNDBG_CLASSMAP, which broke the K&R rule:
"define once, refer many".  In patch 14 it is replaced by:

 DYNDBG_CLASSMAP_DEFINE - define and export a struct ddebug_class_map
 DYNDBG_CLASSMAP_USE - ref the exported struct

test-dynamic-debug is also extended with a -submod.ko, in order to
recapitulate the drm & drivers initialization scenario.

They're on v6.6-rc5 now, and apply cleanly to drm-tip/drm-tip.

Ive been running recent revs on rc3+, on my desktop and laptop.

The final blocker was a missing __align(8) on the ddebug_class_user
record inserted by DYNDBG_CLASSMAP_USE.  This caused DRM=y (builtin
only) to have a corrupt record for drm_kms_helper (builtin dependent).
Curiously, a clang build did not exhibit this problem.

Heres a part of dmesg, for a DRM=y kernel, booted with
 dynamic_debug.verbose=3 drm.debug=0x10

[0.466747] dyndbg: add-module: drm 406 sites
[0.467569] dyndbg: classes[0]: module:drm base:0 len:10 type:DISJOINT_BITS
[0.467743] dyndbg: module:drm attached 1 classes
[0.468557] dyndbg: builtin class: module:drm base:0 len:10 
type:DISJOINT_BITS
[0.468742] dyndbg:  found kp:drm.debug =0x10
[0.468743] dyndbg:   mapped to: module:drm base:0 len:10 type:DISJOINT_BITS
[0.469742] dyndbg:   drm.debug: classbits: 0x10
[0.470573] dyndbg: apply bitmap: 0x10 to: 0x0 for drm
[0.470743] dyndbg: query 0: "class DRM_UT_ATOMIC +p" mod:drm
[0.471743] dyndbg: split into words: "class" "DRM_UT_ATOMIC" "+p"
[0.472743] dyndbg: op='+' flags=0x1 maskp=0x
[0.473679] dyndbg: parsed: func="" file="" module="drm" format="" 
lineno=0-0 class=DRM_UT_ATOMIC
[0.473749] dyndbg: processed 1 queries, with 0 matches, 0 errs
[0.474742] dyndbg: bit_4: 0 matches on class: DRM_UT_ATOMIC -> 0x10
[0.475742] dyndbg: applied bitmap: 0x10 to: 0x0 for drm
[0.476686] dyndbg: 406 debug prints in module drm
[0.476743] dyndbg: add-module: drm_kms_helper 93 sites
[0.477727] dyndbg: class_ref[0] drm_kms_helper -> drm module:drm base:0 
len:10 type:DISJOINT_BITS
[0.477743] dyndbg: builtin class: module:drm base:0 len:10 
type:DISJOINT_BITS
[0.478742] dyndbg:  found kp:drm.debug =0x10
[0.478743] dyndbg:   mapped to: module:drm base:0 len:10 type:DISJOINT_BITS
[0.479743] dyndbg:   drm.debug: classbits: 0x10
[0.480592] dyndbg: apply bitmap: 0x10 to: 0x0 for drm_kms_helper
[0.480743] dyndbg: query 0: "class DRM_UT_ATOMIC +p" mod:drm_kms_helper
[0.481743] dyndbg: split into words: "class" "DRM_UT_ATOMIC" "+p"
[0.482743] dyndbg: op='+' flags=0x1 maskp=0x
[0.483743] dyndbg: parsed: func="" file="" module="drm_kms_helper" 
format="" lineno=0-0 class=DRM_UT_ATOMIC
[0.484750] dyndbg: class-ref: drm_kms_helper.DRM_UT_ATOMIC  
module:drm_kms_helper nd:93 nc:0 nu:1
[0.485809] dyndbg: processed 1 queries, with 44 matches, 0 errs
[0.486742] dyndbg: bit_4: 44 matches on class: DRM_UT_ATOMIC -> 0x10
[0.487742] dyndbg: applied bitmap: 0x10 to: 0x0 for drm_kms_helper
[0.488743] dyndbg: attach-client-module:  module:drm_kms_helper nd:93 nc:0 
nu:1
[0.489742] dyndbg:  93 debug prints in module drm_kms_helper

Widespread testing is appreciated.
I have scripts if anyone wants them.

I'll forward lkp-robot reports here when I get them.

Jim Cromie (25):
  test-dyndbg: fixup CLASSMAP usage error
  dyndbg: reword "class unknown," to "class:_UNKNOWN_"
  dyndbg: make ddebug_class_param union members same size
  dyndbg: replace classmap list with a vector
  dyndbg: ddebug_apply_class_bitmap - add module arg, select on it
  dyndbg: split param_set_dyndbg_classes to module/wrapper fns
  dyndbg: drop NUM_TYPE_ARRAY
  dyndbg: reduce verbose/debug clutter
  dyndbg: silence debugs with no-change updates
  dyndbg: tighten ddebug_class_name() 1st arg type
  dyndbg: tighten fn-sig of ddebug_apply_class_bitmap
  dyndbg: reduce verbose=3 messages in ddebug_add_module
  dyndbg-API: remove DD_CLASS_TYPE_(DISJOINT|LEVEL)_NAMES and code
  dyndbg-API: fix CONFIG_DRM_USE_DYNAMIC_DEBUG regression
  dyndbg: add for_each_boxed_vector
  dyndbg: refactor ddebug_classparam_clamp_input
  dyndbg-API: promote DYNDBG_CLASSMAP_PARAM to API
  dyndbg-doc: add classmap info to howto
  dyndbg: reserve flag bit _DPRINTK_FLAGS_PREFIX_CACHED
  dyndbg: add _DPRINTK_FLAGS_INCL_LOOKUP
  dyndbg: refactor *dynamic_emit_prefix
  dyndbg: improve err report in attach_user_module_classes
  drm: use correct ccflags-y spelling
  drm-drivers: DRM_CLASSMAP_USE in 2nd batch of drivers, helpers
  drm: restore CONFIG_DRM_USE_DYNAMIC_DEBUG un-BROKEN

 .../adm

[PATCH v7 02/25] dyndbg: reword "class unknown, " to "class:_UNKNOWN_"

2023-10-12 Thread Jim Cromie
This appears in the control-file to report an unknown class-name, which
indicates that the class_id is not authorized, and dyndbg will ignore
changes to it.  Generally, this means that a DYNDBG_CLASSMAP_DEFINE or
DYNDBG_CLASSMAP_USE is missing.

But the word "unknown" appears in quite a few prdbg formats, so thats
a suboptimal search term to find occurrences of the problem.  Thus
change it to "_UNKNOWN_" which properly shouts the condition.

Signed-off-by: Jim Cromie 
---
 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 6fba6423cc10..ceb3067a5c83 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -1151,7 +1151,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_puts(m, "\n");
 
-- 
2.41.0



[PATCH v7 01/25] test-dyndbg: fixup CLASSMAP usage error

2023-10-12 Thread Jim Cromie
more careful reading of test output reveals:

lib/test_dynamic_debug.c:103 [test_dynamic_debug]do_cats =pmf "doing 
categories\n"
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

That last line is wrong, the HI class is declared.

But the enum's 1st val (explicitly initialized) was wrong; it must be
_base, not _base+1 (a DECLARE_DYNDBG_CLASSMAP[1] param).  So the last
enumeration exceeded the range of mapped class-id's, which triggered
the "class unknown" report.  I intentionally coded in an error, but
forgot to verify its detection and remove it.

RFC:

This patch fixes a bad usage of DECLARE_DYNDBG_CLASSMAP(), showing
that it is too error-prone.  As noted in test-mod comments:

 * 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-62 class_id space !!
 *   (build-bug-on tips welcome)

Those shortcomings could largely be fixed with a __stringify_list
(which doesn't exist,) used in DECLARE_DYNDBG_CLASSMAP to stringify
__VA_ARGS__.  Then, API would accept DRM_UT_* values literally; all
the categories, in order, and not their stringifications, which
created all the usage complications above.

[1] name changes later to DYNDBG_CLASSMAP_DEFINE

Signed-off-by: Jim Cromie 
---
 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 8dd250ad022b..a01f0193a419 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.41.0



[PATCH v7 04/25] dyndbg: replace classmap list with a vector

2023-10-12 Thread Jim Cromie
Classmaps are stored/linked in a section/array, but are each added to
the module's ddebug_table.maps list-head.

This is unnecessary; even when ddebug_attach_classmap() is handling
the builtin section (with classmaps for multiple builtin modules), its
contents are ordered, so a module's possibly multiple classmaps will
be consecutive in the section, and could be treated as a vector/block,
since both start-addy and subrange length are in the ddebug_info arg.

So this changes:

struct ddebug_class_map drops list-head link.

struct ddebug_table drops the list-head maps, and gets: classes &
num_classes for the start-addy and num_classes, placed to improve
struct packing.

The loading: in ddebug_attach_module_classes(), replace the
for-the-modname list-add loop, with a forloop that finds the module's
subrange (start,length) of matching classmaps within the possibly
builtin classmaps vector, and saves those to the ddebug_table.

The reading/using: change list-foreach loops in ddebug_class_name() &
ddebug_find_valid_class() to walk the array from start to length.

Also:
Move #define __outvar up, above an added use in a fn-prototype.
Simplify ddebug_attach_module_classes args, ref has both addy,len.

no functional changes

Signed-off-by: Jim Cromie 
---
 include/linux/dynamic_debug.h |  1 -
 lib/dynamic_debug.c   | 61 ++-
 2 files changed, 32 insertions(+), 30 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 5231aaf361c4..b53217e4b711 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -83,7 +83,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 b984ce338921..a3be2e7c8c84 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 {
@@ -147,13 +148,15 @@ static void vpr_info_dq(const struct ddebug_query *query, 
const char *msg)
  query->first_lineno, query->last_lineno, query->class_string);
 }
 
+#define __outvar /* filled by callee */
 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,
+   __outvar 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;
@@ -164,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
@@ -,9 +1113,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];
 
@@ -1197,30 +1200,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

[PATCH v7 03/25] dyndbg: make ddebug_class_param union members same size

2023-10-12 Thread Jim Cromie
struct ddebug_class_param keeps a ref to the state-storage of the
param, make both flavors use the same unsigned long under-type.
ISTM this is simpler and safer.

Signed-off-by: Jim Cromie 
---
 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 4fcbf4d4fd0a..5231aaf361c4 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -124,7 +124,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 ceb3067a5c83..b984ce338921 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -796,7 +796,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.41.0



[PATCH v7 08/25] dyndbg: reduce verbose/debug clutter

2023-10-12 Thread Jim Cromie
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=0x

 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 is like 1st, with result, not procedure.
   2nd is just status, retold in 4th, with more info.

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 14 +++---
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index b67c9b137447..b0e11f6bfaa2 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -266,9 +266,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;
 }
 
@@ -497,7 +494,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--) {
@@ -511,7 +507,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) {
@@ -527,7 +522,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;
 }
@@ -537,7 +532,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);
@@ -555,10 +550,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
-- 
2.41.0



[PATCH v7 06/25] dyndbg: split param_set_dyndbg_classes to module/wrapper fns

2023-10-12 Thread Jim Cromie
rename param_set_dyndbg_classes: add _module_ name & arg, old name is
wrapper to new.  New arg allows caller to specify that only one module
is affected by a prdbgs update.

Outer fn preserves kernel_param interface, passing NULL to inner fn.
This selectivity will be used later to narrow the scope of changes
made.

no functional change.

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 37 ++---
 1 file changed, 22 insertions(+), 15 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index ba41fdeaaf98..b67c9b137447 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -708,18 +708,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 *modnm)
 {
const struct ddebug_class_param *dcp = kp->arg;
const struct ddebug_class_map *map = dcp->map;
@@ -756,8 +747,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, 
NULL);
+   v2pr_info("bits:0x%lx > %s.%s\n", inrep, modnm ?: "*", 
KP_NAME(kp));
+   totct += ddebug_apply_class_bitmap(dcp, &inrep, dcp->bits, 
modnm);
*dcp->bits = inrep;
break;
case DD_CLASS_TYPE_LEVEL_NUM:
@@ -770,7 +761,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, 
NULL);
+   totct += ddebug_apply_class_bitmap(dcp, &new_bits, &old_bits, 
modnm);
*dcp->lvl = inrep;
break;
default:
@@ -779,6 +770,22 @@ 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 - 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)
+{
+   return param_set_dyndbg_module_classes(instr, kp, NULL);
+}
 EXPORT_SYMBOL(param_set_dyndbg_classes);
 
 /**
-- 
2.41.0



[PATCH v7 05/25] dyndbg: ddebug_apply_class_bitmap - add module arg, select on it

2023-10-12 Thread Jim Cromie
Add query_module param to ddebug_apply_class_bitmap().  This allows
its caller to update just one module, or all (as currently).  We'll
use this later to propagate drm.debug to each USEr as they're
modprobed.

No functional change.

Signed-off-by: Jim Cromie 
---

after `modprobe i915`, heres the module dependencies,
though not all on drm.debug.

bash-5.2# lsmod
Module  Size  Used by
i915 3133440  0
drm_buddy  20480  1 i915
ttm90112  1 i915
i2c_algo_bit   16384  1 i915
video  61440  1 i915
wmi32768  1 video
drm_display_helper200704  1 i915
drm_kms_helper208896  2 drm_display_helper,i915
drm   606208  5 
drm_kms_helper,drm_display_helper,drm_buddy,i915,ttm
cec57344  2 drm_display_helper,i915
---
 lib/dynamic_debug.c | 19 ---
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index a3be2e7c8c84..ba41fdeaaf98 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -601,7 +601,8 @@ static int ddebug_exec_queries(char *query, const char 
*modname)
 
 /* apply a new bitmap to the sys-knob's current bit-state */
 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];
@@ -609,7 +610,8 @@ 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);
+   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))
@@ -618,12 +620,15 @@ 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);
}
+   v2pr_info("applied bitmap: 0x%lx to: 0x%lx for %s\n", *new_bits, 
*old_bits,
+ query_modname ?: "");
+
return matches;
 }
 
@@ -679,7 +684,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]);
@@ -689,7 +694,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);
@@ -752,7 +757,7 @@ int param_set_dyndbg_classes(const char *instr, const 
struct kernel_param *kp)
inrep &= CLASSMAP_BITMASK(map->length);
}
v2pr_info("bits:%lx > %s\n", inrep, KP_NAME(kp));
-   totct += ddebug_apply_class_bitmap(dcp, &inrep, dcp->bits);
+   totct += ddebug_apply_class_bitmap(dcp, &inrep, dcp->bits, 
NULL);
*dcp->bits = inrep;
break;
case DD_CLASS_TYPE_LEVEL_NUM:
@@ -765,7 +770,7 @@ int param_set_dyndbg_classes(const char *instr, const 
struct kernel_param *kp)
old_bits = CLASSMAP_BITMASK(*dcp->lvl)

[PATCH v7 10/25] dyndbg: tighten ddebug_class_name() 1st arg type

2023-10-12 Thread Jim Cromie
Change function's 1st arg-type, and deref in the caller.
The fn doesn't need any other fields in the struct.

no functional change.

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index b07aab422604..8158943b350d 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -1117,12 +1117,12 @@ static void *ddebug_proc_next(struct seq_file *m, void 
*p, loff_t *pos)
 #define class_in_range(class_id, map)  \
(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 = dt->classes;
+   int i;
 
-   for (i = 0; i < nc; i++, map++)
+   for (i = 0; i < dt->num_classes; i++, map++)
if (class_in_range(dp->class_id, map))
return map->class_names[dp->class_id - map->base];
 
@@ -1156,7 +1156,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
seq_puts(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
-- 
2.41.0



[PATCH v7 12/25] dyndbg: reduce verbose=3 messages in ddebug_add_module

2023-10-12 Thread Jim Cromie
The fn currently says "add-module", then "skipping" if the module has
no prdbgs.  Just check 1st and return quietly.

no functional change

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 8beb98a831f5..45870a699507 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -1242,11 +1242,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(sizeof(*dt), GFP_KERNEL);
if (dt == NULL) {
-- 
2.41.0



[PATCH v7 09/25] dyndbg: silence debugs with no-change updates

2023-10-12 Thread Jim Cromie
check for actual changes before announcing them, declutter logs.

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index b0e11f6bfaa2..b07aab422604 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -591,7 +591,7 @@ 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,
 const char *query_modname)
@@ -602,8 +602,9 @@ static int ddebug_apply_class_bitmap(const struct 
ddebug_class_param *dcp,
int matches = 0;
int bi, ct;
 
-   v2pr_info("apply bitmap: 0x%lx to: 0x%lx for %s\n", *new_bits, 
*old_bits,
- query_modname ?: "");
+   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))
@@ -618,8 +619,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);
}
-   v2pr_info("applied bitmap: 0x%lx to: 0x%lx for %s\n", *new_bits, 
*old_bits,
- query_modname ?: "");
+   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;
 }
-- 
2.41.0



[PATCH v7 15/25] dyndbg: add for_each_boxed_vector

2023-10-12 Thread Jim Cromie
Add a for_each iterator to walk a counted vector member in a struct
(ie the box), and use it to replace 8 open-coded loops.

Signed-off-by: Jim Cromie 
---
v5- parens-on-box-force-precedence
---
 lib/dynamic_debug.c | 20 +++-
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index be49e104ec76..c11feca70d6f 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -158,6 +158,9 @@ static void vpr_info_dq(const struct ddebug_query *query, 
const char *msg)
  _dt->num_class_users);\
})
 
+#define for_each_boxed_vector(_box, _vec, _len, _ct, _curs)\
+   for (_ct = 0, _curs = (_box)->_vec; _ct < (_box)->_len; _ct++, _curs++)
+
 #define __outvar /* filled by callee */
 static struct ddebug_class_map *ddebug_find_valid_class(struct ddebug_table 
const *dt,
const char 
*class_string,
@@ -167,7 +170,7 @@ static struct ddebug_class_map 
*ddebug_find_valid_class(struct ddebug_table cons
struct ddebug_class_user *cli;
int i, idx;
 
-   for (i = 0, map = dt->classes; i < dt->num_classes; i++, map++) {
+   for_each_boxed_vector(dt, classes, num_classes, i, map) {
idx = match_string(map->class_names, map->length, class_string);
if (idx >= 0) {
*class_id = idx + map->base;
@@ -175,7 +178,7 @@ static struct ddebug_class_map 
*ddebug_find_valid_class(struct ddebug_table cons
return map;
}
}
-   for (i = 0, cli = dt->class_users; i < dt->num_class_users; i++, cli++) 
{
+   for_each_boxed_vector(dt, class_users, num_class_users, i, cli) {
idx = match_string(cli->map->class_names, cli->map->length, 
class_string);
if (idx >= 0) {
*class_id = idx + cli->map->base;
@@ -1058,11 +1061,11 @@ static const char *ddebug_class_name(struct 
ddebug_table *dt, struct _ddebug *dp
struct ddebug_class_user *cli = dt->class_users;
int i;
 
-   for (i = 0; i < dt->num_classes; i++, map++)
+   for_each_boxed_vector(dt, classes, num_classes, i, map)
if (class_in_range(dp->class_id, map))
return map->class_names[dp->class_id - map->base];
 
-   for (i = 0; i < dt->num_class_users; i++, cli++)
+   for_each_boxed_vector(dt, class_users, num_class_users, i, cli)
if (class_in_range(dp->class_id, cli->map))
return cli->map->class_names[dp->class_id - 
cli->map->base];
 
@@ -1216,7 +1219,7 @@ static void ddebug_attach_module_classes(struct 
ddebug_table *dt, struct _ddebug
struct ddebug_class_map *cm;
int i, nc = 0;
 
-   for (i = 0, cm = di->classes; i < di->num_classes; i++, cm++) {
+   for_each_boxed_vector(di, classes, num_classes, i, cm) {
 
if (!strcmp(cm->mod_name, dt->mod_name)) {
vpr_cm_info(cm, "classes[%d]:", i);
@@ -1230,7 +1233,7 @@ static void ddebug_attach_module_classes(struct 
ddebug_table *dt, struct _ddebug
vpr_info("module:%s attached %d classes\n", dt->mod_name, nc);
dt->num_classes = nc;
 
-   for (i = 0, cm = dt->classes; i < dt->num_classes; i++, cm++)
+   for_each_boxed_vector(di, classes, num_classes, i, cm)
ddebug_apply_params(cm, cm->mod_name);
 }
 
@@ -1250,7 +1253,7 @@ static void ddebug_attach_user_module_classes(struct 
ddebug_table *dt,
 * module's refs, save to dt.  For loadables, this is the
 * whole array.
 */
-   for (i = 0, cli = di->class_users; i < di->num_class_users; i++, cli++) 
{
+   for_each_boxed_vector(di, class_users, num_class_users, i, cli) {
 
if (WARN_ON(!cli || !cli->map || !cli->user_mod_name))
continue;
@@ -1268,8 +1271,7 @@ static void ddebug_attach_user_module_classes(struct 
ddebug_table *dt,
 
dt->num_class_users = nc;
 
-   /* now iterate dt */
-   for (i = 0, cli = dt->class_users; i < dt->num_class_users; i++, cli++)
+   for_each_boxed_vector(di, class_users, num_class_users, i, cli)
ddebug_apply_params(cli->map, cli->user_mod_name);
 
vpr_dt_info(dt, "attach-client-module: ");
-- 
2.41.0



[PATCH v7 14/25] dyndbg-API: fix CONFIG_DRM_USE_DYNAMIC_DEBUG regression

2023-10-12 Thread Jim Cromie
ble 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, with the new ifdef _SUBMOD block invoking DYNDBG_CLASSMAP_USE
for the 2 test-interfaces.  I think this is clearer.

These 2 modules are independently configurable, allowing builtin
parent and loadable submod, which recapitulates a troublesome build
combo for drm & drivers.

DEBUG details:

``#define DEBUG`` in src enables all pr_debugs after it, including any
class'd pr_debugs; its not necessarily all-or-nothing, unless its a
one-file-module with DEBUG at the top.

If a CLASSMAP_PARAM is defined on a classmap, its readback value
cannot describe the set of enablements.  The param is basically
write-only; it cannot know if `echo $cmd >control` was done since.

To know the exact pr-debug state with certainty, toggle to both:

   echo 0x3ff > /sys/module/drm/parameters/debug
   echo 0 > /sys/module/drm/parameters/debug

Cc: Daniel Vetter 
Cc: Jani Nikula 
Cc: Tvrtko Ursulin 
Cc: Rob Clark 
Cc: Sean Paul 
Cc: Luis Chamberlain 
Fixes: aad0214f3026 ("dyndbg: add DECLARE_DYNDBG_CLASSMAP macro")
Fixes: f158936b60a7 ("drm: POC drm on dyndbg - use in core, 2 helpers, 3 
drivers.")
Ref: commit bb2ff6c27bc9 ("drm: Disable dynamic debug as broken")

Signed-off-by: Jim Cromie 
---
 MAINTAINERS |   2 +-
 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_print.c |  25 ++--
 drivers/gpu/drm/i915/i915_params.c  |  12 +-
 drivers/gpu/drm/nouveau/nouveau_drm.c   |  12 +-
 include/asm-generic/vmlinux.lds.h   |   1 +
 include/drm/drm_print.h |  10 +-
 include/linux/dynamic_debug.h   |  53 +--
 kernel/module/main.c|   3 +
 lib/Kconfig.debug   |  22 ++-
 lib/Makefile|   3 +
 lib/dynamic_debug.c | 183 +---
 lib/test_dynamic_debug.c| 127 ++--
 lib/test_dynamic_debug_submod.c |  10 ++
 16 files changed, 346 insertions(+), 153 deletions(-)
 create mode 100644 lib/test_dynamic_debug_submod.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 6c4cce45a09d..aa09ac8dbb39 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7302,7 +7302,7 @@ M:Jim Cromie 
 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
 
 DYNAMIC INTERRUPT MODERATION
 M: Tal Gilboa 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 81edf66dbea8..efba99c9393e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -197,17 +197,7 @@ int amdgpu_user_partt_mode = 
AMDGPU_AUTO_COMPUTE_PARTITION_MODE;
 
 static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work);
 
-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),
diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
b/drivers/gpu/drm/display/drm_dp_helper.c
index e6a78fd32380..d97de1a27939 100644
--- a/drivers/gpu/drm/display/drm_dp_helper.c
+++ b/drivers/gpu/drm/display/drm_dp_helper.c
@@ -41,17 +41,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",
-   "DR

[PATCH v7 13/25] dyndbg-API: remove DD_CLASS_TYPE_(DISJOINT|LEVEL)_NAMES and code

2023-10-12 Thread Jim Cromie
Remove the NAMED class types; 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 simplify things for now.

Signed-off-by: Jim Cromie 
---
 include/linux/dynamic_debug.h |  19 ++-
 lib/dynamic_debug.c   | 103 +++---
 lib/test_dynamic_debug.c  |  12 
 3 files changed, 12 insertions(+), 122 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 8116d0a0d33a..8eaf8eabdc8d 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -61,24 +61,13 @@ struct _ddebug {
 enum 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
 */
 };
 
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 45870a699507..91c8b67fd8f8 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -632,77 +632,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(instr, GFP_KERNEL);
-   p = strchr(cl_str, '\n');
-   if (p)
-   *p = '\0';
-
-   /* 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);
- 

[PATCH v7 16/25] dyndbg: refactor ddebug_classparam_clamp_input

2023-10-12 Thread Jim Cromie
Extract input validation code, from param_set_dyndbg_module_classes()
(the sys-node >handler) to new: ddebug_classparam_clamp_input(kp),
call it from former.  It takes kernel-param arg, so it can complain
about "foo: bad input".

Reuse ddparam_clamp_input(kp) in ddebug_sync_classbits(),
to validate inputs from parent's params, just like our own.
To support that reuse, alter ddebug_sync_classbits() and caller to
pass kp instead of kp->arg.

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 70 ++---
 1 file changed, 47 insertions(+), 23 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index c11feca70d6f..17eefb35ac96 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -656,6 +656,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 *modnm)
@@ -674,26 +698,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, modnm ?: "*", 
KP_NAME(kp));
totct += ddebug_apply_class_bitmap(dcp, &inrep, *dcp->bits, 
modnm);
*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));
@@ -1160,16 +1173,27 @@ static const char * const ddebug_classmap_typenames[] = 
{
  ddebug_classmap_typenames[_cm->map_type]);\
})
 
-static void ddebug_sync_classbits(const struct ddebug_class_param *dcp, const 
char *modname)
+static void ddebug_sync_classbits(const struct kernel_param *kp, const char 
*modname)
 {
-   /* 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);
+   struct ddebug_class_param *dcp = kp->arg;
+   unsigned long new_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_TY

[PATCH v7 07/25] dyndbg: drop NUM_TYPE_ARRAY

2023-10-12 Thread Jim Cromie
ARRAY_SIZE works here, since array decl is complete.

no functional change

Signed-off-by: Jim Cromie 
---
 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 b53217e4b711..8116d0a0d33a 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -106,11 +106,9 @@ struct ddebug_class_map {
.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))
 
 /* encapsulate linker provided built-in (or module) dyndbg data */
 struct _ddebug_info {
-- 
2.41.0



[PATCH v7 11/25] dyndbg: tighten fn-sig of ddebug_apply_class_bitmap

2023-10-12 Thread Jim Cromie
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.

Signed-off-by: Jim Cromie 
---
 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 8158943b350d..8beb98a831f5 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -593,7 +593,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
@@ -602,12 +603,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],
@@ -619,9 +620,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;
 }
@@ -678,7 +679,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]);
@@ -688,7 +689,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);
@@ -742,7 +743,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, modnm ?: "*", 
KP_NAME(kp));
-   totct += ddebug_apply_class_bitmap(dcp, &inrep, dcp->bits, 
modnm);
+   totct += ddebug_apply_class_bitmap(dcp, &inrep, *dcp->bits, 
modnm);
*dcp->bits = inrep;
break;
case DD_CLASS_TYPE_LEVEL_NUM:
@@ -755,7 +756,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, 
modnm);
+   totct += ddebug_apply_class_bitmap(dcp, &new_bits, old_bits, 
modnm);
*dcp->lvl = inrep;
break;
default:
-- 
2.41.0



[PATCH v7 19/25] dyndbg: reserve flag bit _DPRINTK_FLAGS_PREFIX_CACHED

2023-10-12 Thread Jim Cromie
Reserve bit 7 to remember that a pr-debug callsite is/was:
- enabled, with +p
- wants a dynamic-prefix, with one+ of module:function:sourcfile
- was previously called
- was thus saved in the cache. NOT YET.

Its unclear whether any cache fetch would be faster than 2-3 field
fetches, but theres another factor; the 3 columns in the __dyndbg
section are highly redundant and compressible, but to get the
compression, we need field accessors, which will rebalance the
tradeoff.

So, for now, its just the bit reservation.

Signed-off-by: Jim Cromie 
---
 include/linux/dynamic_debug.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index f182f95caabb..927cb14f24e0 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -38,6 +38,7 @@ struct _ddebug {
 #define _DPRINTK_FLAGS_INCL_LINENO (1<<3)
 #define _DPRINTK_FLAGS_INCL_TID(1<<4)
 #define _DPRINTK_FLAGS_INCL_SOURCENAME (1<<5)
+#define _DPRINTK_FLAGS_PREFIX_CACHED   (1<<7)
 
 #define _DPRINTK_FLAGS_INCL_ANY\
(_DPRINTK_FLAGS_INCL_MODNAME | _DPRINTK_FLAGS_INCL_FUNCNAME |\
-- 
2.41.0



[PATCH v7 17/25] dyndbg-API: promote DYNDBG_CLASSMAP_PARAM to API

2023-10-12 Thread Jim Cromie
move macro from test-dynamic-debug.c into header, and refine it.

Distinguish the 2 use cases of DYNDBG_CLASSMAP_PARAM*

1.DYNDBG_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.DYNDBG_CLASSMAP_PARAM
new user (test_dynamic_debug) doesn't need to share state,
decls a static long unsigned int to store the bitvec.

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

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

Signed-off-by: Jim Cromie 
---
v5b - parens-on-PARAM
---
 drivers/gpu/drm/drm_print.c |  8 ++---
 include/drm/drm_print.h |  6 ++--
 include/linux/dynamic_debug.h   | 37 -
 lib/test_dynamic_debug.c| 58 +
 lib/test_dynamic_debug_submod.c |  9 -
 5 files changed, 73 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c
index dabcfa0dd279..8f4b609353a5 100644
--- a/drivers/gpu/drm/drm_print.c
+++ b/drivers/gpu/drm/drm_print.c
@@ -69,12 +69,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, ¶m_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 706afc97c79c..94d4f5500030 100644
--- a/include/drm/drm_print.h
+++ b/include/drm/drm_print.h
@@ -322,11 +322,13 @@ enum drm_debug_category {
 };
 
 #ifdef CONFIG_DRM_USE_DYNAMIC_DEBUG
-#define DRM_CLASSMAP_DEFINE(...) DYNDBG_CLASSMAP_DEFINE(__VA_ARGS__)
-#define DRM_CLASSMAP_USE(name)   DYNDBG_CLASSMAP_USE(name)
+#define DRM_CLASSMAP_DEFINE(...)   DYNDBG_CLASSMAP_DEFINE(__VA_ARGS__)
+#define DRM_CLASSMAP_USE(name) DYNDBG_CLASSMAP_USE(name)
+#define DRM_CLASSMAP_PARAM_REF(...)DYNDBG_CLASSMAP_PARAM_REF(__VA_ARGS__)
 #else
 #define DRM_CLASSMAP_DEFINE(...)
 #define DRM_CLASSMAP_USE(name)
+#define DRM_CLASSMAP_PARAM_REF(...)
 #endif
 
 static inline bool drm_debug_enabled_raw(enum drm_debug_category category)
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 1b027be2cdc4..f182f95caabb 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -91,7 +91,7 @@ struct ddebug_class_map {
  * used to validate a "class FOO .." >control command on the module
  */
 #define DYNDBG_CLASSMAP_DEFINE(_var, _maptype, _base, ...) \
-   const char *_var##_classnames[] = { __VA_ARGS__ };  \
+   static const char *_var##_classnames[] = { __VA_ARGS__ };   \
struct ddebug_class_map __aligned(8) __used \
__section("__dyndbg_classes") _var = {  \
.mod = THIS_MODULE, \
@@ -145,6 +145,41 @@ struct ddebug_class_param {
const struct ddebug_class_map *map;
 };
 
+/**
+ * DYNDBG_CLASSMAP_PARAM - wrap a dyndbg-classmap with a controlling sys-param
+ * @_name  sysfs node name
+ * @_var   name of the struct classmap var defining the controlled classes
+ * @_flags flags to be toggled, typically just 'p'
+ *
+ * Creates a sysfs-param to control the classes defined by the
+ * classmap.  Keeps bits in a private/static
+ */
+#define DYNDBG_CLASSMAP_PARAM(_name, _var, _flags) \
+   static unsigned long _name##_bvec;  \
+   __DYNDBG_CLASSMAP_PARAM(_name, _name##_bvec, _var, _flags)
+
+/**
+ * DYNDBG_CLASSMAP_PARAM_REF - wrap a dyndbg-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 struct classmap var defining the controlled classes
+ * @_flags flags to be toggled, typically just 'p'
+ *
+ * Creates a sysfs-param to control the classmap, keeping bitvec in user 
@_bits.
+ * This lets drm use __drm_debug elsewhere too.
+ */
+#define DYNDBG_CLASSMAP_PARAM_REF(_name, _bits, _var, _flags)  \
+   __DYNDBG_CLASSMAP_PARAM(_name, _bits, _var, _flags)
+
+#define __DYNDBG_CLASSMAP_PARAM(_name, _bits, _var, _flags)\
+   static struct ddebug_class_param _name##_##_flags = {   \
+   .bits = &(_bits),   \
+   .flags = #_flags,   \
+   .map = &(_var), \
+   }; 

[PATCH v7 20/25] dyndbg: add _DPRINTK_FLAGS_INCL_LOOKUP

2023-10-12 Thread Jim Cromie
dyndbg's dynamic prefixing (by +tmfsl flags) is needlessly expensive.

When an enabled (with +p) pr_debug is called, _DPRINTK_FLAGS_INCL_ANY
prefix decorations are sprintf'd into stack-mem for every call.

This string (or part of it) could be cached once its 1st generated,
and retreived thereafter, as long as its deleted any time the
callsite's flags are changed afterwards.

So consider the prefix/decoration flags: 'tmfsl', and what should be
in the cache:

-t  thread-id. not part of the "callsite" info, derived from current.
doesnt belong in the cache. it would be wrong.
can be done in outer: dynamic_emit_prefix()

-l  line number
this could be part of the prefix, but would bloat the cache
can also be done in outer: dynamic_emit_prefix()

-mfs  module, function, source-file
we cache these, composed into a sub-string.
they are "lookups", currently to descriptor fields,
could be accessor macros to "compressed" tables.
cache saves more access work.

All enabled together, they compose a prefix string like:

  # outer   -inner--   outer
  "[tid] module:function:sourcfile:line: "

So this patch extracts _DPRINTK_FLAGS_INCL_LOOKUP macro out of
_DPRINTK_FLAGS_INCL_ANY macro, then redefs latter.

Next re-refactor dynamic_emit_prefix inner/outer fns accordingly.

Signed-off-by: Jim Cromie 
---
 include/linux/dynamic_debug.h | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 927cb14f24e0..2237d454bc19 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -40,10 +40,12 @@ struct _ddebug {
 #define _DPRINTK_FLAGS_INCL_SOURCENAME (1<<5)
 #define _DPRINTK_FLAGS_PREFIX_CACHED   (1<<7)
 
-#define _DPRINTK_FLAGS_INCL_ANY\
-   (_DPRINTK_FLAGS_INCL_MODNAME | _DPRINTK_FLAGS_INCL_FUNCNAME |\
-_DPRINTK_FLAGS_INCL_LINENO  | _DPRINTK_FLAGS_INCL_TID |\
+#define _DPRINTK_FLAGS_INCL_LOOKUP \
+   (_DPRINTK_FLAGS_INCL_MODNAME | _DPRINTK_FLAGS_INCL_FUNCNAME |   \
 _DPRINTK_FLAGS_INCL_SOURCENAME)
+#define _DPRINTK_FLAGS_INCL_ANY
\
+   (_DPRINTK_FLAGS_INCL_LINENO | _DPRINTK_FLAGS_INCL_TID | \
+_DPRINTK_FLAGS_INCL_LOOKUP)
 
 #if defined DEBUG
 #define _DPRINTK_FLAGS_DEFAULT _DPRINTK_FLAGS_PRINT
-- 
2.41.0



[PATCH v7 22/25] dyndbg: improve err report in attach_user_module_classes

2023-10-12 Thread Jim Cromie
convert a WARN on 3 conditions, into BUG_ON 2 of them (which don't
happen), and an early return on (!cli->user_mod_name), which *was*
happening, so should be seen going forward.  Maybe this should be a
WARN.

NB: The underlying problem was a missing __align(8) in the
DYNDBG_CLASSMAP_USE, which manifested as a corrupt record with a map
pointer which segv'd.

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 974395bf8a83..3dc512fb1d66 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -1284,9 +1284,11 @@ static void ddebug_attach_user_module_classes(struct 
ddebug_table *dt,
 */
for_each_boxed_vector(di, class_users, num_class_users, i, cli) {
 
-   if (WARN_ON(!cli || !cli->map || !cli->user_mod_name))
-   continue;
-
+   BUG_ON(!cli || !cli->map);
+   if (!cli->user_mod_name) {
+   pr_warn("class_ref[%d] !user-mod-name looking for 
%s\n", i, dt->mod_name);
+   return;
+   }
if (!strcmp(cli->user_mod_name, dt->mod_name)) {
 
vpr_cm_info(cli->map, "class_ref[%d] %s -> %s", i,
-- 
2.41.0



[PATCH v7 18/25] dyndbg-doc: add classmap info to howto

2023-10-12 Thread Jim Cromie
Add some basic info on classmap usage and api

Signed-off-by: Jim Cromie 
---
v5- adjustments per Randy Dunlap, me
---
 .../admin-guide/dynamic-debug-howto.rst   | 59 ++-
 1 file changed, 58 insertions(+), 1 deletion(-)

diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst 
b/Documentation/admin-guide/dynamic-debug-howto.rst
index 0b3d39c610d9..d8813dcc394a 100644
--- a/Documentation/admin-guide/dynamic-debug-howto.rst
+++ b/Documentation/admin-guide/dynamic-debug-howto.rst
@@ -225,7 +225,6 @@ the ``p`` flag has meaning, other flags are ignored.
 Note the regexp ``^[-+=][fslmpt_]+$`` matches a flags specification.
 To clear all flags at once, use ``=_`` or ``-fslmpt``.
 
-
 Debug messages during Boot Process
 ==
 
@@ -375,3 +374,61 @@ 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.
+
+Dynamic Debug classmaps
+===
+
+Dyndbg allows selection/grouping of *prdbg* callsites using structural
+info: module, file, function, line.  Classmaps allow authors to add
+their own domain-oriented groupings using class-names.  Classmaps are
+exported, so they referencable from other modules.
+
+  # enable classes individually
+  :#> ddcmd class DRM_UT_CORE +p
+  :#> ddcmd class DRM_UT_KMS +p
+  # or more selectively
+  :#> ddcmd class DRM_UT_CORE module drm +p
+
+The "class FOO" syntax protects class'd prdbgs from generic overwrite::
+
+  # IOW this doesn't wipe any DRM.debug settings
+  :#> ddcmd -p
+
+To support the DRM.debug parameter, DYNDBG_CLASSMAP_PARAM* updates all
+classes in a classmap, mapping param-bits 0..N onto the classes:
+DRM_UT_<*> for the DRM use-case.
+
+Dynamic Debug Classmap API
+==
+
+DYNDBG_CLASSMAP_DEFINE - modules use this to create classmaps, naming
+each of the classes (stringified enum-symbols: "DRM_UT_<*>"), and
+type, and mapping the class-names to consecutive _class_ids.
+
+By doing so, modules tell dyndbg that they are have prdbgs with those
+class_ids, and they authorize dyndbg to accept "class FOO" for module
+defining that classname.
+
+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)
+
+DYNDBG_CLASSMAP_PARAM - refers to a DEFINEd classmap, exposing the set
+of defined classes to manipulation as a group.  This interface
+enforces the relatedness of classes of DD_CLASS_TYPE_LEVEL_NUM typed
+classmaps; all classes are independent in the >control parser itself.
+
+DYNDBG_CLASSMAP_USE - drm drivers invoke this to ref the the CLASSMAP
+that drm DEFINEs.  This shares the classmap definition, and authorizes
+dyndbg to apply changes to the using modules class'd pr_debugs.  It
+also tells dyndbg how to initialize the user's prdbgs at modprobe.
+
+Modules or module-groups (drm & drivers) can define multiple
+classmaps, as long as they share the limited 0..62 per-module-group
+_class_id range, without overlap.
+
+``#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 pr_debug callsites can be toggled into agreement with the
+param.
-- 
2.41.0



[PATCH v7 23/25] drm: use correct ccflags-y spelling

2023-10-12 Thread Jim Cromie
Incorrectly spelled CFLAGS- failed to add -DDYNAMIC_DEBUG_MODULE,
which broke builds with:

CONFIG_DRM_USE_DYNAMIC_DEBUG=y
CONFIG_DYNAMIC_DEBUG_CORE=y
CONFIG_DYNAMIC_DEBUG=n

Also add subdir-ccflags so that all drivers pick up the addition.

Fixes: 84ec67288c10 ("drm_print: wrap drm_*_dbg in dyndbg descriptor factory 
macro")
Signed-off-by: Jim Cromie 
---
 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 215e78e79125..22b1984cc982 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
 
 drm-y := \
drm_aperture.o \
-- 
2.41.0



[PATCH v7 21/25] dyndbg: refactor *dynamic_emit_prefix

2023-10-12 Thread Jim Cromie
Refactor the split of duties between outer & inner fns.

The outer fn was previously just an inline unlikely forward to inner,
which did all the work.

Now, outer handles +t and +l flags itself, and calls inner only when
_DPRINTK_FLAGS_INCL_LOOKUP is needed.

No functional change.

But it does make the results of the inner-fn more cache-friendly
(fewer entries, reused more often):

1- no spurious [TID] or  noise
2- no LINE-number to bloat the cache (avg 9 pr_debugs/fn)
3- only LOOKUP stuff

Currently LOOKUPs are descriptor-field refs but could be replaced by
accessor functions.  This would allow the __dyndbg_sites section to be
de-duplicated and reclaimed; currently module, filename fields are
~90% repeated.  As the accessors get more expensive, the value of
caching part of the prefix goes up.

Also change inner-fn to return count of extra chars written to the
buffer, and drop "inline" from outer, let the compiler decide.  Maybe
also change name accordingly.

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 55 -
 1 file changed, 30 insertions(+), 25 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 17eefb35ac96..974395bf8a83 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -777,19 +777,8 @@ static int remaining(int wrote)
return 0;
 }
 
-static char *__dynamic_emit_prefix(const struct _ddebug *desc, char *buf)
+static int __dynamic_emit_prefix(const struct _ddebug *desc, char *buf, int 
pos)
 {
-   int pos_after_tid;
-   int pos = 0;
-
-   if (desc->flags & _DPRINTK_FLAGS_INCL_TID) {
-   if (in_interrupt())
-   pos += snprintf(buf + pos, remaining(pos), " ");
-   else
-   pos += snprintf(buf + pos, remaining(pos), "[%d] ",
-   task_pid_vnr(current));
-   }
-   pos_after_tid = pos;
if (desc->flags & _DPRINTK_FLAGS_INCL_MODNAME)
pos += snprintf(buf + pos, remaining(pos), "%s:",
desc->modname);
@@ -799,22 +788,38 @@ static char *__dynamic_emit_prefix(const struct _ddebug 
*desc, char *buf)
if (desc->flags & _DPRINTK_FLAGS_INCL_SOURCENAME)
pos += snprintf(buf + pos, remaining(pos), "%s:",
trim_prefix(desc->filename));
-   if (desc->flags & _DPRINTK_FLAGS_INCL_LINENO)
-   pos += snprintf(buf + pos, remaining(pos), "%d:",
-   desc->lineno);
-   if (pos - pos_after_tid)
-   pos += snprintf(buf + pos, remaining(pos), " ");
-   if (pos >= PREFIX_SIZE)
-   buf[PREFIX_SIZE - 1] = '\0';
-
-   return buf;
+   return pos;
 }
 
-static inline char *dynamic_emit_prefix(struct _ddebug *desc, char *buf)
+static char *dynamic_emit_prefix(struct _ddebug *desc, char *buf)
 {
-   if (unlikely(desc->flags & _DPRINTK_FLAGS_INCL_ANY))
-   return __dynamic_emit_prefix(desc, buf);
-   return buf;
+int pos_after_tid;
+int pos = 0;
+
+if (likely(!(desc->flags & _DPRINTK_FLAGS_INCL_ANY)))
+return buf;
+
+if (desc->flags & _DPRINTK_FLAGS_INCL_TID) {
+if (in_interrupt())
+pos += snprintf(buf + pos, remaining(pos), " ");
+else
+pos += snprintf(buf + pos, remaining(pos), "[%d] ",
+task_pid_vnr(current));
+}
+pos_after_tid = pos;
+
+if (unlikely(desc->flags & _DPRINTK_FLAGS_INCL_LOOKUP))
+pos += __dynamic_emit_prefix(desc, buf, pos);
+
+if (desc->flags & _DPRINTK_FLAGS_INCL_LINENO)
+pos += snprintf(buf + pos, remaining(pos), "%d:",
+desc->lineno);
+if (pos - pos_after_tid)
+pos += snprintf(buf + pos, remaining(pos), " ");
+if (pos >= PREFIX_SIZE)
+buf[PREFIX_SIZE - 1] = '\0';
+
+return buf;
 }
 
 void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...)
-- 
2.41.0



[PATCH v7 25/25] drm: restore CONFIG_DRM_USE_DYNAMIC_DEBUG un-BROKEN

2023-10-12 Thread Jim Cromie
Lots of burn-in testing needed before signing, upstreaming.

NOTE: I set default Y to maximize testing by default.
Is there a better way to do this ?

Signed-off-by: Jim Cromie 
---
 drivers/gpu/drm/Kconfig | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 3caa020391c7..708f5e8cb205 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -55,8 +55,7 @@ config DRM_DEBUG_MM
 
 config DRM_USE_DYNAMIC_DEBUG
bool "use dynamic debug to implement drm.debug"
-   default n
-   depends on BROKEN
+   default y
depends on DRM
depends on DYNAMIC_DEBUG || DYNAMIC_DEBUG_CORE
depends on JUMP_LABEL
-- 
2.41.0



[PATCH v7 24/25] drm-drivers: DRM_CLASSMAP_USE in 2nd batch of drivers, helpers

2023-10-12 Thread Jim Cromie
Add a DRM_CLASSMAP_USE declaration to 2nd batch of helpers and *_drv.c
files.  For drivers, add the decl just above the module's PARAMs,
since it identifies the "inherited" drm.debug param.

Note: with CONFIG_DRM_USE_DYNAMIC_DEBUG=y, a module not also declaring
DRM_CLASSMAP_USE will have its class'd prdbgs stuck in the initial
(disabled, but for DEBUG) state.

The stuck sites are evident in /proc/dynamic_debug/control as:

   class:_UNKNOWN_ _id:N# control's last column

rather than a proper "enumeration":

   class:DRM_UT_CORE

This set of updates was found by choosing M for all DRM-config items I
found (not allmodconfig), building & modprobing them, and grepping
"class unknown," control.  There may yet be others.

Signed-off-by: Jim Cromie 
---
 drivers/gpu/drm/drm_gem_shmem_helper.c | 2 ++
 drivers/gpu/drm/gud/gud_drv.c  | 2 ++
 drivers/gpu/drm/mgag200/mgag200_drv.c  | 2 ++
 drivers/gpu/drm/qxl/qxl_drv.c  | 2 ++
 drivers/gpu/drm/radeon/radeon_drv.c| 2 ++
 drivers/gpu/drm/udl/udl_main.c | 2 ++
 drivers/gpu/drm/vkms/vkms_drv.c| 2 ++
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c| 2 ++
 8 files changed, 16 insertions(+)

diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c 
b/drivers/gpu/drm/drm_gem_shmem_helper.c
index e435f986cd13..066d906e3199 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -23,6 +23,8 @@
 #include 
 #include 
 
+DRM_CLASSMAP_USE(drm_debug_classes);
+
 MODULE_IMPORT_NS(DMA_BUF);
 
 /**
diff --git a/drivers/gpu/drm/gud/gud_drv.c b/drivers/gpu/drm/gud/gud_drv.c
index 9d7bf8ee45f1..5b555045fce4 100644
--- a/drivers/gpu/drm/gud/gud_drv.c
+++ b/drivers/gpu/drm/gud/gud_drv.c
@@ -31,6 +31,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,
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c 
b/drivers/gpu/drm/mgag200/mgag200_drv.c
index abddf37f0ea1..d678eb8e028d 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.c
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.c
@@ -24,6 +24,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;
diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c
index b30ede1cf62d..91942ffcc2b4 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.c
+++ b/drivers/gpu/drm/qxl/qxl_drv.c
@@ -65,6 +65,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;
 
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c 
b/drivers/gpu/drm/radeon/radeon_drv.c
index fa531493b111..ab29945af657 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -247,6 +247,8 @@ int radeon_cik_support = 1;
 MODULE_PARM_DESC(cik_support, "CIK support (1 = enabled (default), 0 = 
disabled)");
 module_param_named(cik_support, radeon_cik_support, int, 0444);
 
+DRM_CLASSMAP_USE(drm_debug_classes);
+
 static struct pci_device_id pciidlist[] = {
radeon_PCI_IDS
 };
diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c
index 3ebe2ce55dfd..ba57c14454e5 100644
--- a/drivers/gpu/drm/udl/udl_main.c
+++ b/drivers/gpu/drm/udl/udl_main.c
@@ -19,6 +19,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
diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c
index dd0af086e7fa..086797c4b82b 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.c
+++ b/drivers/gpu/drm/vkms/vkms_drv.c
@@ -39,6 +39,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");
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 8b24ecf60e3e..9cb6be422621 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -275,6 +275,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_iom

[PATCH v7b 01/25] test-dyndbg: fixup CLASSMAP usage error

2023-10-13 Thread Jim Cromie
more careful reading of test output reveals:

lib/test_dynamic_debug.c:103 [test_dynamic_debug]do_cats =pmf "doing 
categories\n"
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

That last line is wrong, the HI class is declared.

But the enum's 1st val (explicitly initialized) was wrong; it must be
_base, not _base+1 (a DECLARE_DYNDBG_CLASSMAP[1] param).  So the last
enumeration exceeded the range of mapped class-id's, which triggered
the "class unknown" report.  I intentionally coded in an error, but
forgot to verify its detection and remove it.

RFC:

This patch fixes a bad usage of DECLARE_DYNDBG_CLASSMAP(), showing
that it is too error-prone.  As noted in test-mod comments:

 * 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-62 class_id space !!
 *   (build-bug-on tips welcome)

Those shortcomings could largely be fixed with a __stringify_list
(which doesn't exist,) used in DECLARE_DYNDBG_CLASSMAP to stringify
__VA_ARGS__.  Then, API would accept DRM_UT_* values literally; all
the categories, in order, and not their stringifications, which
created all the usage complications above.

[1] name changes later to DYNDBG_CLASSMAP_DEFINE

Signed-off-by: Jim Cromie 
---
 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 8dd250ad022b..a01f0193a419 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.41.0



[PATCH v7b 00/25] fix DRM_USE_DYNAMIC_DEBUG=y regression

2023-10-13 Thread Jim Cromie
hi Jason, DRM-folk

(now with checkpatch fixes)

This patchest fixes the chicken-egg initialization problem in the 1st
version of ddebug-class-maps, that DRM-CI uncovered.

The root-problem was DECLARE_DYNDBG_CLASSMAP, which broke the K&R rule:
"define once, refer many".  In patch 14 it is replaced by:

 DYNDBG_CLASSMAP_DEFINE - define and export a struct ddebug_class_map
 DYNDBG_CLASSMAP_USE - ref the exported struct

test-dynamic-debug is also extended with a -submod.ko, in order to
recapitulate the drm & drivers initialization scenario.

They're on v6.6-rc5 now, and apply cleanly to drm-tip/drm-tip.

Ive been running recent revs on rc3+, on my desktop and laptop.

The final blocker was a missing __align(8) on the ddebug_class_user
record inserted by DYNDBG_CLASSMAP_USE.  This caused DRM=y (builtin
only) to have a corrupt record for drm_kms_helper (builtin dependent).
Curiously, a clang build did not exhibit this problem.

Heres a part of dmesg, for a DRM=y kernel, booted with
 dynamic_debug.verbose=3 drm.debug=0x10

[0.466747] dyndbg: add-module: drm 406 sites
[0.467569] dyndbg: classes[0]: module:drm base:0 len:10 type:DISJOINT_BITS
[0.467743] dyndbg: module:drm attached 1 classes
[0.468557] dyndbg: builtin class: module:drm base:0 len:10 
type:DISJOINT_BITS
[0.468742] dyndbg:  found kp:drm.debug =0x10
[0.468743] dyndbg:   mapped to: module:drm base:0 len:10 type:DISJOINT_BITS
[0.469742] dyndbg:   drm.debug: classbits: 0x10
[0.470573] dyndbg: apply bitmap: 0x10 to: 0x0 for drm
[0.470743] dyndbg: query 0: "class DRM_UT_ATOMIC +p" mod:drm
[0.471743] dyndbg: split into words: "class" "DRM_UT_ATOMIC" "+p"
[0.472743] dyndbg: op='+' flags=0x1 maskp=0x
[0.473679] dyndbg: parsed: func="" file="" module="drm" format="" 
lineno=0-0 class=DRM_UT_ATOMIC
[0.473749] dyndbg: processed 1 queries, with 0 matches, 0 errs
[0.474742] dyndbg: bit_4: 0 matches on class: DRM_UT_ATOMIC -> 0x10
[0.475742] dyndbg: applied bitmap: 0x10 to: 0x0 for drm
[0.476686] dyndbg: 406 debug prints in module drm
[0.476743] dyndbg: add-module: drm_kms_helper 93 sites
[0.477727] dyndbg: class_ref[0] drm_kms_helper -> drm module:drm base:0 
len:10 type:DISJOINT_BITS
[0.477743] dyndbg: builtin class: module:drm base:0 len:10 
type:DISJOINT_BITS
[0.478742] dyndbg:  found kp:drm.debug =0x10
[0.478743] dyndbg:   mapped to: module:drm base:0 len:10 type:DISJOINT_BITS
[0.479743] dyndbg:   drm.debug: classbits: 0x10
[0.480592] dyndbg: apply bitmap: 0x10 to: 0x0 for drm_kms_helper
[0.480743] dyndbg: query 0: "class DRM_UT_ATOMIC +p" mod:drm_kms_helper
[0.481743] dyndbg: split into words: "class" "DRM_UT_ATOMIC" "+p"
[0.482743] dyndbg: op='+' flags=0x1 maskp=0x
[0.483743] dyndbg: parsed: func="" file="" module="drm_kms_helper" 
format="" lineno=0-0 class=DRM_UT_ATOMIC
[0.484750] dyndbg: class-ref: drm_kms_helper.DRM_UT_ATOMIC  
module:drm_kms_helper nd:93 nc:0 nu:1
[0.485809] dyndbg: processed 1 queries, with 44 matches, 0 errs
[0.486742] dyndbg: bit_4: 44 matches on class: DRM_UT_ATOMIC -> 0x10
[0.487742] dyndbg: applied bitmap: 0x10 to: 0x0 for drm_kms_helper
[0.488743] dyndbg: attach-client-module:  module:drm_kms_helper nd:93 nc:0 
nu:1
[0.489742] dyndbg:  93 debug prints in module drm_kms_helper

Widespread testing is appreciated.
I have scripts if anyone wants them.

I'll forward lkp-robot reports here when I get them.
Patches also at https://github.com/jimc/linux (dd-fix-7b)


Jim Cromie (25):
  test-dyndbg: fixup CLASSMAP usage error
  dyndbg: reword "class unknown," to "class:_UNKNOWN_"
  dyndbg: make ddebug_class_param union members same size
  dyndbg: replace classmap list with a vector
  dyndbg: ddebug_apply_class_bitmap - add module arg, select on it
  dyndbg: split param_set_dyndbg_classes to module/wrapper fns
  dyndbg: drop NUM_TYPE_ARRAY
  dyndbg: reduce verbose/debug clutter
  dyndbg: silence debugs with no-change updates
  dyndbg: tighten ddebug_class_name() 1st arg type
  dyndbg: tighten fn-sig of ddebug_apply_class_bitmap
  dyndbg: reduce verbose=3 messages in ddebug_add_module
  dyndbg-API: remove DD_CLASS_TYPE_(DISJOINT|LEVEL)_NAMES and code
  dyndbg-API: fix CONFIG_DRM_USE_DYNAMIC_DEBUG regression
  dyndbg: add for_each_boxed_vector
  dyndbg: refactor ddebug_classparam_clamp_input
  dyndbg-API: promote DYNDBG_CLASSMAP_PARAM to API
  dyndbg-doc: add classmap info to howto
  dyndbg: reserve flag bit _DPRINTK_FLAGS_PREFIX_CACHED
  dyndbg: add _DPRINTK_FLAGS_INCL_LOOKUP
  dyndbg: refactor *dynamic_emit_prefix
  dyndbg: change WARN_ON to WARN_ON_ONCE
  drm: use correct ccflags-y spelling
  drm-drivers: DRM_CLASSMAP_USE in 2nd batch of drivers, helpers

[PATCH v7b 02/25] dyndbg: reword "class unknown, " to "class:_UNKNOWN_"

2023-10-13 Thread Jim Cromie
This appears in the control-file to report an unknown class-name, which
indicates that the class_id is not authorized, and dyndbg will ignore
changes to it.  Generally, this means that a DYNDBG_CLASSMAP_DEFINE or
DYNDBG_CLASSMAP_USE is missing.

But the word "unknown" appears in quite a few prdbg formats, so thats
a suboptimal search term to find occurrences of the problem.  Thus
change it to "_UNKNOWN_" which properly shouts the condition.

Signed-off-by: Jim Cromie 
---
 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 6fba6423cc10..ceb3067a5c83 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -1151,7 +1151,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_puts(m, "\n");
 
-- 
2.41.0



[PATCH v7b 03/25] dyndbg: make ddebug_class_param union members same size

2023-10-13 Thread Jim Cromie
struct ddebug_class_param keeps a ref to the state-storage of the
param, make both flavors use the same unsigned long under-type.
ISTM this is simpler and safer.

Signed-off-by: Jim Cromie 
---
 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 4fcbf4d4fd0a..5231aaf361c4 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -124,7 +124,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 ceb3067a5c83..b984ce338921 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -796,7 +796,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.41.0



[PATCH v7b 04/25] dyndbg: replace classmap list with a vector

2023-10-13 Thread Jim Cromie
Classmaps are stored/linked in a section/array, but are each added to
the module's ddebug_table.maps list-head.

This is unnecessary; even when ddebug_attach_classmap() is handling
the builtin section (with classmaps for multiple builtin modules), its
contents are ordered, so a module's possibly multiple classmaps will
be consecutive in the section, and could be treated as a vector/block,
since both start-addy and subrange length are in the ddebug_info arg.

So this changes:

struct ddebug_class_map drops list-head link.

struct ddebug_table drops the list-head maps, and gets: classes &
num_classes for the start-addy and num_classes, placed to improve
struct packing.

The loading: in ddebug_attach_module_classes(), replace the
for-the-modname list-add loop, with a forloop that finds the module's
subrange (start,length) of matching classmaps within the possibly
builtin classmaps vector, and saves those to the ddebug_table.

The reading/using: change list-foreach loops in ddebug_class_name() &
ddebug_find_valid_class() to walk the array from start to length.

Also:
Move #define __outvar up, above an added use in a fn-prototype.
Simplify ddebug_attach_module_classes args, ref has both addy,len.

no functional changes

Signed-off-by: Jim Cromie 
---
 include/linux/dynamic_debug.h |  1 -
 lib/dynamic_debug.c   | 61 ++-
 2 files changed, 32 insertions(+), 30 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 5231aaf361c4..b53217e4b711 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -83,7 +83,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 b984ce338921..a3be2e7c8c84 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 {
@@ -147,13 +148,15 @@ static void vpr_info_dq(const struct ddebug_query *query, 
const char *msg)
  query->first_lineno, query->last_lineno, query->class_string);
 }
 
+#define __outvar /* filled by callee */
 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,
+   __outvar 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;
@@ -164,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
@@ -,9 +1113,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];
 
@@ -1197,30 +1200,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

[PATCH v7b 07/25] dyndbg: drop NUM_TYPE_ARRAY

2023-10-13 Thread Jim Cromie
ARRAY_SIZE works here, since array decl is complete.

no functional change

Signed-off-by: Jim Cromie 
---
 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 b53217e4b711..8116d0a0d33a 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -106,11 +106,9 @@ struct ddebug_class_map {
.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))
 
 /* encapsulate linker provided built-in (or module) dyndbg data */
 struct _ddebug_info {
-- 
2.41.0



[PATCH v7b 06/25] dyndbg: split param_set_dyndbg_classes to module/wrapper fns

2023-10-13 Thread Jim Cromie
rename param_set_dyndbg_classes: add _module_ name & arg, old name is
wrapper to new.  New arg allows caller to specify that only one module
is affected by a prdbgs update.

Outer fn preserves kernel_param interface, passing NULL to inner fn.
This selectivity will be used later to narrow the scope of changes
made.

no functional change.

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 37 ++---
 1 file changed, 22 insertions(+), 15 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index ba41fdeaaf98..b67c9b137447 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -708,18 +708,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 *modnm)
 {
const struct ddebug_class_param *dcp = kp->arg;
const struct ddebug_class_map *map = dcp->map;
@@ -756,8 +747,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, 
NULL);
+   v2pr_info("bits:0x%lx > %s.%s\n", inrep, modnm ?: "*", 
KP_NAME(kp));
+   totct += ddebug_apply_class_bitmap(dcp, &inrep, dcp->bits, 
modnm);
*dcp->bits = inrep;
break;
case DD_CLASS_TYPE_LEVEL_NUM:
@@ -770,7 +761,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, 
NULL);
+   totct += ddebug_apply_class_bitmap(dcp, &new_bits, &old_bits, 
modnm);
*dcp->lvl = inrep;
break;
default:
@@ -779,6 +770,22 @@ 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 - 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)
+{
+   return param_set_dyndbg_module_classes(instr, kp, NULL);
+}
 EXPORT_SYMBOL(param_set_dyndbg_classes);
 
 /**
-- 
2.41.0



[PATCH v7b 05/25] dyndbg: ddebug_apply_class_bitmap - add module arg, select on it

2023-10-13 Thread Jim Cromie
Add query_module param to ddebug_apply_class_bitmap().  This allows
its caller to update just one module, or all (as currently).  We'll
use this later to propagate drm.debug to each USEr as they're
modprobed.

No functional change.

Signed-off-by: Jim Cromie 
---

after `modprobe i915`, heres the module dependencies,
though not all on drm.debug.

bash-5.2# lsmod
Module  Size  Used by
i915 3133440  0
drm_buddy  20480  1 i915
ttm90112  1 i915
i2c_algo_bit   16384  1 i915
video  61440  1 i915
wmi32768  1 video
drm_display_helper200704  1 i915
drm_kms_helper208896  2 drm_display_helper,i915
drm   606208  5 
drm_kms_helper,drm_display_helper,drm_buddy,i915,ttm
cec57344  2 drm_display_helper,i915
---
 lib/dynamic_debug.c | 19 ---
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index a3be2e7c8c84..ba41fdeaaf98 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -601,7 +601,8 @@ static int ddebug_exec_queries(char *query, const char 
*modname)
 
 /* apply a new bitmap to the sys-knob's current bit-state */
 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];
@@ -609,7 +610,8 @@ 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);
+   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))
@@ -618,12 +620,15 @@ 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);
}
+   v2pr_info("applied bitmap: 0x%lx to: 0x%lx for %s\n", *new_bits, 
*old_bits,
+ query_modname ?: "");
+
return matches;
 }
 
@@ -679,7 +684,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]);
@@ -689,7 +694,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);
@@ -752,7 +757,7 @@ int param_set_dyndbg_classes(const char *instr, const 
struct kernel_param *kp)
inrep &= CLASSMAP_BITMASK(map->length);
}
v2pr_info("bits:%lx > %s\n", inrep, KP_NAME(kp));
-   totct += ddebug_apply_class_bitmap(dcp, &inrep, dcp->bits);
+   totct += ddebug_apply_class_bitmap(dcp, &inrep, dcp->bits, 
NULL);
*dcp->bits = inrep;
break;
case DD_CLASS_TYPE_LEVEL_NUM:
@@ -765,7 +770,7 @@ int param_set_dyndbg_classes(const char *instr, const 
struct kernel_param *kp)
old_bits = CLASSMAP_BITMASK(*dcp->lvl)

[PATCH v7b 08/25] dyndbg: reduce verbose/debug clutter

2023-10-13 Thread Jim Cromie
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=0x

 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 is like 1st, with result, not procedure.
   2nd is just status, retold in 4th, with more info.

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 14 +++---
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index b67c9b137447..b0e11f6bfaa2 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -266,9 +266,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;
 }
 
@@ -497,7 +494,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--) {
@@ -511,7 +507,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) {
@@ -527,7 +522,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;
 }
@@ -537,7 +532,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);
@@ -555,10 +550,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
-- 
2.41.0



[PATCH v7b 09/25] dyndbg: silence debugs with no-change updates

2023-10-13 Thread Jim Cromie
check for actual changes before announcing them, declutter logs.

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index b0e11f6bfaa2..b07aab422604 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -591,7 +591,7 @@ 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,
 const char *query_modname)
@@ -602,8 +602,9 @@ static int ddebug_apply_class_bitmap(const struct 
ddebug_class_param *dcp,
int matches = 0;
int bi, ct;
 
-   v2pr_info("apply bitmap: 0x%lx to: 0x%lx for %s\n", *new_bits, 
*old_bits,
- query_modname ?: "");
+   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))
@@ -618,8 +619,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);
}
-   v2pr_info("applied bitmap: 0x%lx to: 0x%lx for %s\n", *new_bits, 
*old_bits,
- query_modname ?: "");
+   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;
 }
-- 
2.41.0



[PATCH v7b 11/25] dyndbg: tighten fn-sig of ddebug_apply_class_bitmap

2023-10-13 Thread Jim Cromie
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.

Signed-off-by: Jim Cromie 
---
 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 8158943b350d..8beb98a831f5 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -593,7 +593,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
@@ -602,12 +603,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],
@@ -619,9 +620,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;
 }
@@ -678,7 +679,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]);
@@ -688,7 +689,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);
@@ -742,7 +743,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, modnm ?: "*", 
KP_NAME(kp));
-   totct += ddebug_apply_class_bitmap(dcp, &inrep, dcp->bits, 
modnm);
+   totct += ddebug_apply_class_bitmap(dcp, &inrep, *dcp->bits, 
modnm);
*dcp->bits = inrep;
break;
case DD_CLASS_TYPE_LEVEL_NUM:
@@ -755,7 +756,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, 
modnm);
+   totct += ddebug_apply_class_bitmap(dcp, &new_bits, old_bits, 
modnm);
*dcp->lvl = inrep;
break;
default:
-- 
2.41.0



[PATCH v7b 12/25] dyndbg: reduce verbose=3 messages in ddebug_add_module

2023-10-13 Thread Jim Cromie
The fn currently says "add-module", then "skipping" if the module has
no prdbgs.  Just check 1st and return quietly.

no functional change

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 8beb98a831f5..45870a699507 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -1242,11 +1242,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(sizeof(*dt), GFP_KERNEL);
if (dt == NULL) {
-- 
2.41.0



[PATCH v7b 10/25] dyndbg: tighten ddebug_class_name() 1st arg type

2023-10-13 Thread Jim Cromie
Change function's 1st arg-type, and deref in the caller.
The fn doesn't need any other fields in the struct.

no functional change.

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index b07aab422604..8158943b350d 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -1117,12 +1117,12 @@ static void *ddebug_proc_next(struct seq_file *m, void 
*p, loff_t *pos)
 #define class_in_range(class_id, map)  \
(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 = dt->classes;
+   int i;
 
-   for (i = 0; i < nc; i++, map++)
+   for (i = 0; i < dt->num_classes; i++, map++)
if (class_in_range(dp->class_id, map))
return map->class_names[dp->class_id - map->base];
 
@@ -1156,7 +1156,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
seq_puts(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
-- 
2.41.0



[PATCH v7b 14/25] dyndbg-API: fix CONFIG_DRM_USE_DYNAMIC_DEBUG regression

2023-10-13 Thread Jim Cromie
ble 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, with the new ifdef _SUBMOD block invoking DYNDBG_CLASSMAP_USE
for the 2 test-interfaces.  I think this is clearer.

These 2 modules are independently configurable, allowing builtin
parent and loadable submod, which recapitulates a troublesome build
combo for drm & drivers.

DEBUG details:

``#define DEBUG`` in src enables all pr_debugs after it, including any
class'd pr_debugs; its not necessarily all-or-nothing, unless its a
one-file-module with DEBUG at the top.

If a CLASSMAP_PARAM is defined on a classmap, its readback value
cannot describe the set of enablements.  The param is basically
write-only; it cannot know if `echo $cmd >control` was done since.

To know the exact pr-debug state with certainty, toggle to both:

   echo 0x3ff > /sys/module/drm/parameters/debug
   echo 0 > /sys/module/drm/parameters/debug

Cc: Daniel Vetter 
Cc: Jani Nikula 
Cc: Tvrtko Ursulin 
Cc: Rob Clark 
Cc: Sean Paul 
Cc: Luis Chamberlain 
Fixes: aad0214f3026 ("dyndbg: add DECLARE_DYNDBG_CLASSMAP macro")
Fixes: f158936b60a7 ("drm: POC drm on dyndbg - use in core, 2 helpers, 3 
drivers.")
Ref: commit bb2ff6c27bc9 ("drm: Disable dynamic debug as broken")

Signed-off-by: Jim Cromie 
---

fixup-kconfig description too short
---
 MAINTAINERS |   2 +-
 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_print.c |  25 ++--
 drivers/gpu/drm/i915/i915_params.c  |  12 +-
 drivers/gpu/drm/nouveau/nouveau_drm.c   |  12 +-
 include/asm-generic/vmlinux.lds.h   |   1 +
 include/drm/drm_print.h |  10 +-
 include/linux/dynamic_debug.h   |  53 +--
 kernel/module/main.c|   3 +
 lib/Kconfig.debug   |  24 +++-
 lib/Makefile|   3 +
 lib/dynamic_debug.c | 183 +---
 lib/test_dynamic_debug.c| 127 ++--
 lib/test_dynamic_debug_submod.c |  10 ++
 16 files changed, 348 insertions(+), 153 deletions(-)
 create mode 100644 lib/test_dynamic_debug_submod.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 6c4cce45a09d..aa09ac8dbb39 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7302,7 +7302,7 @@ M:Jim Cromie 
 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
 
 DYNAMIC INTERRUPT MODERATION
 M: Tal Gilboa 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 81edf66dbea8..efba99c9393e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -197,17 +197,7 @@ int amdgpu_user_partt_mode = 
AMDGPU_AUTO_COMPUTE_PARTITION_MODE;
 
 static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work);
 
-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),
diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
b/drivers/gpu/drm/display/drm_dp_helper.c
index e6a78fd32380..d97de1a27939 100644
--- a/drivers/gpu/drm/display/drm_dp_helper.c
+++ b/drivers/gpu/drm/display/drm_dp_helper.c
@@ -41,17 +41,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

[PATCH v7b 13/25] dyndbg-API: remove DD_CLASS_TYPE_(DISJOINT|LEVEL)_NAMES and code

2023-10-13 Thread Jim Cromie
Remove the NAMED class types; 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 simplify things for now.

Signed-off-by: Jim Cromie 
---
 include/linux/dynamic_debug.h |  19 ++-
 lib/dynamic_debug.c   | 103 +++---
 lib/test_dynamic_debug.c  |  12 
 3 files changed, 12 insertions(+), 122 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 8116d0a0d33a..8eaf8eabdc8d 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -61,24 +61,13 @@ struct _ddebug {
 enum 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
 */
 };
 
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 45870a699507..91c8b67fd8f8 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -632,77 +632,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(instr, GFP_KERNEL);
-   p = strchr(cl_str, '\n');
-   if (p)
-   *p = '\0';
-
-   /* 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);
- 

[PATCH v7b 15/25] dyndbg: add for_each_boxed_vector

2023-10-13 Thread Jim Cromie
Add a for_each iterator to walk a counted vector member in a struct
(ie the box), and use it to replace 8 open-coded loops.

Signed-off-by: Jim Cromie 
---
v5- parens-on-box-force-precedence
---
 lib/dynamic_debug.c | 20 +++-
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index be49e104ec76..c11feca70d6f 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -158,6 +158,9 @@ static void vpr_info_dq(const struct ddebug_query *query, 
const char *msg)
  _dt->num_class_users);\
})
 
+#define for_each_boxed_vector(_box, _vec, _len, _ct, _curs)\
+   for (_ct = 0, _curs = (_box)->_vec; _ct < (_box)->_len; _ct++, _curs++)
+
 #define __outvar /* filled by callee */
 static struct ddebug_class_map *ddebug_find_valid_class(struct ddebug_table 
const *dt,
const char 
*class_string,
@@ -167,7 +170,7 @@ static struct ddebug_class_map 
*ddebug_find_valid_class(struct ddebug_table cons
struct ddebug_class_user *cli;
int i, idx;
 
-   for (i = 0, map = dt->classes; i < dt->num_classes; i++, map++) {
+   for_each_boxed_vector(dt, classes, num_classes, i, map) {
idx = match_string(map->class_names, map->length, class_string);
if (idx >= 0) {
*class_id = idx + map->base;
@@ -175,7 +178,7 @@ static struct ddebug_class_map 
*ddebug_find_valid_class(struct ddebug_table cons
return map;
}
}
-   for (i = 0, cli = dt->class_users; i < dt->num_class_users; i++, cli++) 
{
+   for_each_boxed_vector(dt, class_users, num_class_users, i, cli) {
idx = match_string(cli->map->class_names, cli->map->length, 
class_string);
if (idx >= 0) {
*class_id = idx + cli->map->base;
@@ -1058,11 +1061,11 @@ static const char *ddebug_class_name(struct 
ddebug_table *dt, struct _ddebug *dp
struct ddebug_class_user *cli = dt->class_users;
int i;
 
-   for (i = 0; i < dt->num_classes; i++, map++)
+   for_each_boxed_vector(dt, classes, num_classes, i, map)
if (class_in_range(dp->class_id, map))
return map->class_names[dp->class_id - map->base];
 
-   for (i = 0; i < dt->num_class_users; i++, cli++)
+   for_each_boxed_vector(dt, class_users, num_class_users, i, cli)
if (class_in_range(dp->class_id, cli->map))
return cli->map->class_names[dp->class_id - 
cli->map->base];
 
@@ -1216,7 +1219,7 @@ static void ddebug_attach_module_classes(struct 
ddebug_table *dt, struct _ddebug
struct ddebug_class_map *cm;
int i, nc = 0;
 
-   for (i = 0, cm = di->classes; i < di->num_classes; i++, cm++) {
+   for_each_boxed_vector(di, classes, num_classes, i, cm) {
 
if (!strcmp(cm->mod_name, dt->mod_name)) {
vpr_cm_info(cm, "classes[%d]:", i);
@@ -1230,7 +1233,7 @@ static void ddebug_attach_module_classes(struct 
ddebug_table *dt, struct _ddebug
vpr_info("module:%s attached %d classes\n", dt->mod_name, nc);
dt->num_classes = nc;
 
-   for (i = 0, cm = dt->classes; i < dt->num_classes; i++, cm++)
+   for_each_boxed_vector(di, classes, num_classes, i, cm)
ddebug_apply_params(cm, cm->mod_name);
 }
 
@@ -1250,7 +1253,7 @@ static void ddebug_attach_user_module_classes(struct 
ddebug_table *dt,
 * module's refs, save to dt.  For loadables, this is the
 * whole array.
 */
-   for (i = 0, cli = di->class_users; i < di->num_class_users; i++, cli++) 
{
+   for_each_boxed_vector(di, class_users, num_class_users, i, cli) {
 
if (WARN_ON(!cli || !cli->map || !cli->user_mod_name))
continue;
@@ -1268,8 +1271,7 @@ static void ddebug_attach_user_module_classes(struct 
ddebug_table *dt,
 
dt->num_class_users = nc;
 
-   /* now iterate dt */
-   for (i = 0, cli = dt->class_users; i < dt->num_class_users; i++, cli++)
+   for_each_boxed_vector(di, class_users, num_class_users, i, cli)
ddebug_apply_params(cli->map, cli->user_mod_name);
 
vpr_dt_info(dt, "attach-client-module: ");
-- 
2.41.0



[PATCH v7b 18/25] dyndbg-doc: add classmap info to howto

2023-10-13 Thread Jim Cromie
Add some basic info on classmap usage and api

cc: linux-...@vger.kernel.org
Signed-off-by: Jim Cromie 
---
v5- adjustments per Randy Dunlap, me
v7b- checkpatch fixes
---
 .../admin-guide/dynamic-debug-howto.rst   | 60 ++-
 1 file changed, 59 insertions(+), 1 deletion(-)

diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst 
b/Documentation/admin-guide/dynamic-debug-howto.rst
index 0b3d39c610d9..028c2cb5b4c5 100644
--- a/Documentation/admin-guide/dynamic-debug-howto.rst
+++ b/Documentation/admin-guide/dynamic-debug-howto.rst
@@ -225,7 +225,6 @@ the ``p`` flag has meaning, other flags are ignored.
 Note the regexp ``^[-+=][fslmpt_]+$`` matches a flags specification.
 To clear all flags at once, use ``=_`` or ``-fslmpt``.
 
-
 Debug messages during Boot Process
 ==
 
@@ -375,3 +374,62 @@ 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.
+
+Dynamic Debug classmaps
+===
+
+Dyndbg allows selection/grouping of *prdbg* callsites using structural
+info: module, file, function, line.  Classmaps allow authors to add
+their own domain-oriented groupings using class-names.  Classmaps are
+exported, so they referencable from other modules.
+
+  # enable classes individually
+  :#> ddcmd class DRM_UT_CORE +p
+  :#> ddcmd class DRM_UT_KMS +p
+  # or more selectively
+  :#> ddcmd class DRM_UT_CORE module drm +p
+
+The "class FOO" syntax protects class'd prdbgs from generic overwrite::
+
+  # IOW this doesn't wipe any DRM.debug settings
+  :#> ddcmd -p
+
+To support the DRM.debug parameter, DYNDBG_CLASSMAP_PARAM* updates all
+classes in a classmap, mapping param-bits 0..N onto the classes:
+DRM_UT_<*> for the DRM use-case.
+
+Dynamic Debug Classmap API
+==
+
+DYNDBG_CLASSMAP_DEFINE - modules use this to create classmaps, naming
+each of the classes (stringified enum-symbols: "DRM_UT_<*>"), and
+type, and mapping the class-names to consecutive _class_ids.
+
+By doing so, modules tell dyndbg that they are have prdbgs with those
+class_ids, and they authorize dyndbg to accept "class FOO" for the
+module defining that classname.
+
+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)
+
+DYNDBG_CLASSMAP_PARAM - refers to a DEFINEd classmap, exposing the set
+of defined classes to manipulation as a group.  This interface
+enforces the relatedness of classes of DD_CLASS_TYPE_LEVEL_NUM typed
+classmaps; all classes are independent in the >control parser itself.
+
+DYNDBG_CLASSMAP_USE - drm drivers invoke this to ref the CLASSMAP that
+drm DEFINEs.  This shares the classmap definition, and authorizes
+dyndbg to apply changes to the user module's class'd pr_debugs.  It
+also tells dyndbg how to initialize the user's prdbgs at modprobe,
+based upon the current setting of the parent's controlling param.
+
+Modules or module-groups (drm & drivers) can define multiple
+classmaps, as long as they share the limited 0..62 per-module-group
+_class_id range, without overlap.
+
+``#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 pr_debug callsites can be toggled into agreement with the
+param.
-- 
2.41.0



[PATCH v7b 16/25] dyndbg: refactor ddebug_classparam_clamp_input

2023-10-13 Thread Jim Cromie
Extract input validation code, from param_set_dyndbg_module_classes()
(the sys-node >handler) to new: ddebug_classparam_clamp_input(kp),
call it from former.  It takes kernel-param arg, so it can complain
about "foo: bad input".

Reuse ddparam_clamp_input(kp) in ddebug_sync_classbits(),
to validate inputs from parent's params, just like our own.
To support that reuse, alter ddebug_sync_classbits() and caller to
pass kp instead of kp->arg.

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 70 ++---
 1 file changed, 47 insertions(+), 23 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index c11feca70d6f..17eefb35ac96 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -656,6 +656,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 *modnm)
@@ -674,26 +698,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, modnm ?: "*", 
KP_NAME(kp));
totct += ddebug_apply_class_bitmap(dcp, &inrep, *dcp->bits, 
modnm);
*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));
@@ -1160,16 +1173,27 @@ static const char * const ddebug_classmap_typenames[] = 
{
  ddebug_classmap_typenames[_cm->map_type]);\
})
 
-static void ddebug_sync_classbits(const struct ddebug_class_param *dcp, const 
char *modname)
+static void ddebug_sync_classbits(const struct kernel_param *kp, const char 
*modname)
 {
-   /* 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);
+   struct ddebug_class_param *dcp = kp->arg;
+   unsigned long new_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_TY

[PATCH v7b 22/25] dyndbg: change WARN_ON to WARN_ON_ONCE

2023-10-13 Thread Jim Cromie
This shouldn't ever happen, and 1st 2 conditions never have.

The 3rd condition did happen, due to corrupt linkage due to a missing
align(8) in DYNDBG_CLASSMAP_USE, on the static struct allocation into
the __dyndbg_class_users section.

Not sure whether changing to _ONCE is appropriate - this is a
module-load activity, so it won't continuously spam syslog.

Signed-off-by: Jim Cromie 
---
undo BUG_ON addition
---
 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 5825b58043a6..2a5eb64dbc27 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -1284,7 +1284,7 @@ static void ddebug_attach_user_module_classes(struct 
ddebug_table *dt,
 */
for_each_boxed_vector(di, class_users, num_class_users, i, cli) {
 
-   if (WARN_ON(!cli || !cli->map || !cli->user_mod_name))
+   if (WARN_ON_ONCE(!cli || !cli->map || !cli->user_mod_name))
continue;
 
if (!strcmp(cli->user_mod_name, dt->mod_name)) {
-- 
2.41.0



[PATCH v7b 19/25] dyndbg: reserve flag bit _DPRINTK_FLAGS_PREFIX_CACHED

2023-10-13 Thread Jim Cromie
Reserve bit 7 to remember that a pr-debug callsite is/was:
- enabled, with +p
- wants a dynamic-prefix, with one+ of module:function:sourcfile
- was previously called
- was thus saved in the cache. NOT YET.

Its unclear whether any cache fetch would be faster than 2-3 field
fetches, but theres another factor; the 3 columns in the __dyndbg
section are highly redundant and compressible, but to get the
compression, we need field accessors, which will rebalance the
tradeoff.

So, for now, its just the bit reservation.

Signed-off-by: Jim Cromie 
---
 include/linux/dynamic_debug.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index f182f95caabb..927cb14f24e0 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -38,6 +38,7 @@ struct _ddebug {
 #define _DPRINTK_FLAGS_INCL_LINENO (1<<3)
 #define _DPRINTK_FLAGS_INCL_TID(1<<4)
 #define _DPRINTK_FLAGS_INCL_SOURCENAME (1<<5)
+#define _DPRINTK_FLAGS_PREFIX_CACHED   (1<<7)
 
 #define _DPRINTK_FLAGS_INCL_ANY\
(_DPRINTK_FLAGS_INCL_MODNAME | _DPRINTK_FLAGS_INCL_FUNCNAME |\
-- 
2.41.0



[PATCH v7b 21/25] dyndbg: refactor *dynamic_emit_prefix

2023-10-13 Thread Jim Cromie
Refactor the split of duties between outer & inner fns.

The outer fn was previously just an inline unlikely forward to inner,
which did all the work.

Now, outer handles +t and +l flags itself, and calls inner only when
_DPRINTK_FLAGS_INCL_LOOKUP is needed.

No functional change.

But it does make the results of the inner-fn more cache-friendly
(fewer entries, reused more often):

1- no spurious [TID] or  noise
2- no LINE-number to bloat the cache (avg 9 pr_debugs/fn)
3- only LOOKUP stuff

Currently LOOKUPs are descriptor-field refs but could be replaced by
accessor functions.  This would allow the __dyndbg_sites section to be
de-duplicated and reclaimed; currently module, filename fields are
~90% repeated.  As the accessors get more expensive, the value of
caching part of the prefix goes up.

Also change inner-fn to return count of extra chars written to the
buffer, and drop "inline" from outer, let the compiler decide.  Maybe
also change name accordingly.

Signed-off-by: Jim Cromie 
---
fixup whitespace
---
 lib/dynamic_debug.c | 39 ++-
 1 file changed, 22 insertions(+), 17 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 17eefb35ac96..5825b58043a6 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -777,11 +777,28 @@ static int remaining(int wrote)
return 0;
 }
 
-static char *__dynamic_emit_prefix(const struct _ddebug *desc, char *buf)
+static int __dynamic_emit_prefix(const struct _ddebug *desc, char *buf, int 
pos)
+{
+   if (desc->flags & _DPRINTK_FLAGS_INCL_MODNAME)
+   pos += snprintf(buf + pos, remaining(pos), "%s:",
+   desc->modname);
+   if (desc->flags & _DPRINTK_FLAGS_INCL_FUNCNAME)
+   pos += snprintf(buf + pos, remaining(pos), "%s:",
+   desc->function);
+   if (desc->flags & _DPRINTK_FLAGS_INCL_SOURCENAME)
+   pos += snprintf(buf + pos, remaining(pos), "%s:",
+   trim_prefix(desc->filename));
+   return pos;
+}
+
+static char *dynamic_emit_prefix(struct _ddebug *desc, char *buf)
 {
int pos_after_tid;
int pos = 0;
 
+   if (likely(!(desc->flags & _DPRINTK_FLAGS_INCL_ANY)))
+   return buf;
+
if (desc->flags & _DPRINTK_FLAGS_INCL_TID) {
if (in_interrupt())
pos += snprintf(buf + pos, remaining(pos), " ");
@@ -790,15 +807,10 @@ static char *__dynamic_emit_prefix(const struct _ddebug 
*desc, char *buf)
task_pid_vnr(current));
}
pos_after_tid = pos;
-   if (desc->flags & _DPRINTK_FLAGS_INCL_MODNAME)
-   pos += snprintf(buf + pos, remaining(pos), "%s:",
-   desc->modname);
-   if (desc->flags & _DPRINTK_FLAGS_INCL_FUNCNAME)
-   pos += snprintf(buf + pos, remaining(pos), "%s:",
-   desc->function);
-   if (desc->flags & _DPRINTK_FLAGS_INCL_SOURCENAME)
-   pos += snprintf(buf + pos, remaining(pos), "%s:",
-   trim_prefix(desc->filename));
+
+   if (unlikely(desc->flags & _DPRINTK_FLAGS_INCL_LOOKUP))
+   pos += __dynamic_emit_prefix(desc, buf, pos);
+
if (desc->flags & _DPRINTK_FLAGS_INCL_LINENO)
pos += snprintf(buf + pos, remaining(pos), "%d:",
desc->lineno);
@@ -810,13 +822,6 @@ static char *__dynamic_emit_prefix(const struct _ddebug 
*desc, char *buf)
return buf;
 }
 
-static inline char *dynamic_emit_prefix(struct _ddebug *desc, char *buf)
-{
-   if (unlikely(desc->flags & _DPRINTK_FLAGS_INCL_ANY))
-   return __dynamic_emit_prefix(desc, buf);
-   return buf;
-}
-
 void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...)
 {
va_list args;
-- 
2.41.0



[PATCH v7b 20/25] dyndbg: add _DPRINTK_FLAGS_INCL_LOOKUP

2023-10-13 Thread Jim Cromie
dyndbg's dynamic prefixing (by +tmfsl flags) is needlessly expensive.

When an enabled (with +p) pr_debug is called, _DPRINTK_FLAGS_INCL_ANY
prefix decorations are sprintf'd into stack-mem for every call.

This string (or part of it) could be cached once its 1st generated,
and retrieved thereafter, as long as its deleted any time the
callsite's flags are changed afterwards.

So consider the prefix/decoration flags: 'tmfsl', and what should be
in the cache:

-t  thread-id. not part of the "callsite" info, derived from current.
doesn't belong in the cache. it would be wrong.
can be done in outer: dynamic_emit_prefix()

-l  line number
this could be part of the prefix, but would bloat the cache
can also be done in outer: dynamic_emit_prefix()

-mfs  module, function, source-file
we cache these, composed into a sub-string.
they are "lookups", currently to descriptor fields,
could be accessor macros to "compressed" tables.
cache saves more access work.

All enabled together, they compose a prefix string like:

  # outer   -inner--   outer
  "[tid] module:function:sourcfile:line: "

So this patch extracts _DPRINTK_FLAGS_INCL_LOOKUP macro out of
_DPRINTK_FLAGS_INCL_ANY macro, then redefs latter.

Next re-refactor dynamic_emit_prefix inner/outer fns accordingly.

Signed-off-by: Jim Cromie 
---
 include/linux/dynamic_debug.h | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 927cb14f24e0..2237d454bc19 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -40,10 +40,12 @@ struct _ddebug {
 #define _DPRINTK_FLAGS_INCL_SOURCENAME (1<<5)
 #define _DPRINTK_FLAGS_PREFIX_CACHED   (1<<7)
 
-#define _DPRINTK_FLAGS_INCL_ANY\
-   (_DPRINTK_FLAGS_INCL_MODNAME | _DPRINTK_FLAGS_INCL_FUNCNAME |\
-_DPRINTK_FLAGS_INCL_LINENO  | _DPRINTK_FLAGS_INCL_TID |\
+#define _DPRINTK_FLAGS_INCL_LOOKUP \
+   (_DPRINTK_FLAGS_INCL_MODNAME | _DPRINTK_FLAGS_INCL_FUNCNAME |   \
 _DPRINTK_FLAGS_INCL_SOURCENAME)
+#define _DPRINTK_FLAGS_INCL_ANY
\
+   (_DPRINTK_FLAGS_INCL_LINENO | _DPRINTK_FLAGS_INCL_TID | \
+_DPRINTK_FLAGS_INCL_LOOKUP)
 
 #if defined DEBUG
 #define _DPRINTK_FLAGS_DEFAULT _DPRINTK_FLAGS_PRINT
-- 
2.41.0



[PATCH v7b 23/25] drm: use correct ccflags-y spelling

2023-10-13 Thread Jim Cromie
Incorrectly spelled CFLAGS- failed to add -DDYNAMIC_DEBUG_MODULE,
which broke builds with:

CONFIG_DRM_USE_DYNAMIC_DEBUG=y
CONFIG_DYNAMIC_DEBUG_CORE=y
CONFIG_DYNAMIC_DEBUG=n

Also add subdir-ccflags so that all drivers pick up the addition.

Fixes: 84ec67288c10 ("drm_print: wrap drm_*_dbg in dyndbg descriptor factory 
macro")
Signed-off-by: Jim Cromie 
---
 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 215e78e79125..22b1984cc982 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
 
 drm-y := \
drm_aperture.o \
-- 
2.41.0



[PATCH v7b 17/25] dyndbg-API: promote DYNDBG_CLASSMAP_PARAM to API

2023-10-13 Thread Jim Cromie
move the DYNDBG_CLASSMAP_PARAM macro from test-dynamic-debug.c into
the header, and refine it, by distinguishing the 2 use cases:

1.DYNDBG_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.DYNDBG_CLASSMAP_PARAM
new user (test_dynamic_debug) doesn't need to share state,
decls a static long unsigned int to store the bitvec.

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

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

Signed-off-by: Jim Cromie 
---
---
 drivers/gpu/drm/drm_print.c |  8 ++---
 include/drm/drm_print.h |  6 ++--
 include/linux/dynamic_debug.h   | 37 +-
 lib/test_dynamic_debug.c| 56 +++--
 lib/test_dynamic_debug_submod.c |  9 +-
 5 files changed, 69 insertions(+), 47 deletions(-)

diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c
index dabcfa0dd279..8f4b609353a5 100644
--- a/drivers/gpu/drm/drm_print.c
+++ b/drivers/gpu/drm/drm_print.c
@@ -69,12 +69,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, ¶m_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 706afc97c79c..94d4f5500030 100644
--- a/include/drm/drm_print.h
+++ b/include/drm/drm_print.h
@@ -322,11 +322,13 @@ enum drm_debug_category {
 };
 
 #ifdef CONFIG_DRM_USE_DYNAMIC_DEBUG
-#define DRM_CLASSMAP_DEFINE(...) DYNDBG_CLASSMAP_DEFINE(__VA_ARGS__)
-#define DRM_CLASSMAP_USE(name)   DYNDBG_CLASSMAP_USE(name)
+#define DRM_CLASSMAP_DEFINE(...)   DYNDBG_CLASSMAP_DEFINE(__VA_ARGS__)
+#define DRM_CLASSMAP_USE(name) DYNDBG_CLASSMAP_USE(name)
+#define DRM_CLASSMAP_PARAM_REF(...)DYNDBG_CLASSMAP_PARAM_REF(__VA_ARGS__)
 #else
 #define DRM_CLASSMAP_DEFINE(...)
 #define DRM_CLASSMAP_USE(name)
+#define DRM_CLASSMAP_PARAM_REF(...)
 #endif
 
 static inline bool drm_debug_enabled_raw(enum drm_debug_category category)
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 1b027be2cdc4..f182f95caabb 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -91,7 +91,7 @@ struct ddebug_class_map {
  * used to validate a "class FOO .." >control command on the module
  */
 #define DYNDBG_CLASSMAP_DEFINE(_var, _maptype, _base, ...) \
-   const char *_var##_classnames[] = { __VA_ARGS__ };  \
+   static const char *_var##_classnames[] = { __VA_ARGS__ };   \
struct ddebug_class_map __aligned(8) __used \
__section("__dyndbg_classes") _var = {  \
.mod = THIS_MODULE, \
@@ -145,6 +145,41 @@ struct ddebug_class_param {
const struct ddebug_class_map *map;
 };
 
+/**
+ * DYNDBG_CLASSMAP_PARAM - wrap a dyndbg-classmap with a controlling sys-param
+ * @_name  sysfs node name
+ * @_var   name of the struct classmap var defining the controlled classes
+ * @_flags flags to be toggled, typically just 'p'
+ *
+ * Creates a sysfs-param to control the classes defined by the
+ * classmap.  Keeps bits in a private/static
+ */
+#define DYNDBG_CLASSMAP_PARAM(_name, _var, _flags) \
+   static unsigned long _name##_bvec;  \
+   __DYNDBG_CLASSMAP_PARAM(_name, _name##_bvec, _var, _flags)
+
+/**
+ * DYNDBG_CLASSMAP_PARAM_REF - wrap a dyndbg-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 struct classmap var defining the controlled classes
+ * @_flags flags to be toggled, typically just 'p'
+ *
+ * Creates a sysfs-param to control the classmap, keeping bitvec in user 
@_bits.
+ * This lets drm use __drm_debug elsewhere too.
+ */
+#define DYNDBG_CLASSMAP_PARAM_REF(_name, _bits, _var, _flags)  \
+   __DYNDBG_CLASSMAP_PARAM(_name, _bits, _var, _flags)
+
+#define __DYNDBG_CLASSMAP_PARAM(_name, _bits, _var, _flags)\
+   static struct ddebug_class_param _name##_##_flags = {   \
+   .bits = &(_bits),   \
+   .flags = #_flags,   \
+   .map = &(_var), \
+   }; 

[PATCH v7b 24/25] drm-drivers: DRM_CLASSMAP_USE in 2nd batch of drivers, helpers

2023-10-13 Thread Jim Cromie
Add a DRM_CLASSMAP_USE declaration to 2nd batch of helpers and *_drv.c
files.  For drivers, add the decl just above the module's PARAMs,
since it identifies the "inherited" drm.debug param.

Note: with CONFIG_DRM_USE_DYNAMIC_DEBUG=y, a module not also declaring
DRM_CLASSMAP_USE will have its class'd prdbgs stuck in the initial
(disabled, but for DEBUG) state.

The stuck sites are evident in /proc/dynamic_debug/control as:

   class:_UNKNOWN_ _id:N# control's last column

rather than a proper "enumeration":

   class:DRM_UT_CORE

This set of updates was found by choosing M for all DRM-config items I
found (not allmodconfig), building & modprobing them, and grepping
"class unknown," control.  There may yet be others.

Signed-off-by: Jim Cromie 
---
 drivers/gpu/drm/drm_gem_shmem_helper.c | 2 ++
 drivers/gpu/drm/gud/gud_drv.c  | 2 ++
 drivers/gpu/drm/mgag200/mgag200_drv.c  | 2 ++
 drivers/gpu/drm/qxl/qxl_drv.c  | 2 ++
 drivers/gpu/drm/radeon/radeon_drv.c| 2 ++
 drivers/gpu/drm/udl/udl_main.c | 2 ++
 drivers/gpu/drm/vkms/vkms_drv.c| 2 ++
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c| 2 ++
 8 files changed, 16 insertions(+)

diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c 
b/drivers/gpu/drm/drm_gem_shmem_helper.c
index e435f986cd13..066d906e3199 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -23,6 +23,8 @@
 #include 
 #include 
 
+DRM_CLASSMAP_USE(drm_debug_classes);
+
 MODULE_IMPORT_NS(DMA_BUF);
 
 /**
diff --git a/drivers/gpu/drm/gud/gud_drv.c b/drivers/gpu/drm/gud/gud_drv.c
index 9d7bf8ee45f1..5b555045fce4 100644
--- a/drivers/gpu/drm/gud/gud_drv.c
+++ b/drivers/gpu/drm/gud/gud_drv.c
@@ -31,6 +31,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,
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c 
b/drivers/gpu/drm/mgag200/mgag200_drv.c
index abddf37f0ea1..d678eb8e028d 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.c
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.c
@@ -24,6 +24,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;
diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c
index b30ede1cf62d..91942ffcc2b4 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.c
+++ b/drivers/gpu/drm/qxl/qxl_drv.c
@@ -65,6 +65,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;
 
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c 
b/drivers/gpu/drm/radeon/radeon_drv.c
index fa531493b111..ab29945af657 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -247,6 +247,8 @@ int radeon_cik_support = 1;
 MODULE_PARM_DESC(cik_support, "CIK support (1 = enabled (default), 0 = 
disabled)");
 module_param_named(cik_support, radeon_cik_support, int, 0444);
 
+DRM_CLASSMAP_USE(drm_debug_classes);
+
 static struct pci_device_id pciidlist[] = {
radeon_PCI_IDS
 };
diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c
index 3ebe2ce55dfd..ba57c14454e5 100644
--- a/drivers/gpu/drm/udl/udl_main.c
+++ b/drivers/gpu/drm/udl/udl_main.c
@@ -19,6 +19,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
diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c
index dd0af086e7fa..086797c4b82b 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.c
+++ b/drivers/gpu/drm/vkms/vkms_drv.c
@@ -39,6 +39,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");
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 8b24ecf60e3e..9cb6be422621 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -275,6 +275,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_iom

[PATCH v7b 25/25] drm: restore CONFIG_DRM_USE_DYNAMIC_DEBUG un-BROKEN

2023-10-13 Thread Jim Cromie
Lots of burn-in testing needed before signing, upstreaming.

NOTE: I set default Y to maximize testing by default.
Is there a better way to do this ?

Signed-off-by: Jim Cromie 
---
 drivers/gpu/drm/Kconfig | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 3caa020391c7..708f5e8cb205 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -55,8 +55,7 @@ config DRM_DEBUG_MM
 
 config DRM_USE_DYNAMIC_DEBUG
bool "use dynamic debug to implement drm.debug"
-   default n
-   depends on BROKEN
+   default y
depends on DRM
depends on DYNAMIC_DEBUG || DYNAMIC_DEBUG_CORE
depends on JUMP_LABEL
-- 
2.41.0



Re: [PATCH v7b 00/25] fix DRM_USE_DYNAMIC_DEBUG=y regression

2023-10-14 Thread jim . cromie
On Fri, Oct 13, 2023 at 4:48 PM Jim Cromie  wrote:
>
> hi Jason, DRM-folk
>
> (now with checkpatch fixes)

I missed fixing boxed-vector, am just dropping it.

>
> This patchest fixes the chicken-egg initialization problem in the 1st
> version of ddebug-class-maps, that DRM-CI uncovered.
>
> The root-problem was DECLARE_DYNDBG_CLASSMAP, which broke the K&R rule:
> "define once, refer many".  In patch 14 it is replaced by:
>
>  DYNDBG_CLASSMAP_DEFINE - define and export a struct ddebug_class_map
>  DYNDBG_CLASSMAP_USE - ref the exported struct
>
> test-dynamic-debug is also extended with a -submod.ko, in order to
> recapitulate the drm & drivers initialization scenario.
>
> They're on v6.6-rc5 now, and apply cleanly to drm-tip/drm-tip.
>
> Ive been running recent revs on rc3+, on my desktop and laptop.
>
> The final blocker was a missing __align(8) on the ddebug_class_user
> record inserted by DYNDBG_CLASSMAP_USE.  This caused DRM=y (builtin
> only) to have a corrupt record for drm_kms_helper (builtin dependent).
> Curiously, a clang build did not exhibit this problem.
>

>
> Widespread testing is appreciated.
> I have scripts if anyone wants them.
>
> I'll forward lkp-robot reports here when I get them.
> Patches also at https://github.com/jimc/linux (dd-fix-7b)
>

Date: Sat, 14 Oct 2023 18:22:28 +0800
From: kernel test robot 
To: Jim Cromie 
Subject: [jimc:dd-fix-7a] BUILD SUCCESS 8e96f63f570a462b859876601a5f795a15999f6b
Message-ID: <202310141826.an7mad40-...@intel.com>
User-Agent: s-nail v14.9.24

tree/branch: https://github.com/jimc/linux.git dd-fix-7a
branch HEAD: 8e96f63f570a462b859876601a5f795a15999f6b  drm: restore
CONFIG_DRM_USE_DYNAMIC_DEBUG un-BROKEN

elapsed time: 3187m

configs tested: 103
configs skipped: 2

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha allnoconfig   gcc
alphaallyesconfig   gcc
alpha   defconfig   gcc
arc  allmodconfig   gcc
arc   allnoconfig   gcc
arc  allyesconfig   gcc
arc defconfig   gcc
arc   randconfig-001-20231012   gcc
arm  allmodconfig   gcc
arm   allnoconfig   gcc
arm  allyesconfig   gcc
arm defconfig   gcc
arm   randconfig-001-20231013   gcc
arm64allmodconfig   gcc
arm64 allnoconfig   gcc
arm64allyesconfig   gcc
arm64   defconfig   gcc
csky allmodconfig   gcc
csky  allnoconfig   gcc
csky allyesconfig   gcc
cskydefconfig   gcc
i386 allmodconfig   gcc
i386  allnoconfig   gcc
i386 allyesconfig   gcc
i386  debian-10.3   gcc
i386defconfig   gcc
i386  randconfig-001-20231013   gcc
i386  randconfig-002-20231013   gcc
i386  randconfig-003-20231013   gcc
i386  randconfig-004-20231013   gcc
i386  randconfig-005-20231013   gcc
i386  randconfig-006-20231013   gcc
loongarchallmodconfig   gcc
loongarch allnoconfig   gcc
loongarchallyesconfig   gcc
loongarch   defconfig   gcc
loongarch randconfig-001-20231012   gcc
m68k allmodconfig   gcc
m68k  allnoconfig   gcc
m68k allyesconfig   gcc
m68kdefconfig   gcc
microblaze   allmodconfig   gcc
microblazeallnoconfig   gcc
microblaze   allyesconfig   gcc
microblaze  defconfig   gcc
mips allmodconfig   gcc
mips  allnoconfig   gcc
mips allyesconfig   gcc
nios2allmodconfig   gcc
nios2 allnoconfig   gcc
nios2allyesconfig   gcc
nios2   defconfig   gcc
openrisc allmodconfig   gcc
openrisc  allnoconfig   gcc
openrisc allyesconfig   gcc
openriscdefconfig   gcc
parisc   allmodconfig   gcc
parisc 

[PATCH v7c 00/24] fix DRM_USE_DYNAMIC_DEBUG=y regression

2023-10-18 Thread Jim Cromie


hi Jason, DRM-folk

(v7c now with all checkpatch fixes)

This patchest fixes the chicken-egg initialization problem in the 1st
version of ddebug-class-maps, that DRM-CI uncovered.

The root-problem was DECLARE_DYNDBG_CLASSMAP, which broke the K&R rule:
"define once, refer many".  In patch 14 it is replaced by:

 DYNDBG_CLASSMAP_DEFINE - define and export a struct ddebug_class_map
 DYNDBG_CLASSMAP_USE - ref the exported struct

test-dynamic-debug is also extended with a -submod.ko, in order to
recapitulate the drm & drivers initialization scenario.

They're on v6.6-rc6 now, and recently applied cleanly to drm-tip/drm-tip.

Ive been running recent revs on rc3+, on my desktop and laptop.

The final blocker was a missing __align(8) on the ddebug_class_user
record inserted by DYNDBG_CLASSMAP_USE.  This caused DRM=y (builtin
only) to have a corrupt record for drm_kms_helper (a builtin dependent).
Curiously, a clang build did not exhibit this problem.

Heres a part of dmesg, for a DRM=y kernel, booted with
 dynamic_debug.verbose=3 drm.debug=0x10

[0.466747] dyndbg: add-module: drm 406 sites
[0.467569] dyndbg: classes[0]: module:drm base:0 len:10 type:DISJOINT_BITS
[0.467743] dyndbg: module:drm attached 1 classes
[0.468557] dyndbg: builtin class: module:drm base:0 len:10 
type:DISJOINT_BITS
[0.468742] dyndbg:  found kp:drm.debug =0x10
[0.468743] dyndbg:   mapped to: module:drm base:0 len:10 type:DISJOINT_BITS
[0.469742] dyndbg:   drm.debug: classbits: 0x10
[0.470573] dyndbg: apply bitmap: 0x10 to: 0x0 for drm
[0.470743] dyndbg: query 0: "class DRM_UT_ATOMIC +p" mod:drm
[0.471743] dyndbg: split into words: "class" "DRM_UT_ATOMIC" "+p"
[0.472743] dyndbg: op='+' flags=0x1 maskp=0x
[0.473679] dyndbg: parsed: func="" file="" module="drm" format="" 
lineno=0-0 class=DRM_UT_ATOMIC
[0.473749] dyndbg: processed 1 queries, with 0 matches, 0 errs
[0.474742] dyndbg: bit_4: 0 matches on class: DRM_UT_ATOMIC -> 0x10
[0.475742] dyndbg: applied bitmap: 0x10 to: 0x0 for drm
[0.476686] dyndbg: 406 debug prints in module drm
[0.476743] dyndbg: add-module: drm_kms_helper 93 sites
[0.477727] dyndbg: class_ref[0] drm_kms_helper -> drm module:drm base:0 
len:10 type:DISJOINT_BITS
[0.477743] dyndbg: builtin class: module:drm base:0 len:10 
type:DISJOINT_BITS
[0.478742] dyndbg:  found kp:drm.debug =0x10
[0.478743] dyndbg:   mapped to: module:drm base:0 len:10 type:DISJOINT_BITS
[0.479743] dyndbg:   drm.debug: classbits: 0x10
[0.480592] dyndbg: apply bitmap: 0x10 to: 0x0 for drm_kms_helper
[0.480743] dyndbg: query 0: "class DRM_UT_ATOMIC +p" mod:drm_kms_helper
[0.481743] dyndbg: split into words: "class" "DRM_UT_ATOMIC" "+p"
[0.482743] dyndbg: op='+' flags=0x1 maskp=0x
[0.483743] dyndbg: parsed: func="" file="" module="drm_kms_helper" 
format="" lineno=0-0 class=DRM_UT_ATOMIC
[0.484750] dyndbg: class-ref: drm_kms_helper.DRM_UT_ATOMIC  
module:drm_kms_helper nd:93 nc:0 nu:1
[0.485809] dyndbg: processed 1 queries, with 44 matches, 0 errs
[0.486742] dyndbg: bit_4: 44 matches on class: DRM_UT_ATOMIC -> 0x10
[0.487742] dyndbg: applied bitmap: 0x10 to: 0x0 for drm_kms_helper
[0.488743] dyndbg: attach-client-module:  module:drm_kms_helper nd:93 nc:0 
nu:1
[0.489742] dyndbg:  93 debug prints in module drm_kms_helper

Widespread testing is appreciated.
I have scripts if anyone wants them.
lkp-robot reported success on dd-fix-7b, no report yet on 7c

Patches are also at https://github.com/jimc/linux/tree/dd-fix-7c

Jim Cromie (24):
  test-dyndbg: fixup CLASSMAP usage error
  dyndbg: reword "class unknown," to "class:_UNKNOWN_"
  dyndbg: make ddebug_class_param union members same size
  dyndbg: replace classmap list with a vector
  dyndbg: ddebug_apply_class_bitmap - add module arg, select on it
  dyndbg: split param_set_dyndbg_classes to module/wrapper fns
  dyndbg: drop NUM_TYPE_ARRAY
  dyndbg: reduce verbose/debug clutter
  dyndbg: silence debugs with no-change updates
  dyndbg: tighten ddebug_class_name() 1st arg type
  dyndbg: tighten fn-sig of ddebug_apply_class_bitmap
  dyndbg: reduce verbose=3 messages in ddebug_add_module
  dyndbg-API: remove DD_CLASS_TYPE_(DISJOINT|LEVEL)_NAMES and code
  dyndbg-API: fix CONFIG_DRM_USE_DYNAMIC_DEBUG regression
  dyndbg: refactor ddebug_classparam_clamp_input
  dyndbg-API: promote DYNDBG_CLASSMAP_PARAM to API
  dyndbg-doc: add classmap info to howto
  dyndbg: reserve flag bit _DPRINTK_FLAGS_PREFIX_CACHED
  dyndbg: add _DPRINTK_FLAGS_INCL_LOOKUP
  dyndbg: refactor *dynamic_emit_prefix
  dyndbg: change WARN_ON to WARN_ON_ONCE
  drm: use correct ccflags-y spelling
  drm-drivers: DRM_CLASSMAP_USE in 2nd batch of drivers, helpers

[PATCH v7c 01/24] test-dyndbg: fixup CLASSMAP usage error

2023-10-18 Thread Jim Cromie
more careful reading of test output reveals:

lib/test_dynamic_debug.c:103 [test_dynamic_debug]do_cats =pmf "doing 
categories\n"
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

That last line is wrong, the HI class is declared.

But the enum's 1st val (explicitly initialized) was wrong; it must be
_base, not _base+1 (a DECLARE_DYNDBG_CLASSMAP[1] param).  So the last
enumeration exceeded the range of mapped class-id's, which triggered
the "class unknown" report.  I intentionally coded in an error, but
forgot to verify its detection and remove it.

RFC:

This patch fixes a bad usage of DECLARE_DYNDBG_CLASSMAP(), showing
that it is too error-prone.  As noted in test-mod comments:

 * 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-62 class_id space !!
 *   (build-bug-on tips welcome)

Those shortcomings could largely be fixed with a __stringify_list
(which doesn't exist,) used in DECLARE_DYNDBG_CLASSMAP to stringify
__VA_ARGS__.  Then, API would accept DRM_UT_* values literally; all
the categories, in order, and not their stringifications, which
created all the usage complications above.

[1] name changes later to DYNDBG_CLASSMAP_DEFINE

Signed-off-by: Jim Cromie 
---
 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 8dd250ad022b..a01f0193a419 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.41.0



[PATCH v7c 02/24] dyndbg: reword "class unknown, " to "class:_UNKNOWN_"

2023-10-18 Thread Jim Cromie
This appears in the control-file to report an unknown class-name, which
indicates that the class_id is not authorized, and dyndbg will ignore
changes to it.  Generally, this means that a DYNDBG_CLASSMAP_DEFINE or
DYNDBG_CLASSMAP_USE is missing.

But the word "unknown" appears in quite a few prdbg formats, so thats
a suboptimal search term to find occurrences of the problem.  Thus
change it to "_UNKNOWN_" which properly shouts the condition.

Signed-off-by: Jim Cromie 
---
 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 6fba6423cc10..ceb3067a5c83 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -1151,7 +1151,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_puts(m, "\n");
 
-- 
2.41.0



[PATCH v7c 03/24] dyndbg: make ddebug_class_param union members same size

2023-10-18 Thread Jim Cromie
struct ddebug_class_param keeps a ref to the state-storage of the
param, make both flavors use the same unsigned long under-type.
ISTM this is simpler and safer.

Signed-off-by: Jim Cromie 
---
 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 4fcbf4d4fd0a..5231aaf361c4 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -124,7 +124,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 ceb3067a5c83..b984ce338921 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -796,7 +796,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.41.0



[PATCH v7c 04/24] dyndbg: replace classmap list with a vector

2023-10-18 Thread Jim Cromie
Classmaps are stored/linked in a section/array, but are each added to
the module's ddebug_table.maps list-head.

This is unnecessary; even when ddebug_attach_classmap() is handling
the builtin section (with classmaps for multiple builtin modules), its
contents are ordered, so a module's possibly multiple classmaps will
be consecutive in the section, and could be treated as a vector/block,
since both start-addy and subrange length are in the ddebug_info arg.

So this changes:

struct ddebug_class_map drops list-head link.

struct ddebug_table drops the list-head maps, and gets: classes &
num_classes for the start-addy and num_classes, placed to improve
struct packing.

The loading: in ddebug_attach_module_classes(), replace the
for-the-modname list-add loop, with a forloop that finds the module's
subrange (start,length) of matching classmaps within the possibly
builtin classmaps vector, and saves those to the ddebug_table.

The reading/using: change list-foreach loops in ddebug_class_name() &
ddebug_find_valid_class() to walk the array from start to length.

Also:
Move #define __outvar up, above an added use in a fn-prototype.
Simplify ddebug_attach_module_classes args, ref has both addy,len.

no functional changes

Signed-off-by: Jim Cromie 
---
 include/linux/dynamic_debug.h |  1 -
 lib/dynamic_debug.c   | 61 ++-
 2 files changed, 32 insertions(+), 30 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 5231aaf361c4..b53217e4b711 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -83,7 +83,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 b984ce338921..a3be2e7c8c84 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 {
@@ -147,13 +148,15 @@ static void vpr_info_dq(const struct ddebug_query *query, 
const char *msg)
  query->first_lineno, query->last_lineno, query->class_string);
 }
 
+#define __outvar /* filled by callee */
 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,
+   __outvar 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;
@@ -164,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
@@ -,9 +1113,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];
 
@@ -1197,30 +1200,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

[PATCH v7c 05/24] dyndbg: ddebug_apply_class_bitmap - add module arg, select on it

2023-10-18 Thread Jim Cromie
Add query_module param to ddebug_apply_class_bitmap().  This allows
its caller to update just one module, or all (as currently).  We'll
use this later to propagate drm.debug to each USEr as they're
modprobed.

No functional change.

Signed-off-by: Jim Cromie 
---

after `modprobe i915`, heres the module dependencies,
though not all on drm.debug.

bash-5.2# lsmod
Module  Size  Used by
i915 3133440  0
drm_buddy  20480  1 i915
ttm90112  1 i915
i2c_algo_bit   16384  1 i915
video  61440  1 i915
wmi32768  1 video
drm_display_helper200704  1 i915
drm_kms_helper208896  2 drm_display_helper,i915
drm   606208  5 
drm_kms_helper,drm_display_helper,drm_buddy,i915,ttm
cec57344  2 drm_display_helper,i915
---
 lib/dynamic_debug.c | 19 ---
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index a3be2e7c8c84..ba41fdeaaf98 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -601,7 +601,8 @@ static int ddebug_exec_queries(char *query, const char 
*modname)
 
 /* apply a new bitmap to the sys-knob's current bit-state */
 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];
@@ -609,7 +610,8 @@ 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);
+   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))
@@ -618,12 +620,15 @@ 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);
}
+   v2pr_info("applied bitmap: 0x%lx to: 0x%lx for %s\n", *new_bits, 
*old_bits,
+ query_modname ?: "");
+
return matches;
 }
 
@@ -679,7 +684,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]);
@@ -689,7 +694,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);
@@ -752,7 +757,7 @@ int param_set_dyndbg_classes(const char *instr, const 
struct kernel_param *kp)
inrep &= CLASSMAP_BITMASK(map->length);
}
v2pr_info("bits:%lx > %s\n", inrep, KP_NAME(kp));
-   totct += ddebug_apply_class_bitmap(dcp, &inrep, dcp->bits);
+   totct += ddebug_apply_class_bitmap(dcp, &inrep, dcp->bits, 
NULL);
*dcp->bits = inrep;
break;
case DD_CLASS_TYPE_LEVEL_NUM:
@@ -765,7 +770,7 @@ int param_set_dyndbg_classes(const char *instr, const 
struct kernel_param *kp)
old_bits = CLASSMAP_BITMASK(*dcp->lvl)

[PATCH v7c 06/24] dyndbg: split param_set_dyndbg_classes to module/wrapper fns

2023-10-18 Thread Jim Cromie
rename param_set_dyndbg_classes: add _module_ name & arg, old name is
wrapper to new.  New arg allows caller to specify that only one module
is affected by a prdbgs update.

Outer fn preserves kernel_param interface, passing NULL to inner fn.
This selectivity will be used later to narrow the scope of changes
made.

no functional change.

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 37 ++---
 1 file changed, 22 insertions(+), 15 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index ba41fdeaaf98..b67c9b137447 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -708,18 +708,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 *modnm)
 {
const struct ddebug_class_param *dcp = kp->arg;
const struct ddebug_class_map *map = dcp->map;
@@ -756,8 +747,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, 
NULL);
+   v2pr_info("bits:0x%lx > %s.%s\n", inrep, modnm ?: "*", 
KP_NAME(kp));
+   totct += ddebug_apply_class_bitmap(dcp, &inrep, dcp->bits, 
modnm);
*dcp->bits = inrep;
break;
case DD_CLASS_TYPE_LEVEL_NUM:
@@ -770,7 +761,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, 
NULL);
+   totct += ddebug_apply_class_bitmap(dcp, &new_bits, &old_bits, 
modnm);
*dcp->lvl = inrep;
break;
default:
@@ -779,6 +770,22 @@ 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 - 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)
+{
+   return param_set_dyndbg_module_classes(instr, kp, NULL);
+}
 EXPORT_SYMBOL(param_set_dyndbg_classes);
 
 /**
-- 
2.41.0



[PATCH v7c 07/24] dyndbg: drop NUM_TYPE_ARRAY

2023-10-18 Thread Jim Cromie
ARRAY_SIZE works here, since array decl is complete.

no functional change

Signed-off-by: Jim Cromie 
---
 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 b53217e4b711..8116d0a0d33a 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -106,11 +106,9 @@ struct ddebug_class_map {
.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))
 
 /* encapsulate linker provided built-in (or module) dyndbg data */
 struct _ddebug_info {
-- 
2.41.0



[PATCH v7c 08/24] dyndbg: reduce verbose/debug clutter

2023-10-18 Thread Jim Cromie
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=0x

 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 is like 1st, with result, not procedure.
   2nd is just status, retold in 4th, with more info.

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 14 +++---
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index b67c9b137447..b0e11f6bfaa2 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -266,9 +266,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;
 }
 
@@ -497,7 +494,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--) {
@@ -511,7 +507,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) {
@@ -527,7 +522,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;
 }
@@ -537,7 +532,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);
@@ -555,10 +550,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
-- 
2.41.0



[PATCH v7c 10/24] dyndbg: tighten ddebug_class_name() 1st arg type

2023-10-18 Thread Jim Cromie
Change function's 1st arg-type, and deref in the caller.
The fn doesn't need any other fields in the struct.

no functional change.

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index b07aab422604..8158943b350d 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -1117,12 +1117,12 @@ static void *ddebug_proc_next(struct seq_file *m, void 
*p, loff_t *pos)
 #define class_in_range(class_id, map)  \
(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 = dt->classes;
+   int i;
 
-   for (i = 0; i < nc; i++, map++)
+   for (i = 0; i < dt->num_classes; i++, map++)
if (class_in_range(dp->class_id, map))
return map->class_names[dp->class_id - map->base];
 
@@ -1156,7 +1156,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
seq_puts(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
-- 
2.41.0



[PATCH v7c 09/24] dyndbg: silence debugs with no-change updates

2023-10-18 Thread Jim Cromie
check for actual changes before announcing them, declutter logs.

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index b0e11f6bfaa2..b07aab422604 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -591,7 +591,7 @@ 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,
 const char *query_modname)
@@ -602,8 +602,9 @@ static int ddebug_apply_class_bitmap(const struct 
ddebug_class_param *dcp,
int matches = 0;
int bi, ct;
 
-   v2pr_info("apply bitmap: 0x%lx to: 0x%lx for %s\n", *new_bits, 
*old_bits,
- query_modname ?: "");
+   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))
@@ -618,8 +619,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);
}
-   v2pr_info("applied bitmap: 0x%lx to: 0x%lx for %s\n", *new_bits, 
*old_bits,
- query_modname ?: "");
+   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;
 }
-- 
2.41.0



[PATCH v7c 12/24] dyndbg: reduce verbose=3 messages in ddebug_add_module

2023-10-18 Thread Jim Cromie
The fn currently says "add-module", then "skipping" if the module has
no prdbgs.  Just check 1st and return quietly.

no functional change

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 8beb98a831f5..45870a699507 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -1242,11 +1242,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(sizeof(*dt), GFP_KERNEL);
if (dt == NULL) {
-- 
2.41.0



[PATCH v7c 16/24] dyndbg-API: promote DYNDBG_CLASSMAP_PARAM to API

2023-10-18 Thread Jim Cromie
move the DYNDBG_CLASSMAP_PARAM macro from test-dynamic-debug.c into
the header, and refine it, by distinguishing the 2 use cases:

1.DYNDBG_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.DYNDBG_CLASSMAP_PARAM
new user (test_dynamic_debug) doesn't need to share state,
decls a static long unsigned int to store the bitvec.

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

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

Signed-off-by: Jim Cromie 
---
---
 drivers/gpu/drm/drm_print.c |  8 ++
 include/drm/drm_print.h |  6 ++--
 include/linux/dynamic_debug.h   | 37 +++-
 lib/test_dynamic_debug.c| 50 +
 lib/test_dynamic_debug_submod.c |  9 +-
 5 files changed, 69 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c
index dabcfa0dd279..8f4b609353a5 100644
--- a/drivers/gpu/drm/drm_print.c
+++ b/drivers/gpu/drm/drm_print.c
@@ -69,12 +69,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, ¶m_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 706afc97c79c..94d4f5500030 100644
--- a/include/drm/drm_print.h
+++ b/include/drm/drm_print.h
@@ -322,11 +322,13 @@ enum drm_debug_category {
 };
 
 #ifdef CONFIG_DRM_USE_DYNAMIC_DEBUG
-#define DRM_CLASSMAP_DEFINE(...) DYNDBG_CLASSMAP_DEFINE(__VA_ARGS__)
-#define DRM_CLASSMAP_USE(name)   DYNDBG_CLASSMAP_USE(name)
+#define DRM_CLASSMAP_DEFINE(...)   DYNDBG_CLASSMAP_DEFINE(__VA_ARGS__)
+#define DRM_CLASSMAP_USE(name) DYNDBG_CLASSMAP_USE(name)
+#define DRM_CLASSMAP_PARAM_REF(...)DYNDBG_CLASSMAP_PARAM_REF(__VA_ARGS__)
 #else
 #define DRM_CLASSMAP_DEFINE(...)
 #define DRM_CLASSMAP_USE(name)
+#define DRM_CLASSMAP_PARAM_REF(...)
 #endif
 
 static inline bool drm_debug_enabled_raw(enum drm_debug_category category)
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 1b027be2cdc4..f182f95caabb 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -91,7 +91,7 @@ struct ddebug_class_map {
  * used to validate a "class FOO .." >control command on the module
  */
 #define DYNDBG_CLASSMAP_DEFINE(_var, _maptype, _base, ...) \
-   const char *_var##_classnames[] = { __VA_ARGS__ };  \
+   static const char *_var##_classnames[] = { __VA_ARGS__ };   \
struct ddebug_class_map __aligned(8) __used \
__section("__dyndbg_classes") _var = {  \
.mod = THIS_MODULE, \
@@ -145,6 +145,41 @@ struct ddebug_class_param {
const struct ddebug_class_map *map;
 };
 
+/**
+ * DYNDBG_CLASSMAP_PARAM - wrap a dyndbg-classmap with a controlling sys-param
+ * @_name  sysfs node name
+ * @_var   name of the struct classmap var defining the controlled classes
+ * @_flags flags to be toggled, typically just 'p'
+ *
+ * Creates a sysfs-param to control the classes defined by the
+ * classmap.  Keeps bits in a private/static
+ */
+#define DYNDBG_CLASSMAP_PARAM(_name, _var, _flags) \
+   static unsigned long _name##_bvec;  \
+   __DYNDBG_CLASSMAP_PARAM(_name, _name##_bvec, _var, _flags)
+
+/**
+ * DYNDBG_CLASSMAP_PARAM_REF - wrap a dyndbg-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 struct classmap var defining the controlled classes
+ * @_flags flags to be toggled, typically just 'p'
+ *
+ * Creates a sysfs-param to control the classmap, keeping bitvec in user 
@_bits.
+ * This lets drm use __drm_debug elsewhere too.
+ */
+#define DYNDBG_CLASSMAP_PARAM_REF(_name, _bits, _var, _flags)  \
+   __DYNDBG_CLASSMAP_PARAM(_name, _bits, _var, _flags)
+
+#define __DYNDBG_CLASSMAP_PARAM(_name, _bits, _var, _flags)\
+   static struct ddebug_class_param _name##_##_flags = {   \
+   .bits = &(_bits),   \
+   .flags = #_flags,   \
+   .map = &(_var), \
+   }; 

[PATCH v7c 14/24] dyndbg-API: fix CONFIG_DRM_USE_DYNAMIC_DEBUG regression

2023-10-18 Thread Jim Cromie
ble 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, with the new ifdef _SUBMOD block invoking DYNDBG_CLASSMAP_USE
for the 2 test-interfaces.  I think this is clearer.

These 2 modules are independently configurable, allowing builtin
parent and loadable submod, which recapitulates a troublesome build
combo for drm & drivers.

DEBUG details:

``#define DEBUG`` in src enables all pr_debugs after it, including any
class'd pr_debugs; its not necessarily all-or-nothing, unless its a
one-file-module with DEBUG at the top.

If a CLASSMAP_PARAM is defined on a classmap, its readback value
cannot describe the set of enablements.  The param is basically
write-only; it cannot know if `echo $cmd >control` was done since.

To know the exact pr-debug state with certainty, toggle to both:

   echo 0x3ff > /sys/module/drm/parameters/debug
   echo 0 > /sys/module/drm/parameters/debug

Cc: Daniel Vetter 
Cc: Jani Nikula 
Cc: Tvrtko Ursulin 
Cc: Rob Clark 
Cc: Sean Paul 
Cc: Luis Chamberlain 
Fixes: aad0214f3026 ("dyndbg: add DECLARE_DYNDBG_CLASSMAP macro")
Fixes: f158936b60a7 ("drm: POC drm on dyndbg - use in core, 2 helpers, 3 
drivers.")
Ref: commit bb2ff6c27bc9 ("drm: Disable dynamic debug as broken")

Signed-off-by: Jim Cromie 
---

fixup-kconfig description too short
---
 MAINTAINERS |   2 +-
 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_print.c |  25 ++--
 drivers/gpu/drm/i915/i915_params.c  |  12 +-
 drivers/gpu/drm/nouveau/nouveau_drm.c   |  12 +-
 include/asm-generic/vmlinux.lds.h   |   1 +
 include/drm/drm_print.h |  10 +-
 include/linux/dynamic_debug.h   |  53 +--
 kernel/module/main.c|   3 +
 lib/Kconfig.debug   |  24 +++-
 lib/Makefile|   3 +
 lib/dynamic_debug.c | 183 +---
 lib/test_dynamic_debug.c| 111 +-
 lib/test_dynamic_debug_submod.c |  10 ++
 16 files changed, 344 insertions(+), 141 deletions(-)
 create mode 100644 lib/test_dynamic_debug_submod.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 7a7bd8bd80e9..ac0b6a4e4ee7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7320,7 +7320,7 @@ M:Jim Cromie 
 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
 
 DYNAMIC INTERRUPT MODERATION
 M: Tal Gilboa 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 81edf66dbea8..efba99c9393e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -197,17 +197,7 @@ int amdgpu_user_partt_mode = 
AMDGPU_AUTO_COMPUTE_PARTITION_MODE;
 
 static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work);
 
-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),
diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
b/drivers/gpu/drm/display/drm_dp_helper.c
index e6a78fd32380..d97de1a27939 100644
--- a/drivers/gpu/drm/display/drm_dp_helper.c
+++ b/drivers/gpu/drm/display/drm_dp_helper.c
@@ -41,17 +41,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

[PATCH v7c 18/24] dyndbg: reserve flag bit _DPRINTK_FLAGS_PREFIX_CACHED

2023-10-18 Thread Jim Cromie
Reserve bit 7 to remember that a pr-debug callsite is/was:
- enabled, with +p
- wants a dynamic-prefix, with one+ of module:function:sourcfile
- was previously called
- was thus saved in the cache. NOT YET.

Its unclear whether any cache fetch would be faster than 2-3 field
fetches, but theres another factor; the 3 columns in the __dyndbg
section are highly redundant and compressible, but to get the
compression, we need field accessors, which will rebalance the
tradeoff.

So, for now, its just the bit reservation.

Signed-off-by: Jim Cromie 
---
 include/linux/dynamic_debug.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index f182f95caabb..927cb14f24e0 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -38,6 +38,7 @@ struct _ddebug {
 #define _DPRINTK_FLAGS_INCL_LINENO (1<<3)
 #define _DPRINTK_FLAGS_INCL_TID(1<<4)
 #define _DPRINTK_FLAGS_INCL_SOURCENAME (1<<5)
+#define _DPRINTK_FLAGS_PREFIX_CACHED   (1<<7)
 
 #define _DPRINTK_FLAGS_INCL_ANY\
(_DPRINTK_FLAGS_INCL_MODNAME | _DPRINTK_FLAGS_INCL_FUNCNAME |\
-- 
2.41.0



[PATCH v7c 19/24] dyndbg: add _DPRINTK_FLAGS_INCL_LOOKUP

2023-10-18 Thread Jim Cromie
dyndbg's dynamic prefixing (by +tmfsl flags) is needlessly expensive.

When an enabled (with +p) pr_debug is called, _DPRINTK_FLAGS_INCL_ANY
prefix decorations are sprintf'd into stack-mem for every call.

This string (or part of it) could be cached once its 1st generated,
and retrieved thereafter, as long as its deleted any time the
callsite's flags are changed afterwards.

So consider the prefix/decoration flags: 'tmfsl', and what should be
in the cache:

-t  thread-id. not part of the "callsite" info, derived from current.
doesn't belong in the cache. it would be wrong.
can be done in outer: dynamic_emit_prefix()

-l  line number
this could be part of the prefix, but would bloat the cache
can also be done in outer: dynamic_emit_prefix()

-mfs  module, function, source-file
we cache these, composed into a sub-string.
they are "lookups", currently to descriptor fields,
could be accessor macros to "compressed" tables.
cache saves more access work.

All enabled together, they compose a prefix string like:

  # outer   -inner--   outer
  "[tid] module:function:sourcfile:line: "

So this patch extracts _DPRINTK_FLAGS_INCL_LOOKUP macro out of
_DPRINTK_FLAGS_INCL_ANY macro, then redefs latter.

Next re-refactor dynamic_emit_prefix inner/outer fns accordingly.

Signed-off-by: Jim Cromie 
---
 include/linux/dynamic_debug.h | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 927cb14f24e0..2237d454bc19 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -40,10 +40,12 @@ struct _ddebug {
 #define _DPRINTK_FLAGS_INCL_SOURCENAME (1<<5)
 #define _DPRINTK_FLAGS_PREFIX_CACHED   (1<<7)
 
-#define _DPRINTK_FLAGS_INCL_ANY\
-   (_DPRINTK_FLAGS_INCL_MODNAME | _DPRINTK_FLAGS_INCL_FUNCNAME |\
-_DPRINTK_FLAGS_INCL_LINENO  | _DPRINTK_FLAGS_INCL_TID |\
+#define _DPRINTK_FLAGS_INCL_LOOKUP \
+   (_DPRINTK_FLAGS_INCL_MODNAME | _DPRINTK_FLAGS_INCL_FUNCNAME |   \
 _DPRINTK_FLAGS_INCL_SOURCENAME)
+#define _DPRINTK_FLAGS_INCL_ANY
\
+   (_DPRINTK_FLAGS_INCL_LINENO | _DPRINTK_FLAGS_INCL_TID | \
+_DPRINTK_FLAGS_INCL_LOOKUP)
 
 #if defined DEBUG
 #define _DPRINTK_FLAGS_DEFAULT _DPRINTK_FLAGS_PRINT
-- 
2.41.0



[PATCH v7c 21/24] dyndbg: change WARN_ON to WARN_ON_ONCE

2023-10-18 Thread Jim Cromie
This shouldn't ever happen, and 1st 2 conditions never have.

The 3rd condition did happen, due to corrupt linkage due to a missing
align(8) in DYNDBG_CLASSMAP_USE, on the static struct allocation into
the __dyndbg_class_users section.

Not sure whether changing to _ONCE is appropriate - this is a
module-load activity, so it won't continuously spam syslog.

Signed-off-by: Jim Cromie 
---
undo BUG_ON addition
---
 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 9db797a0cf82..213110ec1e9c 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -1281,7 +1281,7 @@ static void ddebug_attach_user_module_classes(struct 
ddebug_table *dt,
 */
for (i = 0, cli = di->class_users; i < di->num_class_users; i++, cli++) 
{
 
-   if (WARN_ON(!cli || !cli->map || !cli->user_mod_name))
+   if (WARN_ON_ONCE(!cli || !cli->map || !cli->user_mod_name))
continue;
 
if (!strcmp(cli->user_mod_name, dt->mod_name)) {
-- 
2.41.0



[PATCH v7c 22/24] drm: use correct ccflags-y spelling

2023-10-18 Thread Jim Cromie
Incorrectly spelled CFLAGS- failed to add -DDYNAMIC_DEBUG_MODULE,
which broke builds with:

CONFIG_DRM_USE_DYNAMIC_DEBUG=y
CONFIG_DYNAMIC_DEBUG_CORE=y
CONFIG_DYNAMIC_DEBUG=n

Also add subdir-ccflags so that all drivers pick up the addition.

Fixes: 84ec67288c10 ("drm_print: wrap drm_*_dbg in dyndbg descriptor factory 
macro")
Signed-off-by: Jim Cromie 
---
 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 215e78e79125..22b1984cc982 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
 
 drm-y := \
drm_aperture.o \
-- 
2.41.0



[PATCH v7c 13/24] dyndbg-API: remove DD_CLASS_TYPE_(DISJOINT|LEVEL)_NAMES and code

2023-10-18 Thread Jim Cromie
Remove the NAMED class types; 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 simplify things for now.

Signed-off-by: Jim Cromie 
---
 include/linux/dynamic_debug.h |  19 ++-
 lib/dynamic_debug.c   | 103 +++---
 lib/test_dynamic_debug.c  |  26 -
 3 files changed, 12 insertions(+), 136 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 8116d0a0d33a..8eaf8eabdc8d 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -61,24 +61,13 @@ struct _ddebug {
 enum 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
 */
 };
 
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 45870a699507..91c8b67fd8f8 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -632,77 +632,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(instr, GFP_KERNEL);
-   p = strchr(cl_str, '\n');
-   if (p)
-   *p = '\0';
-
-   /* 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);
- 

[PATCH v7c 11/24] dyndbg: tighten fn-sig of ddebug_apply_class_bitmap

2023-10-18 Thread Jim Cromie
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.

Signed-off-by: Jim Cromie 
---
 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 8158943b350d..8beb98a831f5 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -593,7 +593,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
@@ -602,12 +603,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],
@@ -619,9 +620,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;
 }
@@ -678,7 +679,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]);
@@ -688,7 +689,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);
@@ -742,7 +743,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, modnm ?: "*", 
KP_NAME(kp));
-   totct += ddebug_apply_class_bitmap(dcp, &inrep, dcp->bits, 
modnm);
+   totct += ddebug_apply_class_bitmap(dcp, &inrep, *dcp->bits, 
modnm);
*dcp->bits = inrep;
break;
case DD_CLASS_TYPE_LEVEL_NUM:
@@ -755,7 +756,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, 
modnm);
+   totct += ddebug_apply_class_bitmap(dcp, &new_bits, old_bits, 
modnm);
*dcp->lvl = inrep;
break;
default:
-- 
2.41.0



[PATCH v7c 20/24] dyndbg: refactor *dynamic_emit_prefix

2023-10-18 Thread Jim Cromie
Refactor the split of duties between outer & inner fns.

The outer fn was previously just an inline unlikely forward to inner,
which did all the work.

Now, outer handles +t and +l flags itself, and calls inner only when
_DPRINTK_FLAGS_INCL_LOOKUP is needed.

No functional change.

But it does make the results of the inner-fn more cache-friendly
(fewer entries, reused more often):

1- no spurious [TID] or  noise
2- no LINE-number to bloat the cache (avg 9 pr_debugs/fn)
3- only LOOKUP stuff

Currently LOOKUPs are descriptor-field refs but could be replaced by
accessor functions.  This would allow the __dyndbg_sites section to be
de-duplicated and reclaimed; currently module, filename fields are
~90% repeated.  As the accessors get more expensive, the value of
caching part of the prefix goes up.

Also change inner-fn to return count of extra chars written to the
buffer, and drop "inline" from outer, let the compiler decide.  Maybe
also change name accordingly.

Signed-off-by: Jim Cromie 
---
fixup whitespace
---
 lib/dynamic_debug.c | 39 ++-
 1 file changed, 22 insertions(+), 17 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index a6ee142668bf..9db797a0cf82 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -774,11 +774,28 @@ static int remaining(int wrote)
return 0;
 }
 
-static char *__dynamic_emit_prefix(const struct _ddebug *desc, char *buf)
+static int __dynamic_emit_prefix(const struct _ddebug *desc, char *buf, int 
pos)
+{
+   if (desc->flags & _DPRINTK_FLAGS_INCL_MODNAME)
+   pos += snprintf(buf + pos, remaining(pos), "%s:",
+   desc->modname);
+   if (desc->flags & _DPRINTK_FLAGS_INCL_FUNCNAME)
+   pos += snprintf(buf + pos, remaining(pos), "%s:",
+   desc->function);
+   if (desc->flags & _DPRINTK_FLAGS_INCL_SOURCENAME)
+   pos += snprintf(buf + pos, remaining(pos), "%s:",
+   trim_prefix(desc->filename));
+   return pos;
+}
+
+static char *dynamic_emit_prefix(struct _ddebug *desc, char *buf)
 {
int pos_after_tid;
int pos = 0;
 
+   if (likely(!(desc->flags & _DPRINTK_FLAGS_INCL_ANY)))
+   return buf;
+
if (desc->flags & _DPRINTK_FLAGS_INCL_TID) {
if (in_interrupt())
pos += snprintf(buf + pos, remaining(pos), " ");
@@ -787,15 +804,10 @@ static char *__dynamic_emit_prefix(const struct _ddebug 
*desc, char *buf)
task_pid_vnr(current));
}
pos_after_tid = pos;
-   if (desc->flags & _DPRINTK_FLAGS_INCL_MODNAME)
-   pos += snprintf(buf + pos, remaining(pos), "%s:",
-   desc->modname);
-   if (desc->flags & _DPRINTK_FLAGS_INCL_FUNCNAME)
-   pos += snprintf(buf + pos, remaining(pos), "%s:",
-   desc->function);
-   if (desc->flags & _DPRINTK_FLAGS_INCL_SOURCENAME)
-   pos += snprintf(buf + pos, remaining(pos), "%s:",
-   trim_prefix(desc->filename));
+
+   if (unlikely(desc->flags & _DPRINTK_FLAGS_INCL_LOOKUP))
+   pos += __dynamic_emit_prefix(desc, buf, pos);
+
if (desc->flags & _DPRINTK_FLAGS_INCL_LINENO)
pos += snprintf(buf + pos, remaining(pos), "%d:",
desc->lineno);
@@ -807,13 +819,6 @@ static char *__dynamic_emit_prefix(const struct _ddebug 
*desc, char *buf)
return buf;
 }
 
-static inline char *dynamic_emit_prefix(struct _ddebug *desc, char *buf)
-{
-   if (unlikely(desc->flags & _DPRINTK_FLAGS_INCL_ANY))
-   return __dynamic_emit_prefix(desc, buf);
-   return buf;
-}
-
 void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...)
 {
va_list args;
-- 
2.41.0



[PATCH v7c 17/24] dyndbg-doc: add classmap info to howto

2023-10-18 Thread Jim Cromie
Add some basic info on classmap usage and api

cc: linux-...@vger.kernel.org
Signed-off-by: Jim Cromie 
---
v5- adjustments per Randy Dunlap, me
v7b- checkpatch fixes
---
 .../admin-guide/dynamic-debug-howto.rst   | 60 ++-
 1 file changed, 59 insertions(+), 1 deletion(-)

diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst 
b/Documentation/admin-guide/dynamic-debug-howto.rst
index 0b3d39c610d9..028c2cb5b4c5 100644
--- a/Documentation/admin-guide/dynamic-debug-howto.rst
+++ b/Documentation/admin-guide/dynamic-debug-howto.rst
@@ -225,7 +225,6 @@ the ``p`` flag has meaning, other flags are ignored.
 Note the regexp ``^[-+=][fslmpt_]+$`` matches a flags specification.
 To clear all flags at once, use ``=_`` or ``-fslmpt``.
 
-
 Debug messages during Boot Process
 ==
 
@@ -375,3 +374,62 @@ 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.
+
+Dynamic Debug classmaps
+===
+
+Dyndbg allows selection/grouping of *prdbg* callsites using structural
+info: module, file, function, line.  Classmaps allow authors to add
+their own domain-oriented groupings using class-names.  Classmaps are
+exported, so they referencable from other modules.
+
+  # enable classes individually
+  :#> ddcmd class DRM_UT_CORE +p
+  :#> ddcmd class DRM_UT_KMS +p
+  # or more selectively
+  :#> ddcmd class DRM_UT_CORE module drm +p
+
+The "class FOO" syntax protects class'd prdbgs from generic overwrite::
+
+  # IOW this doesn't wipe any DRM.debug settings
+  :#> ddcmd -p
+
+To support the DRM.debug parameter, DYNDBG_CLASSMAP_PARAM* updates all
+classes in a classmap, mapping param-bits 0..N onto the classes:
+DRM_UT_<*> for the DRM use-case.
+
+Dynamic Debug Classmap API
+==
+
+DYNDBG_CLASSMAP_DEFINE - modules use this to create classmaps, naming
+each of the classes (stringified enum-symbols: "DRM_UT_<*>"), and
+type, and mapping the class-names to consecutive _class_ids.
+
+By doing so, modules tell dyndbg that they are have prdbgs with those
+class_ids, and they authorize dyndbg to accept "class FOO" for the
+module defining that classname.
+
+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)
+
+DYNDBG_CLASSMAP_PARAM - refers to a DEFINEd classmap, exposing the set
+of defined classes to manipulation as a group.  This interface
+enforces the relatedness of classes of DD_CLASS_TYPE_LEVEL_NUM typed
+classmaps; all classes are independent in the >control parser itself.
+
+DYNDBG_CLASSMAP_USE - drm drivers invoke this to ref the CLASSMAP that
+drm DEFINEs.  This shares the classmap definition, and authorizes
+dyndbg to apply changes to the user module's class'd pr_debugs.  It
+also tells dyndbg how to initialize the user's prdbgs at modprobe,
+based upon the current setting of the parent's controlling param.
+
+Modules or module-groups (drm & drivers) can define multiple
+classmaps, as long as they share the limited 0..62 per-module-group
+_class_id range, without overlap.
+
+``#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 pr_debug callsites can be toggled into agreement with the
+param.
-- 
2.41.0



[PATCH v7c 15/24] dyndbg: refactor ddebug_classparam_clamp_input

2023-10-18 Thread Jim Cromie
Extract input validation code, from param_set_dyndbg_module_classes()
(the sys-node >handler) to new: ddebug_classparam_clamp_input(kp),
call it from former.  It takes kernel-param arg, so it can complain
about "foo: bad input".

Reuse ddparam_clamp_input(kp) in ddebug_sync_classbits(),
to validate inputs from parent's params, just like our own.
To support that reuse, alter ddebug_sync_classbits() and caller to
pass kp instead of kp->arg.

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 70 ++---
 1 file changed, 47 insertions(+), 23 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index c9517d403e06..a6ee142668bf 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -653,6 +653,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 *modnm)
@@ -671,26 +695,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, modnm ?: "*", 
KP_NAME(kp));
totct += ddebug_apply_class_bitmap(dcp, &inrep, *dcp->bits, 
modnm);
*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));
@@ -1157,16 +1170,27 @@ static const char * const ddebug_classmap_typenames[] = 
{
  ddebug_classmap_typenames[_cm->map_type]);\
})
 
-static void ddebug_sync_classbits(const struct ddebug_class_param *dcp, const 
char *modname)
+static void ddebug_sync_classbits(const struct kernel_param *kp, const char 
*modname)
 {
-   /* 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);
+   struct ddebug_class_param *dcp = kp->arg;
+   unsigned long new_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_TY

[PATCH v7c 24/24] drm: restore CONFIG_DRM_USE_DYNAMIC_DEBUG un-BROKEN

2023-10-18 Thread Jim Cromie
Lots of burn-in testing needed before signing, upstreaming.

NOTE: I set default Y to maximize testing by default.
Is there a better way to do this ?

Signed-off-by: Jim Cromie 
---
 drivers/gpu/drm/Kconfig | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 3caa020391c7..708f5e8cb205 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -55,8 +55,7 @@ config DRM_DEBUG_MM
 
 config DRM_USE_DYNAMIC_DEBUG
bool "use dynamic debug to implement drm.debug"
-   default n
-   depends on BROKEN
+   default y
depends on DRM
depends on DYNAMIC_DEBUG || DYNAMIC_DEBUG_CORE
depends on JUMP_LABEL
-- 
2.41.0



[PATCH v7c 23/24] drm-drivers: DRM_CLASSMAP_USE in 2nd batch of drivers, helpers

2023-10-18 Thread Jim Cromie
Add a DRM_CLASSMAP_USE declaration to 2nd batch of helpers and *_drv.c
files.  For drivers, add the decl just above the module's PARAMs,
since it identifies the "inherited" drm.debug param.

Note: with CONFIG_DRM_USE_DYNAMIC_DEBUG=y, a module not also declaring
DRM_CLASSMAP_USE will have its class'd prdbgs stuck in the initial
(disabled, but for DEBUG) state.

The stuck sites are evident in /proc/dynamic_debug/control as:

   class:_UNKNOWN_ _id:N# control's last column

rather than a proper "enumeration":

   class:DRM_UT_CORE

This set of updates was found by choosing M for all DRM-config items I
found (not allmodconfig), building & modprobing them, and grepping
"class unknown," control.  There may yet be others.

Signed-off-by: Jim Cromie 
---
 drivers/gpu/drm/drm_gem_shmem_helper.c | 2 ++
 drivers/gpu/drm/gud/gud_drv.c  | 2 ++
 drivers/gpu/drm/mgag200/mgag200_drv.c  | 2 ++
 drivers/gpu/drm/qxl/qxl_drv.c  | 2 ++
 drivers/gpu/drm/radeon/radeon_drv.c| 2 ++
 drivers/gpu/drm/udl/udl_main.c | 2 ++
 drivers/gpu/drm/vkms/vkms_drv.c| 2 ++
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c| 2 ++
 8 files changed, 16 insertions(+)

diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c 
b/drivers/gpu/drm/drm_gem_shmem_helper.c
index e435f986cd13..066d906e3199 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -23,6 +23,8 @@
 #include 
 #include 
 
+DRM_CLASSMAP_USE(drm_debug_classes);
+
 MODULE_IMPORT_NS(DMA_BUF);
 
 /**
diff --git a/drivers/gpu/drm/gud/gud_drv.c b/drivers/gpu/drm/gud/gud_drv.c
index 9d7bf8ee45f1..5b555045fce4 100644
--- a/drivers/gpu/drm/gud/gud_drv.c
+++ b/drivers/gpu/drm/gud/gud_drv.c
@@ -31,6 +31,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,
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c 
b/drivers/gpu/drm/mgag200/mgag200_drv.c
index abddf37f0ea1..d678eb8e028d 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.c
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.c
@@ -24,6 +24,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;
diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c
index b30ede1cf62d..91942ffcc2b4 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.c
+++ b/drivers/gpu/drm/qxl/qxl_drv.c
@@ -65,6 +65,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;
 
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c 
b/drivers/gpu/drm/radeon/radeon_drv.c
index fa531493b111..ab29945af657 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -247,6 +247,8 @@ int radeon_cik_support = 1;
 MODULE_PARM_DESC(cik_support, "CIK support (1 = enabled (default), 0 = 
disabled)");
 module_param_named(cik_support, radeon_cik_support, int, 0444);
 
+DRM_CLASSMAP_USE(drm_debug_classes);
+
 static struct pci_device_id pciidlist[] = {
radeon_PCI_IDS
 };
diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c
index 3ebe2ce55dfd..ba57c14454e5 100644
--- a/drivers/gpu/drm/udl/udl_main.c
+++ b/drivers/gpu/drm/udl/udl_main.c
@@ -19,6 +19,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
diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c
index dd0af086e7fa..086797c4b82b 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.c
+++ b/drivers/gpu/drm/vkms/vkms_drv.c
@@ -39,6 +39,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");
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 8b24ecf60e3e..9cb6be422621 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -275,6 +275,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_iom

[PATCH v7d 00/23] fix DRM_USE_DYNAMIC_DEBUG=y regression

2023-10-31 Thread Jim Cromie
hi Jason, DRM-folk

(v7d - refreshed onto v6.6, patch-21 squashed into 14)

This patchest fixes the chicken-egg initialization problem in the 1st
version of ddebug-class-maps, that DRM-CI uncovered.

The root-problem was DECLARE_DYNDBG_CLASSMAP, which broke the K&R rule:
"define once, refer many".  In patch 14 it is replaced by:

 DYNDBG_CLASSMAP_DEFINE - define and export a struct ddebug_class_map
 DYNDBG_CLASSMAP_USE - ref the exported struct

test-dynamic-debug is also extended with a -submod.ko, in order to
recapitulate the drm & drivers initialization scenario.

The final blocking bug was a missing __align(8) on the ddebug_class_user
record inserted by DYNDBG_CLASSMAP_USE.  This caused DRM=y (builtin
only) to have a corrupt record for drm_kms_helper (a builtin dependent).
Curiously, a clang build did not exhibit this problem.

Heres a part of dmesg, for a DRM=y kernel, booted with
 dynamic_debug.verbose=3 drm.debug=0x10

[0.466747] dyndbg: add-module: drm 406 sites
[0.467569] dyndbg: classes[0]: module:drm base:0 len:10 type:DISJOINT_BITS
[0.467743] dyndbg: module:drm attached 1 classes
[0.468557] dyndbg: builtin class: module:drm base:0 len:10 
type:DISJOINT_BITS
[0.468742] dyndbg:  found kp:drm.debug =0x10
[0.468743] dyndbg:   mapped to: module:drm base:0 len:10 type:DISJOINT_BITS
[0.469742] dyndbg:   drm.debug: classbits: 0x10
[0.470573] dyndbg: apply bitmap: 0x10 to: 0x0 for drm
[0.470743] dyndbg: query 0: "class DRM_UT_ATOMIC +p" mod:drm
[0.471743] dyndbg: split into words: "class" "DRM_UT_ATOMIC" "+p"
[0.472743] dyndbg: op='+' flags=0x1 maskp=0x
[0.473679] dyndbg: parsed: func="" file="" module="drm" format="" 
lineno=0-0 class=DRM_UT_ATOMIC
[0.473749] dyndbg: processed 1 queries, with 0 matches, 0 errs
[0.474742] dyndbg: bit_4: 0 matches on class: DRM_UT_ATOMIC -> 0x10
[0.475742] dyndbg: applied bitmap: 0x10 to: 0x0 for drm
[0.476686] dyndbg: 406 debug prints in module drm
[0.476743] dyndbg: add-module: drm_kms_helper 93 sites
[0.477727] dyndbg: class_ref[0] drm_kms_helper -> drm module:drm base:0 
len:10 type:DISJOINT_BITS
[0.477743] dyndbg: builtin class: module:drm base:0 len:10 
type:DISJOINT_BITS
[0.478742] dyndbg:  found kp:drm.debug =0x10
[0.478743] dyndbg:   mapped to: module:drm base:0 len:10 type:DISJOINT_BITS
[0.479743] dyndbg:   drm.debug: classbits: 0x10
[0.480592] dyndbg: apply bitmap: 0x10 to: 0x0 for drm_kms_helper
[0.480743] dyndbg: query 0: "class DRM_UT_ATOMIC +p" mod:drm_kms_helper
[0.481743] dyndbg: split into words: "class" "DRM_UT_ATOMIC" "+p"
[0.482743] dyndbg: op='+' flags=0x1 maskp=0x
[0.483743] dyndbg: parsed: func="" file="" module="drm_kms_helper" 
format="" lineno=0-0 class=DRM_UT_ATOMIC
[0.484750] dyndbg: class-ref: drm_kms_helper.DRM_UT_ATOMIC  
module:drm_kms_helper nd:93 nc:0 nu:1
[0.485809] dyndbg: processed 1 queries, with 44 matches, 0 errs
[0.486742] dyndbg: bit_4: 44 matches on class: DRM_UT_ATOMIC -> 0x10
[0.487742] dyndbg: applied bitmap: 0x10 to: 0x0 for drm_kms_helper
[0.488743] dyndbg: attach-client-module:  module:drm_kms_helper nd:93 nc:0 
nu:1
[0.489742] dyndbg:  93 debug prints in module drm_kms_helper

Id like to get this into linux-next, so widespread testing is appreciated.
lkp-robot reported BUILD SUCCESS on it, Im running it on my amdgpu desktop.
I have scripts to operate the test-module if anyone wants them.

Patches are also at https://github.com/jimc/linux/tree/dd-fix-7d


Jim Cromie (23):
  test-dyndbg: fixup CLASSMAP usage error
  dyndbg: reword "class unknown," to "class:_UNKNOWN_"
  dyndbg: make ddebug_class_param union members same size
  dyndbg: replace classmap list with a vector
  dyndbg: ddebug_apply_class_bitmap - add module arg, select on it
  dyndbg: split param_set_dyndbg_classes to module/wrapper fns
  dyndbg: drop NUM_TYPE_ARRAY
  dyndbg: reduce verbose/debug clutter
  dyndbg: silence debugs with no-change updates
  dyndbg: tighten ddebug_class_name() 1st arg type
  dyndbg: tighten fn-sig of ddebug_apply_class_bitmap
  dyndbg: reduce verbose=3 messages in ddebug_add_module
  dyndbg-API: remove DD_CLASS_TYPE_(DISJOINT|LEVEL)_NAMES and code
  dyndbg-API: fix CONFIG_DRM_USE_DYNAMIC_DEBUG regression
  dyndbg: refactor ddebug_classparam_clamp_input
  dyndbg-API: promote DYNDBG_CLASSMAP_PARAM to API
  dyndbg-doc: add classmap info to howto
  dyndbg: reserve flag bit _DPRINTK_FLAGS_PREFIX_CACHED
  dyndbg: add _DPRINTK_FLAGS_INCL_LOOKUP
  dyndbg: refactor *dynamic_emit_prefix
  drm: use correct ccflags-y spelling
  drm-drivers: DRM_CLASSMAP_USE in 2nd batch of drivers, helpers
  drm: restore CONFIG_DRM_USE_DYNAMIC_DEBUG un-BROKEN

 .../admin-guide/dynamic-

[PATCH v7d 01/23] test-dyndbg: fixup CLASSMAP usage error

2023-10-31 Thread Jim Cromie
more careful reading of test output reveals:

lib/test_dynamic_debug.c:103 [test_dynamic_debug]do_cats =pmf "doing 
categories\n"
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

That last line is wrong, the HI class is declared.

But the enum's 1st val (explicitly initialized) was wrong; it must be
_base, not _base+1 (a DECLARE_DYNDBG_CLASSMAP[1] param).  So the last
enumeration exceeded the range of mapped class-id's, which triggered
the "class unknown" report.  I intentionally coded in an error, but
forgot to verify its detection and remove it.

RFC:

This patch fixes a bad usage of DECLARE_DYNDBG_CLASSMAP(), showing
that it is too error-prone.  As noted in test-mod comments:

 * 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-62 class_id space !!
 *   (build-bug-on tips welcome)

Those shortcomings could largely be fixed with a __stringify_list
(which doesn't exist,) used in DECLARE_DYNDBG_CLASSMAP to stringify
__VA_ARGS__.  Then, API would accept DRM_UT_* values literally; all
the categories, in order, and not their stringifications, which
created all the usage complications above.

[1] name changes later to DYNDBG_CLASSMAP_DEFINE

Signed-off-by: Jim Cromie 
---
 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 8dd250ad022b..a01f0193a419 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.41.0



[PATCH v7d 02/23] dyndbg: reword "class unknown, " to "class:_UNKNOWN_"

2023-10-31 Thread Jim Cromie
This appears in the control-file to report an unknown class-name, which
indicates that the class_id is not authorized, and dyndbg will ignore
changes to it.  Generally, this means that a DYNDBG_CLASSMAP_DEFINE or
DYNDBG_CLASSMAP_USE is missing.

But the word "unknown" appears in quite a few prdbg formats, so thats
a suboptimal search term to find occurrences of the problem.  Thus
change it to "_UNKNOWN_" which properly shouts the condition.

Signed-off-by: Jim Cromie 
---
 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 6fba6423cc10..ceb3067a5c83 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -1151,7 +1151,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_puts(m, "\n");
 
-- 
2.41.0



[PATCH v7d 04/23] dyndbg: replace classmap list with a vector

2023-10-31 Thread Jim Cromie
Classmaps are stored/linked in a section/array, but are each added to
the module's ddebug_table.maps list-head.

This is unnecessary; even when ddebug_attach_classmap() is handling
the builtin section (with classmaps for multiple builtin modules), its
contents are ordered, so a module's possibly multiple classmaps will
be consecutive in the section, and could be treated as a vector/block,
since both start-addy and subrange length are in the ddebug_info arg.

So this changes:

struct ddebug_class_map drops list-head link.

struct ddebug_table drops the list-head maps, and gets: classes &
num_classes for the start-addy and num_classes, placed to improve
struct packing.

The loading: in ddebug_attach_module_classes(), replace the
for-the-modname list-add loop, with a forloop that finds the module's
subrange (start,length) of matching classmaps within the possibly
builtin classmaps vector, and saves those to the ddebug_table.

The reading/using: change list-foreach loops in ddebug_class_name() &
ddebug_find_valid_class() to walk the array from start to length.

Also:
Move #define __outvar up, above an added use in a fn-prototype.
Simplify ddebug_attach_module_classes args, ref has both addy,len.

no functional changes

Signed-off-by: Jim Cromie 
---
 include/linux/dynamic_debug.h |  1 -
 lib/dynamic_debug.c   | 61 ++-
 2 files changed, 32 insertions(+), 30 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 5231aaf361c4..b53217e4b711 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -83,7 +83,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 b984ce338921..a3be2e7c8c84 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 {
@@ -147,13 +148,15 @@ static void vpr_info_dq(const struct ddebug_query *query, 
const char *msg)
  query->first_lineno, query->last_lineno, query->class_string);
 }
 
+#define __outvar /* filled by callee */
 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,
+   __outvar 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;
@@ -164,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
@@ -,9 +1113,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];
 
@@ -1197,30 +1200,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

[PATCH v7d 03/23] dyndbg: make ddebug_class_param union members same size

2023-10-31 Thread Jim Cromie
struct ddebug_class_param keeps a ref to the state-storage of the
param, make both flavors use the same unsigned long under-type.
ISTM this is simpler and safer.

Signed-off-by: Jim Cromie 
---
 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 4fcbf4d4fd0a..5231aaf361c4 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -124,7 +124,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 ceb3067a5c83..b984ce338921 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -796,7 +796,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.41.0



[PATCH v7d 05/23] dyndbg: ddebug_apply_class_bitmap - add module arg, select on it

2023-10-31 Thread Jim Cromie
Add query_module param to ddebug_apply_class_bitmap().  This allows
its caller to update just one module, or all (as currently).  We'll
use this later to propagate drm.debug to each USEr as they're
modprobed.

No functional change.

Signed-off-by: Jim Cromie 
---

after `modprobe i915`, heres the module dependencies,
though not all on drm.debug.

bash-5.2# lsmod
Module  Size  Used by
i915 3133440  0
drm_buddy  20480  1 i915
ttm90112  1 i915
i2c_algo_bit   16384  1 i915
video  61440  1 i915
wmi32768  1 video
drm_display_helper200704  1 i915
drm_kms_helper208896  2 drm_display_helper,i915
drm   606208  5 
drm_kms_helper,drm_display_helper,drm_buddy,i915,ttm
cec57344  2 drm_display_helper,i915
---
 lib/dynamic_debug.c | 19 ---
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index a3be2e7c8c84..ba41fdeaaf98 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -601,7 +601,8 @@ static int ddebug_exec_queries(char *query, const char 
*modname)
 
 /* apply a new bitmap to the sys-knob's current bit-state */
 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];
@@ -609,7 +610,8 @@ 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);
+   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))
@@ -618,12 +620,15 @@ 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);
}
+   v2pr_info("applied bitmap: 0x%lx to: 0x%lx for %s\n", *new_bits, 
*old_bits,
+ query_modname ?: "");
+
return matches;
 }
 
@@ -679,7 +684,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]);
@@ -689,7 +694,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);
@@ -752,7 +757,7 @@ int param_set_dyndbg_classes(const char *instr, const 
struct kernel_param *kp)
inrep &= CLASSMAP_BITMASK(map->length);
}
v2pr_info("bits:%lx > %s\n", inrep, KP_NAME(kp));
-   totct += ddebug_apply_class_bitmap(dcp, &inrep, dcp->bits);
+   totct += ddebug_apply_class_bitmap(dcp, &inrep, dcp->bits, 
NULL);
*dcp->bits = inrep;
break;
case DD_CLASS_TYPE_LEVEL_NUM:
@@ -765,7 +770,7 @@ int param_set_dyndbg_classes(const char *instr, const 
struct kernel_param *kp)
old_bits = CLASSMAP_BITMASK(*dcp->lvl)

[PATCH v7d 07/23] dyndbg: drop NUM_TYPE_ARRAY

2023-10-31 Thread Jim Cromie
ARRAY_SIZE works here, since array decl is complete.

no functional change

Signed-off-by: Jim Cromie 
---
 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 b53217e4b711..8116d0a0d33a 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -106,11 +106,9 @@ struct ddebug_class_map {
.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))
 
 /* encapsulate linker provided built-in (or module) dyndbg data */
 struct _ddebug_info {
-- 
2.41.0



[PATCH v7d 06/23] dyndbg: split param_set_dyndbg_classes to module/wrapper fns

2023-10-31 Thread Jim Cromie
rename param_set_dyndbg_classes: add _module_ name & arg, old name is
wrapper to new.  New arg allows caller to specify that only one module
is affected by a prdbgs update.

Outer fn preserves kernel_param interface, passing NULL to inner fn.
This selectivity will be used later to narrow the scope of changes
made.

no functional change.

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 37 ++---
 1 file changed, 22 insertions(+), 15 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index ba41fdeaaf98..b67c9b137447 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -708,18 +708,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 *modnm)
 {
const struct ddebug_class_param *dcp = kp->arg;
const struct ddebug_class_map *map = dcp->map;
@@ -756,8 +747,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, 
NULL);
+   v2pr_info("bits:0x%lx > %s.%s\n", inrep, modnm ?: "*", 
KP_NAME(kp));
+   totct += ddebug_apply_class_bitmap(dcp, &inrep, dcp->bits, 
modnm);
*dcp->bits = inrep;
break;
case DD_CLASS_TYPE_LEVEL_NUM:
@@ -770,7 +761,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, 
NULL);
+   totct += ddebug_apply_class_bitmap(dcp, &new_bits, &old_bits, 
modnm);
*dcp->lvl = inrep;
break;
default:
@@ -779,6 +770,22 @@ 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 - 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)
+{
+   return param_set_dyndbg_module_classes(instr, kp, NULL);
+}
 EXPORT_SYMBOL(param_set_dyndbg_classes);
 
 /**
-- 
2.41.0



[PATCH v7d 08/23] dyndbg: reduce verbose/debug clutter

2023-10-31 Thread Jim Cromie
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=0x

 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 is like 1st, with result, not procedure.
   2nd is just status, retold in 4th, with more info.

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 14 +++---
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index b67c9b137447..b0e11f6bfaa2 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -266,9 +266,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;
 }
 
@@ -497,7 +494,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--) {
@@ -511,7 +507,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) {
@@ -527,7 +522,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;
 }
@@ -537,7 +532,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);
@@ -555,10 +550,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
-- 
2.41.0



[PATCH v7d 09/23] dyndbg: silence debugs with no-change updates

2023-10-31 Thread Jim Cromie
check for actual changes before announcing them, declutter logs.

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index b0e11f6bfaa2..b07aab422604 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -591,7 +591,7 @@ 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,
 const char *query_modname)
@@ -602,8 +602,9 @@ static int ddebug_apply_class_bitmap(const struct 
ddebug_class_param *dcp,
int matches = 0;
int bi, ct;
 
-   v2pr_info("apply bitmap: 0x%lx to: 0x%lx for %s\n", *new_bits, 
*old_bits,
- query_modname ?: "");
+   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))
@@ -618,8 +619,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);
}
-   v2pr_info("applied bitmap: 0x%lx to: 0x%lx for %s\n", *new_bits, 
*old_bits,
- query_modname ?: "");
+   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;
 }
-- 
2.41.0



[PATCH v7d 10/23] dyndbg: tighten ddebug_class_name() 1st arg type

2023-10-31 Thread Jim Cromie
Change function's 1st arg-type, and deref in the caller.
The fn doesn't need any other fields in the struct.

no functional change.

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index b07aab422604..8158943b350d 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -1117,12 +1117,12 @@ static void *ddebug_proc_next(struct seq_file *m, void 
*p, loff_t *pos)
 #define class_in_range(class_id, map)  \
(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 = dt->classes;
+   int i;
 
-   for (i = 0; i < nc; i++, map++)
+   for (i = 0; i < dt->num_classes; i++, map++)
if (class_in_range(dp->class_id, map))
return map->class_names[dp->class_id - map->base];
 
@@ -1156,7 +1156,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
seq_puts(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
-- 
2.41.0



[PATCH v7d 13/23] dyndbg-API: remove DD_CLASS_TYPE_(DISJOINT|LEVEL)_NAMES and code

2023-10-31 Thread Jim Cromie
Remove the NAMED class types; 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 simplify things for now.

Signed-off-by: Jim Cromie 
---
 include/linux/dynamic_debug.h |  19 ++-
 lib/dynamic_debug.c   | 103 +++---
 lib/test_dynamic_debug.c  |  26 -
 3 files changed, 12 insertions(+), 136 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 8116d0a0d33a..8eaf8eabdc8d 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -61,24 +61,13 @@ struct _ddebug {
 enum 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
 */
 };
 
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 45870a699507..91c8b67fd8f8 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -632,77 +632,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(instr, GFP_KERNEL);
-   p = strchr(cl_str, '\n');
-   if (p)
-   *p = '\0';
-
-   /* 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);
- 

[PATCH v7d 12/23] dyndbg: reduce verbose=3 messages in ddebug_add_module

2023-10-31 Thread Jim Cromie
The fn currently says "add-module", then "skipping" if the module has
no prdbgs.  Just check 1st and return quietly.

no functional change

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 8beb98a831f5..45870a699507 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -1242,11 +1242,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(sizeof(*dt), GFP_KERNEL);
if (dt == NULL) {
-- 
2.41.0



[PATCH v7d 11/23] dyndbg: tighten fn-sig of ddebug_apply_class_bitmap

2023-10-31 Thread Jim Cromie
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.

Signed-off-by: Jim Cromie 
---
 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 8158943b350d..8beb98a831f5 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -593,7 +593,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
@@ -602,12 +603,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],
@@ -619,9 +620,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;
 }
@@ -678,7 +679,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]);
@@ -688,7 +689,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);
@@ -742,7 +743,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, modnm ?: "*", 
KP_NAME(kp));
-   totct += ddebug_apply_class_bitmap(dcp, &inrep, dcp->bits, 
modnm);
+   totct += ddebug_apply_class_bitmap(dcp, &inrep, *dcp->bits, 
modnm);
*dcp->bits = inrep;
break;
case DD_CLASS_TYPE_LEVEL_NUM:
@@ -755,7 +756,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, 
modnm);
+   totct += ddebug_apply_class_bitmap(dcp, &new_bits, old_bits, 
modnm);
*dcp->lvl = inrep;
break;
default:
-- 
2.41.0



[PATCH v7d 14/23] dyndbg-API: fix CONFIG_DRM_USE_DYNAMIC_DEBUG regression

2023-10-31 Thread Jim Cromie
 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, with the new ifdef _SUBMOD block invoking DYNDBG_CLASSMAP_USE
for the 2 test-interfaces.  I think this is clearer.

These 2 modules are independently configurable, allowing builtin
parent and loadable submod, which recapitulates a troublesome build
combo for drm & drivers.

DEBUG details:

``#define DEBUG`` in src enables all pr_debugs after it, including any
class'd pr_debugs; its not necessarily all-or-nothing, unless its a
one-file-module with DEBUG at the top.

If a CLASSMAP_PARAM is defined on a classmap, its readback value
cannot describe the set of enablements.  The param is basically
write-only; it cannot know if `echo $cmd >control` was done since.

To know the exact pr-debug state with certainty, toggle to both:

   echo 0x3ff > /sys/module/drm/parameters/debug
   echo 0 > /sys/module/drm/parameters/debug

Cc: Daniel Vetter 
Cc: Jani Nikula 
Cc: Tvrtko Ursulin 
Cc: Rob Clark 
Cc: Sean Paul 
Cc: Luis Chamberlain 
Fixes: aad0214f3026 ("dyndbg: add DECLARE_DYNDBG_CLASSMAP macro")
Fixes: f158936b60a7 ("drm: POC drm on dyndbg - use in core, 2 helpers, 3 
drivers.")
Ref: commit bb2ff6c27bc9 ("drm: Disable dynamic debug as broken")

Signed-off-by: Jim Cromie 
---
last submission-blocking bug:

missing __align(8) in DYNAMIC_DEBUG_DECLARE_METADATA on
ddebug_class_user caused corrupt records, but only for builtin
modules; module loader code probably pinned allocations to the right
alignment naturally, hiding the bug for typical builds.

v7e- squash patch 21 into 14 - WARN_ON_ONCE
v7d- fix _var expanded 2x in macro, by wrapping with ()
v6?- fix kconfig description too short
---
 MAINTAINERS |   2 +-
 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_print.c |  25 ++--
 drivers/gpu/drm/i915/i915_params.c  |  12 +-
 drivers/gpu/drm/nouveau/nouveau_drm.c   |  12 +-
 include/asm-generic/vmlinux.lds.h   |   1 +
 include/drm/drm_print.h |  10 +-
 include/linux/dynamic_debug.h   |  53 +--
 kernel/module/main.c|   3 +
 lib/Kconfig.debug   |  24 +++-
 lib/Makefile|   3 +
 lib/dynamic_debug.c | 183 +---
 lib/test_dynamic_debug.c| 111 +-
 lib/test_dynamic_debug_submod.c |  10 ++
 16 files changed, 344 insertions(+), 141 deletions(-)
 create mode 100644 lib/test_dynamic_debug_submod.c

diff --git a/MAINTAINERS b/MAINTAINERS
index dd5de540ec0b..2f8e5a79d982 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7321,7 +7321,7 @@ M:Jim Cromie 
 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
 
 DYNAMIC INTERRUPT MODERATION
 M: Tal Gilboa 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 81edf66dbea8..efba99c9393e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -197,17 +197,7 @@ int amdgpu_user_partt_mode = 
AMDGPU_AUTO_COMPUTE_PARTITION_MODE;
 
 static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work);
 
-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),
diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
b/drivers/gpu/drm/display/drm_dp_helper.c
index e6a78fd32380..d97de1a27939 100644
--- a/drivers/gpu/drm/display/drm_dp_helper.

[PATCH v7d 15/23] dyndbg: refactor ddebug_classparam_clamp_input

2023-10-31 Thread Jim Cromie
Extract input validation code, from param_set_dyndbg_module_classes()
(the sys-node >handler) to new: ddebug_classparam_clamp_input(kp),
call it from former.  It takes kernel-param arg, so it can complain
about "foo: bad input".

Reuse ddparam_clamp_input(kp) in ddebug_sync_classbits(),
to validate inputs from parent's params, just like our own.
To support that reuse, alter ddebug_sync_classbits() and caller to
pass kp instead of kp->arg.

Signed-off-by: Jim Cromie 
---
 lib/dynamic_debug.c | 70 ++---
 1 file changed, 47 insertions(+), 23 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 7d3261dede77..f878a6f09fc8 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -653,6 +653,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 *modnm)
@@ -671,26 +695,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, modnm ?: "*", 
KP_NAME(kp));
totct += ddebug_apply_class_bitmap(dcp, &inrep, *dcp->bits, 
modnm);
*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));
@@ -1157,16 +1170,27 @@ static const char * const ddebug_classmap_typenames[] = 
{
  ddebug_classmap_typenames[_cm->map_type]);\
})
 
-static void ddebug_sync_classbits(const struct ddebug_class_param *dcp, const 
char *modname)
+static void ddebug_sync_classbits(const struct kernel_param *kp, const char 
*modname)
 {
-   /* 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);
+   struct ddebug_class_param *dcp = kp->arg;
+   unsigned long new_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_TY

[PATCH v7d 18/23] dyndbg: reserve flag bit _DPRINTK_FLAGS_PREFIX_CACHED

2023-10-31 Thread Jim Cromie
Reserve bit 7 to remember that a pr-debug callsite is/was:
- enabled, with +p
- wants a dynamic-prefix, with one+ of module:function:sourcfile
- was previously called
- was thus saved in the cache. NOT YET.

Its unclear whether any cache fetch would be faster than 2-3 field
fetches, but theres another factor; the 3 columns in the __dyndbg
section are highly redundant and compressible, but to get the
compression, we need field accessors, which will rebalance the
tradeoff.

So, for now, its just the bit reservation.

Signed-off-by: Jim Cromie 
---
 include/linux/dynamic_debug.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 2a7832b1ba5b..4ffddf5e9152 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -38,6 +38,7 @@ struct _ddebug {
 #define _DPRINTK_FLAGS_INCL_LINENO (1<<3)
 #define _DPRINTK_FLAGS_INCL_TID(1<<4)
 #define _DPRINTK_FLAGS_INCL_SOURCENAME (1<<5)
+#define _DPRINTK_FLAGS_PREFIX_CACHED   (1<<7)
 
 #define _DPRINTK_FLAGS_INCL_ANY\
(_DPRINTK_FLAGS_INCL_MODNAME | _DPRINTK_FLAGS_INCL_FUNCNAME |\
-- 
2.41.0



[PATCH v7d 16/23] dyndbg-API: promote DYNDBG_CLASSMAP_PARAM to API

2023-10-31 Thread Jim Cromie
move the DYNDBG_CLASSMAP_PARAM macro from test-dynamic-debug.c into
the header, and refine it, by distinguishing the 2 use cases:

1.DYNDBG_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.DYNDBG_CLASSMAP_PARAM
new user (test_dynamic_debug) doesn't need to share state,
decls a static long unsigned int to store the bitvec.

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

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

Signed-off-by: Jim Cromie 
---
---
 drivers/gpu/drm/drm_print.c |  8 ++
 include/drm/drm_print.h |  6 ++--
 include/linux/dynamic_debug.h   | 37 +++-
 lib/test_dynamic_debug.c| 50 +
 lib/test_dynamic_debug_submod.c |  9 +-
 5 files changed, 69 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c
index dabcfa0dd279..8f4b609353a5 100644
--- a/drivers/gpu/drm/drm_print.c
+++ b/drivers/gpu/drm/drm_print.c
@@ -69,12 +69,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, ¶m_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 706afc97c79c..94d4f5500030 100644
--- a/include/drm/drm_print.h
+++ b/include/drm/drm_print.h
@@ -322,11 +322,13 @@ enum drm_debug_category {
 };
 
 #ifdef CONFIG_DRM_USE_DYNAMIC_DEBUG
-#define DRM_CLASSMAP_DEFINE(...) DYNDBG_CLASSMAP_DEFINE(__VA_ARGS__)
-#define DRM_CLASSMAP_USE(name)   DYNDBG_CLASSMAP_USE(name)
+#define DRM_CLASSMAP_DEFINE(...)   DYNDBG_CLASSMAP_DEFINE(__VA_ARGS__)
+#define DRM_CLASSMAP_USE(name) DYNDBG_CLASSMAP_USE(name)
+#define DRM_CLASSMAP_PARAM_REF(...)DYNDBG_CLASSMAP_PARAM_REF(__VA_ARGS__)
 #else
 #define DRM_CLASSMAP_DEFINE(...)
 #define DRM_CLASSMAP_USE(name)
+#define DRM_CLASSMAP_PARAM_REF(...)
 #endif
 
 static inline bool drm_debug_enabled_raw(enum drm_debug_category category)
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 373d152f4285..2a7832b1ba5b 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -91,7 +91,7 @@ struct ddebug_class_map {
  * used to validate a "class FOO .." >control command on the module
  */
 #define DYNDBG_CLASSMAP_DEFINE(_var, _maptype, _base, ...) \
-   const char *_var##_classnames[] = { __VA_ARGS__ };  \
+   static const char *_var##_classnames[] = { __VA_ARGS__ };   \
struct ddebug_class_map __aligned(8) __used \
__section("__dyndbg_classes") _var = {  \
.mod = THIS_MODULE, \
@@ -145,6 +145,41 @@ struct ddebug_class_param {
const struct ddebug_class_map *map;
 };
 
+/**
+ * DYNDBG_CLASSMAP_PARAM - wrap a dyndbg-classmap with a controlling sys-param
+ * @_name  sysfs node name
+ * @_var   name of the struct classmap var defining the controlled classes
+ * @_flags flags to be toggled, typically just 'p'
+ *
+ * Creates a sysfs-param to control the classes defined by the
+ * classmap.  Keeps bits in a private/static
+ */
+#define DYNDBG_CLASSMAP_PARAM(_name, _var, _flags) \
+   static unsigned long _name##_bvec;  \
+   __DYNDBG_CLASSMAP_PARAM(_name, _name##_bvec, _var, _flags)
+
+/**
+ * DYNDBG_CLASSMAP_PARAM_REF - wrap a dyndbg-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 struct classmap var defining the controlled classes
+ * @_flags flags to be toggled, typically just 'p'
+ *
+ * Creates a sysfs-param to control the classmap, keeping bitvec in user 
@_bits.
+ * This lets drm use __drm_debug elsewhere too.
+ */
+#define DYNDBG_CLASSMAP_PARAM_REF(_name, _bits, _var, _flags)  \
+   __DYNDBG_CLASSMAP_PARAM(_name, _bits, _var, _flags)
+
+#define __DYNDBG_CLASSMAP_PARAM(_name, _bits, _var, _flags)\
+   static struct ddebug_class_param _name##_##_flags = {   \
+   .bits = &(_bits),   \
+   .flags = #_flags,   \
+   .map = &(_var), \
+   }; 

[PATCH v7d 20/23] dyndbg: refactor *dynamic_emit_prefix

2023-10-31 Thread Jim Cromie
Refactor the split of duties between outer & inner fns.

The outer fn was previously just an inline unlikely forward to inner,
which did all the work.

Now, outer handles +t and +l flags itself, and calls inner only when
_DPRINTK_FLAGS_INCL_LOOKUP is needed.

No functional change.

But it does make the results of the inner-fn more cache-friendly
(fewer entries, reused more often):

1- no spurious [TID] or  noise
2- no LINE-number to bloat the cache (avg 9 pr_debugs/fn)
3- only LOOKUP stuff

Currently LOOKUPs are descriptor-field refs but could be replaced by
accessor functions.  This would allow the __dyndbg_sites section to be
de-duplicated and reclaimed; currently module, filename fields are
~90% repeated.  As the accessors get more expensive, the value of
caching part of the prefix goes up.

Also change inner-fn to return count of extra chars written to the
buffer, and drop "inline" from outer, let the compiler decide.  Maybe
also change name accordingly.

Signed-off-by: Jim Cromie 
---
fixup whitespace
---
 lib/dynamic_debug.c | 39 ++-
 1 file changed, 22 insertions(+), 17 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index f878a6f09fc8..213110ec1e9c 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -774,11 +774,28 @@ static int remaining(int wrote)
return 0;
 }
 
-static char *__dynamic_emit_prefix(const struct _ddebug *desc, char *buf)
+static int __dynamic_emit_prefix(const struct _ddebug *desc, char *buf, int 
pos)
+{
+   if (desc->flags & _DPRINTK_FLAGS_INCL_MODNAME)
+   pos += snprintf(buf + pos, remaining(pos), "%s:",
+   desc->modname);
+   if (desc->flags & _DPRINTK_FLAGS_INCL_FUNCNAME)
+   pos += snprintf(buf + pos, remaining(pos), "%s:",
+   desc->function);
+   if (desc->flags & _DPRINTK_FLAGS_INCL_SOURCENAME)
+   pos += snprintf(buf + pos, remaining(pos), "%s:",
+   trim_prefix(desc->filename));
+   return pos;
+}
+
+static char *dynamic_emit_prefix(struct _ddebug *desc, char *buf)
 {
int pos_after_tid;
int pos = 0;
 
+   if (likely(!(desc->flags & _DPRINTK_FLAGS_INCL_ANY)))
+   return buf;
+
if (desc->flags & _DPRINTK_FLAGS_INCL_TID) {
if (in_interrupt())
pos += snprintf(buf + pos, remaining(pos), " ");
@@ -787,15 +804,10 @@ static char *__dynamic_emit_prefix(const struct _ddebug 
*desc, char *buf)
task_pid_vnr(current));
}
pos_after_tid = pos;
-   if (desc->flags & _DPRINTK_FLAGS_INCL_MODNAME)
-   pos += snprintf(buf + pos, remaining(pos), "%s:",
-   desc->modname);
-   if (desc->flags & _DPRINTK_FLAGS_INCL_FUNCNAME)
-   pos += snprintf(buf + pos, remaining(pos), "%s:",
-   desc->function);
-   if (desc->flags & _DPRINTK_FLAGS_INCL_SOURCENAME)
-   pos += snprintf(buf + pos, remaining(pos), "%s:",
-   trim_prefix(desc->filename));
+
+   if (unlikely(desc->flags & _DPRINTK_FLAGS_INCL_LOOKUP))
+   pos += __dynamic_emit_prefix(desc, buf, pos);
+
if (desc->flags & _DPRINTK_FLAGS_INCL_LINENO)
pos += snprintf(buf + pos, remaining(pos), "%d:",
desc->lineno);
@@ -807,13 +819,6 @@ static char *__dynamic_emit_prefix(const struct _ddebug 
*desc, char *buf)
return buf;
 }
 
-static inline char *dynamic_emit_prefix(struct _ddebug *desc, char *buf)
-{
-   if (unlikely(desc->flags & _DPRINTK_FLAGS_INCL_ANY))
-   return __dynamic_emit_prefix(desc, buf);
-   return buf;
-}
-
 void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...)
 {
va_list args;
-- 
2.41.0



[PATCH v7d 21/23] drm: use correct ccflags-y spelling

2023-10-31 Thread Jim Cromie
Incorrectly spelled CFLAGS- failed to add -DDYNAMIC_DEBUG_MODULE,
which broke builds with:

CONFIG_DRM_USE_DYNAMIC_DEBUG=y
CONFIG_DYNAMIC_DEBUG_CORE=y
CONFIG_DYNAMIC_DEBUG=n

Also add subdir-ccflags so that all drivers pick up the addition.

Fixes: 84ec67288c10 ("drm_print: wrap drm_*_dbg in dyndbg descriptor factory 
macro")
Signed-off-by: Jim Cromie 
---
 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 215e78e79125..22b1984cc982 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
 
 drm-y := \
drm_aperture.o \
-- 
2.41.0



[PATCH v7d 19/23] dyndbg: add _DPRINTK_FLAGS_INCL_LOOKUP

2023-10-31 Thread Jim Cromie
dyndbg's dynamic prefixing (by +tmfsl flags) is needlessly expensive.

When an enabled (with +p) pr_debug is called, _DPRINTK_FLAGS_INCL_ANY
prefix decorations are sprintf'd into stack-mem for every call.

This string (or part of it) could be cached once its 1st generated,
and retrieved thereafter, as long as its deleted any time the
callsite's flags are changed afterwards.

So consider the prefix/decoration flags: 'tmfsl', and what should be
in the cache:

-t  thread-id. not part of the "callsite" info, derived from current.
doesn't belong in the cache. it would be wrong.
can be done in outer: dynamic_emit_prefix()

-l  line number
this could be part of the prefix, but would bloat the cache
can also be done in outer: dynamic_emit_prefix()

-mfs  module, function, source-file
we cache these, composed into a sub-string.
they are "lookups", currently to descriptor fields,
could be accessor macros to "compressed" tables.
cache saves more access work.

All enabled together, they compose a prefix string like:

  # outer   -inner--   outer
  "[tid] module:function:sourcfile:line: "

So this patch extracts _DPRINTK_FLAGS_INCL_LOOKUP macro out of
_DPRINTK_FLAGS_INCL_ANY macro, then redefs latter.

Next re-refactor dynamic_emit_prefix inner/outer fns accordingly.

Signed-off-by: Jim Cromie 
---
 include/linux/dynamic_debug.h | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 4ffddf5e9152..b4550f80cfd5 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -40,10 +40,12 @@ struct _ddebug {
 #define _DPRINTK_FLAGS_INCL_SOURCENAME (1<<5)
 #define _DPRINTK_FLAGS_PREFIX_CACHED   (1<<7)
 
-#define _DPRINTK_FLAGS_INCL_ANY\
-   (_DPRINTK_FLAGS_INCL_MODNAME | _DPRINTK_FLAGS_INCL_FUNCNAME |\
-_DPRINTK_FLAGS_INCL_LINENO  | _DPRINTK_FLAGS_INCL_TID |\
+#define _DPRINTK_FLAGS_INCL_LOOKUP \
+   (_DPRINTK_FLAGS_INCL_MODNAME | _DPRINTK_FLAGS_INCL_FUNCNAME |   \
 _DPRINTK_FLAGS_INCL_SOURCENAME)
+#define _DPRINTK_FLAGS_INCL_ANY
\
+   (_DPRINTK_FLAGS_INCL_LINENO | _DPRINTK_FLAGS_INCL_TID | \
+_DPRINTK_FLAGS_INCL_LOOKUP)
 
 #if defined DEBUG
 #define _DPRINTK_FLAGS_DEFAULT _DPRINTK_FLAGS_PRINT
-- 
2.41.0



  1   2   3   4   5   6   7   8   9   >