From patchwork Wed Dec 9 13:02:47 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alberto Milone X-Patchwork-Id: 40722 X-Patchwork-Delegate: stefan.bader@canonical.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from chlorine.canonical.com (chlorine.canonical.com [91.189.94.204]) by ozlabs.org (Postfix) with ESMTP id E6736B6EF7 for ; Thu, 10 Dec 2009 00:03:03 +1100 (EST) Received: from localhost ([127.0.0.1] helo=chlorine.canonical.com) by chlorine.canonical.com with esmtp (Exim 4.60) (envelope-from ) id 1NIMC0-00061O-Cy; Wed, 09 Dec 2009 13:02:56 +0000 Received: from mail-fx0-f219.google.com ([209.85.220.219]) by chlorine.canonical.com with esmtp (Exim 4.60) (envelope-from ) id 1NIMBv-00061F-Nf for kernel-team@lists.ubuntu.com; Wed, 09 Dec 2009 13:02:51 +0000 Received: by fxm19 with SMTP id 19so6555022fxm.17 for ; Wed, 09 Dec 2009 05:02:51 -0800 (PST) Received: by 10.223.5.18 with SMTP id 18mr1586839fat.58.1260363771061; Wed, 09 Dec 2009 05:02:51 -0800 (PST) Received: from alberto-desktop.localnet (host28-94-dynamic.7-87-r.retail.telecomitalia.it [87.7.94.28]) by mx.google.com with ESMTPS id e17sm3151922fke.23.2009.12.09.05.02.49 (version=TLSv1/SSLv3 cipher=RC4-MD5); Wed, 09 Dec 2009 05:02:50 -0800 (PST) From: Alberto Milone To: "UBUNTU kernel-team" , Bill Filler Subject: [PATCH] [Karmic SRU] [Lucid] drm/i915: Fix sync to vblank when VGA output is turned off Date: Wed, 9 Dec 2009 14:02:47 +0100 User-Agent: KMail/1.12.2 (Linux/2.6.31-15-generic-pae; KDE/4.3.2; i686; ; ) MIME-Version: 1.0 Message-Id: <200912091402.47945.alberto.milone@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.8 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: kernel-team-bounces@lists.ubuntu.com Errors-To: kernel-team-bounces@lists.ubuntu.com Hi all, SRU Justification: The problem described in this email was reported in a private OEM bug report for Dell and has been solved by upstream. It's a regression in the drm code which causes a massive system slowdown if we turn off the VGA output. The patch is sane and minimal and is available in the drm-intel branch and in the linux-next branch (see the link to the commit in the bug report). I have applied (and slightly adapted, as it didn't apply cleanly to our lucid and karmic git branches) and tested the patch successfully in Karmic. The integration of this patch is very important for our Dell projects and for the Ubuntu desktop at large. Please include the attached patch in both Karmic and Lucid ASAP. Bug #494461 Thanks in advance for your time. Regards, Acked-by: Andy Whitcroft From 778c902640530371a169ad1c03566e7c51b09874 Mon Sep 17 00:00:00 2001 From: Li Peng Date: Mon, 9 Nov 2009 12:51:22 +0800 Subject: [PATCH 1/1] drm/i915: Fix sync to vblank when VGA output is turned off In current vblank-wait implementation, if we turn off VGA output, drm_wait_vblank will still wait on the disabled pipe until timeout, because vblank on the pipe is assumed be enabled. This would cause slow system response on some system such as moblin. This patch resolve the issue by adding a drm helper function drm_vblank_off which explicitly clear vblank_enabled[crtc], wake up any waiting queue and save last vblank counter before turning off crtc. It also slightly change drm_vblank_get to ensure that we will will return immediately if trying to wait on a disabled pipe. Signed-off-by: Li Peng Reviewed-by: Jesse Barnes [anholt: hand-applied for conflicts with overlay changes] Signed-off-by: Eric Anholt --- diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index f85aaf2..f298434 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -402,15 +402,21 @@ int drm_vblank_get(struct drm_device *dev, int crtc) spin_lock_irqsave(&dev->vbl_lock, irqflags); /* Going from 0->1 means we have to enable interrupts again */ - if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1 && - !dev->vblank_enabled[crtc]) { - ret = dev->driver->enable_vblank(dev, crtc); - DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret); - if (ret) + if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) { + if (!dev->vblank_enabled[crtc]) { + ret = dev->driver->enable_vblank(dev, crtc); + DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret); + if (ret) + atomic_dec(&dev->vblank_refcount[crtc]); + else { + dev->vblank_enabled[crtc] = 1; + drm_update_vblank_count(dev, crtc); + } + } + } else { + if (!dev->vblank_enabled[crtc]) { atomic_dec(&dev->vblank_refcount[crtc]); - else { - dev->vblank_enabled[crtc] = 1; - drm_update_vblank_count(dev, crtc); + ret = -EINVAL; } } spin_unlock_irqrestore(&dev->vbl_lock, irqflags); @@ -437,6 +443,18 @@ void drm_vblank_put(struct drm_device *dev, int crtc) } EXPORT_SYMBOL(drm_vblank_put); +void drm_vblank_off(struct drm_device *dev, int crtc) +{ + unsigned long irqflags; + + spin_lock_irqsave(&dev->vbl_lock, irqflags); + DRM_WAKEUP(&dev->vbl_queue[crtc]); + dev->vblank_enabled[crtc] = 0; + dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc); + spin_unlock_irqrestore(&dev->vbl_lock, irqflags); +} +EXPORT_SYMBOL(drm_vblank_off); + /** * drm_vblank_pre_modeset - account for vblanks across mode sets * @dev: DRM device diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 318ba47..652e9ac 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1540,6 +1540,7 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) intel_update_watermarks(dev); /* Give the overlay scaler a chance to disable if it's on this pipe */ //intel_crtc_dpms_video(crtc, FALSE); TODO + drm_vblank_off(dev, pipe); /* Disable the VGA plane that we never use */ i915_disable_vga(dev); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 45b67d9..4637dce 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1268,6 +1268,7 @@ extern u32 drm_vblank_count(struct drm_device *dev, int crtc); extern void drm_handle_vblank(struct drm_device *dev, int crtc); extern int drm_vblank_get(struct drm_device *dev, int crtc); extern void drm_vblank_put(struct drm_device *dev, int crtc); +extern void drm_vblank_off(struct drm_device *dev, int crtc); extern void drm_vblank_cleanup(struct drm_device *dev); /* Modesetting support */ extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc);