<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    On 5/23/2024 16:54, Daniele Ceraolo Spurio wrote:<br>
    <blockquote type="cite" cite="mid:d928673b-133f-4d0d-8c8d-44f4ebad33b6@intel.com">
      
      -------- Forwarded Message --------
      <div class="moz-forward-container">
        <table class="moz-email-headers-table" cellspacing="0" cellpadding="0" border="0">
          <tbody>
            <tr>
              <th valign="BASELINE" nowrap="nowrap" align="RIGHT">Subject:
              </th>
              <td>[RFC] drm/print: Introduce drm_line_printer</td>
            </tr>
            <tr>
              <th valign="BASELINE" nowrap="nowrap" align="RIGHT">Date:
              </th>
              <td>Tue, 14 May 2024 16:56:31 +0200</td>
            </tr>
            <tr>
              <th valign="BASELINE" nowrap="nowrap" align="RIGHT">From:
              </th>
              <td>Michal Wajdeczko <a class="moz-txt-link-rfc2396E" href="mailto:michal.wajdeczko@intel.com" moz-do-not-send="true"><michal.wajdeczko@intel.com></a></td>
            </tr>
            <tr>
              <th valign="BASELINE" nowrap="nowrap" align="RIGHT">To: </th>
              <td><a class="moz-txt-link-abbreviated moz-txt-link-freetext" href="mailto:dri-devel@lists.freedesktop.org" moz-do-not-send="true">dri-devel@lists.freedesktop.org</a></td>
            </tr>
          </tbody>
        </table>
        <br>
        <br>
        This drm printer wrapper can be used to increase the robustness
        of<br>
        the captured output generated by any other drm_printer to make
        sure<br>
        we didn't lost any intermediate lines of the output by adding
        line<br>
        numbers to each output line. Helpful for capturing some crash
        data.<br>
        <br>
        Signed-off-by: Michal Wajdeczko <a class="moz-txt-link-rfc2396E" href="mailto:michal.wajdeczko@intel.com" moz-do-not-send="true"><michal.wajdeczko@intel.com></a><br>
        ---<br>
        drivers/gpu/drm/drm_print.c | 9 +++++++++<br>
        include/drm/drm_print.h | 37
        +++++++++++++++++++++++++++++++++++++<br>
        2 files changed, 46 insertions(+)<br>
        <br>
        diff --git a/drivers/gpu/drm/drm_print.c
        b/drivers/gpu/drm/drm_print.c<br>
        index cf2efb44722c..d6fb50d3407a 100644<br>
        --- a/drivers/gpu/drm/drm_print.c<br>
        +++ b/drivers/gpu/drm/drm_print.c<br>
        @@ -214,6 +214,15 @@ void __drm_printfn_err(struct drm_printer
        *p, struct va_format *vaf)<br>
        }<br>
        EXPORT_SYMBOL(__drm_printfn_err);<br>
        +void __drm_printfn_line(struct drm_printer *p, struct va_format
        *vaf)<br>
        +{<br>
        + unsigned int line = (uintptr_t)(++p->prefix);<br>
      </div>
    </blockquote>
    The prefix field is officially supposed to be a const char *. There
    is no documentation to say that this is intended to be used as a
    private data field by random printer wrappers. So overloading it
    like this feels very hacky and dangerous. Also, you are mixing types
    - uintptr_t then uint. So an arch with 64-bit pointers but only
    32-bit ints would hit a truncated compiler warning?<br>
    <br>
    <blockquote type="cite" cite="mid:d928673b-133f-4d0d-8c8d-44f4ebad33b6@intel.com">
      <div class="moz-forward-container"> + struct drm_printer *dp =
        p->arg;<br>
        +<br>
        + drm_printf(dp, "%u: %pV", line, vaf);<br>
      </div>
    </blockquote>
    This is insufficient. As previously commented, there needs to be a
    global counter as well as a local line counter. The global count
    must be global to at least whatever entity is generating a specific
    set of prints. Being global to a higher level, e.g. kernel global,
    is fine. But without that, two concurrent dumps that get interleaved
    can be impossible to separate resulting in a useless bug report/log.<br>
    <br>
    The prefix field could potentially be split into a 16:16
    global:local index with the global master just being a static u16
    inside that function. With the first print call to a given
    drm_printer object being defined by the global value being zero. And
    it then sets the global value to the next increment skipping over
    zero on a 16-bit wrap around. But see above about prefix not being
    intended for such purposes. So now you are just piling hacks upon
    hacks.<br>
    <br>
    Plus it would be much nicer output to have the ability to put an
    arbitrary prefix in front of the G.L number, as per the original
    implementation. The whole point of this is to aid identification of
    otherwise uniform data such as hexdumps. So anything that makes it
    less clear is bad.<br>
    <br>
    John.<br>
    <br>
    <br>
    <blockquote type="cite" cite="mid:d928673b-133f-4d0d-8c8d-44f4ebad33b6@intel.com">
      <div class="moz-forward-container"> +}<br>
        +EXPORT_SYMBOL(__drm_printfn_line);<br>
        +<br>
        /**<br>
        * drm_puts - print a const string to a &drm_printer stream<br>
        * @p: the &drm printer<br>
        diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h<br>
        index 089950ad8681..58cc73c53853 100644<br>
        --- a/include/drm/drm_print.h<br>
        +++ b/include/drm/drm_print.h<br>
        @@ -186,6 +186,7 @@ void __drm_puts_seq_file(struct drm_printer
        *p, const char *str);<br>
        void __drm_printfn_info(struct drm_printer *p, struct va_format
        *vaf);<br>
        void __drm_printfn_dbg(struct drm_printer *p, struct va_format
        *vaf);<br>
        void __drm_printfn_err(struct drm_printer *p, struct va_format
        *vaf);<br>
        +void __drm_printfn_line(struct drm_printer *p, struct va_format
        *vaf);<br>
        __printf(2, 3)<br>
        void drm_printf(struct drm_printer *p, const char *f, ...);<br>
        @@ -357,6 +358,42 @@ static inline struct drm_printer
        drm_err_printer(struct drm_device *drm,<br>
        return p;<br>
        }<br>
        +/**<br>
        + * drm_line_printer - construct a &drm_printer that
        prefixes outputs with line numbers<br>
        + * @dp: the &struct drm_printer which actually generates
        the output<br>
        + *<br>
        + * This printer can be used to increase the robustness of the
        captured output<br>
        + * to make sure we didn't lost any intermediate lines of the
        output. Helpful<br>
        + * while capturing some crash data.<br>
        + *<br>
        + * For example::<br>
        + *<br>
        + * void crash_dump(struct drm_device *drm)<br>
        + * {<br>
        + * struct drm_printer dp = drm_err_printer(drm, "crash");<br>
        + * struct drm_printer lp = drm_line_printer(&dp);<br>
        + *<br>
        + * drm_printf(&lp, "foo");<br>
        + * drm_printf(&lp, "bar");<br>
        + * }<br>
        + *<br>
        + * Above code will print into the dmesg something like::<br>
        + *<br>
        + * [ ] 0000:00:00.0: [drm] *ERROR* crash 1: foo<br>
        + * [ ] 0000:00:00.0: [drm] *ERROR* crash 2: bar<br>
        + *<br>
        + * RETURNS:<br>
        + * The &drm_printer object<br>
        + */<br>
        +static inline struct drm_printer drm_line_printer(struct
        drm_printer *dp)<br>
        +{<br>
        + struct drm_printer lp = {<br>
        + .printfn = __drm_printfn_line,<br>
        + .arg = dp,<br>
        + };<br>
        + return lp;<br>
        +}<br>
        +<br>
        /*<br>
        * struct device based logging<br>
        *<br>
        <pre class="moz-signature">-- 
2.43.0

</pre>
      </div>
    </blockquote>
    <br>
  </body>
</html>