diff mbox

[5/5] drm/i915: put/get the power well at the FB bind/unbind functions

Message ID 1380236762-1698-6-git-send-email-przanoni@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Paulo Zanoni Sept. 26, 2013, 11:06 p.m. UTC
From: Paulo Zanoni <paulo.r.zanoni@intel.com>

If we run the following command on Haswell when the power well is
disabled:
    echo 0 > /sys/class/vtconsole/vtcon1/bind
then we'll get thousands of consecutive interrupts because something
is trying to touch registers that are on the disabled power well. So
before we unbind the console, we need to enable the power well to make
the VGA interface work correctly. With this, whoever is using it
doesn't trigger interrupts on i915.ko.

Fixes regression introduced by:
    commit bf51d5e2cda5d36d98e4b46ac7fca9461e512c41
    Author: Paulo Zanoni <paulo.r.zanoni@intel.com>
        drm/i915: switch disable_power_well default value to 1

Besides the command above, the "module_reload" test from
intel-gpu-tools can also be used to reproduce the bug fixed by this
patch.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=67813
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_drv.h |  1 +
 drivers/gpu/drm/i915/intel_fb.c  | 23 +++++++++++++++++++++++
 2 files changed, 24 insertions(+)
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index e63646a..a643c48 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -113,6 +113,7 @@  struct intel_fbdev {
 	struct intel_framebuffer ifb;
 	struct list_head fbdev_list;
 	struct drm_display_mode *our_mode;
+	bool first_bind_done;
 };
 
 struct intel_encoder {
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index d883b77..8c6ed1c 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -43,6 +43,27 @@ 
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 
+static void intel_fb_bind(struct fb_info *info)
+{
+	struct drm_fb_helper *drm_helper = info->par;
+	struct drm_device *dev = drm_helper->dev;
+	struct intel_fbdev *ifbdev =
+		container_of(drm_helper, struct intel_fbdev, helper);
+
+	if (ifbdev->first_bind_done)
+		intel_display_power_put(dev, POWER_DOMAIN_VGA);
+	else
+		ifbdev->first_bind_done = true;
+}
+
+static void intel_fb_unbind(struct fb_info *info)
+{
+	struct drm_fb_helper *fb_helper = info->par;
+	struct drm_device *dev = fb_helper->dev;
+
+	intel_display_power_get(dev, POWER_DOMAIN_VGA);
+}
+
 static struct fb_ops intelfb_ops = {
 	.owner = THIS_MODULE,
 	.fb_check_var = drm_fb_helper_check_var,
@@ -55,6 +76,8 @@  static struct fb_ops intelfb_ops = {
 	.fb_setcmap = drm_fb_helper_setcmap,
 	.fb_debug_enter = drm_fb_helper_debug_enter,
 	.fb_debug_leave = drm_fb_helper_debug_leave,
+	.fb_bind = intel_fb_bind,
+	.fb_unbind = intel_fb_unbind,
 };
 
 static int intelfb_create(struct drm_fb_helper *helper,