<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Mon, Jul 7, 2014 at 2:34 PM, Daniel Vetter <span dir="ltr"><<a href="mailto:daniel@ffwll.ch" target="_blank">daniel@ffwll.ch</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">On Fri, Jul 04, 2014 at 11:50:32AM -0300, Paulo Zanoni wrote:<br>
> From: Paulo Zanoni <<a href="mailto:paulo.r.zanoni@intel.com">paulo.r.zanoni@intel.com</a>><br>
><br>
> The current code only runs when we do an I915_WRITE operation. It<br>
> checks if the unclaimed register flag is set before we do the<br>
> operation, and then it checks it again after we do the operation. This<br>
> double check allows us to find out if the I915_WRITE operation in<br>
> question is the bad one, or if some previous code is the bad one. When<br>
> it finds a problem, our code uses DRM_ERROR to signal it.<br>
><br>
> The good thing about the current code is that it detects the problem,<br>
> so at least we can know we did something wrong. The problem is that<br>
> even though we find the problem, we don't really have much information<br>
> to actually debug it. So whenever I see one of these DRM_ERROR<br>
> messages on my systems, the first thing I do is apply a patch to<br>
> change the DRM_ERROR to a WARN and also check for unclaimed registers<br>
> on I915_READ operations. This local patch makes things even slower,<br>
> but it usually helps a lot in finding the bad code.<br>
><br>
> The first point here is that since the current code is only useful to<br>
> detect whether we have a problem or not, but it is not really good to<br>
> find the cause of the problem, I don't think we should be checking<br>
> both before and after every I915_WRITE operation: just doing the check<br>
> once should be enough for us to quickly detect problems. With this<br>
> change, the code that runs by default for every single user will only<br>
> do 1 read operation for every single I915_WRITE, instead of 2. This<br>
> patch does this change.<br>
><br>
> The second point is that the local patch I have should be upstream,<br>
> but since it makes things slower it should be disabled by default. So<br>
> I added the i915.mmio_debug option to enable it.<br>
><br>
> So after this patch, this is what will happen:<br>
>  - By default, we will try to detect unclaimed registers once after<br>
>    every I915_WRITE operation. Previously we tried twice for every<br>
>    I915_WRITE.<br>
>  - When we find an unclaimed register we will still print a DRM_ERROR<br>
>    message, but we will now tell the user to try again with<br>
>    i915.mmio_debug=1.<br>
>  - When we use i915.mmio_debug=1 we will try to find unclaimed<br>
>    registers both before and after every I915_READ and I915_WRITE<br>
>    operation, and we will print stack traces in case we find them.<br>
>    This should really help locating the exact point of the bad code<br>
>    (or at least finding out that i915.ko is not the problem).<br>
><br>
> This commit also opens space for really-slow register debugging<br>
> operations on other platforms. In theory we can now add lots and lots<br>
> of debug code behind i915.mmio_debug, enable this option on our tests,<br>
> and catch more problems.<br>
><br>
> Signed-off-by: Paulo Zanoni <<a href="mailto:paulo.r.zanoni@intel.com">paulo.r.zanoni@intel.com</a>><br>
> ---<br>
>  drivers/gpu/drm/i915/i915_drv.h     |  1 +<br>
>  drivers/gpu/drm/i915/i915_params.c  |  6 ++++<br>
>  drivers/gpu/drm/i915/intel_uncore.c | 68 +++++++++++++++++++++++++++++++++----<br>
>  3 files changed, 68 insertions(+), 7 deletions(-)<br>
><br>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h<br>
> index ac06c0f..51d867f 100644<br>
> --- a/drivers/gpu/drm/i915/i915_drv.h<br>
> +++ b/drivers/gpu/drm/i915/i915_drv.h<br>
> @@ -2092,6 +2092,7 @@ struct i915_params {<br>
>       bool disable_display;<br>
>       bool disable_vtd_wa;<br>
>       int use_mmio_flip;<br>
> +     bool mmio_debug;<br>
>  };<br>
>  extern struct i915_params i915 __read_mostly;<br>
><br>
> diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c<br>
> index 8145729..7977872 100644<br>
> --- a/drivers/gpu/drm/i915/i915_params.c<br>
> +++ b/drivers/gpu/drm/i915/i915_params.c<br>
> @@ -49,6 +49,7 @@ struct i915_params i915 __read_mostly = {<br>
>       .enable_cmd_parser = 1,<br>
>       .disable_vtd_wa = 0,<br>
>       .use_mmio_flip = 0,<br>
> +     .mmio_debug = 0,<br>
>  };<br>
><br>
>  module_param_named(modeset, i915.modeset, int, 0400);<br>
> @@ -161,3 +162,8 @@ MODULE_PARM_DESC(enable_cmd_parser,<br>
>  module_param_named(use_mmio_flip, i915.use_mmio_flip, int, 0600);<br>
>  MODULE_PARM_DESC(use_mmio_flip,<br>
>                "use MMIO flips (-1=never, 0=driver discretion [default], 1=always)");<br>
> +<br>
> +module_param_named(mmio_debug, i915.mmio_debug, bool, 0600);<br>
> +MODULE_PARM_DESC(disable_vtd_wa,<br></div></div></blockquote><div><br></div><div>wrong parameter here!</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="HOEnZb"><div class="h5">
> +     "Enable the MMIO debug code (default: false). This may negatively "<br>
> +     "affect performance.");<br>
> diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c<br>
> index 29145df..de5402f 100644<br>
> --- a/drivers/gpu/drm/i915/intel_uncore.c<br>
> +++ b/drivers/gpu/drm/i915/intel_uncore.c<br>
> @@ -513,21 +513,72 @@ ilk_dummy_write(struct drm_i915_private *dev_priv)<br>
>       __raw_i915_write32(dev_priv, MI_MODE, 0);<br>
>  }<br>
><br>
> +/**<br>
> + * hsw_unclaimed_reg_debug - tries to find unclaimed registers<br>
> + * @dev_priv: device private data<br>
> + * @reg: register we're about to touch or just have touched<br>
> + * @read: are we reading or writing a register now?<br>
> + * @before: are we running this before or after we touch the register?<br>
> + *<br>
> + * This function tries to detect unclaimed registers and provide as much<br>
> + * information as possible. It will only do something if the i915.mmio_debug<br>
> + * option is enabled.<br>
> + *<br>
> + * If we detect an unclaimed register when @before is true, it means some<br>
> + * unknown code wrote to an unclaimed register, and we're just detecting it now.<br>
> + * The bad code can be i915.ko, some other Kernel module (e.g., snd_hda_intel,<br>
> + * vgacon) or even user space. If we detect it when @before is false, then<br>
> + * there's a really good chance that the read/write operation we just did to<br>
> + * @reg is what triggered the unclaimed register message, but there's also the<br>
> + * possibility that after the operation we did, and before this function,<br>
> + * something else touched another unclaimed register, and we are detecting it<br>
> + * now.<br>
> + *<br>
> + * The unclaimed register bit can get set when we touch a register that does not<br>
> + * exist and when we touch a register that exists but is powered down. Please<br>
> + * also notice that the HW can only check some register ranges, so there's no<br>
> + * guarantee that all read and write operations to inexistent registers will be<br>
> + * caught by this function.<br>
> + *<br>
> + * Also please notice that we don't run this function on __raw operations and in<br>
> + * many other cases, so the case where @before is true is quite common.<br>
> + */<br>
<br>
</div></div>Pet peeve of mine: Comments have a cost since they get stale really fast<br>
and then can be awfully misleading. We have way too many examples for<br>
that. My rule of interface kerneldoc for functions is that we should only<br>
have it for exported functions used in multiple different places in the<br>
driver. If there's only one caller (like for _init/fini) functions the<br>
comment should be very terse at most.<br>
<br>
For static inline helpers in the same file otoh code should simply be<br>
readable enough to not require comments. Imo this is the case here, so the<br>
kerneldoc should imo be dropped.<br>
<br>
If you want to keep some of it I guess we could document i915.mmio_debug<br>
with kerneldoc and then also pull it into our i915 section in the drm<br>
docbook. Maybe under a new "debug options" setting. We probably need a<br>
DOC: section to make this work. A few sentences should be more than<br>
enough.<br>
<div><div class="h5"><br>
>  static void<br>
> -hsw_unclaimed_reg_clear(struct drm_i915_private *dev_priv, u32 reg)<br>
> +hsw_unclaimed_reg_debug(struct drm_i915_private *dev_priv, u32 reg, bool read,<br>
> +                     bool before)<br>
>  {<br>
> +     const char *op = read ? "reading" : "writing to";<br>
> +     const char *when = before ? "before" : "after";<br>
> +<br>
> +     if (!i915.mmio_debug)<br>
> +             return;<br>
> +<br>
>       if (__raw_i915_read32(dev_priv, FPGA_DBG) & FPGA_DBG_RM_NOCLAIM) {<br>
> -             DRM_ERROR("Unknown unclaimed register before writing to %x\n",<br>
> -                       reg);<br>
> +             WARN(1, "Unclaimed register detected %s %s register 0x%x\n",<br>
> +                  when, op, reg);<br>
>               __raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM);<br>
>       }<br>
>  }<br>
><br>
> +/**<br>
> + * hsw_unclaimed_reg_detect - tries to find unclaimed registers<br>
> + * @dev_priv: device private data<br>
> + *<br>
> + * This function will try to detect if something touched and unclaimed register,<br>
> + * triggering the FPGA_DBG bit. If this happens, we will print a message telling<br>
> + * the user to use i915.mmio_debug=1 so we can properly debug the problem.<br>
> + *<br>
> + * This way, we can still detect our bugs without giving the user the<br>
> + * performance impact of hsw_unclaimed_reg_debug().<br>
> + */<br>
>  static void<br>
> -hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg)<br>
> +hsw_unclaimed_reg_detect(struct drm_i915_private *dev_priv)<br>
>  {<br>
> +     if (i915.mmio_debug)<br>
> +             return;<br>
> +<br>
>       if (__raw_i915_read32(dev_priv, FPGA_DBG) & FPGA_DBG_RM_NOCLAIM) {<br>
> -             DRM_ERROR("Unclaimed write to %x\n", reg);<br>
> +             DRM_ERROR("Unclaimed register detected. Please use the i915.mmio_debug=1 to debug this problem.");<br>
<br>
</div></div>But imo really the only piece that's required is this helpful message here<br>
into dmesg.<br>
<br>
Anyway, the concept looks solid.<br>
-Daniel<br>
<div class="HOEnZb"><div class="h5"><br>
>               __raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM);<br>
>       }<br>
>  }<br>
> @@ -564,6 +615,7 @@ gen5_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \<br>
>  static u##x \<br>
>  gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \<br>
>       REG_READ_HEADER(x); \<br>
> +     hsw_unclaimed_reg_debug(dev_priv, reg, true, true); \<br>
>       if (dev_priv->uncore.forcewake_count == 0 && \<br>
>           NEEDS_FORCE_WAKE((dev_priv), (reg))) { \<br>
>               dev_priv->uncore.funcs.force_wake_get(dev_priv, \<br>
> @@ -574,6 +626,7 @@ gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \<br>
>       } else { \<br>
>               val = __raw_i915_read##x(dev_priv, reg); \<br>
>       } \<br>
> +     hsw_unclaimed_reg_debug(dev_priv, reg, true, false); \<br>
>       REG_READ_FOOTER; \<br>
>  }<br>
><br>
> @@ -700,12 +753,13 @@ hsw_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace)<br>
>       if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \<br>
>               __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \<br>
>       } \<br>
> -     hsw_unclaimed_reg_clear(dev_priv, reg); \<br>
> +     hsw_unclaimed_reg_debug(dev_priv, reg, false, true); \<br>
>       __raw_i915_write##x(dev_priv, reg, val); \<br>
>       if (unlikely(__fifo_ret)) { \<br>
>               gen6_gt_check_fifodbg(dev_priv); \<br>
>       } \<br>
> -     hsw_unclaimed_reg_check(dev_priv, reg); \<br>
> +     hsw_unclaimed_reg_debug(dev_priv, reg, false, false); \<br>
> +     hsw_unclaimed_reg_detect(dev_priv); \<br>
>       REG_WRITE_FOOTER; \<br>
>  }<br>
><br>
> --<br>
> 2.0.0<br>
><br>
> _______________________________________________<br>
> Intel-gfx mailing list<br>
> <a href="mailto:Intel-gfx@lists.freedesktop.org">Intel-gfx@lists.freedesktop.org</a><br>
> <a href="http://lists.freedesktop.org/mailman/listinfo/intel-gfx" target="_blank">http://lists.freedesktop.org/mailman/listinfo/intel-gfx</a><br>
<br>
</div></div><span class="HOEnZb"><font color="#888888">--<br>
Daniel Vetter<br>
Software Engineer, Intel Corporation<br>
<a href="tel:%2B41%20%280%29%2079%20365%2057%2048" value="+41793655748">+41 (0) 79 365 57 48</a> - <a href="http://blog.ffwll.ch" target="_blank">http://blog.ffwll.ch</a><br>
</font></span><div class="HOEnZb"><div class="h5">_______________________________________________<br>
Intel-gfx mailing list<br>
<a href="mailto:Intel-gfx@lists.freedesktop.org">Intel-gfx@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/intel-gfx" target="_blank">http://lists.freedesktop.org/mailman/listinfo/intel-gfx</a><br>
</div></div></blockquote></div><br>The rest looks good. With that fixed and probably with comment removed as Daniel mentioned, feel free to use:</div><div class="gmail_extra">Reviewed-by: Rodrigo Vivi <<a href="mailto:rodrigo.vivi@gmail.com">rodrigo.vivi@gmail.com</a>><br clear="all">
<div><br></div>-- <br><div>Rodrigo Vivi</div><div>Blog: <a href="http://blog.vivi.eng.br" target="_blank">http://blog.vivi.eng.br</a></div><div> </div>
</div></div>