From: Jim Cromie <[email protected]>

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

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

2.DYNAMIC_DEBUG_CLASSMAP_PARAM
    new user (test_dynamic_debug) doesn't need to share state,
    declares a u32 to store the bitvec.

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

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

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

cc: [email protected]
Signed-off-by: Jim Cromie <[email protected]>
Reviewed-by: Louis Chauvet <[email protected]>
---
 include/linux/dynamic_debug.h                      | 40 ++++++++++++
 lib/dynamic_debug.c                                | 76 +++++++++++-----------
 lib/test_dynamic_debug.c                           | 55 ++++++----------
 lib/test_dynamic_debug_submod.c                    |  9 ++-
 .../selftests/dynamic_debug/dyndbg_selftest.sh     | 10 +--
 5 files changed, 112 insertions(+), 78 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 471b9891bd83..a740b3fabc09 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -291,6 +291,44 @@ struct ddebug_class_param {
                .offset = _offset                                       \
        }
 
+/**
+ * DYNAMIC_DEBUG_CLASSMAP_PARAM - control a ddebug-classmap from a sys-param
+ * @_name:  sysfs node name
+ * @_var:   name of the classmap var defining the controlled classes/bits
+ * @_flags: flags to be toggled, typically just 'p'
+ *
+ * Creates a sysfs-param to control the classes defined by the
+ * exported classmap, with bits 0..N-1 mapped to the classes named.
+ * This version keeps class-state in a private long int.
+ */
+#define DYNAMIC_DEBUG_CLASSMAP_PARAM(_name, _var, _flags)              \
+       static u32 _name##_bvec;                                        \
+       __DYNAMIC_DEBUG_CLASSMAP_PARAM(_name, _name##_bvec, _var, _flags)
+
+/**
+ * DYNAMIC_DEBUG_CLASSMAP_PARAM_REF - wrap a classmap with a controlling 
sys-param
+ * @_name:  sysfs node name
+ * @_bits:  name of the module's unsigned long bit-vector, ex: __drm_debug
+ * @_var:   name of the (exported) classmap var defining the classes/bits
+ * @_flags: flags to be toggled, typically just 'p'
+ *
+ * Creates a sysfs-param to control the classes defined by the
+ * exported clasmap, with bits 0..N-1 mapped to the classes named.
+ * This version keeps class-state in user @_bits.  This lets drm check
+ * __drm_debug elsewhere too.
+ */
+#define DYNAMIC_DEBUG_CLASSMAP_PARAM_REF(_name, _bits, _var, _flags)   \
+       __DYNAMIC_DEBUG_CLASSMAP_PARAM(_name, _bits, _var, _flags)
+
+#define __DYNAMIC_DEBUG_CLASSMAP_PARAM(_name, _bits, _var, _flags)     \
+       static struct ddebug_class_param _name##_##_flags = {           \
+               .bits = &(_bits),                                       \
+               .flags = #_flags,                                       \
+               .map = &(_var),                                         \
+       };                                                              \
+       module_param_cb(_name, &param_ops_dyndbg_classes,               \
+                       &_name##_##_flags, 0600)
+
 extern __printf(2, 3)
 void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
 
@@ -473,6 +511,8 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 
 #define DYNAMIC_DEBUG_CLASSMAP_DEFINE(_var, _mapty, _base, ...)
 #define DYNAMIC_DEBUG_CLASSMAP_USE(_var)
+#define DYNAMIC_DEBUG_CLASSMAP_PARAM(_name, _var, _flags)
+#define DYNAMIC_DEBUG_CLASSMAP_PARAM_REF(_name, _var, _flags)
 #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)
 #define DYNAMIC_DEBUG_BRANCH(descriptor) false
 #define DECLARE_DYNDBG_CLASSMAP(...)
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 0f89b6784ab2..3f9821f747d8 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -697,9 +697,42 @@ static int ddebug_apply_class_bitmap(const struct 
ddebug_class_param *dcp,
 
 #define CLASSMAP_BITMASK(width) ((width) >= 32 ? ~0U : (1U << (width)) - 1)
 
-/*
- * param-setter helper to validate numeric input, clamp its value by
- * the classmap type and size, and apply the bits.
+static void __maybe_unused ddebug_class_param_clamp_input(u32 *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%x exceeds mask: 0x%x, 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:%d exceeds max:%d, clamping\n",
+                               KP_NAME(kp), *inrep, map->length);
+                       *inrep = map->length;
+               }
+               break;
+       }
+}
+
+/**
+ * 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
+ * @mod_name: module name or null for all modules with the classes
+ *
+ * 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.
  */
 static int param_set_dyndbg_module_classes(const char *instr,
                                           const struct kernel_param *kp,
@@ -718,31 +751,21 @@ static int param_set_dyndbg_module_classes(const char 
*instr,
                       len, 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%x exceeds mask: 0x%x, masking\n",
-                               KP_NAME(kp), inrep, 
CLASSMAP_BITMASK(map->length));
-                       inrep &= CLASSMAP_BITMASK(map->length);
-               }
                old_val = READ_ONCE(*dcp->bits);
                v2pr_info("bits:0x%x > %s.%s\n", inrep, mod_name ?: "*", 
KP_NAME(kp));
                totct += ddebug_apply_class_bitmap(dcp, &inrep, old_val, 
mod_name);
                WRITE_ONCE(*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:%u exceeds max:%d, clamping\n",
-                               KP_NAME(kp), inrep, map->length);
-                       inrep = map->length;
-               }
                old_val = READ_ONCE(*dcp->lvl);
                old_bits = CLASSMAP_BITMASK(old_val);
                new_bits = CLASSMAP_BITMASK(inrep);
                v2pr_info("lvl:%u bits:0x%x > %s\n", inrep, new_bits, 
KP_NAME(kp));
+               v2pr_info("lvl:%u bits:0x%x > %s\n", inrep, new_bits, 
KP_NAME(kp));
                totct += ddebug_apply_class_bitmap(dcp, &new_bits, old_bits, 
mod_name);
                WRITE_ONCE(*dcp->lvl, inrep);
                break;
@@ -1236,30 +1259,7 @@ static inline u32 ddebug_class_param_to_bits(const 
struct ddebug_class_param *dc
        }
 }
 
