From patchwork Thu Jan 10 02:23:37 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 1958381 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork2.kernel.org (Postfix) with ESMTP id AEAB5DF2EB for ; Thu, 10 Jan 2013 02:25:16 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 69EA9E6000 for ; Wed, 9 Jan 2013 18:25:16 -0800 (PST) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (smtp.fireflyinternet.com [109.228.6.236]) by gabe.freedesktop.org (Postfix) with ESMTP id 582C8E5C4F for ; Wed, 9 Jan 2013 18:25:05 -0800 (PST) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.73.22; Received: from arrandale.alporthouse.com (unverified [78.156.73.22]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 127735976-1500050 for multiple; Thu, 10 Jan 2013 02:24:49 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Thu, 10 Jan 2013 02:23:37 +0000 Message-Id: <1357784617-18956-1-git-send-email-chris@chris-wilson.co.uk> X-Mailer: git-send-email 1.7.10.4 X-Originating-IP: 78.156.73.22 Cc: Daniel Vetter , Ben Widawsky Subject: [Intel-gfx] [PATCH] drm/i915: Resurrect ring kicking for semaphores, selectively X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.13 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 Once we thought we got semaphores working, we disabled kicking the ring if hangcheck fired whilst waiting upon a ring as it was doing more harm than good: commit 4e0e90dcb8a7df1229c69e30abebb59b0b3c2a1f Author: Daniel Vetter Date: Wed Dec 14 13:56:58 2011 +0100 drm/i915: kicking rings stuck on semaphores considered harmful However, life is never that easy and semaphores are still causing problems whereby the value written by one ring (bcs) is not being propagated to the waiter (rcs). Thus the waiter never wakes up and we declare the GPU hung, which often has unfortunate consequences, even if we successfully reset the GPU. But the GPU is idle as it has completed the work, just didn't notify its clients. So we can detect the incomplete wait during hang check and probe the target ring to see if has indeed emitted the breadcrumb seqno following the work and then and only then kick the waiter. Based on a suggestion by Ben Widawsky. References: https://bugs.freedesktop.org/show_bug.cgi?id=54226 Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Ben Widawsky Acked-by: Ben Widawsky --- drivers/gpu/drm/i915/i915_irq.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 39e4177..3cc52b2 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1693,6 +1693,32 @@ static bool i915_hangcheck_ring_idle(struct intel_ring_buffer *ring, bool *err) return false; } +static bool semaphore_passed(struct intel_ring_buffer *waiter) +{ + struct drm_i915_private *dev_priv = waiter->dev->dev_private; + int acthd = intel_ring_get_active_head(waiter) & HEAD_ADDR; + struct intel_ring_buffer *signaller; + u32 cmd; + + /* ACTHD is likely pointing to the dword after the actual command, + * so scan backwards until we find the MBOX. + */ +#define WAIT (MI_SEMAPHORE_MBOX | MI_SEMAPHORE_COMPARE | MI_SEMAPHORE_REGISTER) + do { + cmd = ioread32(waiter->virtual_start+acthd); + if ((cmd & ~(0x3 << 16)) == WAIT) + break; + acthd -= 4; + if (acthd < 0) + return false; + } while (1); +#undef WAIT + + signaller = &dev_priv->ring[(waiter->id + (((cmd >> 16) & 3) - 1)) % 3]; + return i915_seqno_passed(signaller->get_seqno(signaller, false), + ioread32(waiter->virtual_start+acthd+4)+1); +} + static bool kick_ring(struct intel_ring_buffer *ring) { struct drm_device *dev = ring->dev; @@ -1704,6 +1730,14 @@ static bool kick_ring(struct intel_ring_buffer *ring) I915_WRITE_CTL(ring, tmp); return true; } + if (INTEL_INFO(dev)->gen >= 6 && + tmp & RING_WAIT_SEMAPHORE && + semaphore_passed(ring)) { + DRM_ERROR("Kicking stuck semaphore on %s\n", + ring->name); + I915_WRITE_CTL(ring, tmp); + return true; + } return false; }