Message ID | 1395766942-5792-1-git-send-email-mika.kuoppala@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Tue, Mar 25, 2014 at 07:02:21PM +0200, Mika Kuoppala wrote: > Multiple tests are introducing hangs by fidding with i915_ring_stop > debugfs entry. > > Signed-off-by: Mika Kuoppala <mika.kuoppala@intel.com> Both patches look good to me. One thing we could do is add an exit handler to reset stop_rings to 0, just in case the test died and somehow the stop_rings value leaked. With or w/o that change both patches lgtm, so feel free to push. -Daniel > --- > lib/igt_debugfs.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++ > lib/igt_debugfs.h | 28 ++++++++++++++ > 2 files changed, 135 insertions(+) > > diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c > index e04f8c5..c4cf50d 100644 > --- a/lib/igt_debugfs.c > +++ b/lib/igt_debugfs.c > @@ -28,9 +28,11 @@ > #include <errno.h> > #include <stdio.h> > #include <stdlib.h> > +#include <limits.h> > #include <string.h> > #include <fcntl.h> > #include <unistd.h> > +#include <i915_drm.h> > > #include "drmtest.h" > #include "igt_display.h" > @@ -615,3 +617,108 @@ int igt_open_forcewake_handle(void) > { > return igt_debugfs_open("i915_forcewake_user", O_WRONLY); > } > + > +/** > + * igt_to_stop_ring_flag: > + * @ring: ring to get flag for, in drm I915_EXEC_* namespace > + * > + * This converts ring specified (drm namespace) to a ring flag > + * to be used with igt_get_stop_rings() and igt_set_stop_rings(). > + * > + * Returns: > + * Ring flag for the give 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 cpu from writing tail pointer for ring @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 to give a log > + * notification that this was simulated hang, as the batch would have > + * caused hang in any case. Or if you use valid or noop batch and want > + * to hang the ring (gpu), you must set this flag before submitting the > + * batch. > + * > + * Driver checks periodically if ring is making any progress, and if > + * 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 tunes down gpu 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) == 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..72f4999 100644 > --- a/lib/igt_debugfs.h > +++ b/lib/igt_debugfs.h > @@ -143,4 +143,32 @@ 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 > + * > + * Enumeration of all supported flags for igt_set_stop_rings(). > + * > + */ > +enum stop_ring_flags { > + STOP_RING_NONE = 0, > + STOP_RING_RENDER = (1 << 0), > + STOP_RING_BSD = (1 << 1), > + STOP_RING_BLT = (1 << 2), > + STOP_RING_VEBOX = (1 << 3), > + STOP_RING_ALL = 0xff, > +}; > + > +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__ */ > -- > 1.7.9.5 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c index e04f8c5..c4cf50d 100644 --- a/lib/igt_debugfs.c +++ b/lib/igt_debugfs.c @@ -28,9 +28,11 @@ #include <errno.h> #include <stdio.h> #include <stdlib.h> +#include <limits.h> #include <string.h> #include <fcntl.h> #include <unistd.h> +#include <i915_drm.h> #include "drmtest.h" #include "igt_display.h" @@ -615,3 +617,108 @@ int igt_open_forcewake_handle(void) { return igt_debugfs_open("i915_forcewake_user", O_WRONLY); } + +/** + * igt_to_stop_ring_flag: + * @ring: ring to get flag for, in drm I915_EXEC_* namespace + * + * This converts ring specified (drm namespace) to a ring flag + * to be used with igt_get_stop_rings() and igt_set_stop_rings(). + * + * Returns: + * Ring flag for the give 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 cpu from writing tail pointer for ring @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 to give a log + * notification that this was simulated hang, as the batch would have + * caused hang in any case. Or if you use valid or noop batch and want + * to hang the ring (gpu), you must set this flag before submitting the + * batch. + * + * Driver checks periodically if ring is making any progress, and if + * 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 tunes down gpu 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) == 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..72f4999 100644 --- a/lib/igt_debugfs.h +++ b/lib/igt_debugfs.h @@ -143,4 +143,32 @@ 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 + * + * Enumeration of all supported flags for igt_set_stop_rings(). + * + */ +enum stop_ring_flags { + STOP_RING_NONE = 0, + STOP_RING_RENDER = (1 << 0), + STOP_RING_BSD = (1 << 1), + STOP_RING_BLT = (1 << 2), + STOP_RING_VEBOX = (1 << 3), + STOP_RING_ALL = 0xff, +}; + +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__ */
Multiple tests are introducing hangs by fidding with i915_ring_stop debugfs entry. Signed-off-by: Mika Kuoppala <mika.kuoppala@intel.com> --- lib/igt_debugfs.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/igt_debugfs.h | 28 ++++++++++++++ 2 files changed, 135 insertions(+)