-static void __maybe_unused ddebug_class_param_clamp_input(u32 *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%x exceeds mask: 0x%x, 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:%d exceeds max:%d, clamping\n",
-                               KP_NAME(kp), *inrep, map->length);
-                       *inrep = map->length;
-               }
-               break;
-       }
-}
 
 /* called for class-users only, parse_one does this for definer modules */
 static void ddebug_sync_classbits(const struct kernel_param *kp, const char 
*modname)
diff --git a/lib/test_dynamic_debug.c b/lib/test_dynamic_debug.c
index 39499e52d7c0..def44524b762 100644
--- a/lib/test_dynamic_debug.c
+++ b/lib/test_dynamic_debug.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Kernel module for testing dynamic_debug
+ * Kernel module to test/demonstrate dynamic_debug features,
+ * particularly classmaps and their support for subsystems like DRM.
  *
  * Authors:
  *      Jim Cromie     <[email protected]>
@@ -67,32 +68,7 @@ static const struct kernel_param_ops param_ops_do_repeats = {
 module_param_cb(do_classes, &param_ops_do_repeats, do_classes, 0600);
 module_param_cb(do_bulk, &param_ops_do_repeats, do_bulk, 0600);
 
-/*
- * Using the CLASSMAP api:
- * - classmaps must have corresponding enum
- * - enum symbols must match/correlate with class-name strings in the map.
- * - base must equal enum's 1st value
- * - multiple maps must set their base to share the 0-30 class_id space !!
- *   (build-bug-on tips welcome)
- * Additionally, here:
- * - tie together sysname, mapname, bitsname, flagsname
- */
-#define DYNAMIC_DEBUG_CLASSMAP_PARAM_(_model, _flags, _init)           \
-       static u32 bits_##_model = _init;                               \
-       static struct ddebug_class_param _flags##_##_model = {          \
-               .bits = &bits_##_model,                                 \
-               .flags = #_flags,                                       \
-               .map = &map_##_model,                                   \
-       };                                                              \
-       module_param_cb(_flags##_##_model, &param_ops_dyndbg_classes,   \
-                       &_flags##_##_model, 0600)
-#ifdef DEBUG
-#define DYNAMIC_DEBUG_CLASSMAP_PARAM(_model, _flags)           \
-       DYNAMIC_DEBUG_CLASSMAP_PARAM_(_model, _flags, ~0)
-#else
-#define DYNAMIC_DEBUG_CLASSMAP_PARAM(_model, _flags)           \
-       DYNAMIC_DEBUG_CLASSMAP_PARAM_(_model, _flags, 0)
-#endif
+#define CLASSMAP_BITMASK(width, base) (((1ULL << (width)) - 1) << (base))
 
 /*
  * Demonstrate/test DISJOINT & LEVEL typed classmaps with a sys-param.
@@ -127,12 +103,15 @@ enum cat_level_num { V1 = 16, V2, V3, V4, V5, V6, V7, V8 
};
 /* test _USE_ w offset */
 enum cat_level_offset { Vu1 = V1 + 8, Vu2, Vu3, Vu4, Vu5, Vu6, Vu7, Vu8 };
 
-/* recapitulate DRM's multi-classmap setup */
+/*
+ * use/demonstrate multi-module-group classmaps, as for DRM
+ */
 #if !defined(TEST_DYNAMIC_DEBUG_SUBMOD)
 /*
- * In single user, or parent / coordinator (drm.ko) modules, define
- * classmaps on the client enums above, and then declares the PARAMS
- * ref'g the classmaps.  Each is exported.
+ * For module-groups of 1+, define classmaps with names (stringified
+ * enum-symbols) copied from above. 1-to-1 mapping is recommended.
+ * The classmap is exported, so that other modules in the group can
+ * link to it and control their prdbgs.
  */
 DYNAMIC_DEBUG_CLASSMAP_DEFINE(map_disjoint_bits, DD_CLASS_TYPE_DISJOINT_BITS,
                              D2_CORE,
@@ -150,6 +129,15 @@ DYNAMIC_DEBUG_CLASSMAP_DEFINE(map_disjoint_bits, 
DD_CLASS_TYPE_DISJOINT_BITS,
 DYNAMIC_DEBUG_CLASSMAP_DEFINE(map_level_num, DD_CLASS_TYPE_LEVEL_NUM,
                              V1, "V1", "V2", "V3", "V4", "V5", "V6", "V7");
 
+/*
+ * for use-cases that want it, provide a sysfs-param to set the
+ * classes in the classmap.  It is at this interface where the
+ * "v3>v2" property is applied to DD_CLASS_TYPE_LEVEL_NUM inputs.
+ */
+
+DYNAMIC_DEBUG_CLASSMAP_PARAM(p_disjoint_bits,  map_disjoint_bits, p);
+DYNAMIC_DEBUG_CLASSMAP_PARAM(p_level_num,      map_level_num, p);
+
 #ifdef FORCE_CLASSID_CONFLICT
 /*
  * Enable with -Dflag on compile to test overlapping class-id range
@@ -158,6 +146,7 @@ DYNAMIC_DEBUG_CLASSMAP_DEFINE(map_level_num, 
DD_CLASS_TYPE_LEVEL_NUM,
 DYNAMIC_DEBUG_CLASSMAP_DEFINE(classid_range_conflict, 0, D2_CORE + 1, 
"D3_CORE");
 #endif
 
+
 #if defined(DD_MACRO_ARGCHECK)
 /*
  * Exersize compile-time arg-checks in DYNAMIC_DEBUG_CLASSMAP_DEFINE.
@@ -191,8 +180,6 @@ DYNAMIC_DEBUG_CLASSMAP_USE_(fail_offset_big, 100);
 /*
  * now add the sysfs-params to both sub/super-mods
  */
-DYNAMIC_DEBUG_CLASSMAP_PARAM(disjoint_bits, p);
-DYNAMIC_DEBUG_CLASSMAP_PARAM(level_num, p);
 
 /* stand-in for all pr_debug etc */
 #define prdbg(SYM) __pr_debug_cls(SYM, #SYM " msg\n")
@@ -283,5 +270,5 @@ module_init(test_dynamic_debug_init);
 module_exit(test_dynamic_debug_exit);
 
 MODULE_AUTHOR("Jim Cromie <[email protected]>");
-MODULE_DESCRIPTION("Kernel module for testing dynamic_debug");
+MODULE_DESCRIPTION("test/demonstrate dynamic-debug features");
 MODULE_LICENSE("GPL");
diff --git a/lib/test_dynamic_debug_submod.c b/lib/test_dynamic_debug_submod.c
index 672aabf40160..3adf3925fb86 100644
--- a/lib/test_dynamic_debug_submod.c
+++ b/lib/test_dynamic_debug_submod.c
@@ -1,6 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Kernel module for testing dynamic_debug
+ * Kernel module to test/demonstrate dynamic_debug features,
+ * particularly classmaps and their support for subsystems, like DRM,
+ * which defines its drm_debug classmap in drm module, and uses it in
+ * helpers & drivers.
  *
  * Authors:
  *      Jim Cromie     <[email protected]>
@@ -12,3 +15,7 @@
  */
 #define TEST_DYNAMIC_DEBUG_SUBMOD
 #include "test_dynamic_debug.c"
+
+MODULE_DESCRIPTION("test/demonstrate dynamic-debug subsystem support");
+MODULE_AUTHOR("Jim Cromie <[email protected]>");
+MODULE_LICENSE("GPL");
diff --git a/tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh 
b/tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh
index 3d9c777a0fc3..2018031f58b9 100755
--- a/tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh
+++ b/tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh
@@ -651,7 +651,7 @@ function GOLDEN_RECORDS {
 #K= bede904b02278e5648bb7a8243be8d98 FT_path_module_queries.4
 #K= 5d38e4cca64da64a4d7f433398668836 FT_test_classes.1
 #K= 5516e3d13cba7ea4197a7fb6c033887a FT_test_classes.2
-#K= a3677b84d39c42c24d879f34f879aa07 FT_test_classes.3
+#K= 40a294034c886787960f4c751b196da9 FT_test_classes.3
 #K= 38e813e9025107ac3e24226b8d487a92 FT_classmap_inheritance.1
 #K= 9b82b12a35ad98ef26183db15071f70e FT_classmap_inheritance.2
 #K= d4937472530af6fdcb0a2440d4a366ea FT_classmap_inheritance.3
@@ -685,13 +685,13 @@ function GOLDEN_RECORDS {
 #K= 030cda0a59aaae95750d5ec55acbcb8c FT_modprobe_w_param.26
 #K= 7b91db8e9f160aebb1ee87fab2232404 FT_modprobe_w_param.27
 #K= 030cda0a59aaae95750d5ec55acbcb8c FT_modprobe_w_param.28
-#K= e393499e02677de414e478f4e710eeb9 FT_modprobe_w_param.29
+#K= caa849a2817863d68a8d11ee415b049c FT_modprobe_w_param.29
 #K= 030cda0a59aaae95750d5ec55acbcb8c FT_modprobe_w_param.30
-#K= 375e38613af3b49bb7c7689dfecf4177 FT_modprobe_w_param.31
+#K= e94cc54f62faa428a03f2a7dbca06f97 FT_modprobe_w_param.31
 #K= 030cda0a59aaae95750d5ec55acbcb8c FT_modprobe_w_param.32
-#K= 745a61d20e26a6a22db0b99420fea80a FT_modprobe_w_param.33
+#K= 8919dde0fee0cf42f9388e541b33aa01 FT_modprobe_w_param.33
 #K= 030cda0a59aaae95750d5ec55acbcb8c FT_modprobe_w_param.34
-#K= 3d2538bf868e71bff17c768cf118c352 FT_modprobe_w_param.35
+#K= ff5bf6afec9642da83d3dcdb5e732ab9 FT_modprobe_w_param.35
 #K= 030cda0a59aaae95750d5ec55acbcb8c FT_modprobe_w_param.36
 EOF
         # Read the K-recs and skip those for tests that can't run

-- 
2.55.0


Reply via email to