From patchwork Fri Mar 28 16:38:47 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Kuoppala X-Patchwork-Id: 3904911 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 78E749F2B6 for ; Fri, 28 Mar 2014 16:38:58 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7D39A20304 for ; Fri, 28 Mar 2014 16:38:57 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 69CCC202A7 for ; Fri, 28 Mar 2014 16:38:56 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id CF0616ED46; Fri, 28 Mar 2014 09:38:55 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by gabe.freedesktop.org (Postfix) with ESMTP id 77C4A6ED46 for ; Fri, 28 Mar 2014 09:38:54 -0700 (PDT) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga102.jf.intel.com with ESMTP; 28 Mar 2014 09:34:16 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.97,751,1389772800"; d="scan'208";a="482230577" Received: from rosetta.fi.intel.com (HELO rosetta) ([10.237.72.72]) by orsmga001.jf.intel.com with ESMTP; 28 Mar 2014 09:38:53 -0700 Received: by rosetta (Postfix, from userid 1000) id 919A981665; Fri, 28 Mar 2014 18:38:52 +0200 (EET) From: Mika Kuoppala To: intel-gfx@lists.freedesktop.org Date: Fri, 28 Mar 2014 18:38:47 +0200 Message-Id: <1396024730-9514-1-git-send-email-mika.kuoppala@intel.com> X-Mailer: git-send-email 1.7.9.5 Subject: [Intel-gfx] [PATCH 1/4] lib: add igt_get_stop_rings and igt_set_stop_rings X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-4.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Multiple tests are introducing hangs by fidding with i915_ring_stop debugfs entry. Signed-off-by: Mika Kuoppala --- lib/drmtest.c | 16 ++++++++ lib/igt_debugfs.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/igt_debugfs.h | 33 ++++++++++++++++ 3 files changed, 157 insertions(+) diff --git a/lib/drmtest.c b/lib/drmtest.c index b1bf589..2c9cf62 100644 --- a/lib/drmtest.c +++ b/lib/drmtest.c @@ -88,6 +88,18 @@ is_intel(int fd) return IS_INTEL(devid); } +static void check_stop_rings(void) +{ + enum stop_ring_flags flags; + flags = igt_get_stop_rings(); + igt_warn_on_f(flags != 0, + "i915_ring_stop flags on exit 0x%x, can't quiescent gpu cleanly\n", + flags); + + if (flags) + igt_set_stop_rings(STOP_RING_NONE); +} + #define LOCAL_I915_EXEC_VEBOX (4 << 0) /** * gem_quiescent_gpu: @@ -108,6 +120,8 @@ void gem_quiescent_gpu(int fd) struct drm_i915_gem_execbuffer2 execbuf; struct drm_i915_gem_exec_object2 gem_exec[1]; + check_stop_rings(); + handle = gem_create(fd, 4096); gem_write(fd, handle, 0, batch, sizeof(batch)); @@ -252,6 +266,7 @@ static void quiescent_gpu_at_exit(int sig) if (at_exit_drm_fd < 0) return; + check_stop_rings(); gem_quiescent_gpu(at_exit_drm_fd); close(at_exit_drm_fd); at_exit_drm_fd = -1; @@ -262,6 +277,7 @@ static void quiescent_gpu_at_exit_render(int sig) if (at_exit_drm_render_fd < 0) return; + check_stop_rings(); gem_quiescent_gpu(at_exit_drm_render_fd); close(at_exit_drm_render_fd); at_exit_drm_render_fd = -1; diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c index 81a06ff..0996666 100644 --- a/lib/igt_debugfs.c +++ b/lib/igt_debugfs.c @@ -28,9 +28,11 @@ #include #include #include +#include #include #include #include +#include #include "drmtest.h" #include "igt_kms.h" @@ -615,3 +617,109 @@ int igt_open_forcewake_handle(void) { return igt_debugfs_open("i915_forcewake_user", O_WRONLY); } + +/** + * igt_to_stop_ring_flag: + * @ring: the specified ring flag from execbuf ioctl (I915_EXEC_*) + * + * This converts the specified ring to a ring flag to be used + * with igt_get_stop_rings() and igt_set_stop_rings(). + * + * Returns: + * Ring flag for the given ring. + */ +enum stop_ring_flags igt_to_stop_ring_flag(int ring) { + if (ring == I915_EXEC_DEFAULT) + return STOP_RING_RENDER; + + igt_assert(ring && ((ring & ~I915_EXEC_RING_MASK) == 0)); + return 1 << (ring - 1); +} + +static void stop_rings_write(uint32_t mask) +{ + int fd; + char buf[80]; + + igt_assert(snprintf(buf, sizeof(buf), "0x%08x", mask) == 10); + fd = igt_debugfs_open("i915_ring_stop", O_WRONLY); + igt_assert(fd >= 0); + + igt_assert(write(fd, buf, strlen(buf)) == strlen(buf)); + close(fd); +} + +/** + * igt_get_stop_rings: + * + * Read current ring flags from 'i915_ring_stop' debugfs entry. + * + * Returns: + * Current ring flags. + */ +enum stop_ring_flags igt_get_stop_rings(void) +{ + int fd; + char buf[80]; + int l; + unsigned long long ring_mask; + + fd = igt_debugfs_open("i915_ring_stop", O_RDONLY); + igt_assert(fd >= 0); + l = read(fd, buf, sizeof(buf)); + igt_assert(l > 0); + igt_assert(l < sizeof(buf)); + + buf[l] = '\0'; + + close(fd); + + errno = 0; + ring_mask = strtoull(buf, NULL, 0); + igt_assert(errno == 0); + return ring_mask; +} + +/** + * igt_set_stop_rings: + * @flags: Ring flags to write + * + * This writes @flags to 'i915_ring_stop' debugfs entry. Driver will + * prevent the CPU from writing tail pointer for the ring that @flags + * specify. Note that the ring is not stopped right away. Instead any + * further command emissions won't be executed after the flag is set. + * + * This is the least invasive way to make the GPU stuck. Hence you must + * set this after a batch submission with it's own invalid or endless + * looping instructions. In this case it is merely for giving notification + * for the driver that this was simulated hang, as the batch would have + * caused hang in any case. On the other hand if you use a valid or noop + * batch and want to hang the ring (GPU), you must set corresponding flag + * before submitting the batch. + * + * Driver checks periodically if a ring is making any progress, and if + * it is not, it will declare the ring to be hung and will reset the GPU. + * After reset, the driver will clear flags in 'i915_ring_stop' + * + * Note: Always when hanging the GPU, use igt_set_stop_rings() to + * notify the driver. Driver controls hang log messaging based on + * these flags and thus prevents false positives on logs. + */ +void igt_set_stop_rings(enum stop_ring_flags flags) +{ + enum stop_ring_flags current; + + igt_assert((flags & ~(STOP_RING_ALL | + STOP_RING_ALLOW_BAN | + STOP_RING_ALLOW_ERRORS)) == 0); + + current = igt_get_stop_rings(); + igt_assert_f(current == 0, + "previous i915_ring_stop is still 0x%x\n", current); + + stop_rings_write(flags); + current = igt_get_stop_rings(); + if (current != flags) + igt_warn("i915_ring_stop readback mismatch 0x%x vs 0x%x\n", + flags, current); +} diff --git a/lib/igt_debugfs.h b/lib/igt_debugfs.h index 3312a8b..bcd7f76 100644 --- a/lib/igt_debugfs.h +++ b/lib/igt_debugfs.h @@ -143,4 +143,37 @@ void igt_enable_prefault(void); int igt_open_forcewake_handle(void); +/** + * stop_ring_flags: + * + * @STOP_RING_NONE: Can be used to clear the pending stop (warning: hang might + * be declared already). Returned by igt_get_stop_rings() if there is + * no currently stopped rings. + * @STOP_RING_RENDER: Render ring + * @STOP_RING_BSD: Video encoding/decoding ring + * @STOP_RING_BLT: Blitter ring + * @STOP_RING_VEBOX: Video enchanment ring + * @STOP_RING_ALL: All rings + * @STOP_RING_ALLOW_ERRORS: Driver will not omit expected DRM_ERRORS + * @STOP_RING_ALLOW_BAN: Driver will use context ban policy + * @STOP_RING_DEFAULT: STOP_RING_ALL | STOP_RING_ALLOW_ERRORS + * Enumeration of all supported flags for igt_set_stop_rings(). + * + */ +enum stop_ring_flags { + STOP_RING_NONE = 0x00, + STOP_RING_RENDER = (1 << 0), + STOP_RING_BSD = (1 << 1), + STOP_RING_BLT = (1 << 2), + STOP_RING_VEBOX = (1 << 3), + STOP_RING_ALL = 0xff, + STOP_RING_ALLOW_ERRORS = (1 << 30), + STOP_RING_ALLOW_BAN = (1 << 31), + STOP_RING_DEFAULTS = STOP_RING_ALL | STOP_RING_ALLOW_ERRORS, +}; + +enum stop_ring_flags igt_to_stop_ring_flag(int ring); +void igt_set_stop_rings(enum stop_ring_flags flags); +enum stop_ring_flags igt_get_stop_rings(void); + #endif /* __IGT_DEBUGFS_H__ */