On Fri, Dec 13, 2019 at 05:34:25PM +0200, Jani Nikula wrote:
> On Thu, 12 Dec 2019, Sean Paul <[email protected]> wrote:
> > From: Sean Paul <[email protected]>
> >
> > For a long while now, we (ChromeOS) have been struggling getting any
> > value out of user feedback reports of display failures (notably external
> > displays not working). The problem is that all logging, even fatal
> > errors (well, fatal in the sense that a display won't light up) are
> > logged at DEBUG log level. So in order to extract these logs, users need
> > to be able to turn on logging, and reproduce the issue with debug
> > enabled. Unfortunately, this isn't really something we can ask CrOS users
> > to do. I spoke with airlied about this and RHEL has similar issues. After
> > a few more people piped up on previous versions of this patch, it is a
> > Real Issue.
> >
> > So why don't we just enable DRM_UT_BLAH? Here are the reasons in
> > ascending order of severity:
> >  1- People aren't consistent with their categories, so we'd have to
> >     enable a bunch to get proper coverage
> >  2- We don't want to overwhelm syslog with drm spam, others have to use
> >     it too
> >  3- Console logging is slow
> >
> > So what we really want is a ringbuffer of the most recent logs
> > (filtered by categories we're interested in) exposed via debugfs so the
> > logs can be extracted when users file feedback.
> >
> > It just so happens that there is something which does _exactly_ this!
> > This patch dumps drm logs into tracepoints, which allows us to turn tracing
> > on and off depending on which category is useful, and pull them from
> > tracefs on demand.
> >
> > What about trace_printk()? It doesn't give us the control we get from using
> > tracepoints and it's not meant to be left sprinkled around in code.
> >
> > Cc: David Airlie <[email protected]>
> > Cc: Daniel Vetter <[email protected]>
> > Cc: Pekka Paalanen <[email protected]>
> > Cc: Joonas Lahtinen <[email protected]>
> > Cc: Thomas Zimmermann <[email protected]>
> > Cc: Rob Clark <[email protected]>
> > Cc: Ville Syrjälä <[email protected]>
> > Acked-by: Daniel Vetter <[email protected]>
> > Signed-off-by: Sean Paul <[email protected]>
> > Link: 
> > https://patchwork.freedesktop.org/patch/msgid/[email protected]
> >  #v1
> >
> > Changes in v2:
> > - Went with a completely different approach: 
> > https://lists.freedesktop.org/archives/dri-devel/2019-November/243230.html
> >
> > Changes in v3:
> > - Changed commit message to be a bit less RFC-y
> > - Make class_drm_category_log an actual trace class
> > ---
> >
> > Even though we don't want it to be, this is UAPI. So here's some userspace
> > code which uses it:
> > https://chromium-review.googlesource.com/c/chromiumos/platform2/+/1965562
> >
> >
> >  drivers/gpu/drm/drm_print.c      | 143 ++++++++++++++++++++++++++-----
> >  include/trace/events/drm_print.h | 116 +++++++++++++++++++++++++
> >  2 files changed, 239 insertions(+), 20 deletions(-)
> >  create mode 100644 include/trace/events/drm_print.h
> >
> > diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c
> > index 9a25d73c155c..f591292811aa 100644
> > --- a/drivers/gpu/drm/drm_print.c
> > +++ b/drivers/gpu/drm/drm_print.c
> > @@ -27,11 +27,15 @@
> >  
> >  #include <stdarg.h>
> >  
> > +#include <linux/bitops.h>
> >  #include <linux/io.h>
> >  #include <linux/moduleparam.h>
> >  #include <linux/seq_file.h>
> >  #include <linux/slab.h>
> >  
> > +#define CREATE_TRACE_POINTS
> > +#include <trace/events/drm_print.h>
> > +
> >  #include <drm/drm.h>
> >  #include <drm/drm_drv.h>
> >  #include <drm/drm_print.h>
> > @@ -241,10 +245,10 @@ void drm_dev_printk(const struct device *dev, const 
> > char *level,
> >     struct va_format vaf;
> >     va_list args;
> >  
> > -   va_start(args, format);
> >     vaf.fmt = format;
> >     vaf.va = &args;
> >  
> > +   va_start(args, format);
> >     if (dev)
> >             dev_printk(level, dev, "[" DRM_NAME ":%ps] %pV",
> >                        __builtin_return_address(0), &vaf);
> > @@ -253,49 +257,145 @@ void drm_dev_printk(const struct device *dev, const 
> > char *level,
> >                    level, __builtin_return_address(0), &vaf);
> >  
> >     va_end(args);
> > +
> > +   va_start(args, format);
> > +   trace_drm_log(level, dev, &vaf);
> > +   va_end(args);
> >  }
> >  EXPORT_SYMBOL(drm_dev_printk);
> >  
> > +static unsigned int drm_trace_enabled(unsigned int category)
> > +{
> > +   unsigned int bit;
> > +
> > +   for_each_set_bit(bit, (unsigned long*)&category, sizeof(category) * 8) {
> 
> You'll want to use BITS_PER_TYPE().
> 
> But wait, I've switched category to an enum upstream, and there should
> only ever be one bit set anyway?
> 
> > +           switch (BIT(bit)) {
> > +           case DRM_UT_NONE:
> > +                   return trace_drm_dbg_none_enabled();
> > +           case DRM_UT_CORE:
> > +                   return trace_drm_dbg_core_enabled();
> > +           case DRM_UT_DRIVER:
> > +                   return trace_drm_dbg_driver_enabled();
> > +           case DRM_UT_KMS:
> > +                   return trace_drm_dbg_kms_enabled();
> > +           case DRM_UT_PRIME:
> > +                   return trace_drm_dbg_prime_enabled();
> > +           case DRM_UT_ATOMIC:
> > +                   return trace_drm_dbg_atomic_enabled();
> > +           case DRM_UT_VBL:
> > +                   return trace_drm_dbg_vbl_enabled();
> > +           case DRM_UT_STATE:
> > +                   return trace_drm_dbg_state_enabled();
> > +           case DRM_UT_LEASE:
> > +                   return trace_drm_dbg_lease_enabled();
> > +           case DRM_UT_DP:
> > +                   return trace_drm_dbg_dp_enabled();
> > +           default:
> > +                   return trace_drm_dbg_unknown_enabled();
> > +           }
> > +   }
> > +   return false;
> > +}
> > +
> > +static void drm_do_trace(const struct device *dev, unsigned int category,
> > +                    struct va_format *vaf)
> > +{
> > +   WARN_ON(hweight32(category) > 1);
> > +
> > +   switch (category) {
> > +   case DRM_UT_NONE:
> > +           trace_drm_dbg_none(dev, vaf);
> > +           break;
> > +   case DRM_UT_CORE:
> > +           trace_drm_dbg_core(dev, vaf);
> > +           break;
> > +   case DRM_UT_DRIVER:
> > +           trace_drm_dbg_driver(dev, vaf);
> > +           break;
> > +   case DRM_UT_KMS:
> > +           trace_drm_dbg_kms(dev, vaf);
> > +           break;
> > +   case DRM_UT_PRIME:
> > +           trace_drm_dbg_prime(dev, vaf);
> > +           break;
> > +   case DRM_UT_ATOMIC:
> > +           trace_drm_dbg_atomic(dev, vaf);
> > +           break;
> > +   case DRM_UT_VBL:
> > +           trace_drm_dbg_vbl(dev, vaf);
> > +           break;
> > +   case DRM_UT_STATE:
> > +           trace_drm_dbg_state(dev, vaf);
> > +           break;
> > +   case DRM_UT_LEASE:
> > +           trace_drm_dbg_lease(dev, vaf);
> > +           break;
> > +   case DRM_UT_DP:
> > +           trace_drm_dbg_dp(dev, vaf);
> > +           break;
> > +   default:
> > +           trace_drm_dbg_unknown(dev, vaf);
> > +           break;
> > +   }
> > +}
> > +
> >  void drm_dev_dbg(const struct device *dev, unsigned int category,
> >              const char *format, ...)
> >  {
> >     struct va_format vaf;
> > +   unsigned int bit;
> >     va_list args;
> >  
> > -   if (!drm_debug_enabled(category))
> > -           return;
> > -
> > -   va_start(args, format);
> >     vaf.fmt = format;
> >     vaf.va = &args;
> >  
> > -   if (dev)
> > -           dev_printk(KERN_DEBUG, dev, "[" DRM_NAME ":%ps] %pV",
> > -                      __builtin_return_address(0), &vaf);
> > -   else
> > -           printk(KERN_DEBUG "[" DRM_NAME ":%ps] %pV",
> > -                  __builtin_return_address(0), &vaf);
> > +   if (drm_debug_enabled(category)) {
> 
> Ville wants to move this check outside of the functions in the macro
> level in the header file. Apparently it's pretty bad for performance on
> some (older Atom) machines to do the call for nothing.

I've been meaning to measure if this actually matters. But haven't
managed to motivate myself enough. Could be a good project for
some random person to write a test that just does tons of different
kinds of atomic TEST_ONLY commits to measure how badly we suck.

-- 
Ville Syrjälä
Intel
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to