drm/print: Introduce drm_line_printer

This drm printer wrapper can be used to increase the robustness of
the captured output generated by any other drm_printer to make sure
we didn't lost any intermediate lines of the output by adding line
numbers to each output line. Helpful for capturing some crash data.

v2: Extended short int counters to full int (JohnH)

Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Signed-off-by: John Harrison <John.C.Harrison@Intel.com>
Cc: Jani Nikula <jani.nikula@intel.com>
Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
Acked-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241003004611.2323493-8-John.C.Harrison@Intel.com
This commit is contained in:
Michal Wajdeczko 2024-10-02 17:46:07 -07:00 committed by John Harrison
parent d8ce1a9772
commit 754e707e20
2 changed files with 78 additions and 0 deletions

View File

@ -235,6 +235,20 @@ void __drm_printfn_err(struct drm_printer *p, struct va_format *vaf)
}
EXPORT_SYMBOL(__drm_printfn_err);
void __drm_printfn_line(struct drm_printer *p, struct va_format *vaf)
{
unsigned int counter = ++p->line.counter;
const char *prefix = p->prefix ?: "";
const char *pad = p->prefix ? " " : "";
if (p->line.series)
drm_printf(p->arg, "%s%s%u.%u: %pV",
prefix, pad, p->line.series, counter, vaf);
else
drm_printf(p->arg, "%s%s%u: %pV", prefix, pad, counter, vaf);
}
EXPORT_SYMBOL(__drm_printfn_line);
/**
* drm_puts - print a const string to a &drm_printer stream
* @p: the &drm printer

View File

@ -177,6 +177,10 @@ struct drm_printer {
void *arg;
const void *origin;
const char *prefix;
struct {
unsigned int series;
unsigned int counter;
} line;
enum drm_debug_category category;
};
@ -187,6 +191,7 @@ void __drm_puts_seq_file(struct drm_printer *p, const char *str);
void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf);
void __drm_printfn_dbg(struct drm_printer *p, struct va_format *vaf);
void __drm_printfn_err(struct drm_printer *p, struct va_format *vaf);
void __drm_printfn_line(struct drm_printer *p, struct va_format *vaf);
__printf(2, 3)
void drm_printf(struct drm_printer *p, const char *f, ...);
@ -411,6 +416,65 @@ static inline struct drm_printer drm_err_printer(struct drm_device *drm,
return p;
}
/**
* drm_line_printer - construct a &drm_printer that prefixes outputs with line numbers
* @p: the &struct drm_printer which actually generates the output
* @prefix: optional output prefix, or NULL for no prefix
* @series: optional unique series identifier, or 0 to omit identifier in the output
*
* This printer can be used to increase the robustness of the captured output
* to make sure we didn't lost any intermediate lines of the output. Helpful
* while capturing some crash data.
*
* Example 1::
*
* void crash_dump(struct drm_device *drm)
* {
* static unsigned int id;
* struct drm_printer p = drm_err_printer(drm, "crash");
* struct drm_printer lp = drm_line_printer(&p, "dump", ++id);
*
* drm_printf(&lp, "foo");
* drm_printf(&lp, "bar");
* }
*
* Above code will print into the dmesg something like::
*
* [ ] 0000:00:00.0: [drm] *ERROR* crash dump 1.1: foo
* [ ] 0000:00:00.0: [drm] *ERROR* crash dump 1.2: bar
*
* Example 2::
*
* void line_dump(struct device *dev)
* {
* struct drm_printer p = drm_info_printer(dev);
* struct drm_printer lp = drm_line_printer(&p, NULL, 0);
*
* drm_printf(&lp, "foo");
* drm_printf(&lp, "bar");
* }
*
* Above code will print::
*
* [ ] 0000:00:00.0: [drm] 1: foo
* [ ] 0000:00:00.0: [drm] 2: bar
*
* RETURNS:
* The &drm_printer object
*/
static inline struct drm_printer drm_line_printer(struct drm_printer *p,
const char *prefix,
unsigned int series)
{
struct drm_printer lp = {
.printfn = __drm_printfn_line,
.arg = p,
.prefix = prefix,
.line = { .series = series, },
};
return lp;
}
/*
* struct device based logging
*