From patchwork Tue Nov 22 17:47:01 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robert Hooker X-Patchwork-Id: 127141 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 2AACAB70C7 for ; Wed, 23 Nov 2011 04:48:25 +1100 (EST) Received: from localhost ([127.0.0.1] helo=chlorine.canonical.com) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1RSuSA-0005jm-8Q; Tue, 22 Nov 2011 17:48:18 +0000 Received: from mail-vw0-f49.google.com ([209.85.212.49]) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1RSuS8-0005bX-00 for kernel-team@lists.ubuntu.com; Tue, 22 Nov 2011 17:48:16 +0000 Received: by vbbfs19 with SMTP id fs19so561672vbb.8 for ; Tue, 22 Nov 2011 09:48:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=sender:from:to:subject:date:message-id:x-mailer; bh=3P+GIkco4mFhvA0rdcQYLgubNOtxigvNvooQvJwJpAc=; b=S0MW8AJiBIPeLs/ws2h4kmXbnFXd5I/u0sPkv8YfIAUJK+BLkog300bbWuiwOWsTz6 9G81izC82YPK5YSC4saiLg+oY2hMCFWVypb5FuMNv/Pb0doHYXGT/bbHWWX/ZMMDHq8q jOd8/d3nEhITSctDVM1RRE5rMjCbftJS5wzzg= Received: by 10.52.16.243 with SMTP id j19mr21604901vdd.109.1321984094161; Tue, 22 Nov 2011 09:48:14 -0800 (PST) Received: from localhost.localdomain (c-68-34-39-96.hsd1.va.comcast.net. [68.34.39.96]) by mx.google.com with ESMTPS id z3sm4428713vdg.16.2011.11.22.09.48.07 (version=SSLv3 cipher=OTHER); Tue, 22 Nov 2011 09:48:09 -0800 (PST) From: Robert Hooker To: kernel-team@lists.ubuntu.com Subject: [PATCH v2] drm/i915: add multi-threaded forcewake support Date: Tue, 22 Nov 2011 12:47:01 -0500 Message-Id: <1321984021-27556-1-git-send-email-sarvatt@ubuntu.com> X-Mailer: git-send-email 1.7.5.4 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.13 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: kernel-team-bounces@lists.ubuntu.com Errors-To: kernel-team-bounces@lists.ubuntu.com From: Keith Packard On IVB C0+ with newer BIOSes, the forcewake handshake has changed. There's now a bitfield for different driver components to keep the GT powered on. On Linux, we centralize forcewake handling in one place, so we still just need a single bit, but we need to use the new registers if MT forcewake is enabled. This needs testing on affected machines. Please reply with your tested-by if you had problems after a BIOS upgrade and this patch fixes them. v2: force MT mode. shift by 16 v3: set MT force wake bits then check ECOBUS This patch was submitted to intel-gfx by upstream and has not yet made it to the linus tree, the patch was backported to Oneiric, and tested on ivybridge system. BugLink: http://bugs.launchpad.net/bugs/891270 Tested-by: Keith Packard Signed-off-by: Jesse Barnes Signed-off-by: Keith Packard Backported to 3.0 Signed-off-by: Robert Hooker Signed-off-by: Manoj Iyer --- drivers/gpu/drm/i915/i915_drv.c | 30 ++++++++++++++++++++++++++---- drivers/gpu/drm/i915/i915_drv.h | 13 +++++++++++-- drivers/gpu/drm/i915/i915_reg.h | 4 ++++ drivers/gpu/drm/i915/intel_display.c | 22 ++++++++++++++++++++++ 4 files changed, 63 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index eb91e2d..0b1a752 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -295,7 +295,7 @@ void intel_detect_pch (struct drm_device *dev) } } -static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) +void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) { int count; @@ -311,6 +311,22 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) udelay(10); } +void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) +{ + int count; + + count = 0; + while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1)) + udelay(10); + + I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 1); + POSTING_READ(FORCEWAKE_MT); + + count = 0; + while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1) == 0) + udelay(10); +} + /* * Generally this is called implicitly by the register read function. However, * if some sequence requires the GT to not power down then this function should @@ -323,15 +339,21 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) /* Forcewake is atomic in case we get in here without the lock */ if (atomic_add_return(1, &dev_priv->forcewake_count) == 1) - __gen6_gt_force_wake_get(dev_priv); + dev_priv->display.force_wake_get(dev_priv); } -static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) +void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) { I915_WRITE_NOTRACE(FORCEWAKE, 0); POSTING_READ(FORCEWAKE); } +void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) +{ + I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 0); + POSTING_READ(FORCEWAKE_MT); +} + /* * see gen6_gt_force_wake_get() */ @@ -340,7 +362,7 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); if (atomic_dec_and_test(&dev_priv->forcewake_count)) - __gen6_gt_force_wake_put(dev_priv); + dev_priv->display.force_wake_put(dev_priv); } void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1c44613..dc1f499 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -107,6 +107,7 @@ struct opregion_header; struct opregion_acpi; struct opregion_swsci; struct opregion_asle; +struct drm_i915_private; struct intel_opregion { struct opregion_header *header; @@ -215,6 +216,8 @@ struct drm_i915_display_funcs { int (*queue_flip)(struct drm_device *dev, struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_i915_gem_object *obj); + void (*force_wake_get)(struct drm_i915_private *dev_priv); + void (*force_wake_put)(struct drm_i915_private *dev_priv); /* clock updates for mode set */ /* cursor updates */ /* render clock increase/decrease */ @@ -1299,6 +1302,11 @@ extern void gen6_set_rps(struct drm_device *dev, u8 val); extern void intel_detect_pch (struct drm_device *dev); extern int intel_trans_dp_port_sel (struct drm_crtc *crtc); +extern void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv); +extern void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv); +extern void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv); +extern void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv); + /* overlay */ #ifdef CONFIG_DEBUG_FS extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev); @@ -1343,8 +1351,9 @@ void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv); /* We give fast paths for the really cool registers */ #define NEEDS_FORCE_WAKE(dev_priv, reg) \ (((dev_priv)->info->gen >= 6) && \ - ((reg) < 0x40000) && \ - ((reg) != FORCEWAKE)) + ((reg) < 0x40000) && \ + ((reg) != FORCEWAKE) && \ + ((reg) != ECOBUS)) #define __i915_read(x, y) \ static inline u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 500e734..414d86d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3371,6 +3371,10 @@ #define FORCEWAKE 0xA18C #define FORCEWAKE_ACK 0x130090 +#define FORCEWAKE_MT 0xa188 /* multi-threaded */ +#define FORCEWAKE_MT_ACK 0x130040 +#define ECOBUS 0xa180 +#define FORCEWAKE_MT_ENABLE (1<<5) #define GT_FIFO_FREE_ENTRIES 0x120008 diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9fd9421..5d118ff 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7721,6 +7721,28 @@ static void intel_init_display(struct drm_device *dev) /* For FIFO watermark updates */ if (HAS_PCH_SPLIT(dev)) { + dev_priv->display.force_wake_get = __gen6_gt_force_wake_get; + dev_priv->display.force_wake_put = __gen6_gt_force_wake_put; + + /* IVB configs may use multi-threaded forcewake */ + if (IS_IVYBRIDGE(dev)) { + u32 ecobus; + + mutex_lock(&dev->struct_mutex); + __gen6_gt_force_wake_mt_get(dev_priv); + ecobus = I915_READ(ECOBUS); + __gen6_gt_force_wake_mt_put(dev_priv); + mutex_unlock(&dev->struct_mutex); + + if (ecobus & FORCEWAKE_MT_ENABLE) { + DRM_DEBUG_KMS("Using MT version of forcewake\n"); + dev_priv->display.force_wake_get = + __gen6_gt_force_wake_mt_get; + dev_priv->display.force_wake_put = + __gen6_gt_force_wake_mt_put; + } + } + if (HAS_PCH_IBX(dev)) dev_priv->display.init_pch_clock_gating = ibx_init_clock_gating; else if (HAS_PCH_CPT(dev))