All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] dyndbg add exclusive class support
@ 2022-03-11  4:47 ` Jim Cromie
  0 siblings, 0 replies; 49+ messages in thread
From: Jim Cromie @ 2022-03-11  4:47 UTC (permalink / raw)
  To: jbaron, gregkh, linux-kernel
  Cc: daniel.vetter, seanpaul, robdclark, linux, joe, dri-devel,
	amd-gfx, intel-gvt-dev, intel-gfx, Jim Cromie

Hi Greg, Jason,

Please consider these for char/misc or linux-next/soon/mumble.

This patchset adds exclusive class support to dyndbg, allowing it to
directly represent drm's debug_category.

It is the dyndbg half of:
https://lore.kernel.org/lkml/20220217034829.64395-1-jim.cromie@gmail.com/

The DRM half of that patchset uses this support to reimplement
drm.debug on dyndbg, and uses its callsite patching to avoid the
runtime checking done by drm_debug_enabled().

Background:

In the past, various extensions to dyndbg/pr_debug have been proposed,
none seemed to gain any consensus.  This list is certainly incomplete.

https://lore.kernel.org/lkml/20200609104604.1594-1-stanimir.varbanov@linaro.org/

pr_levels was discussed around this patchset, in revs 3,4,5
This search helps:
	s:venus: s:dynamic f:stanimir.varbanov@linaro.org

IMO, pr_levels suffers from implied meaning between the levels: 2 > 1.
In contrast, DRM has logically disjoint categories, and is implemented
in an enum (despite its flag/mask values, a micro-optimization).

https://lore.kernel.org/lkml/20210813151734.1236324-1-jim.cromie@gmail.com/

That patchset used pr_debug in DRM, and prepended "drm:kms:" etc to
the format strings so each category was selectable; "format drm:kms:"
in the query.  This worked, but it made the format config-dependent,
and was hard to explain without undue "artifact".


So this patchset adds .class_id field (4-bits) to dynamic-debug
callsites, and 'class N' query/command support to select upon it.
Existing callsites and queries get .class_id=15, so 0-14 are available
for use by the client (DRM wants 0-10).

The DRM patchset then:
. renumbers drm_debug_category to fit into the 4-bit .class_id
  the new enumerations *are* the bit-positions in drm/parameters/debug.
. adapts the category-macro layer to use _CLS macros, mapping categories.
. adds macro layer under the category-macro layer
  which wraps drm_*dbg inside a dyndbg Factory macro
. uses DEFINE_DYNAMIC_DEBUG_CLASSBITS to tie to __drm_debug
  callbacks ref the var, so drm_debug_enabled(cat) just works.

Jim Cromie (5):

dyndbg: fix static_branch manipulation
  fixes a latent bug, before a 2nd "enable" flag exposes it.

dyndbg: add class_id field and query support
  will allow (with that drm patchset):
  #> # turn on DRM_ATOMIC in amdgpu
  #> echo module amdgpu class 4 +p > /proc/dynamic_debug/control
  #> # turn on DRM_CORE in drm
  #> echo module drm class 0 +p > /proc/dynamic_debug/control

dyndbg: add DEFINE_DYNAMIC_DEBUG_CLASSBITS macro
  adds macro & callbacks to support drm.debug bitmap
  #> echo 4 > /sys/module/drm/parameters/debug

dyndbg: drop EXPORTed dynamic_debug_exec_queries
  unused yet, obsoleted by 2,3

dyndbg: show both old and new in change-info
  minor debug improvement


 .../admin-guide/dynamic-debug-howto.rst       |   7 +
 include/linux/dynamic_debug.h                 | 111 ++++++++++---
 lib/dynamic_debug.c                           | 150 ++++++++++++++----
 3 files changed, 213 insertions(+), 55 deletions(-)

-- 
2.35.1


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

* [PATCH 0/5] dyndbg add exclusive class support
@ 2022-03-11  4:47 ` Jim Cromie
  0 siblings, 0 replies; 49+ messages in thread
From: Jim Cromie @ 2022-03-11  4:47 UTC (permalink / raw)
  To: jbaron, gregkh, linux-kernel
  Cc: daniel.vetter, intel-gfx, linux, dri-devel, seanpaul, amd-gfx,
	joe, intel-gvt-dev

Hi Greg, Jason,

Please consider these for char/misc or linux-next/soon/mumble.

This patchset adds exclusive class support to dyndbg, allowing it to
directly represent drm's debug_category.

It is the dyndbg half of:
https://lore.kernel.org/lkml/20220217034829.64395-1-jim.cromie@gmail.com/

The DRM half of that patchset uses this support to reimplement
drm.debug on dyndbg, and uses its callsite patching to avoid the
runtime checking done by drm_debug_enabled().

Background:

In the past, various extensions to dyndbg/pr_debug have been proposed,
none seemed to gain any consensus.  This list is certainly incomplete.

https://lore.kernel.org/lkml/20200609104604.1594-1-stanimir.varbanov@linaro.org/

pr_levels was discussed around this patchset, in revs 3,4,5
This search helps:
	s:venus: s:dynamic f:stanimir.varbanov@linaro.org

IMO, pr_levels suffers from implied meaning between the levels: 2 > 1.
In contrast, DRM has logically disjoint categories, and is implemented
in an enum (despite its flag/mask values, a micro-optimization).

https://lore.kernel.org/lkml/20210813151734.1236324-1-jim.cromie@gmail.com/

That patchset used pr_debug in DRM, and prepended "drm:kms:" etc to
the format strings so each category was selectable; "format drm:kms:"
in the query.  This worked, but it made the format config-dependent,
and was hard to explain without undue "artifact".


So this patchset adds .class_id field (4-bits) to dynamic-debug
callsites, and 'class N' query/command support to select upon it.
Existing callsites and queries get .class_id=15, so 0-14 are available
for use by the client (DRM wants 0-10).

The DRM patchset then:
. renumbers drm_debug_category to fit into the 4-bit .class_id
  the new enumerations *are* the bit-positions in drm/parameters/debug.
. adapts the category-macro layer to use _CLS macros, mapping categories.
. adds macro layer under the category-macro layer
  which wraps drm_*dbg inside a dyndbg Factory macro
. uses DEFINE_DYNAMIC_DEBUG_CLASSBITS to tie to __drm_debug
  callbacks ref the var, so drm_debug_enabled(cat) just works.

Jim Cromie (5):

dyndbg: fix static_branch manipulation
  fixes a latent bug, before a 2nd "enable" flag exposes it.

dyndbg: add class_id field and query support
  will allow (with that drm patchset):
  #> # turn on DRM_ATOMIC in amdgpu
  #> echo module amdgpu class 4 +p > /proc/dynamic_debug/control
  #> # turn on DRM_CORE in drm
  #> echo module drm class 0 +p > /proc/dynamic_debug/control

dyndbg: add DEFINE_DYNAMIC_DEBUG_CLASSBITS macro
  adds macro & callbacks to support drm.debug bitmap
  #> echo 4 > /sys/module/drm/parameters/debug

dyndbg: drop EXPORTed dynamic_debug_exec_queries
  unused yet, obsoleted by 2,3

dyndbg: show both old and new in change-info
  minor debug improvement


 .../admin-guide/dynamic-debug-howto.rst       |   7 +
 include/linux/dynamic_debug.h                 | 111 ++++++++++---
 lib/dynamic_debug.c                           | 150 ++++++++++++++----
 3 files changed, 213 insertions(+), 55 deletions(-)

-- 
2.35.1


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

* [Intel-gfx] [PATCH 0/5] dyndbg add exclusive class support
@ 2022-03-11  4:47 ` Jim Cromie
  0 siblings, 0 replies; 49+ messages in thread
From: Jim Cromie @ 2022-03-11  4:47 UTC (permalink / raw)
  To: jbaron, gregkh, linux-kernel
  Cc: Jim Cromie, daniel.vetter, intel-gfx, linux, dri-devel, seanpaul,
	amd-gfx, joe, intel-gvt-dev

Hi Greg, Jason,

Please consider these for char/misc or linux-next/soon/mumble.

This patchset adds exclusive class support to dyndbg, allowing it to
directly represent drm's debug_category.

It is the dyndbg half of:
https://lore.kernel.org/lkml/20220217034829.64395-1-jim.cromie@gmail.com/

The DRM half of that patchset uses this support to reimplement
drm.debug on dyndbg, and uses its callsite patching to avoid the
runtime checking done by drm_debug_enabled().

Background:

In the past, various extensions to dyndbg/pr_debug have been proposed,
none seemed to gain any consensus.  This list is certainly incomplete.

https://lore.kernel.org/lkml/20200609104604.1594-1-stanimir.varbanov@linaro.org/

pr_levels was discussed around this patchset, in revs 3,4,5
This search helps:
	s:venus: s:dynamic f:stanimir.varbanov@linaro.org

IMO, pr_levels suffers from implied meaning between the levels: 2 > 1.
In contrast, DRM has logically disjoint categories, and is implemented
in an enum (despite its flag/mask values, a micro-optimization).

https://lore.kernel.org/lkml/20210813151734.1236324-1-jim.cromie@gmail.com/

That patchset used pr_debug in DRM, and prepended "drm:kms:" etc to
the format strings so each category was selectable; "format drm:kms:"
in the query.  This worked, but it made the format config-dependent,
and was hard to explain without undue "artifact".


So this patchset adds .class_id field (4-bits) to dynamic-debug
callsites, and 'class N' query/command support to select upon it.
Existing callsites and queries get .class_id=15, so 0-14 are available
for use by the client (DRM wants 0-10).

The DRM patchset then:
. renumbers drm_debug_category to fit into the 4-bit .class_id
  the new enumerations *are* the bit-positions in drm/parameters/debug.
. adapts the category-macro layer to use _CLS macros, mapping categories.
. adds macro layer under the category-macro layer
  which wraps drm_*dbg inside a dyndbg Factory macro
. uses DEFINE_DYNAMIC_DEBUG_CLASSBITS to tie to __drm_debug
  callbacks ref the var, so drm_debug_enabled(cat) just works.

Jim Cromie (5):

dyndbg: fix static_branch manipulation
  fixes a latent bug, before a 2nd "enable" flag exposes it.

dyndbg: add class_id field and query support
  will allow (with that drm patchset):
  #> # turn on DRM_ATOMIC in amdgpu
  #> echo module amdgpu class 4 +p > /proc/dynamic_debug/control
  #> # turn on DRM_CORE in drm
  #> echo module drm class 0 +p > /proc/dynamic_debug/control

dyndbg: add DEFINE_DYNAMIC_DEBUG_CLASSBITS macro
  adds macro & callbacks to support drm.debug bitmap
  #> echo 4 > /sys/module/drm/parameters/debug

dyndbg: drop EXPORTed dynamic_debug_exec_queries
  unused yet, obsoleted by 2,3

dyndbg: show both old and new in change-info
  minor debug improvement


 .../admin-guide/dynamic-debug-howto.rst       |   7 +
 include/linux/dynamic_debug.h                 | 111 ++++++++++---
 lib/dynamic_debug.c                           | 150 ++++++++++++++----
 3 files changed, 213 insertions(+), 55 deletions(-)

-- 
2.35.1


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

* [PATCH 0/5] dyndbg add exclusive class support
@ 2022-03-11  4:47 ` Jim Cromie
  0 siblings, 0 replies; 49+ messages in thread
From: Jim Cromie @ 2022-03-11  4:47 UTC (permalink / raw)
  To: jbaron, gregkh, linux-kernel
  Cc: Jim Cromie, daniel.vetter, intel-gfx, linux, dri-devel,
	robdclark, seanpaul, amd-gfx, joe, intel-gvt-dev

Hi Greg, Jason,

Please consider these for char/misc or linux-next/soon/mumble.

This patchset adds exclusive class support to dyndbg, allowing it to
directly represent drm's debug_category.

It is the dyndbg half of:
https://lore.kernel.org/lkml/20220217034829.64395-1-jim.cromie@gmail.com/

The DRM half of that patchset uses this support to reimplement
drm.debug on dyndbg, and uses its callsite patching to avoid the
runtime checking done by drm_debug_enabled().

Background:

In the past, various extensions to dyndbg/pr_debug have been proposed,
none seemed to gain any consensus.  This list is certainly incomplete.

https://lore.kernel.org/lkml/20200609104604.1594-1-stanimir.varbanov@linaro.org/

pr_levels was discussed around this patchset, in revs 3,4,5
This search helps:
	s:venus: s:dynamic f:stanimir.varbanov@linaro.org

IMO, pr_levels suffers from implied meaning between the levels: 2 > 1.
In contrast, DRM has logically disjoint categories, and is implemented
in an enum (despite its flag/mask values, a micro-optimization).

https://lore.kernel.org/lkml/20210813151734.1236324-1-jim.cromie@gmail.com/

That patchset used pr_debug in DRM, and prepended "drm:kms:" etc to
the format strings so each category was selectable; "format drm:kms:"
in the query.  This worked, but it made the format config-dependent,
and was hard to explain without undue "artifact".


So this patchset adds .class_id field (4-bits) to dynamic-debug
callsites, and 'class N' query/command support to select upon it.
Existing callsites and queries get .class_id=15, so 0-14 are available
for use by the client (DRM wants 0-10).

The DRM patchset then:
. renumbers drm_debug_category to fit into the 4-bit .class_id
  the new enumerations *are* the bit-positions in drm/parameters/debug.
. adapts the category-macro layer to use _CLS macros, mapping categories.
. adds macro layer under the category-macro layer
  which wraps drm_*dbg inside a dyndbg Factory macro
. uses DEFINE_DYNAMIC_DEBUG_CLASSBITS to tie to __drm_debug
  callbacks ref the var, so drm_debug_enabled(cat) just works.

Jim Cromie (5):

dyndbg: fix static_branch manipulation
  fixes a latent bug, before a 2nd "enable" flag exposes it.

dyndbg: add class_id field and query support
  will allow (with that drm patchset):
  #> # turn on DRM_ATOMIC in amdgpu
  #> echo module amdgpu class 4 +p > /proc/dynamic_debug/control
  #> # turn on DRM_CORE in drm
  #> echo module drm class 0 +p > /proc/dynamic_debug/control

dyndbg: add DEFINE_DYNAMIC_DEBUG_CLASSBITS macro
  adds macro & callbacks to support drm.debug bitmap
  #> echo 4 > /sys/module/drm/parameters/debug

dyndbg: drop EXPORTed dynamic_debug_exec_queries
  unused yet, obsoleted by 2,3

dyndbg: show both old and new in change-info
  minor debug improvement


 .../admin-guide/dynamic-debug-howto.rst       |   7 +
 include/linux/dynamic_debug.h                 | 111 ++++++++++---
 lib/dynamic_debug.c                           | 150 ++++++++++++++----
 3 files changed, 213 insertions(+), 55 deletions(-)

-- 
2.35.1


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

* [PATCH 1/5] dyndbg: fix static_branch manipulation
  2022-03-11  4:47 ` Jim Cromie
  (?)
  (?)
@ 2022-03-11  4:47   ` Jim Cromie
  -1 siblings, 0 replies; 49+ messages in thread
From: Jim Cromie @ 2022-03-11  4:47 UTC (permalink / raw)
  To: jbaron, gregkh, linux-kernel
  Cc: daniel.vetter, seanpaul, robdclark, linux, joe, dri-devel,
	amd-gfx, intel-gvt-dev, intel-gfx, Jim Cromie,
	vincent.whitchurch

In https://lore.kernel.org/lkml/20211209150910.GA23668@axis.com/

Vincent's patch commented on, and worked around, a bug toggling
static_branch's, when a 2nd PRINTK-ish flag was added.  The bug
results in a premature static_branch_disable when the 1st of 2 flags
was disabled.

The cited commit computed newflags, but then in the JUMP_LABEL block,
failed to use that result, instead using just one of the terms in it.
Using newflags instead made the code work properly.

This is Vincents test-case, reduced.  It needs the 2nd flag to work
properly, but it's explanatory here.

pt_test() {
    echo 5 > /sys/module/dynamic_debug/verbose

    site="module tcp" # just one callsite
    echo " $site =_ " > /proc/dynamic_debug/control # clear it

    # A B ~A ~B
    for flg in +T +p "-T #broke here" -p; do
	echo " $site $flg " > /proc/dynamic_debug/control
    done;

    # A B ~B ~A
    for flg in +T +p "-p #broke here" -T; do
	echo " $site $flg " > /proc/dynamic_debug/control
    done
}
pt_test

Fixes: 84da83a6ffc0 dyndbg: combine flags & mask into a struct, simplify with it
CC: vincent.whitchurch@axis.com
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>

--
.drop @stable, no exposed bug.
---
 lib/dynamic_debug.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index dd7f56af9aed..a56c1286ffa4 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -211,10 +211,11 @@ static int ddebug_change(const struct ddebug_query *query,
 				continue;
 #ifdef CONFIG_JUMP_LABEL
 			if (dp->flags & _DPRINTK_FLAGS_PRINT) {
-				if (!(modifiers->flags & _DPRINTK_FLAGS_PRINT))
+				if (!(newflags & _DPRINTK_FLAGS_PRINT))
 					static_branch_disable(&dp->key.dd_key_true);
-			} else if (modifiers->flags & _DPRINTK_FLAGS_PRINT)
+			} else if (newflags & _DPRINTK_FLAGS_PRINT) {
 				static_branch_enable(&dp->key.dd_key_true);
+			}
 #endif
 			dp->flags = newflags;
 			v4pr_info("changed %s:%d [%s]%s =%s\n",
-- 
2.35.1


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

* [PATCH 1/5] dyndbg: fix static_branch manipulation
@ 2022-03-11  4:47   ` Jim Cromie
  0 siblings, 0 replies; 49+ messages in thread
From: Jim Cromie @ 2022-03-11  4:47 UTC (permalink / raw)
  To: jbaron, gregkh, linux-kernel
  Cc: daniel.vetter, intel-gfx, vincent.whitchurch, linux, dri-devel,
	seanpaul, amd-gfx, joe, intel-gvt-dev

In https://lore.kernel.org/lkml/20211209150910.GA23668@axis.com/

Vincent's patch commented on, and worked around, a bug toggling
static_branch's, when a 2nd PRINTK-ish flag was added.  The bug
results in a premature static_branch_disable when the 1st of 2 flags
was disabled.

The cited commit computed newflags, but then in the JUMP_LABEL block,
failed to use that result, instead using just one of the terms in it.
Using newflags instead made the code work properly.

This is Vincents test-case, reduced.  It needs the 2nd flag to work
properly, but it's explanatory here.

pt_test() {
    echo 5 > /sys/module/dynamic_debug/verbose

    site="module tcp" # just one callsite
    echo " $site =_ " > /proc/dynamic_debug/control # clear it

    # A B ~A ~B
    for flg in +T +p "-T #broke here" -p; do
	echo " $site $flg " > /proc/dynamic_debug/control
    done;

    # A B ~B ~A
    for flg in +T +p "-p #broke here" -T; do
	echo " $site $flg " > /proc/dynamic_debug/control
    done
}
pt_test

Fixes: 84da83a6ffc0 dyndbg: combine flags & mask into a struct, simplify with it
CC: vincent.whitchurch@axis.com
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>

--
.drop @stable, no exposed bug.
---
 lib/dynamic_debug.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index dd7f56af9aed..a56c1286ffa4 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -211,10 +211,11 @@ static int ddebug_change(const struct ddebug_query *query,
 				continue;
 #ifdef CONFIG_JUMP_LABEL
 			if (dp->flags & _DPRINTK_FLAGS_PRINT) {
-				if (!(modifiers->flags & _DPRINTK_FLAGS_PRINT))
+				if (!(newflags & _DPRINTK_FLAGS_PRINT))
 					static_branch_disable(&dp->key.dd_key_true);
-			} else if (modifiers->flags & _DPRINTK_FLAGS_PRINT)
+			} else if (newflags & _DPRINTK_FLAGS_PRINT) {
 				static_branch_enable(&dp->key.dd_key_true);
+			}
 #endif
 			dp->flags = newflags;
 			v4pr_info("changed %s:%d [%s]%s =%s\n",
-- 
2.35.1


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

* [Intel-gfx] [PATCH 1/5] dyndbg: fix static_branch manipulation
@ 2022-03-11  4:47   ` Jim Cromie
  0 siblings, 0 replies; 49+ messages in thread
From: Jim Cromie @ 2022-03-11  4:47 UTC (permalink / raw)
  To: jbaron, gregkh, linux-kernel
  Cc: Jim Cromie, daniel.vetter, intel-gfx, vincent.whitchurch, linux,
	dri-devel, seanpaul, amd-gfx, joe, intel-gvt-dev

In https://lore.kernel.org/lkml/20211209150910.GA23668@axis.com/

Vincent's patch commented on, and worked around, a bug toggling
static_branch's, when a 2nd PRINTK-ish flag was added.  The bug
results in a premature static_branch_disable when the 1st of 2 flags
was disabled.

The cited commit computed newflags, but then in the JUMP_LABEL block,
failed to use that result, instead using just one of the terms in it.
Using newflags instead made the code work properly.

This is Vincents test-case, reduced.  It needs the 2nd flag to work
properly, but it's explanatory here.

pt_test() {
    echo 5 > /sys/module/dynamic_debug/verbose

    site="module tcp" # just one callsite
    echo " $site =_ " > /proc/dynamic_debug/control # clear it

    # A B ~A ~B
    for flg in +T +p "-T #broke here" -p; do
	echo " $site $flg " > /proc/dynamic_debug/control
    done;

    # A B ~B ~A
    for flg in +T +p "-p #broke here" -T; do
	echo " $site $flg " > /proc/dynamic_debug/control
    done
}
pt_test

Fixes: 84da83a6ffc0 dyndbg: combine flags & mask into a struct, simplify with it
CC: vincent.whitchurch@axis.com
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>

--
.drop @stable, no exposed bug.
---
 lib/dynamic_debug.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index dd7f56af9aed..a56c1286ffa4 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -211,10 +211,11 @@ static int ddebug_change(const struct ddebug_query *query,
 				continue;
 #ifdef CONFIG_JUMP_LABEL
 			if (dp->flags & _DPRINTK_FLAGS_PRINT) {
-				if (!(modifiers->flags & _DPRINTK_FLAGS_PRINT))
+				if (!(newflags & _DPRINTK_FLAGS_PRINT))
 					static_branch_disable(&dp->key.dd_key_true);
-			} else if (modifiers->flags & _DPRINTK_FLAGS_PRINT)
+			} else if (newflags & _DPRINTK_FLAGS_PRINT) {
 				static_branch_enable(&dp->key.dd_key_true);
+			}
 #endif
 			dp->flags = newflags;
 			v4pr_info("changed %s:%d [%s]%s =%s\n",
-- 
2.35.1


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

* [PATCH 1/5] dyndbg: fix static_branch manipulation
@ 2022-03-11  4:47   ` Jim Cromie
  0 siblings, 0 replies; 49+ messages in thread
From: Jim Cromie @ 2022-03-11  4:47 UTC (permalink / raw)
  To: jbaron, gregkh, linux-kernel
  Cc: Jim Cromie, daniel.vetter, intel-gfx, vincent.whitchurch, linux,
	dri-devel, robdclark, seanpaul, amd-gfx, joe, intel-gvt-dev

In https://lore.kernel.org/lkml/20211209150910.GA23668@axis.com/

Vincent's patch commented on, and worked around, a bug toggling
static_branch's, when a 2nd PRINTK-ish flag was added.  The bug
results in a premature static_branch_disable when the 1st of 2 flags
was disabled.

The cited commit computed newflags, but then in the JUMP_LABEL block,
failed to use that result, instead using just one of the terms in it.
Using newflags instead made the code work properly.

This is Vincents test-case, reduced.  It needs the 2nd flag to work
properly, but it's explanatory here.

pt_test() {
    echo 5 > /sys/module/dynamic_debug/verbose

    site="module tcp" # just one callsite
    echo " $site =_ " > /proc/dynamic_debug/control # clear it

    # A B ~A ~B
    for flg in +T +p "-T #broke here" -p; do
	echo " $site $flg " > /proc/dynamic_debug/control
    done;

    # A B ~B ~A
    for flg in +T +p "-p #broke here" -T; do
	echo " $site $flg " > /proc/dynamic_debug/control
    done
}
pt_test

Fixes: 84da83a6ffc0 dyndbg: combine flags & mask into a struct, simplify with it
CC: vincent.whitchurch@axis.com
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>

--
.drop @stable, no exposed bug.
---
 lib/dynamic_debug.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index dd7f56af9aed..a56c1286ffa4 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -211,10 +211,11 @@ static int ddebug_change(const struct ddebug_query *query,
 				continue;
 #ifdef CONFIG_JUMP_LABEL
 			if (dp->flags & _DPRINTK_FLAGS_PRINT) {
-				if (!(modifiers->flags & _DPRINTK_FLAGS_PRINT))
+				if (!(newflags & _DPRINTK_FLAGS_PRINT))
 					static_branch_disable(&dp->key.dd_key_true);
-			} else if (modifiers->flags & _DPRINTK_FLAGS_PRINT)
+			} else if (newflags & _DPRINTK_FLAGS_PRINT) {
 				static_branch_enable(&dp->key.dd_key_true);
+			}
 #endif
 			dp->flags = newflags;
 			v4pr_info("changed %s:%d [%s]%s =%s\n",
-- 
2.35.1


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

* [PATCH 2/5] dyndbg: add class_id field and query support
  2022-03-11  4:47 ` Jim Cromie
  (?)
  (?)
@ 2022-03-11  4:47   ` Jim Cromie
  -1 siblings, 0 replies; 49+ messages in thread
From: Jim Cromie @ 2022-03-11  4:47 UTC (permalink / raw)
  To: jbaron, gregkh, linux-kernel
  Cc: daniel.vetter, seanpaul, robdclark, linux, joe, dri-devel,
	amd-gfx, intel-gvt-dev, intel-gfx, Jim Cromie

DRM defines/uses 10 enum drm_debug_category's to create exclusive
classes of debug messages.  To support this directly in dynamic-debug,
add the following:

- struct _ddebug.class_id:4 - 4 bits is enough
- define _DPRINTK_SITE_UNCLASSED 15 - see below

and the query support:
- struct _ddebug_query.class_id
- ddebug_parse_query	- looks for "class" keyword, then calls..
- parse_class		- accepts uint: 0-15, sets query.class_id and marker
- vpr_info_dq		- displays new field
- ddebug_proc_show	- append column with "cls:%d" if !UNCLASSED

With the patch, one can enable current/unclassed callsites by:

  #> echo drm class 15 +p > /proc/dynamic_debug/control

parse_class() accepts 0 .. _DPRINTK_SITE_UNCLASSED, which allows the
>control interface to explicitly manipulate unclassed callsites.

After parsing keywords, ddebug_parse_query() sets .class_id=15, iff it
wasnt explicitly set.  This allows future classed/categorized
callsites to be untouched by legacy (class unaware) queries.

DEFINE_DYNAMIC_DEBUG_METADATA gets _CLS(cls,) suffix and arg, and
initializes the new .class_id=cls field.  The old name gets the default.

Then, these _CLS(cls,...) modifications are repeated up through the
stack of *dynamic_func_call* macros that use the METADATA initializer,
so as to actually supply the category into it.

NOTES:

_DPRINTK_SITE_UNCLASSED: this symbol is used to initialize all
existing/unclassed pr-debug callsites.  Normally, the default would be
zero, but DRM_UT_CORE "uses" that value, in the sense that 0 is
exposed as a bit position in drm.debug.  Using 15 allows identity
mapping from category to class, avoiding fiddly offsets.

Default .class_id = 15 means that ``echo +p > control`` no longer
toggles ALL the callsites, only the unclassed ones.  This was only
useful for static-branch toggle load testing anyway.

RFC:

The new _CLS macro flavor gets a warning from DRM/dri-devel's CI,
but not from checkpatch (on this subject).

a8f6c71f283e dyndbg: add class_id field and query support
-:141: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'id' - possible side-effects?
+#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {	\
+	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);	\
+	if (DYNAMIC_DEBUG_BRANCH(id))				\
+		func(&id, ##__VA_ARGS__);			\
 } while (0)

I couldn't fix it with a ``typeof(id) _id = id`` construct.  I haven't
seen the warning myself, on the _CLS extended macro, nor the original.

CC: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 .../admin-guide/dynamic-debug-howto.rst       |  7 +++
 include/linux/dynamic_debug.h                 | 54 ++++++++++++++-----
 lib/dynamic_debug.c                           | 48 ++++++++++++++---
 3 files changed, 88 insertions(+), 21 deletions(-)

diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst b/Documentation/admin-guide/dynamic-debug-howto.rst
index a89cfa083155..8ef8d7dcd140 100644
--- a/Documentation/admin-guide/dynamic-debug-howto.rst
+++ b/Documentation/admin-guide/dynamic-debug-howto.rst
@@ -35,6 +35,7 @@ Dynamic debug has even more useful features:
    - line number (including ranges of line numbers)
    - module name
    - format string
+   - class number:0-15
 
  * Provides a debugfs control file: ``<debugfs>/dynamic_debug/control``
    which can be read to display the complete list of known debug
@@ -143,6 +144,7 @@ against.  Possible keywords are:::
 		 'module' string |
 		 'format' string |
 		 'line' line-range
+		 'class' integer:[0-15]
 
   line-range ::= lineno |
 		 '-'lineno |
@@ -217,6 +219,11 @@ line
 	line -1605          // the 1605 lines from line 1 to line 1605
 	line 1600-          // all lines from line 1600 to the end of the file
 
+class
+    This expects a single integer in range: 0-15.
+    15 is used/reserved for existing/unclassed callsites,
+    and is defaulted in unless specified to >control
+
 The flags specification comprises a change operation followed
 by one or more flag characters.  The change operation is one
 of the characters::
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index dce631e678dd..d4b48f3cc6e8 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -6,6 +6,8 @@
 #include <linux/jump_label.h>
 #endif
 
+#include <linux/build_bug.h>
+
 /*
  * An instance of this structure is created in a special
  * ELF section at every dynamic debug callsite.  At runtime,
@@ -21,6 +23,9 @@ struct _ddebug {
 	const char *filename;
 	const char *format;
 	unsigned int lineno:18;
+#define CLS_BITS 4
+	unsigned int class_id:CLS_BITS;
+#define _DPRINTK_SITE_UNCLASSED		((1 << CLS_BITS) - 1)
 	/*
 	 * The flags field controls the behaviour at the callsite.
 	 * The bits here are changed dynamically when the user
@@ -87,7 +92,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 			 const struct ib_device *ibdev,
 			 const char *fmt, ...);
 
-#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)		\
+#define DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, cls, fmt)	\
 	static struct _ddebug  __aligned(8)			\
 	__section("__dyndbg") name = {				\
 		.modname = KBUILD_MODNAME,			\
@@ -96,8 +101,14 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 		.format = (fmt),				\
 		.lineno = __LINE__,				\
 		.flags = _DPRINTK_FLAGS_DEFAULT,		\
+		.class_id = cls,				\
 		_DPRINTK_KEY_INIT				\
-	}
+	};							\
+	BUILD_BUG_ON_MSG(cls > _DPRINTK_SITE_UNCLASSED,		\
+			 "classid value overflow")
+
+#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)		\
+	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, _DPRINTK_SITE_UNCLASSED, fmt)
 
 #ifdef CONFIG_JUMP_LABEL
 
@@ -128,18 +139,26 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 
 #endif /* CONFIG_JUMP_LABEL */
 
-#define __dynamic_func_call(id, fmt, func, ...) do {	\
-	DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt);		\
-	if (DYNAMIC_DEBUG_BRANCH(id))			\
-		func(&id, ##__VA_ARGS__);		\
+#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {	\
+	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);	\
+	if (DYNAMIC_DEBUG_BRANCH(id))				\
+		func(&id, ##__VA_ARGS__);			\
 } while (0)
 
-#define __dynamic_func_call_no_desc(id, fmt, func, ...) do {	\
-	DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt);			\
-	if (DYNAMIC_DEBUG_BRANCH(id))				\
-		func(__VA_ARGS__);				\
+#define __dynamic_func_call_no_desc_cls(id, cls, fmt, func, ...) do {	\
+	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);		\
+	if (DYNAMIC_DEBUG_BRANCH(id))					\
+		func(__VA_ARGS__);					\
 } while (0)
 
+#define __dynamic_func_call(id, fmt, func, ...)				\
+	__dynamic_func_call_cls(id, _DPRINTK_SITE_UNCLASSED,		\
+				fmt, func, ##__VA_ARGS__)
+
+#define __dynamic_func_call_no_desc(id, fmt, func, ...)			\
+	__dynamic_func_call_no_desc_cls(id, _DPRINTK_SITE_UNCLASSED,	\
+					fmt, func, ##__VA_ARGS__)
+
 /*
  * "Factory macro" for generating a call to func, guarded by a
  * DYNAMIC_DEBUG_BRANCH. The dynamic debug descriptor will be
@@ -148,15 +167,24 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
  * the varargs. Note that fmt is repeated in invocations of this
  * macro.
  */
+#define _dynamic_func_call_cls(cls, fmt, func, ...)			\
+	__dynamic_func_call_cls(__UNIQUE_ID(ddebug), cls, fmt, func, ##__VA_ARGS__)
 #define _dynamic_func_call(fmt, func, ...)				\
-	__dynamic_func_call(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
+	_dynamic_func_call_cls(_DPRINTK_SITE_UNCLASSED, fmt, func, ##__VA_ARGS__)
+
 /*
  * A variant that does the same, except that the descriptor is not
  * passed as the first argument to the function; it is only called
  * with precisely the macro's varargs.
  */
-#define _dynamic_func_call_no_desc(fmt, func, ...)	\
-	__dynamic_func_call_no_desc(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
+#define _dynamic_func_call_no_desc_cls(fmt, cat, func, ...)		\
+	__dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug), cat,	\
+					fmt, func, ##__VA_ARGS__)
+
+#define _dynamic_func_call_no_desc(fmt, func, ...)			\
+	__dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug),		\
+					_DPRINTK_SITE_UNCLASSED,	\
+					fmt, func, ##__VA_ARGS__)
 
 #define dynamic_pr_debug(fmt, ...)				\
 	_dynamic_func_call(fmt,	__dynamic_pr_debug,		\
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index a56c1286ffa4..ee2129becacc 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -55,6 +55,8 @@ struct ddebug_query {
 	const char *function;
 	const char *format;
 	unsigned int first_lineno, last_lineno;
+	unsigned int class_id;
+	unsigned int class_marked:1;
 };
 
 struct ddebug_iter {
@@ -134,13 +136,13 @@ static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
 			fmtlen--;
 	}
 
-	v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u\n",
-		 msg,
-		 query->function ?: "",
-		 query->filename ?: "",
-		 query->module ?: "",
-		 fmtlen, query->format ?: "",
-		 query->first_lineno, query->last_lineno);
+	v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u class=%u\n",
+		  msg,
+		  query->function ?: "",
+		  query->filename ?: "",
+		  query->module ?: "",
+		  fmtlen, query->format ?: "",
+		  query->first_lineno, query->last_lineno, query->class_id);
 }
 
 /*
@@ -170,6 +172,10 @@ static int ddebug_change(const struct ddebug_query *query,
 		for (i = 0; i < dt->num_ddebugs; i++) {
 			struct _ddebug *dp = &dt->ddebugs[i];
 
+			/* match against the class_id, either given or default */
+			if (query->class_id != dp->class_id)
+				continue;
+
 			/* match against the source filename */
 			if (query->filename &&
 			    !match_wildcard(query->filename, dp->filename) &&
@@ -308,6 +314,21 @@ static inline int parse_lineno(const char *str, unsigned int *val)
 	return 0;
 }
 
+static inline int parse_class(struct ddebug_query *query, const char *str)
+{
+	int rc;
+	unsigned int val;
+
+	rc = kstrtouint(str, 10, &val);
+	if (rc < 0 || val > _DPRINTK_SITE_UNCLASSED) {
+		pr_err("expecting class:[0-%d], not %s\n", _DPRINTK_SITE_UNCLASSED, str);
+		return -EINVAL;
+	}
+	query->class_id = val;
+	query->class_marked = 1;
+	return 0;
+}
+
 static int parse_linerange(struct ddebug_query *query, const char *first)
 {
 	char *last = strchr(first, '-');
@@ -421,6 +442,9 @@ static int ddebug_parse_query(char *words[], int nwords,
 		} else if (!strcmp(keyword, "line")) {
 			if (parse_linerange(query, arg))
 				return -EINVAL;
+		} else if (!strcmp(keyword, "class")) {
+			if (parse_class(query, arg))
+				return -EINVAL;
 		} else {
 			pr_err("unknown keyword \"%s\"\n", keyword);
 			return -EINVAL;
@@ -428,6 +452,10 @@ static int ddebug_parse_query(char *words[], int nwords,
 		if (rc)
 			return rc;
 	}
+	/* post-validate the query, set default */
+	if (!query->class_marked)
+		query->class_id = _DPRINTK_SITE_UNCLASSED;
+
 	vpr_info_dq(query, "parsed");
 	return 0;
 }
@@ -900,7 +928,11 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
 		   iter->table->mod_name, dp->function,
 		   ddebug_describe_flags(dp->flags, &flags));
 	seq_escape(m, dp->format, "\t\r\n\"");
-	seq_puts(m, "\"\n");
+	seq_puts(m, "\"");
+
+	if (dp->class_id != _DPRINTK_SITE_UNCLASSED)
+		seq_printf(m, " cls:%u", dp->class_id);
+	seq_puts(m, "\n");
 
 	return 0;
 }
-- 
2.35.1


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

* [PATCH 2/5] dyndbg: add class_id field and query support
@ 2022-03-11  4:47   ` Jim Cromie
  0 siblings, 0 replies; 49+ messages in thread
From: Jim Cromie @ 2022-03-11  4:47 UTC (permalink / raw)
  To: jbaron, gregkh, linux-kernel
  Cc: daniel.vetter, intel-gfx, linux, dri-devel, seanpaul, amd-gfx,
	joe, intel-gvt-dev

DRM defines/uses 10 enum drm_debug_category's to create exclusive
classes of debug messages.  To support this directly in dynamic-debug,
add the following:

- struct _ddebug.class_id:4 - 4 bits is enough
- define _DPRINTK_SITE_UNCLASSED 15 - see below

and the query support:
- struct _ddebug_query.class_id
- ddebug_parse_query	- looks for "class" keyword, then calls..
- parse_class		- accepts uint: 0-15, sets query.class_id and marker
- vpr_info_dq		- displays new field
- ddebug_proc_show	- append column with "cls:%d" if !UNCLASSED

With the patch, one can enable current/unclassed callsites by:

  #> echo drm class 15 +p > /proc/dynamic_debug/control

parse_class() accepts 0 .. _DPRINTK_SITE_UNCLASSED, which allows the
>control interface to explicitly manipulate unclassed callsites.

After parsing keywords, ddebug_parse_query() sets .class_id=15, iff it
wasnt explicitly set.  This allows future classed/categorized
callsites to be untouched by legacy (class unaware) queries.

DEFINE_DYNAMIC_DEBUG_METADATA gets _CLS(cls,) suffix and arg, and
initializes the new .class_id=cls field.  The old name gets the default.

Then, these _CLS(cls,...) modifications are repeated up through the
stack of *dynamic_func_call* macros that use the METADATA initializer,
so as to actually supply the category into it.

NOTES:

_DPRINTK_SITE_UNCLASSED: this symbol is used to initialize all
existing/unclassed pr-debug callsites.  Normally, the default would be
zero, but DRM_UT_CORE "uses" that value, in the sense that 0 is
exposed as a bit position in drm.debug.  Using 15 allows identity
mapping from category to class, avoiding fiddly offsets.

Default .class_id = 15 means that ``echo +p > control`` no longer
toggles ALL the callsites, only the unclassed ones.  This was only
useful for static-branch toggle load testing anyway.

RFC:

The new _CLS macro flavor gets a warning from DRM/dri-devel's CI,
but not from checkpatch (on this subject).

a8f6c71f283e dyndbg: add class_id field and query support
-:141: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'id' - possible side-effects?
+#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {	\
+	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);	\
+	if (DYNAMIC_DEBUG_BRANCH(id))				\
+		func(&id, ##__VA_ARGS__);			\
 } while (0)

I couldn't fix it with a ``typeof(id) _id = id`` construct.  I haven't
seen the warning myself, on the _CLS extended macro, nor the original.

CC: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 .../admin-guide/dynamic-debug-howto.rst       |  7 +++
 include/linux/dynamic_debug.h                 | 54 ++++++++++++++-----
 lib/dynamic_debug.c                           | 48 ++++++++++++++---
 3 files changed, 88 insertions(+), 21 deletions(-)

diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst b/Documentation/admin-guide/dynamic-debug-howto.rst
index a89cfa083155..8ef8d7dcd140 100644
--- a/Documentation/admin-guide/dynamic-debug-howto.rst
+++ b/Documentation/admin-guide/dynamic-debug-howto.rst
@@ -35,6 +35,7 @@ Dynamic debug has even more useful features:
    - line number (including ranges of line numbers)
    - module name
    - format string
+   - class number:0-15
 
  * Provides a debugfs control file: ``<debugfs>/dynamic_debug/control``
    which can be read to display the complete list of known debug
@@ -143,6 +144,7 @@ against.  Possible keywords are:::
 		 'module' string |
 		 'format' string |
 		 'line' line-range
+		 'class' integer:[0-15]
 
   line-range ::= lineno |
 		 '-'lineno |
@@ -217,6 +219,11 @@ line
 	line -1605          // the 1605 lines from line 1 to line 1605
 	line 1600-          // all lines from line 1600 to the end of the file
 
+class
+    This expects a single integer in range: 0-15.
+    15 is used/reserved for existing/unclassed callsites,
+    and is defaulted in unless specified to >control
+
 The flags specification comprises a change operation followed
 by one or more flag characters.  The change operation is one
 of the characters::
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index dce631e678dd..d4b48f3cc6e8 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -6,6 +6,8 @@
 #include <linux/jump_label.h>
 #endif
 
+#include <linux/build_bug.h>
+
 /*
  * An instance of this structure is created in a special
  * ELF section at every dynamic debug callsite.  At runtime,
@@ -21,6 +23,9 @@ struct _ddebug {
 	const char *filename;
 	const char *format;
 	unsigned int lineno:18;
+#define CLS_BITS 4
+	unsigned int class_id:CLS_BITS;
+#define _DPRINTK_SITE_UNCLASSED		((1 << CLS_BITS) - 1)
 	/*
 	 * The flags field controls the behaviour at the callsite.
 	 * The bits here are changed dynamically when the user
@@ -87,7 +92,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 			 const struct ib_device *ibdev,
 			 const char *fmt, ...);
 
-#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)		\
+#define DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, cls, fmt)	\
 	static struct _ddebug  __aligned(8)			\
 	__section("__dyndbg") name = {				\
 		.modname = KBUILD_MODNAME,			\
@@ -96,8 +101,14 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 		.format = (fmt),				\
 		.lineno = __LINE__,				\
 		.flags = _DPRINTK_FLAGS_DEFAULT,		\
+		.class_id = cls,				\
 		_DPRINTK_KEY_INIT				\
-	}
+	};							\
+	BUILD_BUG_ON_MSG(cls > _DPRINTK_SITE_UNCLASSED,		\
+			 "classid value overflow")
+
+#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)		\
+	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, _DPRINTK_SITE_UNCLASSED, fmt)
 
 #ifdef CONFIG_JUMP_LABEL
 
@@ -128,18 +139,26 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 
 #endif /* CONFIG_JUMP_LABEL */
 
-#define __dynamic_func_call(id, fmt, func, ...) do {	\
-	DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt);		\
-	if (DYNAMIC_DEBUG_BRANCH(id))			\
-		func(&id, ##__VA_ARGS__);		\
+#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {	\
+	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);	\
+	if (DYNAMIC_DEBUG_BRANCH(id))				\
+		func(&id, ##__VA_ARGS__);			\
 } while (0)
 
-#define __dynamic_func_call_no_desc(id, fmt, func, ...) do {	\
-	DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt);			\
-	if (DYNAMIC_DEBUG_BRANCH(id))				\
-		func(__VA_ARGS__);				\
+#define __dynamic_func_call_no_desc_cls(id, cls, fmt, func, ...) do {	\
+	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);		\
+	if (DYNAMIC_DEBUG_BRANCH(id))					\
+		func(__VA_ARGS__);					\
 } while (0)
 
+#define __dynamic_func_call(id, fmt, func, ...)				\
+	__dynamic_func_call_cls(id, _DPRINTK_SITE_UNCLASSED,		\
+				fmt, func, ##__VA_ARGS__)
+
+#define __dynamic_func_call_no_desc(id, fmt, func, ...)			\
+	__dynamic_func_call_no_desc_cls(id, _DPRINTK_SITE_UNCLASSED,	\
+					fmt, func, ##__VA_ARGS__)
+
 /*
  * "Factory macro" for generating a call to func, guarded by a
  * DYNAMIC_DEBUG_BRANCH. The dynamic debug descriptor will be
@@ -148,15 +167,24 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
  * the varargs. Note that fmt is repeated in invocations of this
  * macro.
  */
+#define _dynamic_func_call_cls(cls, fmt, func, ...)			\
+	__dynamic_func_call_cls(__UNIQUE_ID(ddebug), cls, fmt, func, ##__VA_ARGS__)
 #define _dynamic_func_call(fmt, func, ...)				\
-	__dynamic_func_call(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
+	_dynamic_func_call_cls(_DPRINTK_SITE_UNCLASSED, fmt, func, ##__VA_ARGS__)
+
 /*
  * A variant that does the same, except that the descriptor is not
  * passed as the first argument to the function; it is only called
  * with precisely the macro's varargs.
  */
-#define _dynamic_func_call_no_desc(fmt, func, ...)	\
-	__dynamic_func_call_no_desc(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
+#define _dynamic_func_call_no_desc_cls(fmt, cat, func, ...)		\
+	__dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug), cat,	\
+					fmt, func, ##__VA_ARGS__)
+
+#define _dynamic_func_call_no_desc(fmt, func, ...)			\
+	__dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug),		\
+					_DPRINTK_SITE_UNCLASSED,	\
+					fmt, func, ##__VA_ARGS__)
 
 #define dynamic_pr_debug(fmt, ...)				\
 	_dynamic_func_call(fmt,	__dynamic_pr_debug,		\
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index a56c1286ffa4..ee2129becacc 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -55,6 +55,8 @@ struct ddebug_query {
 	const char *function;
 	const char *format;
 	unsigned int first_lineno, last_lineno;
+	unsigned int class_id;
+	unsigned int class_marked:1;
 };
 
 struct ddebug_iter {
@@ -134,13 +136,13 @@ static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
 			fmtlen--;
 	}
 
-	v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u\n",
-		 msg,
-		 query->function ?: "",
-		 query->filename ?: "",
-		 query->module ?: "",
-		 fmtlen, query->format ?: "",
-		 query->first_lineno, query->last_lineno);
+	v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u class=%u\n",
+		  msg,
+		  query->function ?: "",
+		  query->filename ?: "",
+		  query->module ?: "",
+		  fmtlen, query->format ?: "",
+		  query->first_lineno, query->last_lineno, query->class_id);
 }
 
 /*
@@ -170,6 +172,10 @@ static int ddebug_change(const struct ddebug_query *query,
 		for (i = 0; i < dt->num_ddebugs; i++) {
 			struct _ddebug *dp = &dt->ddebugs[i];
 
+			/* match against the class_id, either given or default */
+			if (query->class_id != dp->class_id)
+				continue;
+
 			/* match against the source filename */
 			if (query->filename &&
 			    !match_wildcard(query->filename, dp->filename) &&
@@ -308,6 +314,21 @@ static inline int parse_lineno(const char *str, unsigned int *val)
 	return 0;
 }
 
+static inline int parse_class(struct ddebug_query *query, const char *str)
+{
+	int rc;
+	unsigned int val;
+
+	rc = kstrtouint(str, 10, &val);
+	if (rc < 0 || val > _DPRINTK_SITE_UNCLASSED) {
+		pr_err("expecting class:[0-%d], not %s\n", _DPRINTK_SITE_UNCLASSED, str);
+		return -EINVAL;
+	}
+	query->class_id = val;
+	query->class_marked = 1;
+	return 0;
+}
+
 static int parse_linerange(struct ddebug_query *query, const char *first)
 {
 	char *last = strchr(first, '-');
@@ -421,6 +442,9 @@ static int ddebug_parse_query(char *words[], int nwords,
 		} else if (!strcmp(keyword, "line")) {
 			if (parse_linerange(query, arg))
 				return -EINVAL;
+		} else if (!strcmp(keyword, "class")) {
+			if (parse_class(query, arg))
+				return -EINVAL;
 		} else {
 			pr_err("unknown keyword \"%s\"\n", keyword);
 			return -EINVAL;
@@ -428,6 +452,10 @@ static int ddebug_parse_query(char *words[], int nwords,
 		if (rc)
 			return rc;
 	}
+	/* post-validate the query, set default */
+	if (!query->class_marked)
+		query->class_id = _DPRINTK_SITE_UNCLASSED;
+
 	vpr_info_dq(query, "parsed");
 	return 0;
 }
@@ -900,7 +928,11 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
 		   iter->table->mod_name, dp->function,
 		   ddebug_describe_flags(dp->flags, &flags));
 	seq_escape(m, dp->format, "\t\r\n\"");
-	seq_puts(m, "\"\n");
+	seq_puts(m, "\"");
+
+	if (dp->class_id != _DPRINTK_SITE_UNCLASSED)
+		seq_printf(m, " cls:%u", dp->class_id);
+	seq_puts(m, "\n");
 
 	return 0;
 }
-- 
2.35.1


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

* [Intel-gfx] [PATCH 2/5] dyndbg: add class_id field and query support
@ 2022-03-11  4:47   ` Jim Cromie
  0 siblings, 0 replies; 49+ messages in thread
From: Jim Cromie @ 2022-03-11  4:47 UTC (permalink / raw)
  To: jbaron, gregkh, linux-kernel
  Cc: Jim Cromie, daniel.vetter, intel-gfx, linux, dri-devel, seanpaul,
	amd-gfx, joe, intel-gvt-dev

DRM defines/uses 10 enum drm_debug_category's to create exclusive
classes of debug messages.  To support this directly in dynamic-debug,
add the following:

- struct _ddebug.class_id:4 - 4 bits is enough
- define _DPRINTK_SITE_UNCLASSED 15 - see below

and the query support:
- struct _ddebug_query.class_id
- ddebug_parse_query	- looks for "class" keyword, then calls..
- parse_class		- accepts uint: 0-15, sets query.class_id and marker
- vpr_info_dq		- displays new field
- ddebug_proc_show	- append column with "cls:%d" if !UNCLASSED

With the patch, one can enable current/unclassed callsites by:

  #> echo drm class 15 +p > /proc/dynamic_debug/control

parse_class() accepts 0 .. _DPRINTK_SITE_UNCLASSED, which allows the
>control interface to explicitly manipulate unclassed callsites.

After parsing keywords, ddebug_parse_query() sets .class_id=15, iff it
wasnt explicitly set.  This allows future classed/categorized
callsites to be untouched by legacy (class unaware) queries.

DEFINE_DYNAMIC_DEBUG_METADATA gets _CLS(cls,) suffix and arg, and
initializes the new .class_id=cls field.  The old name gets the default.

Then, these _CLS(cls,...) modifications are repeated up through the
stack of *dynamic_func_call* macros that use the METADATA initializer,
so as to actually supply the category into it.

NOTES:

_DPRINTK_SITE_UNCLASSED: this symbol is used to initialize all
existing/unclassed pr-debug callsites.  Normally, the default would be
zero, but DRM_UT_CORE "uses" that value, in the sense that 0 is
exposed as a bit position in drm.debug.  Using 15 allows identity
mapping from category to class, avoiding fiddly offsets.

Default .class_id = 15 means that ``echo +p > control`` no longer
toggles ALL the callsites, only the unclassed ones.  This was only
useful for static-branch toggle load testing anyway.

RFC:

The new _CLS macro flavor gets a warning from DRM/dri-devel's CI,
but not from checkpatch (on this subject).

a8f6c71f283e dyndbg: add class_id field and query support
-:141: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'id' - possible side-effects?
+#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {	\
+	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);	\
+	if (DYNAMIC_DEBUG_BRANCH(id))				\
+		func(&id, ##__VA_ARGS__);			\
 } while (0)

I couldn't fix it with a ``typeof(id) _id = id`` construct.  I haven't
seen the warning myself, on the _CLS extended macro, nor the original.

CC: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 .../admin-guide/dynamic-debug-howto.rst       |  7 +++
 include/linux/dynamic_debug.h                 | 54 ++++++++++++++-----
 lib/dynamic_debug.c                           | 48 ++++++++++++++---
 3 files changed, 88 insertions(+), 21 deletions(-)

diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst b/Documentation/admin-guide/dynamic-debug-howto.rst
index a89cfa083155..8ef8d7dcd140 100644
--- a/Documentation/admin-guide/dynamic-debug-howto.rst
+++ b/Documentation/admin-guide/dynamic-debug-howto.rst
@@ -35,6 +35,7 @@ Dynamic debug has even more useful features:
    - line number (including ranges of line numbers)
    - module name
    - format string
+   - class number:0-15
 
  * Provides a debugfs control file: ``<debugfs>/dynamic_debug/control``
    which can be read to display the complete list of known debug
@@ -143,6 +144,7 @@ against.  Possible keywords are:::
 		 'module' string |
 		 'format' string |
 		 'line' line-range
+		 'class' integer:[0-15]
 
   line-range ::= lineno |
 		 '-'lineno |
@@ -217,6 +219,11 @@ line
 	line -1605          // the 1605 lines from line 1 to line 1605
 	line 1600-          // all lines from line 1600 to the end of the file
 
+class
+    This expects a single integer in range: 0-15.
+    15 is used/reserved for existing/unclassed callsites,
+    and is defaulted in unless specified to >control
+
 The flags specification comprises a change operation followed
 by one or more flag characters.  The change operation is one
 of the characters::
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index dce631e678dd..d4b48f3cc6e8 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -6,6 +6,8 @@
 #include <linux/jump_label.h>
 #endif
 
+#include <linux/build_bug.h>
+
 /*
  * An instance of this structure is created in a special
  * ELF section at every dynamic debug callsite.  At runtime,
@@ -21,6 +23,9 @@ struct _ddebug {
 	const char *filename;
 	const char *format;
 	unsigned int lineno:18;
+#define CLS_BITS 4
+	unsigned int class_id:CLS_BITS;
+#define _DPRINTK_SITE_UNCLASSED		((1 << CLS_BITS) - 1)
 	/*
 	 * The flags field controls the behaviour at the callsite.
 	 * The bits here are changed dynamically when the user
@@ -87,7 +92,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 			 const struct ib_device *ibdev,
 			 const char *fmt, ...);
 
-#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)		\
+#define DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, cls, fmt)	\
 	static struct _ddebug  __aligned(8)			\
 	__section("__dyndbg") name = {				\
 		.modname = KBUILD_MODNAME,			\
@@ -96,8 +101,14 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 		.format = (fmt),				\
 		.lineno = __LINE__,				\
 		.flags = _DPRINTK_FLAGS_DEFAULT,		\
+		.class_id = cls,				\
 		_DPRINTK_KEY_INIT				\
-	}
+	};							\
+	BUILD_BUG_ON_MSG(cls > _DPRINTK_SITE_UNCLASSED,		\
+			 "classid value overflow")
+
+#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)		\
+	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, _DPRINTK_SITE_UNCLASSED, fmt)
 
 #ifdef CONFIG_JUMP_LABEL
 
@@ -128,18 +139,26 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 
 #endif /* CONFIG_JUMP_LABEL */
 
-#define __dynamic_func_call(id, fmt, func, ...) do {	\
-	DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt);		\
-	if (DYNAMIC_DEBUG_BRANCH(id))			\
-		func(&id, ##__VA_ARGS__);		\
+#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {	\
+	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);	\
+	if (DYNAMIC_DEBUG_BRANCH(id))				\
+		func(&id, ##__VA_ARGS__);			\
 } while (0)
 
-#define __dynamic_func_call_no_desc(id, fmt, func, ...) do {	\
-	DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt);			\
-	if (DYNAMIC_DEBUG_BRANCH(id))				\
-		func(__VA_ARGS__);				\
+#define __dynamic_func_call_no_desc_cls(id, cls, fmt, func, ...) do {	\
+	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);		\
+	if (DYNAMIC_DEBUG_BRANCH(id))					\
+		func(__VA_ARGS__);					\
 } while (0)
 
+#define __dynamic_func_call(id, fmt, func, ...)				\
+	__dynamic_func_call_cls(id, _DPRINTK_SITE_UNCLASSED,		\
+				fmt, func, ##__VA_ARGS__)
+
+#define __dynamic_func_call_no_desc(id, fmt, func, ...)			\
+	__dynamic_func_call_no_desc_cls(id, _DPRINTK_SITE_UNCLASSED,	\
+					fmt, func, ##__VA_ARGS__)
+
 /*
  * "Factory macro" for generating a call to func, guarded by a
  * DYNAMIC_DEBUG_BRANCH. The dynamic debug descriptor will be
@@ -148,15 +167,24 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
  * the varargs. Note that fmt is repeated in invocations of this
  * macro.
  */
+#define _dynamic_func_call_cls(cls, fmt, func, ...)			\
+	__dynamic_func_call_cls(__UNIQUE_ID(ddebug), cls, fmt, func, ##__VA_ARGS__)
 #define _dynamic_func_call(fmt, func, ...)				\
-	__dynamic_func_call(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
+	_dynamic_func_call_cls(_DPRINTK_SITE_UNCLASSED, fmt, func, ##__VA_ARGS__)
+
 /*
  * A variant that does the same, except that the descriptor is not
  * passed as the first argument to the function; it is only called
  * with precisely the macro's varargs.
  */
-#define _dynamic_func_call_no_desc(fmt, func, ...)	\
-	__dynamic_func_call_no_desc(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
+#define _dynamic_func_call_no_desc_cls(fmt, cat, func, ...)		\
+	__dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug), cat,	\
+					fmt, func, ##__VA_ARGS__)
+
+#define _dynamic_func_call_no_desc(fmt, func, ...)			\
+	__dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug),		\
+					_DPRINTK_SITE_UNCLASSED,	\
+					fmt, func, ##__VA_ARGS__)
 
 #define dynamic_pr_debug(fmt, ...)				\
 	_dynamic_func_call(fmt,	__dynamic_pr_debug,		\
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index a56c1286ffa4..ee2129becacc 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -55,6 +55,8 @@ struct ddebug_query {
 	const char *function;
 	const char *format;
 	unsigned int first_lineno, last_lineno;
+	unsigned int class_id;
+	unsigned int class_marked:1;
 };
 
 struct ddebug_iter {
@@ -134,13 +136,13 @@ static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
 			fmtlen--;
 	}
 
-	v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u\n",
-		 msg,
-		 query->function ?: "",
-		 query->filename ?: "",
-		 query->module ?: "",
-		 fmtlen, query->format ?: "",
-		 query->first_lineno, query->last_lineno);
+	v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u class=%u\n",
+		  msg,
+		  query->function ?: "",
+		  query->filename ?: "",
+		  query->module ?: "",
+		  fmtlen, query->format ?: "",
+		  query->first_lineno, query->last_lineno, query->class_id);
 }
 
 /*
@@ -170,6 +172,10 @@ static int ddebug_change(const struct ddebug_query *query,
 		for (i = 0; i < dt->num_ddebugs; i++) {
 			struct _ddebug *dp = &dt->ddebugs[i];
 
+			/* match against the class_id, either given or default */
+			if (query->class_id != dp->class_id)
+				continue;
+
 			/* match against the source filename */
 			if (query->filename &&
 			    !match_wildcard(query->filename, dp->filename) &&
@@ -308,6 +314,21 @@ static inline int parse_lineno(const char *str, unsigned int *val)
 	return 0;
 }
 
+static inline int parse_class(struct ddebug_query *query, const char *str)
+{
+	int rc;
+	unsigned int val;
+
+	rc = kstrtouint(str, 10, &val);
+	if (rc < 0 || val > _DPRINTK_SITE_UNCLASSED) {
+		pr_err("expecting class:[0-%d], not %s\n", _DPRINTK_SITE_UNCLASSED, str);
+		return -EINVAL;
+	}
+	query->class_id = val;
+	query->class_marked = 1;
+	return 0;
+}
+
 static int parse_linerange(struct ddebug_query *query, const char *first)
 {
 	char *last = strchr(first, '-');
@@ -421,6 +442,9 @@ static int ddebug_parse_query(char *words[], int nwords,
 		} else if (!strcmp(keyword, "line")) {
 			if (parse_linerange(query, arg))
 				return -EINVAL;
+		} else if (!strcmp(keyword, "class")) {
+			if (parse_class(query, arg))
+				return -EINVAL;
 		} else {
 			pr_err("unknown keyword \"%s\"\n", keyword);
 			return -EINVAL;
@@ -428,6 +452,10 @@ static int ddebug_parse_query(char *words[], int nwords,
 		if (rc)
 			return rc;
 	}
+	/* post-validate the query, set default */
+	if (!query->class_marked)
+		query->class_id = _DPRINTK_SITE_UNCLASSED;
+
 	vpr_info_dq(query, "parsed");
 	return 0;
 }
@@ -900,7 +928,11 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
 		   iter->table->mod_name, dp->function,
 		   ddebug_describe_flags(dp->flags, &flags));
 	seq_escape(m, dp->format, "\t\r\n\"");
-	seq_puts(m, "\"\n");
+	seq_puts(m, "\"");
+
+	if (dp->class_id != _DPRINTK_SITE_UNCLASSED)
+		seq_printf(m, " cls:%u", dp->class_id);
+	seq_puts(m, "\n");
 
 	return 0;
 }
-- 
2.35.1


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

* [PATCH 2/5] dyndbg: add class_id field and query support
@ 2022-03-11  4:47   ` Jim Cromie
  0 siblings, 0 replies; 49+ messages in thread
From: Jim Cromie @ 2022-03-11  4:47 UTC (permalink / raw)
  To: jbaron, gregkh, linux-kernel
  Cc: Jim Cromie, daniel.vetter, intel-gfx, linux, dri-devel,
	robdclark, seanpaul, amd-gfx, joe, intel-gvt-dev

DRM defines/uses 10 enum drm_debug_category's to create exclusive
classes of debug messages.  To support this directly in dynamic-debug,
add the following:

- struct _ddebug.class_id:4 - 4 bits is enough
- define _DPRINTK_SITE_UNCLASSED 15 - see below

and the query support:
- struct _ddebug_query.class_id
- ddebug_parse_query	- looks for "class" keyword, then calls..
- parse_class		- accepts uint: 0-15, sets query.class_id and marker
- vpr_info_dq		- displays new field
- ddebug_proc_show	- append column with "cls:%d" if !UNCLASSED

With the patch, one can enable current/unclassed callsites by:

  #> echo drm class 15 +p > /proc/dynamic_debug/control

parse_class() accepts 0 .. _DPRINTK_SITE_UNCLASSED, which allows the
>control interface to explicitly manipulate unclassed callsites.

After parsing keywords, ddebug_parse_query() sets .class_id=15, iff it
wasnt explicitly set.  This allows future classed/categorized
callsites to be untouched by legacy (class unaware) queries.

DEFINE_DYNAMIC_DEBUG_METADATA gets _CLS(cls,) suffix and arg, and
initializes the new .class_id=cls field.  The old name gets the default.

Then, these _CLS(cls,...) modifications are repeated up through the
stack of *dynamic_func_call* macros that use the METADATA initializer,
so as to actually supply the category into it.

NOTES:

_DPRINTK_SITE_UNCLASSED: this symbol is used to initialize all
existing/unclassed pr-debug callsites.  Normally, the default would be
zero, but DRM_UT_CORE "uses" that value, in the sense that 0 is
exposed as a bit position in drm.debug.  Using 15 allows identity
mapping from category to class, avoiding fiddly offsets.

Default .class_id = 15 means that ``echo +p > control`` no longer
toggles ALL the callsites, only the unclassed ones.  This was only
useful for static-branch toggle load testing anyway.

RFC:

The new _CLS macro flavor gets a warning from DRM/dri-devel's CI,
but not from checkpatch (on this subject).

a8f6c71f283e dyndbg: add class_id field and query support
-:141: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'id' - possible side-effects?
+#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {	\
+	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);	\
+	if (DYNAMIC_DEBUG_BRANCH(id))				\
+		func(&id, ##__VA_ARGS__);			\
 } while (0)

I couldn't fix it with a ``typeof(id) _id = id`` construct.  I haven't
seen the warning myself, on the _CLS extended macro, nor the original.

CC: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 .../admin-guide/dynamic-debug-howto.rst       |  7 +++
 include/linux/dynamic_debug.h                 | 54 ++++++++++++++-----
 lib/dynamic_debug.c                           | 48 ++++++++++++++---
 3 files changed, 88 insertions(+), 21 deletions(-)

diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst b/Documentation/admin-guide/dynamic-debug-howto.rst
index a89cfa083155..8ef8d7dcd140 100644
--- a/Documentation/admin-guide/dynamic-debug-howto.rst
+++ b/Documentation/admin-guide/dynamic-debug-howto.rst
@@ -35,6 +35,7 @@ Dynamic debug has even more useful features:
    - line number (including ranges of line numbers)
    - module name
    - format string
+   - class number:0-15
 
  * Provides a debugfs control file: ``<debugfs>/dynamic_debug/control``
    which can be read to display the complete list of known debug
@@ -143,6 +144,7 @@ against.  Possible keywords are:::
 		 'module' string |
 		 'format' string |
 		 'line' line-range
+		 'class' integer:[0-15]
 
   line-range ::= lineno |
 		 '-'lineno |
@@ -217,6 +219,11 @@ line
 	line -1605          // the 1605 lines from line 1 to line 1605
 	line 1600-          // all lines from line 1600 to the end of the file
 
+class
+    This expects a single integer in range: 0-15.
+    15 is used/reserved for existing/unclassed callsites,
+    and is defaulted in unless specified to >control
+
 The flags specification comprises a change operation followed
 by one or more flag characters.  The change operation is one
 of the characters::
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index dce631e678dd..d4b48f3cc6e8 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -6,6 +6,8 @@
 #include <linux/jump_label.h>
 #endif
 
+#include <linux/build_bug.h>
+
 /*
  * An instance of this structure is created in a special
  * ELF section at every dynamic debug callsite.  At runtime,
@@ -21,6 +23,9 @@ struct _ddebug {
 	const char *filename;
 	const char *format;
 	unsigned int lineno:18;
+#define CLS_BITS 4
+	unsigned int class_id:CLS_BITS;
+#define _DPRINTK_SITE_UNCLASSED		((1 << CLS_BITS) - 1)
 	/*
 	 * The flags field controls the behaviour at the callsite.
 	 * The bits here are changed dynamically when the user
@@ -87,7 +92,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 			 const struct ib_device *ibdev,
 			 const char *fmt, ...);
 
-#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)		\
+#define DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, cls, fmt)	\
 	static struct _ddebug  __aligned(8)			\
 	__section("__dyndbg") name = {				\
 		.modname = KBUILD_MODNAME,			\
@@ -96,8 +101,14 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 		.format = (fmt),				\
 		.lineno = __LINE__,				\
 		.flags = _DPRINTK_FLAGS_DEFAULT,		\
+		.class_id = cls,				\
 		_DPRINTK_KEY_INIT				\
-	}
+	};							\
+	BUILD_BUG_ON_MSG(cls > _DPRINTK_SITE_UNCLASSED,		\
+			 "classid value overflow")
+
+#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)		\
+	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, _DPRINTK_SITE_UNCLASSED, fmt)
 
 #ifdef CONFIG_JUMP_LABEL
 
@@ -128,18 +139,26 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 
 #endif /* CONFIG_JUMP_LABEL */
 
-#define __dynamic_func_call(id, fmt, func, ...) do {	\
-	DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt);		\
-	if (DYNAMIC_DEBUG_BRANCH(id))			\
-		func(&id, ##__VA_ARGS__);		\
+#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {	\
+	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);	\
+	if (DYNAMIC_DEBUG_BRANCH(id))				\
+		func(&id, ##__VA_ARGS__);			\
 } while (0)
 
-#define __dynamic_func_call_no_desc(id, fmt, func, ...) do {	\
-	DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt);			\
-	if (DYNAMIC_DEBUG_BRANCH(id))				\
-		func(__VA_ARGS__);				\
+#define __dynamic_func_call_no_desc_cls(id, cls, fmt, func, ...) do {	\
+	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);		\
+	if (DYNAMIC_DEBUG_BRANCH(id))					\
+		func(__VA_ARGS__);					\
 } while (0)
 
+#define __dynamic_func_call(id, fmt, func, ...)				\
+	__dynamic_func_call_cls(id, _DPRINTK_SITE_UNCLASSED,		\
+				fmt, func, ##__VA_ARGS__)
+
+#define __dynamic_func_call_no_desc(id, fmt, func, ...)			\
+	__dynamic_func_call_no_desc_cls(id, _DPRINTK_SITE_UNCLASSED,	\
+					fmt, func, ##__VA_ARGS__)
+
 /*
  * "Factory macro" for generating a call to func, guarded by a
  * DYNAMIC_DEBUG_BRANCH. The dynamic debug descriptor will be
@@ -148,15 +167,24 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
  * the varargs. Note that fmt is repeated in invocations of this
  * macro.
  */
+#define _dynamic_func_call_cls(cls, fmt, func, ...)			\
+	__dynamic_func_call_cls(__UNIQUE_ID(ddebug), cls, fmt, func, ##__VA_ARGS__)
 #define _dynamic_func_call(fmt, func, ...)				\
-	__dynamic_func_call(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
+	_dynamic_func_call_cls(_DPRINTK_SITE_UNCLASSED, fmt, func, ##__VA_ARGS__)
+
 /*
  * A variant that does the same, except that the descriptor is not
  * passed as the first argument to the function; it is only called
  * with precisely the macro's varargs.
  */
-#define _dynamic_func_call_no_desc(fmt, func, ...)	\
-	__dynamic_func_call_no_desc(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
+#define _dynamic_func_call_no_desc_cls(fmt, cat, func, ...)		\
+	__dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug), cat,	\
+					fmt, func, ##__VA_ARGS__)
+
+#define _dynamic_func_call_no_desc(fmt, func, ...)			\
+	__dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug),		\
+					_DPRINTK_SITE_UNCLASSED,	\
+					fmt, func, ##__VA_ARGS__)
 
 #define dynamic_pr_debug(fmt, ...)				\
 	_dynamic_func_call(fmt,	__dynamic_pr_debug,		\
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index a56c1286ffa4..ee2129becacc 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -55,6 +55,8 @@ struct ddebug_query {
 	const char *function;
 	const char *format;
 	unsigned int first_lineno, last_lineno;
+	unsigned int class_id;
+	unsigned int class_marked:1;
 };
 
 struct ddebug_iter {
@@ -134,13 +136,13 @@ static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
 			fmtlen--;
 	}
 
-	v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u\n",
-		 msg,
-		 query->function ?: "",
-		 query->filename ?: "",
-		 query->module ?: "",
-		 fmtlen, query->format ?: "",
-		 query->first_lineno, query->last_lineno);
+	v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u class=%u\n",
+		  msg,
+		  query->function ?: "",
+		  query->filename ?: "",
+		  query->module ?: "",
+		  fmtlen, query->format ?: "",
+		  query->first_lineno, query->last_lineno, query->class_id);
 }
 
 /*
@@ -170,6 +172,10 @@ static int ddebug_change(const struct ddebug_query *query,
 		for (i = 0; i < dt->num_ddebugs; i++) {
 			struct _ddebug *dp = &dt->ddebugs[i];
 
+			/* match against the class_id, either given or default */
+			if (query->class_id != dp->class_id)
+				continue;
+
 			/* match against the source filename */
 			if (query->filename &&
 			    !match_wildcard(query->filename, dp->filename) &&
@@ -308,6 +314,21 @@ static inline int parse_lineno(const char *str, unsigned int *val)
 	return 0;
 }
 
+static inline int parse_class(struct ddebug_query *query, const char *str)
+{
+	int rc;
+	unsigned int val;
+
+	rc = kstrtouint(str, 10, &val);
+	if (rc < 0 || val > _DPRINTK_SITE_UNCLASSED) {
+		pr_err("expecting class:[0-%d], not %s\n", _DPRINTK_SITE_UNCLASSED, str);
+		return -EINVAL;
+	}
+	query->class_id = val;
+	query->class_marked = 1;
+	return 0;
+}
+
 static int parse_linerange(struct ddebug_query *query, const char *first)
 {
 	char *last = strchr(first, '-');
@@ -421,6 +442,9 @@ static int ddebug_parse_query(char *words[], int nwords,
 		} else if (!strcmp(keyword, "line")) {
 			if (parse_linerange(query, arg))
 				return -EINVAL;
+		} else if (!strcmp(keyword, "class")) {
+			if (parse_class(query, arg))
+				return -EINVAL;
 		} else {
 			pr_err("unknown keyword \"%s\"\n", keyword);
 			return -EINVAL;
@@ -428,6 +452,10 @@ static int ddebug_parse_query(char *words[], int nwords,
 		if (rc)
 			return rc;
 	}
+	/* post-validate the query, set default */
+	if (!query->class_marked)
+		query->class_id = _DPRINTK_SITE_UNCLASSED;
+
 	vpr_info_dq(query, "parsed");
 	return 0;
 }
@@ -900,7 +928,11 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
 		   iter->table->mod_name, dp->function,
 		   ddebug_describe_flags(dp->flags, &flags));
 	seq_escape(m, dp->format, "\t\r\n\"");
-	seq_puts(m, "\"\n");
+	seq_puts(m, "\"");
+
+	if (dp->class_id != _DPRINTK_SITE_UNCLASSED)
+		seq_printf(m, " cls:%u", dp->class_id);
+	seq_puts(m, "\n");
 
 	return 0;
 }
-- 
2.35.1


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

* [PATCH 3/5] dyndbg: add DEFINE_DYNAMIC_DEBUG_CLASSBITS macro
  2022-03-11  4:47 ` Jim Cromie
  (?)
  (?)
@ 2022-03-11  4:47   ` Jim Cromie
  -1 siblings, 0 replies; 49+ messages in thread
From: Jim Cromie @ 2022-03-11  4:47 UTC (permalink / raw)
  To: jbaron, gregkh, linux-kernel
  Cc: daniel.vetter, seanpaul, robdclark, linux, joe, dri-devel,
	amd-gfx, intel-gvt-dev, intel-gfx, Jim Cromie

DEFINE_DYNAMIC_DEBUG_CLASSBITS(fsname, var, bitmap_desc, classes..)
allows users to create a drm.debug style (bitmap) sysfs interface, to
control sets of pr_debug's according to their .class_id's

This wraps existing "class" keyword and behavior:

   bash-5.1# echo <<END  > /proc/dynamic_debug/control
   > module drm class 0 +p
   > module drm class 2 +p
   > END

With the macro used (in a client), this is basically equivalent:

   # but this also clears other flags, if theyre set
   echo 0x05 > /sys/module/drm/parameters/debug

To use:

DEFINE_DYNAMIC_DEBUG_CLASSBITS(debug, __drm_debug, "pmfl",
	"drm.debug - bits => categories:",
	/* vector of uint:4 symbols, ala enum drm_debug_category, 15 is EOL */
	DRM_UT_CORE,
	DRM_UT_DRIVER,
	DRM_UT_KMS ... );

The 3rd arg is a string with any of the dyndbg.flags [pmflt_]+
Full exposure of the flags here lets the module author:

- fully customize/take-over the decorations of enabled sites.
  generally leaving decorations to user is preferred.

- aim the debug-stream:
  now printk, later tracefs.
  using both together means more work (p or T, in practice)
  iface doesn't care about new flags added later

- declare 2 separate sysfs-knobs, one each for p, T, if desired.

- decorations are per callsite,
  shared across sysfs-knobs for any controlled classes

To support the macro, the patch adds:

 - int param_set_dyndbg_classbits()
 - int param_get_dyndbg_classbits()
 - struct kernel_param_ops param_ops_dyndbg_classbits

Following the model of kernel/params.c STANDARD_PARAM_DEFS, these are
non-static and exported.

get/set use an augmented kernel_param; the arg refs a new struct
dyndbg_bitmap_param containing:

A- the vector of classes (drm.debug "categories") being controlled

This in-line vector of constants (uint [0-14]) specifies a sequence of
controlling bits (by position, starting at 0) with the values naming
the class_id's mapped to that bit.

A value of _DPRINTK_SITE_UNCLASSED terminates the vector processing by
param_set_dyndbg_classbits(), and is appended by the macro to insure a
defined termination after max 15 classes are applied.

Technically, the vector is a flex-array, but its size is practically
limited to max 15 in length (repeats are pointless).

B- a pointer to the user module's ulong holding the bits/state.

By accessing client's bit-state, we coordinate with existing code
that still uses drm_debug_enabled(), so they work unchanged.
The change to ulong allows use of BIT() etc.

NOTES:

_DPRINTK_SITE_UNCLASSED = 15, ie 2**CLS_BITS-1, deserves special
mention; it already marks all existing pr-debug callsites, only the
new drm.debug callsites are initialized to other (DRM_UT_*) values.

_DPRINTK_SITE_UNCLASSED is used in param_set_dyndbg_classbits() to
limit the range of bits that are processed to what fits in uint:4.
It also terminates the class-id list passed into the macro, so dont
use it halfway through your list of classes-to-control.

param_set_dyndbg_classbits() compares new vs old bits, and only
updates each class on changes.  This maximally preserves the
underlying state, which may have been customized at some point via
`echo $cmd >control`.  So if users really want to know that all
prdbgs are set precisely, they must pre-clear then set.

Identity mapping in (A) is encouraged.  Your vector should exclude 15,
if used, it terminates the list prematurely; any following bit
mappings will be ignored (it is the default/non category).

The whole (A) vector/list passed to the macro is:

- not strictly needed: 0-N bits are scanned, only N is needed in the
  macro interface to do this, not the whole list.

- 0-N list allows juggling the bit->class map
  Identity map is preferred.
  15 terminates list if used. (macro impl does this)

That said, (A) is self-documenting; the explicit list is greppable,
'DRM_UT_*' provides lots of clues.  Further, it could be upgraded,
something like:

  _pick_sym_(DRM_UT_CORE, "mumble something useful about CORE debug")

_pick_sym_(a,b) a		// gives us what we need here
_pick_help_(a,b) #a " : " b	// mod-info fodder

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

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index d4b48f3cc6e8..e83c4e36ad29 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -209,6 +209,10 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 				   KERN_DEBUG, prefix_str, prefix_type,	\
 				   rowsize, groupsize, buf, len, ascii)
 
+struct kernel_param;
+int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp);
+int param_get_dyndbg_classbits(char *buffer, const struct kernel_param *kp);
+
 #else /* !CONFIG_DYNAMIC_DEBUG_CORE */
 
 #include <linux/string.h>
@@ -255,6 +259,52 @@ static inline int dynamic_debug_exec_queries(const char *query, const char *modn
 	return 0;
 }
 
+struct kernel_param;
+static inline int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp)
+{ return 0; }
+static inline int param_get_dyndbg_classbits(char *buffer, const struct kernel_param *kp)
+{ return 0; }
+
 #endif /* !CONFIG_DYNAMIC_DEBUG_CORE */
 
+#define FLAGS_LEN 8
+struct dyndbg_classbits_param {
+	unsigned long *bits;		/* ref to shared state */
+	const char flags[FLAGS_LEN];	/* toggle these flags on bit-changes */
+	const int classes[];		/* indexed by bitpos */
+};
+
+#if defined(CONFIG_DYNAMIC_DEBUG) || defined(CONFIG_DYNAMIC_DEBUG_CORE)
+/**
+ * DEFINE_DYNAMIC_DEBUG_CLASSBITS() - bitmap control of classed pr_debugs
+ * @sysname: sysfs-node name
+ * @_var:    C-identifier holding bit-vector (Bits 0-14 are usable)
+ * @_flgs:   string with dyndbg flags: 'p' and/or 'T', and maybe "fmlt" also.
+ * @desc:    string summarizing the controls provided
+ * @classes: vector of callsite.class_id's (uint:4, 15 is reserved)
+ *
+ * This macro implements a DRM.debug API style bitmap, mapping bits
+ * 0-14 to classes of prdbg's, as initialized in their .class_id fields.
+ * @_flgs chooses the debug recipient; p - syslog, T - tracefs, and
+ * can include log decorations; m - module, f - function, l - line_num
+ */
+#define DEFINE_DYNAMIC_DEBUG_CLASSBITS(fsname, _var, _flgs, desc, ...)	\
+	MODULE_PARM_DESC(fsname, desc);					\
+	static struct dyndbg_classbits_param ddcats_##_var = {		\
+		.bits = &(_var),					\
+		.flags = _flgs,						\
+		.classes = { __VA_ARGS__, _DPRINTK_SITE_UNCLASSED }	\
+	};								\
+	module_param_cb(fsname, &param_ops_dyndbg_classbits,		\
+			&ddcats_##_var, 0644)
+
+extern const struct kernel_param_ops param_ops_dyndbg_classbits;
+
+#else /* no dyndbg configured, throw error on macro use */
+
+#define DEFINE_DYNAMIC_DEBUG_CLASSBITS(fsname, var, bitmap_desc, ...)	\
+	BUILD_BUG_ON_MSG(1, "CONFIG_DYNAMIC_DEBUG* needed to use this macro: " #fsname)
+
+#endif
+
 #endif
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index ee2129becacc..704361af5b23 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -611,6 +611,83 @@ int dynamic_debug_exec_queries(const char *query, const char *modname)
 }
 EXPORT_SYMBOL_GPL(dynamic_debug_exec_queries);
 
+#ifdef CONFIG_MODULES
+#define KP_MOD_NAME kp->mod->name
+#else
+#define KP_MOD_NAME NULL /* wildcard */
+#endif
+#define FMT_QUERY_SIZE 128 /* typically need <40 */
+/**
+ * param_set_dyndbg_classbits - bits => categories >control setter
+ * @instr: string echo>d to sysfs
+ * @kp:    kp->arg has state: bits, map
+ *
+ * Enable/disable prdbgs by their "category", as specified in the
+ * DEFINE_DYNAMIC_DEBUG_BITGRPS.classbits argument.
+ *
+ * Returns: 0 or <0 if error.
+ */
+int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp)
+{
+	unsigned long inbits;
+	int rc, i, matches = 0, totct = 0;
+	char query[FMT_QUERY_SIZE];
+	const struct dyndbg_classbits_param *dcp = kp->arg;
+
+	if (!dcp) {
+		pr_err("set_dyndbg_classbits: no bits=>queries map\n");
+		return -EINVAL;
+	}
+	rc = kstrtoul(instr, 0, &inbits);
+	if (rc) {
+		pr_err("set_dyndbg_classbits: expecting unsigned int\n");
+		return rc;
+	}
+	vpr_info("set_dyndbg_classbits: new 0x%lx old 0x%lx\n", inbits, *dcp->bits);
+
+	for (i = 0; (i < _DPRINTK_SITE_UNCLASSED &&
+		     dcp->classes[i] < _DPRINTK_SITE_UNCLASSED); i++) {
+
+		if (test_bit(i, &inbits) == test_bit(i, dcp->bits))
+			continue;
+		snprintf(query, FMT_QUERY_SIZE, "class %d %cT",
+			 dcp->classes[i], test_bit(i, &inbits) ? '+' : '-');
+
+		matches = ddebug_exec_queries(query, KP_MOD_NAME);
+
+		v2pr_info("bit-%d: %d matches on class:%u\n", i,
+			  matches, dcp->classes[i]);
+		totct += matches;
+	}
+	*dcp->bits = inbits;
+	vpr_info("total matches: %d\n", totct);
+	return 0;
+}
+EXPORT_SYMBOL(param_set_dyndbg_classbits);
+
+/**
+ * param_get_dyndbg_classbits - classbits reader
+ * @buffer: string description of controlled bits -> classes
+ * @kp:     kp->arg has state: bits, map
+ *
+ * Reads last written bits, underlying prdbg state may have changed since.
+ * Returns: #chars written or <0 on error
+ */
+int param_get_dyndbg_classbits(char *buffer, const struct kernel_param *kp)
+{
+	const struct dyndbg_classbits_param *p = kp->arg;
+	unsigned long val = *p->bits;
+
+	return scnprintf(buffer, PAGE_SIZE, "0x%lx\n", val);
+}
+EXPORT_SYMBOL(param_get_dyndbg_classbits);
+
+const struct kernel_param_ops param_ops_dyndbg_classbits = {
+	.set = param_set_dyndbg_classbits,
+	.get = param_get_dyndbg_classbits,
+};
+EXPORT_SYMBOL(param_ops_dyndbg_classbits);
+
 #define PREFIX_SIZE 64
 
 static int remaining(int wrote)
-- 
2.35.1


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

* [PATCH 3/5] dyndbg: add DEFINE_DYNAMIC_DEBUG_CLASSBITS macro
@ 2022-03-11  4:47   ` Jim Cromie
  0 siblings, 0 replies; 49+ messages in thread
From: Jim Cromie @ 2022-03-11  4:47 UTC (permalink / raw)
  To: jbaron, gregkh, linux-kernel
  Cc: daniel.vetter, intel-gfx, linux, dri-devel, seanpaul, amd-gfx,
	joe, intel-gvt-dev

DEFINE_DYNAMIC_DEBUG_CLASSBITS(fsname, var, bitmap_desc, classes..)
allows users to create a drm.debug style (bitmap) sysfs interface, to
control sets of pr_debug's according to their .class_id's

This wraps existing "class" keyword and behavior:

   bash-5.1# echo <<END  > /proc/dynamic_debug/control
   > module drm class 0 +p
   > module drm class 2 +p
   > END

With the macro used (in a client), this is basically equivalent:

   # but this also clears other flags, if theyre set
   echo 0x05 > /sys/module/drm/parameters/debug

To use:

DEFINE_DYNAMIC_DEBUG_CLASSBITS(debug, __drm_debug, "pmfl",
	"drm.debug - bits => categories:",
	/* vector of uint:4 symbols, ala enum drm_debug_category, 15 is EOL */
	DRM_UT_CORE,
	DRM_UT_DRIVER,
	DRM_UT_KMS ... );

The 3rd arg is a string with any of the dyndbg.flags [pmflt_]+
Full exposure of the flags here lets the module author:

- fully customize/take-over the decorations of enabled sites.
  generally leaving decorations to user is preferred.

- aim the debug-stream:
  now printk, later tracefs.
  using both together means more work (p or T, in practice)
  iface doesn't care about new flags added later

- declare 2 separate sysfs-knobs, one each for p, T, if desired.

- decorations are per callsite,
  shared across sysfs-knobs for any controlled classes

To support the macro, the patch adds:

 - int param_set_dyndbg_classbits()
 - int param_get_dyndbg_classbits()
 - struct kernel_param_ops param_ops_dyndbg_classbits

Following the model of kernel/params.c STANDARD_PARAM_DEFS, these are
non-static and exported.

get/set use an augmented kernel_param; the arg refs a new struct
dyndbg_bitmap_param containing:

A- the vector of classes (drm.debug "categories") being controlled

This in-line vector of constants (uint [0-14]) specifies a sequence of
controlling bits (by position, starting at 0) with the values naming
the class_id's mapped to that bit.

A value of _DPRINTK_SITE_UNCLASSED terminates the vector processing by
param_set_dyndbg_classbits(), and is appended by the macro to insure a
defined termination after max 15 classes are applied.

Technically, the vector is a flex-array, but its size is practically
limited to max 15 in length (repeats are pointless).

B- a pointer to the user module's ulong holding the bits/state.

By accessing client's bit-state, we coordinate with existing code
that still uses drm_debug_enabled(), so they work unchanged.
The change to ulong allows use of BIT() etc.

NOTES:

_DPRINTK_SITE_UNCLASSED = 15, ie 2**CLS_BITS-1, deserves special
mention; it already marks all existing pr-debug callsites, only the
new drm.debug callsites are initialized to other (DRM_UT_*) values.

_DPRINTK_SITE_UNCLASSED is used in param_set_dyndbg_classbits() to
limit the range of bits that are processed to what fits in uint:4.
It also terminates the class-id list passed into the macro, so dont
use it halfway through your list of classes-to-control.

param_set_dyndbg_classbits() compares new vs old bits, and only
updates each class on changes.  This maximally preserves the
underlying state, which may have been customized at some point via
`echo $cmd >control`.  So if users really want to know that all
prdbgs are set precisely, they must pre-clear then set.

Identity mapping in (A) is encouraged.  Your vector should exclude 15,
if used, it terminates the list prematurely; any following bit
mappings will be ignored (it is the default/non category).

The whole (A) vector/list passed to the macro is:

- not strictly needed: 0-N bits are scanned, only N is needed in the
  macro interface to do this, not the whole list.

- 0-N list allows juggling the bit->class map
  Identity map is preferred.
  15 terminates list if used. (macro impl does this)

That said, (A) is self-documenting; the explicit list is greppable,
'DRM_UT_*' provides lots of clues.  Further, it could be upgraded,
something like:

  _pick_sym_(DRM_UT_CORE, "mumble something useful about CORE debug")

_pick_sym_(a,b) a		// gives us what we need here
_pick_help_(a,b) #a " : " b	// mod-info fodder

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

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index d4b48f3cc6e8..e83c4e36ad29 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -209,6 +209,10 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 				   KERN_DEBUG, prefix_str, prefix_type,	\
 				   rowsize, groupsize, buf, len, ascii)
 
+struct kernel_param;
+int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp);
+int param_get_dyndbg_classbits(char *buffer, const struct kernel_param *kp);
+
 #else /* !CONFIG_DYNAMIC_DEBUG_CORE */
 
 #include <linux/string.h>
@@ -255,6 +259,52 @@ static inline int dynamic_debug_exec_queries(const char *query, const char *modn
 	return 0;
 }
 
+struct kernel_param;
+static inline int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp)
+{ return 0; }
+static inline int param_get_dyndbg_classbits(char *buffer, const struct kernel_param *kp)
+{ return 0; }
+
 #endif /* !CONFIG_DYNAMIC_DEBUG_CORE */
 
+#define FLAGS_LEN 8
+struct dyndbg_classbits_param {
+	unsigned long *bits;		/* ref to shared state */
+	const char flags[FLAGS_LEN];	/* toggle these flags on bit-changes */
+	const int classes[];		/* indexed by bitpos */
+};
+
+#if defined(CONFIG_DYNAMIC_DEBUG) || defined(CONFIG_DYNAMIC_DEBUG_CORE)
+/**
+ * DEFINE_DYNAMIC_DEBUG_CLASSBITS() - bitmap control of classed pr_debugs
+ * @sysname: sysfs-node name
+ * @_var:    C-identifier holding bit-vector (Bits 0-14 are usable)
+ * @_flgs:   string with dyndbg flags: 'p' and/or 'T', and maybe "fmlt" also.
+ * @desc:    string summarizing the controls provided
+ * @classes: vector of callsite.class_id's (uint:4, 15 is reserved)
+ *
+ * This macro implements a DRM.debug API style bitmap, mapping bits
+ * 0-14 to classes of prdbg's, as initialized in their .class_id fields.
+ * @_flgs chooses the debug recipient; p - syslog, T - tracefs, and
+ * can include log decorations; m - module, f - function, l - line_num
+ */
+#define DEFINE_DYNAMIC_DEBUG_CLASSBITS(fsname, _var, _flgs, desc, ...)	\
+	MODULE_PARM_DESC(fsname, desc);					\
+	static struct dyndbg_classbits_param ddcats_##_var = {		\
+		.bits = &(_var),					\
+		.flags = _flgs,						\
+		.classes = { __VA_ARGS__, _DPRINTK_SITE_UNCLASSED }	\
+	};								\
+	module_param_cb(fsname, &param_ops_dyndbg_classbits,		\
+			&ddcats_##_var, 0644)
+
+extern const struct kernel_param_ops param_ops_dyndbg_classbits;
+
+#else /* no dyndbg configured, throw error on macro use */
+
+#define DEFINE_DYNAMIC_DEBUG_CLASSBITS(fsname, var, bitmap_desc, ...)	\
+	BUILD_BUG_ON_MSG(1, "CONFIG_DYNAMIC_DEBUG* needed to use this macro: " #fsname)
+
+#endif
+
 #endif
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index ee2129becacc..704361af5b23 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -611,6 +611,83 @@ int dynamic_debug_exec_queries(const char *query, const char *modname)
 }
 EXPORT_SYMBOL_GPL(dynamic_debug_exec_queries);
 
+#ifdef CONFIG_MODULES
+#define KP_MOD_NAME kp->mod->name
+#else
+#define KP_MOD_NAME NULL /* wildcard */
+#endif
+#define FMT_QUERY_SIZE 128 /* typically need <40 */
+/**
+ * param_set_dyndbg_classbits - bits => categories >control setter
+ * @instr: string echo>d to sysfs
+ * @kp:    kp->arg has state: bits, map
+ *
+ * Enable/disable prdbgs by their "category", as specified in the
+ * DEFINE_DYNAMIC_DEBUG_BITGRPS.classbits argument.
+ *
+ * Returns: 0 or <0 if error.
+ */
+int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp)
+{
+	unsigned long inbits;
+	int rc, i, matches = 0, totct = 0;
+	char query[FMT_QUERY_SIZE];
+	const struct dyndbg_classbits_param *dcp = kp->arg;
+
+	if (!dcp) {
+		pr_err("set_dyndbg_classbits: no bits=>queries map\n");
+		return -EINVAL;
+	}
+	rc = kstrtoul(instr, 0, &inbits);
+	if (rc) {
+		pr_err("set_dyndbg_classbits: expecting unsigned int\n");
+		return rc;
+	}
+	vpr_info("set_dyndbg_classbits: new 0x%lx old 0x%lx\n", inbits, *dcp->bits);
+
+	for (i = 0; (i < _DPRINTK_SITE_UNCLASSED &&
+		     dcp->classes[i] < _DPRINTK_SITE_UNCLASSED); i++) {
+
+		if (test_bit(i, &inbits) == test_bit(i, dcp->bits))
+			continue;
+		snprintf(query, FMT_QUERY_SIZE, "class %d %cT",
+			 dcp->classes[i], test_bit(i, &inbits) ? '+' : '-');
+
+		matches = ddebug_exec_queries(query, KP_MOD_NAME);
+
+		v2pr_info("bit-%d: %d matches on class:%u\n", i,
+			  matches, dcp->classes[i]);
+		totct += matches;
+	}
+	*dcp->bits = inbits;
+	vpr_info("total matches: %d\n", totct);
+	return 0;
+}
+EXPORT_SYMBOL(param_set_dyndbg_classbits);
+
+/**
+ * param_get_dyndbg_classbits - classbits reader
+ * @buffer: string description of controlled bits -> classes
+ * @kp:     kp->arg has state: bits, map
+ *
+ * Reads last written bits, underlying prdbg state may have changed since.
+ * Returns: #chars written or <0 on error
+ */
+int param_get_dyndbg_classbits(char *buffer, const struct kernel_param *kp)
+{
+	const struct dyndbg_classbits_param *p = kp->arg;
+	unsigned long val = *p->bits;
+
+	return scnprintf(buffer, PAGE_SIZE, "0x%lx\n", val);
+}
+EXPORT_SYMBOL(param_get_dyndbg_classbits);
+
+const struct kernel_param_ops param_ops_dyndbg_classbits = {
+	.set = param_set_dyndbg_classbits,
+	.get = param_get_dyndbg_classbits,
+};
+EXPORT_SYMBOL(param_ops_dyndbg_classbits);
+
 #define PREFIX_SIZE 64
 
 static int remaining(int wrote)
-- 
2.35.1


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

* [Intel-gfx] [PATCH 3/5] dyndbg: add DEFINE_DYNAMIC_DEBUG_CLASSBITS macro
@ 2022-03-11  4:47   ` Jim Cromie
  0 siblings, 0 replies; 49+ messages in thread
From: Jim Cromie @ 2022-03-11  4:47 UTC (permalink / raw)
  To: jbaron, gregkh, linux-kernel
  Cc: Jim Cromie, daniel.vetter, intel-gfx, linux, dri-devel, seanpaul,
	amd-gfx, joe, intel-gvt-dev

DEFINE_DYNAMIC_DEBUG_CLASSBITS(fsname, var, bitmap_desc, classes..)
allows users to create a drm.debug style (bitmap) sysfs interface, to
control sets of pr_debug's according to their .class_id's

This wraps existing "class" keyword and behavior:

   bash-5.1# echo <<END  > /proc/dynamic_debug/control
   > module drm class 0 +p
   > module drm class 2 +p
   > END

With the macro used (in a client), this is basically equivalent:

   # but this also clears other flags, if theyre set
   echo 0x05 > /sys/module/drm/parameters/debug

To use:

DEFINE_DYNAMIC_DEBUG_CLASSBITS(debug, __drm_debug, "pmfl",
	"drm.debug - bits => categories:",
	/* vector of uint:4 symbols, ala enum drm_debug_category, 15 is EOL */
	DRM_UT_CORE,
	DRM_UT_DRIVER,
	DRM_UT_KMS ... );

The 3rd arg is a string with any of the dyndbg.flags [pmflt_]+
Full exposure of the flags here lets the module author:

- fully customize/take-over the decorations of enabled sites.
  generally leaving decorations to user is preferred.

- aim the debug-stream:
  now printk, later tracefs.
  using both together means more work (p or T, in practice)
  iface doesn't care about new flags added later

- declare 2 separate sysfs-knobs, one each for p, T, if desired.

- decorations are per callsite,
  shared across sysfs-knobs for any controlled classes

To support the macro, the patch adds:

 - int param_set_dyndbg_classbits()
 - int param_get_dyndbg_classbits()
 - struct kernel_param_ops param_ops_dyndbg_classbits

Following the model of kernel/params.c STANDARD_PARAM_DEFS, these are
non-static and exported.

get/set use an augmented kernel_param; the arg refs a new struct
dyndbg_bitmap_param containing:

A- the vector of classes (drm.debug "categories") being controlled

This in-line vector of constants (uint [0-14]) specifies a sequence of
controlling bits (by position, starting at 0) with the values naming
the class_id's mapped to that bit.

A value of _DPRINTK_SITE_UNCLASSED terminates the vector processing by
param_set_dyndbg_classbits(), and is appended by the macro to insure a
defined termination after max 15 classes are applied.

Technically, the vector is a flex-array, but its size is practically
limited to max 15 in length (repeats are pointless).

B- a pointer to the user module's ulong holding the bits/state.

By accessing client's bit-state, we coordinate with existing code
that still uses drm_debug_enabled(), so they work unchanged.
The change to ulong allows use of BIT() etc.

NOTES:

_DPRINTK_SITE_UNCLASSED = 15, ie 2**CLS_BITS-1, deserves special
mention; it already marks all existing pr-debug callsites, only the
new drm.debug callsites are initialized to other (DRM_UT_*) values.

_DPRINTK_SITE_UNCLASSED is used in param_set_dyndbg_classbits() to
limit the range of bits that are processed to what fits in uint:4.
It also terminates the class-id list passed into the macro, so dont
use it halfway through your list of classes-to-control.

param_set_dyndbg_classbits() compares new vs old bits, and only
updates each class on changes.  This maximally preserves the
underlying state, which may have been customized at some point via
`echo $cmd >control`.  So if users really want to know that all
prdbgs are set precisely, they must pre-clear then set.

Identity mapping in (A) is encouraged.  Your vector should exclude 15,
if used, it terminates the list prematurely; any following bit
mappings will be ignored (it is the default/non category).

The whole (A) vector/list passed to the macro is:

- not strictly needed: 0-N bits are scanned, only N is needed in the
  macro interface to do this, not the whole list.

- 0-N list allows juggling the bit->class map
  Identity map is preferred.
  15 terminates list if used. (macro impl does this)

That said, (A) is self-documenting; the explicit list is greppable,
'DRM_UT_*' provides lots of clues.  Further, it could be upgraded,
something like:

  _pick_sym_(DRM_UT_CORE, "mumble something useful about CORE debug")

_pick_sym_(a,b) a		// gives us what we need here
_pick_help_(a,b) #a " : " b	// mod-info fodder

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

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index d4b48f3cc6e8..e83c4e36ad29 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -209,6 +209,10 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 				   KERN_DEBUG, prefix_str, prefix_type,	\
 				   rowsize, groupsize, buf, len, ascii)
 
+struct kernel_param;
+int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp);
+int param_get_dyndbg_classbits(char *buffer, const struct kernel_param *kp);
+
 #else /* !CONFIG_DYNAMIC_DEBUG_CORE */
 
 #include <linux/string.h>
@@ -255,6 +259,52 @@ static inline int dynamic_debug_exec_queries(const char *query, const char *modn
 	return 0;
 }
 
+struct kernel_param;
+static inline int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp)
+{ return 0; }
+static inline int param_get_dyndbg_classbits(char *buffer, const struct kernel_param *kp)
+{ return 0; }
+
 #endif /* !CONFIG_DYNAMIC_DEBUG_CORE */
 
+#define FLAGS_LEN 8
+struct dyndbg_classbits_param {
+	unsigned long *bits;		/* ref to shared state */
+	const char flags[FLAGS_LEN];	/* toggle these flags on bit-changes */
+	const int classes[];		/* indexed by bitpos */
+};
+
+#if defined(CONFIG_DYNAMIC_DEBUG) || defined(CONFIG_DYNAMIC_DEBUG_CORE)
+/**
+ * DEFINE_DYNAMIC_DEBUG_CLASSBITS() - bitmap control of classed pr_debugs
+ * @sysname: sysfs-node name
+ * @_var:    C-identifier holding bit-vector (Bits 0-14 are usable)
+ * @_flgs:   string with dyndbg flags: 'p' and/or 'T', and maybe "fmlt" also.
+ * @desc:    string summarizing the controls provided
+ * @classes: vector of callsite.class_id's (uint:4, 15 is reserved)
+ *
+ * This macro implements a DRM.debug API style bitmap, mapping bits
+ * 0-14 to classes of prdbg's, as initialized in their .class_id fields.
+ * @_flgs chooses the debug recipient; p - syslog, T - tracefs, and
+ * can include log decorations; m - module, f - function, l - line_num
+ */
+#define DEFINE_DYNAMIC_DEBUG_CLASSBITS(fsname, _var, _flgs, desc, ...)	\
+	MODULE_PARM_DESC(fsname, desc);					\
+	static struct dyndbg_classbits_param ddcats_##_var = {		\
+		.bits = &(_var),					\
+		.flags = _flgs,						\
+		.classes = { __VA_ARGS__, _DPRINTK_SITE_UNCLASSED }	\
+	};								\
+	module_param_cb(fsname, &param_ops_dyndbg_classbits,		\
+			&ddcats_##_var, 0644)
+
+extern const struct kernel_param_ops param_ops_dyndbg_classbits;
+
+#else /* no dyndbg configured, throw error on macro use */
+
+#define DEFINE_DYNAMIC_DEBUG_CLASSBITS(fsname, var, bitmap_desc, ...)	\
+	BUILD_BUG_ON_MSG(1, "CONFIG_DYNAMIC_DEBUG* needed to use this macro: " #fsname)
+
+#endif
+
 #endif
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index ee2129becacc..704361af5b23 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -611,6 +611,83 @@ int dynamic_debug_exec_queries(const char *query, const char *modname)
 }
 EXPORT_SYMBOL_GPL(dynamic_debug_exec_queries);
 
+#ifdef CONFIG_MODULES
+#define KP_MOD_NAME kp->mod->name
+#else
+#define KP_MOD_NAME NULL /* wildcard */
+#endif
+#define FMT_QUERY_SIZE 128 /* typically need <40 */
+/**
+ * param_set_dyndbg_classbits - bits => categories >control setter
+ * @instr: string echo>d to sysfs
+ * @kp:    kp->arg has state: bits, map
+ *
+ * Enable/disable prdbgs by their "category", as specified in the
+ * DEFINE_DYNAMIC_DEBUG_BITGRPS.classbits argument.
+ *
+ * Returns: 0 or <0 if error.
+ */
+int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp)
+{
+	unsigned long inbits;
+	int rc, i, matches = 0, totct = 0;
+	char query[FMT_QUERY_SIZE];
+	const struct dyndbg_classbits_param *dcp = kp->arg;
+
+	if (!dcp) {
+		pr_err("set_dyndbg_classbits: no bits=>queries map\n");
+		return -EINVAL;
+	}
+	rc = kstrtoul(instr, 0, &inbits);
+	if (rc) {
+		pr_err("set_dyndbg_classbits: expecting unsigned int\n");
+		return rc;
+	}
+	vpr_info("set_dyndbg_classbits: new 0x%lx old 0x%lx\n", inbits, *dcp->bits);
+
+	for (i = 0; (i < _DPRINTK_SITE_UNCLASSED &&
+		     dcp->classes[i] < _DPRINTK_SITE_UNCLASSED); i++) {
+
+		if (test_bit(i, &inbits) == test_bit(i, dcp->bits))
+			continue;
+		snprintf(query, FMT_QUERY_SIZE, "class %d %cT",
+			 dcp->classes[i], test_bit(i, &inbits) ? '+' : '-');
+
+		matches = ddebug_exec_queries(query, KP_MOD_NAME);
+
+		v2pr_info("bit-%d: %d matches on class:%u\n", i,
+			  matches, dcp->classes[i]);
+		totct += matches;
+	}
+	*dcp->bits = inbits;
+	vpr_info("total matches: %d\n", totct);
+	return 0;
+}
+EXPORT_SYMBOL(param_set_dyndbg_classbits);
+
+/**
+ * param_get_dyndbg_classbits - classbits reader
+ * @buffer: string description of controlled bits -> classes
+ * @kp:     kp->arg has state: bits, map
+ *
+ * Reads last written bits, underlying prdbg state may have changed since.
+ * Returns: #chars written or <0 on error
+ */
+int param_get_dyndbg_classbits(char *buffer, const struct kernel_param *kp)
+{
+	const struct dyndbg_classbits_param *p = kp->arg;
+	unsigned long val = *p->bits;
+
+	return scnprintf(buffer, PAGE_SIZE, "0x%lx\n", val);
+}
+EXPORT_SYMBOL(param_get_dyndbg_classbits);
+
+const struct kernel_param_ops param_ops_dyndbg_classbits = {
+	.set = param_set_dyndbg_classbits,
+	.get = param_get_dyndbg_classbits,
+};
+EXPORT_SYMBOL(param_ops_dyndbg_classbits);
+
 #define PREFIX_SIZE 64
 
 static int remaining(int wrote)
-- 
2.35.1


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

* [PATCH 3/5] dyndbg: add DEFINE_DYNAMIC_DEBUG_CLASSBITS macro
@ 2022-03-11  4:47   ` Jim Cromie
  0 siblings, 0 replies; 49+ messages in thread
From: Jim Cromie @ 2022-03-11  4:47 UTC (permalink / raw)
  To: jbaron, gregkh, linux-kernel
  Cc: Jim Cromie, daniel.vetter, intel-gfx, linux, dri-devel,
	robdclark, seanpaul, amd-gfx, joe, intel-gvt-dev

DEFINE_DYNAMIC_DEBUG_CLASSBITS(fsname, var, bitmap_desc, classes..)
allows users to create a drm.debug style (bitmap) sysfs interface, to
control sets of pr_debug's according to their .class_id's

This wraps existing "class" keyword and behavior:

   bash-5.1# echo <<END  > /proc/dynamic_debug/control
   > module drm class 0 +p
   > module drm class 2 +p
   > END

With the macro used (in a client), this is basically equivalent:

   # but this also clears other flags, if theyre set
   echo 0x05 > /sys/module/drm/parameters/debug

To use:

DEFINE_DYNAMIC_DEBUG_CLASSBITS(debug, __drm_debug, "pmfl",
	"drm.debug - bits => categories:",
	/* vector of uint:4 symbols, ala enum drm_debug_category, 15 is EOL */
	DRM_UT_CORE,
	DRM_UT_DRIVER,
	DRM_UT_KMS ... );

The 3rd arg is a string with any of the dyndbg.flags [pmflt_]+
Full exposure of the flags here lets the module author:

- fully customize/take-over the decorations of enabled sites.
  generally leaving decorations to user is preferred.

- aim the debug-stream:
  now printk, later tracefs.
  using both together means more work (p or T, in practice)
  iface doesn't care about new flags added later

- declare 2 separate sysfs-knobs, one each for p, T, if desired.

- decorations are per callsite,
  shared across sysfs-knobs for any controlled classes

To support the macro, the patch adds:

 - int param_set_dyndbg_classbits()
 - int param_get_dyndbg_classbits()
 - struct kernel_param_ops param_ops_dyndbg_classbits

Following the model of kernel/params.c STANDARD_PARAM_DEFS, these are
non-static and exported.

get/set use an augmented kernel_param; the arg refs a new struct
dyndbg_bitmap_param containing:

A- the vector of classes (drm.debug "categories") being controlled

This in-line vector of constants (uint [0-14]) specifies a sequence of
controlling bits (by position, starting at 0) with the values naming
the class_id's mapped to that bit.

A value of _DPRINTK_SITE_UNCLASSED terminates the vector processing by
param_set_dyndbg_classbits(), and is appended by the macro to insure a
defined termination after max 15 classes are applied.

Technically, the vector is a flex-array, but its size is practically
limited to max 15 in length (repeats are pointless).

B- a pointer to the user module's ulong holding the bits/state.

By accessing client's bit-state, we coordinate with existing code
that still uses drm_debug_enabled(), so they work unchanged.
The change to ulong allows use of BIT() etc.

NOTES:

_DPRINTK_SITE_UNCLASSED = 15, ie 2**CLS_BITS-1, deserves special
mention; it already marks all existing pr-debug callsites, only the
new drm.debug callsites are initialized to other (DRM_UT_*) values.

_DPRINTK_SITE_UNCLASSED is used in param_set_dyndbg_classbits() to
limit the range of bits that are processed to what fits in uint:4.
It also terminates the class-id list passed into the macro, so dont
use it halfway through your list of classes-to-control.

param_set_dyndbg_classbits() compares new vs old bits, and only
updates each class on changes.  This maximally preserves the
underlying state, which may have been customized at some point via
`echo $cmd >control`.  So if users really want to know that all
prdbgs are set precisely, they must pre-clear then set.

Identity mapping in (A) is encouraged.  Your vector should exclude 15,
if used, it terminates the list prematurely; any following bit
mappings will be ignored (it is the default/non category).

The whole (A) vector/list passed to the macro is:

- not strictly needed: 0-N bits are scanned, only N is needed in the
  macro interface to do this, not the whole list.

- 0-N list allows juggling the bit->class map
  Identity map is preferred.
  15 terminates list if used. (macro impl does this)

That said, (A) is self-documenting; the explicit list is greppable,
'DRM_UT_*' provides lots of clues.  Further, it could be upgraded,
something like:

  _pick_sym_(DRM_UT_CORE, "mumble something useful about CORE debug")

_pick_sym_(a,b) a		// gives us what we need here
_pick_help_(a,b) #a " : " b	// mod-info fodder

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

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index d4b48f3cc6e8..e83c4e36ad29 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -209,6 +209,10 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 				   KERN_DEBUG, prefix_str, prefix_type,	\
 				   rowsize, groupsize, buf, len, ascii)
 
+struct kernel_param;
+int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp);
+int param_get_dyndbg_classbits(char *buffer, const struct kernel_param *kp);
+
 #else /* !CONFIG_DYNAMIC_DEBUG_CORE */
 
 #include <linux/string.h>
@@ -255,6 +259,52 @@ static inline int dynamic_debug_exec_queries(const char *query, const char *modn
 	return 0;
 }
 
+struct kernel_param;
+static inline int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp)
+{ return 0; }
+static inline int param_get_dyndbg_classbits(char *buffer, const struct kernel_param *kp)
+{ return 0; }
+
 #endif /* !CONFIG_DYNAMIC_DEBUG_CORE */
 
+#define FLAGS_LEN 8
+struct dyndbg_classbits_param {
+	unsigned long *bits;		/* ref to shared state */
+	const char flags[FLAGS_LEN];	/* toggle these flags on bit-changes */
+	const int classes[];		/* indexed by bitpos */
+};
+
+#if defined(CONFIG_DYNAMIC_DEBUG) || defined(CONFIG_DYNAMIC_DEBUG_CORE)
+/**
+ * DEFINE_DYNAMIC_DEBUG_CLASSBITS() - bitmap control of classed pr_debugs
+ * @sysname: sysfs-node name
+ * @_var:    C-identifier holding bit-vector (Bits 0-14 are usable)
+ * @_flgs:   string with dyndbg flags: 'p' and/or 'T', and maybe "fmlt" also.
+ * @desc:    string summarizing the controls provided
+ * @classes: vector of callsite.class_id's (uint:4, 15 is reserved)
+ *
+ * This macro implements a DRM.debug API style bitmap, mapping bits
+ * 0-14 to classes of prdbg's, as initialized in their .class_id fields.
+ * @_flgs chooses the debug recipient; p - syslog, T - tracefs, and
+ * can include log decorations; m - module, f - function, l - line_num
+ */
+#define DEFINE_DYNAMIC_DEBUG_CLASSBITS(fsname, _var, _flgs, desc, ...)	\
+	MODULE_PARM_DESC(fsname, desc);					\
+	static struct dyndbg_classbits_param ddcats_##_var = {		\
+		.bits = &(_var),					\
+		.flags = _flgs,						\
+		.classes = { __VA_ARGS__, _DPRINTK_SITE_UNCLASSED }	\
+	};								\
+	module_param_cb(fsname, &param_ops_dyndbg_classbits,		\
+			&ddcats_##_var, 0644)
+
+extern const struct kernel_param_ops param_ops_dyndbg_classbits;
+
+#else /* no dyndbg configured, throw error on macro use */
+
+#define DEFINE_DYNAMIC_DEBUG_CLASSBITS(fsname, var, bitmap_desc, ...)	\
+	BUILD_BUG_ON_MSG(1, "CONFIG_DYNAMIC_DEBUG* needed to use this macro: " #fsname)
+
+#endif
+
 #endif
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index ee2129becacc..704361af5b23 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -611,6 +611,83 @@ int dynamic_debug_exec_queries(const char *query, const char *modname)
 }
 EXPORT_SYMBOL_GPL(dynamic_debug_exec_queries);
 
+#ifdef CONFIG_MODULES
+#define KP_MOD_NAME kp->mod->name
+#else
+#define KP_MOD_NAME NULL /* wildcard */
+#endif
+#define FMT_QUERY_SIZE 128 /* typically need <40 */
+/**
+ * param_set_dyndbg_classbits - bits => categories >control setter
+ * @instr: string echo>d to sysfs
+ * @kp:    kp->arg has state: bits, map
+ *
+ * Enable/disable prdbgs by their "category", as specified in the
+ * DEFINE_DYNAMIC_DEBUG_BITGRPS.classbits argument.
+ *
+ * Returns: 0 or <0 if error.
+ */
+int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp)
+{
+	unsigned long inbits;
+	int rc, i, matches = 0, totct = 0;
+	char query[FMT_QUERY_SIZE];
+	const struct dyndbg_classbits_param *dcp = kp->arg;
+
+	if (!dcp) {
+		pr_err("set_dyndbg_classbits: no bits=>queries map\n");
+		return -EINVAL;
+	}
+	rc = kstrtoul(instr, 0, &inbits);
+	if (rc) {
+		pr_err("set_dyndbg_classbits: expecting unsigned int\n");
+		return rc;
+	}
+	vpr_info("set_dyndbg_classbits: new 0x%lx old 0x%lx\n", inbits, *dcp->bits);
+
+	for (i = 0; (i < _DPRINTK_SITE_UNCLASSED &&
+		     dcp->classes[i] < _DPRINTK_SITE_UNCLASSED); i++) {
+
+		if (test_bit(i, &inbits) == test_bit(i, dcp->bits))
+			continue;
+		snprintf(query, FMT_QUERY_SIZE, "class %d %cT",
+			 dcp->classes[i], test_bit(i, &inbits) ? '+' : '-');
+
+		matches = ddebug_exec_queries(query, KP_MOD_NAME);
+
+		v2pr_info("bit-%d: %d matches on class:%u\n", i,
+			  matches, dcp->classes[i]);
+		totct += matches;
+	}
+	*dcp->bits = inbits;
+	vpr_info("total matches: %d\n", totct);
+	return 0;
+}
+EXPORT_SYMBOL(param_set_dyndbg_classbits);
+
+/**
+ * param_get_dyndbg_classbits - classbits reader
+ * @buffer: string description of controlled bits -> classes
+ * @kp:     kp->arg has state: bits, map
+ *
+ * Reads last written bits, underlying prdbg state may have changed since.
+ * Returns: #chars written or <0 on error
+ */
+int param_get_dyndbg_classbits(char *buffer, const struct kernel_param *kp)
+{
+	const struct dyndbg_classbits_param *p = kp->arg;
+	unsigned long val = *p->bits;
+
+	return scnprintf(buffer, PAGE_SIZE, "0x%lx\n", val);
+}
+EXPORT_SYMBOL(param_get_dyndbg_classbits);
+
+const struct kernel_param_ops param_ops_dyndbg_classbits = {
+	.set = param_set_dyndbg_classbits,
+	.get = param_get_dyndbg_classbits,
+};
+EXPORT_SYMBOL(param_ops_dyndbg_classbits);
+
 #define PREFIX_SIZE 64
 
 static int remaining(int wrote)
-- 
2.35.1


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

* [PATCH 4/5] dyndbg: drop EXPORTed dynamic_debug_exec_queries
  2022-03-11  4:47 ` Jim Cromie
  (?)
  (?)
@ 2022-03-11  4:47   ` Jim Cromie
  -1 siblings, 0 replies; 49+ messages in thread
From: Jim Cromie @ 2022-03-11  4:47 UTC (permalink / raw)
  To: jbaron, gregkh, linux-kernel
  Cc: daniel.vetter, seanpaul, robdclark, linux, joe, dri-devel,
	amd-gfx, intel-gvt-dev, intel-gfx, Jim Cromie

This exported fn is effectively obsoleted by Commit:HEAD~2, so remove it.

Its intent was to allow drm.debug to use the exported function to
implement its drm.debug bitmap api using dynamic_debug.  Instead,
HEAD~2 implements the bitmap inside dyndbg, using the internal fn that
the export wraps.

Since there are no other expected users, and any prospects would
likely reuse the bitmap or a straightforward extension of it, we can
drop the exported function until its really needed.

This also drops the CONFIG_DYNAMIC_DEBUG=N stub-func, and its
pr_warn(), which I avoided in 2012, then added in 2020 :-/

Fixes: a2d375eda771 ("dyndbg: refine export, rename to dynamic_debug_exec_queries()")
Fixes: 4c0d77828d4f ("dyndbg: export ddebug_exec_queries")
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 include/linux/dynamic_debug.h |  9 ---------
 lib/dynamic_debug.c           | 29 -----------------------------
 2 files changed, 38 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index e83c4e36ad29..664bb83778d2 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -60,9 +60,6 @@ struct _ddebug {
 
 #if defined(CONFIG_DYNAMIC_DEBUG_CORE)
 
-/* exported for module authors to exercise >control */
-int dynamic_debug_exec_queries(const char *query, const char *modname);
-
 int ddebug_add_module(struct _ddebug *tab, unsigned int n,
 				const char *modname);
 extern int ddebug_remove_module(const char *mod_name);
@@ -253,12 +250,6 @@ static inline int ddebug_dyndbg_module_param_cb(char *param, char *val,
 				rowsize, groupsize, buf, len, ascii);	\
 	} while (0)
 
-static inline int dynamic_debug_exec_queries(const char *query, const char *modname)
-{
-	pr_warn("kernel not built with CONFIG_DYNAMIC_DEBUG_CORE\n");
-	return 0;
-}
-
 struct kernel_param;
 static inline int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp)
 { return 0; }
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 704361af5b23..b15a9c715e5b 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -582,35 +582,6 @@ static int ddebug_exec_queries(char *query, const char *modname)
 	return nfound;
 }
 
-/**
- * dynamic_debug_exec_queries - select and change dynamic-debug prints
- * @query: query-string described in admin-guide/dynamic-debug-howto
- * @modname: string containing module name, usually &module.mod_name
- *
- * This uses the >/proc/dynamic_debug/control reader, allowing module
- * authors to modify their dynamic-debug callsites. The modname is
- * canonically struct module.mod_name, but can also be null or a
- * module-wildcard, for example: "drm*".
- */
-int dynamic_debug_exec_queries(const char *query, const char *modname)
-{
-	int rc;
-	char *qry; /* writable copy of query */
-
-	if (!query) {
-		pr_err("non-null query/command string expected\n");
-		return -EINVAL;
-	}
-	qry = kstrndup(query, PAGE_SIZE, GFP_KERNEL);
-	if (!qry)
-		return -ENOMEM;
-
-	rc = ddebug_exec_queries(qry, modname);
-	kfree(qry);
-	return rc;
-}
-EXPORT_SYMBOL_GPL(dynamic_debug_exec_queries);
-
 #ifdef CONFIG_MODULES
 #define KP_MOD_NAME kp->mod->name
 #else
-- 
2.35.1


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

* [PATCH 4/5] dyndbg: drop EXPORTed dynamic_debug_exec_queries
@ 2022-03-11  4:47   ` Jim Cromie
  0 siblings, 0 replies; 49+ messages in thread
From: Jim Cromie @ 2022-03-11  4:47 UTC (permalink / raw)
  To: jbaron, gregkh, linux-kernel
  Cc: daniel.vetter, intel-gfx, linux, dri-devel, seanpaul, amd-gfx,
	joe, intel-gvt-dev

This exported fn is effectively obsoleted by Commit:HEAD~2, so remove it.

Its intent was to allow drm.debug to use the exported function to
implement its drm.debug bitmap api using dynamic_debug.  Instead,
HEAD~2 implements the bitmap inside dyndbg, using the internal fn that
the export wraps.

Since there are no other expected users, and any prospects would
likely reuse the bitmap or a straightforward extension of it, we can
drop the exported function until its really needed.

This also drops the CONFIG_DYNAMIC_DEBUG=N stub-func, and its
pr_warn(), which I avoided in 2012, then added in 2020 :-/

Fixes: a2d375eda771 ("dyndbg: refine export, rename to dynamic_debug_exec_queries()")
Fixes: 4c0d77828d4f ("dyndbg: export ddebug_exec_queries")
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 include/linux/dynamic_debug.h |  9 ---------
 lib/dynamic_debug.c           | 29 -----------------------------
 2 files changed, 38 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index e83c4e36ad29..664bb83778d2 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -60,9 +60,6 @@ struct _ddebug {
 
 #if defined(CONFIG_DYNAMIC_DEBUG_CORE)
 
-/* exported for module authors to exercise >control */
-int dynamic_debug_exec_queries(const char *query, const char *modname);
-
 int ddebug_add_module(struct _ddebug *tab, unsigned int n,
 				const char *modname);
 extern int ddebug_remove_module(const char *mod_name);
@@ -253,12 +250,6 @@ static inline int ddebug_dyndbg_module_param_cb(char *param, char *val,
 				rowsize, groupsize, buf, len, ascii);	\
 	} while (0)
 
-static inline int dynamic_debug_exec_queries(const char *query, const char *modname)
-{
-	pr_warn("kernel not built with CONFIG_DYNAMIC_DEBUG_CORE\n");
-	return 0;
-}
-
 struct kernel_param;
 static inline int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp)
 { return 0; }
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 704361af5b23..b15a9c715e5b 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -582,35 +582,6 @@ static int ddebug_exec_queries(char *query, const char *modname)
 	return nfound;
 }
 
-/**
- * dynamic_debug_exec_queries - select and change dynamic-debug prints
- * @query: query-string described in admin-guide/dynamic-debug-howto
- * @modname: string containing module name, usually &module.mod_name
- *
- * This uses the >/proc/dynamic_debug/control reader, allowing module
- * authors to modify their dynamic-debug callsites. The modname is
- * canonically struct module.mod_name, but can also be null or a
- * module-wildcard, for example: "drm*".
- */
-int dynamic_debug_exec_queries(const char *query, const char *modname)
-{
-	int rc;
-	char *qry; /* writable copy of query */
-
-	if (!query) {
-		pr_err("non-null query/command string expected\n");
-		return -EINVAL;
-	}
-	qry = kstrndup(query, PAGE_SIZE, GFP_KERNEL);
-	if (!qry)
-		return -ENOMEM;
-
-	rc = ddebug_exec_queries(qry, modname);
-	kfree(qry);
-	return rc;
-}
-EXPORT_SYMBOL_GPL(dynamic_debug_exec_queries);
-
 #ifdef CONFIG_MODULES
 #define KP_MOD_NAME kp->mod->name
 #else
-- 
2.35.1


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

* [Intel-gfx] [PATCH 4/5] dyndbg: drop EXPORTed dynamic_debug_exec_queries
@ 2022-03-11  4:47   ` Jim Cromie
  0 siblings, 0 replies; 49+ messages in thread
From: Jim Cromie @ 2022-03-11  4:47 UTC (permalink / raw)
  To: jbaron, gregkh, linux-kernel
  Cc: Jim Cromie, daniel.vetter, intel-gfx, linux, dri-devel, seanpaul,
	amd-gfx, joe, intel-gvt-dev

This exported fn is effectively obsoleted by Commit:HEAD~2, so remove it.

Its intent was to allow drm.debug to use the exported function to
implement its drm.debug bitmap api using dynamic_debug.  Instead,
HEAD~2 implements the bitmap inside dyndbg, using the internal fn that
the export wraps.

Since there are no other expected users, and any prospects would
likely reuse the bitmap or a straightforward extension of it, we can
drop the exported function until its really needed.

This also drops the CONFIG_DYNAMIC_DEBUG=N stub-func, and its
pr_warn(), which I avoided in 2012, then added in 2020 :-/

Fixes: a2d375eda771 ("dyndbg: refine export, rename to dynamic_debug_exec_queries()")
Fixes: 4c0d77828d4f ("dyndbg: export ddebug_exec_queries")
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 include/linux/dynamic_debug.h |  9 ---------
 lib/dynamic_debug.c           | 29 -----------------------------
 2 files changed, 38 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index e83c4e36ad29..664bb83778d2 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -60,9 +60,6 @@ struct _ddebug {
 
 #if defined(CONFIG_DYNAMIC_DEBUG_CORE)
 
-/* exported for module authors to exercise >control */
-int dynamic_debug_exec_queries(const char *query, const char *modname);
-
 int ddebug_add_module(struct _ddebug *tab, unsigned int n,
 				const char *modname);
 extern int ddebug_remove_module(const char *mod_name);
@@ -253,12 +250,6 @@ static inline int ddebug_dyndbg_module_param_cb(char *param, char *val,
 				rowsize, groupsize, buf, len, ascii);	\
 	} while (0)
 
-static inline int dynamic_debug_exec_queries(const char *query, const char *modname)
-{
-	pr_warn("kernel not built with CONFIG_DYNAMIC_DEBUG_CORE\n");
-	return 0;
-}
-
 struct kernel_param;
 static inline int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp)
 { return 0; }
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 704361af5b23..b15a9c715e5b 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -582,35 +582,6 @@ static int ddebug_exec_queries(char *query, const char *modname)
 	return nfound;
 }
 
-/**
- * dynamic_debug_exec_queries - select and change dynamic-debug prints
- * @query: query-string described in admin-guide/dynamic-debug-howto
- * @modname: string containing module name, usually &module.mod_name
- *
- * This uses the >/proc/dynamic_debug/control reader, allowing module
- * authors to modify their dynamic-debug callsites. The modname is
- * canonically struct module.mod_name, but can also be null or a
- * module-wildcard, for example: "drm*".
- */
-int dynamic_debug_exec_queries(const char *query, const char *modname)
-{
-	int rc;
-	char *qry; /* writable copy of query */
-
-	if (!query) {
-		pr_err("non-null query/command string expected\n");
-		return -EINVAL;
-	}
-	qry = kstrndup(query, PAGE_SIZE, GFP_KERNEL);
-	if (!qry)
-		return -ENOMEM;
-
-	rc = ddebug_exec_queries(qry, modname);
-	kfree(qry);
-	return rc;
-}
-EXPORT_SYMBOL_GPL(dynamic_debug_exec_queries);
-
 #ifdef CONFIG_MODULES
 #define KP_MOD_NAME kp->mod->name
 #else
-- 
2.35.1


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

* [PATCH 4/5] dyndbg: drop EXPORTed dynamic_debug_exec_queries
@ 2022-03-11  4:47   ` Jim Cromie
  0 siblings, 0 replies; 49+ messages in thread
From: Jim Cromie @ 2022-03-11  4:47 UTC (permalink / raw)
  To: jbaron, gregkh, linux-kernel
  Cc: Jim Cromie, daniel.vetter, intel-gfx, linux, dri-devel,
	robdclark, seanpaul, amd-gfx, joe, intel-gvt-dev

This exported fn is effectively obsoleted by Commit:HEAD~2, so remove it.

Its intent was to allow drm.debug to use the exported function to
implement its drm.debug bitmap api using dynamic_debug.  Instead,
HEAD~2 implements the bitmap inside dyndbg, using the internal fn that
the export wraps.

Since there are no other expected users, and any prospects would
likely reuse the bitmap or a straightforward extension of it, we can
drop the exported function until its really needed.

This also drops the CONFIG_DYNAMIC_DEBUG=N stub-func, and its
pr_warn(), which I avoided in 2012, then added in 2020 :-/

Fixes: a2d375eda771 ("dyndbg: refine export, rename to dynamic_debug_exec_queries()")
Fixes: 4c0d77828d4f ("dyndbg: export ddebug_exec_queries")
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 include/linux/dynamic_debug.h |  9 ---------
 lib/dynamic_debug.c           | 29 -----------------------------
 2 files changed, 38 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index e83c4e36ad29..664bb83778d2 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -60,9 +60,6 @@ struct _ddebug {
 
 #if defined(CONFIG_DYNAMIC_DEBUG_CORE)
 
-/* exported for module authors to exercise >control */
-int dynamic_debug_exec_queries(const char *query, const char *modname);
-
 int ddebug_add_module(struct _ddebug *tab, unsigned int n,
 				const char *modname);
 extern int ddebug_remove_module(const char *mod_name);
@@ -253,12 +250,6 @@ static inline int ddebug_dyndbg_module_param_cb(char *param, char *val,
 				rowsize, groupsize, buf, len, ascii);	\
 	} while (0)
 
-static inline int dynamic_debug_exec_queries(const char *query, const char *modname)
-{
-	pr_warn("kernel not built with CONFIG_DYNAMIC_DEBUG_CORE\n");
-	return 0;
-}
-
 struct kernel_param;
 static inline int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp)
 { return 0; }
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 704361af5b23..b15a9c715e5b 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -582,35 +582,6 @@ static int ddebug_exec_queries(char *query, const char *modname)
 	return nfound;
 }
 
-/**
- * dynamic_debug_exec_queries - select and change dynamic-debug prints
- * @query: query-string described in admin-guide/dynamic-debug-howto
- * @modname: string containing module name, usually &module.mod_name
- *
- * This uses the >/proc/dynamic_debug/control reader, allowing module
- * authors to modify their dynamic-debug callsites. The modname is
- * canonically struct module.mod_name, but can also be null or a
- * module-wildcard, for example: "drm*".
- */
-int dynamic_debug_exec_queries(const char *query, const char *modname)
-{
-	int rc;
-	char *qry; /* writable copy of query */
-
-	if (!query) {
-		pr_err("non-null query/command string expected\n");
-		return -EINVAL;
-	}
-	qry = kstrndup(query, PAGE_SIZE, GFP_KERNEL);
-	if (!qry)
-		return -ENOMEM;
-
-	rc = ddebug_exec_queries(qry, modname);
-	kfree(qry);
-	return rc;
-}
-EXPORT_SYMBOL_GPL(dynamic_debug_exec_queries);
-
 #ifdef CONFIG_MODULES
 #define KP_MOD_NAME kp->mod->name
 #else
-- 
2.35.1


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

* [PATCH 5/5] dyndbg: show both old and new in change-info
  2022-03-11  4:47 ` Jim Cromie
  (?)
  (?)
@ 2022-03-11  4:47   ` Jim Cromie
  -1 siblings, 0 replies; 49+ messages in thread
From: Jim Cromie @ 2022-03-11  4:47 UTC (permalink / raw)
  To: jbaron, gregkh, linux-kernel
  Cc: daniel.vetter, seanpaul, robdclark, linux, joe, dri-devel,
	amd-gfx, intel-gvt-dev, intel-gfx, Jim Cromie

print old -> new flag values in the info("change") message.

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

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index b15a9c715e5b..cceac8ebbacd 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -158,7 +158,7 @@ static int ddebug_change(const struct ddebug_query *query,
 	struct ddebug_table *dt;
 	unsigned int newflags;
 	unsigned int nfound = 0;
-	struct flagsbuf fbuf;
+	struct flagsbuf fbuf, nbuf;
 
 	/* search for matching ddebugs */
 	mutex_lock(&ddebug_lock);
@@ -223,11 +223,12 @@ static int ddebug_change(const struct ddebug_query *query,
 				static_branch_enable(&dp->key.dd_key_true);
 			}
 #endif
+			v4pr_info("changed %s:%d [%s]%s %s -> %s\n",
+				  trim_prefix(dp->filename), dp->lineno,
+				  dt->mod_name, dp->function,
+				  ddebug_describe_flags(dp->flags, &fbuf),
+				  ddebug_describe_flags(newflags, &nbuf));
 			dp->flags = newflags;
-			v4pr_info("changed %s:%d [%s]%s =%s\n",
-				 trim_prefix(dp->filename), dp->lineno,
-				 dt->mod_name, dp->function,
-				 ddebug_describe_flags(dp->flags, &fbuf));
 		}
 	}
 	mutex_unlock(&ddebug_lock);
-- 
2.35.1


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

* [PATCH 5/5] dyndbg: show both old and new in change-info
@ 2022-03-11  4:47   ` Jim Cromie
  0 siblings, 0 replies; 49+ messages in thread
From: Jim Cromie @ 2022-03-11  4:47 UTC (permalink / raw)
  To: jbaron, gregkh, linux-kernel
  Cc: daniel.vetter, intel-gfx, linux, dri-devel, seanpaul, amd-gfx,
	joe, intel-gvt-dev

print old -> new flag values in the info("change") message.

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

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index b15a9c715e5b..cceac8ebbacd 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -158,7 +158,7 @@ static int ddebug_change(const struct ddebug_query *query,
 	struct ddebug_table *dt;
 	unsigned int newflags;
 	unsigned int nfound = 0;
-	struct flagsbuf fbuf;
+	struct flagsbuf fbuf, nbuf;
 
 	/* search for matching ddebugs */
 	mutex_lock(&ddebug_lock);
@@ -223,11 +223,12 @@ static int ddebug_change(const struct ddebug_query *query,
 				static_branch_enable(&dp->key.dd_key_true);
 			}
 #endif
+			v4pr_info("changed %s:%d [%s]%s %s -> %s\n",
+				  trim_prefix(dp->filename), dp->lineno,
+				  dt->mod_name, dp->function,
+				  ddebug_describe_flags(dp->flags, &fbuf),
+				  ddebug_describe_flags(newflags, &nbuf));
 			dp->flags = newflags;
-			v4pr_info("changed %s:%d [%s]%s =%s\n",
-				 trim_prefix(dp->filename), dp->lineno,
-				 dt->mod_name, dp->function,
-				 ddebug_describe_flags(dp->flags, &fbuf));
 		}
 	}
 	mutex_unlock(&ddebug_lock);
-- 
2.35.1


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

* [Intel-gfx] [PATCH 5/5] dyndbg: show both old and new in change-info
@ 2022-03-11  4:47   ` Jim Cromie
  0 siblings, 0 replies; 49+ messages in thread
From: Jim Cromie @ 2022-03-11  4:47 UTC (permalink / raw)
  To: jbaron, gregkh, linux-kernel
  Cc: Jim Cromie, daniel.vetter, intel-gfx, linux, dri-devel, seanpaul,
	amd-gfx, joe, intel-gvt-dev

print old -> new flag values in the info("change") message.

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

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index b15a9c715e5b..cceac8ebbacd 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -158,7 +158,7 @@ static int ddebug_change(const struct ddebug_query *query,
 	struct ddebug_table *dt;
 	unsigned int newflags;
 	unsigned int nfound = 0;
-	struct flagsbuf fbuf;
+	struct flagsbuf fbuf, nbuf;
 
 	/* search for matching ddebugs */
 	mutex_lock(&ddebug_lock);
@@ -223,11 +223,12 @@ static int ddebug_change(const struct ddebug_query *query,
 				static_branch_enable(&dp->key.dd_key_true);
 			}
 #endif
+			v4pr_info("changed %s:%d [%s]%s %s -> %s\n",
+				  trim_prefix(dp->filename), dp->lineno,
+				  dt->mod_name, dp->function,
+				  ddebug_describe_flags(dp->flags, &fbuf),
+				  ddebug_describe_flags(newflags, &nbuf));
 			dp->flags = newflags;
-			v4pr_info("changed %s:%d [%s]%s =%s\n",
-				 trim_prefix(dp->filename), dp->lineno,
-				 dt->mod_name, dp->function,
-				 ddebug_describe_flags(dp->flags, &fbuf));
 		}
 	}
 	mutex_unlock(&ddebug_lock);
-- 
2.35.1


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

* [PATCH 5/5] dyndbg: show both old and new in change-info
@ 2022-03-11  4:47   ` Jim Cromie
  0 siblings, 0 replies; 49+ messages in thread
From: Jim Cromie @ 2022-03-11  4:47 UTC (permalink / raw)
  To: jbaron, gregkh, linux-kernel
  Cc: Jim Cromie, daniel.vetter, intel-gfx, linux, dri-devel,
	robdclark, seanpaul, amd-gfx, joe, intel-gvt-dev

print old -> new flag values in the info("change") message.

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

diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index b15a9c715e5b..cceac8ebbacd 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -158,7 +158,7 @@ static int ddebug_change(const struct ddebug_query *query,
 	struct ddebug_table *dt;
 	unsigned int newflags;
 	unsigned int nfound = 0;
-	struct flagsbuf fbuf;
+	struct flagsbuf fbuf, nbuf;
 
 	/* search for matching ddebugs */
 	mutex_lock(&ddebug_lock);
@@ -223,11 +223,12 @@ static int ddebug_change(const struct ddebug_query *query,
 				static_branch_enable(&dp->key.dd_key_true);
 			}
 #endif
+			v4pr_info("changed %s:%d [%s]%s %s -> %s\n",
+				  trim_prefix(dp->filename), dp->lineno,
+				  dt->mod_name, dp->function,
+				  ddebug_describe_flags(dp->flags, &fbuf),
+				  ddebug_describe_flags(newflags, &nbuf));
 			dp->flags = newflags;
-			v4pr_info("changed %s:%d [%s]%s =%s\n",
-				 trim_prefix(dp->filename), dp->lineno,
-				 dt->mod_name, dp->function,
-				 ddebug_describe_flags(dp->flags, &fbuf));
 		}
 	}
 	mutex_unlock(&ddebug_lock);
-- 
2.35.1


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

* [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for dyndbg add exclusive class support
  2022-03-11  4:47 ` Jim Cromie
                   ` (7 preceding siblings ...)
  (?)
@ 2022-03-11  5:13 ` Patchwork
  -1 siblings, 0 replies; 49+ messages in thread
From: Patchwork @ 2022-03-11  5:13 UTC (permalink / raw)
  To: Jim Cromie; +Cc: intel-gfx

== Series Details ==

Series: dyndbg add exclusive class support
URL   : https://patchwork.freedesktop.org/series/101265/
State : warning

== Summary ==

$ dim checkpatch origin/drm-tip
7362a1150693 dyndbg: fix static_branch manipulation
38c78ef4dda7 dyndbg: add class_id field and query support
-:55: ERROR:GIT_COMMIT_ID: Please use git commit description style 'commit <12+ chars of sha1> ("<title line>")' - ie: 'commit a8f6c71f283e ("dyndbg: add class_id field and query support")'
#55: 
a8f6c71f283e dyndbg: add class_id field and query support

-:56: WARNING:COMMIT_LOG_LONG_LINE: Possible unwrapped commit description (prefer a maximum 75 chars per line)
#56: 
-:141: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'id' - possible side-effects?

-:157: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'id' - possible side-effects?
#157: FILE: include/linux/dynamic_debug.h:142:
+#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {	\
+	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);	\
+	if (DYNAMIC_DEBUG_BRANCH(id))				\
+		func(&id, ##__VA_ARGS__);			\
 } while (0)

-:167: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'id' - possible side-effects?
#167: FILE: include/linux/dynamic_debug.h:148:
+#define __dynamic_func_call_no_desc_cls(id, cls, fmt, func, ...) do {	\
+	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);		\
+	if (DYNAMIC_DEBUG_BRANCH(id))					\
+		func(__VA_ARGS__);					\
 } while (0)

total: 1 errors, 1 warnings, 2 checks, 216 lines checked
af3ef83dfd0c dyndbg: add DEFINE_DYNAMIC_DEBUG_CLASSBITS macro
-:167: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'fsname' - possible side-effects?
#167: FILE: include/linux/dynamic_debug.h:291:
+#define DEFINE_DYNAMIC_DEBUG_CLASSBITS(fsname, _var, _flgs, desc, ...)	\
+	MODULE_PARM_DESC(fsname, desc);					\
+	static struct dyndbg_classbits_param ddcats_##_var = {		\
+		.bits = &(_var),					\
+		.flags = _flgs,						\
+		.classes = { __VA_ARGS__, _DPRINTK_SITE_UNCLASSED }	\
+	};								\
+	module_param_cb(fsname, &param_ops_dyndbg_classbits,		\
+			&ddcats_##_var, 0644)

-:231: CHECK:BRACES: Blank lines aren't necessary after an open brace '{'
#231: FILE: lib/dynamic_debug.c:650:
+		     dcp->classes[i] < _DPRINTK_SITE_UNCLASSED); i++) {
+

total: 0 errors, 0 warnings, 2 checks, 145 lines checked
718d3bf7a683 dyndbg: drop EXPORTed dynamic_debug_exec_queries
e9b94040c396 dyndbg: show both old and new in change-info



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

* [Intel-gfx] ✗ Fi.CI.SPARSE: warning for dyndbg add exclusive class support
  2022-03-11  4:47 ` Jim Cromie
                   ` (8 preceding siblings ...)
  (?)
@ 2022-03-11  5:17 ` Patchwork
  -1 siblings, 0 replies; 49+ messages in thread
From: Patchwork @ 2022-03-11  5:17 UTC (permalink / raw)
  To: Jim Cromie; +Cc: intel-gfx

== Series Details ==

Series: dyndbg add exclusive class support
URL   : https://patchwork.freedesktop.org/series/101265/
State : warning

== Summary ==

$ dim sparse --fast origin/drm-tip
Sparse version: v0.6.2
Fast mode used, each commit won't be checked separately.



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

* [Intel-gfx] ✓ Fi.CI.BAT: success for dyndbg add exclusive class support
  2022-03-11  4:47 ` Jim Cromie
                   ` (9 preceding siblings ...)
  (?)
@ 2022-03-11  5:42 ` Patchwork
  -1 siblings, 0 replies; 49+ messages in thread
From: Patchwork @ 2022-03-11  5:42 UTC (permalink / raw)
  To: Jim Cromie; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 6802 bytes --]

== Series Details ==

Series: dyndbg add exclusive class support
URL   : https://patchwork.freedesktop.org/series/101265/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_11350 -> Patchwork_22537
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/index.html

Participating hosts (48 -> 41)
------------------------------

  Missing    (7): shard-tglu fi-hsw-4200u fi-bsw-cyan fi-ctg-p8600 shard-rkl shard-dg1 fi-bdw-samus 

Known issues
------------

  Here are the changes found in Patchwork_22537 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@amdgpu/amd_basic@semaphore:
    - fi-hsw-4770:        NOTRUN -> [SKIP][1] ([fdo#109271] / [fdo#109315]) +17 similar issues
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/fi-hsw-4770/igt@amdgpu/amd_basic@semaphore.html

  * igt@amdgpu/amd_cs_nop@fork-gfx0:
    - fi-icl-u2:          NOTRUN -> [SKIP][2] ([fdo#109315]) +17 similar issues
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/fi-icl-u2/igt@amdgpu/amd_cs_nop@fork-gfx0.html

  * igt@i915_pm_rps@basic-api:
    - bat-dg1-6:          [PASS][3] -> [FAIL][4] ([i915#4032])
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/bat-dg1-6/igt@i915_pm_rps@basic-api.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/bat-dg1-6/igt@i915_pm_rps@basic-api.html

  * igt@i915_selftest@live@requests:
    - fi-blb-e6850:       [PASS][5] -> [DMESG-FAIL][6] ([i915#4528])
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/fi-blb-e6850/igt@i915_selftest@live@requests.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/fi-blb-e6850/igt@i915_selftest@live@requests.html

  * igt@runner@aborted:
    - fi-blb-e6850:       NOTRUN -> [FAIL][7] ([fdo#109271] / [i915#2403] / [i915#4312])
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/fi-blb-e6850/igt@runner@aborted.html

  
#### Possible fixes ####

  * igt@core_hotunplug@unbind-rebind:
    - fi-bwr-2160:        [FAIL][8] ([i915#3194]) -> [PASS][9]
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/fi-bwr-2160/igt@core_hotunplug@unbind-rebind.html
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/fi-bwr-2160/igt@core_hotunplug@unbind-rebind.html

  * igt@i915_selftest@live@execlists:
    - fi-icl-u2:          [INCOMPLETE][10] -> [PASS][11]
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/fi-icl-u2/igt@i915_selftest@live@execlists.html
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/fi-icl-u2/igt@i915_selftest@live@execlists.html

  * igt@i915_selftest@live@gt_heartbeat:
    - {bat-rpls-2}:       [DMESG-WARN][12] ([i915#4391]) -> [PASS][13]
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/bat-rpls-2/igt@i915_selftest@live@gt_heartbeat.html
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/bat-rpls-2/igt@i915_selftest@live@gt_heartbeat.html

  * igt@i915_selftest@live@hangcheck:
    - fi-hsw-4770:        [INCOMPLETE][14] ([i915#3303]) -> [PASS][15]
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/fi-hsw-4770/igt@i915_selftest@live@hangcheck.html
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/fi-hsw-4770/igt@i915_selftest@live@hangcheck.html

  * igt@i915_selftest@live@hugepages:
    - {bat-rpls-2}:       [DMESG-WARN][16] ([i915#5278]) -> [PASS][17]
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/bat-rpls-2/igt@i915_selftest@live@hugepages.html
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/bat-rpls-2/igt@i915_selftest@live@hugepages.html

  * igt@i915_selftest@live@reset:
    - {bat-rpls-2}:       [INCOMPLETE][18] ([i915#4983]) -> [PASS][19]
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/bat-rpls-2/igt@i915_selftest@live@reset.html
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/bat-rpls-2/igt@i915_selftest@live@reset.html

  * igt@i915_selftest@live@workarounds:
    - {bat-adlp-6}:       [DMESG-WARN][20] ([i915#5068]) -> [PASS][21]
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/bat-adlp-6/igt@i915_selftest@live@workarounds.html
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/bat-adlp-6/igt@i915_selftest@live@workarounds.html

  * igt@kms_busy@basic@flip:
    - {bat-adlp-6}:       [DMESG-WARN][22] ([i915#3576]) -> [PASS][23]
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/bat-adlp-6/igt@kms_busy@basic@flip.html
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/bat-adlp-6/igt@kms_busy@basic@flip.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#109315]: https://bugs.freedesktop.org/show_bug.cgi?id=109315
  [i915#2403]: https://gitlab.freedesktop.org/drm/intel/issues/2403
  [i915#3194]: https://gitlab.freedesktop.org/drm/intel/issues/3194
  [i915#3303]: https://gitlab.freedesktop.org/drm/intel/issues/3303
  [i915#3576]: https://gitlab.freedesktop.org/drm/intel/issues/3576
  [i915#4032]: https://gitlab.freedesktop.org/drm/intel/issues/4032
  [i915#4312]: https://gitlab.freedesktop.org/drm/intel/issues/4312
  [i915#4391]: https://gitlab.freedesktop.org/drm/intel/issues/4391
  [i915#4528]: https://gitlab.freedesktop.org/drm/intel/issues/4528
  [i915#4983]: https://gitlab.freedesktop.org/drm/intel/issues/4983
  [i915#5068]: https://gitlab.freedesktop.org/drm/intel/issues/5068
  [i915#5087]: https://gitlab.freedesktop.org/drm/intel/issues/5087
  [i915#5195]: https://gitlab.freedesktop.org/drm/intel/issues/5195
  [i915#5276]: https://gitlab.freedesktop.org/drm/intel/issues/5276
  [i915#5278]: https://gitlab.freedesktop.org/drm/intel/issues/5278


Build changes
-------------

  * Linux: CI_DRM_11350 -> Patchwork_22537

  CI-20190529: 20190529
  CI_DRM_11350: 925314164278701a48bb63b89a95d6c7e179a02e @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_6375: aa6eb64bac510b7d617436997171bfe388943d89 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  Patchwork_22537: e9b94040c39627c68aed9fa0183865fa1925c352 @ git://anongit.freedesktop.org/gfx-ci/linux


== Linux commits ==

e9b94040c396 dyndbg: show both old and new in change-info
718d3bf7a683 dyndbg: drop EXPORTed dynamic_debug_exec_queries
af3ef83dfd0c dyndbg: add DEFINE_DYNAMIC_DEBUG_CLASSBITS macro
38c78ef4dda7 dyndbg: add class_id field and query support
7362a1150693 dyndbg: fix static_branch manipulation

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/index.html

[-- Attachment #2: Type: text/html, Size: 7684 bytes --]

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

* [Intel-gfx] ✓ Fi.CI.IGT: success for dyndbg add exclusive class support
  2022-03-11  4:47 ` Jim Cromie
                   ` (10 preceding siblings ...)
  (?)
@ 2022-03-11  7:27 ` Patchwork
  -1 siblings, 0 replies; 49+ messages in thread
From: Patchwork @ 2022-03-11  7:27 UTC (permalink / raw)
  To: Jim Cromie; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 30258 bytes --]

== Series Details ==

Series: dyndbg add exclusive class support
URL   : https://patchwork.freedesktop.org/series/101265/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_11350_full -> Patchwork_22537_full
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  

Participating hosts (13 -> 13)
------------------------------

  No changes in participating hosts

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_22537_full:

### IGT changes ###

#### Suppressed ####

  The following results come from untrusted machines, tests, or statuses.
  They do not affect the overall result.

  * igt@api_intel_allocator@fork-simple-stress-signal:
    - {shard-dg1}:        [PASS][1] -> [TIMEOUT][2]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-dg1-18/igt@api_intel_allocator@fork-simple-stress-signal.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-dg1-17/igt@api_intel_allocator@fork-simple-stress-signal.html

  * igt@kms_cursor_legacy@all-pipes-single-move:
    - {shard-rkl}:        [PASS][3] -> [INCOMPLETE][4]
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-rkl-6/igt@kms_cursor_legacy@all-pipes-single-move.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-rkl-5/igt@kms_cursor_legacy@all-pipes-single-move.html

  
Known issues
------------

  Here are the changes found in Patchwork_22537_full that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_create@create-massive:
    - shard-apl:          NOTRUN -> [DMESG-WARN][5] ([i915#4991])
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-apl2/igt@gem_create@create-massive.html

  * igt@gem_exec_balancer@parallel-balancer:
    - shard-iclb:         [PASS][6] -> [SKIP][7] ([i915#4525])
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-iclb2/igt@gem_exec_balancer@parallel-balancer.html
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb8/igt@gem_exec_balancer@parallel-balancer.html

  * igt@gem_exec_balancer@parallel-keep-submit-fence:
    - shard-iclb:         NOTRUN -> [DMESG-WARN][8] ([i915#5076])
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb2/igt@gem_exec_balancer@parallel-keep-submit-fence.html

  * igt@gem_exec_balancer@parallel-ordering:
    - shard-kbl:          NOTRUN -> [DMESG-FAIL][9] ([i915#5076])
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-kbl4/igt@gem_exec_balancer@parallel-ordering.html

  * igt@gem_exec_fair@basic-none-rrul@rcs0:
    - shard-iclb:         NOTRUN -> [FAIL][10] ([i915#2842])
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb8/igt@gem_exec_fair@basic-none-rrul@rcs0.html

  * igt@gem_exec_fair@basic-none@vcs0:
    - shard-apl:          [PASS][11] -> [FAIL][12] ([i915#2842])
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-apl1/igt@gem_exec_fair@basic-none@vcs0.html
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-apl8/igt@gem_exec_fair@basic-none@vcs0.html

  * igt@gem_exec_fair@basic-pace-solo@rcs0:
    - shard-kbl:          NOTRUN -> [FAIL][13] ([i915#2842])
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-kbl4/igt@gem_exec_fair@basic-pace-solo@rcs0.html

  * igt@gem_exec_fair@basic-pace@rcs0:
    - shard-kbl:          [PASS][14] -> [FAIL][15] ([i915#2842])
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-kbl6/igt@gem_exec_fair@basic-pace@rcs0.html
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-kbl7/igt@gem_exec_fair@basic-pace@rcs0.html

  * igt@gem_exec_params@no-vebox:
    - shard-iclb:         NOTRUN -> [SKIP][16] ([fdo#109283])
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb8/igt@gem_exec_params@no-vebox.html

  * igt@gem_lmem_swapping@heavy-random:
    - shard-iclb:         NOTRUN -> [SKIP][17] ([i915#4613])
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb7/igt@gem_lmem_swapping@heavy-random.html

  * igt@gem_lmem_swapping@parallel-random-engines:
    - shard-glk:          NOTRUN -> [SKIP][18] ([fdo#109271] / [i915#4613])
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-glk4/igt@gem_lmem_swapping@parallel-random-engines.html

  * igt@gem_lmem_swapping@random:
    - shard-skl:          NOTRUN -> [SKIP][19] ([fdo#109271] / [i915#4613])
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-skl8/igt@gem_lmem_swapping@random.html

  * igt@gem_pxp@create-regular-buffer:
    - shard-iclb:         NOTRUN -> [SKIP][20] ([i915#4270])
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb7/igt@gem_pxp@create-regular-buffer.html

  * igt@gem_pxp@verify-pxp-key-change-after-suspend-resume:
    - shard-tglb:         NOTRUN -> [SKIP][21] ([i915#4270])
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-tglb5/igt@gem_pxp@verify-pxp-key-change-after-suspend-resume.html

  * igt@gem_render_copy@y-tiled-mc-ccs-to-vebox-y-tiled:
    - shard-iclb:         NOTRUN -> [SKIP][22] ([i915#768]) +3 similar issues
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb8/igt@gem_render_copy@y-tiled-mc-ccs-to-vebox-y-tiled.html

  * igt@gem_render_copy@yf-tiled-mc-ccs-to-vebox-y-tiled:
    - shard-glk:          NOTRUN -> [SKIP][23] ([fdo#109271]) +35 similar issues
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-glk4/igt@gem_render_copy@yf-tiled-mc-ccs-to-vebox-y-tiled.html

  * igt@gen3_render_linear_blits:
    - shard-tglb:         NOTRUN -> [SKIP][24] ([fdo#109289])
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-tglb5/igt@gen3_render_linear_blits.html

  * igt@gen7_exec_parse@basic-rejected:
    - shard-iclb:         NOTRUN -> [SKIP][25] ([fdo#109289])
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb8/igt@gen7_exec_parse@basic-rejected.html

  * igt@gen9_exec_parse@secure-batches:
    - shard-iclb:         NOTRUN -> [SKIP][26] ([i915#2856])
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb2/igt@gen9_exec_parse@secure-batches.html

  * igt@i915_pm_dc@dc6-dpms:
    - shard-iclb:         [PASS][27] -> [FAIL][28] ([i915#454])
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-iclb6/igt@i915_pm_dc@dc6-dpms.html
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb3/igt@i915_pm_dc@dc6-dpms.html

  * igt@i915_pm_lpsp@screens-disabled:
    - shard-iclb:         NOTRUN -> [SKIP][29] ([i915#1902])
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb8/igt@i915_pm_lpsp@screens-disabled.html

  * igt@i915_pm_rc6_residency@rc6-idle:
    - shard-iclb:         NOTRUN -> [WARN][30] ([i915#2684])
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb2/igt@i915_pm_rc6_residency@rc6-idle.html

  * igt@i915_pm_rpm@modeset-non-lpsp:
    - shard-iclb:         NOTRUN -> [SKIP][31] ([fdo#110892])
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb2/igt@i915_pm_rpm@modeset-non-lpsp.html

  * igt@kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-0-async-flip:
    - shard-iclb:         NOTRUN -> [SKIP][32] ([i915#5286])
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb8/igt@kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-0-async-flip.html

  * igt@kms_big_fb@x-tiled-64bpp-rotate-270:
    - shard-iclb:         NOTRUN -> [SKIP][33] ([fdo#110725] / [fdo#111614])
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb7/igt@kms_big_fb@x-tiled-64bpp-rotate-270.html

  * igt@kms_big_fb@x-tiled-max-hw-stride-32bpp-rotate-0-async-flip:
    - shard-skl:          NOTRUN -> [FAIL][34] ([i915#3743]) +2 similar issues
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-skl8/igt@kms_big_fb@x-tiled-max-hw-stride-32bpp-rotate-0-async-flip.html

  * igt@kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-180-hflip-async-flip:
    - shard-skl:          NOTRUN -> [SKIP][35] ([fdo#109271] / [i915#3777])
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-skl9/igt@kms_big_fb@y-tiled-max-hw-stride-32bpp-rotate-180-hflip-async-flip.html

  * igt@kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-0-async-flip:
    - shard-skl:          NOTRUN -> [FAIL][36] ([i915#3763])
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-skl8/igt@kms_big_fb@y-tiled-max-hw-stride-64bpp-rotate-0-async-flip.html

  * igt@kms_big_fb@yf-tiled-32bpp-rotate-180:
    - shard-iclb:         [PASS][37] -> [DMESG-FAIL][38] ([i915#1888])
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-iclb2/igt@kms_big_fb@yf-tiled-32bpp-rotate-180.html
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb2/igt@kms_big_fb@yf-tiled-32bpp-rotate-180.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-hflip:
    - shard-glk:          NOTRUN -> [SKIP][39] ([fdo#109271] / [i915#3777]) +1 similar issue
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-glk4/igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-hflip.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-0:
    - shard-apl:          NOTRUN -> [SKIP][40] ([fdo#109271]) +82 similar issues
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-apl2/igt@kms_big_fb@yf-tiled-max-hw-stride-64bpp-rotate-0.html

  * igt@kms_big_joiner@2x-modeset:
    - shard-iclb:         NOTRUN -> [SKIP][41] ([i915#2705])
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb7/igt@kms_big_joiner@2x-modeset.html

  * igt@kms_ccs@pipe-a-ccs-on-another-bo-y_tiled_gen12_rc_ccs_cc:
    - shard-iclb:         NOTRUN -> [SKIP][42] ([fdo#109278] / [i915#3886]) +4 similar issues
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb8/igt@kms_ccs@pipe-a-ccs-on-another-bo-y_tiled_gen12_rc_ccs_cc.html

  * igt@kms_ccs@pipe-a-random-ccs-data-yf_tiled_ccs:
    - shard-tglb:         NOTRUN -> [SKIP][43] ([fdo#111615] / [i915#3689])
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-tglb5/igt@kms_ccs@pipe-a-random-ccs-data-yf_tiled_ccs.html

  * igt@kms_ccs@pipe-b-crc-primary-basic-y_tiled_gen12_mc_ccs:
    - shard-skl:          NOTRUN -> [SKIP][44] ([fdo#109271] / [i915#3886]) +6 similar issues
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-skl8/igt@kms_ccs@pipe-b-crc-primary-basic-y_tiled_gen12_mc_ccs.html
    - shard-kbl:          NOTRUN -> [SKIP][45] ([fdo#109271] / [i915#3886]) +1 similar issue
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-kbl4/igt@kms_ccs@pipe-b-crc-primary-basic-y_tiled_gen12_mc_ccs.html

  * igt@kms_ccs@pipe-b-crc-sprite-planes-basic-y_tiled_gen12_rc_ccs_cc:
    - shard-apl:          NOTRUN -> [SKIP][46] ([fdo#109271] / [i915#3886]) +3 similar issues
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-apl8/igt@kms_ccs@pipe-b-crc-sprite-planes-basic-y_tiled_gen12_rc_ccs_cc.html

  * igt@kms_ccs@pipe-c-random-ccs-data-y_tiled_gen12_rc_ccs_cc:
    - shard-glk:          NOTRUN -> [SKIP][47] ([fdo#109271] / [i915#3886]) +1 similar issue
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-glk4/igt@kms_ccs@pipe-c-random-ccs-data-y_tiled_gen12_rc_ccs_cc.html

  * igt@kms_ccs@pipe-d-missing-ccs-buffer-y_tiled_gen12_mc_ccs:
    - shard-tglb:         NOTRUN -> [SKIP][48] ([i915#3689])
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-tglb5/igt@kms_ccs@pipe-d-missing-ccs-buffer-y_tiled_gen12_mc_ccs.html

  * igt@kms_chamelium@dp-crc-multiple:
    - shard-apl:          NOTRUN -> [SKIP][49] ([fdo#109271] / [fdo#111827]) +6 similar issues
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-apl8/igt@kms_chamelium@dp-crc-multiple.html

  * igt@kms_chamelium@hdmi-aspect-ratio:
    - shard-glk:          NOTRUN -> [SKIP][50] ([fdo#109271] / [fdo#111827]) +3 similar issues
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-glk4/igt@kms_chamelium@hdmi-aspect-ratio.html

  * igt@kms_chamelium@hdmi-audio:
    - shard-iclb:         NOTRUN -> [SKIP][51] ([fdo#109284] / [fdo#111827]) +10 similar issues
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb2/igt@kms_chamelium@hdmi-audio.html

  * igt@kms_chamelium@hdmi-hpd-after-suspend:
    - shard-snb:          NOTRUN -> [SKIP][52] ([fdo#109271] / [fdo#111827]) +3 similar issues
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-snb4/igt@kms_chamelium@hdmi-hpd-after-suspend.html

  * igt@kms_color@pipe-d-ctm-0-5:
    - shard-iclb:         NOTRUN -> [SKIP][53] ([fdo#109278] / [i915#1149])
   [53]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb7/igt@kms_color@pipe-d-ctm-0-5.html

  * igt@kms_color_chamelium@pipe-b-ctm-max:
    - shard-skl:          NOTRUN -> [SKIP][54] ([fdo#109271] / [fdo#111827]) +9 similar issues
   [54]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-skl8/igt@kms_color_chamelium@pipe-b-ctm-max.html

  * igt@kms_color_chamelium@pipe-c-ctm-max:
    - shard-kbl:          NOTRUN -> [SKIP][55] ([fdo#109271] / [fdo#111827]) +2 similar issues
   [55]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-kbl4/igt@kms_color_chamelium@pipe-c-ctm-max.html

  * igt@kms_cursor_crc@pipe-b-cursor-suspend:
    - shard-apl:          NOTRUN -> [DMESG-WARN][56] ([i915#180])
   [56]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-apl2/igt@kms_cursor_crc@pipe-b-cursor-suspend.html

  * igt@kms_cursor_crc@pipe-c-cursor-512x170-sliding:
    - shard-iclb:         NOTRUN -> [SKIP][57] ([fdo#109278] / [fdo#109279])
   [57]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb8/igt@kms_cursor_crc@pipe-c-cursor-512x170-sliding.html

  * igt@kms_cursor_crc@pipe-d-cursor-256x256-rapid-movement:
    - shard-iclb:         NOTRUN -> [SKIP][58] ([fdo#109278]) +18 similar issues
   [58]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb8/igt@kms_cursor_crc@pipe-d-cursor-256x256-rapid-movement.html

  * igt@kms_cursor_legacy@2x-flip-vs-cursor-atomic:
    - shard-iclb:         NOTRUN -> [SKIP][59] ([fdo#109274] / [fdo#109278]) +1 similar issue
   [59]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb2/igt@kms_cursor_legacy@2x-flip-vs-cursor-atomic.html

  * igt@kms_cursor_legacy@cursorb-vs-flipa-legacy:
    - shard-tglb:         NOTRUN -> [SKIP][60] ([fdo#109274] / [fdo#111825]) +1 similar issue
   [60]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-tglb5/igt@kms_cursor_legacy@cursorb-vs-flipa-legacy.html

  * igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size:
    - shard-skl:          [PASS][61] -> [FAIL][62] ([i915#2346] / [i915#533])
   [61]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-skl6/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size.html
   [62]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-skl7/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size.html

  * igt@kms_cursor_legacy@pipe-d-torture-bo:
    - shard-apl:          NOTRUN -> [SKIP][63] ([fdo#109271] / [i915#533]) +1 similar issue
   [63]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-apl4/igt@kms_cursor_legacy@pipe-d-torture-bo.html

  * igt@kms_draw_crc@draw-method-rgb565-mmap-gtt-4tiled:
    - shard-iclb:         NOTRUN -> [SKIP][64] ([i915#5287]) +1 similar issue
   [64]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb2/igt@kms_draw_crc@draw-method-rgb565-mmap-gtt-4tiled.html

  * igt@kms_flip@2x-flip-vs-dpms:
    - shard-iclb:         NOTRUN -> [SKIP][65] ([fdo#109274]) +3 similar issues
   [65]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb7/igt@kms_flip@2x-flip-vs-dpms.html

  * igt@kms_flip@2x-flip-vs-expired-vblank-interruptible@ab-hdmi-a1-hdmi-a2:
    - shard-glk:          [PASS][66] -> [FAIL][67] ([i915#79])
   [66]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-glk3/igt@kms_flip@2x-flip-vs-expired-vblank-interruptible@ab-hdmi-a1-hdmi-a2.html
   [67]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-glk9/igt@kms_flip@2x-flip-vs-expired-vblank-interruptible@ab-hdmi-a1-hdmi-a2.html

  * igt@kms_flip@flip-vs-suspend-interruptible@a-dp1:
    - shard-kbl:          [PASS][68] -> [DMESG-WARN][69] ([i915#180]) +3 similar issues
   [68]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-kbl3/igt@kms_flip@flip-vs-suspend-interruptible@a-dp1.html
   [69]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-kbl1/igt@kms_flip@flip-vs-suspend-interruptible@a-dp1.html

  * igt@kms_flip@plain-flip-ts-check@a-edp1:
    - shard-skl:          [PASS][70] -> [FAIL][71] ([i915#2122])
   [70]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-skl1/igt@kms_flip@plain-flip-ts-check@a-edp1.html
   [71]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-skl7/igt@kms_flip@plain-flip-ts-check@a-edp1.html

  * igt@kms_frontbuffer_tracking@fbc-1p-shrfb-fliptrack-mmap-gtt:
    - shard-skl:          NOTRUN -> [SKIP][72] ([fdo#109271]) +117 similar issues
   [72]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-skl8/igt@kms_frontbuffer_tracking@fbc-1p-shrfb-fliptrack-mmap-gtt.html

  * igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-shrfb-draw-pwrite:
    - shard-tglb:         NOTRUN -> [SKIP][73] ([fdo#109280] / [fdo#111825]) +4 similar issues
   [73]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-tglb5/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-shrfb-draw-pwrite.html

  * igt@kms_frontbuffer_tracking@fbc-2p-shrfb-fliptrack-mmap-gtt:
    - shard-iclb:         NOTRUN -> [SKIP][74] ([fdo#109280]) +19 similar issues
   [74]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb7/igt@kms_frontbuffer_tracking@fbc-2p-shrfb-fliptrack-mmap-gtt.html

  * igt@kms_pipe_b_c_ivb@from-pipe-c-to-b-with-3-lanes:
    - shard-kbl:          NOTRUN -> [SKIP][75] ([fdo#109271]) +34 similar issues
   [75]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-kbl4/igt@kms_pipe_b_c_ivb@from-pipe-c-to-b-with-3-lanes.html

  * igt@kms_pipe_crc_basic@suspend-read-crc-pipe-a:
    - shard-kbl:          [PASS][76] -> [DMESG-WARN][77] ([i915#180] / [i915#1982])
   [76]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-kbl4/igt@kms_pipe_crc_basic@suspend-read-crc-pipe-a.html
   [77]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-kbl1/igt@kms_pipe_crc_basic@suspend-read-crc-pipe-a.html

  * igt@kms_pipe_crc_basic@suspend-read-crc-pipe-d:
    - shard-skl:          NOTRUN -> [SKIP][78] ([fdo#109271] / [i915#533]) +1 similar issue
   [78]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-skl8/igt@kms_pipe_crc_basic@suspend-read-crc-pipe-d.html

  * igt@kms_plane@plane-panning-bottom-right-suspend@pipe-a-planes:
    - shard-apl:          [PASS][79] -> [DMESG-WARN][80] ([i915#180]) +3 similar issues
   [79]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-apl1/igt@kms_plane@plane-panning-bottom-right-suspend@pipe-a-planes.html
   [80]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-apl8/igt@kms_plane@plane-panning-bottom-right-suspend@pipe-a-planes.html

  * igt@kms_plane_alpha_blend@pipe-a-alpha-basic:
    - shard-skl:          NOTRUN -> [FAIL][81] ([fdo#108145] / [i915#265]) +1 similar issue
   [81]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-skl8/igt@kms_plane_alpha_blend@pipe-a-alpha-basic.html
    - shard-kbl:          NOTRUN -> [FAIL][82] ([fdo#108145] / [i915#265])
   [82]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-kbl4/igt@kms_plane_alpha_blend@pipe-a-alpha-basic.html

  * igt@kms_plane_alpha_blend@pipe-c-alpha-opaque-fb:
    - shard-glk:          NOTRUN -> [FAIL][83] ([fdo#108145] / [i915#265])
   [83]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-glk4/igt@kms_plane_alpha_blend@pipe-c-alpha-opaque-fb.html

  * igt@kms_plane_lowres@pipe-a-tiling-4:
    - shard-iclb:         NOTRUN -> [SKIP][84] ([i915#5288])
   [84]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb8/igt@kms_plane_lowres@pipe-a-tiling-4.html

  * igt@kms_plane_lowres@pipe-c-tiling-yf:
    - shard-iclb:         NOTRUN -> [SKIP][85] ([i915#3536])
   [85]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb8/igt@kms_plane_lowres@pipe-c-tiling-yf.html

  * igt@kms_psr2_sf@overlay-plane-update-continuous-sf:
    - shard-apl:          NOTRUN -> [SKIP][86] ([fdo#109271] / [i915#658])
   [86]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-apl4/igt@kms_psr2_sf@overlay-plane-update-continuous-sf.html

  * igt@kms_psr2_sf@primary-plane-update-sf-dmg-area:
    - shard-glk:          NOTRUN -> [SKIP][87] ([fdo#109271] / [i915#658])
   [87]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-glk4/igt@kms_psr2_sf@primary-plane-update-sf-dmg-area.html

  * igt@kms_psr2_su@page_flip-xrgb8888:
    - shard-skl:          NOTRUN -> [SKIP][88] ([fdo#109271] / [i915#658]) +3 similar issues
   [88]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-skl8/igt@kms_psr2_su@page_flip-xrgb8888.html
    - shard-kbl:          NOTRUN -> [SKIP][89] ([fdo#109271] / [i915#658]) +1 similar issue
   [89]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-kbl4/igt@kms_psr2_su@page_flip-xrgb8888.html

  * igt@kms_psr@psr2_cursor_plane_onoff:
    - shard-iclb:         [PASS][90] -> [SKIP][91] ([fdo#109441]) +1 similar issue
   [90]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-iclb2/igt@kms_psr@psr2_cursor_plane_onoff.html
   [91]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb8/igt@kms_psr@psr2_cursor_plane_onoff.html

  * igt@kms_psr@psr2_sprite_render:
    - shard-iclb:         NOTRUN -> [SKIP][92] ([fdo#109441])
   [92]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb8/igt@kms_psr@psr2_sprite_render.html

  * igt@kms_sysfs_edid_timing:
    - shard-apl:          NOTRUN -> [FAIL][93] ([IGT#2])
   [93]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-apl2/igt@kms_sysfs_edid_timing.html

  * igt@kms_vrr@flipline:
    - shard-iclb:         NOTRUN -> [SKIP][94] ([fdo#109502])
   [94]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb8/igt@kms_vrr@flipline.html

  * igt@kms_writeback@writeback-check-output:
    - shard-apl:          NOTRUN -> [SKIP][95] ([fdo#109271] / [i915#2437])
   [95]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-apl2/igt@kms_writeback@writeback-check-output.html

  * igt@nouveau_crc@pipe-b-source-outp-inactive:
    - shard-iclb:         NOTRUN -> [SKIP][96] ([i915#2530])
   [96]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb8/igt@nouveau_crc@pipe-b-source-outp-inactive.html

  * igt@perf@buffer-fill:
    - shard-snb:          NOTRUN -> [SKIP][97] ([fdo#109271]) +53 similar issues
   [97]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-snb4/igt@perf@buffer-fill.html

  * igt@prime_nv_api@i915_nv_import_vs_close:
    - shard-iclb:         NOTRUN -> [SKIP][98] ([fdo#109291])
   [98]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb8/igt@prime_nv_api@i915_nv_import_vs_close.html

  * igt@prime_udl:
    - shard-tglb:         NOTRUN -> [SKIP][99] ([fdo#109291])
   [99]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-tglb5/igt@prime_udl.html

  * igt@syncobj_timeline@transfer-timeline-point:
    - shard-kbl:          NOTRUN -> [DMESG-FAIL][100] ([i915#5098])
   [100]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-kbl1/igt@syncobj_timeline@transfer-timeline-point.html

  * igt@sysfs_clients@busy:
    - shard-skl:          NOTRUN -> [SKIP][101] ([fdo#109271] / [i915#2994]) +1 similar issue
   [101]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-skl8/igt@sysfs_clients@busy.html
    - shard-iclb:         NOTRUN -> [SKIP][102] ([i915#2994])
   [102]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb8/igt@sysfs_clients@busy.html

  * igt@sysfs_clients@fair-1:
    - shard-glk:          NOTRUN -> [SKIP][103] ([fdo#109271] / [i915#2994])
   [103]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-glk4/igt@sysfs_clients@fair-1.html

  * igt@sysfs_clients@recycle-many:
    - shard-apl:          NOTRUN -> [SKIP][104] ([fdo#109271] / [i915#2994]) +1 similar issue
   [104]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-apl8/igt@sysfs_clients@recycle-many.html

  * igt@sysfs_clients@split-50:
    - shard-kbl:          NOTRUN -> [SKIP][105] ([fdo#109271] / [i915#2994]) +1 similar issue
   [105]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-kbl4/igt@sysfs_clients@split-50.html

  
#### Possible fixes ####

  * igt@gem_eio@kms:
    - {shard-rkl}:        [SKIP][106] ([i915#1845]) -> [PASS][107] +9 similar issues
   [106]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-rkl-1/igt@gem_eio@kms.html
   [107]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-rkl-6/igt@gem_eio@kms.html

  * igt@gem_eio@unwedge-stress:
    - {shard-tglu}:       [TIMEOUT][108] ([i915#3063] / [i915#3648]) -> [PASS][109]
   [108]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-tglu-3/igt@gem_eio@unwedge-stress.html
   [109]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-tglu-1/igt@gem_eio@unwedge-stress.html

  * igt@gem_exec_capture@pi@bcs0:
    - shard-iclb:         [INCOMPLETE][110] ([i915#3371]) -> [PASS][111]
   [110]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-iclb4/igt@gem_exec_capture@pi@bcs0.html
   [111]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb7/igt@gem_exec_capture@pi@bcs0.html

  * igt@gem_exec_capture@pi@vcs0:
    - {shard-tglu}:       [INCOMPLETE][112] ([i915#3371]) -> [PASS][113]
   [112]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-tglu-1/igt@gem_exec_capture@pi@vcs0.html
   [113]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-tglu-6/igt@gem_exec_capture@pi@vcs0.html

  * igt@gem_exec_fair@basic-none@vcs0:
    - shard-kbl:          [FAIL][114] ([i915#2842]) -> [PASS][115] +6 similar issues
   [114]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-kbl1/igt@gem_exec_fair@basic-none@vcs0.html
   [115]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-kbl4/igt@gem_exec_fair@basic-none@vcs0.html

  * igt@gem_exec_whisper@basic-fds-all:
    - shard-glk:          [INCOMPLETE][116] -> [PASS][117]
   [116]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-glk3/igt@gem_exec_whisper@basic-fds-all.html
   [117]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-glk4/igt@gem_exec_whisper@basic-fds-all.html

  * igt@gem_fence_thrash@bo-write-verify-none:
    - {shard-rkl}:        [INCOMPLETE][118] -> [PASS][119]
   [118]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-rkl-5/igt@gem_fence_thrash@bo-write-verify-none.html
   [119]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-rkl-2/igt@gem_fence_thrash@bo-write-verify-none.html

  * igt@gem_workarounds@suspend-resume-context:
    - shard-apl:          [DMESG-WARN][120] ([i915#180]) -> [PASS][121] +2 similar issues
   [120]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-apl4/igt@gem_workarounds@suspend-resume-context.html
   [121]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-apl2/igt@gem_workarounds@suspend-resume-context.html

  * igt@gen9_exec_parse@allowed-single:
    - shard-skl:          [DMESG-WARN][122] ([i915#1436] / [i915#716]) -> [PASS][123]
   [122]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-skl10/igt@gen9_exec_parse@allowed-single.html
   [123]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-skl9/igt@gen9_exec_parse@allowed-single.html

  * igt@i915_selftest@live@hangcheck:
    - shard-iclb:         [INCOMPLETE][124] -> [PASS][125]
   [124]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-iclb5/igt@i915_selftest@live@hangcheck.html
   [125]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-iclb2/igt@i915_selftest@live@hangcheck.html
    - shard-snb:          [INCOMPLETE][126] ([i915#3921]) -> [PASS][127]
   [126]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-snb7/igt@i915_selftest@live@hangcheck.html
   [127]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-snb4/igt@i915_selftest@live@hangcheck.html

  * igt@kms_cursor_crc@pipe-a-cursor-64x21-sliding:
    - {shard-rkl}:        [SKIP][128] ([fdo#112022] / [i915#4070]) -> [PASS][129]
   [128]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-rkl-1/igt@kms_cursor_crc@pipe-a-cursor-64x21-sliding.html
   [129]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-rkl-6/igt@kms_cursor_crc@pipe-a-cursor-64x21-sliding.html

  * igt@kms_cursor_edge_walk@pipe-b-256x256-left-edge:
    - {shard-rkl}:        [SKIP][130] ([i915#1849] / [i915#4070]) -> [PASS][131] +2 similar issues
   [130]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-rkl-1/igt@kms_cursor_edge_walk@pipe-b-256x256-left-edge.html
   [131]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-rkl-6/igt@kms_cursor_edge_walk@pipe-b-256x256-left-edge.html

  * igt@kms_draw_crc@draw-method-rgb565-mmap-gtt-ytiled:
    - {shard-rkl}:        [SKIP][132] ([fdo#111314] / [i915#4369]) -> [PASS][133] +2 similar issues
   [132]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11350/shard-rkl-1/igt@kms_draw_crc@draw-method-rgb565-mmap-gtt-ytiled.html
   [133]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/shard-rkl-6/igt

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22537/index.html

[-- Attachment #2: Type: text/html, Size: 33735 bytes --]

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

* Re: [PATCH 1/5] dyndbg: fix static_branch manipulation
  2022-03-11  4:47   ` Jim Cromie
  (?)
  (?)
@ 2022-03-11 18:03     ` Jason Baron
  -1 siblings, 0 replies; 49+ messages in thread
From: Jason Baron @ 2022-03-11 18:03 UTC (permalink / raw)
  To: Jim Cromie, gregkh, linux-kernel
  Cc: daniel.vetter, seanpaul, robdclark, linux, joe, dri-devel,
	amd-gfx, intel-gvt-dev, intel-gfx, vincent.whitchurch



On 3/10/22 23:47, Jim Cromie wrote:
> In https://urldefense.com/v3/__https://lore.kernel.org/lkml/20211209150910.GA23668@axis.com/__;!!GjvTz_vk!HGKKoni4RVdEBgv_V0zPSNSX428bpf02zkCy2WbeQkBdVtp1QJqGX-lJYlRDGg$ 
> 
> Vincent's patch commented on, and worked around, a bug toggling
> static_branch's, when a 2nd PRINTK-ish flag was added.  The bug
> results in a premature static_branch_disable when the 1st of 2 flags
> was disabled.
> 
> The cited commit computed newflags, but then in the JUMP_LABEL block,
> failed to use that result, instead using just one of the terms in it.
> Using newflags instead made the code work properly.
> 
> This is Vincents test-case, reduced.  It needs the 2nd flag to work
> properly, but it's explanatory here.
> 
> pt_test() {
>     echo 5 > /sys/module/dynamic_debug/verbose
> 
>     site="module tcp" # just one callsite
>     echo " $site =_ " > /proc/dynamic_debug/control # clear it
> 
>     # A B ~A ~B
>     for flg in +T +p "-T #broke here" -p; do
> 	echo " $site $flg " > /proc/dynamic_debug/control
>     done;
> 
>     # A B ~B ~A
>     for flg in +T +p "-p #broke here" -T; do
> 	echo " $site $flg " > /proc/dynamic_debug/control
>     done
> }
> pt_test
> 
> Fixes: 84da83a6ffc0 dyndbg: combine flags & mask into a struct, simplify with it
> CC: vincent.whitchurch@axis.com
> Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
> 
> --
> .drop @stable, no exposed bug.
> ---
>  lib/dynamic_debug.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
> index dd7f56af9aed..a56c1286ffa4 100644
> --- a/lib/dynamic_debug.c
> +++ b/lib/dynamic_debug.c
> @@ -211,10 +211,11 @@ static int ddebug_change(const struct ddebug_query *query,
>  				continue;
>  #ifdef CONFIG_JUMP_LABEL
>  			if (dp->flags & _DPRINTK_FLAGS_PRINT) {
> -				if (!(modifiers->flags & _DPRINTK_FLAGS_PRINT))
> +				if (!(newflags & _DPRINTK_FLAGS_PRINT))
>  					static_branch_disable(&dp->key.dd_key_true);
> -			} else if (modifiers->flags & _DPRINTK_FLAGS_PRINT)
> +			} else if (newflags & _DPRINTK_FLAGS_PRINT) {
>  				static_branch_enable(&dp->key.dd_key_true);
> +			}
>  #endif
>  			dp->flags = newflags;
>  			v4pr_info("changed %s:%d [%s]%s =%s\n",



Hi Jim,

If iiuc this is currently a bug but could be if we add a second 'print' bit
such as for printing to the tracing logs. That said I agree that using 'newflags'
here makes the code more straightforward/readable. So this one is fine with
me.

Acked-by: Jason Baron <jbaron@akamai.com>

Thanks,

-Jason

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

* Re: [PATCH 1/5] dyndbg: fix static_branch manipulation
@ 2022-03-11 18:03     ` Jason Baron
  0 siblings, 0 replies; 49+ messages in thread
From: Jason Baron @ 2022-03-11 18:03 UTC (permalink / raw)
  To: Jim Cromie, gregkh, linux-kernel
  Cc: daniel.vetter, intel-gfx, vincent.whitchurch, linux, dri-devel,
	seanpaul, amd-gfx, joe, intel-gvt-dev



On 3/10/22 23:47, Jim Cromie wrote:
> In https://urldefense.com/v3/__https://lore.kernel.org/lkml/20211209150910.GA23668@axis.com/__;!!GjvTz_vk!HGKKoni4RVdEBgv_V0zPSNSX428bpf02zkCy2WbeQkBdVtp1QJqGX-lJYlRDGg$ 
> 
> Vincent's patch commented on, and worked around, a bug toggling
> static_branch's, when a 2nd PRINTK-ish flag was added.  The bug
> results in a premature static_branch_disable when the 1st of 2 flags
> was disabled.
> 
> The cited commit computed newflags, but then in the JUMP_LABEL block,
> failed to use that result, instead using just one of the terms in it.
> Using newflags instead made the code work properly.
> 
> This is Vincents test-case, reduced.  It needs the 2nd flag to work
> properly, but it's explanatory here.
> 
> pt_test() {
>     echo 5 > /sys/module/dynamic_debug/verbose
> 
>     site="module tcp" # just one callsite
>     echo " $site =_ " > /proc/dynamic_debug/control # clear it
> 
>     # A B ~A ~B
>     for flg in +T +p "-T #broke here" -p; do
> 	echo " $site $flg " > /proc/dynamic_debug/control
>     done;
> 
>     # A B ~B ~A
>     for flg in +T +p "-p #broke here" -T; do
> 	echo " $site $flg " > /proc/dynamic_debug/control
>     done
> }
> pt_test
> 
> Fixes: 84da83a6ffc0 dyndbg: combine flags & mask into a struct, simplify with it
> CC: vincent.whitchurch@axis.com
> Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
> 
> --
> .drop @stable, no exposed bug.
> ---
>  lib/dynamic_debug.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
> index dd7f56af9aed..a56c1286ffa4 100644
> --- a/lib/dynamic_debug.c
> +++ b/lib/dynamic_debug.c
> @@ -211,10 +211,11 @@ static int ddebug_change(const struct ddebug_query *query,
>  				continue;
>  #ifdef CONFIG_JUMP_LABEL
>  			if (dp->flags & _DPRINTK_FLAGS_PRINT) {
> -				if (!(modifiers->flags & _DPRINTK_FLAGS_PRINT))
> +				if (!(newflags & _DPRINTK_FLAGS_PRINT))
>  					static_branch_disable(&dp->key.dd_key_true);
> -			} else if (modifiers->flags & _DPRINTK_FLAGS_PRINT)
> +			} else if (newflags & _DPRINTK_FLAGS_PRINT) {
>  				static_branch_enable(&dp->key.dd_key_true);
> +			}
>  #endif
>  			dp->flags = newflags;
>  			v4pr_info("changed %s:%d [%s]%s =%s\n",



Hi Jim,

If iiuc this is currently a bug but could be if we add a second 'print' bit
such as for printing to the tracing logs. That said I agree that using 'newflags'
here makes the code more straightforward/readable. So this one is fine with
me.

Acked-by: Jason Baron <jbaron@akamai.com>

Thanks,

-Jason

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

* Re: [PATCH 1/5] dyndbg: fix static_branch manipulation
@ 2022-03-11 18:03     ` Jason Baron
  0 siblings, 0 replies; 49+ messages in thread
From: Jason Baron @ 2022-03-11 18:03 UTC (permalink / raw)
  To: Jim Cromie, gregkh, linux-kernel
  Cc: daniel.vetter, intel-gfx, vincent.whitchurch, linux, dri-devel,
	robdclark, seanpaul, amd-gfx, joe, intel-gvt-dev



On 3/10/22 23:47, Jim Cromie wrote:
> In https://urldefense.com/v3/__https://lore.kernel.org/lkml/20211209150910.GA23668@axis.com/__;!!GjvTz_vk!HGKKoni4RVdEBgv_V0zPSNSX428bpf02zkCy2WbeQkBdVtp1QJqGX-lJYlRDGg$ 
> 
> Vincent's patch commented on, and worked around, a bug toggling
> static_branch's, when a 2nd PRINTK-ish flag was added.  The bug
> results in a premature static_branch_disable when the 1st of 2 flags
> was disabled.
> 
> The cited commit computed newflags, but then in the JUMP_LABEL block,
> failed to use that result, instead using just one of the terms in it.
> Using newflags instead made the code work properly.
> 
> This is Vincents test-case, reduced.  It needs the 2nd flag to work
> properly, but it's explanatory here.
> 
> pt_test() {
>     echo 5 > /sys/module/dynamic_debug/verbose
> 
>     site="module tcp" # just one callsite
>     echo " $site =_ " > /proc/dynamic_debug/control # clear it
> 
>     # A B ~A ~B
>     for flg in +T +p "-T #broke here" -p; do
> 	echo " $site $flg " > /proc/dynamic_debug/control
>     done;
> 
>     # A B ~B ~A
>     for flg in +T +p "-p #broke here" -T; do
> 	echo " $site $flg " > /proc/dynamic_debug/control
>     done
> }
> pt_test
> 
> Fixes: 84da83a6ffc0 dyndbg: combine flags & mask into a struct, simplify with it
> CC: vincent.whitchurch@axis.com
> Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
> 
> --
> .drop @stable, no exposed bug.
> ---
>  lib/dynamic_debug.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
> index dd7f56af9aed..a56c1286ffa4 100644
> --- a/lib/dynamic_debug.c
> +++ b/lib/dynamic_debug.c
> @@ -211,10 +211,11 @@ static int ddebug_change(const struct ddebug_query *query,
>  				continue;
>  #ifdef CONFIG_JUMP_LABEL
>  			if (dp->flags & _DPRINTK_FLAGS_PRINT) {
> -				if (!(modifiers->flags & _DPRINTK_FLAGS_PRINT))
> +				if (!(newflags & _DPRINTK_FLAGS_PRINT))
>  					static_branch_disable(&dp->key.dd_key_true);
> -			} else if (modifiers->flags & _DPRINTK_FLAGS_PRINT)
> +			} else if (newflags & _DPRINTK_FLAGS_PRINT) {
>  				static_branch_enable(&dp->key.dd_key_true);
> +			}
>  #endif
>  			dp->flags = newflags;
>  			v4pr_info("changed %s:%d [%s]%s =%s\n",



Hi Jim,

If iiuc this is currently a bug but could be if we add a second 'print' bit
such as for printing to the tracing logs. That said I agree that using 'newflags'
here makes the code more straightforward/readable. So this one is fine with
me.

Acked-by: Jason Baron <jbaron@akamai.com>

Thanks,

-Jason

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

* Re: [Intel-gfx] [PATCH 1/5] dyndbg: fix static_branch manipulation
@ 2022-03-11 18:03     ` Jason Baron
  0 siblings, 0 replies; 49+ messages in thread
From: Jason Baron @ 2022-03-11 18:03 UTC (permalink / raw)
  To: Jim Cromie, gregkh, linux-kernel
  Cc: daniel.vetter, intel-gfx, vincent.whitchurch, linux, dri-devel,
	seanpaul, amd-gfx, joe, intel-gvt-dev



On 3/10/22 23:47, Jim Cromie wrote:
> In https://urldefense.com/v3/__https://lore.kernel.org/lkml/20211209150910.GA23668@axis.com/__;!!GjvTz_vk!HGKKoni4RVdEBgv_V0zPSNSX428bpf02zkCy2WbeQkBdVtp1QJqGX-lJYlRDGg$ 
> 
> Vincent's patch commented on, and worked around, a bug toggling
> static_branch's, when a 2nd PRINTK-ish flag was added.  The bug
> results in a premature static_branch_disable when the 1st of 2 flags
> was disabled.
> 
> The cited commit computed newflags, but then in the JUMP_LABEL block,
> failed to use that result, instead using just one of the terms in it.
> Using newflags instead made the code work properly.
> 
> This is Vincents test-case, reduced.  It needs the 2nd flag to work
> properly, but it's explanatory here.
> 
> pt_test() {
>     echo 5 > /sys/module/dynamic_debug/verbose
> 
>     site="module tcp" # just one callsite
>     echo " $site =_ " > /proc/dynamic_debug/control # clear it
> 
>     # A B ~A ~B
>     for flg in +T +p "-T #broke here" -p; do
> 	echo " $site $flg " > /proc/dynamic_debug/control
>     done;
> 
>     # A B ~B ~A
>     for flg in +T +p "-p #broke here" -T; do
> 	echo " $site $flg " > /proc/dynamic_debug/control
>     done
> }
> pt_test
> 
> Fixes: 84da83a6ffc0 dyndbg: combine flags & mask into a struct, simplify with it
> CC: vincent.whitchurch@axis.com
> Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
> 
> --
> .drop @stable, no exposed bug.
> ---
>  lib/dynamic_debug.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
> index dd7f56af9aed..a56c1286ffa4 100644
> --- a/lib/dynamic_debug.c
> +++ b/lib/dynamic_debug.c
> @@ -211,10 +211,11 @@ static int ddebug_change(const struct ddebug_query *query,
>  				continue;
>  #ifdef CONFIG_JUMP_LABEL
>  			if (dp->flags & _DPRINTK_FLAGS_PRINT) {
> -				if (!(modifiers->flags & _DPRINTK_FLAGS_PRINT))
> +				if (!(newflags & _DPRINTK_FLAGS_PRINT))
>  					static_branch_disable(&dp->key.dd_key_true);
> -			} else if (modifiers->flags & _DPRINTK_FLAGS_PRINT)
> +			} else if (newflags & _DPRINTK_FLAGS_PRINT) {
>  				static_branch_enable(&dp->key.dd_key_true);
> +			}
>  #endif
>  			dp->flags = newflags;
>  			v4pr_info("changed %s:%d [%s]%s =%s\n",



Hi Jim,

If iiuc this is currently a bug but could be if we add a second 'print' bit
such as for printing to the tracing logs. That said I agree that using 'newflags'
here makes the code more straightforward/readable. So this one is fine with
me.

Acked-by: Jason Baron <jbaron@akamai.com>

Thanks,

-Jason

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

* Re: [PATCH 2/5] dyndbg: add class_id field and query support
  2022-03-11  4:47   ` Jim Cromie
  (?)
  (?)
@ 2022-03-11 19:06     ` Jason Baron
  -1 siblings, 0 replies; 49+ messages in thread
From: Jason Baron @ 2022-03-11 19:06 UTC (permalink / raw)
  To: Jim Cromie, gregkh, linux-kernel
  Cc: daniel.vetter, seanpaul, robdclark, linux, joe, dri-devel,
	amd-gfx, intel-gvt-dev, intel-gfx



On 3/10/22 23:47, Jim Cromie wrote:
> DRM defines/uses 10 enum drm_debug_category's to create exclusive
> classes of debug messages.  To support this directly in dynamic-debug,
> add the following:
> 
> - struct _ddebug.class_id:4 - 4 bits is enough
> - define _DPRINTK_SITE_UNCLASSED 15 - see below
> 
> and the query support:
> - struct _ddebug_query.class_id
> - ddebug_parse_query	- looks for "class" keyword, then calls..
> - parse_class		- accepts uint: 0-15, sets query.class_id and marker
> - vpr_info_dq		- displays new field
> - ddebug_proc_show	- append column with "cls:%d" if !UNCLASSED
> 
> With the patch, one can enable current/unclassed callsites by:
> 
>   #> echo drm class 15 +p > /proc/dynamic_debug/control
> 

To me, this is hard to read, what the heck is '15'? I have to go look it
up in the control file and it's not descriptive. I think that using
classes/categories makes sense but I'm wondering if it can be a bit more
user friendly? Perhaps, we can pass an array of strings that is indexed
by the class id to each pr_debug() site that wants to use class. So
something like:

enum levels {
	LOW,
	MEDIUM,
	HIGH
};

static const char * const level_to_strings[] = {
        [LOW] = "low",
        [MEDIUM] = "medium",
        [HIGH] = "high",
};

And then you'd have a wrapper macros in your driver:

#define module_foo_pr_debug_class(level, fmt, args...)
	pr_debug_class(level, level_to_strings, fmt, args);

Such that call sites look like:

module_foo_pr_debug_class(LOW, fmt, args...);

Such that you're not always passing the strings array around. Now, this
does mean another pointer for struct _ddebug and most wouldn't have it.
Maybe we could just add another linker section for these so as to save
space.

> parse_class() accepts 0 .. _DPRINTK_SITE_UNCLASSED, which allows the
>> control interface to explicitly manipulate unclassed callsites.
> 
> After parsing keywords, ddebug_parse_query() sets .class_id=15, iff it
> wasnt explicitly set.  This allows future classed/categorized
> callsites to be untouched by legacy (class unaware) queries.
> 
> DEFINE_DYNAMIC_DEBUG_METADATA gets _CLS(cls,) suffix and arg, and
> initializes the new .class_id=cls field.  The old name gets the default.
> 
> Then, these _CLS(cls,...) modifications are repeated up through the
> stack of *dynamic_func_call* macros that use the METADATA initializer,
> so as to actually supply the category into it.
> 
> NOTES:
> 
> _DPRINTK_SITE_UNCLASSED: this symbol is used to initialize all
> existing/unclassed pr-debug callsites.  Normally, the default would be
> zero, but DRM_UT_CORE "uses" that value, in the sense that 0 is
> exposed as a bit position in drm.debug.  Using 15 allows identity
> mapping from category to class, avoiding fiddly offsets.
> 
> Default .class_id = 15 means that ``echo +p > control`` no longer
> toggles ALL the callsites, only the unclassed ones.  This was only
> useful for static-branch toggle load testing anyway.
> 

I think that # echo +p > control should continue to work as is, why
should the introduction of classes change that ?

> RFC:
> 
> The new _CLS macro flavor gets a warning from DRM/dri-devel's CI,
> but not from checkpatch (on this subject).
> 
> a8f6c71f283e dyndbg: add class_id field and query support
> -:141: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'id' - possible side-effects?
> +#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {	\
> +	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);	\
> +	if (DYNAMIC_DEBUG_BRANCH(id))				\
> +		func(&id, ##__VA_ARGS__);			\
>  } while (0)
> 
> I couldn't fix it with a ``typeof(id) _id = id`` construct.  I haven't
> seen the warning myself, on the _CLS extended macro, nor the original.
> 
> CC: Rasmus Villemoes <linux@rasmusvillemoes.dk>
> Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
> ---
>  .../admin-guide/dynamic-debug-howto.rst       |  7 +++
>  include/linux/dynamic_debug.h                 | 54 ++++++++++++++-----
>  lib/dynamic_debug.c                           | 48 ++++++++++++++---
>  3 files changed, 88 insertions(+), 21 deletions(-)
> 
> diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst b/Documentation/admin-guide/dynamic-debug-howto.rst
> index a89cfa083155..8ef8d7dcd140 100644
> --- a/Documentation/admin-guide/dynamic-debug-howto.rst
> +++ b/Documentation/admin-guide/dynamic-debug-howto.rst
> @@ -35,6 +35,7 @@ Dynamic debug has even more useful features:
>     - line number (including ranges of line numbers)
>     - module name
>     - format string
> +   - class number:0-15
>  
>   * Provides a debugfs control file: ``<debugfs>/dynamic_debug/control``
>     which can be read to display the complete list of known debug
> @@ -143,6 +144,7 @@ against.  Possible keywords are:::
>  		 'module' string |
>  		 'format' string |
>  		 'line' line-range
> +		 'class' integer:[0-15]
>  
>    line-range ::= lineno |
>  		 '-'lineno |
> @@ -217,6 +219,11 @@ line
>  	line -1605          // the 1605 lines from line 1 to line 1605
>  	line 1600-          // all lines from line 1600 to the end of the file
>  
> +class
> +    This expects a single integer in range: 0-15.
> +    15 is used/reserved for existing/unclassed callsites,
> +    and is defaulted in unless specified to >control
> +
>  The flags specification comprises a change operation followed
>  by one or more flag characters.  The change operation is one
>  of the characters::
> diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
> index dce631e678dd..d4b48f3cc6e8 100644
> --- a/include/linux/dynamic_debug.h
> +++ b/include/linux/dynamic_debug.h
> @@ -6,6 +6,8 @@
>  #include <linux/jump_label.h>
>  #endif
>  
> +#include <linux/build_bug.h>
> +
>  /*
>   * An instance of this structure is created in a special
>   * ELF section at every dynamic debug callsite.  At runtime,
> @@ -21,6 +23,9 @@ struct _ddebug {
>  	const char *filename;
>  	const char *format;
>  	unsigned int lineno:18;
> +#define CLS_BITS 4
> +	unsigned int class_id:CLS_BITS;
> +#define _DPRINTK_SITE_UNCLASSED		((1 << CLS_BITS) - 1)
>  	/*
>  	 * The flags field controls the behaviour at the callsite.
>  	 * The bits here are changed dynamically when the user
> @@ -87,7 +92,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
>  			 const struct ib_device *ibdev,
>  			 const char *fmt, ...);
>  
> -#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)		\
> +#define DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, cls, fmt)	\
>  	static struct _ddebug  __aligned(8)			\
>  	__section("__dyndbg") name = {				\
>  		.modname = KBUILD_MODNAME,			\
> @@ -96,8 +101,14 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
>  		.format = (fmt),				\
>  		.lineno = __LINE__,				\
>  		.flags = _DPRINTK_FLAGS_DEFAULT,		\
> +		.class_id = cls,				\
>  		_DPRINTK_KEY_INIT				\
> -	}
> +	};							\
> +	BUILD_BUG_ON_MSG(cls > _DPRINTK_SITE_UNCLASSED,		\
> +			 "classid value overflow")
> +
> +#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)		\
> +	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, _DPRINTK_SITE_UNCLASSED, fmt)
>  
>  #ifdef CONFIG_JUMP_LABEL
>  
> @@ -128,18 +139,26 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
>  
>  #endif /* CONFIG_JUMP_LABEL */
>  
> -#define __dynamic_func_call(id, fmt, func, ...) do {	\
> -	DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt);		\
> -	if (DYNAMIC_DEBUG_BRANCH(id))			\
> -		func(&id, ##__VA_ARGS__);		\
> +#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {	\
> +	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);	\
> +	if (DYNAMIC_DEBUG_BRANCH(id))				\
> +		func(&id, ##__VA_ARGS__);			\
>  } while (0)
>  
> -#define __dynamic_func_call_no_desc(id, fmt, func, ...) do {	\
> -	DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt);			\
> -	if (DYNAMIC_DEBUG_BRANCH(id))				\
> -		func(__VA_ARGS__);				\
> +#define __dynamic_func_call_no_desc_cls(id, cls, fmt, func, ...) do {	\
> +	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);		\
> +	if (DYNAMIC_DEBUG_BRANCH(id))					\
> +		func(__VA_ARGS__);					\
>  } while (0)
>  
> +#define __dynamic_func_call(id, fmt, func, ...)				\
> +	__dynamic_func_call_cls(id, _DPRINTK_SITE_UNCLASSED,		\
> +				fmt, func, ##__VA_ARGS__)
> +
> +#define __dynamic_func_call_no_desc(id, fmt, func, ...)			\
> +	__dynamic_func_call_no_desc_cls(id, _DPRINTK_SITE_UNCLASSED,	\
> +					fmt, func, ##__VA_ARGS__)
> +
>  /*
>   * "Factory macro" for generating a call to func, guarded by a
>   * DYNAMIC_DEBUG_BRANCH. The dynamic debug descriptor will be
> @@ -148,15 +167,24 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
>   * the varargs. Note that fmt is repeated in invocations of this
>   * macro.
>   */
> +#define _dynamic_func_call_cls(cls, fmt, func, ...)			\
> +	__dynamic_func_call_cls(__UNIQUE_ID(ddebug), cls, fmt, func, ##__VA_ARGS__)
>  #define _dynamic_func_call(fmt, func, ...)				\
> -	__dynamic_func_call(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
> +	_dynamic_func_call_cls(_DPRINTK_SITE_UNCLASSED, fmt, func, ##__VA_ARGS__)
> +
>  /*
>   * A variant that does the same, except that the descriptor is not
>   * passed as the first argument to the function; it is only called
>   * with precisely the macro's varargs.
>   */
> -#define _dynamic_func_call_no_desc(fmt, func, ...)	\
> -	__dynamic_func_call_no_desc(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
> +#define _dynamic_func_call_no_desc_cls(fmt, cat, func, ...)		\
> +	__dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug), cat,	\
> +					fmt, func, ##__VA_ARGS__)
> +
> +#define _dynamic_func_call_no_desc(fmt, func, ...)			\
> +	__dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug),		\
> +					_DPRINTK_SITE_UNCLASSED,	\
> +					fmt, func, ##__VA_ARGS__)
>  
>  #define dynamic_pr_debug(fmt, ...)				\
>  	_dynamic_func_call(fmt,	__dynamic_pr_debug,		\
> diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
> index a56c1286ffa4..ee2129becacc 100644
> --- a/lib/dynamic_debug.c
> +++ b/lib/dynamic_debug.c
> @@ -55,6 +55,8 @@ struct ddebug_query {
>  	const char *function;
>  	const char *format;
>  	unsigned int first_lineno, last_lineno;
> +	unsigned int class_id;
> +	unsigned int class_marked:1;
>  };
>  
>  struct ddebug_iter {
> @@ -134,13 +136,13 @@ static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
>  			fmtlen--;
>  	}
>  
> -	v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u\n",
> -		 msg,
> -		 query->function ?: "",
> -		 query->filename ?: "",
> -		 query->module ?: "",
> -		 fmtlen, query->format ?: "",
> -		 query->first_lineno, query->last_lineno);
> +	v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u class=%u\n",
> +		  msg,
> +		  query->function ?: "",
> +		  query->filename ?: "",
> +		  query->module ?: "",
> +		  fmtlen, query->format ?: "",
> +		  query->first_lineno, query->last_lineno, query->class_id);
>  }
>  
>  /*
> @@ -170,6 +172,10 @@ static int ddebug_change(const struct ddebug_query *query,
>  		for (i = 0; i < dt->num_ddebugs; i++) {
>  			struct _ddebug *dp = &dt->ddebugs[i];
>  
> +			/* match against the class_id, either given or default */
> +			if (query->class_id != dp->class_id)
> +				continue;
> +

Could that instead be:

if (query->class_id != _DPRINTK_SITE_UNCLASSED && query->class_id != dp->class_id)
	continue;

That way by default we fall through and enable callsites for queries that do not have
the 'class' keyboard specified. I think I would also disallow setting
_DPRINTK_SITE_UNCLASSED explicitly since it would now mean 'class *', and what if
we expand class_id size to greater than 15 at some point?

>  			/* match against the source filename */
>  			if (query->filename &&
>  			    !match_wildcard(query->filename, dp->filename) &&
> @@ -308,6 +314,21 @@ static inline int parse_lineno(const char *str, unsigned int *val)
>  	return 0;
>  }
>  
> +static inline int parse_class(struct ddebug_query *query, const char *str)
> +{
> +	int rc;
> +	unsigned int val;
> +
> +	rc = kstrtouint(str, 10, &val);
> +	if (rc < 0 || val > _DPRINTK_SITE_UNCLASSED) {
> +		pr_err("expecting class:[0-%d], not %s\n", _DPRINTK_SITE_UNCLASSED, str);
> +		return -EINVAL;
> +	}
> +	query->class_id = val;
> +	query->class_marked = 1;
> +	return 0;
> +}
> +
>  static int parse_linerange(struct ddebug_query *query, const char *first)
>  {
>  	char *last = strchr(first, '-');
> @@ -421,6 +442,9 @@ static int ddebug_parse_query(char *words[], int nwords,
>  		} else if (!strcmp(keyword, "line")) {
>  			if (parse_linerange(query, arg))
>  				return -EINVAL;
> +		} else if (!strcmp(keyword, "class")) {
> +			if (parse_class(query, arg))
> +				return -EINVAL;
>  		} else {
>  			pr_err("unknown keyword \"%s\"\n", keyword);
>  			return -EINVAL;
> @@ -428,6 +452,10 @@ static int ddebug_parse_query(char *words[], int nwords,
>  		if (rc)
>  			return rc;
>  	}
> +	/* post-validate the query, set default */
> +	if (!query->class_marked)
> +		query->class_id = _DPRINTK_SITE_UNCLASSED;
> +
>  	vpr_info_dq(query, "parsed");
>  	return 0;
>  }
> @@ -900,7 +928,11 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
>  		   iter->table->mod_name, dp->function,
>  		   ddebug_describe_flags(dp->flags, &flags));
>  	seq_escape(m, dp->format, "\t\r\n\"");
> -	seq_puts(m, "\"\n");
> +	seq_puts(m, "\"");
> +
> +	if (dp->class_id != _DPRINTK_SITE_UNCLASSED)
> +		seq_printf(m, " cls:%u", dp->class_id);
> +	seq_puts(m, "\n");
>  
>  	return 0;
>  }

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

* Re: [PATCH 2/5] dyndbg: add class_id field and query support
@ 2022-03-11 19:06     ` Jason Baron
  0 siblings, 0 replies; 49+ messages in thread
From: Jason Baron @ 2022-03-11 19:06 UTC (permalink / raw)
  To: Jim Cromie, gregkh, linux-kernel
  Cc: daniel.vetter, intel-gfx, linux, dri-devel, seanpaul, amd-gfx,
	joe, intel-gvt-dev



On 3/10/22 23:47, Jim Cromie wrote:
> DRM defines/uses 10 enum drm_debug_category's to create exclusive
> classes of debug messages.  To support this directly in dynamic-debug,
> add the following:
> 
> - struct _ddebug.class_id:4 - 4 bits is enough
> - define _DPRINTK_SITE_UNCLASSED 15 - see below
> 
> and the query support:
> - struct _ddebug_query.class_id
> - ddebug_parse_query	- looks for "class" keyword, then calls..
> - parse_class		- accepts uint: 0-15, sets query.class_id and marker
> - vpr_info_dq		- displays new field
> - ddebug_proc_show	- append column with "cls:%d" if !UNCLASSED
> 
> With the patch, one can enable current/unclassed callsites by:
> 
>   #> echo drm class 15 +p > /proc/dynamic_debug/control
> 

To me, this is hard to read, what the heck is '15'? I have to go look it
up in the control file and it's not descriptive. I think that using
classes/categories makes sense but I'm wondering if it can be a bit more
user friendly? Perhaps, we can pass an array of strings that is indexed
by the class id to each pr_debug() site that wants to use class. So
something like:

enum levels {
	LOW,
	MEDIUM,
	HIGH
};

static const char * const level_to_strings[] = {
        [LOW] = "low",
        [MEDIUM] = "medium",
        [HIGH] = "high",
};

And then you'd have a wrapper macros in your driver:

#define module_foo_pr_debug_class(level, fmt, args...)
	pr_debug_class(level, level_to_strings, fmt, args);

Such that call sites look like:

module_foo_pr_debug_class(LOW, fmt, args...);

Such that you're not always passing the strings array around. Now, this
does mean another pointer for struct _ddebug and most wouldn't have it.
Maybe we could just add another linker section for these so as to save
space.

> parse_class() accepts 0 .. _DPRINTK_SITE_UNCLASSED, which allows the
>> control interface to explicitly manipulate unclassed callsites.
> 
> After parsing keywords, ddebug_parse_query() sets .class_id=15, iff it
> wasnt explicitly set.  This allows future classed/categorized
> callsites to be untouched by legacy (class unaware) queries.
> 
> DEFINE_DYNAMIC_DEBUG_METADATA gets _CLS(cls,) suffix and arg, and
> initializes the new .class_id=cls field.  The old name gets the default.
> 
> Then, these _CLS(cls,...) modifications are repeated up through the
> stack of *dynamic_func_call* macros that use the METADATA initializer,
> so as to actually supply the category into it.
> 
> NOTES:
> 
> _DPRINTK_SITE_UNCLASSED: this symbol is used to initialize all
> existing/unclassed pr-debug callsites.  Normally, the default would be
> zero, but DRM_UT_CORE "uses" that value, in the sense that 0 is
> exposed as a bit position in drm.debug.  Using 15 allows identity
> mapping from category to class, avoiding fiddly offsets.
> 
> Default .class_id = 15 means that ``echo +p > control`` no longer
> toggles ALL the callsites, only the unclassed ones.  This was only
> useful for static-branch toggle load testing anyway.
> 

I think that # echo +p > control should continue to work as is, why
should the introduction of classes change that ?

> RFC:
> 
> The new _CLS macro flavor gets a warning from DRM/dri-devel's CI,
> but not from checkpatch (on this subject).
> 
> a8f6c71f283e dyndbg: add class_id field and query support
> -:141: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'id' - possible side-effects?
> +#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {	\
> +	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);	\
> +	if (DYNAMIC_DEBUG_BRANCH(id))				\
> +		func(&id, ##__VA_ARGS__);			\
>  } while (0)
> 
> I couldn't fix it with a ``typeof(id) _id = id`` construct.  I haven't
> seen the warning myself, on the _CLS extended macro, nor the original.
> 
> CC: Rasmus Villemoes <linux@rasmusvillemoes.dk>
> Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
> ---
>  .../admin-guide/dynamic-debug-howto.rst       |  7 +++
>  include/linux/dynamic_debug.h                 | 54 ++++++++++++++-----
>  lib/dynamic_debug.c                           | 48 ++++++++++++++---
>  3 files changed, 88 insertions(+), 21 deletions(-)
> 
> diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst b/Documentation/admin-guide/dynamic-debug-howto.rst
> index a89cfa083155..8ef8d7dcd140 100644
> --- a/Documentation/admin-guide/dynamic-debug-howto.rst
> +++ b/Documentation/admin-guide/dynamic-debug-howto.rst
> @@ -35,6 +35,7 @@ Dynamic debug has even more useful features:
>     - line number (including ranges of line numbers)
>     - module name
>     - format string
> +   - class number:0-15
>  
>   * Provides a debugfs control file: ``<debugfs>/dynamic_debug/control``
>     which can be read to display the complete list of known debug
> @@ -143,6 +144,7 @@ against.  Possible keywords are:::
>  		 'module' string |
>  		 'format' string |
>  		 'line' line-range
> +		 'class' integer:[0-15]
>  
>    line-range ::= lineno |
>  		 '-'lineno |
> @@ -217,6 +219,11 @@ line
>  	line -1605          // the 1605 lines from line 1 to line 1605
>  	line 1600-          // all lines from line 1600 to the end of the file
>  
> +class
> +    This expects a single integer in range: 0-15.
> +    15 is used/reserved for existing/unclassed callsites,
> +    and is defaulted in unless specified to >control
> +
>  The flags specification comprises a change operation followed
>  by one or more flag characters.  The change operation is one
>  of the characters::
> diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
> index dce631e678dd..d4b48f3cc6e8 100644
> --- a/include/linux/dynamic_debug.h
> +++ b/include/linux/dynamic_debug.h
> @@ -6,6 +6,8 @@
>  #include <linux/jump_label.h>
>  #endif
>  
> +#include <linux/build_bug.h>
> +
>  /*
>   * An instance of this structure is created in a special
>   * ELF section at every dynamic debug callsite.  At runtime,
> @@ -21,6 +23,9 @@ struct _ddebug {
>  	const char *filename;
>  	const char *format;
>  	unsigned int lineno:18;
> +#define CLS_BITS 4
> +	unsigned int class_id:CLS_BITS;
> +#define _DPRINTK_SITE_UNCLASSED		((1 << CLS_BITS) - 1)
>  	/*
>  	 * The flags field controls the behaviour at the callsite.
>  	 * The bits here are changed dynamically when the user
> @@ -87,7 +92,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
>  			 const struct ib_device *ibdev,
>  			 const char *fmt, ...);
>  
> -#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)		\
> +#define DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, cls, fmt)	\
>  	static struct _ddebug  __aligned(8)			\
>  	__section("__dyndbg") name = {				\
>  		.modname = KBUILD_MODNAME,			\
> @@ -96,8 +101,14 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
>  		.format = (fmt),				\
>  		.lineno = __LINE__,				\
>  		.flags = _DPRINTK_FLAGS_DEFAULT,		\
> +		.class_id = cls,				\
>  		_DPRINTK_KEY_INIT				\
> -	}
> +	};							\
> +	BUILD_BUG_ON_MSG(cls > _DPRINTK_SITE_UNCLASSED,		\
> +			 "classid value overflow")
> +
> +#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)		\
> +	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, _DPRINTK_SITE_UNCLASSED, fmt)
>  
>  #ifdef CONFIG_JUMP_LABEL
>  
> @@ -128,18 +139,26 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
>  
>  #endif /* CONFIG_JUMP_LABEL */
>  
> -#define __dynamic_func_call(id, fmt, func, ...) do {	\
> -	DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt);		\
> -	if (DYNAMIC_DEBUG_BRANCH(id))			\
> -		func(&id, ##__VA_ARGS__);		\
> +#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {	\
> +	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);	\
> +	if (DYNAMIC_DEBUG_BRANCH(id))				\
> +		func(&id, ##__VA_ARGS__);			\
>  } while (0)
>  
> -#define __dynamic_func_call_no_desc(id, fmt, func, ...) do {	\
> -	DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt);			\
> -	if (DYNAMIC_DEBUG_BRANCH(id))				\
> -		func(__VA_ARGS__);				\
> +#define __dynamic_func_call_no_desc_cls(id, cls, fmt, func, ...) do {	\
> +	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);		\
> +	if (DYNAMIC_DEBUG_BRANCH(id))					\
> +		func(__VA_ARGS__);					\
>  } while (0)
>  
> +#define __dynamic_func_call(id, fmt, func, ...)				\
> +	__dynamic_func_call_cls(id, _DPRINTK_SITE_UNCLASSED,		\
> +				fmt, func, ##__VA_ARGS__)
> +
> +#define __dynamic_func_call_no_desc(id, fmt, func, ...)			\
> +	__dynamic_func_call_no_desc_cls(id, _DPRINTK_SITE_UNCLASSED,	\
> +					fmt, func, ##__VA_ARGS__)
> +
>  /*
>   * "Factory macro" for generating a call to func, guarded by a
>   * DYNAMIC_DEBUG_BRANCH. The dynamic debug descriptor will be
> @@ -148,15 +167,24 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
>   * the varargs. Note that fmt is repeated in invocations of this
>   * macro.
>   */
> +#define _dynamic_func_call_cls(cls, fmt, func, ...)			\
> +	__dynamic_func_call_cls(__UNIQUE_ID(ddebug), cls, fmt, func, ##__VA_ARGS__)
>  #define _dynamic_func_call(fmt, func, ...)				\
> -	__dynamic_func_call(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
> +	_dynamic_func_call_cls(_DPRINTK_SITE_UNCLASSED, fmt, func, ##__VA_ARGS__)
> +
>  /*
>   * A variant that does the same, except that the descriptor is not
>   * passed as the first argument to the function; it is only called
>   * with precisely the macro's varargs.
>   */
> -#define _dynamic_func_call_no_desc(fmt, func, ...)	\
> -	__dynamic_func_call_no_desc(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
> +#define _dynamic_func_call_no_desc_cls(fmt, cat, func, ...)		\
> +	__dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug), cat,	\
> +					fmt, func, ##__VA_ARGS__)
> +
> +#define _dynamic_func_call_no_desc(fmt, func, ...)			\
> +	__dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug),		\
> +					_DPRINTK_SITE_UNCLASSED,	\
> +					fmt, func, ##__VA_ARGS__)
>  
>  #define dynamic_pr_debug(fmt, ...)				\
>  	_dynamic_func_call(fmt,	__dynamic_pr_debug,		\
> diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
> index a56c1286ffa4..ee2129becacc 100644
> --- a/lib/dynamic_debug.c
> +++ b/lib/dynamic_debug.c
> @@ -55,6 +55,8 @@ struct ddebug_query {
>  	const char *function;
>  	const char *format;
>  	unsigned int first_lineno, last_lineno;
> +	unsigned int class_id;
> +	unsigned int class_marked:1;
>  };
>  
>  struct ddebug_iter {
> @@ -134,13 +136,13 @@ static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
>  			fmtlen--;
>  	}
>  
> -	v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u\n",
> -		 msg,
> -		 query->function ?: "",
> -		 query->filename ?: "",
> -		 query->module ?: "",
> -		 fmtlen, query->format ?: "",
> -		 query->first_lineno, query->last_lineno);
> +	v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u class=%u\n",
> +		  msg,
> +		  query->function ?: "",
> +		  query->filename ?: "",
> +		  query->module ?: "",
> +		  fmtlen, query->format ?: "",
> +		  query->first_lineno, query->last_lineno, query->class_id);
>  }
>  
>  /*
> @@ -170,6 +172,10 @@ static int ddebug_change(const struct ddebug_query *query,
>  		for (i = 0; i < dt->num_ddebugs; i++) {
>  			struct _ddebug *dp = &dt->ddebugs[i];
>  
> +			/* match against the class_id, either given or default */
> +			if (query->class_id != dp->class_id)
> +				continue;
> +

Could that instead be:

if (query->class_id != _DPRINTK_SITE_UNCLASSED && query->class_id != dp->class_id)
	continue;

That way by default we fall through and enable callsites for queries that do not have
the 'class' keyboard specified. I think I would also disallow setting
_DPRINTK_SITE_UNCLASSED explicitly since it would now mean 'class *', and what if
we expand class_id size to greater than 15 at some point?

>  			/* match against the source filename */
>  			if (query->filename &&
>  			    !match_wildcard(query->filename, dp->filename) &&
> @@ -308,6 +314,21 @@ static inline int parse_lineno(const char *str, unsigned int *val)
>  	return 0;
>  }
>  
> +static inline int parse_class(struct ddebug_query *query, const char *str)
> +{
> +	int rc;
> +	unsigned int val;
> +
> +	rc = kstrtouint(str, 10, &val);
> +	if (rc < 0 || val > _DPRINTK_SITE_UNCLASSED) {
> +		pr_err("expecting class:[0-%d], not %s\n", _DPRINTK_SITE_UNCLASSED, str);
> +		return -EINVAL;
> +	}
> +	query->class_id = val;
> +	query->class_marked = 1;
> +	return 0;
> +}
> +
>  static int parse_linerange(struct ddebug_query *query, const char *first)
>  {
>  	char *last = strchr(first, '-');
> @@ -421,6 +442,9 @@ static int ddebug_parse_query(char *words[], int nwords,
>  		} else if (!strcmp(keyword, "line")) {
>  			if (parse_linerange(query, arg))
>  				return -EINVAL;
> +		} else if (!strcmp(keyword, "class")) {
> +			if (parse_class(query, arg))
> +				return -EINVAL;
>  		} else {
>  			pr_err("unknown keyword \"%s\"\n", keyword);
>  			return -EINVAL;
> @@ -428,6 +452,10 @@ static int ddebug_parse_query(char *words[], int nwords,
>  		if (rc)
>  			return rc;
>  	}
> +	/* post-validate the query, set default */
> +	if (!query->class_marked)
> +		query->class_id = _DPRINTK_SITE_UNCLASSED;
> +
>  	vpr_info_dq(query, "parsed");
>  	return 0;
>  }
> @@ -900,7 +928,11 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
>  		   iter->table->mod_name, dp->function,
>  		   ddebug_describe_flags(dp->flags, &flags));
>  	seq_escape(m, dp->format, "\t\r\n\"");
> -	seq_puts(m, "\"\n");
> +	seq_puts(m, "\"");
> +
> +	if (dp->class_id != _DPRINTK_SITE_UNCLASSED)
> +		seq_printf(m, " cls:%u", dp->class_id);
> +	seq_puts(m, "\n");
>  
>  	return 0;
>  }

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

* Re: [PATCH 2/5] dyndbg: add class_id field and query support
@ 2022-03-11 19:06     ` Jason Baron
  0 siblings, 0 replies; 49+ messages in thread
From: Jason Baron @ 2022-03-11 19:06 UTC (permalink / raw)
  To: Jim Cromie, gregkh, linux-kernel
  Cc: daniel.vetter, intel-gfx, linux, dri-devel, robdclark, seanpaul,
	amd-gfx, joe, intel-gvt-dev



On 3/10/22 23:47, Jim Cromie wrote:
> DRM defines/uses 10 enum drm_debug_category's to create exclusive
> classes of debug messages.  To support this directly in dynamic-debug,
> add the following:
> 
> - struct _ddebug.class_id:4 - 4 bits is enough
> - define _DPRINTK_SITE_UNCLASSED 15 - see below
> 
> and the query support:
> - struct _ddebug_query.class_id
> - ddebug_parse_query	- looks for "class" keyword, then calls..
> - parse_class		- accepts uint: 0-15, sets query.class_id and marker
> - vpr_info_dq		- displays new field
> - ddebug_proc_show	- append column with "cls:%d" if !UNCLASSED
> 
> With the patch, one can enable current/unclassed callsites by:
> 
>   #> echo drm class 15 +p > /proc/dynamic_debug/control
> 

To me, this is hard to read, what the heck is '15'? I have to go look it
up in the control file and it's not descriptive. I think that using
classes/categories makes sense but I'm wondering if it can be a bit more
user friendly? Perhaps, we can pass an array of strings that is indexed
by the class id to each pr_debug() site that wants to use class. So
something like:

enum levels {
	LOW,
	MEDIUM,
	HIGH
};

static const char * const level_to_strings[] = {
        [LOW] = "low",
        [MEDIUM] = "medium",
        [HIGH] = "high",
};

And then you'd have a wrapper macros in your driver:

#define module_foo_pr_debug_class(level, fmt, args...)
	pr_debug_class(level, level_to_strings, fmt, args);

Such that call sites look like:

module_foo_pr_debug_class(LOW, fmt, args...);

Such that you're not always passing the strings array around. Now, this
does mean another pointer for struct _ddebug and most wouldn't have it.
Maybe we could just add another linker section for these so as to save
space.

> parse_class() accepts 0 .. _DPRINTK_SITE_UNCLASSED, which allows the
>> control interface to explicitly manipulate unclassed callsites.
> 
> After parsing keywords, ddebug_parse_query() sets .class_id=15, iff it
> wasnt explicitly set.  This allows future classed/categorized
> callsites to be untouched by legacy (class unaware) queries.
> 
> DEFINE_DYNAMIC_DEBUG_METADATA gets _CLS(cls,) suffix and arg, and
> initializes the new .class_id=cls field.  The old name gets the default.
> 
> Then, these _CLS(cls,...) modifications are repeated up through the
> stack of *dynamic_func_call* macros that use the METADATA initializer,
> so as to actually supply the category into it.
> 
> NOTES:
> 
> _DPRINTK_SITE_UNCLASSED: this symbol is used to initialize all
> existing/unclassed pr-debug callsites.  Normally, the default would be
> zero, but DRM_UT_CORE "uses" that value, in the sense that 0 is
> exposed as a bit position in drm.debug.  Using 15 allows identity
> mapping from category to class, avoiding fiddly offsets.
> 
> Default .class_id = 15 means that ``echo +p > control`` no longer
> toggles ALL the callsites, only the unclassed ones.  This was only
> useful for static-branch toggle load testing anyway.
> 

I think that # echo +p > control should continue to work as is, why
should the introduction of classes change that ?

> RFC:
> 
> The new _CLS macro flavor gets a warning from DRM/dri-devel's CI,
> but not from checkpatch (on this subject).
> 
> a8f6c71f283e dyndbg: add class_id field and query support
> -:141: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'id' - possible side-effects?
> +#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {	\
> +	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);	\
> +	if (DYNAMIC_DEBUG_BRANCH(id))				\
> +		func(&id, ##__VA_ARGS__);			\
>  } while (0)
> 
> I couldn't fix it with a ``typeof(id) _id = id`` construct.  I haven't
> seen the warning myself, on the _CLS extended macro, nor the original.
> 
> CC: Rasmus Villemoes <linux@rasmusvillemoes.dk>
> Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
> ---
>  .../admin-guide/dynamic-debug-howto.rst       |  7 +++
>  include/linux/dynamic_debug.h                 | 54 ++++++++++++++-----
>  lib/dynamic_debug.c                           | 48 ++++++++++++++---
>  3 files changed, 88 insertions(+), 21 deletions(-)
> 
> diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst b/Documentation/admin-guide/dynamic-debug-howto.rst
> index a89cfa083155..8ef8d7dcd140 100644
> --- a/Documentation/admin-guide/dynamic-debug-howto.rst
> +++ b/Documentation/admin-guide/dynamic-debug-howto.rst
> @@ -35,6 +35,7 @@ Dynamic debug has even more useful features:
>     - line number (including ranges of line numbers)
>     - module name
>     - format string
> +   - class number:0-15
>  
>   * Provides a debugfs control file: ``<debugfs>/dynamic_debug/control``
>     which can be read to display the complete list of known debug
> @@ -143,6 +144,7 @@ against.  Possible keywords are:::
>  		 'module' string |
>  		 'format' string |
>  		 'line' line-range
> +		 'class' integer:[0-15]
>  
>    line-range ::= lineno |
>  		 '-'lineno |
> @@ -217,6 +219,11 @@ line
>  	line -1605          // the 1605 lines from line 1 to line 1605
>  	line 1600-          // all lines from line 1600 to the end of the file
>  
> +class
> +    This expects a single integer in range: 0-15.
> +    15 is used/reserved for existing/unclassed callsites,
> +    and is defaulted in unless specified to >control
> +
>  The flags specification comprises a change operation followed
>  by one or more flag characters.  The change operation is one
>  of the characters::
> diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
> index dce631e678dd..d4b48f3cc6e8 100644
> --- a/include/linux/dynamic_debug.h
> +++ b/include/linux/dynamic_debug.h
> @@ -6,6 +6,8 @@
>  #include <linux/jump_label.h>
>  #endif
>  
> +#include <linux/build_bug.h>
> +
>  /*
>   * An instance of this structure is created in a special
>   * ELF section at every dynamic debug callsite.  At runtime,
> @@ -21,6 +23,9 @@ struct _ddebug {
>  	const char *filename;
>  	const char *format;
>  	unsigned int lineno:18;
> +#define CLS_BITS 4
> +	unsigned int class_id:CLS_BITS;
> +#define _DPRINTK_SITE_UNCLASSED		((1 << CLS_BITS) - 1)
>  	/*
>  	 * The flags field controls the behaviour at the callsite.
>  	 * The bits here are changed dynamically when the user
> @@ -87,7 +92,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
>  			 const struct ib_device *ibdev,
>  			 const char *fmt, ...);
>  
> -#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)		\
> +#define DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, cls, fmt)	\
>  	static struct _ddebug  __aligned(8)			\
>  	__section("__dyndbg") name = {				\
>  		.modname = KBUILD_MODNAME,			\
> @@ -96,8 +101,14 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
>  		.format = (fmt),				\
>  		.lineno = __LINE__,				\
>  		.flags = _DPRINTK_FLAGS_DEFAULT,		\
> +		.class_id = cls,				\
>  		_DPRINTK_KEY_INIT				\
> -	}
> +	};							\
> +	BUILD_BUG_ON_MSG(cls > _DPRINTK_SITE_UNCLASSED,		\
> +			 "classid value overflow")
> +
> +#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)		\
> +	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, _DPRINTK_SITE_UNCLASSED, fmt)
>  
>  #ifdef CONFIG_JUMP_LABEL
>  
> @@ -128,18 +139,26 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
>  
>  #endif /* CONFIG_JUMP_LABEL */
>  
> -#define __dynamic_func_call(id, fmt, func, ...) do {	\
> -	DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt);		\
> -	if (DYNAMIC_DEBUG_BRANCH(id))			\
> -		func(&id, ##__VA_ARGS__);		\
> +#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {	\
> +	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);	\
> +	if (DYNAMIC_DEBUG_BRANCH(id))				\
> +		func(&id, ##__VA_ARGS__);			\
>  } while (0)
>  
> -#define __dynamic_func_call_no_desc(id, fmt, func, ...) do {	\
> -	DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt);			\
> -	if (DYNAMIC_DEBUG_BRANCH(id))				\
> -		func(__VA_ARGS__);				\
> +#define __dynamic_func_call_no_desc_cls(id, cls, fmt, func, ...) do {	\
> +	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);		\
> +	if (DYNAMIC_DEBUG_BRANCH(id))					\
> +		func(__VA_ARGS__);					\
>  } while (0)
>  
> +#define __dynamic_func_call(id, fmt, func, ...)				\
> +	__dynamic_func_call_cls(id, _DPRINTK_SITE_UNCLASSED,		\
> +				fmt, func, ##__VA_ARGS__)
> +
> +#define __dynamic_func_call_no_desc(id, fmt, func, ...)			\
> +	__dynamic_func_call_no_desc_cls(id, _DPRINTK_SITE_UNCLASSED,	\
> +					fmt, func, ##__VA_ARGS__)
> +
>  /*
>   * "Factory macro" for generating a call to func, guarded by a
>   * DYNAMIC_DEBUG_BRANCH. The dynamic debug descriptor will be
> @@ -148,15 +167,24 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
>   * the varargs. Note that fmt is repeated in invocations of this
>   * macro.
>   */
> +#define _dynamic_func_call_cls(cls, fmt, func, ...)			\
> +	__dynamic_func_call_cls(__UNIQUE_ID(ddebug), cls, fmt, func, ##__VA_ARGS__)
>  #define _dynamic_func_call(fmt, func, ...)				\
> -	__dynamic_func_call(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
> +	_dynamic_func_call_cls(_DPRINTK_SITE_UNCLASSED, fmt, func, ##__VA_ARGS__)
> +
>  /*
>   * A variant that does the same, except that the descriptor is not
>   * passed as the first argument to the function; it is only called
>   * with precisely the macro's varargs.
>   */
> -#define _dynamic_func_call_no_desc(fmt, func, ...)	\
> -	__dynamic_func_call_no_desc(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
> +#define _dynamic_func_call_no_desc_cls(fmt, cat, func, ...)		\
> +	__dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug), cat,	\
> +					fmt, func, ##__VA_ARGS__)
> +
> +#define _dynamic_func_call_no_desc(fmt, func, ...)			\
> +	__dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug),		\
> +					_DPRINTK_SITE_UNCLASSED,	\
> +					fmt, func, ##__VA_ARGS__)
>  
>  #define dynamic_pr_debug(fmt, ...)				\
>  	_dynamic_func_call(fmt,	__dynamic_pr_debug,		\
> diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
> index a56c1286ffa4..ee2129becacc 100644
> --- a/lib/dynamic_debug.c
> +++ b/lib/dynamic_debug.c
> @@ -55,6 +55,8 @@ struct ddebug_query {
>  	const char *function;
>  	const char *format;
>  	unsigned int first_lineno, last_lineno;
> +	unsigned int class_id;
> +	unsigned int class_marked:1;
>  };
>  
>  struct ddebug_iter {
> @@ -134,13 +136,13 @@ static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
>  			fmtlen--;
>  	}
>  
> -	v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u\n",
> -		 msg,
> -		 query->function ?: "",
> -		 query->filename ?: "",
> -		 query->module ?: "",
> -		 fmtlen, query->format ?: "",
> -		 query->first_lineno, query->last_lineno);
> +	v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u class=%u\n",
> +		  msg,
> +		  query->function ?: "",
> +		  query->filename ?: "",
> +		  query->module ?: "",
> +		  fmtlen, query->format ?: "",
> +		  query->first_lineno, query->last_lineno, query->class_id);
>  }
>  
>  /*
> @@ -170,6 +172,10 @@ static int ddebug_change(const struct ddebug_query *query,
>  		for (i = 0; i < dt->num_ddebugs; i++) {
>  			struct _ddebug *dp = &dt->ddebugs[i];
>  
> +			/* match against the class_id, either given or default */
> +			if (query->class_id != dp->class_id)
> +				continue;
> +

Could that instead be:

if (query->class_id != _DPRINTK_SITE_UNCLASSED && query->class_id != dp->class_id)
	continue;

That way by default we fall through and enable callsites for queries that do not have
the 'class' keyboard specified. I think I would also disallow setting
_DPRINTK_SITE_UNCLASSED explicitly since it would now mean 'class *', and what if
we expand class_id size to greater than 15 at some point?

>  			/* match against the source filename */
>  			if (query->filename &&
>  			    !match_wildcard(query->filename, dp->filename) &&
> @@ -308,6 +314,21 @@ static inline int parse_lineno(const char *str, unsigned int *val)
>  	return 0;
>  }
>  
> +static inline int parse_class(struct ddebug_query *query, const char *str)
> +{
> +	int rc;
> +	unsigned int val;
> +
> +	rc = kstrtouint(str, 10, &val);
> +	if (rc < 0 || val > _DPRINTK_SITE_UNCLASSED) {
> +		pr_err("expecting class:[0-%d], not %s\n", _DPRINTK_SITE_UNCLASSED, str);
> +		return -EINVAL;
> +	}
> +	query->class_id = val;
> +	query->class_marked = 1;
> +	return 0;
> +}
> +
>  static int parse_linerange(struct ddebug_query *query, const char *first)
>  {
>  	char *last = strchr(first, '-');
> @@ -421,6 +442,9 @@ static int ddebug_parse_query(char *words[], int nwords,
>  		} else if (!strcmp(keyword, "line")) {
>  			if (parse_linerange(query, arg))
>  				return -EINVAL;
> +		} else if (!strcmp(keyword, "class")) {
> +			if (parse_class(query, arg))
> +				return -EINVAL;
>  		} else {
>  			pr_err("unknown keyword \"%s\"\n", keyword);
>  			return -EINVAL;
> @@ -428,6 +452,10 @@ static int ddebug_parse_query(char *words[], int nwords,
>  		if (rc)
>  			return rc;
>  	}
> +	/* post-validate the query, set default */
> +	if (!query->class_marked)
> +		query->class_id = _DPRINTK_SITE_UNCLASSED;
> +
>  	vpr_info_dq(query, "parsed");
>  	return 0;
>  }
> @@ -900,7 +928,11 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
>  		   iter->table->mod_name, dp->function,
>  		   ddebug_describe_flags(dp->flags, &flags));
>  	seq_escape(m, dp->format, "\t\r\n\"");
> -	seq_puts(m, "\"\n");
> +	seq_puts(m, "\"");
> +
> +	if (dp->class_id != _DPRINTK_SITE_UNCLASSED)
> +		seq_printf(m, " cls:%u", dp->class_id);
> +	seq_puts(m, "\n");
>  
>  	return 0;
>  }

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

* Re: [Intel-gfx] [PATCH 2/5] dyndbg: add class_id field and query support
@ 2022-03-11 19:06     ` Jason Baron
  0 siblings, 0 replies; 49+ messages in thread
From: Jason Baron @ 2022-03-11 19:06 UTC (permalink / raw)
  To: Jim Cromie, gregkh, linux-kernel
  Cc: daniel.vetter, intel-gfx, linux, dri-devel, seanpaul, amd-gfx,
	joe, intel-gvt-dev



On 3/10/22 23:47, Jim Cromie wrote:
> DRM defines/uses 10 enum drm_debug_category's to create exclusive
> classes of debug messages.  To support this directly in dynamic-debug,
> add the following:
> 
> - struct _ddebug.class_id:4 - 4 bits is enough
> - define _DPRINTK_SITE_UNCLASSED 15 - see below
> 
> and the query support:
> - struct _ddebug_query.class_id
> - ddebug_parse_query	- looks for "class" keyword, then calls..
> - parse_class		- accepts uint: 0-15, sets query.class_id and marker
> - vpr_info_dq		- displays new field
> - ddebug_proc_show	- append column with "cls:%d" if !UNCLASSED
> 
> With the patch, one can enable current/unclassed callsites by:
> 
>   #> echo drm class 15 +p > /proc/dynamic_debug/control
> 

To me, this is hard to read, what the heck is '15'? I have to go look it
up in the control file and it's not descriptive. I think that using
classes/categories makes sense but I'm wondering if it can be a bit more
user friendly? Perhaps, we can pass an array of strings that is indexed
by the class id to each pr_debug() site that wants to use class. So
something like:

enum levels {
	LOW,
	MEDIUM,
	HIGH
};

static const char * const level_to_strings[] = {
        [LOW] = "low",
        [MEDIUM] = "medium",
        [HIGH] = "high",
};

And then you'd have a wrapper macros in your driver:

#define module_foo_pr_debug_class(level, fmt, args...)
	pr_debug_class(level, level_to_strings, fmt, args);

Such that call sites look like:

module_foo_pr_debug_class(LOW, fmt, args...);

Such that you're not always passing the strings array around. Now, this
does mean another pointer for struct _ddebug and most wouldn't have it.
Maybe we could just add another linker section for these so as to save
space.

> parse_class() accepts 0 .. _DPRINTK_SITE_UNCLASSED, which allows the
>> control interface to explicitly manipulate unclassed callsites.
> 
> After parsing keywords, ddebug_parse_query() sets .class_id=15, iff it
> wasnt explicitly set.  This allows future classed/categorized
> callsites to be untouched by legacy (class unaware) queries.
> 
> DEFINE_DYNAMIC_DEBUG_METADATA gets _CLS(cls,) suffix and arg, and
> initializes the new .class_id=cls field.  The old name gets the default.
> 
> Then, these _CLS(cls,...) modifications are repeated up through the
> stack of *dynamic_func_call* macros that use the METADATA initializer,
> so as to actually supply the category into it.
> 
> NOTES:
> 
> _DPRINTK_SITE_UNCLASSED: this symbol is used to initialize all
> existing/unclassed pr-debug callsites.  Normally, the default would be
> zero, but DRM_UT_CORE "uses" that value, in the sense that 0 is
> exposed as a bit position in drm.debug.  Using 15 allows identity
> mapping from category to class, avoiding fiddly offsets.
> 
> Default .class_id = 15 means that ``echo +p > control`` no longer
> toggles ALL the callsites, only the unclassed ones.  This was only
> useful for static-branch toggle load testing anyway.
> 

I think that # echo +p > control should continue to work as is, why
should the introduction of classes change that ?

> RFC:
> 
> The new _CLS macro flavor gets a warning from DRM/dri-devel's CI,
> but not from checkpatch (on this subject).
> 
> a8f6c71f283e dyndbg: add class_id field and query support
> -:141: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'id' - possible side-effects?
> +#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {	\
> +	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);	\
> +	if (DYNAMIC_DEBUG_BRANCH(id))				\
> +		func(&id, ##__VA_ARGS__);			\
>  } while (0)
> 
> I couldn't fix it with a ``typeof(id) _id = id`` construct.  I haven't
> seen the warning myself, on the _CLS extended macro, nor the original.
> 
> CC: Rasmus Villemoes <linux@rasmusvillemoes.dk>
> Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
> ---
>  .../admin-guide/dynamic-debug-howto.rst       |  7 +++
>  include/linux/dynamic_debug.h                 | 54 ++++++++++++++-----
>  lib/dynamic_debug.c                           | 48 ++++++++++++++---
>  3 files changed, 88 insertions(+), 21 deletions(-)
> 
> diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst b/Documentation/admin-guide/dynamic-debug-howto.rst
> index a89cfa083155..8ef8d7dcd140 100644
> --- a/Documentation/admin-guide/dynamic-debug-howto.rst
> +++ b/Documentation/admin-guide/dynamic-debug-howto.rst
> @@ -35,6 +35,7 @@ Dynamic debug has even more useful features:
>     - line number (including ranges of line numbers)
>     - module name
>     - format string
> +   - class number:0-15
>  
>   * Provides a debugfs control file: ``<debugfs>/dynamic_debug/control``
>     which can be read to display the complete list of known debug
> @@ -143,6 +144,7 @@ against.  Possible keywords are:::
>  		 'module' string |
>  		 'format' string |
>  		 'line' line-range
> +		 'class' integer:[0-15]
>  
>    line-range ::= lineno |
>  		 '-'lineno |
> @@ -217,6 +219,11 @@ line
>  	line -1605          // the 1605 lines from line 1 to line 1605
>  	line 1600-          // all lines from line 1600 to the end of the file
>  
> +class
> +    This expects a single integer in range: 0-15.
> +    15 is used/reserved for existing/unclassed callsites,
> +    and is defaulted in unless specified to >control
> +
>  The flags specification comprises a change operation followed
>  by one or more flag characters.  The change operation is one
>  of the characters::
> diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
> index dce631e678dd..d4b48f3cc6e8 100644
> --- a/include/linux/dynamic_debug.h
> +++ b/include/linux/dynamic_debug.h
> @@ -6,6 +6,8 @@
>  #include <linux/jump_label.h>
>  #endif
>  
> +#include <linux/build_bug.h>
> +
>  /*
>   * An instance of this structure is created in a special
>   * ELF section at every dynamic debug callsite.  At runtime,
> @@ -21,6 +23,9 @@ struct _ddebug {
>  	const char *filename;
>  	const char *format;
>  	unsigned int lineno:18;
> +#define CLS_BITS 4
> +	unsigned int class_id:CLS_BITS;
> +#define _DPRINTK_SITE_UNCLASSED		((1 << CLS_BITS) - 1)
>  	/*
>  	 * The flags field controls the behaviour at the callsite.
>  	 * The bits here are changed dynamically when the user
> @@ -87,7 +92,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
>  			 const struct ib_device *ibdev,
>  			 const char *fmt, ...);
>  
> -#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)		\
> +#define DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, cls, fmt)	\
>  	static struct _ddebug  __aligned(8)			\
>  	__section("__dyndbg") name = {				\
>  		.modname = KBUILD_MODNAME,			\
> @@ -96,8 +101,14 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
>  		.format = (fmt),				\
>  		.lineno = __LINE__,				\
>  		.flags = _DPRINTK_FLAGS_DEFAULT,		\
> +		.class_id = cls,				\
>  		_DPRINTK_KEY_INIT				\
> -	}
> +	};							\
> +	BUILD_BUG_ON_MSG(cls > _DPRINTK_SITE_UNCLASSED,		\
> +			 "classid value overflow")
> +
> +#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)		\
> +	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, _DPRINTK_SITE_UNCLASSED, fmt)
>  
>  #ifdef CONFIG_JUMP_LABEL
>  
> @@ -128,18 +139,26 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
>  
>  #endif /* CONFIG_JUMP_LABEL */
>  
> -#define __dynamic_func_call(id, fmt, func, ...) do {	\
> -	DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt);		\
> -	if (DYNAMIC_DEBUG_BRANCH(id))			\
> -		func(&id, ##__VA_ARGS__);		\
> +#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {	\
> +	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);	\
> +	if (DYNAMIC_DEBUG_BRANCH(id))				\
> +		func(&id, ##__VA_ARGS__);			\
>  } while (0)
>  
> -#define __dynamic_func_call_no_desc(id, fmt, func, ...) do {	\
> -	DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt);			\
> -	if (DYNAMIC_DEBUG_BRANCH(id))				\
> -		func(__VA_ARGS__);				\
> +#define __dynamic_func_call_no_desc_cls(id, cls, fmt, func, ...) do {	\
> +	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);		\
> +	if (DYNAMIC_DEBUG_BRANCH(id))					\
> +		func(__VA_ARGS__);					\
>  } while (0)
>  
> +#define __dynamic_func_call(id, fmt, func, ...)				\
> +	__dynamic_func_call_cls(id, _DPRINTK_SITE_UNCLASSED,		\
> +				fmt, func, ##__VA_ARGS__)
> +
> +#define __dynamic_func_call_no_desc(id, fmt, func, ...)			\
> +	__dynamic_func_call_no_desc_cls(id, _DPRINTK_SITE_UNCLASSED,	\
> +					fmt, func, ##__VA_ARGS__)
> +
>  /*
>   * "Factory macro" for generating a call to func, guarded by a
>   * DYNAMIC_DEBUG_BRANCH. The dynamic debug descriptor will be
> @@ -148,15 +167,24 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
>   * the varargs. Note that fmt is repeated in invocations of this
>   * macro.
>   */
> +#define _dynamic_func_call_cls(cls, fmt, func, ...)			\
> +	__dynamic_func_call_cls(__UNIQUE_ID(ddebug), cls, fmt, func, ##__VA_ARGS__)
>  #define _dynamic_func_call(fmt, func, ...)				\
> -	__dynamic_func_call(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
> +	_dynamic_func_call_cls(_DPRINTK_SITE_UNCLASSED, fmt, func, ##__VA_ARGS__)
> +
>  /*
>   * A variant that does the same, except that the descriptor is not
>   * passed as the first argument to the function; it is only called
>   * with precisely the macro's varargs.
>   */
> -#define _dynamic_func_call_no_desc(fmt, func, ...)	\
> -	__dynamic_func_call_no_desc(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
> +#define _dynamic_func_call_no_desc_cls(fmt, cat, func, ...)		\
> +	__dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug), cat,	\
> +					fmt, func, ##__VA_ARGS__)
> +
> +#define _dynamic_func_call_no_desc(fmt, func, ...)			\
> +	__dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug),		\
> +					_DPRINTK_SITE_UNCLASSED,	\
> +					fmt, func, ##__VA_ARGS__)
>  
>  #define dynamic_pr_debug(fmt, ...)				\
>  	_dynamic_func_call(fmt,	__dynamic_pr_debug,		\
> diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
> index a56c1286ffa4..ee2129becacc 100644
> --- a/lib/dynamic_debug.c
> +++ b/lib/dynamic_debug.c
> @@ -55,6 +55,8 @@ struct ddebug_query {
>  	const char *function;
>  	const char *format;
>  	unsigned int first_lineno, last_lineno;
> +	unsigned int class_id;
> +	unsigned int class_marked:1;
>  };
>  
>  struct ddebug_iter {
> @@ -134,13 +136,13 @@ static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
>  			fmtlen--;
>  	}
>  
> -	v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u\n",
> -		 msg,
> -		 query->function ?: "",
> -		 query->filename ?: "",
> -		 query->module ?: "",
> -		 fmtlen, query->format ?: "",
> -		 query->first_lineno, query->last_lineno);
> +	v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u class=%u\n",
> +		  msg,
> +		  query->function ?: "",
> +		  query->filename ?: "",
> +		  query->module ?: "",
> +		  fmtlen, query->format ?: "",
> +		  query->first_lineno, query->last_lineno, query->class_id);
>  }
>  
>  /*
> @@ -170,6 +172,10 @@ static int ddebug_change(const struct ddebug_query *query,
>  		for (i = 0; i < dt->num_ddebugs; i++) {
>  			struct _ddebug *dp = &dt->ddebugs[i];
>  
> +			/* match against the class_id, either given or default */
> +			if (query->class_id != dp->class_id)
> +				continue;
> +

Could that instead be:

if (query->class_id != _DPRINTK_SITE_UNCLASSED && query->class_id != dp->class_id)
	continue;

That way by default we fall through and enable callsites for queries that do not have
the 'class' keyboard specified. I think I would also disallow setting
_DPRINTK_SITE_UNCLASSED explicitly since it would now mean 'class *', and what if
we expand class_id size to greater than 15 at some point?

>  			/* match against the source filename */
>  			if (query->filename &&
>  			    !match_wildcard(query->filename, dp->filename) &&
> @@ -308,6 +314,21 @@ static inline int parse_lineno(const char *str, unsigned int *val)
>  	return 0;
>  }
>  
> +static inline int parse_class(struct ddebug_query *query, const char *str)
> +{
> +	int rc;
> +	unsigned int val;
> +
> +	rc = kstrtouint(str, 10, &val);
> +	if (rc < 0 || val > _DPRINTK_SITE_UNCLASSED) {
> +		pr_err("expecting class:[0-%d], not %s\n", _DPRINTK_SITE_UNCLASSED, str);
> +		return -EINVAL;
> +	}
> +	query->class_id = val;
> +	query->class_marked = 1;
> +	return 0;
> +}
> +
>  static int parse_linerange(struct ddebug_query *query, const char *first)
>  {
>  	char *last = strchr(first, '-');
> @@ -421,6 +442,9 @@ static int ddebug_parse_query(char *words[], int nwords,
>  		} else if (!strcmp(keyword, "line")) {
>  			if (parse_linerange(query, arg))
>  				return -EINVAL;
> +		} else if (!strcmp(keyword, "class")) {
> +			if (parse_class(query, arg))
> +				return -EINVAL;
>  		} else {
>  			pr_err("unknown keyword \"%s\"\n", keyword);
>  			return -EINVAL;
> @@ -428,6 +452,10 @@ static int ddebug_parse_query(char *words[], int nwords,
>  		if (rc)
>  			return rc;
>  	}
> +	/* post-validate the query, set default */
> +	if (!query->class_marked)
> +		query->class_id = _DPRINTK_SITE_UNCLASSED;
> +
>  	vpr_info_dq(query, "parsed");
>  	return 0;
>  }
> @@ -900,7 +928,11 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
>  		   iter->table->mod_name, dp->function,
>  		   ddebug_describe_flags(dp->flags, &flags));
>  	seq_escape(m, dp->format, "\t\r\n\"");
> -	seq_puts(m, "\"\n");
> +	seq_puts(m, "\"");
> +
> +	if (dp->class_id != _DPRINTK_SITE_UNCLASSED)
> +		seq_printf(m, " cls:%u", dp->class_id);
> +	seq_puts(m, "\n");
>  
>  	return 0;
>  }

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

* Re: [PATCH 2/5] dyndbg: add class_id field and query support
  2022-03-11 19:06     ` Jason Baron
  (?)
  (?)
@ 2022-03-12  1:06       ` jim.cromie
  -1 siblings, 0 replies; 49+ messages in thread
From: jim.cromie @ 2022-03-12  1:06 UTC (permalink / raw)
  To: Jason Baron
  Cc: Greg KH, LKML, Daniel Vetter, Sean Paul, robdclark,
	Rasmus Villemoes, Joe Perches, dri-devel, amd-gfx mailing list,
	intel-gvt-dev, Intel Graphics Development

On Fri, Mar 11, 2022 at 12:06 PM Jason Baron <jbaron@akamai.com> wrote:
>
>
>
> On 3/10/22 23:47, Jim Cromie wrote:
> > DRM defines/uses 10 enum drm_debug_category's to create exclusive
> > classes of debug messages.  To support this directly in dynamic-debug,
> > add the following:
> >
> > - struct _ddebug.class_id:4 - 4 bits is enough
> > - define _DPRINTK_SITE_UNCLASSED 15 - see below
> >
> > and the query support:
> > - struct _ddebug_query.class_id
> > - ddebug_parse_query  - looks for "class" keyword, then calls..
> > - parse_class         - accepts uint: 0-15, sets query.class_id and marker
> > - vpr_info_dq         - displays new field
> > - ddebug_proc_show    - append column with "cls:%d" if !UNCLASSED
> >
> > With the patch, one can enable current/unclassed callsites by:
> >
> >   #> echo drm class 15 +p > /proc/dynamic_debug/control
> >
>
> To me, this is hard to read, what the heck is '15'? I have to go look it
> up in the control file and it's not descriptive. I think that using
> classes/categories makes sense but I'm wondering if it can be a bit more
> user friendly? Perhaps, we can pass an array of strings that is indexed
> by the class id to each pr_debug() site that wants to use class. So
> something like:
>

Im not at all averse to nice names, but as something added on.

1st, the interface to make friendlier is DRM's

echo 0x04 > /sys/module/drm/parameters/debug   # which category ?

parm:           debug:Enable debug output, where each bit enables a
debug category.
Bit 0 (0x01)  will enable CORE messages (drm core code)
Bit 1 (0x02)  will enable DRIVER messages (drm controller code)
Bit 2 (0x04)  will enable KMS messages (modesetting code)

echo DRM_UT_DRIVER,DRM_UT_KMS > /sys/module/drm/parameters/debug   #
now its pretty clear

If that works, its cuz DEFINE_DYNAMIC_DEBUG_CLASSBITS()
plucks class symbols out of its __VA_ARGS__, and #stringifes them.
So that macro could then build the 1-per-module static constant string array
and (only) the callbacks would be able to use it.

from there, it shouldnt be hard to ref that from the module's ddebug_table,
so parse_query could validate class args against the module given (or
fail if none given)

Speaking strictly, theres a gap:
   echo module * class DRM_UT_KMS +p > control
is nonsense for * other than drm + drivers,
but its fair/safe to just disallow wildcards on modname for this purpose.

it does however imply that module foo must exist for FOO_CAT_1 to be usable.
thats not currently the case:
bash-5.1# echo module foo +p > /proc/dynamic_debug/control
[   15.403749] dyndbg: read 14 bytes from userspace
[   15.405413] dyndbg: query 0: "module foo +p" mod:*
[   15.406486] dyndbg: split into words: "module" "foo" "+p"
[   15.407070] dyndbg: op='+'
[   15.407388] dyndbg: flags=0x1
[   15.407809] dyndbg: *flagsp=0x1 *maskp=0xffffffff
[   15.408300] dyndbg: parsed: func="" file="" module="foo" format=""
lineno=0-0 class=15
[   15.409151] dyndbg: no matches for query
[   15.409591] dyndbg: no-match: func="" file="" module="foo"
format="" lineno=0-0 class=15
[   15.410524] dyndbg: processed 1 queries, with 0 matches, 0 errs
bash-5.1#

ISTM we can keep that "0 errs" response for that case, but still reject this:

   echo module foo class FOO_NOT_HERE +p > /proc/dynamic_debug/control


> enum levels {
>         LOW,
>         MEDIUM,
>         HIGH
> };

I want to steer clear of "level" anything,
since 2>1 implies non independence of the categories



>
> static const char * const level_to_strings[] = {
>         [LOW] = "low",
>         [MEDIUM] = "medium",
>         [HIGH] = "high",
> };
>
> And then you'd have a wrapper macros in your driver:
>
> #define module_foo_pr_debug_class(level, fmt, args...)
>         pr_debug_class(level, level_to_strings, fmt, args);
>
> Such that call sites look like:
>
> module_foo_pr_debug_class(LOW, fmt, args...);
>

That macro, minus the "module_foo_" prefix,
could go into dynamic_debug.h

I didnt do that, for 2 reasons:

DRM didnt need it - it had an enum var,
and a set of macros to encapsulate the categories.

-  the "prototype" looks like this might be ok:
    define LOW "low"
    pr_debug_class(LOW, "mumble about something %p %p\n", foo, bar)
ok thats a stretch, but...

Basically, I didnt want to deal with creating a new interface. KIS

> Such that you're not always passing the strings array around. Now, this
> does mean another pointer for struct _ddebug and most wouldn't have it.
> Maybe we could just add another linker section for these so as to save
> space.

From a space consideration, adding DRM users means adding
thousands of callsites ~2k for i915, ~4k for amdgpu
Also increasing per/callsite memory seems counterproductive.

see DEFINE_DYNAMIC_DEBUG_CLASSBITS for the way forward.

> > parse_class() accepts 0 .. _DPRINTK_SITE_UNCLASSED, which allows the
> >> control interface to explicitly manipulate unclassed callsites.
> >
> > After parsing keywords, ddebug_parse_query() sets .class_id=15, iff it
> > wasnt explicitly set.  This allows future classed/categorized
> > callsites to be untouched by legacy (class unaware) queries.
> >
> > DEFINE_DYNAMIC_DEBUG_METADATA gets _CLS(cls,) suffix and arg, and
> > initializes the new .class_id=cls field.  The old name gets the default.
> >
> > Then, these _CLS(cls,...) modifications are repeated up through the
> > stack of *dynamic_func_call* macros that use the METADATA initializer,
> > so as to actually supply the category into it.
> >
> > NOTES:
> >
> > _DPRINTK_SITE_UNCLASSED: this symbol is used to initialize all
> > existing/unclassed pr-debug callsites.  Normally, the default would be
> > zero, but DRM_UT_CORE "uses" that value, in the sense that 0 is
> > exposed as a bit position in drm.debug.  Using 15 allows identity
> > mapping from category to class, avoiding fiddly offsets.
> >
> > Default .class_id = 15 means that ``echo +p > control`` no longer
> > toggles ALL the callsites, only the unclassed ones.  This was only
> > useful for static-branch toggle load testing anyway.
> >
>
> I think that # echo +p > control should continue to work as is, why
> should the introduction of classes change that ?

1st, its a good way to flood your syslog, forex if theres a serial driver built.
And this might get dramatically worse if DRM_VBLANK got lumped in.

but basically, it still affects the same universe of callsites
as before DRM popped/s into existence (which could double the callsites)

ISTM   ``echo "+p;-p" >control``
is primarily useful for work-load generation.
whether 1 cycle is 4k or 8k toggles is unimportant.



>
> > RFC:
> >
> > The new _CLS macro flavor gets a warning from DRM/dri-devel's CI,
> > but not from checkpatch (on this subject).
> >
> > a8f6c71f283e dyndbg: add class_id field and query support
> > -:141: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'id' - possible side-effects?
> > +#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {        \
> > +     DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);        \
> > +     if (DYNAMIC_DEBUG_BRANCH(id))                           \
> > +             func(&id, ##__VA_ARGS__);                       \
> >  } while (0)
> >
> > I couldn't fix it with a ``typeof(id) _id = id`` construct.  I haven't
> > seen the warning myself, on the _CLS extended macro, nor the original.
> >
> > CC: Rasmus Villemoes <linux@rasmusvillemoes.dk>
> > Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
> > ---
> >  .../admin-guide/dynamic-debug-howto.rst       |  7 +++
> >  include/linux/dynamic_debug.h                 | 54 ++++++++++++++-----
> >  lib/dynamic_debug.c                           | 48 ++++++++++++++---
> >  3 files changed, 88 insertions(+), 21 deletions(-)
> >
> > diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst b/Documentation/admin-guide/dynamic-debug-howto.rst
> > index a89cfa083155..8ef8d7dcd140 100644
> > --- a/Documentation/admin-guide/dynamic-debug-howto.rst
> > +++ b/Documentation/admin-guide/dynamic-debug-howto.rst
> > @@ -35,6 +35,7 @@ Dynamic debug has even more useful features:
> >     - line number (including ranges of line numbers)
> >     - module name
> >     - format string
> > +   - class number:0-15
> >
> >   * Provides a debugfs control file: ``<debugfs>/dynamic_debug/control``
> >     which can be read to display the complete list of known debug
> > @@ -143,6 +144,7 @@ against.  Possible keywords are:::
> >                'module' string |
> >                'format' string |
> >                'line' line-range
> > +              'class' integer:[0-15]
> >
> >    line-range ::= lineno |
> >                '-'lineno |
> > @@ -217,6 +219,11 @@ line
> >       line -1605          // the 1605 lines from line 1 to line 1605
> >       line 1600-          // all lines from line 1600 to the end of the file
> >
> > +class
> > +    This expects a single integer in range: 0-15.
> > +    15 is used/reserved for existing/unclassed callsites,
> > +    and is defaulted in unless specified to >control
> > +
> >  The flags specification comprises a change operation followed
> >  by one or more flag characters.  The change operation is one
> >  of the characters::
> > diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
> > index dce631e678dd..d4b48f3cc6e8 100644
> > --- a/include/linux/dynamic_debug.h
> > +++ b/include/linux/dynamic_debug.h
> > @@ -6,6 +6,8 @@
> >  #include <linux/jump_label.h>
> >  #endif
> >
> > +#include <linux/build_bug.h>
> > +
> >  /*
> >   * An instance of this structure is created in a special
> >   * ELF section at every dynamic debug callsite.  At runtime,
> > @@ -21,6 +23,9 @@ struct _ddebug {
> >       const char *filename;
> >       const char *format;
> >       unsigned int lineno:18;
> > +#define CLS_BITS 4
> > +     unsigned int class_id:CLS_BITS;
> > +#define _DPRINTK_SITE_UNCLASSED              ((1 << CLS_BITS) - 1)
> >       /*
> >        * The flags field controls the behaviour at the callsite.
> >        * The bits here are changed dynamically when the user
> > @@ -87,7 +92,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
> >                        const struct ib_device *ibdev,
> >                        const char *fmt, ...);
> >
> > -#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)             \
> > +#define DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, cls, fmt)    \
> >       static struct _ddebug  __aligned(8)                     \
> >       __section("__dyndbg") name = {                          \
> >               .modname = KBUILD_MODNAME,                      \
> > @@ -96,8 +101,14 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
> >               .format = (fmt),                                \
> >               .lineno = __LINE__,                             \
> >               .flags = _DPRINTK_FLAGS_DEFAULT,                \
> > +             .class_id = cls,                                \
> >               _DPRINTK_KEY_INIT                               \
> > -     }
> > +     };                                                      \
> > +     BUILD_BUG_ON_MSG(cls > _DPRINTK_SITE_UNCLASSED,         \
> > +                      "classid value overflow")
> > +
> > +#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)             \
> > +     DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, _DPRINTK_SITE_UNCLASSED, fmt)
> >
> >  #ifdef CONFIG_JUMP_LABEL
> >
> > @@ -128,18 +139,26 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
> >
> >  #endif /* CONFIG_JUMP_LABEL */
> >
> > -#define __dynamic_func_call(id, fmt, func, ...) do { \
> > -     DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt);         \
> > -     if (DYNAMIC_DEBUG_BRANCH(id))                   \
> > -             func(&id, ##__VA_ARGS__);               \
> > +#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {        \
> > +     DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);        \
> > +     if (DYNAMIC_DEBUG_BRANCH(id))                           \
> > +             func(&id, ##__VA_ARGS__);                       \
> >  } while (0)
> >
> > -#define __dynamic_func_call_no_desc(id, fmt, func, ...) do { \
> > -     DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt);                 \
> > -     if (DYNAMIC_DEBUG_BRANCH(id))                           \
> > -             func(__VA_ARGS__);                              \
> > +#define __dynamic_func_call_no_desc_cls(id, cls, fmt, func, ...) do {        \
> > +     DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);                \
> > +     if (DYNAMIC_DEBUG_BRANCH(id))                                   \
> > +             func(__VA_ARGS__);                                      \
> >  } while (0)
> >
> > +#define __dynamic_func_call(id, fmt, func, ...)                              \
> > +     __dynamic_func_call_cls(id, _DPRINTK_SITE_UNCLASSED,            \
> > +                             fmt, func, ##__VA_ARGS__)
> > +
> > +#define __dynamic_func_call_no_desc(id, fmt, func, ...)                      \
> > +     __dynamic_func_call_no_desc_cls(id, _DPRINTK_SITE_UNCLASSED,    \
> > +                                     fmt, func, ##__VA_ARGS__)
> > +
> >  /*
> >   * "Factory macro" for generating a call to func, guarded by a
> >   * DYNAMIC_DEBUG_BRANCH. The dynamic debug descriptor will be
> > @@ -148,15 +167,24 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
> >   * the varargs. Note that fmt is repeated in invocations of this
> >   * macro.
> >   */
> > +#define _dynamic_func_call_cls(cls, fmt, func, ...)                  \
> > +     __dynamic_func_call_cls(__UNIQUE_ID(ddebug), cls, fmt, func, ##__VA_ARGS__)
> >  #define _dynamic_func_call(fmt, func, ...)                           \
> > -     __dynamic_func_call(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
> > +     _dynamic_func_call_cls(_DPRINTK_SITE_UNCLASSED, fmt, func, ##__VA_ARGS__)
> > +
> >  /*
> >   * A variant that does the same, except that the descriptor is not
> >   * passed as the first argument to the function; it is only called
> >   * with precisely the macro's varargs.
> >   */
> > -#define _dynamic_func_call_no_desc(fmt, func, ...)   \
> > -     __dynamic_func_call_no_desc(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
> > +#define _dynamic_func_call_no_desc_cls(fmt, cat, func, ...)          \
> > +     __dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug), cat,       \
> > +                                     fmt, func, ##__VA_ARGS__)
> > +
> > +#define _dynamic_func_call_no_desc(fmt, func, ...)                   \
> > +     __dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug),            \
> > +                                     _DPRINTK_SITE_UNCLASSED,        \
> > +                                     fmt, func, ##__VA_ARGS__)
> >
> >  #define dynamic_pr_debug(fmt, ...)                           \
> >       _dynamic_func_call(fmt, __dynamic_pr_debug,             \
> > diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
> > index a56c1286ffa4..ee2129becacc 100644
> > --- a/lib/dynamic_debug.c
> > +++ b/lib/dynamic_debug.c
> > @@ -55,6 +55,8 @@ struct ddebug_query {
> >       const char *function;
> >       const char *format;
> >       unsigned int first_lineno, last_lineno;
> > +     unsigned int class_id;
> > +     unsigned int class_marked:1;
> >  };
> >
> >

> >  /*
> > @@ -170,6 +172,10 @@ static int ddebug_change(const struct ddebug_query *query,
> >               for (i = 0; i < dt->num_ddebugs; i++) {
> >                       struct _ddebug *dp = &dt->ddebugs[i];
> >
> > +                     /* match against the class_id, either given or default */
> > +                     if (query->class_id != dp->class_id)
> > +                             continue;
> > +
>
> Could that instead be:
>
> if (query->class_id != _DPRINTK_SITE_UNCLASSED && query->class_id != dp->class_id)
>         continue;
>

I think that is the effect currently.

query construction adds in the default if the term wasnt specified.

> That way by default we fall through and enable callsites for queries that do not have
> the 'class' keyboard specified.

thats what I was avoiding - I suppose its a matter of perspective

all existing callsites are unclassified. - ie 15
to preserve the universe affected by old queries,
adding 15 by default comports with this.
then when class !=15 callsites are added,
they are immune from effects by existing queries.

classed queries are the alternate universe.
and need "class N" in >control to get there.
Id expect DRM would like the isolation,
at least against inadvertent changes.

that said,   ``echo +p >control`` can only affect 1 universe at a time.
ISTM this is fine,
the only thing lost is 1/2 the workload for
   while true do echo "+p ; -p" >control; done

> I think I would also disallow setting
> _DPRINTK_SITE_UNCLASSED explicitly since it would now mean 'class *', and what if
> we expand class_id size to greater than 15 at some point?

it doesnt mean class *, it means class OTHER than 0-14

earlier version of parse_class disallowed 15 explicitly,
I changed it to simplify testing.

re-adding that constraint could be argued,
but if class 15 is the default when unspecified,
its hard to explain why "class 15" could draw an errror.

we'd just increase bit-field size, class_id:5
and bump 15 to 31.
is there an appropriate *_MAX macro to use,
to add the right implications / connotations ?
theres something vaguely overflowy / rollover-y here.
What choice words would convey it succinctly ?

>
> >                       /* match against the source filename */
> >                       if (query->filename &&
> >                           !match_wildcard(query->filename, dp->filename) &&
> > @@ -308,6 +314,21 @@ static inline int parse_lineno(const char *str, unsigned int *val)
> >       return 0;
> >  }
> >
> > +static inline int parse_class(struct ddebug_query *query, const char *str)
> > +{
> > +     int rc;
> > +     unsigned int val;
> > +
> > +     rc = kstrtouint(str, 10, &val);
> > +     if (rc < 0 || val > _DPRINTK_SITE_UNCLASSED) {
> > +             pr_err("expecting class:[0-%d], not %s\n", _DPRINTK_SITE_UNCLASSED, str);
> > +             return -EINVAL;
> > +     }
> > +     query->class_id = val;
> > +     query->class_marked = 1;
> > +     return 0;
> > +}
> > +
> >  static int parse_linerange(struct ddebug_query *query, const char *first)
> >  {
> >       char *last = strchr(first, '-');
> > @@ -421,6 +442,9 @@ static int ddebug_parse_query(char *words[], int nwords,
> >               } else if (!strcmp(keyword, "line")) {
> >                       if (parse_linerange(query, arg))
> >                               return -EINVAL;
> > +             } else if (!strcmp(keyword, "class")) {
> > +                     if (parse_class(query, arg))
> > +                             return -EINVAL;
> >               } else {
> >                       pr_err("unknown keyword \"%s\"\n", keyword);
> >                       return -EINVAL;
> > @@ -428,6 +452,10 @@ static int ddebug_parse_query(char *words[], int nwords,
> >               if (rc)
> >                       return rc;
> >       }
> > +     /* post-validate the query, set default */
> > +     if (!query->class_marked)
> > +             query->class_id = _DPRINTK_SITE_UNCLASSED;
> > +
> >       vpr_info_dq(query, "parsed");
> >       return 0;
> >  }
> > @@ -900,7 +928,11 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
> >                  iter->table->mod_name, dp->function,
> >                  ddebug_describe_flags(dp->flags, &flags));
> >       seq_escape(m, dp->format, "\t\r\n\"");
> > -     seq_puts(m, "\"\n");
> > +     seq_puts(m, "\"");
> > +
> > +     if (dp->class_id != _DPRINTK_SITE_UNCLASSED)
> > +             seq_printf(m, " cls:%u", dp->class_id);
> > +     seq_puts(m, "\n");
> >
> >       return 0;
> >  }

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

* Re: [PATCH 2/5] dyndbg: add class_id field and query support
@ 2022-03-12  1:06       ` jim.cromie
  0 siblings, 0 replies; 49+ messages in thread
From: jim.cromie @ 2022-03-12  1:06 UTC (permalink / raw)
  To: Jason Baron
  Cc: Greg KH, Intel Graphics Development, Rasmus Villemoes, LKML,
	dri-devel, Sean Paul, amd-gfx mailing list, Daniel Vetter,
	Joe Perches, intel-gvt-dev

On Fri, Mar 11, 2022 at 12:06 PM Jason Baron <jbaron@akamai.com> wrote:
>
>
>
> On 3/10/22 23:47, Jim Cromie wrote:
> > DRM defines/uses 10 enum drm_debug_category's to create exclusive
> > classes of debug messages.  To support this directly in dynamic-debug,
> > add the following:
> >
> > - struct _ddebug.class_id:4 - 4 bits is enough
> > - define _DPRINTK_SITE_UNCLASSED 15 - see below
> >
> > and the query support:
> > - struct _ddebug_query.class_id
> > - ddebug_parse_query  - looks for "class" keyword, then calls..
> > - parse_class         - accepts uint: 0-15, sets query.class_id and marker
> > - vpr_info_dq         - displays new field
> > - ddebug_proc_show    - append column with "cls:%d" if !UNCLASSED
> >
> > With the patch, one can enable current/unclassed callsites by:
> >
> >   #> echo drm class 15 +p > /proc/dynamic_debug/control
> >
>
> To me, this is hard to read, what the heck is '15'? I have to go look it
> up in the control file and it's not descriptive. I think that using
> classes/categories makes sense but I'm wondering if it can be a bit more
> user friendly? Perhaps, we can pass an array of strings that is indexed
> by the class id to each pr_debug() site that wants to use class. So
> something like:
>

Im not at all averse to nice names, but as something added on.

1st, the interface to make friendlier is DRM's

echo 0x04 > /sys/module/drm/parameters/debug   # which category ?

parm:           debug:Enable debug output, where each bit enables a
debug category.
Bit 0 (0x01)  will enable CORE messages (drm core code)
Bit 1 (0x02)  will enable DRIVER messages (drm controller code)
Bit 2 (0x04)  will enable KMS messages (modesetting code)

echo DRM_UT_DRIVER,DRM_UT_KMS > /sys/module/drm/parameters/debug   #
now its pretty clear

If that works, its cuz DEFINE_DYNAMIC_DEBUG_CLASSBITS()
plucks class symbols out of its __VA_ARGS__, and #stringifes them.
So that macro could then build the 1-per-module static constant string array
and (only) the callbacks would be able to use it.

from there, it shouldnt be hard to ref that from the module's ddebug_table,
so parse_query could validate class args against the module given (or
fail if none given)

Speaking strictly, theres a gap:
   echo module * class DRM_UT_KMS +p > control
is nonsense for * other than drm + drivers,
but its fair/safe to just disallow wildcards on modname for this purpose.

it does however imply that module foo must exist for FOO_CAT_1 to be usable.
thats not currently the case:
bash-5.1# echo module foo +p > /proc/dynamic_debug/control
[   15.403749] dyndbg: read 14 bytes from userspace
[   15.405413] dyndbg: query 0: "module foo +p" mod:*
[   15.406486] dyndbg: split into words: "module" "foo" "+p"
[   15.407070] dyndbg: op='+'
[   15.407388] dyndbg: flags=0x1
[   15.407809] dyndbg: *flagsp=0x1 *maskp=0xffffffff
[   15.408300] dyndbg: parsed: func="" file="" module="foo" format=""
lineno=0-0 class=15
[   15.409151] dyndbg: no matches for query
[   15.409591] dyndbg: no-match: func="" file="" module="foo"
format="" lineno=0-0 class=15
[   15.410524] dyndbg: processed 1 queries, with 0 matches, 0 errs
bash-5.1#

ISTM we can keep that "0 errs" response for that case, but still reject this:

   echo module foo class FOO_NOT_HERE +p > /proc/dynamic_debug/control


> enum levels {
>         LOW,
>         MEDIUM,
>         HIGH
> };

I want to steer clear of "level" anything,
since 2>1 implies non independence of the categories



>
> static const char * const level_to_strings[] = {
>         [LOW] = "low",
>         [MEDIUM] = "medium",
>         [HIGH] = "high",
> };
>
> And then you'd have a wrapper macros in your driver:
>
> #define module_foo_pr_debug_class(level, fmt, args...)
>         pr_debug_class(level, level_to_strings, fmt, args);
>
> Such that call sites look like:
>
> module_foo_pr_debug_class(LOW, fmt, args...);
>

That macro, minus the "module_foo_" prefix,
could go into dynamic_debug.h

I didnt do that, for 2 reasons:

DRM didnt need it - it had an enum var,
and a set of macros to encapsulate the categories.

-  the "prototype" looks like this might be ok:
    define LOW "low"
    pr_debug_class(LOW, "mumble about something %p %p\n", foo, bar)
ok thats a stretch, but...

Basically, I didnt want to deal with creating a new interface. KIS

> Such that you're not always passing the strings array around. Now, this
> does mean another pointer for struct _ddebug and most wouldn't have it.
> Maybe we could just add another linker section for these so as to save
> space.

From a space consideration, adding DRM users means adding
thousands of callsites ~2k for i915, ~4k for amdgpu
Also increasing per/callsite memory seems counterproductive.

see DEFINE_DYNAMIC_DEBUG_CLASSBITS for the way forward.

> > parse_class() accepts 0 .. _DPRINTK_SITE_UNCLASSED, which allows the
> >> control interface to explicitly manipulate unclassed callsites.
> >
> > After parsing keywords, ddebug_parse_query() sets .class_id=15, iff it
> > wasnt explicitly set.  This allows future classed/categorized
> > callsites to be untouched by legacy (class unaware) queries.
> >
> > DEFINE_DYNAMIC_DEBUG_METADATA gets _CLS(cls,) suffix and arg, and
> > initializes the new .class_id=cls field.  The old name gets the default.
> >
> > Then, these _CLS(cls,...) modifications are repeated up through the
> > stack of *dynamic_func_call* macros that use the METADATA initializer,
> > so as to actually supply the category into it.
> >
> > NOTES:
> >
> > _DPRINTK_SITE_UNCLASSED: this symbol is used to initialize all
> > existing/unclassed pr-debug callsites.  Normally, the default would be
> > zero, but DRM_UT_CORE "uses" that value, in the sense that 0 is
> > exposed as a bit position in drm.debug.  Using 15 allows identity
> > mapping from category to class, avoiding fiddly offsets.
> >
> > Default .class_id = 15 means that ``echo +p > control`` no longer
> > toggles ALL the callsites, only the unclassed ones.  This was only
> > useful for static-branch toggle load testing anyway.
> >
>
> I think that # echo +p > control should continue to work as is, why
> should the introduction of classes change that ?

1st, its a good way to flood your syslog, forex if theres a serial driver built.
And this might get dramatically worse if DRM_VBLANK got lumped in.

but basically, it still affects the same universe of callsites
as before DRM popped/s into existence (which could double the callsites)

ISTM   ``echo "+p;-p" >control``
is primarily useful for work-load generation.
whether 1 cycle is 4k or 8k toggles is unimportant.



>
> > RFC:
> >
> > The new _CLS macro flavor gets a warning from DRM/dri-devel's CI,
> > but not from checkpatch (on this subject).
> >
> > a8f6c71f283e dyndbg: add class_id field and query support
> > -:141: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'id' - possible side-effects?
> > +#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {        \
> > +     DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);        \
> > +     if (DYNAMIC_DEBUG_BRANCH(id))                           \
> > +             func(&id, ##__VA_ARGS__);                       \
> >  } while (0)
> >
> > I couldn't fix it with a ``typeof(id) _id = id`` construct.  I haven't
> > seen the warning myself, on the _CLS extended macro, nor the original.
> >
> > CC: Rasmus Villemoes <linux@rasmusvillemoes.dk>
> > Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
> > ---
> >  .../admin-guide/dynamic-debug-howto.rst       |  7 +++
> >  include/linux/dynamic_debug.h                 | 54 ++++++++++++++-----
> >  lib/dynamic_debug.c                           | 48 ++++++++++++++---
> >  3 files changed, 88 insertions(+), 21 deletions(-)
> >
> > diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst b/Documentation/admin-guide/dynamic-debug-howto.rst
> > index a89cfa083155..8ef8d7dcd140 100644
> > --- a/Documentation/admin-guide/dynamic-debug-howto.rst
> > +++ b/Documentation/admin-guide/dynamic-debug-howto.rst
> > @@ -35,6 +35,7 @@ Dynamic debug has even more useful features:
> >     - line number (including ranges of line numbers)
> >     - module name
> >     - format string
> > +   - class number:0-15
> >
> >   * Provides a debugfs control file: ``<debugfs>/dynamic_debug/control``
> >     which can be read to display the complete list of known debug
> > @@ -143,6 +144,7 @@ against.  Possible keywords are:::
> >                'module' string |
> >                'format' string |
> >                'line' line-range
> > +              'class' integer:[0-15]
> >
> >    line-range ::= lineno |
> >                '-'lineno |
> > @@ -217,6 +219,11 @@ line
> >       line -1605          // the 1605 lines from line 1 to line 1605
> >       line 1600-          // all lines from line 1600 to the end of the file
> >
> > +class
> > +    This expects a single integer in range: 0-15.
> > +    15 is used/reserved for existing/unclassed callsites,
> > +    and is defaulted in unless specified to >control
> > +
> >  The flags specification comprises a change operation followed
> >  by one or more flag characters.  The change operation is one
> >  of the characters::
> > diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
> > index dce631e678dd..d4b48f3cc6e8 100644
> > --- a/include/linux/dynamic_debug.h
> > +++ b/include/linux/dynamic_debug.h
> > @@ -6,6 +6,8 @@
> >  #include <linux/jump_label.h>
> >  #endif
> >
> > +#include <linux/build_bug.h>
> > +
> >  /*
> >   * An instance of this structure is created in a special
> >   * ELF section at every dynamic debug callsite.  At runtime,
> > @@ -21,6 +23,9 @@ struct _ddebug {
> >       const char *filename;
> >       const char *format;
> >       unsigned int lineno:18;
> > +#define CLS_BITS 4
> > +     unsigned int class_id:CLS_BITS;
> > +#define _DPRINTK_SITE_UNCLASSED              ((1 << CLS_BITS) - 1)
> >       /*
> >        * The flags field controls the behaviour at the callsite.
> >        * The bits here are changed dynamically when the user
> > @@ -87,7 +92,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
> >                        const struct ib_device *ibdev,
> >                        const char *fmt, ...);
> >
> > -#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)             \
> > +#define DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, cls, fmt)    \
> >       static struct _ddebug  __aligned(8)                     \
> >       __section("__dyndbg") name = {                          \
> >               .modname = KBUILD_MODNAME,                      \
> > @@ -96,8 +101,14 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
> >               .format = (fmt),                                \
> >               .lineno = __LINE__,                             \
> >               .flags = _DPRINTK_FLAGS_DEFAULT,                \
> > +             .class_id = cls,                                \
> >               _DPRINTK_KEY_INIT                               \
> > -     }
> > +     };                                                      \
> > +     BUILD_BUG_ON_MSG(cls > _DPRINTK_SITE_UNCLASSED,         \
> > +                      "classid value overflow")
> > +
> > +#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)             \
> > +     DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, _DPRINTK_SITE_UNCLASSED, fmt)
> >
> >  #ifdef CONFIG_JUMP_LABEL
> >
> > @@ -128,18 +139,26 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
> >
> >  #endif /* CONFIG_JUMP_LABEL */
> >
> > -#define __dynamic_func_call(id, fmt, func, ...) do { \
> > -     DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt);         \
> > -     if (DYNAMIC_DEBUG_BRANCH(id))                   \
> > -             func(&id, ##__VA_ARGS__);               \
> > +#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {        \
> > +     DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);        \
> > +     if (DYNAMIC_DEBUG_BRANCH(id))                           \
> > +             func(&id, ##__VA_ARGS__);                       \
> >  } while (0)
> >
> > -#define __dynamic_func_call_no_desc(id, fmt, func, ...) do { \
> > -     DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt);                 \
> > -     if (DYNAMIC_DEBUG_BRANCH(id))                           \
> > -             func(__VA_ARGS__);                              \
> > +#define __dynamic_func_call_no_desc_cls(id, cls, fmt, func, ...) do {        \
> > +     DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);                \
> > +     if (DYNAMIC_DEBUG_BRANCH(id))                                   \
> > +             func(__VA_ARGS__);                                      \
> >  } while (0)
> >
> > +#define __dynamic_func_call(id, fmt, func, ...)                              \
> > +     __dynamic_func_call_cls(id, _DPRINTK_SITE_UNCLASSED,            \
> > +                             fmt, func, ##__VA_ARGS__)
> > +
> > +#define __dynamic_func_call_no_desc(id, fmt, func, ...)                      \
> > +     __dynamic_func_call_no_desc_cls(id, _DPRINTK_SITE_UNCLASSED,    \
> > +                                     fmt, func, ##__VA_ARGS__)
> > +
> >  /*
> >   * "Factory macro" for generating a call to func, guarded by a
> >   * DYNAMIC_DEBUG_BRANCH. The dynamic debug descriptor will be
> > @@ -148,15 +167,24 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
> >   * the varargs. Note that fmt is repeated in invocations of this
> >   * macro.
> >   */
> > +#define _dynamic_func_call_cls(cls, fmt, func, ...)                  \
> > +     __dynamic_func_call_cls(__UNIQUE_ID(ddebug), cls, fmt, func, ##__VA_ARGS__)
> >  #define _dynamic_func_call(fmt, func, ...)                           \
> > -     __dynamic_func_call(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
> > +     _dynamic_func_call_cls(_DPRINTK_SITE_UNCLASSED, fmt, func, ##__VA_ARGS__)
> > +
> >  /*
> >   * A variant that does the same, except that the descriptor is not
> >   * passed as the first argument to the function; it is only called
> >   * with precisely the macro's varargs.
> >   */
> > -#define _dynamic_func_call_no_desc(fmt, func, ...)   \
> > -     __dynamic_func_call_no_desc(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
> > +#define _dynamic_func_call_no_desc_cls(fmt, cat, func, ...)          \
> > +     __dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug), cat,       \
> > +                                     fmt, func, ##__VA_ARGS__)
> > +
> > +#define _dynamic_func_call_no_desc(fmt, func, ...)                   \
> > +     __dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug),            \
> > +                                     _DPRINTK_SITE_UNCLASSED,        \
> > +                                     fmt, func, ##__VA_ARGS__)
> >
> >  #define dynamic_pr_debug(fmt, ...)                           \
> >       _dynamic_func_call(fmt, __dynamic_pr_debug,             \
> > diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
> > index a56c1286ffa4..ee2129becacc 100644
> > --- a/lib/dynamic_debug.c
> > +++ b/lib/dynamic_debug.c
> > @@ -55,6 +55,8 @@ struct ddebug_query {
> >       const char *function;
> >       const char *format;
> >       unsigned int first_lineno, last_lineno;
> > +     unsigned int class_id;
> > +     unsigned int class_marked:1;
> >  };
> >
> >

> >  /*
> > @@ -170,6 +172,10 @@ static int ddebug_change(const struct ddebug_query *query,
> >               for (i = 0; i < dt->num_ddebugs; i++) {
> >                       struct _ddebug *dp = &dt->ddebugs[i];
> >
> > +                     /* match against the class_id, either given or default */
> > +                     if (query->class_id != dp->class_id)
> > +                             continue;
> > +
>
> Could that instead be:
>
> if (query->class_id != _DPRINTK_SITE_UNCLASSED && query->class_id != dp->class_id)
>         continue;
>

I think that is the effect currently.

query construction adds in the default if the term wasnt specified.

> That way by default we fall through and enable callsites for queries that do not have
> the 'class' keyboard specified.

thats what I was avoiding - I suppose its a matter of perspective

all existing callsites are unclassified. - ie 15
to preserve the universe affected by old queries,
adding 15 by default comports with this.
then when class !=15 callsites are added,
they are immune from effects by existing queries.

classed queries are the alternate universe.
and need "class N" in >control to get there.
Id expect DRM would like the isolation,
at least against inadvertent changes.

that said,   ``echo +p >control`` can only affect 1 universe at a time.
ISTM this is fine,
the only thing lost is 1/2 the workload for
   while true do echo "+p ; -p" >control; done

> I think I would also disallow setting
> _DPRINTK_SITE_UNCLASSED explicitly since it would now mean 'class *', and what if
> we expand class_id size to greater than 15 at some point?

it doesnt mean class *, it means class OTHER than 0-14

earlier version of parse_class disallowed 15 explicitly,
I changed it to simplify testing.

re-adding that constraint could be argued,
but if class 15 is the default when unspecified,
its hard to explain why "class 15" could draw an errror.

we'd just increase bit-field size, class_id:5
and bump 15 to 31.
is there an appropriate *_MAX macro to use,
to add the right implications / connotations ?
theres something vaguely overflowy / rollover-y here.
What choice words would convey it succinctly ?

>
> >                       /* match against the source filename */
> >                       if (query->filename &&
> >                           !match_wildcard(query->filename, dp->filename) &&
> > @@ -308,6 +314,21 @@ static inline int parse_lineno(const char *str, unsigned int *val)
> >       return 0;
> >  }
> >
> > +static inline int parse_class(struct ddebug_query *query, const char *str)
> > +{
> > +     int rc;
> > +     unsigned int val;
> > +
> > +     rc = kstrtouint(str, 10, &val);
> > +     if (rc < 0 || val > _DPRINTK_SITE_UNCLASSED) {
> > +             pr_err("expecting class:[0-%d], not %s\n", _DPRINTK_SITE_UNCLASSED, str);
> > +             return -EINVAL;
> > +     }
> > +     query->class_id = val;
> > +     query->class_marked = 1;
> > +     return 0;
> > +}
> > +
> >  static int parse_linerange(struct ddebug_query *query, const char *first)
> >  {
> >       char *last = strchr(first, '-');
> > @@ -421,6 +442,9 @@ static int ddebug_parse_query(char *words[], int nwords,
> >               } else if (!strcmp(keyword, "line")) {
> >                       if (parse_linerange(query, arg))
> >                               return -EINVAL;
> > +             } else if (!strcmp(keyword, "class")) {
> > +                     if (parse_class(query, arg))
> > +                             return -EINVAL;
> >               } else {
> >                       pr_err("unknown keyword \"%s\"\n", keyword);
> >                       return -EINVAL;
> > @@ -428,6 +452,10 @@ static int ddebug_parse_query(char *words[], int nwords,
> >               if (rc)
> >                       return rc;
> >       }
> > +     /* post-validate the query, set default */
> > +     if (!query->class_marked)
> > +             query->class_id = _DPRINTK_SITE_UNCLASSED;
> > +
> >       vpr_info_dq(query, "parsed");
> >       return 0;
> >  }
> > @@ -900,7 +928,11 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
> >                  iter->table->mod_name, dp->function,
> >                  ddebug_describe_flags(dp->flags, &flags));
> >       seq_escape(m, dp->format, "\t\r\n\"");
> > -     seq_puts(m, "\"\n");
> > +     seq_puts(m, "\"");
> > +
> > +     if (dp->class_id != _DPRINTK_SITE_UNCLASSED)
> > +             seq_printf(m, " cls:%u", dp->class_id);
> > +     seq_puts(m, "\n");
> >
> >       return 0;
> >  }

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

* Re: [Intel-gfx] [PATCH 2/5] dyndbg: add class_id field and query support
@ 2022-03-12  1:06       ` jim.cromie
  0 siblings, 0 replies; 49+ messages in thread
From: jim.cromie @ 2022-03-12  1:06 UTC (permalink / raw)
  To: Jason Baron
  Cc: Greg KH, Intel Graphics Development, Rasmus Villemoes, LKML,
	dri-devel, Sean Paul, amd-gfx mailing list, Daniel Vetter,
	Joe Perches, intel-gvt-dev

On Fri, Mar 11, 2022 at 12:06 PM Jason Baron <jbaron@akamai.com> wrote:
>
>
>
> On 3/10/22 23:47, Jim Cromie wrote:
> > DRM defines/uses 10 enum drm_debug_category's to create exclusive
> > classes of debug messages.  To support this directly in dynamic-debug,
> > add the following:
> >
> > - struct _ddebug.class_id:4 - 4 bits is enough
> > - define _DPRINTK_SITE_UNCLASSED 15 - see below
> >
> > and the query support:
> > - struct _ddebug_query.class_id
> > - ddebug_parse_query  - looks for "class" keyword, then calls..
> > - parse_class         - accepts uint: 0-15, sets query.class_id and marker
> > - vpr_info_dq         - displays new field
> > - ddebug_proc_show    - append column with "cls:%d" if !UNCLASSED
> >
> > With the patch, one can enable current/unclassed callsites by:
> >
> >   #> echo drm class 15 +p > /proc/dynamic_debug/control
> >
>
> To me, this is hard to read, what the heck is '15'? I have to go look it
> up in the control file and it's not descriptive. I think that using
> classes/categories makes sense but I'm wondering if it can be a bit more
> user friendly? Perhaps, we can pass an array of strings that is indexed
> by the class id to each pr_debug() site that wants to use class. So
> something like:
>

Im not at all averse to nice names, but as something added on.

1st, the interface to make friendlier is DRM's

echo 0x04 > /sys/module/drm/parameters/debug   # which category ?

parm:           debug:Enable debug output, where each bit enables a
debug category.
Bit 0 (0x01)  will enable CORE messages (drm core code)
Bit 1 (0x02)  will enable DRIVER messages (drm controller code)
Bit 2 (0x04)  will enable KMS messages (modesetting code)

echo DRM_UT_DRIVER,DRM_UT_KMS > /sys/module/drm/parameters/debug   #
now its pretty clear

If that works, its cuz DEFINE_DYNAMIC_DEBUG_CLASSBITS()
plucks class symbols out of its __VA_ARGS__, and #stringifes them.
So that macro could then build the 1-per-module static constant string array
and (only) the callbacks would be able to use it.

from there, it shouldnt be hard to ref that from the module's ddebug_table,
so parse_query could validate class args against the module given (or
fail if none given)

Speaking strictly, theres a gap:
   echo module * class DRM_UT_KMS +p > control
is nonsense for * other than drm + drivers,
but its fair/safe to just disallow wildcards on modname for this purpose.

it does however imply that module foo must exist for FOO_CAT_1 to be usable.
thats not currently the case:
bash-5.1# echo module foo +p > /proc/dynamic_debug/control
[   15.403749] dyndbg: read 14 bytes from userspace
[   15.405413] dyndbg: query 0: "module foo +p" mod:*
[   15.406486] dyndbg: split into words: "module" "foo" "+p"
[   15.407070] dyndbg: op='+'
[   15.407388] dyndbg: flags=0x1
[   15.407809] dyndbg: *flagsp=0x1 *maskp=0xffffffff
[   15.408300] dyndbg: parsed: func="" file="" module="foo" format=""
lineno=0-0 class=15
[   15.409151] dyndbg: no matches for query
[   15.409591] dyndbg: no-match: func="" file="" module="foo"
format="" lineno=0-0 class=15
[   15.410524] dyndbg: processed 1 queries, with 0 matches, 0 errs
bash-5.1#

ISTM we can keep that "0 errs" response for that case, but still reject this:

   echo module foo class FOO_NOT_HERE +p > /proc/dynamic_debug/control


> enum levels {
>         LOW,
>         MEDIUM,
>         HIGH
> };

I want to steer clear of "level" anything,
since 2>1 implies non independence of the categories



>
> static const char * const level_to_strings[] = {
>         [LOW] = "low",
>         [MEDIUM] = "medium",
>         [HIGH] = "high",
> };
>
> And then you'd have a wrapper macros in your driver:
>
> #define module_foo_pr_debug_class(level, fmt, args...)
>         pr_debug_class(level, level_to_strings, fmt, args);
>
> Such that call sites look like:
>
> module_foo_pr_debug_class(LOW, fmt, args...);
>

That macro, minus the "module_foo_" prefix,
could go into dynamic_debug.h

I didnt do that, for 2 reasons:

DRM didnt need it - it had an enum var,
and a set of macros to encapsulate the categories.

-  the "prototype" looks like this might be ok:
    define LOW "low"
    pr_debug_class(LOW, "mumble about something %p %p\n", foo, bar)
ok thats a stretch, but...

Basically, I didnt want to deal with creating a new interface. KIS

> Such that you're not always passing the strings array around. Now, this
> does mean another pointer for struct _ddebug and most wouldn't have it.
> Maybe we could just add another linker section for these so as to save
> space.

From a space consideration, adding DRM users means adding
thousands of callsites ~2k for i915, ~4k for amdgpu
Also increasing per/callsite memory seems counterproductive.

see DEFINE_DYNAMIC_DEBUG_CLASSBITS for the way forward.

> > parse_class() accepts 0 .. _DPRINTK_SITE_UNCLASSED, which allows the
> >> control interface to explicitly manipulate unclassed callsites.
> >
> > After parsing keywords, ddebug_parse_query() sets .class_id=15, iff it
> > wasnt explicitly set.  This allows future classed/categorized
> > callsites to be untouched by legacy (class unaware) queries.
> >
> > DEFINE_DYNAMIC_DEBUG_METADATA gets _CLS(cls,) suffix and arg, and
> > initializes the new .class_id=cls field.  The old name gets the default.
> >
> > Then, these _CLS(cls,...) modifications are repeated up through the
> > stack of *dynamic_func_call* macros that use the METADATA initializer,
> > so as to actually supply the category into it.
> >
> > NOTES:
> >
> > _DPRINTK_SITE_UNCLASSED: this symbol is used to initialize all
> > existing/unclassed pr-debug callsites.  Normally, the default would be
> > zero, but DRM_UT_CORE "uses" that value, in the sense that 0 is
> > exposed as a bit position in drm.debug.  Using 15 allows identity
> > mapping from category to class, avoiding fiddly offsets.
> >
> > Default .class_id = 15 means that ``echo +p > control`` no longer
> > toggles ALL the callsites, only the unclassed ones.  This was only
> > useful for static-branch toggle load testing anyway.
> >
>
> I think that # echo +p > control should continue to work as is, why
> should the introduction of classes change that ?

1st, its a good way to flood your syslog, forex if theres a serial driver built.
And this might get dramatically worse if DRM_VBLANK got lumped in.

but basically, it still affects the same universe of callsites
as before DRM popped/s into existence (which could double the callsites)

ISTM   ``echo "+p;-p" >control``
is primarily useful for work-load generation.
whether 1 cycle is 4k or 8k toggles is unimportant.



>
> > RFC:
> >
> > The new _CLS macro flavor gets a warning from DRM/dri-devel's CI,
> > but not from checkpatch (on this subject).
> >
> > a8f6c71f283e dyndbg: add class_id field and query support
> > -:141: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'id' - possible side-effects?
> > +#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {        \
> > +     DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);        \
> > +     if (DYNAMIC_DEBUG_BRANCH(id))                           \
> > +             func(&id, ##__VA_ARGS__);                       \
> >  } while (0)
> >
> > I couldn't fix it with a ``typeof(id) _id = id`` construct.  I haven't
> > seen the warning myself, on the _CLS extended macro, nor the original.
> >
> > CC: Rasmus Villemoes <linux@rasmusvillemoes.dk>
> > Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
> > ---
> >  .../admin-guide/dynamic-debug-howto.rst       |  7 +++
> >  include/linux/dynamic_debug.h                 | 54 ++++++++++++++-----
> >  lib/dynamic_debug.c                           | 48 ++++++++++++++---
> >  3 files changed, 88 insertions(+), 21 deletions(-)
> >
> > diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst b/Documentation/admin-guide/dynamic-debug-howto.rst
> > index a89cfa083155..8ef8d7dcd140 100644
> > --- a/Documentation/admin-guide/dynamic-debug-howto.rst
> > +++ b/Documentation/admin-guide/dynamic-debug-howto.rst
> > @@ -35,6 +35,7 @@ Dynamic debug has even more useful features:
> >     - line number (including ranges of line numbers)
> >     - module name
> >     - format string
> > +   - class number:0-15
> >
> >   * Provides a debugfs control file: ``<debugfs>/dynamic_debug/control``
> >     which can be read to display the complete list of known debug
> > @@ -143,6 +144,7 @@ against.  Possible keywords are:::
> >                'module' string |
> >                'format' string |
> >                'line' line-range
> > +              'class' integer:[0-15]
> >
> >    line-range ::= lineno |
> >                '-'lineno |
> > @@ -217,6 +219,11 @@ line
> >       line -1605          // the 1605 lines from line 1 to line 1605
> >       line 1600-          // all lines from line 1600 to the end of the file
> >
> > +class
> > +    This expects a single integer in range: 0-15.
> > +    15 is used/reserved for existing/unclassed callsites,
> > +    and is defaulted in unless specified to >control
> > +
> >  The flags specification comprises a change operation followed
> >  by one or more flag characters.  The change operation is one
> >  of the characters::
> > diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
> > index dce631e678dd..d4b48f3cc6e8 100644
> > --- a/include/linux/dynamic_debug.h
> > +++ b/include/linux/dynamic_debug.h
> > @@ -6,6 +6,8 @@
> >  #include <linux/jump_label.h>
> >  #endif
> >
> > +#include <linux/build_bug.h>
> > +
> >  /*
> >   * An instance of this structure is created in a special
> >   * ELF section at every dynamic debug callsite.  At runtime,
> > @@ -21,6 +23,9 @@ struct _ddebug {
> >       const char *filename;
> >       const char *format;
> >       unsigned int lineno:18;
> > +#define CLS_BITS 4
> > +     unsigned int class_id:CLS_BITS;
> > +#define _DPRINTK_SITE_UNCLASSED              ((1 << CLS_BITS) - 1)
> >       /*
> >        * The flags field controls the behaviour at the callsite.
> >        * The bits here are changed dynamically when the user
> > @@ -87,7 +92,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
> >                        const struct ib_device *ibdev,
> >                        const char *fmt, ...);
> >
> > -#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)             \
> > +#define DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, cls, fmt)    \
> >       static struct _ddebug  __aligned(8)                     \
> >       __section("__dyndbg") name = {                          \
> >               .modname = KBUILD_MODNAME,                      \
> > @@ -96,8 +101,14 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
> >               .format = (fmt),                                \
> >               .lineno = __LINE__,                             \
> >               .flags = _DPRINTK_FLAGS_DEFAULT,                \
> > +             .class_id = cls,                                \
> >               _DPRINTK_KEY_INIT                               \
> > -     }
> > +     };                                                      \
> > +     BUILD_BUG_ON_MSG(cls > _DPRINTK_SITE_UNCLASSED,         \
> > +                      "classid value overflow")
> > +
> > +#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)             \
> > +     DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, _DPRINTK_SITE_UNCLASSED, fmt)
> >
> >  #ifdef CONFIG_JUMP_LABEL
> >
> > @@ -128,18 +139,26 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
> >
> >  #endif /* CONFIG_JUMP_LABEL */
> >
> > -#define __dynamic_func_call(id, fmt, func, ...) do { \
> > -     DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt);         \
> > -     if (DYNAMIC_DEBUG_BRANCH(id))                   \
> > -             func(&id, ##__VA_ARGS__);               \
> > +#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {        \
> > +     DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);        \
> > +     if (DYNAMIC_DEBUG_BRANCH(id))                           \
> > +             func(&id, ##__VA_ARGS__);                       \
> >  } while (0)
> >
> > -#define __dynamic_func_call_no_desc(id, fmt, func, ...) do { \
> > -     DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt);                 \
> > -     if (DYNAMIC_DEBUG_BRANCH(id))                           \
> > -             func(__VA_ARGS__);                              \
> > +#define __dynamic_func_call_no_desc_cls(id, cls, fmt, func, ...) do {        \
> > +     DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);                \
> > +     if (DYNAMIC_DEBUG_BRANCH(id))                                   \
> > +             func(__VA_ARGS__);                                      \
> >  } while (0)
> >
> > +#define __dynamic_func_call(id, fmt, func, ...)                              \
> > +     __dynamic_func_call_cls(id, _DPRINTK_SITE_UNCLASSED,            \
> > +                             fmt, func, ##__VA_ARGS__)
> > +
> > +#define __dynamic_func_call_no_desc(id, fmt, func, ...)                      \
> > +     __dynamic_func_call_no_desc_cls(id, _DPRINTK_SITE_UNCLASSED,    \
> > +                                     fmt, func, ##__VA_ARGS__)
> > +
> >  /*
> >   * "Factory macro" for generating a call to func, guarded by a
> >   * DYNAMIC_DEBUG_BRANCH. The dynamic debug descriptor will be
> > @@ -148,15 +167,24 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
> >   * the varargs. Note that fmt is repeated in invocations of this
> >   * macro.
> >   */
> > +#define _dynamic_func_call_cls(cls, fmt, func, ...)                  \
> > +     __dynamic_func_call_cls(__UNIQUE_ID(ddebug), cls, fmt, func, ##__VA_ARGS__)
> >  #define _dynamic_func_call(fmt, func, ...)                           \
> > -     __dynamic_func_call(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
> > +     _dynamic_func_call_cls(_DPRINTK_SITE_UNCLASSED, fmt, func, ##__VA_ARGS__)
> > +
> >  /*
> >   * A variant that does the same, except that the descriptor is not
> >   * passed as the first argument to the function; it is only called
> >   * with precisely the macro's varargs.
> >   */
> > -#define _dynamic_func_call_no_desc(fmt, func, ...)   \
> > -     __dynamic_func_call_no_desc(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
> > +#define _dynamic_func_call_no_desc_cls(fmt, cat, func, ...)          \
> > +     __dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug), cat,       \
> > +                                     fmt, func, ##__VA_ARGS__)
> > +
> > +#define _dynamic_func_call_no_desc(fmt, func, ...)                   \
> > +     __dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug),            \
> > +                                     _DPRINTK_SITE_UNCLASSED,        \
> > +                                     fmt, func, ##__VA_ARGS__)
> >
> >  #define dynamic_pr_debug(fmt, ...)                           \
> >       _dynamic_func_call(fmt, __dynamic_pr_debug,             \
> > diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
> > index a56c1286ffa4..ee2129becacc 100644
> > --- a/lib/dynamic_debug.c
> > +++ b/lib/dynamic_debug.c
> > @@ -55,6 +55,8 @@ struct ddebug_query {
> >       const char *function;
> >       const char *format;
> >       unsigned int first_lineno, last_lineno;
> > +     unsigned int class_id;
> > +     unsigned int class_marked:1;
> >  };
> >
> >

> >  /*
> > @@ -170,6 +172,10 @@ static int ddebug_change(const struct ddebug_query *query,
> >               for (i = 0; i < dt->num_ddebugs; i++) {
> >                       struct _ddebug *dp = &dt->ddebugs[i];
> >
> > +                     /* match against the class_id, either given or default */
> > +                     if (query->class_id != dp->class_id)
> > +                             continue;
> > +
>
> Could that instead be:
>
> if (query->class_id != _DPRINTK_SITE_UNCLASSED && query->class_id != dp->class_id)
>         continue;
>

I think that is the effect currently.

query construction adds in the default if the term wasnt specified.

> That way by default we fall through and enable callsites for queries that do not have
> the 'class' keyboard specified.

thats what I was avoiding - I suppose its a matter of perspective

all existing callsites are unclassified. - ie 15
to preserve the universe affected by old queries,
adding 15 by default comports with this.
then when class !=15 callsites are added,
they are immune from effects by existing queries.

classed queries are the alternate universe.
and need "class N" in >control to get there.
Id expect DRM would like the isolation,
at least against inadvertent changes.

that said,   ``echo +p >control`` can only affect 1 universe at a time.
ISTM this is fine,
the only thing lost is 1/2 the workload for
   while true do echo "+p ; -p" >control; done

> I think I would also disallow setting
> _DPRINTK_SITE_UNCLASSED explicitly since it would now mean 'class *', and what if
> we expand class_id size to greater than 15 at some point?

it doesnt mean class *, it means class OTHER than 0-14

earlier version of parse_class disallowed 15 explicitly,
I changed it to simplify testing.

re-adding that constraint could be argued,
but if class 15 is the default when unspecified,
its hard to explain why "class 15" could draw an errror.

we'd just increase bit-field size, class_id:5
and bump 15 to 31.
is there an appropriate *_MAX macro to use,
to add the right implications / connotations ?
theres something vaguely overflowy / rollover-y here.
What choice words would convey it succinctly ?

>
> >                       /* match against the source filename */
> >                       if (query->filename &&
> >                           !match_wildcard(query->filename, dp->filename) &&
> > @@ -308,6 +314,21 @@ static inline int parse_lineno(const char *str, unsigned int *val)
> >       return 0;
> >  }
> >
> > +static inline int parse_class(struct ddebug_query *query, const char *str)
> > +{
> > +     int rc;
> > +     unsigned int val;
> > +
> > +     rc = kstrtouint(str, 10, &val);
> > +     if (rc < 0 || val > _DPRINTK_SITE_UNCLASSED) {
> > +             pr_err("expecting class:[0-%d], not %s\n", _DPRINTK_SITE_UNCLASSED, str);
> > +             return -EINVAL;
> > +     }
> > +     query->class_id = val;
> > +     query->class_marked = 1;
> > +     return 0;
> > +}
> > +
> >  static int parse_linerange(struct ddebug_query *query, const char *first)
> >  {
> >       char *last = strchr(first, '-');
> > @@ -421,6 +442,9 @@ static int ddebug_parse_query(char *words[], int nwords,
> >               } else if (!strcmp(keyword, "line")) {
> >                       if (parse_linerange(query, arg))
> >                               return -EINVAL;
> > +             } else if (!strcmp(keyword, "class")) {
> > +                     if (parse_class(query, arg))
> > +                             return -EINVAL;
> >               } else {
> >                       pr_err("unknown keyword \"%s\"\n", keyword);
> >                       return -EINVAL;
> > @@ -428,6 +452,10 @@ static int ddebug_parse_query(char *words[], int nwords,
> >               if (rc)
> >                       return rc;
> >       }
> > +     /* post-validate the query, set default */
> > +     if (!query->class_marked)
> > +             query->class_id = _DPRINTK_SITE_UNCLASSED;
> > +
> >       vpr_info_dq(query, "parsed");
> >       return 0;
> >  }
> > @@ -900,7 +928,11 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
> >                  iter->table->mod_name, dp->function,
> >                  ddebug_describe_flags(dp->flags, &flags));
> >       seq_escape(m, dp->format, "\t\r\n\"");
> > -     seq_puts(m, "\"\n");
> > +     seq_puts(m, "\"");
> > +
> > +     if (dp->class_id != _DPRINTK_SITE_UNCLASSED)
> > +             seq_printf(m, " cls:%u", dp->class_id);
> > +     seq_puts(m, "\n");
> >
> >       return 0;
> >  }

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

* Re: [PATCH 2/5] dyndbg: add class_id field and query support
@ 2022-03-12  1:06       ` jim.cromie
  0 siblings, 0 replies; 49+ messages in thread
From: jim.cromie @ 2022-03-12  1:06 UTC (permalink / raw)
  To: Jason Baron
  Cc: Greg KH, Intel Graphics Development, Rasmus Villemoes, LKML,
	dri-devel, robdclark, Sean Paul, amd-gfx mailing list,
	Daniel Vetter, Joe Perches, intel-gvt-dev

On Fri, Mar 11, 2022 at 12:06 PM Jason Baron <jbaron@akamai.com> wrote:
>
>
>
> On 3/10/22 23:47, Jim Cromie wrote:
> > DRM defines/uses 10 enum drm_debug_category's to create exclusive
> > classes of debug messages.  To support this directly in dynamic-debug,
> > add the following:
> >
> > - struct _ddebug.class_id:4 - 4 bits is enough
> > - define _DPRINTK_SITE_UNCLASSED 15 - see below
> >
> > and the query support:
> > - struct _ddebug_query.class_id
> > - ddebug_parse_query  - looks for "class" keyword, then calls..
> > - parse_class         - accepts uint: 0-15, sets query.class_id and marker
> > - vpr_info_dq         - displays new field
> > - ddebug_proc_show    - append column with "cls:%d" if !UNCLASSED
> >
> > With the patch, one can enable current/unclassed callsites by:
> >
> >   #> echo drm class 15 +p > /proc/dynamic_debug/control
> >
>
> To me, this is hard to read, what the heck is '15'? I have to go look it
> up in the control file and it's not descriptive. I think that using
> classes/categories makes sense but I'm wondering if it can be a bit more
> user friendly? Perhaps, we can pass an array of strings that is indexed
> by the class id to each pr_debug() site that wants to use class. So
> something like:
>

Im not at all averse to nice names, but as something added on.

1st, the interface to make friendlier is DRM's

echo 0x04 > /sys/module/drm/parameters/debug   # which category ?

parm:           debug:Enable debug output, where each bit enables a
debug category.
Bit 0 (0x01)  will enable CORE messages (drm core code)
Bit 1 (0x02)  will enable DRIVER messages (drm controller code)
Bit 2 (0x04)  will enable KMS messages (modesetting code)

echo DRM_UT_DRIVER,DRM_UT_KMS > /sys/module/drm/parameters/debug   #
now its pretty clear

If that works, its cuz DEFINE_DYNAMIC_DEBUG_CLASSBITS()
plucks class symbols out of its __VA_ARGS__, and #stringifes them.
So that macro could then build the 1-per-module static constant string array
and (only) the callbacks would be able to use it.

from there, it shouldnt be hard to ref that from the module's ddebug_table,
so parse_query could validate class args against the module given (or
fail if none given)

Speaking strictly, theres a gap:
   echo module * class DRM_UT_KMS +p > control
is nonsense for * other than drm + drivers,
but its fair/safe to just disallow wildcards on modname for this purpose.

it does however imply that module foo must exist for FOO_CAT_1 to be usable.
thats not currently the case:
bash-5.1# echo module foo +p > /proc/dynamic_debug/control
[   15.403749] dyndbg: read 14 bytes from userspace
[   15.405413] dyndbg: query 0: "module foo +p" mod:*
[   15.406486] dyndbg: split into words: "module" "foo" "+p"
[   15.407070] dyndbg: op='+'
[   15.407388] dyndbg: flags=0x1
[   15.407809] dyndbg: *flagsp=0x1 *maskp=0xffffffff
[   15.408300] dyndbg: parsed: func="" file="" module="foo" format=""
lineno=0-0 class=15
[   15.409151] dyndbg: no matches for query
[   15.409591] dyndbg: no-match: func="" file="" module="foo"
format="" lineno=0-0 class=15
[   15.410524] dyndbg: processed 1 queries, with 0 matches, 0 errs
bash-5.1#

ISTM we can keep that "0 errs" response for that case, but still reject this:

   echo module foo class FOO_NOT_HERE +p > /proc/dynamic_debug/control


> enum levels {
>         LOW,
>         MEDIUM,
>         HIGH
> };

I want to steer clear of "level" anything,
since 2>1 implies non independence of the categories



>
> static const char * const level_to_strings[] = {
>         [LOW] = "low",
>         [MEDIUM] = "medium",
>         [HIGH] = "high",
> };
>
> And then you'd have a wrapper macros in your driver:
>
> #define module_foo_pr_debug_class(level, fmt, args...)
>         pr_debug_class(level, level_to_strings, fmt, args);
>
> Such that call sites look like:
>
> module_foo_pr_debug_class(LOW, fmt, args...);
>

That macro, minus the "module_foo_" prefix,
could go into dynamic_debug.h

I didnt do that, for 2 reasons:

DRM didnt need it - it had an enum var,
and a set of macros to encapsulate the categories.

-  the "prototype" looks like this might be ok:
    define LOW "low"
    pr_debug_class(LOW, "mumble about something %p %p\n", foo, bar)
ok thats a stretch, but...

Basically, I didnt want to deal with creating a new interface. KIS

> Such that you're not always passing the strings array around. Now, this
> does mean another pointer for struct _ddebug and most wouldn't have it.
> Maybe we could just add another linker section for these so as to save
> space.

From a space consideration, adding DRM users means adding
thousands of callsites ~2k for i915, ~4k for amdgpu
Also increasing per/callsite memory seems counterproductive.

see DEFINE_DYNAMIC_DEBUG_CLASSBITS for the way forward.

> > parse_class() accepts 0 .. _DPRINTK_SITE_UNCLASSED, which allows the
> >> control interface to explicitly manipulate unclassed callsites.
> >
> > After parsing keywords, ddebug_parse_query() sets .class_id=15, iff it
> > wasnt explicitly set.  This allows future classed/categorized
> > callsites to be untouched by legacy (class unaware) queries.
> >
> > DEFINE_DYNAMIC_DEBUG_METADATA gets _CLS(cls,) suffix and arg, and
> > initializes the new .class_id=cls field.  The old name gets the default.
> >
> > Then, these _CLS(cls,...) modifications are repeated up through the
> > stack of *dynamic_func_call* macros that use the METADATA initializer,
> > so as to actually supply the category into it.
> >
> > NOTES:
> >
> > _DPRINTK_SITE_UNCLASSED: this symbol is used to initialize all
> > existing/unclassed pr-debug callsites.  Normally, the default would be
> > zero, but DRM_UT_CORE "uses" that value, in the sense that 0 is
> > exposed as a bit position in drm.debug.  Using 15 allows identity
> > mapping from category to class, avoiding fiddly offsets.
> >
> > Default .class_id = 15 means that ``echo +p > control`` no longer
> > toggles ALL the callsites, only the unclassed ones.  This was only
> > useful for static-branch toggle load testing anyway.
> >
>
> I think that # echo +p > control should continue to work as is, why
> should the introduction of classes change that ?

1st, its a good way to flood your syslog, forex if theres a serial driver built.
And this might get dramatically worse if DRM_VBLANK got lumped in.

but basically, it still affects the same universe of callsites
as before DRM popped/s into existence (which could double the callsites)

ISTM   ``echo "+p;-p" >control``
is primarily useful for work-load generation.
whether 1 cycle is 4k or 8k toggles is unimportant.



>
> > RFC:
> >
> > The new _CLS macro flavor gets a warning from DRM/dri-devel's CI,
> > but not from checkpatch (on this subject).
> >
> > a8f6c71f283e dyndbg: add class_id field and query support
> > -:141: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'id' - possible side-effects?
> > +#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {        \
> > +     DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);        \
> > +     if (DYNAMIC_DEBUG_BRANCH(id))                           \
> > +             func(&id, ##__VA_ARGS__);                       \
> >  } while (0)
> >
> > I couldn't fix it with a ``typeof(id) _id = id`` construct.  I haven't
> > seen the warning myself, on the _CLS extended macro, nor the original.
> >
> > CC: Rasmus Villemoes <linux@rasmusvillemoes.dk>
> > Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
> > ---
> >  .../admin-guide/dynamic-debug-howto.rst       |  7 +++
> >  include/linux/dynamic_debug.h                 | 54 ++++++++++++++-----
> >  lib/dynamic_debug.c                           | 48 ++++++++++++++---
> >  3 files changed, 88 insertions(+), 21 deletions(-)
> >
> > diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst b/Documentation/admin-guide/dynamic-debug-howto.rst
> > index a89cfa083155..8ef8d7dcd140 100644
> > --- a/Documentation/admin-guide/dynamic-debug-howto.rst
> > +++ b/Documentation/admin-guide/dynamic-debug-howto.rst
> > @@ -35,6 +35,7 @@ Dynamic debug has even more useful features:
> >     - line number (including ranges of line numbers)
> >     - module name
> >     - format string
> > +   - class number:0-15
> >
> >   * Provides a debugfs control file: ``<debugfs>/dynamic_debug/control``
> >     which can be read to display the complete list of known debug
> > @@ -143,6 +144,7 @@ against.  Possible keywords are:::
> >                'module' string |
> >                'format' string |
> >                'line' line-range
> > +              'class' integer:[0-15]
> >
> >    line-range ::= lineno |
> >                '-'lineno |
> > @@ -217,6 +219,11 @@ line
> >       line -1605          // the 1605 lines from line 1 to line 1605
> >       line 1600-          // all lines from line 1600 to the end of the file
> >
> > +class
> > +    This expects a single integer in range: 0-15.
> > +    15 is used/reserved for existing/unclassed callsites,
> > +    and is defaulted in unless specified to >control
> > +
> >  The flags specification comprises a change operation followed
> >  by one or more flag characters.  The change operation is one
> >  of the characters::
> > diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
> > index dce631e678dd..d4b48f3cc6e8 100644
> > --- a/include/linux/dynamic_debug.h
> > +++ b/include/linux/dynamic_debug.h
> > @@ -6,6 +6,8 @@
> >  #include <linux/jump_label.h>
> >  #endif
> >
> > +#include <linux/build_bug.h>
> > +
> >  /*
> >   * An instance of this structure is created in a special
> >   * ELF section at every dynamic debug callsite.  At runtime,
> > @@ -21,6 +23,9 @@ struct _ddebug {
> >       const char *filename;
> >       const char *format;
> >       unsigned int lineno:18;
> > +#define CLS_BITS 4
> > +     unsigned int class_id:CLS_BITS;
> > +#define _DPRINTK_SITE_UNCLASSED              ((1 << CLS_BITS) - 1)
> >       /*
> >        * The flags field controls the behaviour at the callsite.
> >        * The bits here are changed dynamically when the user
> > @@ -87,7 +92,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
> >                        const struct ib_device *ibdev,
> >                        const char *fmt, ...);
> >
> > -#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)             \
> > +#define DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, cls, fmt)    \
> >       static struct _ddebug  __aligned(8)                     \
> >       __section("__dyndbg") name = {                          \
> >               .modname = KBUILD_MODNAME,                      \
> > @@ -96,8 +101,14 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
> >               .format = (fmt),                                \
> >               .lineno = __LINE__,                             \
> >               .flags = _DPRINTK_FLAGS_DEFAULT,                \
> > +             .class_id = cls,                                \
> >               _DPRINTK_KEY_INIT                               \
> > -     }
> > +     };                                                      \
> > +     BUILD_BUG_ON_MSG(cls > _DPRINTK_SITE_UNCLASSED,         \
> > +                      "classid value overflow")
> > +
> > +#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)             \
> > +     DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, _DPRINTK_SITE_UNCLASSED, fmt)
> >
> >  #ifdef CONFIG_JUMP_LABEL
> >
> > @@ -128,18 +139,26 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
> >
> >  #endif /* CONFIG_JUMP_LABEL */
> >
> > -#define __dynamic_func_call(id, fmt, func, ...) do { \
> > -     DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt);         \
> > -     if (DYNAMIC_DEBUG_BRANCH(id))                   \
> > -             func(&id, ##__VA_ARGS__);               \
> > +#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {        \
> > +     DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);        \
> > +     if (DYNAMIC_DEBUG_BRANCH(id))                           \
> > +             func(&id, ##__VA_ARGS__);                       \
> >  } while (0)
> >
> > -#define __dynamic_func_call_no_desc(id, fmt, func, ...) do { \
> > -     DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt);                 \
> > -     if (DYNAMIC_DEBUG_BRANCH(id))                           \
> > -             func(__VA_ARGS__);                              \
> > +#define __dynamic_func_call_no_desc_cls(id, cls, fmt, func, ...) do {        \
> > +     DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);                \
> > +     if (DYNAMIC_DEBUG_BRANCH(id))                                   \
> > +             func(__VA_ARGS__);                                      \
> >  } while (0)
> >
> > +#define __dynamic_func_call(id, fmt, func, ...)                              \
> > +     __dynamic_func_call_cls(id, _DPRINTK_SITE_UNCLASSED,            \
> > +                             fmt, func, ##__VA_ARGS__)
> > +
> > +#define __dynamic_func_call_no_desc(id, fmt, func, ...)                      \
> > +     __dynamic_func_call_no_desc_cls(id, _DPRINTK_SITE_UNCLASSED,    \
> > +                                     fmt, func, ##__VA_ARGS__)
> > +
> >  /*
> >   * "Factory macro" for generating a call to func, guarded by a
> >   * DYNAMIC_DEBUG_BRANCH. The dynamic debug descriptor will be
> > @@ -148,15 +167,24 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
> >   * the varargs. Note that fmt is repeated in invocations of this
> >   * macro.
> >   */
> > +#define _dynamic_func_call_cls(cls, fmt, func, ...)                  \
> > +     __dynamic_func_call_cls(__UNIQUE_ID(ddebug), cls, fmt, func, ##__VA_ARGS__)
> >  #define _dynamic_func_call(fmt, func, ...)                           \
> > -     __dynamic_func_call(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
> > +     _dynamic_func_call_cls(_DPRINTK_SITE_UNCLASSED, fmt, func, ##__VA_ARGS__)
> > +
> >  /*
> >   * A variant that does the same, except that the descriptor is not
> >   * passed as the first argument to the function; it is only called
> >   * with precisely the macro's varargs.
> >   */
> > -#define _dynamic_func_call_no_desc(fmt, func, ...)   \
> > -     __dynamic_func_call_no_desc(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
> > +#define _dynamic_func_call_no_desc_cls(fmt, cat, func, ...)          \
> > +     __dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug), cat,       \
> > +                                     fmt, func, ##__VA_ARGS__)
> > +
> > +#define _dynamic_func_call_no_desc(fmt, func, ...)                   \
> > +     __dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug),            \
> > +                                     _DPRINTK_SITE_UNCLASSED,        \
> > +                                     fmt, func, ##__VA_ARGS__)
> >
> >  #define dynamic_pr_debug(fmt, ...)                           \
> >       _dynamic_func_call(fmt, __dynamic_pr_debug,             \
> > diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
> > index a56c1286ffa4..ee2129becacc 100644
> > --- a/lib/dynamic_debug.c
> > +++ b/lib/dynamic_debug.c
> > @@ -55,6 +55,8 @@ struct ddebug_query {
> >       const char *function;
> >       const char *format;
> >       unsigned int first_lineno, last_lineno;
> > +     unsigned int class_id;
> > +     unsigned int class_marked:1;
> >  };
> >
> >

> >  /*
> > @@ -170,6 +172,10 @@ static int ddebug_change(const struct ddebug_query *query,
> >               for (i = 0; i < dt->num_ddebugs; i++) {
> >                       struct _ddebug *dp = &dt->ddebugs[i];
> >
> > +                     /* match against the class_id, either given or default */
> > +                     if (query->class_id != dp->class_id)
> > +                             continue;
> > +
>
> Could that instead be:
>
> if (query->class_id != _DPRINTK_SITE_UNCLASSED && query->class_id != dp->class_id)
>         continue;
>

I think that is the effect currently.

query construction adds in the default if the term wasnt specified.

> That way by default we fall through and enable callsites for queries that do not have
> the 'class' keyboard specified.

thats what I was avoiding - I suppose its a matter of perspective

all existing callsites are unclassified. - ie 15
to preserve the universe affected by old queries,
adding 15 by default comports with this.
then when class !=15 callsites are added,
they are immune from effects by existing queries.

classed queries are the alternate universe.
and need "class N" in >control to get there.
Id expect DRM would like the isolation,
at least against inadvertent changes.

that said,   ``echo +p >control`` can only affect 1 universe at a time.
ISTM this is fine,
the only thing lost is 1/2 the workload for
   while true do echo "+p ; -p" >control; done

> I think I would also disallow setting
> _DPRINTK_SITE_UNCLASSED explicitly since it would now mean 'class *', and what if
> we expand class_id size to greater than 15 at some point?

it doesnt mean class *, it means class OTHER than 0-14

earlier version of parse_class disallowed 15 explicitly,
I changed it to simplify testing.

re-adding that constraint could be argued,
but if class 15 is the default when unspecified,
its hard to explain why "class 15" could draw an errror.

we'd just increase bit-field size, class_id:5
and bump 15 to 31.
is there an appropriate *_MAX macro to use,
to add the right implications / connotations ?
theres something vaguely overflowy / rollover-y here.
What choice words would convey it succinctly ?

>
> >                       /* match against the source filename */
> >                       if (query->filename &&
> >                           !match_wildcard(query->filename, dp->filename) &&
> > @@ -308,6 +314,21 @@ static inline int parse_lineno(const char *str, unsigned int *val)
> >       return 0;
> >  }
> >
> > +static inline int parse_class(struct ddebug_query *query, const char *str)
> > +{
> > +     int rc;
> > +     unsigned int val;
> > +
> > +     rc = kstrtouint(str, 10, &val);
> > +     if (rc < 0 || val > _DPRINTK_SITE_UNCLASSED) {
> > +             pr_err("expecting class:[0-%d], not %s\n", _DPRINTK_SITE_UNCLASSED, str);
> > +             return -EINVAL;
> > +     }
> > +     query->class_id = val;
> > +     query->class_marked = 1;
> > +     return 0;
> > +}
> > +
> >  static int parse_linerange(struct ddebug_query *query, const char *first)
> >  {
> >       char *last = strchr(first, '-');
> > @@ -421,6 +442,9 @@ static int ddebug_parse_query(char *words[], int nwords,
> >               } else if (!strcmp(keyword, "line")) {
> >                       if (parse_linerange(query, arg))
> >                               return -EINVAL;
> > +             } else if (!strcmp(keyword, "class")) {
> > +                     if (parse_class(query, arg))
> > +                             return -EINVAL;
> >               } else {
> >                       pr_err("unknown keyword \"%s\"\n", keyword);
> >                       return -EINVAL;
> > @@ -428,6 +452,10 @@ static int ddebug_parse_query(char *words[], int nwords,
> >               if (rc)
> >                       return rc;
> >       }
> > +     /* post-validate the query, set default */
> > +     if (!query->class_marked)
> > +             query->class_id = _DPRINTK_SITE_UNCLASSED;
> > +
> >       vpr_info_dq(query, "parsed");
> >       return 0;
> >  }
> > @@ -900,7 +928,11 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
> >                  iter->table->mod_name, dp->function,
> >                  ddebug_describe_flags(dp->flags, &flags));
> >       seq_escape(m, dp->format, "\t\r\n\"");
> > -     seq_puts(m, "\"\n");
> > +     seq_puts(m, "\"");
> > +
> > +     if (dp->class_id != _DPRINTK_SITE_UNCLASSED)
> > +             seq_printf(m, " cls:%u", dp->class_id);
> > +     seq_puts(m, "\n");
> >
> >       return 0;
> >  }

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

* Re: [PATCH 2/5] dyndbg: add class_id field and query support
  2022-03-12  1:06       ` jim.cromie
  (?)
  (?)
@ 2022-03-14 21:29         ` Jason Baron
  -1 siblings, 0 replies; 49+ messages in thread
From: Jason Baron @ 2022-03-14 21:29 UTC (permalink / raw)
  To: jim.cromie
  Cc: Greg KH, LKML, Daniel Vetter, Sean Paul, robdclark,
	Rasmus Villemoes, Joe Perches, dri-devel, amd-gfx mailing list,
	intel-gvt-dev, Intel Graphics Development



On 3/11/22 20:06, jim.cromie@gmail.com wrote:
> On Fri, Mar 11, 2022 at 12:06 PM Jason Baron <jbaron@akamai.com> wrote:
>>
>>
>>
>> On 3/10/22 23:47, Jim Cromie wrote:
>>> DRM defines/uses 10 enum drm_debug_category's to create exclusive
>>> classes of debug messages.  To support this directly in dynamic-debug,
>>> add the following:
>>>
>>> - struct _ddebug.class_id:4 - 4 bits is enough
>>> - define _DPRINTK_SITE_UNCLASSED 15 - see below
>>>
>>> and the query support:
>>> - struct _ddebug_query.class_id
>>> - ddebug_parse_query  - looks for "class" keyword, then calls..
>>> - parse_class         - accepts uint: 0-15, sets query.class_id and marker
>>> - vpr_info_dq         - displays new field
>>> - ddebug_proc_show    - append column with "cls:%d" if !UNCLASSED
>>>
>>> With the patch, one can enable current/unclassed callsites by:
>>>
>>>   #> echo drm class 15 +p > /proc/dynamic_debug/control
>>>
>>
>> To me, this is hard to read, what the heck is '15'? I have to go look it
>> up in the control file and it's not descriptive. I think that using
>> classes/categories makes sense but I'm wondering if it can be a bit more
>> user friendly? Perhaps, we can pass an array of strings that is indexed
>> by the class id to each pr_debug() site that wants to use class. So
>> something like:
>>
> 
> Im not at all averse to nice names, but as something added on.
> 
> 1st, the interface to make friendlier is DRM's
> 
> echo 0x04 > /sys/module/drm/parameters/debug   # which category ?
> 
> parm:           debug:Enable debug output, where each bit enables a
> debug category.
> Bit 0 (0x01)  will enable CORE messages (drm core code)
> Bit 1 (0x02)  will enable DRIVER messages (drm controller code)
> Bit 2 (0x04)  will enable KMS messages (modesetting code)
> 
> echo DRM_UT_DRIVER,DRM_UT_KMS > /sys/module/drm/parameters/debug   #
> now its pretty clear
> 
> If that works, its cuz DEFINE_DYNAMIC_DEBUG_CLASSBITS()
> plucks class symbols out of its __VA_ARGS__, and #stringifes them.
> So that macro could then build the 1-per-module static constant string array
> and (only) the callbacks would be able to use it.
> 
> from there, it shouldnt be hard to ref that from the module's ddebug_table,
> so parse_query could validate class args against the module given (or
> fail if none given)
> 
> Speaking strictly, theres a gap:
>    echo module * class DRM_UT_KMS +p > control
> is nonsense for * other than drm + drivers,
> but its fair/safe to just disallow wildcards on modname for this purpose.
> 
> it does however imply that module foo must exist for FOO_CAT_1 to be usable.
> thats not currently the case:
> bash-5.1# echo module foo +p > /proc/dynamic_debug/control
> [   15.403749] dyndbg: read 14 bytes from userspace
> [   15.405413] dyndbg: query 0: "module foo +p" mod:*
> [   15.406486] dyndbg: split into words: "module" "foo" "+p"
> [   15.407070] dyndbg: op='+'
> [   15.407388] dyndbg: flags=0x1
> [   15.407809] dyndbg: *flagsp=0x1 *maskp=0xffffffff
> [   15.408300] dyndbg: parsed: func="" file="" module="foo" format=""
> lineno=0-0 class=15
> [   15.409151] dyndbg: no matches for query
> [   15.409591] dyndbg: no-match: func="" file="" module="foo"
> format="" lineno=0-0 class=15
> [   15.410524] dyndbg: processed 1 queries, with 0 matches, 0 errs
> bash-5.1#
> 
> ISTM we can keep that "0 errs" response for that case, but still reject this:
> 
>    echo module foo class FOO_NOT_HERE +p > /proc/dynamic_debug/control
> 
> 

Ok, yeah so I guess I'm thinking about the 'class' more as global namespace,
so that for example, it could span modules, or be specific to certain modules.
I'm also thinking of it as a 'string' which is maybe hierarchical, so that it's
clear what sub-system, or sub-sub-system it belongs to. So for DRM for example,
it could be a string like "DRM:CORE". The index num I think is still helpful for
implementation so we don't have to store a pointer size, but I don't think it's
really exposed (except perhaps in module params b/c drm is doing that already?).


>> enum levels {
>>         LOW,
>>         MEDIUM,
>>         HIGH
>> };
> 
> I want to steer clear of "level" anything,
> since 2>1 implies non independence of the categories
> 
> 

Agreed, that was a bad example on my part.

I've put together a rough patch on top of your series, to make my thinking
hopefully clear. I also think that the module param callback thing could be
implemented in this 'global' space with the 0-14 low numbers, by adding
some sort of offset into the table. IE you would add the low number +
the offset to get the 'string' to add to the ddebug query. I commented it
out in my patch below b/c I didn't implement that part.

Thoughts?


diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 664bb83778d2..b0bc1b536d54 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -8,6 +8,14 @@

 #include <linux/build_bug.h>

+enum ddebug_categories {
+        FOO_BAR = 0,
+        DRM_A = 1,
+        DRM_B = 2,
+        DRM_C = 3,
+        //_DPRINTK_SITE_DEFAULT 63 is max
+};
+
 /*
  * An instance of this structure is created in a special
  * ELF section at every dynamic debug callsite.  At runtime,
@@ -23,9 +31,9 @@ struct _ddebug {
 	const char *filename;
 	const char *format;
 	unsigned int lineno:18;
-#define CLS_BITS 4
+#define CLS_BITS 6
 	unsigned int class_id:CLS_BITS;
-#define _DPRINTK_SITE_UNCLASSED		((1 << CLS_BITS) - 1)
+#define _DPRINTK_SITE_DEFAULT		((1 << CLS_BITS) - 1)
 	/*
 	 * The flags field controls the behaviour at the callsite.
 	 * The bits here are changed dynamically when the user
@@ -101,11 +109,11 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 		.class_id = cls,				\
 		_DPRINTK_KEY_INIT				\
 	};							\
-	BUILD_BUG_ON_MSG(cls > _DPRINTK_SITE_UNCLASSED,		\
+	BUILD_BUG_ON_MSG(cls > _DPRINTK_SITE_DEFAULT,		\
 			 "classid value overflow")

 #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)		\
-	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, _DPRINTK_SITE_UNCLASSED, fmt)
+	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, _DPRINTK_SITE_DEFAULT, fmt)

 #ifdef CONFIG_JUMP_LABEL

@@ -149,11 +157,11 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 } while (0)

 #define __dynamic_func_call(id, fmt, func, ...)				\
-	__dynamic_func_call_cls(id, _DPRINTK_SITE_UNCLASSED,		\
+	__dynamic_func_call_cls(id, _DPRINTK_SITE_DEFAULT,		\
 				fmt, func, ##__VA_ARGS__)

 #define __dynamic_func_call_no_desc(id, fmt, func, ...)			\
-	__dynamic_func_call_no_desc_cls(id, _DPRINTK_SITE_UNCLASSED,	\
+	__dynamic_func_call_no_desc_cls(id, _DPRINTK_SITE_DEFAULT,	\
 					fmt, func, ##__VA_ARGS__)

 /*
@@ -167,7 +175,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 #define _dynamic_func_call_cls(cls, fmt, func, ...)			\
 	__dynamic_func_call_cls(__UNIQUE_ID(ddebug), cls, fmt, func, ##__VA_ARGS__)
 #define _dynamic_func_call(fmt, func, ...)				\
-	_dynamic_func_call_cls(_DPRINTK_SITE_UNCLASSED, fmt, func, ##__VA_ARGS__)
+	_dynamic_func_call_cls(_DPRINTK_SITE_DEFAULT, fmt, func, ##__VA_ARGS__)

 /*
  * A variant that does the same, except that the descriptor is not
@@ -180,7 +188,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,

 #define _dynamic_func_call_no_desc(fmt, func, ...)			\
 	__dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug),		\
-					_DPRINTK_SITE_UNCLASSED,	\
+					_DPRINTK_SITE_DEFAULT,	\
 					fmt, func, ##__VA_ARGS__)

 #define dynamic_pr_debug(fmt, ...)				\
@@ -284,7 +292,7 @@ struct dyndbg_classbits_param {
 	static struct dyndbg_classbits_param ddcats_##_var = {		\
 		.bits = &(_var),					\
 		.flags = _flgs,						\
-		.classes = { __VA_ARGS__, _DPRINTK_SITE_UNCLASSED }	\
+		.classes = { __VA_ARGS__, _DPRINTK_SITE_DEFAULT }	\
 	};								\
 	module_param_cb(fsname, &param_ops_dyndbg_classbits,		\
 			&ddcats_##_var, 0644)
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 11c8d0771cd2..0f390638e46c 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -39,6 +39,14 @@

 #include <rdma/ib_verbs.h>

+static const char * const cat_to_strings[] = {
+        [FOO_BAR] = "foo:bar",
+        [DRM_A] = "drm:A",
+        [DRM_B] = "drm:B",
+        [DRM_C] = "drm:C",
+	[_DPRINTK_SITE_DEFAULT] = "default",
+};
+
 extern struct _ddebug __start___dyndbg[];
 extern struct _ddebug __stop___dyndbg[];

@@ -55,8 +63,7 @@ struct ddebug_query {
 	const char *function;
 	const char *format;
 	unsigned int first_lineno, last_lineno;
-	unsigned int class_id;
-	unsigned int class_marked:1;
+	const char *class_string;
 };

 struct ddebug_iter {
@@ -136,13 +143,13 @@ static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
 			fmtlen--;
 	}

-	v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u class=%u\n",
+	v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u class=%s\n",
 		 msg,
 		 query->function ?: "",
 		 query->filename ?: "",
 		 query->module ?: "",
 		 fmtlen, query->format ?: "",
-		 query->first_lineno, query->last_lineno, query->class_id);
+		 query->first_lineno, query->last_lineno, query->class_string);
 }

 /*
@@ -158,7 +165,7 @@ static int ddebug_change(const struct ddebug_query *query,
 	struct ddebug_table *dt;
 	unsigned int newflags;
 	unsigned int nfound = 0;
-	struct flagsbuf fbuf;
+	struct flagsbuf fbuf, nbuf;

 	/* search for matching ddebugs */
 	mutex_lock(&ddebug_lock);
@@ -172,8 +179,8 @@ static int ddebug_change(const struct ddebug_query *query,
 		for (i = 0; i < dt->num_ddebugs; i++) {
 			struct _ddebug *dp = &dt->ddebugs[i];

-			/* match against the class_id, either given or default */
-			if (query->class_id != dp->class_id)
+			/* if class is not set fall through, ot check if it matches */
+			if (query->class_string && strcmp(query->class_string, cat_to_strings[dp->class_id]))
 				continue;

 			/* match against the source filename */
@@ -223,11 +230,12 @@ static int ddebug_change(const struct ddebug_query *query,
 				static_branch_enable(&dp->key.dd_key_true);
 			}
 #endif
+			v4pr_info("changed %s:%d [%s]%s %s -> %s\n",
+				  trim_prefix(dp->filename), dp->lineno,
+				  dt->mod_name, dp->function,
+				  ddebug_describe_flags(dp->flags, &fbuf),
+				  ddebug_describe_flags(newflags, &nbuf));
 			dp->flags = newflags;
-			v4pr_info("changed %s:%d [%s]%s =%s\n",
-				 trim_prefix(dp->filename), dp->lineno,
-				 dt->mod_name, dp->function,
-				 ddebug_describe_flags(dp->flags, &fbuf));
 		}
 	}
 	mutex_unlock(&ddebug_lock);
@@ -314,21 +322,6 @@ static inline int parse_lineno(const char *str, unsigned int *val)
 	return 0;
 }

-static inline int parse_class(struct ddebug_query *query, const char *str)
-{
-	int rc;
-	unsigned int val;
-
-	rc = kstrtouint(str, 10, &val);
-	if (rc < 0 || val > _DPRINTK_SITE_UNCLASSED) {
-		pr_err("expecting class:[0-%d], not %s\n", _DPRINTK_SITE_UNCLASSED, str);
-		return -EINVAL;
-	}
-	query->class_id = val;
-	query->class_marked = 1;
-	return 0;
-}
-
 static int parse_linerange(struct ddebug_query *query, const char *first)
 {
 	char *last = strchr(first, '-');
@@ -443,8 +436,7 @@ static int ddebug_parse_query(char *words[], int nwords,
 			if (parse_linerange(query, arg))
 				return -EINVAL;
 		} else if (!strcmp(keyword, "class")) {
-			if (parse_class(query, arg))
-				return -EINVAL;
+			rc = check_set(&query->class_string, arg, "class");
 		} else {
 			pr_err("unknown keyword \"%s\"\n", keyword);
 			return -EINVAL;
@@ -452,9 +444,6 @@ static int ddebug_parse_query(char *words[], int nwords,
 		if (rc)
 			return rc;
 	}
-	/* post-validate the query, set default */
-	if (!query->class_marked)
-		query->class_id = _DPRINTK_SITE_UNCLASSED;

 	vpr_info_dq(query, "parsed");
 	return 0;
@@ -616,6 +605,8 @@ int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp)
 	}
 	vpr_info("set_dyndbg_classbits: new 0x%lx old 0x%lx\n", inbits, *dcp->bits);

+
+/*
 	for (i = 0; (i < _DPRINTK_SITE_UNCLASSED &&
 		     dcp->classes[i] < _DPRINTK_SITE_UNCLASSED); i++) {

@@ -630,6 +621,7 @@ int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp)
 			  matches, dcp->classes[i]);
 		totct += matches;
 	}
+*/
 	*dcp->bits = inbits;
 	vpr_info("total matches: %d\n", totct);
 	return 0;
@@ -978,8 +970,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
 	seq_escape(m, dp->format, "\t\r\n\"");
 	seq_puts(m, "\"");

-	if (dp->class_id != _DPRINTK_SITE_UNCLASSED)
-		seq_printf(m, " cls:%u", dp->class_id);
+	seq_printf(m, " cat:%s", cat_to_strings[dp->class_id]);
 	seq_puts(m, "\n");

 	return 0;

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

* Re: [PATCH 2/5] dyndbg: add class_id field and query support
@ 2022-03-14 21:29         ` Jason Baron
  0 siblings, 0 replies; 49+ messages in thread
From: Jason Baron @ 2022-03-14 21:29 UTC (permalink / raw)
  To: jim.cromie
  Cc: Greg KH, Intel Graphics Development, Rasmus Villemoes, LKML,
	dri-devel, Sean Paul, amd-gfx mailing list, Daniel Vetter,
	Joe Perches, intel-gvt-dev



On 3/11/22 20:06, jim.cromie@gmail.com wrote:
> On Fri, Mar 11, 2022 at 12:06 PM Jason Baron <jbaron@akamai.com> wrote:
>>
>>
>>
>> On 3/10/22 23:47, Jim Cromie wrote:
>>> DRM defines/uses 10 enum drm_debug_category's to create exclusive
>>> classes of debug messages.  To support this directly in dynamic-debug,
>>> add the following:
>>>
>>> - struct _ddebug.class_id:4 - 4 bits is enough
>>> - define _DPRINTK_SITE_UNCLASSED 15 - see below
>>>
>>> and the query support:
>>> - struct _ddebug_query.class_id
>>> - ddebug_parse_query  - looks for "class" keyword, then calls..
>>> - parse_class         - accepts uint: 0-15, sets query.class_id and marker
>>> - vpr_info_dq         - displays new field
>>> - ddebug_proc_show    - append column with "cls:%d" if !UNCLASSED
>>>
>>> With the patch, one can enable current/unclassed callsites by:
>>>
>>>   #> echo drm class 15 +p > /proc/dynamic_debug/control
>>>
>>
>> To me, this is hard to read, what the heck is '15'? I have to go look it
>> up in the control file and it's not descriptive. I think that using
>> classes/categories makes sense but I'm wondering if it can be a bit more
>> user friendly? Perhaps, we can pass an array of strings that is indexed
>> by the class id to each pr_debug() site that wants to use class. So
>> something like:
>>
> 
> Im not at all averse to nice names, but as something added on.
> 
> 1st, the interface to make friendlier is DRM's
> 
> echo 0x04 > /sys/module/drm/parameters/debug   # which category ?
> 
> parm:           debug:Enable debug output, where each bit enables a
> debug category.
> Bit 0 (0x01)  will enable CORE messages (drm core code)
> Bit 1 (0x02)  will enable DRIVER messages (drm controller code)
> Bit 2 (0x04)  will enable KMS messages (modesetting code)
> 
> echo DRM_UT_DRIVER,DRM_UT_KMS > /sys/module/drm/parameters/debug   #
> now its pretty clear
> 
> If that works, its cuz DEFINE_DYNAMIC_DEBUG_CLASSBITS()
> plucks class symbols out of its __VA_ARGS__, and #stringifes them.
> So that macro could then build the 1-per-module static constant string array
> and (only) the callbacks would be able to use it.
> 
> from there, it shouldnt be hard to ref that from the module's ddebug_table,
> so parse_query could validate class args against the module given (or
> fail if none given)
> 
> Speaking strictly, theres a gap:
>    echo module * class DRM_UT_KMS +p > control
> is nonsense for * other than drm + drivers,
> but its fair/safe to just disallow wildcards on modname for this purpose.
> 
> it does however imply that module foo must exist for FOO_CAT_1 to be usable.
> thats not currently the case:
> bash-5.1# echo module foo +p > /proc/dynamic_debug/control
> [   15.403749] dyndbg: read 14 bytes from userspace
> [   15.405413] dyndbg: query 0: "module foo +p" mod:*
> [   15.406486] dyndbg: split into words: "module" "foo" "+p"
> [   15.407070] dyndbg: op='+'
> [   15.407388] dyndbg: flags=0x1
> [   15.407809] dyndbg: *flagsp=0x1 *maskp=0xffffffff
> [   15.408300] dyndbg: parsed: func="" file="" module="foo" format=""
> lineno=0-0 class=15
> [   15.409151] dyndbg: no matches for query
> [   15.409591] dyndbg: no-match: func="" file="" module="foo"
> format="" lineno=0-0 class=15
> [   15.410524] dyndbg: processed 1 queries, with 0 matches, 0 errs
> bash-5.1#
> 
> ISTM we can keep that "0 errs" response for that case, but still reject this:
> 
>    echo module foo class FOO_NOT_HERE +p > /proc/dynamic_debug/control
> 
> 

Ok, yeah so I guess I'm thinking about the 'class' more as global namespace,
so that for example, it could span modules, or be specific to certain modules.
I'm also thinking of it as a 'string' which is maybe hierarchical, so that it's
clear what sub-system, or sub-sub-system it belongs to. So for DRM for example,
it could be a string like "DRM:CORE". The index num I think is still helpful for
implementation so we don't have to store a pointer size, but I don't think it's
really exposed (except perhaps in module params b/c drm is doing that already?).


>> enum levels {
>>         LOW,
>>         MEDIUM,
>>         HIGH
>> };
> 
> I want to steer clear of "level" anything,
> since 2>1 implies non independence of the categories
> 
> 

Agreed, that was a bad example on my part.

I've put together a rough patch on top of your series, to make my thinking
hopefully clear. I also think that the module param callback thing could be
implemented in this 'global' space with the 0-14 low numbers, by adding
some sort of offset into the table. IE you would add the low number +
the offset to get the 'string' to add to the ddebug query. I commented it
out in my patch below b/c I didn't implement that part.

Thoughts?


diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 664bb83778d2..b0bc1b536d54 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -8,6 +8,14 @@

 #include <linux/build_bug.h>

+enum ddebug_categories {
+        FOO_BAR = 0,
+        DRM_A = 1,
+        DRM_B = 2,
+        DRM_C = 3,
+        //_DPRINTK_SITE_DEFAULT 63 is max
+};
+
 /*
  * An instance of this structure is created in a special
  * ELF section at every dynamic debug callsite.  At runtime,
@@ -23,9 +31,9 @@ struct _ddebug {
 	const char *filename;
 	const char *format;
 	unsigned int lineno:18;
-#define CLS_BITS 4
+#define CLS_BITS 6
 	unsigned int class_id:CLS_BITS;
-#define _DPRINTK_SITE_UNCLASSED		((1 << CLS_BITS) - 1)
+#define _DPRINTK_SITE_DEFAULT		((1 << CLS_BITS) - 1)
 	/*
 	 * The flags field controls the behaviour at the callsite.
 	 * The bits here are changed dynamically when the user
@@ -101,11 +109,11 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 		.class_id = cls,				\
 		_DPRINTK_KEY_INIT				\
 	};							\
-	BUILD_BUG_ON_MSG(cls > _DPRINTK_SITE_UNCLASSED,		\
+	BUILD_BUG_ON_MSG(cls > _DPRINTK_SITE_DEFAULT,		\
 			 "classid value overflow")

 #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)		\
-	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, _DPRINTK_SITE_UNCLASSED, fmt)
+	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, _DPRINTK_SITE_DEFAULT, fmt)

 #ifdef CONFIG_JUMP_LABEL

@@ -149,11 +157,11 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 } while (0)

 #define __dynamic_func_call(id, fmt, func, ...)				\
-	__dynamic_func_call_cls(id, _DPRINTK_SITE_UNCLASSED,		\
+	__dynamic_func_call_cls(id, _DPRINTK_SITE_DEFAULT,		\
 				fmt, func, ##__VA_ARGS__)

 #define __dynamic_func_call_no_desc(id, fmt, func, ...)			\
-	__dynamic_func_call_no_desc_cls(id, _DPRINTK_SITE_UNCLASSED,	\
+	__dynamic_func_call_no_desc_cls(id, _DPRINTK_SITE_DEFAULT,	\
 					fmt, func, ##__VA_ARGS__)

 /*
@@ -167,7 +175,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 #define _dynamic_func_call_cls(cls, fmt, func, ...)			\
 	__dynamic_func_call_cls(__UNIQUE_ID(ddebug), cls, fmt, func, ##__VA_ARGS__)
 #define _dynamic_func_call(fmt, func, ...)				\
-	_dynamic_func_call_cls(_DPRINTK_SITE_UNCLASSED, fmt, func, ##__VA_ARGS__)
+	_dynamic_func_call_cls(_DPRINTK_SITE_DEFAULT, fmt, func, ##__VA_ARGS__)

 /*
  * A variant that does the same, except that the descriptor is not
@@ -180,7 +188,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,

 #define _dynamic_func_call_no_desc(fmt, func, ...)			\
 	__dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug),		\
-					_DPRINTK_SITE_UNCLASSED,	\
+					_DPRINTK_SITE_DEFAULT,	\
 					fmt, func, ##__VA_ARGS__)

 #define dynamic_pr_debug(fmt, ...)				\
@@ -284,7 +292,7 @@ struct dyndbg_classbits_param {
 	static struct dyndbg_classbits_param ddcats_##_var = {		\
 		.bits = &(_var),					\
 		.flags = _flgs,						\
-		.classes = { __VA_ARGS__, _DPRINTK_SITE_UNCLASSED }	\
+		.classes = { __VA_ARGS__, _DPRINTK_SITE_DEFAULT }	\
 	};								\
 	module_param_cb(fsname, &param_ops_dyndbg_classbits,		\
 			&ddcats_##_var, 0644)
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 11c8d0771cd2..0f390638e46c 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -39,6 +39,14 @@

 #include <rdma/ib_verbs.h>

+static const char * const cat_to_strings[] = {
+        [FOO_BAR] = "foo:bar",
+        [DRM_A] = "drm:A",
+        [DRM_B] = "drm:B",
+        [DRM_C] = "drm:C",
+	[_DPRINTK_SITE_DEFAULT] = "default",
+};
+
 extern struct _ddebug __start___dyndbg[];
 extern struct _ddebug __stop___dyndbg[];

@@ -55,8 +63,7 @@ struct ddebug_query {
 	const char *function;
 	const char *format;
 	unsigned int first_lineno, last_lineno;
-	unsigned int class_id;
-	unsigned int class_marked:1;
+	const char *class_string;
 };

 struct ddebug_iter {
@@ -136,13 +143,13 @@ static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
 			fmtlen--;
 	}

-	v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u class=%u\n",
+	v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u class=%s\n",
 		 msg,
 		 query->function ?: "",
 		 query->filename ?: "",
 		 query->module ?: "",
 		 fmtlen, query->format ?: "",
-		 query->first_lineno, query->last_lineno, query->class_id);
+		 query->first_lineno, query->last_lineno, query->class_string);
 }

 /*
@@ -158,7 +165,7 @@ static int ddebug_change(const struct ddebug_query *query,
 	struct ddebug_table *dt;
 	unsigned int newflags;
 	unsigned int nfound = 0;
-	struct flagsbuf fbuf;
+	struct flagsbuf fbuf, nbuf;

 	/* search for matching ddebugs */
 	mutex_lock(&ddebug_lock);
@@ -172,8 +179,8 @@ static int ddebug_change(const struct ddebug_query *query,
 		for (i = 0; i < dt->num_ddebugs; i++) {
 			struct _ddebug *dp = &dt->ddebugs[i];

-			/* match against the class_id, either given or default */
-			if (query->class_id != dp->class_id)
+			/* if class is not set fall through, ot check if it matches */
+			if (query->class_string && strcmp(query->class_string, cat_to_strings[dp->class_id]))
 				continue;

 			/* match against the source filename */
@@ -223,11 +230,12 @@ static int ddebug_change(const struct ddebug_query *query,
 				static_branch_enable(&dp->key.dd_key_true);
 			}
 #endif
+			v4pr_info("changed %s:%d [%s]%s %s -> %s\n",
+				  trim_prefix(dp->filename), dp->lineno,
+				  dt->mod_name, dp->function,
+				  ddebug_describe_flags(dp->flags, &fbuf),
+				  ddebug_describe_flags(newflags, &nbuf));
 			dp->flags = newflags;
-			v4pr_info("changed %s:%d [%s]%s =%s\n",
-				 trim_prefix(dp->filename), dp->lineno,
-				 dt->mod_name, dp->function,
-				 ddebug_describe_flags(dp->flags, &fbuf));
 		}
 	}
 	mutex_unlock(&ddebug_lock);
@@ -314,21 +322,6 @@ static inline int parse_lineno(const char *str, unsigned int *val)
 	return 0;
 }

-static inline int parse_class(struct ddebug_query *query, const char *str)
-{
-	int rc;
-	unsigned int val;
-
-	rc = kstrtouint(str, 10, &val);
-	if (rc < 0 || val > _DPRINTK_SITE_UNCLASSED) {
-		pr_err("expecting class:[0-%d], not %s\n", _DPRINTK_SITE_UNCLASSED, str);
-		return -EINVAL;
-	}
-	query->class_id = val;
-	query->class_marked = 1;
-	return 0;
-}
-
 static int parse_linerange(struct ddebug_query *query, const char *first)
 {
 	char *last = strchr(first, '-');
@@ -443,8 +436,7 @@ static int ddebug_parse_query(char *words[], int nwords,
 			if (parse_linerange(query, arg))
 				return -EINVAL;
 		} else if (!strcmp(keyword, "class")) {
-			if (parse_class(query, arg))
-				return -EINVAL;
+			rc = check_set(&query->class_string, arg, "class");
 		} else {
 			pr_err("unknown keyword \"%s\"\n", keyword);
 			return -EINVAL;
@@ -452,9 +444,6 @@ static int ddebug_parse_query(char *words[], int nwords,
 		if (rc)
 			return rc;
 	}
-	/* post-validate the query, set default */
-	if (!query->class_marked)
-		query->class_id = _DPRINTK_SITE_UNCLASSED;

 	vpr_info_dq(query, "parsed");
 	return 0;
@@ -616,6 +605,8 @@ int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp)
 	}
 	vpr_info("set_dyndbg_classbits: new 0x%lx old 0x%lx\n", inbits, *dcp->bits);

+
+/*
 	for (i = 0; (i < _DPRINTK_SITE_UNCLASSED &&
 		     dcp->classes[i] < _DPRINTK_SITE_UNCLASSED); i++) {

@@ -630,6 +621,7 @@ int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp)
 			  matches, dcp->classes[i]);
 		totct += matches;
 	}
+*/
 	*dcp->bits = inbits;
 	vpr_info("total matches: %d\n", totct);
 	return 0;
@@ -978,8 +970,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
 	seq_escape(m, dp->format, "\t\r\n\"");
 	seq_puts(m, "\"");

-	if (dp->class_id != _DPRINTK_SITE_UNCLASSED)
-		seq_printf(m, " cls:%u", dp->class_id);
+	seq_printf(m, " cat:%s", cat_to_strings[dp->class_id]);
 	seq_puts(m, "\n");

 	return 0;

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

* Re: [PATCH 2/5] dyndbg: add class_id field and query support
@ 2022-03-14 21:29         ` Jason Baron
  0 siblings, 0 replies; 49+ messages in thread
From: Jason Baron @ 2022-03-14 21:29 UTC (permalink / raw)
  To: jim.cromie
  Cc: Greg KH, Intel Graphics Development, Rasmus Villemoes, LKML,
	dri-devel, robdclark, Sean Paul, amd-gfx mailing list,
	Daniel Vetter, Joe Perches, intel-gvt-dev



On 3/11/22 20:06, jim.cromie@gmail.com wrote:
> On Fri, Mar 11, 2022 at 12:06 PM Jason Baron <jbaron@akamai.com> wrote:
>>
>>
>>
>> On 3/10/22 23:47, Jim Cromie wrote:
>>> DRM defines/uses 10 enum drm_debug_category's to create exclusive
>>> classes of debug messages.  To support this directly in dynamic-debug,
>>> add the following:
>>>
>>> - struct _ddebug.class_id:4 - 4 bits is enough
>>> - define _DPRINTK_SITE_UNCLASSED 15 - see below
>>>
>>> and the query support:
>>> - struct _ddebug_query.class_id
>>> - ddebug_parse_query  - looks for "class" keyword, then calls..
>>> - parse_class         - accepts uint: 0-15, sets query.class_id and marker
>>> - vpr_info_dq         - displays new field
>>> - ddebug_proc_show    - append column with "cls:%d" if !UNCLASSED
>>>
>>> With the patch, one can enable current/unclassed callsites by:
>>>
>>>   #> echo drm class 15 +p > /proc/dynamic_debug/control
>>>
>>
>> To me, this is hard to read, what the heck is '15'? I have to go look it
>> up in the control file and it's not descriptive. I think that using
>> classes/categories makes sense but I'm wondering if it can be a bit more
>> user friendly? Perhaps, we can pass an array of strings that is indexed
>> by the class id to each pr_debug() site that wants to use class. So
>> something like:
>>
> 
> Im not at all averse to nice names, but as something added on.
> 
> 1st, the interface to make friendlier is DRM's
> 
> echo 0x04 > /sys/module/drm/parameters/debug   # which category ?
> 
> parm:           debug:Enable debug output, where each bit enables a
> debug category.
> Bit 0 (0x01)  will enable CORE messages (drm core code)
> Bit 1 (0x02)  will enable DRIVER messages (drm controller code)
> Bit 2 (0x04)  will enable KMS messages (modesetting code)
> 
> echo DRM_UT_DRIVER,DRM_UT_KMS > /sys/module/drm/parameters/debug   #
> now its pretty clear
> 
> If that works, its cuz DEFINE_DYNAMIC_DEBUG_CLASSBITS()
> plucks class symbols out of its __VA_ARGS__, and #stringifes them.
> So that macro could then build the 1-per-module static constant string array
> and (only) the callbacks would be able to use it.
> 
> from there, it shouldnt be hard to ref that from the module's ddebug_table,
> so parse_query could validate class args against the module given (or
> fail if none given)
> 
> Speaking strictly, theres a gap:
>    echo module * class DRM_UT_KMS +p > control
> is nonsense for * other than drm + drivers,
> but its fair/safe to just disallow wildcards on modname for this purpose.
> 
> it does however imply that module foo must exist for FOO_CAT_1 to be usable.
> thats not currently the case:
> bash-5.1# echo module foo +p > /proc/dynamic_debug/control
> [   15.403749] dyndbg: read 14 bytes from userspace
> [   15.405413] dyndbg: query 0: "module foo +p" mod:*
> [   15.406486] dyndbg: split into words: "module" "foo" "+p"
> [   15.407070] dyndbg: op='+'
> [   15.407388] dyndbg: flags=0x1
> [   15.407809] dyndbg: *flagsp=0x1 *maskp=0xffffffff
> [   15.408300] dyndbg: parsed: func="" file="" module="foo" format=""
> lineno=0-0 class=15
> [   15.409151] dyndbg: no matches for query
> [   15.409591] dyndbg: no-match: func="" file="" module="foo"
> format="" lineno=0-0 class=15
> [   15.410524] dyndbg: processed 1 queries, with 0 matches, 0 errs
> bash-5.1#
> 
> ISTM we can keep that "0 errs" response for that case, but still reject this:
> 
>    echo module foo class FOO_NOT_HERE +p > /proc/dynamic_debug/control
> 
> 

Ok, yeah so I guess I'm thinking about the 'class' more as global namespace,
so that for example, it could span modules, or be specific to certain modules.
I'm also thinking of it as a 'string' which is maybe hierarchical, so that it's
clear what sub-system, or sub-sub-system it belongs to. So for DRM for example,
it could be a string like "DRM:CORE". The index num I think is still helpful for
implementation so we don't have to store a pointer size, but I don't think it's
really exposed (except perhaps in module params b/c drm is doing that already?).


>> enum levels {
>>         LOW,
>>         MEDIUM,
>>         HIGH
>> };
> 
> I want to steer clear of "level" anything,
> since 2>1 implies non independence of the categories
> 
> 

Agreed, that was a bad example on my part.

I've put together a rough patch on top of your series, to make my thinking
hopefully clear. I also think that the module param callback thing could be
implemented in this 'global' space with the 0-14 low numbers, by adding
some sort of offset into the table. IE you would add the low number +
the offset to get the 'string' to add to the ddebug query. I commented it
out in my patch below b/c I didn't implement that part.

Thoughts?


diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 664bb83778d2..b0bc1b536d54 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -8,6 +8,14 @@

 #include <linux/build_bug.h>

+enum ddebug_categories {
+        FOO_BAR = 0,
+        DRM_A = 1,
+        DRM_B = 2,
+        DRM_C = 3,
+        //_DPRINTK_SITE_DEFAULT 63 is max
+};
+
 /*
  * An instance of this structure is created in a special
  * ELF section at every dynamic debug callsite.  At runtime,
@@ -23,9 +31,9 @@ struct _ddebug {
 	const char *filename;
 	const char *format;
 	unsigned int lineno:18;
-#define CLS_BITS 4
+#define CLS_BITS 6
 	unsigned int class_id:CLS_BITS;
-#define _DPRINTK_SITE_UNCLASSED		((1 << CLS_BITS) - 1)
+#define _DPRINTK_SITE_DEFAULT		((1 << CLS_BITS) - 1)
 	/*
 	 * The flags field controls the behaviour at the callsite.
 	 * The bits here are changed dynamically when the user
@@ -101,11 +109,11 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 		.class_id = cls,				\
 		_DPRINTK_KEY_INIT				\
 	};							\
-	BUILD_BUG_ON_MSG(cls > _DPRINTK_SITE_UNCLASSED,		\
+	BUILD_BUG_ON_MSG(cls > _DPRINTK_SITE_DEFAULT,		\
 			 "classid value overflow")

 #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)		\
-	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, _DPRINTK_SITE_UNCLASSED, fmt)
+	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, _DPRINTK_SITE_DEFAULT, fmt)

 #ifdef CONFIG_JUMP_LABEL

@@ -149,11 +157,11 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 } while (0)

 #define __dynamic_func_call(id, fmt, func, ...)				\
-	__dynamic_func_call_cls(id, _DPRINTK_SITE_UNCLASSED,		\
+	__dynamic_func_call_cls(id, _DPRINTK_SITE_DEFAULT,		\
 				fmt, func, ##__VA_ARGS__)

 #define __dynamic_func_call_no_desc(id, fmt, func, ...)			\
-	__dynamic_func_call_no_desc_cls(id, _DPRINTK_SITE_UNCLASSED,	\
+	__dynamic_func_call_no_desc_cls(id, _DPRINTK_SITE_DEFAULT,	\
 					fmt, func, ##__VA_ARGS__)

 /*
@@ -167,7 +175,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 #define _dynamic_func_call_cls(cls, fmt, func, ...)			\
 	__dynamic_func_call_cls(__UNIQUE_ID(ddebug), cls, fmt, func, ##__VA_ARGS__)
 #define _dynamic_func_call(fmt, func, ...)				\
-	_dynamic_func_call_cls(_DPRINTK_SITE_UNCLASSED, fmt, func, ##__VA_ARGS__)
+	_dynamic_func_call_cls(_DPRINTK_SITE_DEFAULT, fmt, func, ##__VA_ARGS__)

 /*
  * A variant that does the same, except that the descriptor is not
@@ -180,7 +188,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,

 #define _dynamic_func_call_no_desc(fmt, func, ...)			\
 	__dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug),		\
-					_DPRINTK_SITE_UNCLASSED,	\
+					_DPRINTK_SITE_DEFAULT,	\
 					fmt, func, ##__VA_ARGS__)

 #define dynamic_pr_debug(fmt, ...)				\
@@ -284,7 +292,7 @@ struct dyndbg_classbits_param {
 	static struct dyndbg_classbits_param ddcats_##_var = {		\
 		.bits = &(_var),					\
 		.flags = _flgs,						\
-		.classes = { __VA_ARGS__, _DPRINTK_SITE_UNCLASSED }	\
+		.classes = { __VA_ARGS__, _DPRINTK_SITE_DEFAULT }	\
 	};								\
 	module_param_cb(fsname, &param_ops_dyndbg_classbits,		\
 			&ddcats_##_var, 0644)
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 11c8d0771cd2..0f390638e46c 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -39,6 +39,14 @@

 #include <rdma/ib_verbs.h>

+static const char * const cat_to_strings[] = {
+        [FOO_BAR] = "foo:bar",
+        [DRM_A] = "drm:A",
+        [DRM_B] = "drm:B",
+        [DRM_C] = "drm:C",
+	[_DPRINTK_SITE_DEFAULT] = "default",
+};
+
 extern struct _ddebug __start___dyndbg[];
 extern struct _ddebug __stop___dyndbg[];

@@ -55,8 +63,7 @@ struct ddebug_query {
 	const char *function;
 	const char *format;
 	unsigned int first_lineno, last_lineno;
-	unsigned int class_id;
-	unsigned int class_marked:1;
+	const char *class_string;
 };

 struct ddebug_iter {
@@ -136,13 +143,13 @@ static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
 			fmtlen--;
 	}

-	v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u class=%u\n",
+	v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u class=%s\n",
 		 msg,
 		 query->function ?: "",
 		 query->filename ?: "",
 		 query->module ?: "",
 		 fmtlen, query->format ?: "",
-		 query->first_lineno, query->last_lineno, query->class_id);
+		 query->first_lineno, query->last_lineno, query->class_string);
 }

 /*
@@ -158,7 +165,7 @@ static int ddebug_change(const struct ddebug_query *query,
 	struct ddebug_table *dt;
 	unsigned int newflags;
 	unsigned int nfound = 0;
-	struct flagsbuf fbuf;
+	struct flagsbuf fbuf, nbuf;

 	/* search for matching ddebugs */
 	mutex_lock(&ddebug_lock);
@@ -172,8 +179,8 @@ static int ddebug_change(const struct ddebug_query *query,
 		for (i = 0; i < dt->num_ddebugs; i++) {
 			struct _ddebug *dp = &dt->ddebugs[i];

-			/* match against the class_id, either given or default */
-			if (query->class_id != dp->class_id)
+			/* if class is not set fall through, ot check if it matches */
+			if (query->class_string && strcmp(query->class_string, cat_to_strings[dp->class_id]))
 				continue;

 			/* match against the source filename */
@@ -223,11 +230,12 @@ static int ddebug_change(const struct ddebug_query *query,
 				static_branch_enable(&dp->key.dd_key_true);
 			}
 #endif
+			v4pr_info("changed %s:%d [%s]%s %s -> %s\n",
+				  trim_prefix(dp->filename), dp->lineno,
+				  dt->mod_name, dp->function,
+				  ddebug_describe_flags(dp->flags, &fbuf),
+				  ddebug_describe_flags(newflags, &nbuf));
 			dp->flags = newflags;
-			v4pr_info("changed %s:%d [%s]%s =%s\n",
-				 trim_prefix(dp->filename), dp->lineno,
-				 dt->mod_name, dp->function,
-				 ddebug_describe_flags(dp->flags, &fbuf));
 		}
 	}
 	mutex_unlock(&ddebug_lock);
@@ -314,21 +322,6 @@ static inline int parse_lineno(const char *str, unsigned int *val)
 	return 0;
 }

-static inline int parse_class(struct ddebug_query *query, const char *str)
-{
-	int rc;
-	unsigned int val;
-
-	rc = kstrtouint(str, 10, &val);
-	if (rc < 0 || val > _DPRINTK_SITE_UNCLASSED) {
-		pr_err("expecting class:[0-%d], not %s\n", _DPRINTK_SITE_UNCLASSED, str);
-		return -EINVAL;
-	}
-	query->class_id = val;
-	query->class_marked = 1;
-	return 0;
-}
-
 static int parse_linerange(struct ddebug_query *query, const char *first)
 {
 	char *last = strchr(first, '-');
@@ -443,8 +436,7 @@ static int ddebug_parse_query(char *words[], int nwords,
 			if (parse_linerange(query, arg))
 				return -EINVAL;
 		} else if (!strcmp(keyword, "class")) {
-			if (parse_class(query, arg))
-				return -EINVAL;
+			rc = check_set(&query->class_string, arg, "class");
 		} else {
 			pr_err("unknown keyword \"%s\"\n", keyword);
 			return -EINVAL;
@@ -452,9 +444,6 @@ static int ddebug_parse_query(char *words[], int nwords,
 		if (rc)
 			return rc;
 	}
-	/* post-validate the query, set default */
-	if (!query->class_marked)
-		query->class_id = _DPRINTK_SITE_UNCLASSED;

 	vpr_info_dq(query, "parsed");
 	return 0;
@@ -616,6 +605,8 @@ int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp)
 	}
 	vpr_info("set_dyndbg_classbits: new 0x%lx old 0x%lx\n", inbits, *dcp->bits);

+
+/*
 	for (i = 0; (i < _DPRINTK_SITE_UNCLASSED &&
 		     dcp->classes[i] < _DPRINTK_SITE_UNCLASSED); i++) {

@@ -630,6 +621,7 @@ int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp)
 			  matches, dcp->classes[i]);
 		totct += matches;
 	}
+*/
 	*dcp->bits = inbits;
 	vpr_info("total matches: %d\n", totct);
 	return 0;
@@ -978,8 +970,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
 	seq_escape(m, dp->format, "\t\r\n\"");
 	seq_puts(m, "\"");

-	if (dp->class_id != _DPRINTK_SITE_UNCLASSED)
-		seq_printf(m, " cls:%u", dp->class_id);
+	seq_printf(m, " cat:%s", cat_to_strings[dp->class_id]);
 	seq_puts(m, "\n");

 	return 0;

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

* Re: [Intel-gfx] [PATCH 2/5] dyndbg: add class_id field and query support
@ 2022-03-14 21:29         ` Jason Baron
  0 siblings, 0 replies; 49+ messages in thread
From: Jason Baron @ 2022-03-14 21:29 UTC (permalink / raw)
  To: jim.cromie
  Cc: Greg KH, Intel Graphics Development, Rasmus Villemoes, LKML,
	dri-devel, Sean Paul, amd-gfx mailing list, Daniel Vetter,
	Joe Perches, intel-gvt-dev



On 3/11/22 20:06, jim.cromie@gmail.com wrote:
> On Fri, Mar 11, 2022 at 12:06 PM Jason Baron <jbaron@akamai.com> wrote:
>>
>>
>>
>> On 3/10/22 23:47, Jim Cromie wrote:
>>> DRM defines/uses 10 enum drm_debug_category's to create exclusive
>>> classes of debug messages.  To support this directly in dynamic-debug,
>>> add the following:
>>>
>>> - struct _ddebug.class_id:4 - 4 bits is enough
>>> - define _DPRINTK_SITE_UNCLASSED 15 - see below
>>>
>>> and the query support:
>>> - struct _ddebug_query.class_id
>>> - ddebug_parse_query  - looks for "class" keyword, then calls..
>>> - parse_class         - accepts uint: 0-15, sets query.class_id and marker
>>> - vpr_info_dq         - displays new field
>>> - ddebug_proc_show    - append column with "cls:%d" if !UNCLASSED
>>>
>>> With the patch, one can enable current/unclassed callsites by:
>>>
>>>   #> echo drm class 15 +p > /proc/dynamic_debug/control
>>>
>>
>> To me, this is hard to read, what the heck is '15'? I have to go look it
>> up in the control file and it's not descriptive. I think that using
>> classes/categories makes sense but I'm wondering if it can be a bit more
>> user friendly? Perhaps, we can pass an array of strings that is indexed
>> by the class id to each pr_debug() site that wants to use class. So
>> something like:
>>
> 
> Im not at all averse to nice names, but as something added on.
> 
> 1st, the interface to make friendlier is DRM's
> 
> echo 0x04 > /sys/module/drm/parameters/debug   # which category ?
> 
> parm:           debug:Enable debug output, where each bit enables a
> debug category.
> Bit 0 (0x01)  will enable CORE messages (drm core code)
> Bit 1 (0x02)  will enable DRIVER messages (drm controller code)
> Bit 2 (0x04)  will enable KMS messages (modesetting code)
> 
> echo DRM_UT_DRIVER,DRM_UT_KMS > /sys/module/drm/parameters/debug   #
> now its pretty clear
> 
> If that works, its cuz DEFINE_DYNAMIC_DEBUG_CLASSBITS()
> plucks class symbols out of its __VA_ARGS__, and #stringifes them.
> So that macro could then build the 1-per-module static constant string array
> and (only) the callbacks would be able to use it.
> 
> from there, it shouldnt be hard to ref that from the module's ddebug_table,
> so parse_query could validate class args against the module given (or
> fail if none given)
> 
> Speaking strictly, theres a gap:
>    echo module * class DRM_UT_KMS +p > control
> is nonsense for * other than drm + drivers,
> but its fair/safe to just disallow wildcards on modname for this purpose.
> 
> it does however imply that module foo must exist for FOO_CAT_1 to be usable.
> thats not currently the case:
> bash-5.1# echo module foo +p > /proc/dynamic_debug/control
> [   15.403749] dyndbg: read 14 bytes from userspace
> [   15.405413] dyndbg: query 0: "module foo +p" mod:*
> [   15.406486] dyndbg: split into words: "module" "foo" "+p"
> [   15.407070] dyndbg: op='+'
> [   15.407388] dyndbg: flags=0x1
> [   15.407809] dyndbg: *flagsp=0x1 *maskp=0xffffffff
> [   15.408300] dyndbg: parsed: func="" file="" module="foo" format=""
> lineno=0-0 class=15
> [   15.409151] dyndbg: no matches for query
> [   15.409591] dyndbg: no-match: func="" file="" module="foo"
> format="" lineno=0-0 class=15
> [   15.410524] dyndbg: processed 1 queries, with 0 matches, 0 errs
> bash-5.1#
> 
> ISTM we can keep that "0 errs" response for that case, but still reject this:
> 
>    echo module foo class FOO_NOT_HERE +p > /proc/dynamic_debug/control
> 
> 

Ok, yeah so I guess I'm thinking about the 'class' more as global namespace,
so that for example, it could span modules, or be specific to certain modules.
I'm also thinking of it as a 'string' which is maybe hierarchical, so that it's
clear what sub-system, or sub-sub-system it belongs to. So for DRM for example,
it could be a string like "DRM:CORE". The index num I think is still helpful for
implementation so we don't have to store a pointer size, but I don't think it's
really exposed (except perhaps in module params b/c drm is doing that already?).


>> enum levels {
>>         LOW,
>>         MEDIUM,
>>         HIGH
>> };
> 
> I want to steer clear of "level" anything,
> since 2>1 implies non independence of the categories
> 
> 

Agreed, that was a bad example on my part.

I've put together a rough patch on top of your series, to make my thinking
hopefully clear. I also think that the module param callback thing could be
implemented in this 'global' space with the 0-14 low numbers, by adding
some sort of offset into the table. IE you would add the low number +
the offset to get the 'string' to add to the ddebug query. I commented it
out in my patch below b/c I didn't implement that part.

Thoughts?


diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 664bb83778d2..b0bc1b536d54 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -8,6 +8,14 @@

 #include <linux/build_bug.h>

+enum ddebug_categories {
+        FOO_BAR = 0,
+        DRM_A = 1,
+        DRM_B = 2,
+        DRM_C = 3,
+        //_DPRINTK_SITE_DEFAULT 63 is max
+};
+
 /*
  * An instance of this structure is created in a special
  * ELF section at every dynamic debug callsite.  At runtime,
@@ -23,9 +31,9 @@ struct _ddebug {
 	const char *filename;
 	const char *format;
 	unsigned int lineno:18;
-#define CLS_BITS 4
+#define CLS_BITS 6
 	unsigned int class_id:CLS_BITS;
-#define _DPRINTK_SITE_UNCLASSED		((1 << CLS_BITS) - 1)
+#define _DPRINTK_SITE_DEFAULT		((1 << CLS_BITS) - 1)
 	/*
 	 * The flags field controls the behaviour at the callsite.
 	 * The bits here are changed dynamically when the user
@@ -101,11 +109,11 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 		.class_id = cls,				\
 		_DPRINTK_KEY_INIT				\
 	};							\
-	BUILD_BUG_ON_MSG(cls > _DPRINTK_SITE_UNCLASSED,		\
+	BUILD_BUG_ON_MSG(cls > _DPRINTK_SITE_DEFAULT,		\
 			 "classid value overflow")

 #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)		\
-	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, _DPRINTK_SITE_UNCLASSED, fmt)
+	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, _DPRINTK_SITE_DEFAULT, fmt)

 #ifdef CONFIG_JUMP_LABEL

@@ -149,11 +157,11 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 } while (0)

 #define __dynamic_func_call(id, fmt, func, ...)				\
-	__dynamic_func_call_cls(id, _DPRINTK_SITE_UNCLASSED,		\
+	__dynamic_func_call_cls(id, _DPRINTK_SITE_DEFAULT,		\
 				fmt, func, ##__VA_ARGS__)

 #define __dynamic_func_call_no_desc(id, fmt, func, ...)			\
-	__dynamic_func_call_no_desc_cls(id, _DPRINTK_SITE_UNCLASSED,	\
+	__dynamic_func_call_no_desc_cls(id, _DPRINTK_SITE_DEFAULT,	\
 					fmt, func, ##__VA_ARGS__)

 /*
@@ -167,7 +175,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
 #define _dynamic_func_call_cls(cls, fmt, func, ...)			\
 	__dynamic_func_call_cls(__UNIQUE_ID(ddebug), cls, fmt, func, ##__VA_ARGS__)
 #define _dynamic_func_call(fmt, func, ...)				\
-	_dynamic_func_call_cls(_DPRINTK_SITE_UNCLASSED, fmt, func, ##__VA_ARGS__)
+	_dynamic_func_call_cls(_DPRINTK_SITE_DEFAULT, fmt, func, ##__VA_ARGS__)

 /*
  * A variant that does the same, except that the descriptor is not
@@ -180,7 +188,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,

 #define _dynamic_func_call_no_desc(fmt, func, ...)			\
 	__dynamic_func_call_no_desc_cls(__UNIQUE_ID(ddebug),		\
-					_DPRINTK_SITE_UNCLASSED,	\
+					_DPRINTK_SITE_DEFAULT,	\
 					fmt, func, ##__VA_ARGS__)

 #define dynamic_pr_debug(fmt, ...)				\
@@ -284,7 +292,7 @@ struct dyndbg_classbits_param {
 	static struct dyndbg_classbits_param ddcats_##_var = {		\
 		.bits = &(_var),					\
 		.flags = _flgs,						\
-		.classes = { __VA_ARGS__, _DPRINTK_SITE_UNCLASSED }	\
+		.classes = { __VA_ARGS__, _DPRINTK_SITE_DEFAULT }	\
 	};								\
 	module_param_cb(fsname, &param_ops_dyndbg_classbits,		\
 			&ddcats_##_var, 0644)
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 11c8d0771cd2..0f390638e46c 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -39,6 +39,14 @@

 #include <rdma/ib_verbs.h>

+static const char * const cat_to_strings[] = {
+        [FOO_BAR] = "foo:bar",
+        [DRM_A] = "drm:A",
+        [DRM_B] = "drm:B",
+        [DRM_C] = "drm:C",
+	[_DPRINTK_SITE_DEFAULT] = "default",
+};
+
 extern struct _ddebug __start___dyndbg[];
 extern struct _ddebug __stop___dyndbg[];

@@ -55,8 +63,7 @@ struct ddebug_query {
 	const char *function;
 	const char *format;
 	unsigned int first_lineno, last_lineno;
-	unsigned int class_id;
-	unsigned int class_marked:1;
+	const char *class_string;
 };

 struct ddebug_iter {
@@ -136,13 +143,13 @@ static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
 			fmtlen--;
 	}

-	v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u class=%u\n",
+	v3pr_info("%s: func=\"%s\" file=\"%s\" module=\"%s\" format=\"%.*s\" lineno=%u-%u class=%s\n",
 		 msg,
 		 query->function ?: "",
 		 query->filename ?: "",
 		 query->module ?: "",
 		 fmtlen, query->format ?: "",
-		 query->first_lineno, query->last_lineno, query->class_id);
+		 query->first_lineno, query->last_lineno, query->class_string);
 }

 /*
@@ -158,7 +165,7 @@ static int ddebug_change(const struct ddebug_query *query,
 	struct ddebug_table *dt;
 	unsigned int newflags;
 	unsigned int nfound = 0;
-	struct flagsbuf fbuf;
+	struct flagsbuf fbuf, nbuf;

 	/* search for matching ddebugs */
 	mutex_lock(&ddebug_lock);
@@ -172,8 +179,8 @@ static int ddebug_change(const struct ddebug_query *query,
 		for (i = 0; i < dt->num_ddebugs; i++) {
 			struct _ddebug *dp = &dt->ddebugs[i];

-			/* match against the class_id, either given or default */
-			if (query->class_id != dp->class_id)
+			/* if class is not set fall through, ot check if it matches */
+			if (query->class_string && strcmp(query->class_string, cat_to_strings[dp->class_id]))
 				continue;

 			/* match against the source filename */
@@ -223,11 +230,12 @@ static int ddebug_change(const struct ddebug_query *query,
 				static_branch_enable(&dp->key.dd_key_true);
 			}
 #endif
+			v4pr_info("changed %s:%d [%s]%s %s -> %s\n",
+				  trim_prefix(dp->filename), dp->lineno,
+				  dt->mod_name, dp->function,
+				  ddebug_describe_flags(dp->flags, &fbuf),
+				  ddebug_describe_flags(newflags, &nbuf));
 			dp->flags = newflags;
-			v4pr_info("changed %s:%d [%s]%s =%s\n",
-				 trim_prefix(dp->filename), dp->lineno,
-				 dt->mod_name, dp->function,
-				 ddebug_describe_flags(dp->flags, &fbuf));
 		}
 	}
 	mutex_unlock(&ddebug_lock);
@@ -314,21 +322,6 @@ static inline int parse_lineno(const char *str, unsigned int *val)
 	return 0;
 }

-static inline int parse_class(struct ddebug_query *query, const char *str)
-{
-	int rc;
-	unsigned int val;
-
-	rc = kstrtouint(str, 10, &val);
-	if (rc < 0 || val > _DPRINTK_SITE_UNCLASSED) {
-		pr_err("expecting class:[0-%d], not %s\n", _DPRINTK_SITE_UNCLASSED, str);
-		return -EINVAL;
-	}
-	query->class_id = val;
-	query->class_marked = 1;
-	return 0;
-}
-
 static int parse_linerange(struct ddebug_query *query, const char *first)
 {
 	char *last = strchr(first, '-');
@@ -443,8 +436,7 @@ static int ddebug_parse_query(char *words[], int nwords,
 			if (parse_linerange(query, arg))
 				return -EINVAL;
 		} else if (!strcmp(keyword, "class")) {
-			if (parse_class(query, arg))
-				return -EINVAL;
+			rc = check_set(&query->class_string, arg, "class");
 		} else {
 			pr_err("unknown keyword \"%s\"\n", keyword);
 			return -EINVAL;
@@ -452,9 +444,6 @@ static int ddebug_parse_query(char *words[], int nwords,
 		if (rc)
 			return rc;
 	}
-	/* post-validate the query, set default */
-	if (!query->class_marked)
-		query->class_id = _DPRINTK_SITE_UNCLASSED;

 	vpr_info_dq(query, "parsed");
 	return 0;
@@ -616,6 +605,8 @@ int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp)
 	}
 	vpr_info("set_dyndbg_classbits: new 0x%lx old 0x%lx\n", inbits, *dcp->bits);

+
+/*
 	for (i = 0; (i < _DPRINTK_SITE_UNCLASSED &&
 		     dcp->classes[i] < _DPRINTK_SITE_UNCLASSED); i++) {

@@ -630,6 +621,7 @@ int param_set_dyndbg_classbits(const char *instr, const struct kernel_param *kp)
 			  matches, dcp->classes[i]);
 		totct += matches;
 	}
+*/
 	*dcp->bits = inbits;
 	vpr_info("total matches: %d\n", totct);
 	return 0;
@@ -978,8 +970,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
 	seq_escape(m, dp->format, "\t\r\n\"");
 	seq_puts(m, "\"");

-	if (dp->class_id != _DPRINTK_SITE_UNCLASSED)
-		seq_printf(m, " cls:%u", dp->class_id);
+	seq_printf(m, " cat:%s", cat_to_strings[dp->class_id]);
 	seq_puts(m, "\n");

 	return 0;

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

* [Intel-gfx] ✗ Fi.CI.BUILD: failure for dyndbg add exclusive class support (rev2)
  2022-03-11  4:47 ` Jim Cromie
                   ` (11 preceding siblings ...)
  (?)
@ 2022-03-23 16:00 ` Patchwork
  -1 siblings, 0 replies; 49+ messages in thread
From: Patchwork @ 2022-03-23 16:00 UTC (permalink / raw)
  To: Jason Baron; +Cc: intel-gfx

== Series Details ==

Series: dyndbg add exclusive class support (rev2)
URL   : https://patchwork.freedesktop.org/series/101265/
State : failure

== Summary ==

Applying: dyndbg: fix static_branch manipulation
Applying: dyndbg: add class_id field and query support
error: sha1 information is lacking or useless (lib/dynamic_debug.c).
error: could not build fake ancestor
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0002 dyndbg: add class_id field and query support
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".



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

* Re: [PATCH 2/5] dyndbg: add class_id field and query support
  2022-03-14 21:29         ` Jason Baron
  (?)
  (?)
@ 2022-03-28 19:07           ` jim.cromie
  -1 siblings, 0 replies; 49+ messages in thread
From: jim.cromie @ 2022-03-28 19:07 UTC (permalink / raw)
  To: Jason Baron
  Cc: Greg KH, LKML, Daniel Vetter, Sean Paul, robdclark,
	Rasmus Villemoes, Joe Perches, dri-devel, amd-gfx mailing list,
	intel-gvt-dev, Intel Graphics Development

On Mon, Mar 14, 2022 at 3:30 PM Jason Baron <jbaron@akamai.com> wrote:
>
>
>
> On 3/11/22 20:06, jim.cromie@gmail.com wrote:
> > On Fri, Mar 11, 2022 at 12:06 PM Jason Baron <jbaron@akamai.com> wrote:
> >>
> >>
> >>
> >> On 3/10/22 23:47, Jim Cromie wrote:
> >>>
> >>> With the patch, one can enable current/unclassed callsites by:
> >>>
> >>>   #> echo drm class 15 +p > /proc/dynamic_debug/control
> >>>
> >>
> >> To me, this is hard to read, what the heck is '15'? I have to go look it
> >> up in the control file and it's not descriptive. I think that using
> >> classes/categories makes sense but I'm wondering if it can be a bit more
> >> user friendly? Perhaps, we can pass an array of strings that is indexed
> >> by the class id to each pr_debug() site that wants to use class. So
> >> something like:

hi Jason,
Im now in basically full agreement with you

1.   .class_id  is a "global" space, in that all callsites have one.
2.    0-15 is an exceedingly small range for a global space

Fix that by
3. make it private (by removing "class N" parsing)
   now nobody can do
   echo module * class N +p >control

4. add private/per-module "string" -> class_id map
    each module will have to declare the class-strings they use/accept
    opt-in - want coordinated / shared names for DRM_UT_KMS etc.

5. validate input using the known class_string -> class_id

then, this is knowably right or wrong, depending on DRM_FOO:
     echo module drm class DRM_FOO +p > control

it also means that
     echo class DRM_UT_KMS +p >control
is both wellformed and minimal;
any module that has DRM_UT_KMS defined will know which class_id *they*
have mapped it to.
theres no global "DRM_UT_KMS" to be abused.

So Ive been working towards that..
Heres my current biggest roadblock

DEFINE_DYNAMIC_DEBUG_CLASSBITS
creates the class-strings[] array declaratively, at compile-time.
This array is attached to the kernel-param.args,
so it can be used by the callbacks (to construct the command)

But its not obviously available from outside the sysfs knob
that its attached to, as is needed to apply command >control generally.

If I can attach the class-strings[]  to struct ddebug_table,
then ddebug_change() can use it to validate >control input.

So, how to attach ?
its got to work for both builtin & loadable modules.
(which precludes something in struct module ?)

I looked for a kernel_param_register callback, came up empty.
Trying to add it feels invasive / imposing.


> >
> > If that works, its cuz DEFINE_DYNAMIC_DEBUG_CLASSBITS()
> > plucks class symbols out of its __VA_ARGS__, and #stringifes them.
> > So that macro could then build the 1-per-module static constant string array
> > and (only) the callbacks would be able to use it.
> >

So Ive been tinkering hard on this macro, since its pretty central to
the interface defn.
heres some choices:

this is what Ive been working towards.
using enum symbols directly like this associates them by grep,
in contrast, class-strings are mealy-mouthed, milquetoast.

DEFINE_DYNAMIC_DEBUG_CLASSBITS(debug, __drm_debug, "p",
        "enable drm.debug categories - 1 bit per category",
        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);

 I found a slick MAP ( ) macro to do this:

#define DEFINE_DYNAMIC_DEBUG_CLASSBITS(fsname, _var, _flgs, desc, ...) \
  MODULE_PARM_DESC(fsname, desc); \
  static struct dyndbg_classbits_param ddcats_##_var = { \
    .bits = &(_var), \
    .flags = _flgs, \
    .classes = { __VA_ARGS__, _DPRINTK_CLASS_DFLT }, \
    .class_names = { mgMAP(__stringify, sCOMMA, \
                                                __VA_ARGS__,
_DPRINTK_CLASS_DFLT) } \
}; \
module_param_cb(fsname, &param_ops_dyndbg_classbits, \
&ddcats_##_var, 0644)

 __VA_ARGS__   is used 2x
.class_names is available for validating command >control

As much as I like the above, the MAP macro has a longer, more risky
path to the kernel

so a more modest alternative: module user defines class-strings in interface,
but they *must* align manually with the enum values they correspond to;
the order determines the bit-pos in the sysfs node,
since the interface no longer provides the enum values themselves.

DEFINE_DYNAMIC_DEBUG_CLASS_STRINGS(debug, __drm_debug, "p",
        "enable drm.debug categories - 1 bit per category",
        "DRM_UT_CORE",
        "DRM_UT_DRIVER",
        "DRM_UT_KMS",

different name allows CLASSBITs or similar in future, if MAP works out.
class-strings are completely defined by users, drm can drop UT naming

TLDR: FWIW

iSTM that  the same macro will support the coordinated use of class-strings
across multiple modules.

drm_print.c - natural home for exposed sysfs node

amdgpu/, drm_helper/ i915/  nouveau/  will all need a DEFINE_DD added,
so that ddebug_change() can allow those .class_ids to be controlled.
sysfs perm inits can disable their nodes, since theyre coordinated.

> >
>
> Ok, yeah so I guess I'm thinking about the 'class' more as global namespace,
> so that for example, it could span modules, or be specific to certain modules.
> I'm also thinking of it as a 'string' which is maybe hierarchical, so that it's
> clear what sub-system, or sub-sub-system it belongs to. So for DRM for example,
> it could be a string like "DRM:CORE". The index num I think is still helpful for
> implementation so we don't have to store a pointer size, but I don't think it's
> really exposed (except perhaps in module params b/c drm is doing that already?).
>

So what Ive got here is as described above,
I just need a few bright ideas,
then I can bring it together.
got a spare tuit?

Jim

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

* Re: [PATCH 2/5] dyndbg: add class_id field and query support
@ 2022-03-28 19:07           ` jim.cromie
  0 siblings, 0 replies; 49+ messages in thread
From: jim.cromie @ 2022-03-28 19:07 UTC (permalink / raw)
  To: Jason Baron
  Cc: Greg KH, Intel Graphics Development, Rasmus Villemoes, LKML,
	dri-devel, Sean Paul, amd-gfx mailing list, Daniel Vetter,
	Joe Perches, intel-gvt-dev

On Mon, Mar 14, 2022 at 3:30 PM Jason Baron <jbaron@akamai.com> wrote:
>
>
>
> On 3/11/22 20:06, jim.cromie@gmail.com wrote:
> > On Fri, Mar 11, 2022 at 12:06 PM Jason Baron <jbaron@akamai.com> wrote:
> >>
> >>
> >>
> >> On 3/10/22 23:47, Jim Cromie wrote:
> >>>
> >>> With the patch, one can enable current/unclassed callsites by:
> >>>
> >>>   #> echo drm class 15 +p > /proc/dynamic_debug/control
> >>>
> >>
> >> To me, this is hard to read, what the heck is '15'? I have to go look it
> >> up in the control file and it's not descriptive. I think that using
> >> classes/categories makes sense but I'm wondering if it can be a bit more
> >> user friendly? Perhaps, we can pass an array of strings that is indexed
> >> by the class id to each pr_debug() site that wants to use class. So
> >> something like:

hi Jason,
Im now in basically full agreement with you

1.   .class_id  is a "global" space, in that all callsites have one.
2.    0-15 is an exceedingly small range for a global space

Fix that by
3. make it private (by removing "class N" parsing)
   now nobody can do
   echo module * class N +p >control

4. add private/per-module "string" -> class_id map
    each module will have to declare the class-strings they use/accept
    opt-in - want coordinated / shared names for DRM_UT_KMS etc.

5. validate input using the known class_string -> class_id

then, this is knowably right or wrong, depending on DRM_FOO:
     echo module drm class DRM_FOO +p > control

it also means that
     echo class DRM_UT_KMS +p >control
is both wellformed and minimal;
any module that has DRM_UT_KMS defined will know which class_id *they*
have mapped it to.
theres no global "DRM_UT_KMS" to be abused.

So Ive been working towards that..
Heres my current biggest roadblock

DEFINE_DYNAMIC_DEBUG_CLASSBITS
creates the class-strings[] array declaratively, at compile-time.
This array is attached to the kernel-param.args,
so it can be used by the callbacks (to construct the command)

But its not obviously available from outside the sysfs knob
that its attached to, as is needed to apply command >control generally.

If I can attach the class-strings[]  to struct ddebug_table,
then ddebug_change() can use it to validate >control input.

So, how to attach ?
its got to work for both builtin & loadable modules.
(which precludes something in struct module ?)

I looked for a kernel_param_register callback, came up empty.
Trying to add it feels invasive / imposing.


> >
> > If that works, its cuz DEFINE_DYNAMIC_DEBUG_CLASSBITS()
> > plucks class symbols out of its __VA_ARGS__, and #stringifes them.
> > So that macro could then build the 1-per-module static constant string array
> > and (only) the callbacks would be able to use it.
> >

So Ive been tinkering hard on this macro, since its pretty central to
the interface defn.
heres some choices:

this is what Ive been working towards.
using enum symbols directly like this associates them by grep,
in contrast, class-strings are mealy-mouthed, milquetoast.

DEFINE_DYNAMIC_DEBUG_CLASSBITS(debug, __drm_debug, "p",
        "enable drm.debug categories - 1 bit per category",
        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);

 I found a slick MAP ( ) macro to do this:

#define DEFINE_DYNAMIC_DEBUG_CLASSBITS(fsname, _var, _flgs, desc, ...) \
  MODULE_PARM_DESC(fsname, desc); \
  static struct dyndbg_classbits_param ddcats_##_var = { \
    .bits = &(_var), \
    .flags = _flgs, \
    .classes = { __VA_ARGS__, _DPRINTK_CLASS_DFLT }, \
    .class_names = { mgMAP(__stringify, sCOMMA, \
                                                __VA_ARGS__,
_DPRINTK_CLASS_DFLT) } \
}; \
module_param_cb(fsname, &param_ops_dyndbg_classbits, \
&ddcats_##_var, 0644)

 __VA_ARGS__   is used 2x
.class_names is available for validating command >control

As much as I like the above, the MAP macro has a longer, more risky
path to the kernel

so a more modest alternative: module user defines class-strings in interface,
but they *must* align manually with the enum values they correspond to;
the order determines the bit-pos in the sysfs node,
since the interface no longer provides the enum values themselves.

DEFINE_DYNAMIC_DEBUG_CLASS_STRINGS(debug, __drm_debug, "p",
        "enable drm.debug categories - 1 bit per category",
        "DRM_UT_CORE",
        "DRM_UT_DRIVER",
        "DRM_UT_KMS",

different name allows CLASSBITs or similar in future, if MAP works out.
class-strings are completely defined by users, drm can drop UT naming

TLDR: FWIW

iSTM that  the same macro will support the coordinated use of class-strings
across multiple modules.

drm_print.c - natural home for exposed sysfs node

amdgpu/, drm_helper/ i915/  nouveau/  will all need a DEFINE_DD added,
so that ddebug_change() can allow those .class_ids to be controlled.
sysfs perm inits can disable their nodes, since theyre coordinated.

> >
>
> Ok, yeah so I guess I'm thinking about the 'class' more as global namespace,
> so that for example, it could span modules, or be specific to certain modules.
> I'm also thinking of it as a 'string' which is maybe hierarchical, so that it's
> clear what sub-system, or sub-sub-system it belongs to. So for DRM for example,
> it could be a string like "DRM:CORE". The index num I think is still helpful for
> implementation so we don't have to store a pointer size, but I don't think it's
> really exposed (except perhaps in module params b/c drm is doing that already?).
>

So what Ive got here is as described above,
I just need a few bright ideas,
then I can bring it together.
got a spare tuit?

Jim

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

* Re: [Intel-gfx] [PATCH 2/5] dyndbg: add class_id field and query support
@ 2022-03-28 19:07           ` jim.cromie
  0 siblings, 0 replies; 49+ messages in thread
From: jim.cromie @ 2022-03-28 19:07 UTC (permalink / raw)
  To: Jason Baron
  Cc: Greg KH, Intel Graphics Development, Rasmus Villemoes, LKML,
	dri-devel, Sean Paul, amd-gfx mailing list, Daniel Vetter,
	Joe Perches, intel-gvt-dev

On Mon, Mar 14, 2022 at 3:30 PM Jason Baron <jbaron@akamai.com> wrote:
>
>
>
> On 3/11/22 20:06, jim.cromie@gmail.com wrote:
> > On Fri, Mar 11, 2022 at 12:06 PM Jason Baron <jbaron@akamai.com> wrote:
> >>
> >>
> >>
> >> On 3/10/22 23:47, Jim Cromie wrote:
> >>>
> >>> With the patch, one can enable current/unclassed callsites by:
> >>>
> >>>   #> echo drm class 15 +p > /proc/dynamic_debug/control
> >>>
> >>
> >> To me, this is hard to read, what the heck is '15'? I have to go look it
> >> up in the control file and it's not descriptive. I think that using
> >> classes/categories makes sense but I'm wondering if it can be a bit more
> >> user friendly? Perhaps, we can pass an array of strings that is indexed
> >> by the class id to each pr_debug() site that wants to use class. So
> >> something like:

hi Jason,
Im now in basically full agreement with you

1.   .class_id  is a "global" space, in that all callsites have one.
2.    0-15 is an exceedingly small range for a global space

Fix that by
3. make it private (by removing "class N" parsing)
   now nobody can do
   echo module * class N +p >control

4. add private/per-module "string" -> class_id map
    each module will have to declare the class-strings they use/accept
    opt-in - want coordinated / shared names for DRM_UT_KMS etc.

5. validate input using the known class_string -> class_id

then, this is knowably right or wrong, depending on DRM_FOO:
     echo module drm class DRM_FOO +p > control

it also means that
     echo class DRM_UT_KMS +p >control
is both wellformed and minimal;
any module that has DRM_UT_KMS defined will know which class_id *they*
have mapped it to.
theres no global "DRM_UT_KMS" to be abused.

So Ive been working towards that..
Heres my current biggest roadblock

DEFINE_DYNAMIC_DEBUG_CLASSBITS
creates the class-strings[] array declaratively, at compile-time.
This array is attached to the kernel-param.args,
so it can be used by the callbacks (to construct the command)

But its not obviously available from outside the sysfs knob
that its attached to, as is needed to apply command >control generally.

If I can attach the class-strings[]  to struct ddebug_table,
then ddebug_change() can use it to validate >control input.

So, how to attach ?
its got to work for both builtin & loadable modules.
(which precludes something in struct module ?)

I looked for a kernel_param_register callback, came up empty.
Trying to add it feels invasive / imposing.


> >
> > If that works, its cuz DEFINE_DYNAMIC_DEBUG_CLASSBITS()
> > plucks class symbols out of its __VA_ARGS__, and #stringifes them.
> > So that macro could then build the 1-per-module static constant string array
> > and (only) the callbacks would be able to use it.
> >

So Ive been tinkering hard on this macro, since its pretty central to
the interface defn.
heres some choices:

this is what Ive been working towards.
using enum symbols directly like this associates them by grep,
in contrast, class-strings are mealy-mouthed, milquetoast.

DEFINE_DYNAMIC_DEBUG_CLASSBITS(debug, __drm_debug, "p",
        "enable drm.debug categories - 1 bit per category",
        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);

 I found a slick MAP ( ) macro to do this:

#define DEFINE_DYNAMIC_DEBUG_CLASSBITS(fsname, _var, _flgs, desc, ...) \
  MODULE_PARM_DESC(fsname, desc); \
  static struct dyndbg_classbits_param ddcats_##_var = { \
    .bits = &(_var), \
    .flags = _flgs, \
    .classes = { __VA_ARGS__, _DPRINTK_CLASS_DFLT }, \
    .class_names = { mgMAP(__stringify, sCOMMA, \
                                                __VA_ARGS__,
_DPRINTK_CLASS_DFLT) } \
}; \
module_param_cb(fsname, &param_ops_dyndbg_classbits, \
&ddcats_##_var, 0644)

 __VA_ARGS__   is used 2x
.class_names is available for validating command >control

As much as I like the above, the MAP macro has a longer, more risky
path to the kernel

so a more modest alternative: module user defines class-strings in interface,
but they *must* align manually with the enum values they correspond to;
the order determines the bit-pos in the sysfs node,
since the interface no longer provides the enum values themselves.

DEFINE_DYNAMIC_DEBUG_CLASS_STRINGS(debug, __drm_debug, "p",
        "enable drm.debug categories - 1 bit per category",
        "DRM_UT_CORE",
        "DRM_UT_DRIVER",
        "DRM_UT_KMS",

different name allows CLASSBITs or similar in future, if MAP works out.
class-strings are completely defined by users, drm can drop UT naming

TLDR: FWIW

iSTM that  the same macro will support the coordinated use of class-strings
across multiple modules.

drm_print.c - natural home for exposed sysfs node

amdgpu/, drm_helper/ i915/  nouveau/  will all need a DEFINE_DD added,
so that ddebug_change() can allow those .class_ids to be controlled.
sysfs perm inits can disable their nodes, since theyre coordinated.

> >
>
> Ok, yeah so I guess I'm thinking about the 'class' more as global namespace,
> so that for example, it could span modules, or be specific to certain modules.
> I'm also thinking of it as a 'string' which is maybe hierarchical, so that it's
> clear what sub-system, or sub-sub-system it belongs to. So for DRM for example,
> it could be a string like "DRM:CORE". The index num I think is still helpful for
> implementation so we don't have to store a pointer size, but I don't think it's
> really exposed (except perhaps in module params b/c drm is doing that already?).
>

So what Ive got here is as described above,
I just need a few bright ideas,
then I can bring it together.
got a spare tuit?

Jim

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

* Re: [PATCH 2/5] dyndbg: add class_id field and query support
@ 2022-03-28 19:07           ` jim.cromie
  0 siblings, 0 replies; 49+ messages in thread
From: jim.cromie @ 2022-03-28 19:07 UTC (permalink / raw)
  To: Jason Baron
  Cc: Greg KH, Intel Graphics Development, Rasmus Villemoes, LKML,
	dri-devel, robdclark, Sean Paul, amd-gfx mailing list,
	Daniel Vetter, Joe Perches, intel-gvt-dev

On Mon, Mar 14, 2022 at 3:30 PM Jason Baron <jbaron@akamai.com> wrote:
>
>
>
> On 3/11/22 20:06, jim.cromie@gmail.com wrote:
> > On Fri, Mar 11, 2022 at 12:06 PM Jason Baron <jbaron@akamai.com> wrote:
> >>
> >>
> >>
> >> On 3/10/22 23:47, Jim Cromie wrote:
> >>>
> >>> With the patch, one can enable current/unclassed callsites by:
> >>>
> >>>   #> echo drm class 15 +p > /proc/dynamic_debug/control
> >>>
> >>
> >> To me, this is hard to read, what the heck is '15'? I have to go look it
> >> up in the control file and it's not descriptive. I think that using
> >> classes/categories makes sense but I'm wondering if it can be a bit more
> >> user friendly? Perhaps, we can pass an array of strings that is indexed
> >> by the class id to each pr_debug() site that wants to use class. So
> >> something like:

hi Jason,
Im now in basically full agreement with you

1.   .class_id  is a "global" space, in that all callsites have one.
2.    0-15 is an exceedingly small range for a global space

Fix that by
3. make it private (by removing "class N" parsing)
   now nobody can do
   echo module * class N +p >control

4. add private/per-module "string" -> class_id map
    each module will have to declare the class-strings they use/accept
    opt-in - want coordinated / shared names for DRM_UT_KMS etc.

5. validate input using the known class_string -> class_id

then, this is knowably right or wrong, depending on DRM_FOO:
     echo module drm class DRM_FOO +p > control

it also means that
     echo class DRM_UT_KMS +p >control
is both wellformed and minimal;
any module that has DRM_UT_KMS defined will know which class_id *they*
have mapped it to.
theres no global "DRM_UT_KMS" to be abused.

So Ive been working towards that..
Heres my current biggest roadblock

DEFINE_DYNAMIC_DEBUG_CLASSBITS
creates the class-strings[] array declaratively, at compile-time.
This array is attached to the kernel-param.args,
so it can be used by the callbacks (to construct the command)

But its not obviously available from outside the sysfs knob
that its attached to, as is needed to apply command >control generally.

If I can attach the class-strings[]  to struct ddebug_table,
then ddebug_change() can use it to validate >control input.

So, how to attach ?
its got to work for both builtin & loadable modules.
(which precludes something in struct module ?)

I looked for a kernel_param_register callback, came up empty.
Trying to add it feels invasive / imposing.


> >
> > If that works, its cuz DEFINE_DYNAMIC_DEBUG_CLASSBITS()
> > plucks class symbols out of its __VA_ARGS__, and #stringifes them.
> > So that macro could then build the 1-per-module static constant string array
> > and (only) the callbacks would be able to use it.
> >

So Ive been tinkering hard on this macro, since its pretty central to
the interface defn.
heres some choices:

this is what Ive been working towards.
using enum symbols directly like this associates them by grep,
in contrast, class-strings are mealy-mouthed, milquetoast.

DEFINE_DYNAMIC_DEBUG_CLASSBITS(debug, __drm_debug, "p",
        "enable drm.debug categories - 1 bit per category",
        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);

 I found a slick MAP ( ) macro to do this:

#define DEFINE_DYNAMIC_DEBUG_CLASSBITS(fsname, _var, _flgs, desc, ...) \
  MODULE_PARM_DESC(fsname, desc); \
  static struct dyndbg_classbits_param ddcats_##_var = { \
    .bits = &(_var), \
    .flags = _flgs, \
    .classes = { __VA_ARGS__, _DPRINTK_CLASS_DFLT }, \
    .class_names = { mgMAP(__stringify, sCOMMA, \
                                                __VA_ARGS__,
_DPRINTK_CLASS_DFLT) } \
}; \
module_param_cb(fsname, &param_ops_dyndbg_classbits, \
&ddcats_##_var, 0644)

 __VA_ARGS__   is used 2x
.class_names is available for validating command >control

As much as I like the above, the MAP macro has a longer, more risky
path to the kernel

so a more modest alternative: module user defines class-strings in interface,
but they *must* align manually with the enum values they correspond to;
the order determines the bit-pos in the sysfs node,
since the interface no longer provides the enum values themselves.

DEFINE_DYNAMIC_DEBUG_CLASS_STRINGS(debug, __drm_debug, "p",
        "enable drm.debug categories - 1 bit per category",
        "DRM_UT_CORE",
        "DRM_UT_DRIVER",
        "DRM_UT_KMS",

different name allows CLASSBITs or similar in future, if MAP works out.
class-strings are completely defined by users, drm can drop UT naming

TLDR: FWIW

iSTM that  the same macro will support the coordinated use of class-strings
across multiple modules.

drm_print.c - natural home for exposed sysfs node

amdgpu/, drm_helper/ i915/  nouveau/  will all need a DEFINE_DD added,
so that ddebug_change() can allow those .class_ids to be controlled.
sysfs perm inits can disable their nodes, since theyre coordinated.

> >
>
> Ok, yeah so I guess I'm thinking about the 'class' more as global namespace,
> so that for example, it could span modules, or be specific to certain modules.
> I'm also thinking of it as a 'string' which is maybe hierarchical, so that it's
> clear what sub-system, or sub-sub-system it belongs to. So for DRM for example,
> it could be a string like "DRM:CORE". The index num I think is still helpful for
> implementation so we don't have to store a pointer size, but I don't think it's
> really exposed (except perhaps in module params b/c drm is doing that already?).
>

So what Ive got here is as described above,
I just need a few bright ideas,
then I can bring it together.
got a spare tuit?

Jim

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

end of thread, other threads:[~2022-03-28 19:08 UTC | newest]

Thread overview: 49+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-11  4:47 [PATCH 0/5] dyndbg add exclusive class support Jim Cromie
2022-03-11  4:47 ` Jim Cromie
2022-03-11  4:47 ` [Intel-gfx] " Jim Cromie
2022-03-11  4:47 ` Jim Cromie
2022-03-11  4:47 ` [PATCH 1/5] dyndbg: fix static_branch manipulation Jim Cromie
2022-03-11  4:47   ` Jim Cromie
2022-03-11  4:47   ` [Intel-gfx] " Jim Cromie
2022-03-11  4:47   ` Jim Cromie
2022-03-11 18:03   ` Jason Baron
2022-03-11 18:03     ` [Intel-gfx] " Jason Baron
2022-03-11 18:03     ` Jason Baron
2022-03-11 18:03     ` Jason Baron
2022-03-11  4:47 ` [PATCH 2/5] dyndbg: add class_id field and query support Jim Cromie
2022-03-11  4:47   ` Jim Cromie
2022-03-11  4:47   ` [Intel-gfx] " Jim Cromie
2022-03-11  4:47   ` Jim Cromie
2022-03-11 19:06   ` Jason Baron
2022-03-11 19:06     ` [Intel-gfx] " Jason Baron
2022-03-11 19:06     ` Jason Baron
2022-03-11 19:06     ` Jason Baron
2022-03-12  1:06     ` jim.cromie
2022-03-12  1:06       ` jim.cromie
2022-03-12  1:06       ` [Intel-gfx] " jim.cromie
2022-03-12  1:06       ` jim.cromie
2022-03-14 21:29       ` Jason Baron
2022-03-14 21:29         ` [Intel-gfx] " Jason Baron
2022-03-14 21:29         ` Jason Baron
2022-03-14 21:29         ` Jason Baron
2022-03-28 19:07         ` jim.cromie
2022-03-28 19:07           ` jim.cromie
2022-03-28 19:07           ` [Intel-gfx] " jim.cromie
2022-03-28 19:07           ` jim.cromie
2022-03-11  4:47 ` [PATCH 3/5] dyndbg: add DEFINE_DYNAMIC_DEBUG_CLASSBITS macro Jim Cromie
2022-03-11  4:47   ` Jim Cromie
2022-03-11  4:47   ` [Intel-gfx] " Jim Cromie
2022-03-11  4:47   ` Jim Cromie
2022-03-11  4:47 ` [PATCH 4/5] dyndbg: drop EXPORTed dynamic_debug_exec_queries Jim Cromie
2022-03-11  4:47   ` Jim Cromie
2022-03-11  4:47   ` [Intel-gfx] " Jim Cromie
2022-03-11  4:47   ` Jim Cromie
2022-03-11  4:47 ` [PATCH 5/5] dyndbg: show both old and new in change-info Jim Cromie
2022-03-11  4:47   ` Jim Cromie
2022-03-11  4:47   ` [Intel-gfx] " Jim Cromie
2022-03-11  4:47   ` Jim Cromie
2022-03-11  5:13 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for dyndbg add exclusive class support Patchwork
2022-03-11  5:17 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
2022-03-11  5:42 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
2022-03-11  7:27 ` [Intel-gfx] ✓ Fi.CI.IGT: " Patchwork
2022-03-23 16:00 ` [Intel-gfx] ✗ Fi.CI.BUILD: failure for dyndbg add exclusive class support (rev2) Patchwork

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.