From patchwork Fri Jun 3 19:20:21 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Anholt X-Patchwork-Id: 848122 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter2.kernel.org (8.14.4/8.14.3) with ESMTP id p53JMYUc011758 for ; Fri, 3 Jun 2011 19:22:54 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 860969E740 for ; Fri, 3 Jun 2011 12:22:34 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from annarchy.freedesktop.org (annarchy.freedesktop.org [131.252.210.176]) by gabe.freedesktop.org (Postfix) with ESMTP id DB84C9E78F; Fri, 3 Jun 2011 12:20:26 -0700 (PDT) Received: from pollan.anholt.net (annarchy.freedesktop.org [127.0.0.1]) by annarchy.freedesktop.org (Postfix) with ESMTP id 6DE4B130056; Fri, 3 Jun 2011 12:20:26 -0700 (PDT) Received: by pollan.anholt.net (Postfix, from userid 1000) id ECEB54017B3; Fri, 3 Jun 2011 12:20:23 -0700 (PDT) From: Eric Anholt To: intel-gfx@lists.freedesktop.org Date: Fri, 3 Jun 2011 12:20:21 -0700 Message-Id: <1307128822-9709-4-git-send-email-eric@anholt.net> X-Mailer: git-send-email 1.7.5.1 In-Reply-To: <1307128822-9709-1-git-send-email-eric@anholt.net> References: <1307128822-9709-1-git-send-email-eric@anholt.net> Subject: [Intel-gfx] [PATCH 3/4] drm/i915: Fix missed IRQs on gen6. X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.11 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter2.kernel.org [140.211.167.43]); Fri, 03 Jun 2011 19:22:54 +0000 (UTC) Our wait-on-interrupts path goes: I915_WRITE(IMR, enabled_val) POSTING_READ(IMR); if (!i915_gem_seqno_passed()) sleep(); However, the IMR write can still be queued in the GT FIFO even after the POSTING_READ, since the GT FIFO isn't implementing PCI semantics. Yay. So, when we're doing a POSTING_READ, we get to check that the FIFO is empty, and unfortunately to check that the FIFO is empty, it appears we have to do the FORCEWAKE dance. Previously, piglit copypixels-sync test had about a 0.5% chance of triggering a missed IRQ (meaning I've never seen 500 successful runs without a failure). With this pair of patches, I'm at 5700 clean runs as I type this. Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.c | 41 +++++++++++++++++++++++++++++++++++++- drivers/gpu/drm/i915/i915_drv.h | 3 +- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 0c46bfc..eabf82c 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -304,7 +304,10 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) udelay(10); I915_WRITE_NOTRACE(FORCEWAKE, 1); - POSTING_READ(FORCEWAKE); + /* This is a posting read, but the POSTING_READ macro calls + * this function. + */ + (void)I915_READ_NOTRACE(FORCEWAKE); count = 0; while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1) == 0) @@ -332,7 +335,10 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) { I915_WRITE_NOTRACE(FORCEWAKE, 0); - POSTING_READ(FORCEWAKE); + /* This is a posting read, but the POSTING_READ macro calls + * this function. + */ + (void)I915_READ_NOTRACE(FORCEWAKE); } /* @@ -360,6 +366,37 @@ void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) } } +/* In PCI, writes are not guaranteed to reach the device until a read + * from the device has occurred. The POSTING_READ macro is used to + * indicate when we are doing one of those reads to force writes to + * the device, so that we can for example test a value in some cached + * memory and go to sleep waiting for an interrupt + * (i915_wait_request()) or implement some timing requirement. + * + * However, as of gen6, a mere PCI write posting read doesn't mean + * that the writes have reached the device, as they get queued in a + * FIFO to hide the wake-from-rc6 latency, even if the chip wasn't in + * RC6 at the time. For gen6, we also have to wait for the fifo to + * drain, which means force-waking the GPU so that we can read the + * fifo count. + */ +void +intel_posting_read(struct drm_i915_private *dev_priv, uint32_t reg) +{ + int ret; + + if (dev_priv->info->gen < 6) { + (void)I915_READ_NOTRACE(reg); + return; + } + + gen6_gt_force_wake_get(dev_priv); + ret = wait_for(I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES) == 0x3f, 500); + gen6_gt_force_wake_put(dev_priv); + + WARN_ON_ONCE(ret != 0); +} + static int i915_drm_freeze(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 56ef324..a064044 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1366,6 +1366,7 @@ extern void intel_display_print_error_state(struct seq_file *m, void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv); void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv); void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv); +void intel_posting_read(struct drm_i915_private *dev_priv, uint32_t reg); /* We give fast paths for the really cool registers */ #define NEEDS_FORCE_WAKE(dev_priv, reg) \ @@ -1423,7 +1424,7 @@ __i915_write(64, q) #define I915_WRITE64(reg, val) i915_write64(dev_priv, (reg), (val)) #define I915_READ64(reg) i915_read64(dev_priv, (reg)) -#define POSTING_READ(reg) (void)I915_READ_NOTRACE(reg) +#define POSTING_READ(reg) intel_posting_read(dev_priv, reg) #define POSTING_READ16(reg) (void)I915_READ16_NOTRACE(reg)