From patchwork Tue Oct 11 09:27:14 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 9370293 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 42C8860772 for ; Tue, 11 Oct 2016 09:27:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2489F29C03 for ; Tue, 11 Oct 2016 09:27:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 194B329C05; Tue, 11 Oct 2016 09:27:33 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 4751529C03 for ; Tue, 11 Oct 2016 09:27:28 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id BFDEB6E636; Tue, 11 Oct 2016 09:27:27 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mail-qk0-x243.google.com (mail-qk0-x243.google.com [IPv6:2607:f8b0:400d:c09::243]) by gabe.freedesktop.org (Postfix) with ESMTPS id E33CF6E639 for ; Tue, 11 Oct 2016 09:27:25 +0000 (UTC) Received: by mail-qk0-x243.google.com with SMTP id z190so964212qkc.3 for ; Tue, 11 Oct 2016 02:27:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:subject:date:message-id:in-reply-to:references; bh=6Jl1Lx0P/Off1bQFMFgXOoUrdD8BmdLVLwruFgbZkwQ=; b=gEjnqY/cie2YFgFm8VTSviN+Lqu77M4NZhpVrqOq4krJxMUAlKP3T9mlcSBnPA4Vsy OQBpAaUK0WLcRb5Q1WDQZfm/1hsErJd+3sGDSs8RFJd9l/x4wCn5cCJqLBUkeSAS4TyP a5BFNwgpsQadc25oMqVCBjyXoa+zHGWu1tDTsXJ9eHcJu+NNzywriDx1zXyth5HJdo39 d+tbywQpjnFd1q7jcgoUGPOzoT8aVX0yzNfyxdHmlX1vKT0e+wbysLwx4xUctpCCZhEk O0zfTDReoRdanEratAZ4knB4RbU76ROImWvR9xXZpNC2yEkNlBsVvA66P47QHvmxYY+u xTDw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:subject:date:message-id :in-reply-to:references; bh=6Jl1Lx0P/Off1bQFMFgXOoUrdD8BmdLVLwruFgbZkwQ=; b=A8Yado0TFSm2HyPiDysGzIKcFD54hzZpVHl5Lxi7YEf3Qq/mD2WCXj7e0PIk2HGAuD ScISuxtxo9DENossPThqr7yT/Us0G2sFI+ZGqjrmto5UUgQW0uVsMOYgymJdXyBWuOW5 eZxEKqaWg4WNqWWWmNerRZvz0MK2200Hvmp0zJm79/Jbum5Dk0g2wKfXePoxTfDI31iK 1iC+C0yFYNz68DyGi5u/YDH+YRiUzvNgB622Lgftu2dgaGBwjf4lO4mkPmKnchNkk1cN ZWFzMcAUwdrpElc/mKfIqSkfaSt3ARbTvHzxwn1vVU2rAQGqaPgMbRXeA9Cha3pDR2mI sNsg== X-Gm-Message-State: AA6/9RncL4NvGYHVSXho2vovTvAv+6itxwhITubUg75KeePshfHbp/0XGX3xHDYD0vTbGA== X-Received: by 10.194.176.69 with SMTP id cg5mr3581685wjc.52.1476178044730; Tue, 11 Oct 2016 02:27:24 -0700 (PDT) Received: from haswell.alporthouse.com ([78.156.65.138]) by smtp.gmail.com with ESMTPSA id g6sm4859733wjy.3.2016.10.11.02.27.23 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 11 Oct 2016 02:27:23 -0700 (PDT) From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Tue, 11 Oct 2016 10:27:14 +0100 Message-Id: <20161011092714.19263-5-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20161011092714.19263-1-chris@chris-wilson.co.uk> References: <20161011092714.19263-1-chris@chris-wilson.co.uk> Subject: [Intel-gfx] [CI 5/5] drm/i915: Compress GPU objects in error state X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 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-Virus-Scanned: ClamAV using ClamSMTP Our error states are quickly growing, pinning kernel memory with them. The majority of the space is taken up by the error objects. These compress well using zlib and without decode are mostly meaningless, so encoding them does not hinder quickly parsing the error state for familiarity. v2: Make the zlib dependency optional Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/Kconfig | 12 +++ drivers/gpu/drm/i915/i915_drv.h | 3 +- drivers/gpu/drm/i915/i915_gpu_error.c | 176 ++++++++++++++++++++++++++++++---- 3 files changed, 169 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index 0f46a9c04c0e..92ecced1bc8f 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -57,6 +57,18 @@ config DRM_I915_CAPTURE_ERROR If in doubt, say "Y". +config DRM_I915_COMPRESS_ERROR + bool "Compress GPU error state" + depends on DRM_I915_CAPTURE_ERROR + select ZLIB_DEFLATE + default y + help + This option selects ZLIB_DEFLATE if it isn't already + selected and causes any error state captured upon a GPU hang + to be compressed using zlib. + + If in doubt, say "Y". + config DRM_I915_USERPTR bool "Always enable userptr support" depends on DRM_I915 diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 97203da3a08d..3d46f57eed3f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -820,9 +820,10 @@ struct drm_i915_error_state { struct intel_instdone instdone; struct drm_i915_error_object { - int page_count; u64 gtt_offset; u64 gtt_size; + int page_count; + int unused; u32 *pages[0]; } *ringbuffer, *batchbuffer, *wa_batchbuffer, *ctx, *hws_page; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index bf2498297341..6c22be28ba01 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -29,6 +29,7 @@ #include #include +#include #include "i915_drv.h" #ifdef CONFIG_DRM_I915_CAPTURE_ERROR @@ -175,6 +176,110 @@ static void i915_error_puts(struct drm_i915_error_state_buf *e, #define err_printf(e, ...) i915_error_printf(e, __VA_ARGS__) #define err_puts(e, s) i915_error_puts(e, s) +#ifdef CONFIG_DRM_I915_COMPRESS_ERROR + +static bool compress_init(struct z_stream_s *zstream) +{ + memset(zstream, 0, sizeof(*zstream)); + + zstream->workspace = + kmalloc(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL), + GFP_ATOMIC | __GFP_NOWARN); + if (!zstream->workspace) + return false; + + if (zlib_deflateInit(zstream, Z_DEFAULT_COMPRESSION) != Z_OK) { + kfree(zstream->workspace); + return false; + } + + return true; +} + +static int compress_page(struct z_stream_s *zstream, + void *src, + struct drm_i915_error_object *dst) +{ + zstream->next_in = src; + zstream->avail_in = PAGE_SIZE; + + do { + if (zstream->avail_out == 0) { + unsigned long page; + + page = __get_free_page(GFP_ATOMIC | __GFP_NOWARN); + if (!page) + return -ENOMEM; + + dst->pages[dst->page_count++] = (void *)page; + + zstream->next_out = (void *)page; + zstream->avail_out = PAGE_SIZE; + } + + if (zlib_deflate(zstream, Z_SYNC_FLUSH) != Z_OK) + return -EIO; + } while (zstream->avail_in); + + /* Fallback to uncompressed if we increase size? */ + if (0 && zstream->total_out > zstream->total_in) + return -E2BIG; + + return 0; +} + +static void compress_fini(struct z_stream_s *zstream, + struct drm_i915_error_object *dst) +{ + if (dst) { + zlib_deflate(zstream, Z_FINISH); + dst->unused = zstream->avail_out; + } + + zlib_deflateEnd(zstream); + kfree(zstream->workspace); +} + +static void err_compression_marker(struct drm_i915_error_state_buf *m) +{ + err_puts(m, ":"); +} + +#else + +static bool compress_init(struct z_stream_s *zstream) +{ + return true; +} + +static int compress_page(struct z_stream_s *zstream, + void *src, + struct drm_i915_error_object *dst) +{ + unsigned long page; + + page = __get_free_page(GFP_ATOMIC | __GFP_NOWARN); + if (!page) + return -ENOMEM; + + dst->pages[dst->page_count++] = + memcpy((void *)page, src, PAGE_SIZE); + + return 0; +} + +static void compress_fini(struct z_stream_s *zstream, + struct drm_i915_error_object *dst) +{ +} + +static void err_compression_marker(struct drm_i915_error_state_buf *m) +{ + err_puts(m, "~"); +} + +#endif + static void print_error_buffers(struct drm_i915_error_state_buf *m, const char *name, struct drm_i915_error_buffer *err, @@ -342,12 +447,36 @@ void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...) va_end(args); } +static int +ascii85_encode_len(int len) +{ + return DIV_ROUND_UP(len, 4); +} + +static bool +ascii85_encode(u32 in, char *out) +{ + int i; + + if (in == 0) + return false; + + out[5] = '\0'; + for (i = 5; i--; ) { + out[i] = '!' + in % 85; + in /= 85; + } + + return true; +} + static void print_error_obj(struct drm_i915_error_state_buf *m, struct intel_engine_cs *engine, const char *name, struct drm_i915_error_object *obj) { - int page, offset, elt; + char out[6]; + int page; if (!obj) return; @@ -359,13 +488,23 @@ static void print_error_obj(struct drm_i915_error_state_buf *m, lower_32_bits(obj->gtt_offset)); } - for (page = offset = 0; page < obj->page_count; page++) { - for (elt = 0; elt < PAGE_SIZE/4; elt++) { - err_printf(m, "%08x : %08x\n", offset, - obj->pages[page][elt]); - offset += 4; + err_compression_marker(m); + for (page = 0; page < obj->page_count; page++) { + int i, len; + + len = PAGE_SIZE; + if (page == obj->page_count - 1) + len -= obj->unused; + len = ascii85_encode_len(len); + + for (i = 0; i < len; i++) { + if (ascii85_encode(obj->pages[page][i], out)) + err_puts(m, out); + else + err_puts(m, "z"); } } + err_puts(m, "\n"); } static void err_print_capabilities(struct drm_i915_error_state_buf *m, @@ -645,20 +784,6 @@ static void i915_error_state_free(struct kref *error_ref) kfree(error); } -static int compress_page(void *src, struct drm_i915_error_object *dst) -{ - unsigned long page; - - page = __get_free_page(GFP_ATOMIC | __GFP_NOWARN); - if (!page) - return -ENOMEM; - - dst->pages[dst->page_count++] = (void *)page; - - memcpy((void *)page, src, PAGE_SIZE); - return 0; -} - static struct drm_i915_error_object * i915_error_object_create(struct drm_i915_private *i915, struct i915_vma *vma) @@ -666,6 +791,7 @@ i915_error_object_create(struct drm_i915_private *i915, struct i915_ggtt *ggtt = &i915->ggtt; const u64 slot = ggtt->error_capture.start; struct drm_i915_error_object *dst; + struct z_stream_s zstream; unsigned long num_pages; struct sgt_iter iter; dma_addr_t dma; @@ -674,6 +800,7 @@ i915_error_object_create(struct drm_i915_private *i915, return NULL; num_pages = min_t(u64, vma->size, vma->obj->base.size) >> PAGE_SHIFT; + num_pages = DIV_ROUND_UP(10 * num_pages, 8); /* worstcase zlib growth */ dst = kmalloc(sizeof(*dst) + num_pages * sizeof(u32 *), GFP_ATOMIC | __GFP_NOWARN); if (!dst) @@ -682,6 +809,12 @@ i915_error_object_create(struct drm_i915_private *i915, dst->gtt_offset = vma->node.start; dst->gtt_size = vma->node.size; dst->page_count = 0; + dst->unused = 0; + + if (!compress_init(&zstream)) { + kfree(dst); + return NULL; + } for_each_sgt_dma(dma, iter, vma->pages) { void __iomem *s; @@ -691,7 +824,7 @@ i915_error_object_create(struct drm_i915_private *i915, I915_CACHE_NONE, 0); s = io_mapping_map_atomic_wc(&ggtt->mappable, slot); - ret = compress_page((void * __force)s, dst); + ret = compress_page(&zstream, (void __force *)s, dst); io_mapping_unmap_atomic(s); if (ret) @@ -706,6 +839,7 @@ unwind: dst = NULL; out: + compress_fini(&zstream, dst); ggtt->base.clear_range(&ggtt->base, slot, PAGE_SIZE, true); return dst; }