[Intel-gfx] [PATCH 3/3] drm/i915: touch VGA MSR after we enable the power well

Damien Lespiau damien.lespiau at intel.com
Thu Dec 12 12:36:09 CET 2013


On Wed, Dec 11, 2013 at 06:50:10PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni at intel.com>
> 
> Fixes regression introduced by:
>     commit bf51d5e2cda5d36d98e4b46ac7fca9461e512c41
>     Author: Paulo Zanoni <paulo.r.zanoni at intel.com>
>     Date:   Wed Jul 3 17:12:13 2013 -0300
>         drm/i915: switch disable_power_well default value to 1
> 
> The bug I'm seeing can be reproduced with:
>   - Have vgacon configured/enabled
>   - Make sure the power well gets disabled, then enabled. You can
>     check this by seeing the messages print by hsw_set_power_well
>   - Stop your display manager
>   - echo 0 > /sys/class/vtconsole/vtcon1/bind
> 
> I can easily reproduce this by blacklising snd_hda_intel and booting
> with eDP+HDMI.
> 
> If you do this and then look at dmesg, you'll see we're printing
> infinite "Unclaimed register" messages. This is happening because
> we're stuck on an infinite loop inside console_unlock(), which is
> calling many functions from vgacon.c. And the code that's triggering
> the error messages is from vgacon_set_cursor_size().
> 
> After we re-enable the power well, every time we read/write the VGA
> address 0x3d5 we get an "unclaimed register" interrupt (ERR_INT) and
> print error messages. If we write anything to the VGA MSR register (it
> doesn't really matter which value you write to bit 0), any
> reads/writes to 0x3d5 _don't_ trigger the "unclaimed register" errors
> anymore (even if MSR bit 0 is zero). So what happens with the current
> code is that when we unbind i915 and bind vgacon, we call
> console_unlock(). Function console_unlock() is responsible for
> printing any messages that were supposed to be print when the console
> was locked, so it calls the TTY layer, which calls the console layer,
> which calls vgacon to print the messages. At this point, vgacon
> eventually calls vgacon_set_cursor_size(), which touches 0x3d5, which
> triggers unclaimed register interrupts. The problem is that when we
> get these interrupts, we print the error messages, so we add more work
> to console_unlock(), which will try to print it again, and then call
> vgacon again, trigger a new interrupt, which will put more stuff to
> the buffer, and then we'll be stuck at console_unlock() forever.
> 
> If you patch intel_uncore.c to not print anything when we detect
> unclaimed registers, we won't get into the console_unlock() infinite
> loop and the driver unbind will work just fine. We will still be
> getting interrupts every time vgacon touches those registers, but we
> will survive. This is a valid experiment, but IMHO it's not the real
> fix: if we don't print any error messages we will still keep getting
> the interrupts, and if we disable ERR_INT we won't get the interrupt
> anymore, but we will also stop getting all the other error interrupts.
> 
> I talked about this problem with the HW engineer and his
> recommendation is "So don't do any VGA I/O or memory access while the
> power well is disabled, and make to re-program MSR after enabling the
> power well and before using VGA I/O or memory accesses.".
> 
> Notice that this is just a partial fix to fd.o #67813. This fixes the
> case where the power well is already enabled when we unbind, not when
> it's disabled when we unbind.
> 
> V2: - Rebase (first version was sent in September).
> V3: - Complete rewrite of the same fix: smaller implementation,
>       improved commit message.
> 
> Testcase: igt/drv_module_reload
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=67813
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni at intel.com>

The commit message is convincing!

Reviewed-by: Damien Lespiau <damien.lespiau at intel.com>

-- 
Damien

> ---
>  drivers/gpu/drm/i915/intel_pm.c | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index ce2a188..6695c1d 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -30,6 +30,7 @@
>  #include "intel_drv.h"
>  #include "../../../platform/x86/intel_ips.h"
>  #include <linux/module.h>
> +#include <linux/vgaarb.h>
>  #include <drm/i915_powerwell.h>
>  #include <linux/pm_runtime.h>
>  
> @@ -5687,6 +5688,20 @@ static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv)
>  	struct drm_device *dev = dev_priv->dev;
>  	unsigned long irqflags;
>  
> +	/*
> +	 * After we re-enable the power well, if we touch VGA register 0x3d5
> +	 * we'll get unclaimed register interrupts. This stops after we write
> +	 * anything to the VGA MSR register. The vgacon module uses this
> +	 * register all the time, so if we unbind our driver and, as a
> +	 * consequence, bind vgacon, we'll get stuck in an infinite loop at
> +	 * console_unlock(). So make here we touch the VGA MSR register, making
> +	 * sure vgacon can keep working normally without triggering interrupts
> +	 * and error messages.
> +	 */
> +	vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO);
> +	outb(inb(VGA_MSR_READ), VGA_MSR_WRITE);
> +	vga_put(dev->pdev, VGA_RSRC_LEGACY_IO);
> +
>  	if (IS_BROADWELL(dev)) {
>  		spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
>  		I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_B),
> -- 
> 1.8.3.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



More information about the Intel-gfx mailing list