From patchwork Sat Feb 26 09:55:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Alan Previn X-Patchwork-Id: 12761250 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 8B0B4C433EF for ; Sat, 26 Feb 2022 09:53:49 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id A583410E401; Sat, 26 Feb 2022 09:53:35 +0000 (UTC) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by gabe.freedesktop.org (Postfix) with ESMTPS id 47EDC10E405 for ; Sat, 26 Feb 2022 09:53:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1645869214; x=1677405214; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ugIPfoS/AEn2XiSm8k7ouIwmXjHi4dPb4+NsZDGH8do=; b=VUMepJj+W9YFejvcuyCWXdFC9QlCppLNkFis6tOJPJrmHlhi6fmLYzuc uapygMome5hfmHaqQ//YNyP3EFbEfc9yvGSjEzpCcwj9b8fbZ3Tdlws9o rQNZGKpRgAaDmY+IbH5BHqpLWmfxmIXuGwC8wzvPvUJN6VnXH69bGNdox mEsTPET8bTEYFcV8gWuaojaKxqKzupV912vCJOAUdQYY5xxGG2kwlyGcU OTY0YD4V7YoAQWiDF7yK773dk6YRq0L6CYhE5yTuNSukiOMcbguI8rme/ iqN8+vlbQTY0JU/gkPf4yFzzW3AnAZfT5n45wV1p/0/5qlkj+GgA25bvC w==; X-IronPort-AV: E=McAfee;i="6200,9189,10269"; a="251480182" X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="251480182" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Feb 2022 01:53:33 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="506953219" Received: from aalteres-desk.fm.intel.com ([10.80.57.53]) by orsmga002.jf.intel.com with ESMTP; 26 Feb 2022 01:53:33 -0800 From: Alan Previn To: intel-gfx@lists.freedesktop.org Date: Sat, 26 Feb 2022 01:55:29 -0800 Message-Id: <20220226095541.1010534-2-alan.previn.teres.alexis@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> References: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v7 01/13] drm/i915/guc: Update GuC ADS size for error capture lists X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alan Previn Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Update GuC ADS size allocation to include space for the lists of error state capture register descriptors. Also, populate the lists of registers we want GuC to report back to Host on engine reset events. This list should include global, engine-class and engine-instance registers for every engine-class type on the current hardware. NOTE: Start with a sample table of register lists to layout the framework before adding real registers in subsequent patch. Signed-off-by: Alan Previn Reported-by: kernel test robot --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h | 89 +++++ drivers/gpu/drm/i915/gt/uc/intel_guc.c | 13 +- drivers/gpu/drm/i915/gt/uc/intel_guc.h | 11 +- drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c | 132 ++++++- .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 352 ++++++++++++++++++ .../gpu/drm/i915/gt/uc/intel_guc_capture.h | 22 ++ drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 8 + 8 files changed, 611 insertions(+), 17 deletions(-) create mode 100644 drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 9d588d936e3d..547adc36d4e9 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -184,6 +184,7 @@ i915-y += gt/uc/intel_uc.o \ gt/uc/intel_uc_fw.o \ gt/uc/intel_guc.o \ gt/uc/intel_guc_ads.o \ + gt/uc/intel_guc_capture.o \ gt/uc/intel_guc_ct.o \ gt/uc/intel_guc_debugfs.o \ gt/uc/intel_guc_fw.o \ diff --git a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h new file mode 100644 index 000000000000..858f85478636 --- /dev/null +++ b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2021-2022 Intel Corporation + */ + +#ifndef _INTEL_GUC_CAPTURE_FWIF_H +#define _INTEL_GUC_CAPTURE_FWIF_H + +#include +#include "intel_guc_fwif.h" + +struct intel_guc; +struct file; + +/** + * struct guc_debug_capture_list_header / struct guc_debug_capture_list + * + * As part of ADS registration, these header structures (followed by + * an array of 'struct guc_mmio_reg' entries) are used to register with + * GuC microkernel the list of registers we want it to dump out prior + * to a engine reset. + */ +struct guc_debug_capture_list_header { + u32 info; +#define GUC_CAPTURELISTHDR_NUMDESCR GENMASK(15, 0) +} __packed; + +struct guc_debug_capture_list { + struct guc_debug_capture_list_header header; +} __packed; + +/** + * struct __guc_mmio_reg_descr / struct __guc_mmio_reg_descr_group + * + * intel_guc_capture module uses these structures to maintain static + * tables (per unique platform) that consists of lists of registers + * (offsets, names, flags,...) that are used at the ADS regisration + * time as well as during runtime processing and reporting of error- + * capture states generated by GuC just prior to engine reset events. + */ +struct __guc_mmio_reg_descr { + i915_reg_t reg; + u32 flags; + u32 mask; + const char *regname; +}; + +struct __guc_mmio_reg_descr_group { + const struct __guc_mmio_reg_descr *list; + u32 num_regs; + u32 owner; /* see enum guc_capture_owner */ + u32 type; /* see enum guc_capture_type */ + u32 engine; /* as per MAX_ENGINE_CLASS */ +}; + +/** + * struct __guc_capture_ads_cache + * + * A structure to cache register lists that were populated and registered + * with GuC at startup during ADS registration. This allows much quicker + * GuC resets without re-parsing all the tables for the given gt. + */ +struct __guc_capture_ads_cache { + bool is_valid; + struct file *file; + size_t size; + int status; +}; + +/** + * struct __guc_state_capture_priv + * + * Internal context of the intel_guc_capture module. + */ +struct __guc_state_capture_priv { + /** + * @reglists: static table of register lists used for error-capture state. + */ + const struct __guc_mmio_reg_descr_group *reglists; + + /** + * @ads_cache: cached register lists that is ADS format ready + */ + struct __guc_capture_ads_cache ads_cache[GUC_CAPTURE_LIST_INDEX_MAX] + [GUC_CAPTURE_LIST_TYPE_MAX] + [GUC_MAX_ENGINE_CLASSES]; +}; + +#endif /* _INTEL_GUC_CAPTURE_FWIF_H */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 447a976c9f25..cda7e4bb8bac 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -9,8 +9,9 @@ #include "gt/intel_gt_pm_irq.h" #include "gt/intel_gt_regs.h" #include "intel_guc.h" -#include "intel_guc_slpc.h" #include "intel_guc_ads.h" +#include "intel_guc_capture.h" +#include "intel_guc_slpc.h" #include "intel_guc_submission.h" #include "i915_drv.h" #include "i915_irq.h" @@ -362,9 +363,14 @@ int intel_guc_init(struct intel_guc *guc) if (ret) goto err_fw; - ret = intel_guc_ads_create(guc); + ret = intel_guc_capture_init(guc); if (ret) goto err_log; + + ret = intel_guc_ads_create(guc); + if (ret) + goto err_capture; + GEM_BUG_ON(!guc->ads_vma); ret = intel_guc_ct_init(&guc->ct); @@ -403,6 +409,8 @@ int intel_guc_init(struct intel_guc *guc) intel_guc_ct_fini(&guc->ct); err_ads: intel_guc_ads_destroy(guc); +err_capture: + intel_guc_capture_destroy(guc); err_log: intel_guc_log_destroy(&guc->log); err_fw: @@ -430,6 +438,7 @@ void intel_guc_fini(struct intel_guc *guc) intel_guc_ct_fini(&guc->ct); intel_guc_ads_destroy(guc); + intel_guc_capture_destroy(guc); intel_guc_log_destroy(&guc->log); intel_uc_fw_fini(&guc->fw); } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index bf7079480d47..908c6b1dd51a 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -10,18 +10,19 @@ #include #include -#include "intel_uncore.h" +#include "intel_guc_ct.h" #include "intel_guc_fw.h" #include "intel_guc_fwif.h" -#include "intel_guc_ct.h" #include "intel_guc_log.h" #include "intel_guc_reg.h" #include "intel_guc_slpc_types.h" #include "intel_uc_fw.h" +#include "intel_uncore.h" #include "i915_utils.h" #include "i915_vma.h" struct __guc_ads_blob; +struct __guc_state_capture_priv; /** * struct intel_guc - Top level structure of GuC. @@ -38,6 +39,10 @@ struct intel_guc { struct intel_guc_ct ct; /** @slpc: sub-structure containing SLPC related data and objects */ struct intel_guc_slpc slpc; + /** @capture: the error-state-capture module's data and objects */ + struct intel_guc_state_capture { + struct __guc_state_capture_priv *priv; + } capture; /** @sched_engine: Global engine used to submit requests to GuC */ struct i915_sched_engine *sched_engine; @@ -160,6 +165,8 @@ struct intel_guc { struct guc_mmio_reg *ads_regset; /** @ads_golden_ctxt_size: size of the golden contexts in the ADS */ u32 ads_golden_ctxt_size; + /** @ads_capture_size: size of register lists in the ADS used for error capture */ + u32 ads_capture_size; /** @ads_engine_usage_size: size of engine usage in the ADS */ u32 ads_engine_usage_size; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index 847e00390b00..8bed68299bba 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -11,6 +11,7 @@ #include "gt/intel_lrc.h" #include "gt/shmem_utils.h" #include "intel_guc_ads.h" +#include "intel_guc_capture.h" #include "intel_guc_fwif.h" #include "intel_uc.h" #include "i915_drv.h" @@ -86,8 +87,7 @@ static u32 guc_ads_golden_ctxt_size(struct intel_guc *guc) static u32 guc_ads_capture_size(struct intel_guc *guc) { - /* FIXME: Allocate a proper capture list */ - return PAGE_ALIGN(PAGE_SIZE); + return PAGE_ALIGN(guc->ads_capture_size); } static u32 guc_ads_private_data_size(struct intel_guc *guc) @@ -584,24 +584,124 @@ static void guc_init_golden_context(struct intel_guc *guc) GEM_BUG_ON(guc->ads_golden_ctxt_size != total_size); } -static void guc_capture_list_init(struct intel_guc *guc) +static int +guc_capture_prep_lists(struct intel_guc *guc) { + struct intel_gt *gt = guc_to_gt(guc); + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + u32 ggtt, capture_offset, null_ggtt, total_size = 0; + struct guc_gt_system_info local_info; + struct iosys_map info_map; + u32 null_header[2]={0}; + struct file *file; + size_t size = 0; int i, j; - u32 addr_ggtt, offset; - offset = guc_ads_capture_offset(guc); - addr_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma) + offset; + if (!iosys_map_is_null(&guc->ads_map)) { + capture_offset = guc_ads_capture_offset(guc); + ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma) + capture_offset; + info_map = IOSYS_MAP_INIT_OFFSET(&guc->ads_map, + offsetof(struct __guc_ads_blob, system_info)); + } else { + memset(&local_info, 0, sizeof(local_info)); + iosys_map_set_vaddr(&info_map, &local_info); + fill_engine_enable_masks(gt, &info_map); + } - /* FIXME: Populate a proper capture list */ + /* first, set aside the first page for a capture_list with zero descriptors */ + total_size = PAGE_SIZE; + if (!iosys_map_is_null(&guc->ads_map)) { + file = shmem_create_from_data("guc-err-cap", null_header, sizeof(null_header)); + if (!IS_ERR(file)) { + shmem_read_to_iosys_map(file, 0, &guc->ads_map, + ggtt, sizeof(null_header)); + fput(file); + } else { + drm_dbg(&i915->drm, "GuC-capture: failed shmem for nulllist = 0x%016lx", + PTR_ERR(file)); + } + null_ggtt = ggtt; + ggtt += PAGE_SIZE; + } for (i = 0; i < GUC_CAPTURE_LIST_INDEX_MAX; i++) { for (j = 0; j < GUC_MAX_ENGINE_CLASSES; j++) { - ads_blob_write(guc, ads.capture_instance[i][j], addr_ggtt); - ads_blob_write(guc, ads.capture_class[i][j], addr_ggtt); - } - ads_blob_write(guc, ads.capture_global[i], addr_ggtt); + /* null list if we dont have said engine or list */ + if (!info_map_read(&info_map, engine_enabled_masks[j])) { + + if (!iosys_map_is_null(&guc->ads_map)) { + ads_blob_write(guc, ads.capture_class[i][j], null_ggtt); + ads_blob_write(guc, ads.capture_instance[i][j], null_ggtt); + } + continue; + } + if (intel_guc_capture_getlistsize(guc, i, + GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, + j, &size)) { + if (!iosys_map_is_null(&guc->ads_map)) + ads_blob_write(guc, ads.capture_class[i][j], null_ggtt); + goto engine_instance_list; + } + total_size += size; + if (!iosys_map_is_null(&guc->ads_map)) { + if (total_size > guc->ads_capture_size || + intel_guc_capture_getlist(guc, i, + GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, + j, &file)) { + ads_blob_write(guc, ads.capture_class[i][j], null_ggtt); + continue; + } + ads_blob_write(guc, ads.capture_class[i][j], ggtt); + shmem_read_to_iosys_map(file, 0, &guc->ads_map, ggtt, size); + ggtt += size; + } +engine_instance_list: + if (intel_guc_capture_getlistsize(guc, i, + GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE, + j, &size)) { + if (!iosys_map_is_null(&guc->ads_map)) + ads_blob_write(guc, ads.capture_instance[i][j], null_ggtt); + continue; + } + total_size += size; + if (!iosys_map_is_null(&guc->ads_map)) { + if (total_size > guc->ads_capture_size || + intel_guc_capture_getlist(guc, i, + GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE, + j, &file)) { + ads_blob_write(guc, ads.capture_instance[i][j], null_ggtt); + continue; + } + ads_blob_write(guc, ads.capture_instance[i][j], ggtt); + shmem_read_to_iosys_map(file, 0, &guc->ads_map, ggtt, size); + ggtt += size; + } + } + if (intel_guc_capture_getlistsize(guc, i, GUC_CAPTURE_LIST_TYPE_GLOBAL, 0, &size)) { + if (!iosys_map_is_null(&guc->ads_map)) + ads_blob_write(guc, ads.capture_global[i], null_ggtt); + continue; + } + total_size += size; + if (!iosys_map_is_null(&guc->ads_map)) { + if (total_size > guc->ads_capture_size || + intel_guc_capture_getlist(guc, i, GUC_CAPTURE_LIST_TYPE_GLOBAL, 0, + &file)) { + ads_blob_write(guc, ads.capture_global[i], null_ggtt); + continue; + } + ads_blob_write(guc, ads.capture_global[i], ggtt); + shmem_read_to_iosys_map(file, 0, &guc->ads_map, ggtt, size); + ggtt += size; + } } + + if (guc->ads_capture_size && guc->ads_capture_size != PAGE_ALIGN(total_size)) + drm_warn(&i915->drm, "GuC->ADS->Capture alloc size changed from %d to %d\n", + guc->ads_capture_size, PAGE_ALIGN(total_size)); + + return PAGE_ALIGN(total_size); } static void __guc_ads_init(struct intel_guc *guc) @@ -639,8 +739,8 @@ static void __guc_ads_init(struct intel_guc *guc) base = intel_guc_ggtt_offset(guc, guc->ads_vma); - /* Capture list for hang debug */ - guc_capture_list_init(guc); + /* Lists for error capture debug */ + guc_capture_prep_lists(guc); /* ADS */ ads_blob_write(guc, ads.scheduler_policies, base + @@ -688,6 +788,12 @@ int intel_guc_ads_create(struct intel_guc *guc) return ret; guc->ads_golden_ctxt_size = ret; + /* Likewise the capture lists: */ + ret = guc_capture_prep_lists(guc); + if (ret < 0) + return ret; + guc->ads_capture_size = ret; + /* Now the total size can be determined: */ size = guc_ads_blob_size(guc); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c new file mode 100644 index 000000000000..647a118aa3c3 --- /dev/null +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -0,0 +1,352 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2021-2022 Intel Corporation + */ + +#include + +#include + +#include "gt/intel_engine_regs.h" +#include "gt/intel_gt.h" +#include "gt/intel_gt_regs.h" +#include "gt/shmem_utils.h" +#include "guc_capture_fwif.h" +#include "intel_guc_fwif.h" +#include "i915_drv.h" +#include "i915_memcpy.h" +#include "i915_reg.h" + +/* + * Define all device tables of GuC error capture register lists + * NOTE: For engine-registers, GuC only needs the register offsets + * from the engine-mmio-base + */ +/* XE_LPD - Global */ +static const struct __guc_mmio_reg_descr xe_lpd_global_regs[] = { + {GEN12_RING_FAULT_REG, 0, 0, "GEN12_RING_FAULT_REG"} +}; + +/* XE_LPD - Render / Compute Per-Class */ +static const struct __guc_mmio_reg_descr xe_lpd_rc_class_regs[] = { + {EIR, 0, 0, "EIR"} +}; + +/* XE_LPD - Render / Compute Per-Engine-Instance */ +static const struct __guc_mmio_reg_descr xe_lpd_rc_inst_regs[] = { + {RING_HEAD(0), 0, 0, "RING_HEAD"}, + {RING_TAIL(0), 0, 0, "RING_TAIL"}, +}; + +/* XE_LPD - Media Decode/Encode Per-Class */ +static const struct __guc_mmio_reg_descr xe_lpd_vd_class_regs[] = { +}; + +/* XE_LPD - Media Decode/Encode Per-Engine-Instance */ +static const struct __guc_mmio_reg_descr xe_lpd_vd_inst_regs[] = { + {RING_HEAD(0), 0, 0, "RING_HEAD"}, + {RING_TAIL(0), 0, 0, "RING_TAIL"}, +}; + +/* XE_LPD - Video Enhancement Per-Class */ +static const struct __guc_mmio_reg_descr xe_lpd_vec_class_regs[] = { +}; + +/* XE_LPD - Video Enhancement Per-Engine-Instance */ +static const struct __guc_mmio_reg_descr xe_lpd_vec_inst_regs[] = { + {RING_HEAD(0), 0, 0, "RING_HEAD"}, + {RING_TAIL(0), 0, 0, "RING_TAIL"}, +}; + +#define TO_GCAP_DEF_OWNER(x) (GUC_CAPTURE_LIST_INDEX_##x) +#define TO_GCAP_DEF_TYPE(x) (GUC_CAPTURE_LIST_TYPE_##x) +#define MAKE_REGLIST(regslist, regsowner, regstype, class) \ + { \ + regslist, \ + ARRAY_SIZE(regslist), \ + TO_GCAP_DEF_OWNER(regsowner), \ + TO_GCAP_DEF_TYPE(regstype), \ + class, \ + } + +/* List of lists */ +static const struct __guc_mmio_reg_descr_group xe_lpd_lists[] = { + MAKE_REGLIST(xe_lpd_global_regs, PF, GLOBAL, 0), + MAKE_REGLIST(xe_lpd_rc_class_regs, PF, ENGINE_CLASS, GUC_RENDER_CLASS), + MAKE_REGLIST(xe_lpd_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_RENDER_CLASS), + MAKE_REGLIST(xe_lpd_vd_class_regs, PF, ENGINE_CLASS, GUC_VIDEO_CLASS), + MAKE_REGLIST(xe_lpd_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEO_CLASS), + MAKE_REGLIST(xe_lpd_vec_class_regs, PF, ENGINE_CLASS, GUC_VIDEOENHANCE_CLASS), + MAKE_REGLIST(xe_lpd_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEOENHANCE_CLASS), + {} +}; + +static const struct __guc_mmio_reg_descr_group * +guc_capture_get_device_reglist(struct intel_guc *guc) +{ + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + + if (IS_TIGERLAKE(i915) || IS_ROCKETLAKE(i915) || + IS_ALDERLAKE_S(i915) || IS_ALDERLAKE_P(i915)) { + return xe_lpd_lists; + } + + return NULL; +} + +static const struct __guc_mmio_reg_descr_group * +guc_capture_get_one_list(const struct __guc_mmio_reg_descr_group *reglists, + u32 owner, u32 type, u32 id) +{ + int i; + + if (!reglists) + return NULL; + + for (i = 0; reglists[i].list; ++i) { + if (reglists[i].owner == owner && reglists[i].type == type && + (reglists[i].engine == id || reglists[i].type == GUC_CAPTURE_LIST_TYPE_GLOBAL)) + return ®lists[i]; + } + + return NULL; +} + +static const char * +__stringify_owner(u32 owner) +{ + switch (owner) { + case GUC_CAPTURE_LIST_INDEX_PF: + return "PF"; + case GUC_CAPTURE_LIST_INDEX_VF: + return "VF"; + default: + return "unknown"; + } + + return ""; +} + +static const char * +__stringify_type(u32 type) +{ + switch (type) { + case GUC_CAPTURE_LIST_TYPE_GLOBAL: + return "Global"; + case GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS: + return "Class"; + case GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE: + return "Instance"; + default: + return "unknown"; + } + + return ""; +} + +static const char * +__stringify_engclass(u32 class) +{ + switch (class) { + case GUC_RENDER_CLASS: + return "Render"; + case GUC_VIDEO_CLASS: + return "Video"; + case GUC_VIDEOENHANCE_CLASS: + return "VideoEnhance"; + case GUC_BLITTER_CLASS: + return "Blitter"; + case GUC_RESERVED_CLASS: + return "Reserved"; + default: + return "unknown"; + } + + return ""; +} + +static void +guc_capture_warn_with_list_info(struct drm_i915_private *i915, char *msg, + u32 owner, u32 type, u32 classid) +{ + if (type == GUC_CAPTURE_LIST_TYPE_GLOBAL) + drm_dbg(&i915->drm, "GuC-capture: %s for %s %s-Registers.\n", msg, + __stringify_owner(owner), __stringify_type(type)); + else + drm_dbg(&i915->drm, "GuC-capture: %s for %s %s-Registers on %s-Engine\n", msg, + __stringify_owner(owner), __stringify_type(type), + __stringify_engclass(classid)); +} + +static int +guc_capture_list_init(struct intel_guc *guc, u32 owner, u32 type, u32 classid, + struct guc_mmio_reg *ptr, u16 num_entries) +{ + u32 i = 0; + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + const struct __guc_mmio_reg_descr_group *reglists = guc->capture.priv->reglists; + const struct __guc_mmio_reg_descr_group *match; + + if (!reglists) + return -ENODEV; + + match = guc_capture_get_one_list(reglists, owner, type, classid); + if (match) { + for (i = 0; i < num_entries && i < match->num_regs; ++i) { + ptr[i].offset = match->list[i].reg.reg; + ptr[i].value = 0xDEADF00D; + ptr[i].flags = match->list[i].flags; + ptr[i].mask = match->list[i].mask; + } + return 0; + } + + guc_capture_warn_with_list_info(i915, "Missing register list init", owner, type, + classid); + + return -ENODATA; +} + +static int +guc_cap_list_num_regs(struct __guc_state_capture_priv *gc, u32 owner, u32 type, u32 classid) +{ + const struct __guc_mmio_reg_descr_group *match; + + match = guc_capture_get_one_list(gc->reglists, owner, type, classid); + if (!match) + return 0; + + return match->num_regs; +} + +int +intel_guc_capture_getlistsize(struct intel_guc *guc, u32 owner, u32 type, u32 classid, + size_t *size) +{ + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + struct __guc_state_capture_priv *gc = guc->capture.priv; + struct __guc_capture_ads_cache *cache = &gc->ads_cache[owner][type][classid]; + int num_regs; + + if (!gc->reglists) + return -ENODEV; + + if (cache->is_valid) { + *size = cache->size; + return cache->status; + } + + num_regs = guc_cap_list_num_regs(gc, owner, type, classid); + if (!num_regs) { + guc_capture_warn_with_list_info(i915, "Missing register list size", + owner, type, classid); + return -ENODATA; + } + + *size = PAGE_ALIGN((sizeof(struct guc_debug_capture_list)) + + (num_regs * sizeof(struct guc_mmio_reg))); + + return 0; +} + +int +intel_guc_capture_getlist(struct intel_guc *guc, u32 owner, u32 type, u32 classid, + struct file **fileoutptr) +{ + struct __guc_state_capture_priv *gc = guc->capture.priv; + struct __guc_capture_ads_cache *cache = &gc->ads_cache[owner][type][classid]; + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + struct guc_debug_capture_list *listnode; + struct file *file; + u8 *caplist, *tmp; + size_t size = 0; + int ret, num_regs; + + if (!gc->reglists) + return -ENODEV; + + if (cache->is_valid) { + *fileoutptr = cache->file; + return cache->status; + } + + ret = intel_guc_capture_getlistsize(guc, owner, type, classid, &size); + if (ret) { + cache->is_valid = true; + cache->file = NULL; + cache->size = 0; + cache->status = ret; + return ret; + } + + caplist = kzalloc(size, GFP_KERNEL); + if (!caplist) + return -ENOMEM; + + /* populate capture list header */ + tmp = caplist; + num_regs = guc_cap_list_num_regs(guc->capture.priv, owner, type, classid); + listnode = (struct guc_debug_capture_list *)tmp; + listnode->header.info = FIELD_PREP(GUC_CAPTURELISTHDR_NUMDESCR, (u32)num_regs); + + /* populate list of register descriptor */ + tmp += sizeof(struct guc_debug_capture_list); + guc_capture_list_init(guc, owner, type, classid, (struct guc_mmio_reg *)tmp, num_regs); + + /* ADS only takes file handles, so we keep that as our cache */ + file = shmem_create_from_data("guc-err-cap", caplist, size); + kfree(caplist); + if (IS_ERR(file)) { + drm_warn(&i915->drm, "GuC-capture: cant create shmem for caplist = 0x%016lx", PTR_ERR(file)); + return PTR_ERR(file); + } + + /* cache this list */ + cache->file = file; + cache->size = size; + cache->status = 0; + cache->is_valid = true; + + *fileoutptr = file; + + return 0; +} + +static void +guc_capture_free_ads_cache(struct __guc_state_capture_priv *gc) +{ + int i, j, k; + struct __guc_capture_ads_cache *cache; + + for (i = 0; i < GUC_CAPTURE_LIST_INDEX_MAX; ++i) { + for (j = 0; j < GUC_CAPTURE_LIST_TYPE_MAX; ++j) { + for (k = 0; k < GUC_MAX_ENGINE_CLASSES; ++k) { + cache = &gc->ads_cache[i][j][k]; + if (cache->is_valid && cache->file) + fput(cache->file); + } + } + } +} + +void intel_guc_capture_destroy(struct intel_guc *guc) +{ + if (!guc->capture.priv) + return; + + guc_capture_free_ads_cache(guc->capture.priv); + + kfree(guc->capture.priv); + guc->capture.priv = NULL; +} + +int intel_guc_capture_init(struct intel_guc *guc) +{ + guc->capture.priv = kzalloc(sizeof(*guc->capture.priv), GFP_KERNEL); + if (!guc->capture.priv) + return -ENOMEM; + + guc->capture.priv->reglists = guc_capture_get_device_reglist(guc); + + return 0; +} diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h new file mode 100644 index 000000000000..f05365239a2f --- /dev/null +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2021-2021 Intel Corporation + */ + +#ifndef _INTEL_GUC_CAPTURE_H +#define _INTEL_GUC_CAPTURE_H + +#include + +struct file; +struct guc_gt_system_info; +struct intel_guc; + +int intel_guc_capture_getlist(struct intel_guc *guc, u32 owner, u32 type, u32 classid, + struct file **fileptr); +int intel_guc_capture_getlistsize(struct intel_guc *guc, u32 owner, u32 type, u32 classid, + size_t *size); +void intel_guc_capture_destroy(struct intel_guc *guc); +int intel_guc_capture_init(struct intel_guc *guc); + +#endif /* _INTEL_GUC_CAPTURE_H */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h index 6a4612a852e2..b5f59c6a2424 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h @@ -297,6 +297,14 @@ enum { GUC_CAPTURE_LIST_INDEX_MAX = 2, }; +/*Register-types of GuC capture register lists */ +enum guc_capture_type { + GUC_CAPTURE_LIST_TYPE_GLOBAL = 0, + GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, + GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE, + GUC_CAPTURE_LIST_TYPE_MAX, +}; + /* GuC Additional Data Struct */ struct guc_ads { struct guc_mmio_reg_set reg_state_list[GUC_MAX_ENGINE_CLASSES][GUC_MAX_INSTANCES_PER_CLASS]; From patchwork Sat Feb 26 09:55:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Previn X-Patchwork-Id: 12761256 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C4B51C433FE for ; Sat, 26 Feb 2022 09:53:55 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 0D56E10E456; Sat, 26 Feb 2022 09:53:38 +0000 (UTC) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by gabe.freedesktop.org (Postfix) with ESMTPS id 6ACA110E401 for ; Sat, 26 Feb 2022 09:53:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1645869214; x=1677405214; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=YnH4dw6OqvLRfkQLJ6lr/FTFgiVrkdwLGXVUdkRE7rU=; b=ecda+MUR8NwhvjxFLplYqvZVr19PUd4AEmDVf082E2279WoOSiUX+XAb 1QY0tCNE+PwBn/XALUSg1YLX5mAH99Cds3I6xP0zY/+YluVjLO8xA7AHC /tT26MA50YmBXX+MpKasQ0jnEWITQvZPk2Qq8A+zbi0Ndfdnes1RIVTy6 yEGtzXc+36Kth+mblzAdERxpi7ebLiLVxPj6wimYzjOrlsYpNQTNinHgc EaoY5jdMFhlZA2K5rWl0eARUm99w4enFjFLcMh5DtLAKOkclB6kg1hZoi o+1Y7ckbbIeRTJqqSLaT+SqTG/m+JpLevWb5Z95kJcYkL9MYzzLryd+18 A==; X-IronPort-AV: E=McAfee;i="6200,9189,10269"; a="251480183" X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="251480183" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Feb 2022 01:53:33 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="506953222" Received: from aalteres-desk.fm.intel.com ([10.80.57.53]) by orsmga002.jf.intel.com with ESMTP; 26 Feb 2022 01:53:33 -0800 From: Alan Previn To: intel-gfx@lists.freedesktop.org Date: Sat, 26 Feb 2022 01:55:30 -0800 Message-Id: <20220226095541.1010534-3-alan.previn.teres.alexis@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> References: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v7 02/13] drm/i915/guc: Add XE_LP static registers for GuC error capture. X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alan Previn Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Add device specific tables and register lists to cover different engines class types for GuC error state capture for XE_LP products. Signed-off-by: Alan Previn Reviewed-by: Umesh Nerlige Ramappa --- .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 116 ++++++++++++++---- drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 4 +- 2 files changed, 97 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index 647a118aa3c3..fb3ca734ef97 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -19,43 +19,109 @@ /* * Define all device tables of GuC error capture register lists - * NOTE: For engine-registers, GuC only needs the register offsets - * from the engine-mmio-base + * NOTE1: For engine-registers, GuC only needs the register offsets + * from the engine-mmio-base */ +#define COMMON_GEN12BASE_GLOBAL() \ + {GEN12_FAULT_TLB_DATA0, 0, 0, "GEN12_FAULT_TLB_DATA0"}, \ + {GEN12_FAULT_TLB_DATA1, 0, 0, "GEN12_FAULT_TLB_DATA1"}, \ + {FORCEWAKE_MT, 0, 0, "FORCEWAKE"}, \ + {GEN12_AUX_ERR_DBG, 0, 0, "AUX_ERR_DBG"}, \ + {GEN12_GAM_DONE, 0, 0, "GAM_DONE"}, \ + {GEN12_RING_FAULT_REG, 0, 0, "FAULT_REG"} + +#define COMMON_GEN12BASE_ENGINE_INSTANCE() \ + {RING_PSMI_CTL(0), 0, 0, "RC PSMI"}, \ + {RING_ESR(0), 0, 0, "ESR"}, \ + {RING_DMA_FADD(0), 0, 0, "RING_DMA_FADD_LDW"}, \ + {RING_DMA_FADD_UDW(0), 0, 0, "RING_DMA_FADD_UDW"}, \ + {RING_IPEIR(0), 0, 0, "IPEIR"}, \ + {RING_IPEHR(0), 0, 0, "IPEHR"}, \ + {RING_INSTPS(0), 0, 0, "INSTPS"}, \ + {RING_BBADDR(0), 0, 0, "RING_BBADDR_LOW32"}, \ + {RING_BBADDR_UDW(0), 0, 0, "RING_BBADDR_UP32"}, \ + {RING_BBSTATE(0), 0, 0, "BB_STATE"}, \ + {CCID(0), 0, 0, "CCID"}, \ + {RING_ACTHD(0), 0, 0, "ACTHD_LDW"}, \ + {RING_ACTHD_UDW(0), 0, 0, "ACTHD_UDW"}, \ + {RING_INSTPM(0), 0, 0, "INSTPM"}, \ + {RING_INSTDONE(0), 0, 0, "INSTDONE"}, \ + {RING_NOPID(0), 0, 0, "RING_NOPID"}, \ + {RING_START(0), 0, 0, "START"}, \ + {RING_HEAD(0), 0, 0, "HEAD"}, \ + {RING_TAIL(0), 0, 0, "TAIL"}, \ + {RING_CTL(0), 0, 0, "CTL"}, \ + {RING_MI_MODE(0), 0, 0, "MODE"}, \ + {RING_CONTEXT_CONTROL(0), 0, 0, "RING_CONTEXT_CONTROL"}, \ + {RING_HWS_PGA(0), 0, 0, "HWS"}, \ + {RING_MODE_GEN7(0), 0, 0, "GFX_MODE"}, \ + {GEN8_RING_PDP_LDW(0, 0), 0, 0, "PDP0_LDW"}, \ + {GEN8_RING_PDP_UDW(0, 0), 0, 0, "PDP0_UDW"}, \ + {GEN8_RING_PDP_LDW(0, 1), 0, 0, "PDP1_LDW"}, \ + {GEN8_RING_PDP_UDW(0, 1), 0, 0, "PDP1_UDW"}, \ + {GEN8_RING_PDP_LDW(0, 2), 0, 0, "PDP2_LDW"}, \ + {GEN8_RING_PDP_UDW(0, 2), 0, 0, "PDP2_UDW"}, \ + {GEN8_RING_PDP_LDW(0, 3), 0, 0, "PDP3_LDW"}, \ + {GEN8_RING_PDP_UDW(0, 3), 0, 0, "PDP3_UDW"} + +#define COMMON_GEN12BASE_HAS_EU() \ + {EIR, 0, 0, "EIR"} + +#define COMMON_GEN12BASE_RENDER() \ + {GEN7_SC_INSTDONE, 0, 0, "GEN7_SC_INSTDONE"}, \ + {GEN12_SC_INSTDONE_EXTRA, 0, 0, "GEN12_SC_INSTDONE_EXTRA"}, \ + {GEN12_SC_INSTDONE_EXTRA2, 0, 0, "GEN12_SC_INSTDONE_EXTRA2"} + +#define COMMON_GEN12BASE_VEC() \ + {GEN12_SFC_DONE(0), 0, 0, "SFC_DONE[0]"}, \ + {GEN12_SFC_DONE(1), 0, 0, "SFC_DONE[1]"}, \ + {GEN12_SFC_DONE(2), 0, 0, "SFC_DONE[2]"}, \ + {GEN12_SFC_DONE(3), 0, 0, "SFC_DONE[3]"} + /* XE_LPD - Global */ static const struct __guc_mmio_reg_descr xe_lpd_global_regs[] = { - {GEN12_RING_FAULT_REG, 0, 0, "GEN12_RING_FAULT_REG"} + COMMON_GEN12BASE_GLOBAL(), }; /* XE_LPD - Render / Compute Per-Class */ static const struct __guc_mmio_reg_descr xe_lpd_rc_class_regs[] = { - {EIR, 0, 0, "EIR"} + COMMON_GEN12BASE_HAS_EU(), + COMMON_GEN12BASE_RENDER(), }; /* XE_LPD - Render / Compute Per-Engine-Instance */ static const struct __guc_mmio_reg_descr xe_lpd_rc_inst_regs[] = { - {RING_HEAD(0), 0, 0, "RING_HEAD"}, - {RING_TAIL(0), 0, 0, "RING_TAIL"}, + COMMON_GEN12BASE_ENGINE_INSTANCE(), }; /* XE_LPD - Media Decode/Encode Per-Class */ static const struct __guc_mmio_reg_descr xe_lpd_vd_class_regs[] = { + COMMON_GEN12BASE_ENGINE_INSTANCE(), }; /* XE_LPD - Media Decode/Encode Per-Engine-Instance */ static const struct __guc_mmio_reg_descr xe_lpd_vd_inst_regs[] = { - {RING_HEAD(0), 0, 0, "RING_HEAD"}, - {RING_TAIL(0), 0, 0, "RING_TAIL"}, + COMMON_GEN12BASE_ENGINE_INSTANCE(), }; /* XE_LPD - Video Enhancement Per-Class */ static const struct __guc_mmio_reg_descr xe_lpd_vec_class_regs[] = { + COMMON_GEN12BASE_VEC(), }; /* XE_LPD - Video Enhancement Per-Engine-Instance */ static const struct __guc_mmio_reg_descr xe_lpd_vec_inst_regs[] = { - {RING_HEAD(0), 0, 0, "RING_HEAD"}, - {RING_TAIL(0), 0, 0, "RING_TAIL"}, + COMMON_GEN12BASE_ENGINE_INSTANCE(), +}; + +/* XE_LPD - Blitter Per-Engine-Instance */ +static const struct __guc_mmio_reg_descr xe_lpd_blt_inst_regs[] = { + COMMON_GEN12BASE_ENGINE_INSTANCE(), +}; + +/* XE_LPD - Blitter Per-Class */ +/* XE_LPD - Media Decode/Encode Per-Class */ +static const struct __guc_mmio_reg_descr empty_regs_list[] = { }; #define TO_GCAP_DEF_OWNER(x) (GUC_CAPTURE_LIST_INDEX_##x) @@ -74,10 +140,12 @@ static const struct __guc_mmio_reg_descr_group xe_lpd_lists[] = { MAKE_REGLIST(xe_lpd_global_regs, PF, GLOBAL, 0), MAKE_REGLIST(xe_lpd_rc_class_regs, PF, ENGINE_CLASS, GUC_RENDER_CLASS), MAKE_REGLIST(xe_lpd_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_RENDER_CLASS), - MAKE_REGLIST(xe_lpd_vd_class_regs, PF, ENGINE_CLASS, GUC_VIDEO_CLASS), + MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_VIDEO_CLASS), MAKE_REGLIST(xe_lpd_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEO_CLASS), MAKE_REGLIST(xe_lpd_vec_class_regs, PF, ENGINE_CLASS, GUC_VIDEOENHANCE_CLASS), MAKE_REGLIST(xe_lpd_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEOENHANCE_CLASS), + MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_BLITTER_CLASS), + MAKE_REGLIST(xe_lpd_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_BLITTER_CLASS), {} }; @@ -191,20 +259,24 @@ guc_capture_list_init(struct intel_guc *guc, u32 owner, u32 type, u32 classid, return -ENODEV; match = guc_capture_get_one_list(reglists, owner, type, classid); - if (match) { - for (i = 0; i < num_entries && i < match->num_regs; ++i) { - ptr[i].offset = match->list[i].reg.reg; - ptr[i].value = 0xDEADF00D; - ptr[i].flags = match->list[i].flags; - ptr[i].mask = match->list[i].mask; - } - return 0; + if (!match) { + guc_capture_warn_with_list_info(i915, "Missing register list init", owner, type, + classid); + return -ENODATA; + } + + for (i = 0; i < num_entries && i < match->num_regs; ++i) { + ptr[i].offset = match->list[i].reg.reg; + ptr[i].value = 0xDEADF00D; + ptr[i].flags = match->list[i].flags; + ptr[i].mask = match->list[i].mask; } - guc_capture_warn_with_list_info(i915, "Missing register list init", owner, type, - classid); + if (i < num_entries) + drm_dbg(&i915->drm, "GuC-capture: Init reglist short %d out %d.\n", + (int)i, (int)num_entries); - return -ENODATA; + return 0; } static int diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h index b5f59c6a2424..14ab4c9588ae 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h @@ -271,10 +271,12 @@ struct guc_mmio_reg { u32 offset; u32 value; u32 flags; - u32 mask; #define GUC_REGSET_MASKED BIT(0) #define GUC_REGSET_MASKED_WITH_VALUE BIT(2) #define GUC_REGSET_RESTORE_ONLY BIT(3) +#define GUC_REGSET_STEERING_GROUP GENMASK(15, 12) +#define GUC_REGSET_STEERING_INSTANCE GENMASK(23, 20) + u32 mask; } __packed; /* GuC register sets */ From patchwork Sat Feb 26 09:55:31 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Previn X-Patchwork-Id: 12761249 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id BAC80C433FE for ; Sat, 26 Feb 2022 09:53:47 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id D9D1110E40A; Sat, 26 Feb 2022 09:53:35 +0000 (UTC) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by gabe.freedesktop.org (Postfix) with ESMTPS id 8816310E3FB for ; Sat, 26 Feb 2022 09:53:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1645869214; x=1677405214; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=pcAbaMZhcGFKVYJmaoorXpqkshiueknLurJrK2LOGpE=; b=fGHiR1XVHIaSMhHZUJdW3MvA4Ob1iL+JW68HI2LlXsQU8iGTiqYOY43i STPlC5SGuIZp0K06IgOx2s2qa+ToN1rLoAeWQtb/bSeChI4iGv/WSr5tX aUx1bK3E/XZeM0+OcINUI4qNU+RrftvtKElXTbINpb7IKZPpK4QfrCsCB hCXHysu5cvcghJNkY5tszebP8lFBMg8OCoS9E9lh/x0QmimSS0UmtNJFi HmLrX+vhjy/orQD2uaHMuDaXSc5Sq7D2d8cXswmB/AZ8DmQoxrG2YYbOt qPkGnmRC1tzHjrV/0tpkmt6lsdc4b2VcvzZyKWAibBJ0auwNrloREbIpe w==; X-IronPort-AV: E=McAfee;i="6200,9189,10269"; a="251480184" X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="251480184" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Feb 2022 01:53:34 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="506953225" Received: from aalteres-desk.fm.intel.com ([10.80.57.53]) by orsmga002.jf.intel.com with ESMTP; 26 Feb 2022 01:53:33 -0800 From: Alan Previn To: intel-gfx@lists.freedesktop.org Date: Sat, 26 Feb 2022 01:55:31 -0800 Message-Id: <20220226095541.1010534-4-alan.previn.teres.alexis@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> References: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v7 03/13] drm/i915/guc: Add XE_LP steered register lists support X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alan Previn Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Add the ability for runtime allocation and freeing of steered register list extentions that depend on the detected HW config fuses. Signed-off-by: Alan Previn Reviewed-by: Umesh Nerlige Ramappa --- drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h | 9 + .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 175 ++++++++++++++++-- 2 files changed, 173 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h index 858f85478636..27b89539d0d5 100644 --- a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h @@ -51,6 +51,7 @@ struct __guc_mmio_reg_descr_group { u32 owner; /* see enum guc_capture_owner */ u32 type; /* see enum guc_capture_type */ u32 engine; /* as per MAX_ENGINE_CLASS */ + struct __guc_mmio_reg_descr *extlist; /* only used for steered registers */ }; /** @@ -78,6 +79,14 @@ struct __guc_state_capture_priv { */ const struct __guc_mmio_reg_descr_group *reglists; + /** + * @extlists: allocated table of steered register lists used for error-capture state. + * + * NOTE: steered registers have multiple instances depending on the HW configuration + * (slices or dual-sub-slices) and thus depends on HW fuses discovered at startup + */ + struct __guc_mmio_reg_descr_group *extlists; + /** * @ads_cache: cached register lists that is ADS format ready */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index fb3ca734ef97..6370943ea300 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -133,6 +133,7 @@ static const struct __guc_mmio_reg_descr empty_regs_list[] = { TO_GCAP_DEF_OWNER(regsowner), \ TO_GCAP_DEF_TYPE(regstype), \ class, \ + NULL, \ } /* List of lists */ @@ -150,28 +151,33 @@ static const struct __guc_mmio_reg_descr_group xe_lpd_lists[] = { }; static const struct __guc_mmio_reg_descr_group * -guc_capture_get_device_reglist(struct intel_guc *guc) +guc_capture_get_one_list(const struct __guc_mmio_reg_descr_group *reglists, + u32 owner, u32 type, u32 id) { - struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + int i; - if (IS_TIGERLAKE(i915) || IS_ROCKETLAKE(i915) || - IS_ALDERLAKE_S(i915) || IS_ALDERLAKE_P(i915)) { - return xe_lpd_lists; + if (!reglists) + return NULL; + + for (i = 0; reglists[i].list; ++i) { + if (reglists[i].owner == owner && reglists[i].type == type && + (reglists[i].engine == id || reglists[i].type == GUC_CAPTURE_LIST_TYPE_GLOBAL)) + return ®lists[i]; } return NULL; } -static const struct __guc_mmio_reg_descr_group * -guc_capture_get_one_list(const struct __guc_mmio_reg_descr_group *reglists, - u32 owner, u32 type, u32 id) +static struct __guc_mmio_reg_descr_group * +guc_capture_get_one_ext_list(struct __guc_mmio_reg_descr_group *reglists, + u32 owner, u32 type, u32 id) { int i; if (!reglists) return NULL; - for (i = 0; reglists[i].list; ++i) { + for (i = 0; reglists[i].extlist; ++i) { if (reglists[i].owner == owner && reglists[i].type == type && (reglists[i].engine == id || reglists[i].type == GUC_CAPTURE_LIST_TYPE_GLOBAL)) return ®lists[i]; @@ -180,6 +186,127 @@ guc_capture_get_one_list(const struct __guc_mmio_reg_descr_group *reglists, return NULL; } +static void guc_capture_free_extlists(struct __guc_mmio_reg_descr_group *reglists) +{ + int i = 0; + + if (!reglists) + return; + + while (reglists[i].extlist) + kfree(reglists[i++].extlist); +} + +struct __ext_steer_reg { + const char *name; + i915_reg_t reg; +}; + +static const struct __ext_steer_reg xe_extregs[] = { + {"GEN7_SAMPLER_INSTDONE", GEN7_SAMPLER_INSTDONE}, + {"GEN7_ROW_INSTDONE", GEN7_ROW_INSTDONE} +}; + +static void __fill_ext_reg(struct __guc_mmio_reg_descr *ext, + const struct __ext_steer_reg *extlist, + int slice_id, int subslice_id) +{ + ext->reg = extlist->reg; + ext->flags = FIELD_PREP(GUC_REGSET_STEERING_GROUP, slice_id); + ext->flags |= FIELD_PREP(GUC_REGSET_STEERING_INSTANCE, subslice_id); + ext->regname = extlist->name; +} + +static int +__alloc_ext_regs(struct __guc_mmio_reg_descr_group *newlist, + const struct __guc_mmio_reg_descr_group *rootlist, int num_regs) +{ + struct __guc_mmio_reg_descr *list; + + list = kcalloc(num_regs, sizeof(struct __guc_mmio_reg_descr), GFP_KERNEL); + if (!list) + return -ENOMEM; + + newlist->extlist = list; + newlist->num_regs = num_regs; + newlist->owner = rootlist->owner; + newlist->engine = rootlist->engine; + newlist->type = rootlist->type; + + return 0; +} + +static void +guc_capture_alloc_steered_lists_xe_lpd(struct intel_guc *guc, + const struct __guc_mmio_reg_descr_group *lists) +{ + struct intel_gt *gt = guc_to_gt(guc); + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + int slice, subslice, i, num_steer_regs, num_tot_regs = 0; + const struct __guc_mmio_reg_descr_group *list; + struct __guc_mmio_reg_descr_group *extlists; + struct __guc_mmio_reg_descr *extarray; + struct sseu_dev_info *sseu; + + /* In XE_LPD we only have steered registers for the render-class */ + list = guc_capture_get_one_list(lists, GUC_CAPTURE_LIST_INDEX_PF, + GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, GUC_RENDER_CLASS); + /* skip if extlists was previously allocated */ + if (!list || guc->capture.priv->extlists) + return; + + num_steer_regs = ARRAY_SIZE(xe_extregs); + + sseu = >->info.sseu; + for_each_instdone_slice_subslice(i915, sseu, slice, subslice) + num_tot_regs += num_steer_regs; + + if (!num_tot_regs) + return; + + /* allocate an extra for an end marker */ + extlists = kcalloc(2, sizeof(struct __guc_mmio_reg_descr_group), GFP_KERNEL); + if (!extlists) + return; + + if (__alloc_ext_regs(&extlists[0], list, num_tot_regs)) { + kfree(extlists); + return; + } + + extarray = extlists[0].extlist; + for_each_instdone_slice_subslice(i915, sseu, slice, subslice) { + for (i = 0; i < num_steer_regs; ++i) { + __fill_ext_reg(extarray, &xe_extregs[i], slice, subslice); + ++extarray; + } + } + + guc->capture.priv->extlists = extlists; +} + +static const struct __guc_mmio_reg_descr_group * +guc_capture_get_device_reglist(struct intel_guc *guc) +{ + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + + if (IS_TIGERLAKE(i915) || IS_ROCKETLAKE(i915) || + IS_ALDERLAKE_S(i915) || IS_ALDERLAKE_P(i915)) { + /* + * For certain engine classes, there are slice and subslice + * level registers requiring steering. We allocate and populate + * these at init time based on hw config add it as an extension + * list at the end of the pre-populated render list. + */ + guc_capture_alloc_steered_lists_xe_lpd(guc, xe_lpd_lists); + return xe_lpd_lists; + } + + drm_warn(&i915->drm, "No GuC-capture register lists\n"); + + return NULL; +} + static const char * __stringify_owner(u32 owner) { @@ -250,10 +377,12 @@ static int guc_capture_list_init(struct intel_guc *guc, u32 owner, u32 type, u32 classid, struct guc_mmio_reg *ptr, u16 num_entries) { - u32 i = 0; + u32 i = 0, j = 0; struct drm_i915_private *i915 = guc_to_gt(guc)->i915; const struct __guc_mmio_reg_descr_group *reglists = guc->capture.priv->reglists; + struct __guc_mmio_reg_descr_group *extlists = guc->capture.priv->extlists; const struct __guc_mmio_reg_descr_group *match; + struct __guc_mmio_reg_descr_group *matchext; if (!reglists) return -ENODEV; @@ -272,6 +401,17 @@ guc_capture_list_init(struct intel_guc *guc, u32 owner, u32 type, u32 classid, ptr[i].mask = match->list[i].mask; } + matchext = guc_capture_get_one_ext_list(extlists, owner, type, classid); + if (matchext) { + for (i = match->num_regs, j = 0; i < num_entries && + i < (match->num_regs + matchext->num_regs) && + j < matchext->num_regs; ++i, ++j) { + ptr[i].offset = matchext->extlist[j].reg.reg; + ptr[i].value = 0xDEADF00D; + ptr[i].flags = matchext->extlist[j].flags; + ptr[i].mask = matchext->extlist[j].mask; + } + } if (i < num_entries) drm_dbg(&i915->drm, "GuC-capture: Init reglist short %d out %d.\n", (int)i, (int)num_entries); @@ -283,12 +423,20 @@ static int guc_cap_list_num_regs(struct __guc_state_capture_priv *gc, u32 owner, u32 type, u32 classid) { const struct __guc_mmio_reg_descr_group *match; + struct __guc_mmio_reg_descr_group *matchext; + int num_regs; match = guc_capture_get_one_list(gc->reglists, owner, type, classid); if (!match) return 0; - return match->num_regs; + num_regs = match->num_regs; + + matchext = guc_capture_get_one_ext_list(gc->extlists, owner, type, classid); + if (matchext) + num_regs += matchext->num_regs; + + return num_regs; } int @@ -408,6 +556,11 @@ void intel_guc_capture_destroy(struct intel_guc *guc) guc_capture_free_ads_cache(guc->capture.priv); + if (guc->capture.priv->extlists) { + guc_capture_free_extlists(guc->capture.priv->extlists); + kfree(guc->capture.priv->extlists); + } + kfree(guc->capture.priv); guc->capture.priv = NULL; } From patchwork Sat Feb 26 09:55:32 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Previn X-Patchwork-Id: 12761255 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id CEF40C4332F for ; Sat, 26 Feb 2022 09:53:54 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 0ABA510E44D; Sat, 26 Feb 2022 09:53:37 +0000 (UTC) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by gabe.freedesktop.org (Postfix) with ESMTPS id A64C310E401 for ; Sat, 26 Feb 2022 09:53:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1645869214; x=1677405214; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=4G2au+IyHKFTYi2BZnUQN1RDDbgHMzBcAC3PVo6ho0U=; b=ktiIGWtftwqqCyNsU3sA0JcosRgyafyBAbtXsoWZKtTGjlaOAl6vfQ4b 7ZDJTGG5zJYgD2hc+BsAituwVBOoKK8fohllOZc1IJRL0ySJD+uyfZtFK AG64AE0HuYL9U2zD8SdhQfmadz85HLa8M+lM7+b5/ukDc8SpRRStl/+7F /e2ySj7r1xyHCcZqGmenySWX6FTBzNKog7Tgw+0K895CvQzpYkhzXzMiV MhI+W0ulNSPSKnkBdT0hmx1nb27c4CYF0QGS/3JGT6JVEAF0AFXpDXr1A /wlY5TOmH6VtSEIZxyNZWX2Vf7hlE4/JqypKyu0hgaax/noD2mRAyTMHl g==; X-IronPort-AV: E=McAfee;i="6200,9189,10269"; a="251480185" X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="251480185" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Feb 2022 01:53:34 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="506953228" Received: from aalteres-desk.fm.intel.com ([10.80.57.53]) by orsmga002.jf.intel.com with ESMTP; 26 Feb 2022 01:53:33 -0800 From: Alan Previn To: intel-gfx@lists.freedesktop.org Date: Sat, 26 Feb 2022 01:55:32 -0800 Message-Id: <20220226095541.1010534-5-alan.previn.teres.alexis@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> References: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v7 04/13] drm/i915/guc: Add DG2 registers for GuC error state capture. X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alan Previn Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Add additional DG2 registers for GuC error state capture. Signed-off-by: Alan Previn Reviewed-by: Umesh Nerlige Ramappa --- .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 80 ++++++++++++++++++- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index 6370943ea300..c8441ca1566b 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -285,20 +285,96 @@ guc_capture_alloc_steered_lists_xe_lpd(struct intel_guc *guc, guc->capture.priv->extlists = extlists; } +static const struct __ext_steer_reg xehpg_extregs[] = { + {"XEHPG_INSTDONE_GEOM_SVG", XEHPG_INSTDONE_GEOM_SVG} +}; + +static bool __has_xehpg_extregs(u32 ipver) +{ + return (ipver >= IP_VER(12, 55)); +} + +static void +guc_capture_alloc_steered_lists_xe_hpg(struct intel_guc *guc, + const struct __guc_mmio_reg_descr_group *lists, + u32 ipver) +{ + struct intel_gt *gt = guc_to_gt(guc); + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + struct sseu_dev_info *sseu; + int slice, subslice, i, iter, num_steer_regs, num_tot_regs = 0; + const struct __guc_mmio_reg_descr_group *list; + struct __guc_mmio_reg_descr_group *extlists; + struct __guc_mmio_reg_descr *extarray; + + /* In XE_LP / HPG we only have render-class steering registers during error-capture */ + list = guc_capture_get_one_list(lists, GUC_CAPTURE_LIST_INDEX_PF, + GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, GUC_RENDER_CLASS); + /* skip if extlists was previously allocated */ + if (!list || guc->capture.priv->extlists) + return; + + num_steer_regs = ARRAY_SIZE(xe_extregs); + if (__has_xehpg_extregs(ipver)) + num_steer_regs += ARRAY_SIZE(xehpg_extregs); + + sseu = >->info.sseu; + for_each_instdone_gslice_dss_xehp(i915, sseu, iter, slice, subslice) { + num_tot_regs += num_steer_regs; + } + + if (!num_tot_regs) + return; + + /* allocate an extra for an end marker */ + extlists = kcalloc(2, sizeof(struct __guc_mmio_reg_descr_group), GFP_KERNEL); + if (!extlists) + return; + + if (__alloc_ext_regs(&extlists[0], list, num_tot_regs)) { + kfree(extlists); + return; + } + + extarray = extlists[0].extlist; + for_each_instdone_gslice_dss_xehp(i915, sseu, iter, slice, subslice) { + for (i = 0; i < ARRAY_SIZE(xe_extregs); ++i) { + __fill_ext_reg(extarray, &xe_extregs[i], slice, subslice); + ++extarray; + } + if (__has_xehpg_extregs(ipver)) { + for (i = 0; i < ARRAY_SIZE(xehpg_extregs); ++i) { + __fill_ext_reg(extarray, &xehpg_extregs[i], slice, subslice); + ++extarray; + } + } + } + + drm_dbg(&i915->drm, "GuC-capture found %d-ext-regs.\n", num_tot_regs); + guc->capture.priv->extlists = extlists; +} + static const struct __guc_mmio_reg_descr_group * guc_capture_get_device_reglist(struct intel_guc *guc) { struct drm_i915_private *i915 = guc_to_gt(guc)->i915; if (IS_TIGERLAKE(i915) || IS_ROCKETLAKE(i915) || - IS_ALDERLAKE_S(i915) || IS_ALDERLAKE_P(i915)) { + IS_ALDERLAKE_S(i915) || IS_ALDERLAKE_P(i915) || + IS_DG2(i915) || IS_XEHPSDV(i915)) { /* * For certain engine classes, there are slice and subslice * level registers requiring steering. We allocate and populate * these at init time based on hw config add it as an extension * list at the end of the pre-populated render list. */ - guc_capture_alloc_steered_lists_xe_lpd(guc, xe_lpd_lists); + if (IS_DG2(i915)) + guc_capture_alloc_steered_lists_xe_hpg(guc, xe_lpd_lists, IP_VER(12, 55)); + else if (IS_XEHPSDV(i915)) + guc_capture_alloc_steered_lists_xe_hpg(guc, xe_lpd_lists, IP_VER(12, 50)); + else + guc_capture_alloc_steered_lists_xe_lpd(guc, xe_lpd_lists); + return xe_lpd_lists; } From patchwork Sat Feb 26 09:55:33 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Previn X-Patchwork-Id: 12761252 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 2F72EC433FE for ; Sat, 26 Feb 2022 09:53:52 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 92DF310E472; Sat, 26 Feb 2022 09:53:36 +0000 (UTC) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by gabe.freedesktop.org (Postfix) with ESMTPS id C305D10E3FB for ; Sat, 26 Feb 2022 09:53:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1645869214; x=1677405214; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=op1JmaoJ9s+1oGSjs6slbeenHlicqkRh30+X24fjxcE=; b=AH/Fdt/UkBQeEmz4MU67gAGBZ4fZ6f+cUfcHUwWwV5Nqewq+ERBEt8Dm DiF/ED1lgQYZOatoU8MXDAmDfz5ZZ9R+9uLxdfv8sdDP/gWKpPyBnCCsb pGLOMB+59NJJO0BY7IAUyihWRG9Q+Kshfn7TKzU+X4TmDR4S3rKrMjEb6 Zhr9fHnR9bfiDahceB/s4xs+56uwHk2IJ22pFGndFFPwTIUWfRTelAfHE IhH6oFubNo8iwCURfoNuWQSuMRX/dYEyyYBNHgxBSSJlF74j0r899y5Yw QQk8T8BQQ/7/kxpLxtemX/CtU4tj/lOeX6qmw3YGil/wQ219B3JYkV7ZT g==; X-IronPort-AV: E=McAfee;i="6200,9189,10269"; a="251480186" X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="251480186" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Feb 2022 01:53:34 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="506953231" Received: from aalteres-desk.fm.intel.com ([10.80.57.53]) by orsmga002.jf.intel.com with ESMTP; 26 Feb 2022 01:53:33 -0800 From: Alan Previn To: intel-gfx@lists.freedesktop.org Date: Sat, 26 Feb 2022 01:55:33 -0800 Message-Id: <20220226095541.1010534-6-alan.previn.teres.alexis@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> References: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v7 05/13] drm/i915/guc: Add Gen9 registers for GuC error state capture. X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alan Previn Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Abstract out a Gen9 register list as the default for all other platforms we don't yet formally support GuC submission on. Signed-off-by: Alan Previn Reviewed-by: Umesh Nerlige Ramappa --- .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 82 +++++++++++++------ 1 file changed, 59 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index c8441ca1566b..eb22f979d720 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -22,15 +22,24 @@ * NOTE1: For engine-registers, GuC only needs the register offsets * from the engine-mmio-base */ +#define COMMON_BASE_GLOBAL() \ + {FORCEWAKE_MT, 0, 0, "FORCEWAKE"} + +#define COMMON_GEN9BASE_GLOBAL() \ + {GEN8_FAULT_TLB_DATA0, 0, 0, "GEN8_FAULT_TLB_DATA0"}, \ + {GEN8_FAULT_TLB_DATA1, 0, 0, "GEN8_FAULT_TLB_DATA1"}, \ + {ERROR_GEN6, 0, 0, "ERROR_GEN6"}, \ + {DONE_REG, 0, 0, "DONE_REG"}, \ + {HSW_GTT_CACHE_EN, 0, 0, "HSW_GTT_CACHE_EN"} + #define COMMON_GEN12BASE_GLOBAL() \ {GEN12_FAULT_TLB_DATA0, 0, 0, "GEN12_FAULT_TLB_DATA0"}, \ {GEN12_FAULT_TLB_DATA1, 0, 0, "GEN12_FAULT_TLB_DATA1"}, \ - {FORCEWAKE_MT, 0, 0, "FORCEWAKE"}, \ {GEN12_AUX_ERR_DBG, 0, 0, "AUX_ERR_DBG"}, \ {GEN12_GAM_DONE, 0, 0, "GAM_DONE"}, \ {GEN12_RING_FAULT_REG, 0, 0, "FAULT_REG"} -#define COMMON_GEN12BASE_ENGINE_INSTANCE() \ +#define COMMON_BASE_ENGINE_INSTANCE() \ {RING_PSMI_CTL(0), 0, 0, "RC PSMI"}, \ {RING_ESR(0), 0, 0, "ESR"}, \ {RING_DMA_FADD(0), 0, 0, "RING_DMA_FADD_LDW"}, \ @@ -64,11 +73,13 @@ {GEN8_RING_PDP_LDW(0, 3), 0, 0, "PDP3_LDW"}, \ {GEN8_RING_PDP_UDW(0, 3), 0, 0, "PDP3_UDW"} -#define COMMON_GEN12BASE_HAS_EU() \ +#define COMMON_BASE_HAS_EU() \ {EIR, 0, 0, "EIR"} +#define COMMON_BASE_RENDER() \ + {GEN7_SC_INSTDONE, 0, 0, "GEN7_SC_INSTDONE"} + #define COMMON_GEN12BASE_RENDER() \ - {GEN7_SC_INSTDONE, 0, 0, "GEN7_SC_INSTDONE"}, \ {GEN12_SC_INSTDONE_EXTRA, 0, 0, "GEN12_SC_INSTDONE_EXTRA"}, \ {GEN12_SC_INSTDONE_EXTRA2, 0, 0, "GEN12_SC_INSTDONE_EXTRA2"} @@ -80,28 +91,26 @@ /* XE_LPD - Global */ static const struct __guc_mmio_reg_descr xe_lpd_global_regs[] = { + COMMON_BASE_GLOBAL(), + COMMON_GEN9BASE_GLOBAL(), COMMON_GEN12BASE_GLOBAL(), }; /* XE_LPD - Render / Compute Per-Class */ static const struct __guc_mmio_reg_descr xe_lpd_rc_class_regs[] = { - COMMON_GEN12BASE_HAS_EU(), + COMMON_BASE_HAS_EU(), + COMMON_BASE_RENDER(), COMMON_GEN12BASE_RENDER(), }; -/* XE_LPD - Render / Compute Per-Engine-Instance */ +/* GEN9/XE_LPD - Render / Compute Per-Engine-Instance */ static const struct __guc_mmio_reg_descr xe_lpd_rc_inst_regs[] = { - COMMON_GEN12BASE_ENGINE_INSTANCE(), + COMMON_BASE_ENGINE_INSTANCE(), }; -/* XE_LPD - Media Decode/Encode Per-Class */ -static const struct __guc_mmio_reg_descr xe_lpd_vd_class_regs[] = { - COMMON_GEN12BASE_ENGINE_INSTANCE(), -}; - -/* XE_LPD - Media Decode/Encode Per-Engine-Instance */ +/* GEN9/XE_LPD - Media Decode/Encode Per-Engine-Instance */ static const struct __guc_mmio_reg_descr xe_lpd_vd_inst_regs[] = { - COMMON_GEN12BASE_ENGINE_INSTANCE(), + COMMON_BASE_ENGINE_INSTANCE(), }; /* XE_LPD - Video Enhancement Per-Class */ @@ -109,18 +118,33 @@ static const struct __guc_mmio_reg_descr xe_lpd_vec_class_regs[] = { COMMON_GEN12BASE_VEC(), }; -/* XE_LPD - Video Enhancement Per-Engine-Instance */ +/* GEN9/XE_LPD - Video Enhancement Per-Engine-Instance */ static const struct __guc_mmio_reg_descr xe_lpd_vec_inst_regs[] = { - COMMON_GEN12BASE_ENGINE_INSTANCE(), + COMMON_BASE_ENGINE_INSTANCE(), }; -/* XE_LPD - Blitter Per-Engine-Instance */ +/* GEN9/XE_LPD - Blitter Per-Engine-Instance */ static const struct __guc_mmio_reg_descr xe_lpd_blt_inst_regs[] = { - COMMON_GEN12BASE_ENGINE_INSTANCE(), + COMMON_BASE_ENGINE_INSTANCE(), }; -/* XE_LPD - Blitter Per-Class */ -/* XE_LPD - Media Decode/Encode Per-Class */ +/* GEN9 - Global */ +static const struct __guc_mmio_reg_descr default_global_regs[] = { + COMMON_BASE_GLOBAL(), + COMMON_GEN9BASE_GLOBAL(), +}; + +static const struct __guc_mmio_reg_descr default_rc_class_regs[] = { + COMMON_BASE_HAS_EU(), + COMMON_BASE_RENDER(), +}; + +/* + * Empty lists: + * GEN9/XE_LPD - Blitter Per-Class + * GEN9/XE_LPD - Media Decode/Encode Per-Class + * GEN9 - VEC Class + */ static const struct __guc_mmio_reg_descr empty_regs_list[] = { }; @@ -137,6 +161,19 @@ static const struct __guc_mmio_reg_descr empty_regs_list[] = { } /* List of lists */ +static struct __guc_mmio_reg_descr_group default_lists[] = { + MAKE_REGLIST(default_global_regs, PF, GLOBAL, 0), + MAKE_REGLIST(default_rc_class_regs, PF, ENGINE_CLASS, GUC_RENDER_CLASS), + MAKE_REGLIST(xe_lpd_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_RENDER_CLASS), + MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_VIDEO_CLASS), + MAKE_REGLIST(xe_lpd_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEO_CLASS), + MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_VIDEOENHANCE_CLASS), + MAKE_REGLIST(xe_lpd_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEOENHANCE_CLASS), + MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_BLITTER_CLASS), + MAKE_REGLIST(xe_lpd_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_BLITTER_CLASS), + {} +}; + static const struct __guc_mmio_reg_descr_group xe_lpd_lists[] = { MAKE_REGLIST(xe_lpd_global_regs, PF, GLOBAL, 0), MAKE_REGLIST(xe_lpd_rc_class_regs, PF, ENGINE_CLASS, GUC_RENDER_CLASS), @@ -378,9 +415,8 @@ guc_capture_get_device_reglist(struct intel_guc *guc) return xe_lpd_lists; } - drm_warn(&i915->drm, "No GuC-capture register lists\n"); - - return NULL; + /* if GuC submission is enabled on a non-POR platform, just use a common baseline */ + return default_lists; } static const char * From patchwork Sat Feb 26 09:55:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Previn X-Patchwork-Id: 12761251 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E68C5C433F5 for ; Sat, 26 Feb 2022 09:53:50 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 5AFCF10E462; Sat, 26 Feb 2022 09:53:36 +0000 (UTC) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by gabe.freedesktop.org (Postfix) with ESMTPS id DED2110E401 for ; Sat, 26 Feb 2022 09:53:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1645869214; x=1677405214; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=3FXB6zbaWGzwfJZCwKueTP3egwTX/dnpNvdykQg2WDc=; b=afO2DBduOb9ediap88Tin/S8czkeQAUJ4OaEywq8VZ/tU6p0Bc9wNtn7 U22gvUgkzHCQDP2nuJktwhCIw8/ng+Xsl4nEWDgB5F0aoYhAKpXWj5USE uOVPtqU2bhxveOjUH2pLkQ1nRFrkVT/97GsUIcN3fCMFX4K6fzkuiTKfQ JFy0cUpJEg0yBeb7/97eQLZhMdWMF/wvb0v+i0HMDGfJ4TyQ7ieC4Gf1u hLtP497e6BjAF9MmhgcDRkQBaRjnEn0/DKSvlw79vcYlJu1rMtBs7d2H2 q3CsuiOy1QH0geEe6jGl7U4uXXzfX1Oh8BuViPkSi2u6OQiuojAVSgTgT g==; X-IronPort-AV: E=McAfee;i="6200,9189,10269"; a="251480187" X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="251480187" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Feb 2022 01:53:34 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="506953234" Received: from aalteres-desk.fm.intel.com ([10.80.57.53]) by orsmga002.jf.intel.com with ESMTP; 26 Feb 2022 01:53:34 -0800 From: Alan Previn To: intel-gfx@lists.freedesktop.org Date: Sat, 26 Feb 2022 01:55:34 -0800 Message-Id: <20220226095541.1010534-7-alan.previn.teres.alexis@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> References: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v7 06/13] drm/i915/guc: Add GuC's error state capture output structures. X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alan Previn Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Add GuC's error capture output structures and definitions as how they would appear in GuC log buffer's error capture subregion after an error state capture G2H event notification. Signed-off-by: Alan Previn Reviewed-by: Matthew Brost --- drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h index 27b89539d0d5..d5cb7d5d4ca7 100644 --- a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h @@ -54,6 +54,53 @@ struct __guc_mmio_reg_descr_group { struct __guc_mmio_reg_descr *extlist; /* only used for steered registers */ }; +/** + * struct guc_state_capture_header_t / struct guc_state_capture_t / + * guc_state_capture_group_header_t / guc_state_capture_group_t + * + * Prior to resetting engines that have hung or faulted, GuC microkernel + * reports the engine error-state (register values that was read) by + * logging them into the shared GuC log buffer using these hierarchy + * of structures. + */ +struct guc_state_capture_header_t { + u32 owner; +#define CAP_HDR_CAPTURE_VFID GENMASK(7, 0) + u32 info; +#define CAP_HDR_CAPTURE_TYPE GENMASK(3, 0) /* see enum guc_capture_type */ +#define CAP_HDR_ENGINE_CLASS GENMASK(7, 4) /* see GUC_MAX_ENGINE_CLASSES */ +#define CAP_HDR_ENGINE_INSTANCE GENMASK(11, 8) + u32 lrca; /* if type-instance, LRCA (address) that hung, else set to ~0 */ + u32 guc_id; /* if type-instance, context index of hung context, else set to ~0 */ + u32 num_mmios; +#define CAP_HDR_NUM_MMIOS GENMASK(9, 0) +} __packed; + +struct guc_state_capture_t { + struct guc_state_capture_header_t header; + struct guc_mmio_reg mmio_entries[0]; +} __packed; + +enum guc_capture_group_types { + GUC_STATE_CAPTURE_GROUP_TYPE_FULL, + GUC_STATE_CAPTURE_GROUP_TYPE_PARTIAL, + GUC_STATE_CAPTURE_GROUP_TYPE_MAX, +}; + +struct guc_state_capture_group_header_t { + u32 owner; +#define CAP_GRP_HDR_CAPTURE_VFID GENMASK(7, 0) + u32 info; +#define CAP_GRP_HDR_NUM_CAPTURES GENMASK(7, 0) +#define CAP_GRP_HDR_CAPTURE_TYPE GENMASK(15, 8) /* guc_capture_group_types */ +} __packed; + +/* this is the top level structure where an error-capture dump starts */ +struct guc_state_capture_group_t { + struct guc_state_capture_group_header_t grp_header; + struct guc_state_capture_t capture_entries[0]; +} __packed; + /** * struct __guc_capture_ads_cache * From patchwork Sat Feb 26 09:55:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Previn X-Patchwork-Id: 12761253 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 19D8EC433F5 for ; Sat, 26 Feb 2022 09:53:53 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 13C7C10E69D; Sat, 26 Feb 2022 09:53:37 +0000 (UTC) Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by gabe.freedesktop.org (Postfix) with ESMTPS id F2F4610E405 for ; Sat, 26 Feb 2022 09:53:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1645869215; x=1677405215; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=9A+S7XGA/5R9vVgmR9NG7UuCwrJCNCYsdrqt1LpFAXg=; b=A5oVxgistyBbCKTTWZnw2Zma9TpWpX3vIFtcCOjog3cOsKFp/RfKo51R lBUAzWFvwDmaIWZDyjIDSQns3s1TkDDy3eTzBeVey+o19r2z84vlyEdwC fAo0GE8Cp77kvYJ3fRAgwfOiswDZsRfkmIct9aW/tWdazlVTxhBabduqV 34FbAV8vz5BfcPqdCB/fRbFsiPBm6f0gZkjQBVd5n0apattqnw5LTcyrN 7KjKuiz3+sHiW/rp/ayaMCFgMNEgJ6vrQM2yI+E8ErJH8cTG1WsHoc8oX ahcY8vbrqRDV/LOynhqolvBQv8V1xFI5OiRo4wK6sNQ6Y597CWuKkvMO3 Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10269"; a="232620771" X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="232620771" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Feb 2022 01:53:34 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="506953237" Received: from aalteres-desk.fm.intel.com ([10.80.57.53]) by orsmga002.jf.intel.com with ESMTP; 26 Feb 2022 01:53:34 -0800 From: Alan Previn To: intel-gfx@lists.freedesktop.org Date: Sat, 26 Feb 2022 01:55:35 -0800 Message-Id: <20220226095541.1010534-8-alan.previn.teres.alexis@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> References: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v7 07/13] drm/i915/guc: Update GuC-log relay function names X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alan Previn Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" For the sake of better code readibility, change previous relay logging function names with "capture_logs" to "copy_debug_logs" to differentiate from error capture functions that will use a different region of the same buffer. Signed-off-by: Alan Previn --- drivers/gpu/drm/i915/gt/uc/intel_guc_log.c | 35 ++++++++++++---------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c index b53f61f3101f..bf3abb7e69b0 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c @@ -11,7 +11,7 @@ #include "i915_memcpy.h" #include "intel_guc_log.h" -static void guc_log_capture_logs(struct intel_guc_log *log); +static void guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log); /** * DOC: GuC firmware log @@ -197,7 +197,7 @@ static unsigned int guc_get_log_buffer_size(enum guc_log_buffer_type type) return 0; } -static void guc_read_update_log_buffer(struct intel_guc_log *log) +static void _guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log) { unsigned int buffer_size, read_offset, write_offset, bytes_to_copy, full_cnt; struct guc_log_buffer_state *log_buf_state, *log_buf_snapshot_state; @@ -222,7 +222,7 @@ static void guc_read_update_log_buffer(struct intel_guc_log *log) * Used rate limited to avoid deluge of messages, logs might be * getting consumed by User at a slow rate. */ - DRM_ERROR_RATELIMITED("no sub-buffer to capture logs\n"); + DRM_ERROR_RATELIMITED("no sub-buffer to copy general logs\n"); log->relay.full_count++; goto out_unlock; @@ -300,15 +300,15 @@ static void guc_read_update_log_buffer(struct intel_guc_log *log) mutex_unlock(&log->relay.lock); } -static void capture_logs_work(struct work_struct *work) +static void copy_debug_logs_work(struct work_struct *work) { struct intel_guc_log *log = container_of(work, struct intel_guc_log, relay.flush_work); - guc_log_capture_logs(log); + guc_log_copy_debuglogs_for_relay(log); } -static int guc_log_map(struct intel_guc_log *log) +static int guc_log_relay_map(struct intel_guc_log *log) { void *vaddr; @@ -331,7 +331,7 @@ static int guc_log_map(struct intel_guc_log *log) return 0; } -static void guc_log_unmap(struct intel_guc_log *log) +static void guc_log_relay_unmap(struct intel_guc_log *log) { lockdep_assert_held(&log->relay.lock); @@ -342,7 +342,7 @@ static void guc_log_unmap(struct intel_guc_log *log) void intel_guc_log_init_early(struct intel_guc_log *log) { mutex_init(&log->relay.lock); - INIT_WORK(&log->relay.flush_work, capture_logs_work); + INIT_WORK(&log->relay.flush_work, copy_debug_logs_work); log->relay.started = false; } @@ -357,8 +357,11 @@ static int guc_log_relay_create(struct intel_guc_log *log) lockdep_assert_held(&log->relay.lock); GEM_BUG_ON(!log->vma); - /* Keep the size of sub buffers same as shared log buffer */ - subbuf_size = log->vma->size; + /* + * Keep the size of sub buffers same as shared log buffer + * but GuC log-events excludes the error-state-capture logs + */ + subbuf_size = log->vma->size - CAPTURE_BUFFER_SIZE; /* * Store up to 8 snapshots, which is large enough to buffer sufficient @@ -393,13 +396,13 @@ static void guc_log_relay_destroy(struct intel_guc_log *log) log->relay.channel = NULL; } -static void guc_log_capture_logs(struct intel_guc_log *log) +static void guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log) { struct intel_guc *guc = log_to_guc(log); struct drm_i915_private *dev_priv = guc_to_gt(guc)->i915; intel_wakeref_t wakeref; - guc_read_update_log_buffer(log); + _guc_log_copy_debuglogs_for_relay(log); /* * Generally device is expected to be active only at this @@ -565,7 +568,7 @@ int intel_guc_log_relay_open(struct intel_guc_log *log) if (ret) goto out_unlock; - ret = guc_log_map(log); + ret = guc_log_relay_map(log); if (ret) goto out_relay; @@ -615,8 +618,8 @@ void intel_guc_log_relay_flush(struct intel_guc_log *log) with_intel_runtime_pm(guc_to_gt(guc)->uncore->rpm, wakeref) guc_action_flush_log(guc); - /* GuC would have updated log buffer by now, so capture it */ - guc_log_capture_logs(log); + /* GuC would have updated log buffer by now, so copy it */ + guc_log_copy_debuglogs_for_relay(log); } /* @@ -645,7 +648,7 @@ void intel_guc_log_relay_close(struct intel_guc_log *log) mutex_lock(&log->relay.lock); GEM_BUG_ON(!intel_guc_log_relay_created(log)); - guc_log_unmap(log); + guc_log_relay_unmap(log); guc_log_relay_destroy(log); mutex_unlock(&log->relay.lock); } From patchwork Sat Feb 26 09:55:36 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Previn X-Patchwork-Id: 12761254 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 09C79C433EF for ; Sat, 26 Feb 2022 09:53:54 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 3D0E310E6C7; Sat, 26 Feb 2022 09:53:37 +0000 (UTC) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by gabe.freedesktop.org (Postfix) with ESMTPS id 056BD10E40A for ; Sat, 26 Feb 2022 09:53:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1645869215; x=1677405215; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=yuLxIWZdV7lHx6s93il+zsxxhJsLJLL+V4WnViUqBlA=; b=RX94dNaBlzIOv+DaLW9yUPxCYKNimQUenJhYbPhluHNpMELzR3ozMchc uSzC6d+rFE+7NjYloPsJm7mBdVWZpXyu2+UqjUx4e5O074R/YDZDnVcRM 4iCkyQqq4hqpAuJWqrmPoo29v+vt/W5y3z/F8WCtRKEASvAKkXQLpzV0l 9+uP1oIar8nZ4l65AIylqS67wALjlN0Qar8JSPtvfBgRP1ci6B4ZUz8PB M8hm5P6EXQyClno2jKdjb+0VHHAg9QIVjlTGhzAqgx16ZS237wGnTb5QO fCD+1uTxqwDZGIGq3t+pYuHP+2P2fIL0oIDtW5oUr0u4zXfcll8TFeVfc g==; X-IronPort-AV: E=McAfee;i="6200,9189,10269"; a="251480188" X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="251480188" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Feb 2022 01:53:34 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="506953240" Received: from aalteres-desk.fm.intel.com ([10.80.57.53]) by orsmga002.jf.intel.com with ESMTP; 26 Feb 2022 01:53:34 -0800 From: Alan Previn To: intel-gfx@lists.freedesktop.org Date: Sat, 26 Feb 2022 01:55:36 -0800 Message-Id: <20220226095541.1010534-9-alan.previn.teres.alexis@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> References: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v7 08/13] drm/i915/guc: Add capture region into intel_guc_log X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alan Previn Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" GuC log buffer regions for debug-log-events, crash-dumps and error-state-capture are all part of a single bo allocation that also includes the guc_log_buffer_state structures. Now that we support it, increase the size allocation for error-capture. Since the error-capture region is accessed at non-deterministic times (as part of GuC triggered context reset) while debug-log- events region is accessed as part of relay logging or during debugfs triggered dumps, move the mapping and unmapping of the shared buffer into intel_guc_log_create and intel_guc_log_destroy so that it's always mapped throughout life of GuC operation. Additionally, while here, update the guc log region layout diagram to follow the order according to the enum definition as per the GuC interface. Signed-off-by: Alan Previn --- drivers/gpu/drm/i915/gt/uc/intel_guc_log.c | 58 +++++++++++++--------- drivers/gpu/drm/i915/gt/uc/intel_guc_log.h | 3 +- 2 files changed, 36 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c index bf3abb7e69b0..2cc52f1eedf3 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c @@ -25,7 +25,8 @@ static void guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log); static int guc_action_flush_log_complete(struct intel_guc *guc) { u32 action[] = { - INTEL_GUC_ACTION_LOG_BUFFER_FILE_FLUSH_COMPLETE + INTEL_GUC_ACTION_LOG_BUFFER_FILE_FLUSH_COMPLETE, + GUC_DEBUG_LOG_BUFFER }; return intel_guc_send(guc, action, ARRAY_SIZE(action)); @@ -136,7 +137,7 @@ static void guc_move_to_next_buf(struct intel_guc_log *log) smp_wmb(); /* All data has been written, so now move the offset of sub buffer. */ - relay_reserve(log->relay.channel, log->vma->obj->base.size); + relay_reserve(log->relay.channel, log->vma->obj->base.size - CAPTURE_BUFFER_SIZE); /* Switch to the next sub buffer */ relay_flush(log->relay.channel); @@ -212,7 +213,7 @@ static void _guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log) goto out_unlock; /* Get the pointer to shared GuC log buffer */ - log_buf_state = src_data = log->relay.buf_addr; + log_buf_state = src_data = log->buf_addr; /* Get the pointer to local buffer to store the logs */ log_buf_snapshot_state = dst_data = guc_get_write_buffer(log); @@ -232,7 +233,8 @@ static void _guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log) src_data += PAGE_SIZE; dst_data += PAGE_SIZE; - for (type = GUC_DEBUG_LOG_BUFFER; type < GUC_MAX_LOG_BUFFER; type++) { + /* For relay logging, we exclude error state capture */ + for (type = GUC_DEBUG_LOG_BUFFER; type <= GUC_CRASH_DUMP_LOG_BUFFER; type++) { /* * Make a copy of the state structure, inside GuC log buffer * (which is uncached mapped), on the stack to avoid reading @@ -310,23 +312,17 @@ static void copy_debug_logs_work(struct work_struct *work) static int guc_log_relay_map(struct intel_guc_log *log) { - void *vaddr; - lockdep_assert_held(&log->relay.lock); - if (!log->vma) + if (!log->vma || !log->buf_addr) return -ENODEV; /* - * Create a WC (Uncached for read) vmalloc mapping of log - * buffer pages, so that we can directly get the data - * (up-to-date) from memory. + * WC vmalloc mapping of log buffer pages was done at + * GuC Log Init time, but lets keep a ref for book-keeping */ - vaddr = i915_gem_object_pin_map_unlocked(log->vma->obj, I915_MAP_WC); - if (IS_ERR(vaddr)) - return PTR_ERR(vaddr); - - log->relay.buf_addr = vaddr; + i915_gem_object_get(log->vma->obj); + log->relay.buf_in_use = true; return 0; } @@ -335,8 +331,8 @@ static void guc_log_relay_unmap(struct intel_guc_log *log) { lockdep_assert_held(&log->relay.lock); - i915_gem_object_unpin_map(log->vma->obj); - log->relay.buf_addr = NULL; + i915_gem_object_put(log->vma->obj); + log->relay.buf_in_use = false; } void intel_guc_log_init_early(struct intel_guc_log *log) @@ -442,6 +438,7 @@ int intel_guc_log_create(struct intel_guc_log *log) { struct intel_guc *guc = log_to_guc(log); struct i915_vma *vma; + void *vaddr; u32 guc_log_size; int ret; @@ -449,20 +446,21 @@ int intel_guc_log_create(struct intel_guc_log *log) /* * GuC Log buffer Layout + * (this ordering must follow "enum guc_log_buffer_type" definition) * * +===============================+ 00B - * | Crash dump state header | - * +-------------------------------+ 32B * | Debug state header | + * +-------------------------------+ 32B + * | Crash dump state header | * +-------------------------------+ 64B * | Capture state header | * +-------------------------------+ 96B * | | * +===============================+ PAGE_SIZE (4KB) - * | Crash Dump logs | - * +===============================+ + CRASH_SIZE * | Debug logs | * +===============================+ + DEBUG_SIZE + * | Crash Dump logs | + * +===============================+ + CRASH_SIZE * | Capture logs | * +===============================+ + CAPTURE_SIZE */ @@ -476,6 +474,17 @@ int intel_guc_log_create(struct intel_guc_log *log) } log->vma = vma; + /* + * Create a WC (Uncached for read) vmalloc mapping up front immediate access to + * data from memory during critical events such as error capture + */ + vaddr = i915_gem_object_pin_map_unlocked(log->vma->obj, I915_MAP_WC); + if (IS_ERR(vaddr)) { + ret = PTR_ERR(vaddr); + i915_vma_unpin_and_release(&log->vma, 0); + goto err; + } + log->buf_addr = vaddr; log->level = __get_default_log_level(log); DRM_DEBUG_DRIVER("guc_log_level=%d (%s, verbose:%s, verbosity:%d)\n", @@ -486,13 +495,14 @@ int intel_guc_log_create(struct intel_guc_log *log) return 0; err: - DRM_ERROR("Failed to allocate GuC log buffer. %d\n", ret); + DRM_ERROR("Failed to allocate or map GuC log buffer. %d\n", ret); return ret; } void intel_guc_log_destroy(struct intel_guc_log *log) { - i915_vma_unpin_and_release(&log->vma, 0); + log->buf_addr = NULL; + i915_vma_unpin_and_release(&log->vma, I915_VMA_RELEASE_MAP); } int intel_guc_log_set_level(struct intel_guc_log *log, u32 level) @@ -537,7 +547,7 @@ int intel_guc_log_set_level(struct intel_guc_log *log, u32 level) bool intel_guc_log_relay_created(const struct intel_guc_log *log) { - return log->relay.buf_addr; + return log->buf_addr; } int intel_guc_log_relay_open(struct intel_guc_log *log) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h index d7e1b6471fed..e1345fca7729 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h @@ -49,8 +49,9 @@ struct intel_guc; struct intel_guc_log { u32 level; struct i915_vma *vma; + void *buf_addr; struct { - void *buf_addr; + bool buf_in_use; bool started; struct work_struct flush_work; struct rchan *channel; From patchwork Sat Feb 26 09:55:37 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Previn X-Patchwork-Id: 12761258 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 8C2A1C433EF for ; Sat, 26 Feb 2022 09:53:57 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id E9C6410E40D; Sat, 26 Feb 2022 09:53:37 +0000 (UTC) Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by gabe.freedesktop.org (Postfix) with ESMTPS id 1B39D10E3FB for ; Sat, 26 Feb 2022 09:53:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1645869215; x=1677405215; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=FM7EmRPD8GRplqyioMbBuknpzPACRDkKpZiFlQmW2dc=; b=IOmLlss+xjy/m14AJhQ0Aj37CT3fmQscS6yRR2TB6dxiGbj/meDymvLn Tp1AqLFHFu7g9N1MhiZJL+jjFnZ2lKsEwEXvDL99bhNL+3c8XI5oMWMN3 /FahvyXF2HHNfM3VSqAmklgCw9dy3P+16qNryuGZ9wZjUt+PGdchymJhk 4Jlq/mnG1w0h+vxvVo8MnvuuAWECsmpnMAcvkSu/x5GONTQmr7A+rCNjf 0dliR9z7KRAJHn5UZEt3ZjdJaPYf8Yx5HYYMyNUH6qbVfTFnzqD8IUeIE aMzMddoRLf3ZExnKzfWuZqCHM2JHf2QA7DuXCnTtPUfXe8PRtRdXwrtS5 g==; X-IronPort-AV: E=McAfee;i="6200,9189,10269"; a="232620772" X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="232620772" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Feb 2022 01:53:34 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="506953243" Received: from aalteres-desk.fm.intel.com ([10.80.57.53]) by orsmga002.jf.intel.com with ESMTP; 26 Feb 2022 01:53:34 -0800 From: Alan Previn To: intel-gfx@lists.freedesktop.org Date: Sat, 26 Feb 2022 01:55:37 -0800 Message-Id: <20220226095541.1010534-10-alan.previn.teres.alexis@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> References: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v7 09/13] drm/i915/guc: Check sizing of guc_capture output X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alan Previn Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Add intel_guc_capture_output_min_size_est function to provide a reasonable minimum size for error-capture region before allocating the shared buffer. Signed-off-by: Alan Previn Reported-by: kernel test robot --- .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 47 +++++++++++++++++++ .../gpu/drm/i915/gt/uc/intel_guc_capture.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_guc_log.c | 7 ++- 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index eb22f979d720..ed78995bcc35 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -644,6 +644,53 @@ intel_guc_capture_getlist(struct intel_guc *guc, u32 owner, u32 type, u32 classi return 0; } +#define GUC_CAPTURE_OVERBUFFER_MULTIPLIER 3 +int intel_guc_capture_output_min_size_est(struct intel_guc *guc) +{ + struct intel_gt *gt = guc_to_gt(guc); + struct intel_engine_cs *engine; + enum intel_engine_id id; + int worst_min_size = 0, num_regs = 0; + size_t tmp = 0; + + /* + * If every single engine-instance suffered a failure in quick succession but + * were all unrelated, then a burst of multiple error-capture events would dump + * registers for every one engine instance, one at a time. In this case, GuC + * would even dump the global-registers repeatedly. + * + * For each engine instance, there would be 1 x guc_state_capture_group_t output + * followed by 3 x guc_state_capture_t lists. The latter is how the register + * dumps are split across different register types (where the '3' are global vs class + * vs instance). Finally, let's multiply the whole thing by 3x (just so we are + * not limited to just 1 round of data in a worst case full register dump log) + * + * NOTE: intel_guc_log that allocates the log buffer would round this size up to + * a power of two. + */ + + for_each_engine(engine, gt, id) { + worst_min_size += sizeof(struct guc_state_capture_group_header_t) + + (3 * sizeof(struct guc_state_capture_header_t)); + + if (!intel_guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_GLOBAL, 0, &tmp)) + num_regs += tmp; + + if (!intel_guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, + engine->class, &tmp)) { + num_regs += tmp; + } + if (!intel_guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE, + engine->class, &tmp)) { + num_regs += tmp; + } + } + + worst_min_size += (num_regs * sizeof(struct guc_mmio_reg)); + + return (worst_min_size * GUC_CAPTURE_OVERBUFFER_MULTIPLIER); +} + static void guc_capture_free_ads_cache(struct __guc_state_capture_priv *gc) { diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h index f05365239a2f..24a11f33f7d9 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h @@ -12,6 +12,7 @@ struct file; struct guc_gt_system_info; struct intel_guc; +int intel_guc_capture_output_min_size_est(struct intel_guc *guc); int intel_guc_capture_getlist(struct intel_guc *guc, u32 owner, u32 type, u32 classid, struct file **fileptr); int intel_guc_capture_getlistsize(struct intel_guc *guc, u32 owner, u32 type, u32 classid, diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c index 2cc52f1eedf3..e9a865c2f4cb 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c @@ -6,10 +6,11 @@ #include #include "gt/intel_gt.h" +#include "intel_guc_capture.h" +#include "intel_guc_log.h" #include "i915_drv.h" #include "i915_irq.h" #include "i915_memcpy.h" -#include "intel_guc_log.h" static void guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log); @@ -464,6 +465,10 @@ int intel_guc_log_create(struct intel_guc_log *log) * | Capture logs | * +===============================+ + CAPTURE_SIZE */ + if (intel_guc_capture_output_min_size_est(guc) > CAPTURE_BUFFER_SIZE) + DRM_WARN("GuC log buffer for state_capture maybe too small. %d < %d\n", + CAPTURE_BUFFER_SIZE, intel_guc_capture_output_min_size_est(guc)); + guc_log_size = PAGE_SIZE + CRASH_BUFFER_SIZE + DEBUG_BUFFER_SIZE + CAPTURE_BUFFER_SIZE; From patchwork Sat Feb 26 09:55:38 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Previn X-Patchwork-Id: 12761259 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 67D99C4332F for ; Sat, 26 Feb 2022 09:53:58 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id BC15510E936; Sat, 26 Feb 2022 09:53:38 +0000 (UTC) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTPS id DF39310E40D for ; Sat, 26 Feb 2022 09:53:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1645869215; x=1677405215; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=CeB56e5svrRIpxCbf2iJFQsDNGn2CmjP8dcQ7SHnqzo=; b=jjLffSJapnthLZ7YdP3jJJYvS7HwFaXn17HStiyd0Q0DnoyhYQnWBgR8 A+5ceNAVd/SOkvSBZ6FFmH9PyDsieZyyqpf+wjqxuqh/Ty+TmgaosBwAC vV+WgcBvkqB3I9vHsWCrd1yAFFKPUIhTa4r/nSUqX2L5Efon2p9rcnetj fJaIDZFDrScRBOTGpl5Z9go9eC/j6c0rLSBjcoVoaFsuJ16JiKesKlVZr hNwW+in2UIL37jvz/XdUvKEQz88bFu4nidFoP9DtI7KajpaWfGay3tkad 4stNMXL/hH4fxbx6QYBxk7OQc/MJBLkVhLZxUSr3rW9b/ZgHfuBbyASVh g==; X-IronPort-AV: E=McAfee;i="6200,9189,10269"; a="277288185" X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="277288185" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Feb 2022 01:53:35 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="506953247" Received: from aalteres-desk.fm.intel.com ([10.80.57.53]) by orsmga002.jf.intel.com with ESMTP; 26 Feb 2022 01:53:34 -0800 From: Alan Previn To: intel-gfx@lists.freedesktop.org Date: Sat, 26 Feb 2022 01:55:38 -0800 Message-Id: <20220226095541.1010534-11-alan.previn.teres.alexis@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> References: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v7 10/13] drm/i915/guc: Extract GuC error capture lists on G2H notification. X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alan Previn Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" - Upon the G2H Notify-Err-Capture event, parse through the GuC Log Buffer (error-capture-subregion) and generate one or more capture-nodes. A single node represents a single "engine- instance-capture-dump" and contains at least 3 register lists: global, engine-class and engine-instance. An internal link list is maintained to store one or more nodes. - Because the link-list node generation happen before the call to i915_gpu_codedump, duplicate global and engine-class register lists for each engine-instance register dump if we find dependent-engine resets in a engine-capture-group. - When i915_gpu_coredump calls into capture_engine, (in a subsequent patch) we detach the matching node (guc-id, LRCA, etc) from the link list above and attach it to i915_gpu_coredump's intel_engine_coredump structure when have matching LRCA/guc-id/engine-instance. Additional notes to be aware of: - GuC generates the error capture dump into the GuC log buffer but this buffer is one big log buffer with 3 independent subregions within it. Each subregion is populated with different content and used in different ways and timings but all regions operate behave as independent ring buffers. Each guc-log subregion (general-logs, crash-dump and error- capture) has it's own guc_log_buffer_state that contain independent read and write pointers. Signed-off-by: Alan Previn Reviewed-by: Umesh Nerlige Ramappa --- .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h | 7 + drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h | 56 ++ .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 546 +++++++++++++++++- .../gpu/drm/i915/gt/uc/intel_guc_capture.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_guc_log.c | 26 +- drivers/gpu/drm/i915/gt/uc/intel_guc_log.h | 4 + .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 10 +- 7 files changed, 639 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h index 7afdadc7656f..ae6448fcaf90 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h @@ -173,4 +173,11 @@ enum intel_guc_sleep_state_status { #define GUC_LOG_CONTROL_VERBOSITY_MASK (0xF << GUC_LOG_CONTROL_VERBOSITY_SHIFT) #define GUC_LOG_CONTROL_DEFAULT_LOGGING (1 << 8) +enum intel_guc_state_capture_event_status { + INTEL_GUC_STATE_CAPTURE_EVENT_STATUS_SUCCESS = 0x0, + INTEL_GUC_STATE_CAPTURE_EVENT_STATUS_NOSPACE = 0x1, +}; + +#define INTEL_GUC_STATE_CAPTURE_EVENT_STATUS_MASK 0x000000FF + #endif /* _ABI_GUC_ACTIONS_ABI_H */ diff --git a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h index d5cb7d5d4ca7..2b09aa05d8b7 100644 --- a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h @@ -12,6 +12,52 @@ struct intel_guc; struct file; +/** + * struct __guc_capture_bufstate + * + * Book-keeping structure used to track read and write pointers + * as we extract error capture data from the GuC-log-buffer's + * error-capture region as a stream of dwords. + */ +struct __guc_capture_bufstate { + u32 size; + void *data; + u32 rd; + u32 wr; +}; + +/** + * struct __guc_capture_parsed_output - extracted error capture node + * + * A single unit of extracted error-capture output data grouped together + * at an engine-instance level. We keep these nodes in a linked list. + * See outlist below. + */ +struct __guc_capture_parsed_output { + /* + * A single set of 3 capture lists: a global-list + * an engine-class-list and an engine-instance list. + * outlist in __guc_capture_parsed_output will keep + * a linked list of these nodes that will eventually + * be detached from outlist and attached into to + * i915_gpu_codedump in response to a context reset + */ + struct list_head link; + bool is_partial; + u32 eng_class; + u32 eng_inst; + u32 guc_id; + u32 lrca; + struct gcap_reg_list_info { + u32 vfid; + u32 num_regs; + struct guc_mmio_reg *regs; + } reginfo[GUC_CAPTURE_LIST_TYPE_MAX]; +#define GCAP_PARSED_REGLIST_INDEX_GLOBAL BIT(GUC_CAPTURE_LIST_TYPE_GLOBAL) +#define GCAP_PARSED_REGLIST_INDEX_ENGCLASS BIT(GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS) +#define GCAP_PARSED_REGLIST_INDEX_ENGINST BIT(GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE) +}; + /** * struct guc_debug_capture_list_header / struct guc_debug_capture_list * @@ -140,6 +186,16 @@ struct __guc_state_capture_priv { struct __guc_capture_ads_cache ads_cache[GUC_CAPTURE_LIST_INDEX_MAX] [GUC_CAPTURE_LIST_TYPE_MAX] [GUC_MAX_ENGINE_CLASSES]; + + /** + * @outlist: allocated nodes with parsed engine-instance error capture data + * + * A linked list of parsed GuC error-capture output data before + * reporting with formatting via i915_gpu_coredump. Each node in this linked list shall + * contain a single engine-capture including global, engine-class and + * engine-instance register dumps as per guc_capture_parsed_output_node + */ + struct list_head outlist; }; #endif /* _INTEL_GUC_CAPTURE_FWIF_H */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index ed78995bcc35..9308157d9a74 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -14,6 +14,8 @@ #include "guc_capture_fwif.h" #include "intel_guc_fwif.h" #include "i915_drv.h" +#include "i915_gpu_error.h" +#include "i915_irq.h" #include "i915_memcpy.h" #include "i915_reg.h" @@ -653,6 +655,9 @@ int intel_guc_capture_output_min_size_est(struct intel_guc *guc) int worst_min_size = 0, num_regs = 0; size_t tmp = 0; + if (!guc->capture.priv) + return -ENODEV; + /* * If every single engine-instance suffered a failure in quick succession but * were all unrelated, then a burst of multiple error-capture events would dump @@ -671,7 +676,7 @@ int intel_guc_capture_output_min_size_est(struct intel_guc *guc) for_each_engine(engine, gt, id) { worst_min_size += sizeof(struct guc_state_capture_group_header_t) + - (3 * sizeof(struct guc_state_capture_header_t)); + (3 * sizeof(struct guc_state_capture_header_t)); if (!intel_guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_GLOBAL, 0, &tmp)) num_regs += tmp; @@ -691,6 +696,541 @@ int intel_guc_capture_output_min_size_est(struct intel_guc *guc) return (worst_min_size * GUC_CAPTURE_OVERBUFFER_MULTIPLIER); } +/* + * KMD Init time flows: + * -------------------- + * --> alloc A: GuC input capture regs lists (registered to GuC via ADS). + * intel_guc_ads acquires the register lists by calling + * intel_guc_capture_list_size and intel_guc_capture_list_get 'n' times, + * where n = 1 for global-reg-list + + * num_engine_classes for class-reg-list + + * num_engine_classes for instance-reg-list + * (since all instances of the same engine-class type + * have an identical engine-instance register-list). + * ADS module also calls separately for PF vs VF. + * + * --> alloc B: GuC output capture buf (registered via guc_init_params(log_param)) + * Size = #define CAPTURE_BUFFER_SIZE (warns if on too-small) + * Note2: 'x 3' to hold multiple capture groups + * + * GUC Runtime notify capture: + * -------------------------- + * --> G2H STATE_CAPTURE_NOTIFICATION + * L--> intel_guc_capture_process + * L--> Loop through B (head..tail) and for each engine instance's + * err-state-captured register-list we find, we alloc 'C': + * --> alloc C: A capture-output-node structure that includes misc capture info along + * with 3 register list dumps (global, engine-class and engine-instance) + * This node is dynamically allocated and populated with the error-capture + * data from GuC and then it's added into guc->capture->priv->outlist linked + * list. This list is used for matchup and printout by i915_gpu_coredump + * and err_print_gt, (when user invokes the error capture sysfs). + */ + +static int guc_capture_buf_cnt(struct __guc_capture_bufstate *buf) +{ + if (buf->rd == buf->wr) + return 0; + if (buf->wr > buf->rd) + return (buf->wr - buf->rd); + return (buf->size - buf->rd) + buf->wr; +} + +static int guc_capture_buf_cnt_to_end(struct __guc_capture_bufstate *buf) +{ + if (buf->rd > buf->wr) + return (buf->size - buf->rd); + return (buf->wr - buf->rd); +} + +static int +guc_capture_log_remove_dw(struct intel_guc *guc, struct __guc_capture_bufstate *buf, + u32 *dw) +{ + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + int tries = 2; + int avail = 0; + u32 *src_data; + + if (!guc_capture_buf_cnt(buf)) + return 0; + + while (tries--) { + avail = guc_capture_buf_cnt_to_end(buf); + if (avail >= sizeof(u32)) { + src_data = (u32 *)(buf->data + buf->rd); + *dw = *src_data; + buf->rd += 4; + return 4; + } + if (avail) + drm_dbg(&i915->drm, "GuC-Cap-Logs not dword aligned, skipping.\n"); + buf->rd = 0; + } + + return 0; +} + +static bool +guc_capture_data_extracted(struct __guc_capture_bufstate *b, + int size, void *dest) +{ + if (guc_capture_buf_cnt_to_end(b) >= size) { + memcpy(dest, (b->data + b->rd), size); + b->rd += size; + return true; + } + return false; +} + +static int +guc_capture_log_get_group_hdr(struct intel_guc *guc, struct __guc_capture_bufstate *buf, + struct guc_state_capture_group_header_t *ghdr) +{ + int read = 0; + int fullsize = sizeof(struct guc_state_capture_group_header_t); + + if (fullsize > guc_capture_buf_cnt(buf)) + return -1; + + if (guc_capture_data_extracted(buf, fullsize, (void *)ghdr)) + return 0; + + read += guc_capture_log_remove_dw(guc, buf, &ghdr->owner); + read += guc_capture_log_remove_dw(guc, buf, &ghdr->info); + if (read != fullsize) + return -1; + + return 0; +} + +static int +guc_capture_log_get_data_hdr(struct intel_guc *guc, struct __guc_capture_bufstate *buf, + struct guc_state_capture_header_t *hdr) +{ + int read = 0; + int fullsize = sizeof(struct guc_state_capture_header_t); + + if (fullsize > guc_capture_buf_cnt(buf)) + return -1; + + if (guc_capture_data_extracted(buf, fullsize, (void *)hdr)) + return 0; + + read += guc_capture_log_remove_dw(guc, buf, &hdr->owner); + read += guc_capture_log_remove_dw(guc, buf, &hdr->info); + read += guc_capture_log_remove_dw(guc, buf, &hdr->lrca); + read += guc_capture_log_remove_dw(guc, buf, &hdr->guc_id); + read += guc_capture_log_remove_dw(guc, buf, &hdr->num_mmios); + if (read != fullsize) + return -1; + + return 0; +} + +static int +guc_capture_log_get_register(struct intel_guc *guc, struct __guc_capture_bufstate *buf, + struct guc_mmio_reg *reg) +{ + int read = 0; + int fullsize = sizeof(struct guc_mmio_reg); + + if (fullsize > guc_capture_buf_cnt(buf)) + return -1; + + if (guc_capture_data_extracted(buf, fullsize, (void *)reg)) + return 0; + + read += guc_capture_log_remove_dw(guc, buf, ®->offset); + read += guc_capture_log_remove_dw(guc, buf, ®->value); + read += guc_capture_log_remove_dw(guc, buf, ®->flags); + read += guc_capture_log_remove_dw(guc, buf, ®->mask); + if (read != fullsize) + return -1; + + return 0; +} + +static void +guc_capture_delete_one_node(struct intel_guc *guc, struct __guc_capture_parsed_output *node) +{ + int i; + + for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { + if (node->reginfo[i].regs) + kfree(node->reginfo[i].regs); + } + list_del(&node->link); + kfree(node); +} + +static void +guc_capture_delete_nodes(struct intel_guc *guc) +{ + /* + * NOTE: At the end of driver operation, we must assume that we + * have nodes in outlist from unclaimed error capture events + * that occurred prior to shutdown. + */ + if (!list_empty(&guc->capture.priv->outlist)) { + struct __guc_capture_parsed_output *n, *ntmp; + + list_for_each_entry_safe(n, ntmp, &guc->capture.priv->outlist, link) + guc_capture_delete_one_node(guc, n); + } +} + +static void +guc_capture_add_node_to_list(struct __guc_capture_parsed_output *node, + struct list_head *list) +{ + list_add_tail(&node->link, list); +} + +static void +guc_capture_add_node_to_outlist(struct __guc_state_capture_priv *gc, + struct __guc_capture_parsed_output *node) +{ + guc_capture_add_node_to_list(node, &gc->outlist); +} + +static void +guc_capture_init_node(struct intel_guc *guc, struct __guc_capture_parsed_output *node) +{ + INIT_LIST_HEAD(&node->link); +} + +static struct __guc_capture_parsed_output * +guc_capture_alloc_one_node(struct intel_guc *guc) +{ + struct __guc_capture_parsed_output *new; + + new = kzalloc(sizeof(*new), GFP_KERNEL); + if (!new) + return NULL; + + guc_capture_init_node(guc, new); + + return new; +} + +static struct __guc_capture_parsed_output * +guc_capture_clone_node(struct intel_guc *guc, struct __guc_capture_parsed_output *ori, + u32 keep_reglist_mask) +{ + struct __guc_capture_parsed_output *new; + int i; + + new = guc_capture_alloc_one_node(guc); + if (!new) + return NULL; + if (!ori) + return new; + + new->is_partial = ori->is_partial; + + /* copy reg-lists that we want to clone */ + for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { + if (keep_reglist_mask & BIT(i)) { + new->reginfo[i].regs = kcalloc(ori->reginfo[i].num_regs, + sizeof(struct guc_mmio_reg), GFP_KERNEL); + if (!new->reginfo[i].regs) + goto bail_clone; + + memcpy(new->reginfo[i].regs, ori->reginfo[i].regs, + ori->reginfo[i].num_regs * sizeof(struct guc_mmio_reg)); + new->reginfo[i].num_regs = ori->reginfo[i].num_regs; + new->reginfo[i].vfid = ori->reginfo[i].vfid; + + if (i == GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS) { + new->eng_class = ori->eng_class; + } else if (i == GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE) { + new->eng_inst = ori->eng_inst; + new->guc_id = ori->guc_id; + new->lrca = ori->lrca; + } + } + } + + return new; + +bail_clone: + for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { + if (new->reginfo[i].regs) + kfree(new->reginfo[i].regs); + } + kfree(new); + return NULL; +} + +static int +guc_capture_extract_reglists(struct intel_guc *guc, struct __guc_capture_bufstate *buf) +{ + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + struct guc_state_capture_group_header_t ghdr = {0}; + struct guc_state_capture_header_t hdr = {0}; + struct __guc_capture_parsed_output *node = NULL; + struct guc_mmio_reg *regs = NULL; + int i, numlists, numregs, ret = 0; + enum guc_capture_type datatype; + struct guc_mmio_reg tmp; + bool is_partial = false; + + i = guc_capture_buf_cnt(buf); + if (!i) + return -ENODATA; + if (i % sizeof(u32)) { + drm_warn(&i915->drm, "GuC Capture new entries unaligned\n"); + ret = -EIO; + goto bailout; + } + + /* first get the capture group header */ + if (guc_capture_log_get_group_hdr(guc, buf, &ghdr)) { + ret = -EIO; + goto bailout; + } + /* + * we would typically expect a layout as below where n would be expected to be + * anywhere between 3 to n where n > 3 if we are seeing multiple dependent engine + * instances being reset together. + * ____________________________________________ + * | Capture Group | + * | ________________________________________ | + * | | Capture Group Header: | | + * | | - num_captures = 5 | | + * | |______________________________________| | + * | ________________________________________ | + * | | Capture1: | | + * | | Hdr: GLOBAL, numregs=a | | + * | | ____________________________________ | | + * | | | Reglist | | | + * | | | - reg1, reg2, ... rega | | | + * | | |__________________________________| | | + * | |______________________________________| | + * | ________________________________________ | + * | | Capture2: | | + * | | Hdr: CLASS=RENDER/COMPUTE, numregs=b| | + * | | ____________________________________ | | + * | | | Reglist | | | + * | | | - reg1, reg2, ... regb | | | + * | | |__________________________________| | | + * | |______________________________________| | + * | ________________________________________ | + * | | Capture3: | | + * | | Hdr: INSTANCE=RCS, numregs=c | | + * | | ____________________________________ | | + * | | | Reglist | | | + * | | | - reg1, reg2, ... regc | | | + * | | |__________________________________| | | + * | |______________________________________| | + * | ________________________________________ | + * | | Capture4: | | + * | | Hdr: CLASS=RENDER/COMPUTE, numregs=d| | + * | | ____________________________________ | | + * | | | Reglist | | | + * | | | - reg1, reg2, ... regd | | | + * | | |__________________________________| | | + * | |______________________________________| | + * | ________________________________________ | + * | | Capture5: | | + * | | Hdr: INSTANCE=CCS0, numregs=e | | + * | | ____________________________________ | | + * | | | Reglist | | | + * | | | - reg1, reg2, ... rege | | | + * | | |__________________________________| | | + * | |______________________________________| | + * |__________________________________________| + */ + is_partial = FIELD_GET(CAP_GRP_HDR_CAPTURE_TYPE, ghdr.info); + numlists = FIELD_GET(CAP_GRP_HDR_NUM_CAPTURES, ghdr.info); + + while (numlists--) { + if (guc_capture_log_get_data_hdr(guc, buf, &hdr)) { + ret = -EIO; + break; + } + + datatype = FIELD_GET(CAP_HDR_CAPTURE_TYPE, hdr.info); + if (datatype > GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE) { + /* unknown capture type - skip over to next capture set */ + numregs = FIELD_GET(CAP_HDR_NUM_MMIOS, hdr.num_mmios); + while (numregs--) { + if (guc_capture_log_get_register(guc, buf, &tmp)) { + ret = -EIO; + break; + } + } + continue; + } else if (node) { + /* + * Based on the current capture type and what we have so far, + * decide if we should add the current node into the internal + * linked list for match-up when i915_gpu_coredump calls later + * (and alloc a blank node for the next set of reglists) + * or continue with the same node or clone the current node + * but only retain the global or class registers (such as the + * case of dependent engine resets). + */ + if (datatype == GUC_CAPTURE_LIST_TYPE_GLOBAL) { + guc_capture_add_node_to_outlist(guc->capture.priv, node); + node = NULL; + } else if (datatype == GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS && + node->reginfo[GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS].regs) { + /* Add to list, clone node and duplicate global list */ + guc_capture_add_node_to_outlist(guc->capture.priv, node); + node = guc_capture_clone_node(guc, node, + GCAP_PARSED_REGLIST_INDEX_GLOBAL); + } else if (datatype == GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE && + node->reginfo[GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE].regs) { + /* Add to list, clone node and duplicate global + class lists */ + guc_capture_add_node_to_outlist(guc->capture.priv, node); + node = guc_capture_clone_node(guc, node, + (GCAP_PARSED_REGLIST_INDEX_GLOBAL | + GCAP_PARSED_REGLIST_INDEX_ENGCLASS)); + } + } + + if (!node) { + node = guc_capture_alloc_one_node(guc); + if (!node) { + ret = -ENOMEM; + break; + } + if (datatype != GUC_CAPTURE_LIST_TYPE_GLOBAL) + drm_dbg(&i915->drm, "GuC Capture missing global dump: %08x!\n", + datatype); + } + node->is_partial = is_partial; + node->reginfo[datatype].vfid = FIELD_GET(CAP_HDR_CAPTURE_VFID, hdr.owner); + switch (datatype) { + case GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE: + node->eng_class = FIELD_GET(CAP_HDR_ENGINE_CLASS, hdr.info); + node->eng_inst = FIELD_GET(CAP_HDR_ENGINE_INSTANCE, hdr.info); + node->lrca = hdr.lrca; + node->guc_id = hdr.guc_id; + break; + case GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS: + node->eng_class = FIELD_GET(CAP_HDR_ENGINE_CLASS, hdr.info); + break; + default: + break; + } + + regs = NULL; + numregs = FIELD_GET(CAP_HDR_NUM_MMIOS, hdr.num_mmios); + if (numregs) { + regs = kcalloc(numregs, sizeof(struct guc_mmio_reg), GFP_KERNEL); + if (!regs) { + ret = -ENOMEM; + break; + } + } + node->reginfo[datatype].num_regs = numregs; + node->reginfo[datatype].regs = regs; + i = 0; + while (numregs--) { + if (guc_capture_log_get_register(guc, buf, ®s[i++])) { + ret = -EIO; + break; + } + } + } + +bailout: + if (node) { + /* If we have data, add to linked list for match-up when i915_gpu_coredump calls */ + for (i = GUC_CAPTURE_LIST_TYPE_GLOBAL; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { + if (node->reginfo[i].regs) { + guc_capture_add_node_to_outlist(guc->capture.priv, node); + node = NULL; + break; + } + } + if (node) /* else free it */ + kfree(node); + } + return ret; +} + +static int __guc_capture_flushlog_complete(struct intel_guc *guc) +{ + u32 action[] = { + INTEL_GUC_ACTION_LOG_BUFFER_FILE_FLUSH_COMPLETE, + 2 + }; + + return intel_guc_send(guc, action, ARRAY_SIZE(action)); +} + +static void __guc_capture_process_output(struct intel_guc *guc) +{ + unsigned int buffer_size, read_offset, write_offset, full_count; + struct intel_uc *uc = container_of(guc, typeof(*uc), guc); + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + struct guc_log_buffer_state log_buf_state_local; + struct guc_log_buffer_state *log_buf_state; + struct __guc_capture_bufstate buf; + void *src_data = NULL; + bool new_overflow; + int ret; + + log_buf_state = guc->log.buf_addr + + (sizeof(struct guc_log_buffer_state) * GUC_CAPTURE_LOG_BUFFER); + src_data = guc->log.buf_addr + intel_guc_get_log_buffer_offset(GUC_CAPTURE_LOG_BUFFER); + + /* + * Make a copy of the state structure, inside GuC log buffer + * (which is uncached mapped), on the stack to avoid reading + * from it multiple times. + */ + memcpy(&log_buf_state_local, log_buf_state, sizeof(struct guc_log_buffer_state)); + buffer_size = intel_guc_get_log_buffer_size(GUC_CAPTURE_LOG_BUFFER); + read_offset = log_buf_state_local.read_ptr; + write_offset = log_buf_state_local.sampled_write_ptr; + full_count = log_buf_state_local.buffer_full_cnt; + + /* Bookkeeping stuff */ + guc->log.stats[GUC_CAPTURE_LOG_BUFFER].flush += log_buf_state_local.flush_to_file; + new_overflow = intel_guc_check_log_buf_overflow(&guc->log, GUC_CAPTURE_LOG_BUFFER, + full_count); + + /* Now copy the actual logs. */ + if (unlikely(new_overflow)) { + /* copy the whole buffer in case of overflow */ + read_offset = 0; + write_offset = buffer_size; + } else if (unlikely((read_offset > buffer_size) || + (write_offset > buffer_size))) { + drm_err(&i915->drm, "invalid GuC log capture buffer state!\n"); + /* copy whole buffer as offsets are unreliable */ + read_offset = 0; + write_offset = buffer_size; + } + + buf.size = buffer_size; + buf.rd = read_offset; + buf.wr = write_offset; + buf.data = src_data; + + if (!uc->reset_in_progress) { + do { + ret = guc_capture_extract_reglists(guc, &buf); + } while (ret >= 0); + } + + /* Update the state of log buffer err-cap state */ + log_buf_state->read_ptr = write_offset; + log_buf_state->flush_to_file = 0; + __guc_capture_flushlog_complete(guc); +} + +void intel_guc_capture_process(struct intel_guc *guc) +{ + if (guc->capture.priv) + __guc_capture_process_output(guc); +} + static void guc_capture_free_ads_cache(struct __guc_state_capture_priv *gc) { @@ -715,6 +1255,8 @@ void intel_guc_capture_destroy(struct intel_guc *guc) guc_capture_free_ads_cache(guc->capture.priv); + guc_capture_delete_nodes(guc); + if (guc->capture.priv->extlists) { guc_capture_free_extlists(guc->capture.priv->extlists); kfree(guc->capture.priv->extlists); @@ -732,5 +1274,7 @@ int intel_guc_capture_init(struct intel_guc *guc) guc->capture.priv->reglists = guc_capture_get_device_reglist(guc); + INIT_LIST_HEAD(&guc->capture.priv->outlist); + return 0; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h index 24a11f33f7d9..3c79460c7ca5 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h @@ -12,6 +12,7 @@ struct file; struct guc_gt_system_info; struct intel_guc; +void intel_guc_capture_process(struct intel_guc *guc); int intel_guc_capture_output_min_size_est(struct intel_guc *guc); int intel_guc_capture_getlist(struct intel_guc *guc, u32 owner, u32 type, u32 classid, struct file **fileptr); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c index e9a865c2f4cb..8d59a11ec595 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c @@ -158,9 +158,9 @@ static void *guc_get_write_buffer(struct intel_guc_log *log) return relay_reserve(log->relay.channel, 0); } -static bool guc_check_log_buf_overflow(struct intel_guc_log *log, - enum guc_log_buffer_type type, - unsigned int full_cnt) +bool intel_guc_check_log_buf_overflow(struct intel_guc_log *log, + enum guc_log_buffer_type type, + unsigned int full_cnt) { unsigned int prev_full_cnt = log->stats[type].sampled_overflow; bool overflow = false; @@ -183,7 +183,7 @@ static bool guc_check_log_buf_overflow(struct intel_guc_log *log, return overflow; } -static unsigned int guc_get_log_buffer_size(enum guc_log_buffer_type type) +unsigned int intel_guc_get_log_buffer_size(enum guc_log_buffer_type type) { switch (type) { case GUC_DEBUG_LOG_BUFFER: @@ -199,6 +199,20 @@ static unsigned int guc_get_log_buffer_size(enum guc_log_buffer_type type) return 0; } +size_t intel_guc_get_log_buffer_offset(enum guc_log_buffer_type type) +{ + enum guc_log_buffer_type i; + size_t offset = PAGE_SIZE;/* for the log_buffer_states */ + + for (i = GUC_DEBUG_LOG_BUFFER; i < GUC_MAX_LOG_BUFFER; ++i) { + if (i == type) + break; + offset += intel_guc_get_log_buffer_size(i); + } + + return offset; +} + static void _guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log) { unsigned int buffer_size, read_offset, write_offset, bytes_to_copy, full_cnt; @@ -243,14 +257,14 @@ static void _guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log) */ memcpy(&log_buf_state_local, log_buf_state, sizeof(struct guc_log_buffer_state)); - buffer_size = guc_get_log_buffer_size(type); + buffer_size = intel_guc_get_log_buffer_size(type); read_offset = log_buf_state_local.read_ptr; write_offset = log_buf_state_local.sampled_write_ptr; full_cnt = log_buf_state_local.buffer_full_cnt; /* Bookkeeping stuff */ log->stats[type].flush += log_buf_state_local.flush_to_file; - new_overflow = guc_check_log_buf_overflow(log, type, full_cnt); + new_overflow = intel_guc_check_log_buf_overflow(log, type, full_cnt); /* Update the state of shared log buffer */ log_buf_state->read_ptr = write_offset; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h index e1345fca7729..18007e639be9 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h @@ -67,6 +67,10 @@ struct intel_guc_log { }; void intel_guc_log_init_early(struct intel_guc_log *log); +bool intel_guc_check_log_buf_overflow(struct intel_guc_log *log, enum guc_log_buffer_type type, + unsigned int full_cnt); +unsigned int intel_guc_get_log_buffer_size(enum guc_log_buffer_type type); +size_t intel_guc_get_log_buffer_offset(enum guc_log_buffer_type type); int intel_guc_log_create(struct intel_guc_log *log); void intel_guc_log_destroy(struct intel_guc_log *log); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index ab3cea352fb3..870b48456e9c 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -25,6 +25,7 @@ #include "gt/intel_ring.h" #include "intel_guc_ads.h" +#include "intel_guc_capture.h" #include "intel_guc_submission.h" #include "i915_drv.h" @@ -4070,17 +4071,18 @@ int intel_guc_context_reset_process_msg(struct intel_guc *guc, int intel_guc_error_capture_process_msg(struct intel_guc *guc, const u32 *msg, u32 len) { - int status; + u32 status; if (unlikely(len != 1)) { drm_dbg(&guc_to_gt(guc)->i915->drm, "Invalid length %u", len); return -EPROTO; } - status = msg[0]; - drm_info(&guc_to_gt(guc)->i915->drm, "Got error capture: status = %d", status); + status = msg[0] & INTEL_GUC_STATE_CAPTURE_EVENT_STATUS_MASK; + if (status == INTEL_GUC_STATE_CAPTURE_EVENT_STATUS_NOSPACE) + drm_warn(&guc_to_gt(guc)->i915->drm, "G2H-Error capture no space"); - /* FIXME: Do something with the capture */ + intel_guc_capture_process(guc); return 0; } From patchwork Sat Feb 26 09:55:39 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Previn X-Patchwork-Id: 12761261 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 1D99CC433EF for ; Sat, 26 Feb 2022 09:54:00 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 3636410ED6B; Sat, 26 Feb 2022 09:53:40 +0000 (UTC) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTPS id 11AD810E44D for ; Sat, 26 Feb 2022 09:53:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1645869216; x=1677405216; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=NL4dYF3psQCTDXm8iLpcsNpQ13QYeDKFUh7x1XZQfgk=; b=MRSHiSKwnFeBQcDR0PWaehnCWPvIFFyG1Ol/+R+YhLBrWgE1wUXZAP33 NwtbdNXIwyKqKrABHjdZOjsmw2PcPpAIB4ihek3bl2TOZqMioxfFf2a6V knD4031n24E0vqB4CUc6gDXUlx40ceXbkT4tRmWDKwbbFTjvmy0e8BrGL akAv2bsLBFB+b3KwGxQECcGA+sCPccerAgIi+6KYPlf7L2+9ZCNi0FvBf Am7foPq9AwBKZF0WkkyDbYuEFsDKfS/Q1DGDW78jxRO96TVnJmxyO/Y7m 2qGIFvsO2jgOAmhXrEBKE3XVgnkABCirHgXkdri0I+OgWexT4kpO7pIJa A==; X-IronPort-AV: E=McAfee;i="6200,9189,10269"; a="277288186" X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="277288186" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Feb 2022 01:53:35 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="506953250" Received: from aalteres-desk.fm.intel.com ([10.80.57.53]) by orsmga002.jf.intel.com with ESMTP; 26 Feb 2022 01:53:34 -0800 From: Alan Previn To: intel-gfx@lists.freedesktop.org Date: Sat, 26 Feb 2022 01:55:39 -0800 Message-Id: <20220226095541.1010534-12-alan.previn.teres.alexis@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> References: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v7 11/13] drm/i915/guc: Pre-allocate output nodes for extraction X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alan Previn Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" In the rare but possible scenario where we are in the midst of multiple GuC error-capture (and engine reset) events and the user also triggers a forced full GT reset or the internal watchdog triggers the same, intel_guc_submission_reset_prepare's call to flush_work(&guc->ct.requests.worker) can cause the G2H message handler to trigger intel_guc_capture_store_snapshot upon receiving new G2H error-capture notifications. This can happen despite the prior call to disable_submission(guc);. However, there's no race-free way for intel_guc_capture_store_snapshot to know that we are in the midst of a reset. That said, we can never dynamically allocate the output nodes in this handler. Thus, we shall pre-allocate a fixed number of empty nodes up front (at the time of ADS registration) that we can consume from or return to an internal cached list of nodes. Signed-off-by: Alan Previn Reviewed-by: Umesh Nerlige Ramappa --- drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h | 19 +- .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 178 ++++++++++++++---- 2 files changed, 160 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h index 2b09aa05d8b7..a77a6274e0b0 100644 --- a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h @@ -31,7 +31,7 @@ struct __guc_capture_bufstate { * * A single unit of extracted error-capture output data grouped together * at an engine-instance level. We keep these nodes in a linked list. - * See outlist below. + * See cachelist and outlist below. */ struct __guc_capture_parsed_output { /* @@ -188,7 +188,22 @@ struct __guc_state_capture_priv { [GUC_MAX_ENGINE_CLASSES]; /** - * @outlist: allocated nodes with parsed engine-instance error capture data + * @cachelist: Pool of pre-allocated nodes for error capture output + * + * We need this pool of pre-allocated nodes because we cannot + * dynamically allocate new nodes when receiving the G2H notification + * because the event handlers for all G2H event-processing is called + * by the ct processing worker queue and when that queue is being + * processed, there is no absoluate guarantee that we are not in the + * midst of a GT reset operation (which doesn't allow allocations). + */ + struct list_head cachelist; +#define PREALLOC_NODES_MAX_COUNT (3 * GUC_MAX_ENGINE_CLASSES * GUC_MAX_INSTANCES_PER_CLASS) +#define PREALLOC_NODES_DEFAULT_NUMREGS 64 + int max_mmio_per_node; + + /** + * @outlist: Pool of pre-allocated nodes for error capture output * * A linked list of parsed GuC error-capture output data before * reporting with formatting via i915_gpu_coredump. Each node in this linked list shall diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index 9308157d9a74..7bd297515504 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -583,6 +583,8 @@ intel_guc_capture_getlistsize(struct intel_guc *guc, u32 owner, u32 type, u32 cl return 0; } +static void guc_capture_create_prealloc_nodes(struct intel_guc *guc); + int intel_guc_capture_getlist(struct intel_guc *guc, u32 owner, u32 type, u32 classid, struct file **fileoutptr) @@ -604,6 +606,12 @@ intel_guc_capture_getlist(struct intel_guc *guc, u32 owner, u32 type, u32 classi return cache->status; } + /* + * ADS population of input registers is a good + * time to pre-allocate cachelist output nodes + */ + guc_capture_create_prealloc_nodes(guc); + ret = intel_guc_capture_getlistsize(guc, owner, type, classid, &size); if (ret) { cache->is_valid = true; @@ -721,7 +729,8 @@ int intel_guc_capture_output_min_size_est(struct intel_guc *guc) * err-state-captured register-list we find, we alloc 'C': * --> alloc C: A capture-output-node structure that includes misc capture info along * with 3 register list dumps (global, engine-class and engine-instance) - * This node is dynamically allocated and populated with the error-capture + * This node is created from a pre-allocated list of blank nodes in + * guc->capture->priv->cachelist and populated with the error-capture * data from GuC and then it's added into guc->capture->priv->outlist linked * list. This list is used for matchup and printout by i915_gpu_coredump * and err_print_gt, (when user invokes the error capture sysfs). @@ -865,19 +874,20 @@ guc_capture_delete_one_node(struct intel_guc *guc, struct __guc_capture_parsed_o } static void -guc_capture_delete_nodes(struct intel_guc *guc) +guc_capture_delete_prealloc_nodes(struct intel_guc *guc) { + struct __guc_capture_parsed_output *n, *ntmp; + /* * NOTE: At the end of driver operation, we must assume that we - * have nodes in outlist from unclaimed error capture events - * that occurred prior to shutdown. + * have prealloc nodes in both the cachelist as well as outlist + * if unclaimed error capture events occurred prior to shutdown. */ - if (!list_empty(&guc->capture.priv->outlist)) { - struct __guc_capture_parsed_output *n, *ntmp; + list_for_each_entry_safe(n, ntmp, &guc->capture.priv->outlist, link) + guc_capture_delete_one_node(guc, n); - list_for_each_entry_safe(n, ntmp, &guc->capture.priv->outlist, link) - guc_capture_delete_one_node(guc, n); - } + list_for_each_entry_safe(n, ntmp, &guc->capture.priv->cachelist, link) + guc_capture_delete_one_node(guc, n); } static void @@ -894,21 +904,80 @@ guc_capture_add_node_to_outlist(struct __guc_state_capture_priv *gc, guc_capture_add_node_to_list(node, &gc->outlist); } +static void +guc_capture_add_node_to_cachelist(struct __guc_state_capture_priv *gc, + struct __guc_capture_parsed_output *node) +{ + guc_capture_add_node_to_list(node, &gc->cachelist); +} + static void guc_capture_init_node(struct intel_guc *guc, struct __guc_capture_parsed_output *node) { + struct guc_mmio_reg *tmp[GUC_CAPTURE_LIST_TYPE_MAX]; + int i; + + for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { + tmp[i] = node->reginfo[i].regs; + memset(tmp[i], 0, sizeof(struct guc_mmio_reg) * + guc->capture.priv->max_mmio_per_node); + } + memset(node, 0, sizeof(*node)); + for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) + node->reginfo[i].regs = tmp[i]; + INIT_LIST_HEAD(&node->link); } +static struct __guc_capture_parsed_output * +guc_capture_get_prealloc_node(struct intel_guc *guc) +{ + struct __guc_capture_parsed_output *found = NULL; + + if (!list_empty(&guc->capture.priv->cachelist)) { + struct __guc_capture_parsed_output *n, *ntmp; + + /* get first avail node from the cache list */ + list_for_each_entry_safe(n, ntmp, &guc->capture.priv->cachelist, link) { + found = n; + list_del(&n->link); + break; + } + } else { + struct __guc_capture_parsed_output *n, *ntmp; + + /* traverse down and steal back the oldest node already allocated */ + list_for_each_entry_safe(n, ntmp, &guc->capture.priv->outlist, link) { + found = n; + } + if (found) + list_del(&found->link); + } + if (found) + guc_capture_init_node(guc, found); + + return found; +} + static struct __guc_capture_parsed_output * guc_capture_alloc_one_node(struct intel_guc *guc) { struct __guc_capture_parsed_output *new; + int i; new = kzalloc(sizeof(*new), GFP_KERNEL); if (!new) return NULL; + for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { + new->reginfo[i].regs = kcalloc(guc->capture.priv->max_mmio_per_node, + sizeof(struct guc_mmio_reg), GFP_KERNEL); + if (!new->reginfo[i].regs) { + while (i) + kfree(new->reginfo[--i].regs); + return NULL; + } + } guc_capture_init_node(guc, new); return new; @@ -921,7 +990,7 @@ guc_capture_clone_node(struct intel_guc *guc, struct __guc_capture_parsed_output struct __guc_capture_parsed_output *new; int i; - new = guc_capture_alloc_one_node(guc); + new = guc_capture_get_prealloc_node(guc); if (!new) return NULL; if (!ori) @@ -932,16 +1001,14 @@ guc_capture_clone_node(struct intel_guc *guc, struct __guc_capture_parsed_output /* copy reg-lists that we want to clone */ for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { if (keep_reglist_mask & BIT(i)) { - new->reginfo[i].regs = kcalloc(ori->reginfo[i].num_regs, - sizeof(struct guc_mmio_reg), GFP_KERNEL); - if (!new->reginfo[i].regs) - goto bail_clone; + GEM_BUG_ON(ori->reginfo[i].num_regs > + guc->capture.priv->max_mmio_per_node); memcpy(new->reginfo[i].regs, ori->reginfo[i].regs, ori->reginfo[i].num_regs * sizeof(struct guc_mmio_reg)); + new->reginfo[i].num_regs = ori->reginfo[i].num_regs; new->reginfo[i].vfid = ori->reginfo[i].vfid; - if (i == GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS) { new->eng_class = ori->eng_class; } else if (i == GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE) { @@ -953,14 +1020,58 @@ guc_capture_clone_node(struct intel_guc *guc, struct __guc_capture_parsed_output } return new; +} -bail_clone: - for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { - if (new->reginfo[i].regs) - kfree(new->reginfo[i].regs); +static void +__guc_capture_create_prealloc_nodes(struct intel_guc *guc) +{ + struct __guc_capture_parsed_output *node = NULL; + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + int i; + + for (i = 0; i < PREALLOC_NODES_MAX_COUNT; ++i) { + node = guc_capture_alloc_one_node(guc); + if (!node) { + drm_warn(&i915->drm, "GuC Capture pre-alloc-cache failure\n"); + /* dont free the priors, use what we got and cleanup at shutdown */ + return; + } + guc_capture_add_node_to_cachelist(guc->capture.priv, node); } - kfree(new); - return NULL; +} + +static int +guc_get_max_reglist_count(struct intel_guc *guc) +{ + int i, j, k, tmp, maxregcount = 0; + + for (i = 0; i < GUC_CAPTURE_LIST_INDEX_MAX; ++i) { + for (j = 0; j < GUC_CAPTURE_LIST_TYPE_MAX; ++j) { + for (k = 0; k < GUC_MAX_ENGINE_CLASSES; ++k) { + if (j == GUC_CAPTURE_LIST_TYPE_GLOBAL && k > 0) + continue; + + tmp = guc_cap_list_num_regs(guc->capture.priv, i, j, k); + if (tmp > maxregcount) + maxregcount = tmp; + } + } + } + if (!maxregcount) + maxregcount = PREALLOC_NODES_DEFAULT_NUMREGS; + + return maxregcount; +} + +static void +guc_capture_create_prealloc_nodes(struct intel_guc *guc) +{ + /* skip if we've already done the pre-alloc */ + if (guc->capture.priv->max_mmio_per_node) + return; + + guc->capture.priv->max_mmio_per_node = guc_get_max_reglist_count(guc); + __guc_capture_create_prealloc_nodes(guc); } static int @@ -1076,13 +1187,13 @@ guc_capture_extract_reglists(struct intel_guc *guc, struct __guc_capture_bufstat guc_capture_add_node_to_outlist(guc->capture.priv, node); node = NULL; } else if (datatype == GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS && - node->reginfo[GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS].regs) { + node->reginfo[GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS].num_regs) { /* Add to list, clone node and duplicate global list */ guc_capture_add_node_to_outlist(guc->capture.priv, node); node = guc_capture_clone_node(guc, node, GCAP_PARSED_REGLIST_INDEX_GLOBAL); } else if (datatype == GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE && - node->reginfo[GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE].regs) { + node->reginfo[GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE].num_regs) { /* Add to list, clone node and duplicate global + class lists */ guc_capture_add_node_to_outlist(guc->capture.priv, node); node = guc_capture_clone_node(guc, node, @@ -1092,7 +1203,7 @@ guc_capture_extract_reglists(struct intel_guc *guc, struct __guc_capture_bufstat } if (!node) { - node = guc_capture_alloc_one_node(guc); + node = guc_capture_get_prealloc_node(guc); if (!node) { ret = -ENOMEM; break; @@ -1117,17 +1228,13 @@ guc_capture_extract_reglists(struct intel_guc *guc, struct __guc_capture_bufstat break; } - regs = NULL; numregs = FIELD_GET(CAP_HDR_NUM_MMIOS, hdr.num_mmios); - if (numregs) { - regs = kcalloc(numregs, sizeof(struct guc_mmio_reg), GFP_KERNEL); - if (!regs) { - ret = -ENOMEM; - break; - } + if (numregs > guc->capture.priv->max_mmio_per_node) { + drm_dbg(&i915->drm, "GuC Capture list extraction clipped by prealloc!\n"); + numregs = guc->capture.priv->max_mmio_per_node; } node->reginfo[datatype].num_regs = numregs; - node->reginfo[datatype].regs = regs; + regs = node->reginfo[datatype].regs; i = 0; while (numregs--) { if (guc_capture_log_get_register(guc, buf, ®s[i++])) { @@ -1147,8 +1254,8 @@ guc_capture_extract_reglists(struct intel_guc *guc, struct __guc_capture_bufstat break; } } - if (node) /* else free it */ - kfree(node); + if (node) /* else return it back to cache list */ + guc_capture_add_node_to_cachelist(guc->capture.priv, node); } return ret; } @@ -1255,7 +1362,7 @@ void intel_guc_capture_destroy(struct intel_guc *guc) guc_capture_free_ads_cache(guc->capture.priv); - guc_capture_delete_nodes(guc); + guc_capture_delete_prealloc_nodes(guc); if (guc->capture.priv->extlists) { guc_capture_free_extlists(guc->capture.priv->extlists); @@ -1275,6 +1382,7 @@ int intel_guc_capture_init(struct intel_guc *guc) guc->capture.priv->reglists = guc_capture_get_device_reglist(guc); INIT_LIST_HEAD(&guc->capture.priv->outlist); + INIT_LIST_HEAD(&guc->capture.priv->cachelist); return 0; } From patchwork Sat Feb 26 09:55:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Previn X-Patchwork-Id: 12761260 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 47AC9C433FE for ; Sat, 26 Feb 2022 09:53:59 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 6D10910EA53; Sat, 26 Feb 2022 09:53:39 +0000 (UTC) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTPS id 3B8DC10E451 for ; Sat, 26 Feb 2022 09:53:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1645869216; x=1677405216; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Xbaw4y/cNiFkElWK48uYHmTnbSPRYx60tmeJSgImn+o=; b=HnnbzF3hJrLlWqymFe30GyQxnhCYykWmxsRfy7LLAF9UniDkNh3Q8LNS NSbbJpOzUSpCv1OWJOl6cnSO6w5w0yCC19Sav3ZSnevOhyLE8LWSvDWiI Vzv+qlUMjNc9UQzSkjVUrnr8SG61E2MigDVACwRfe3KcOT8rdOZCT86Pb y3scsdKs+t3aeU6q7uzMGCq6rAPlnOYGzSiOA+RSFtwrcYQhJgQSY67XC NNZOhrw8/tghaa86LDfG6VM7gyQorTUCz1YDIKvzVusiHStsTWMeoqwJv VJjkUC2AZo7NnwgU7C22ou4Fd3acKNVE3MSaaEIpogcONgNkX+UWt1/3Z A==; X-IronPort-AV: E=McAfee;i="6200,9189,10269"; a="277288187" X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="277288187" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Feb 2022 01:53:35 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="506953253" Received: from aalteres-desk.fm.intel.com ([10.80.57.53]) by orsmga002.jf.intel.com with ESMTP; 26 Feb 2022 01:53:34 -0800 From: Alan Previn To: intel-gfx@lists.freedesktop.org Date: Sat, 26 Feb 2022 01:55:40 -0800 Message-Id: <20220226095541.1010534-13-alan.previn.teres.alexis@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> References: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v7 12/13] drm/i915/guc: Plumb GuC-capture into gpu_coredump X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alan Previn Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Add a flags parameter through all of the coredump creation functions. Add a bitmask flag to indicate if the top level gpu_coredump event is triggered in response to a GuC context reset notification. Using that flag, ensure all coredump functions that read or print mmio-register values related to work submission or command-streamer engines are skipped and replaced with a calls guc-capture module equivalent functions to retrieve or print the register dump. While here, split out display related register reading and printing into its own function that is called agnostic to whether GuC had triggered the reset. For now, introduce an empty printing function that can filled in on a subsequent patch just to handle formatting. Signed-off-by: Alan Previn Reviewed-by: Umesh Nerlige Ramappa --- .../drm/i915/gt/intel_execlists_submission.c | 4 +- drivers/gpu/drm/i915/gt/intel_reset.c | 2 +- .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 69 +++++ .../gpu/drm/i915/gt/uc/intel_guc_capture.h | 10 + .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 2 +- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_gpu_error.c | 266 ++++++++++++------ drivers/gpu/drm/i915/i915_gpu_error.h | 30 +- 8 files changed, 288 insertions(+), 97 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index 961d795220a3..fc7c27df5d44 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c @@ -2231,11 +2231,11 @@ static struct execlists_capture *capture_regs(struct intel_engine_cs *engine) if (!cap->error) goto err_cap; - cap->error->gt = intel_gt_coredump_alloc(engine->gt, gfp); + cap->error->gt = intel_gt_coredump_alloc(engine->gt, gfp, CORE_DUMP_FLAG_NONE); if (!cap->error->gt) goto err_gpu; - cap->error->gt->engine = intel_engine_coredump_alloc(engine, gfp); + cap->error->gt->engine = intel_engine_coredump_alloc(engine, gfp, CORE_DUMP_FLAG_NONE); if (!cap->error->gt->engine) goto err_gt; diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index 82713264b96c..2d120bd391a2 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -1318,7 +1318,7 @@ void intel_gt_handle_error(struct intel_gt *gt, engine_mask &= gt->info.engine_mask; if (flags & I915_ERROR_CAPTURE) { - i915_capture_error_state(gt, engine_mask); + i915_capture_error_state(gt, engine_mask, CORE_DUMP_FLAG_NONE); intel_gt_clear_error_registers(gt, engine_mask); } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index 7bd297515504..621c0b4537a9 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -734,6 +734,18 @@ int intel_guc_capture_output_min_size_est(struct intel_guc *guc) * data from GuC and then it's added into guc->capture->priv->outlist linked * list. This list is used for matchup and printout by i915_gpu_coredump * and err_print_gt, (when user invokes the error capture sysfs). + * + * GUC --> notify context reset: + * ----------------------------- + * --> G2H CONTEXT RESET + * L--> guc_handle_context_reset --> i915_capture_error_state + * L--> i915_gpu_coredump(..IS_GUC_CAPTURE) --> gt_record_engines + * --> capture_engine(..IS_GUC_CAPTURE) + * L--> intel_guc_capture_get_matching_node is where + * detach C from internal linked list and add it into + * intel_engine_coredump struct (if the context and + * engine of the event notification matches a node + * in the link list). */ static int guc_capture_buf_cnt(struct __guc_capture_bufstate *buf) @@ -1332,6 +1344,63 @@ static void __guc_capture_process_output(struct intel_guc *guc) __guc_capture_flushlog_complete(guc); } +#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) + +int intel_guc_capture_print_engine_node(struct drm_i915_error_state_buf *ebuf, + const struct intel_engine_coredump *ee) +{ + return 0; +} + +#endif //CONFIG_DRM_I915_CAPTURE_ERROR + +void intel_guc_capture_free_node(struct intel_engine_coredump *ee) +{ + if (!ee || !ee->guc_capture_node) + return; + + guc_capture_add_node_to_cachelist(ee->capture->priv, ee->guc_capture_node); + ee->capture = NULL; + ee->guc_capture_node = NULL; +} + +void intel_guc_capture_get_matching_node(struct intel_gt *gt, + struct intel_engine_coredump *ee, + struct intel_context *ce) +{ + struct __guc_capture_parsed_output *n, *ntmp; + struct drm_i915_private *i915; + struct intel_guc *guc; + + if (!gt || !ee || !ce) + return; + + i915 = gt->i915; + guc = >->uc.guc; + if (!guc->capture.priv) + return; + + GEM_BUG_ON(ee->guc_capture_node); + /* + * Look for a matching GuC reported error capture node from + * the internal output link-list based on lrca, guc-id and engine + * identification. + */ + list_for_each_entry_safe(n, ntmp, &guc->capture.priv->outlist, link) { + if (n->eng_inst == GUC_ID_TO_ENGINE_INSTANCE(ee->engine->guc_id) && + n->eng_class == GUC_ID_TO_ENGINE_CLASS(ee->engine->guc_id) && + n->guc_id && n->guc_id == ce->guc_id.id && + (n->lrca & CTX_GTT_ADDRESS_MASK) && (n->lrca & CTX_GTT_ADDRESS_MASK) == + (ce->lrc.lrca & CTX_GTT_ADDRESS_MASK)) { + list_del(&n->link); + ee->guc_capture_node = n; + ee->capture = &guc->capture; + return; + } + } + drm_dbg(&i915->drm, "GuC capture can't match ee to node\n"); +} + void intel_guc_capture_process(struct intel_guc *guc) { if (guc->capture.priv) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h index 3c79460c7ca5..ae527c98e2f6 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h @@ -8,10 +8,20 @@ #include +struct drm_i915_error_state_buf; struct file; +struct guc_ads; struct guc_gt_system_info; +struct intel_context; +struct intel_engine_coredump; +struct intel_gt; struct intel_guc; +void intel_guc_capture_free_node(struct intel_engine_coredump *ee); +int intel_guc_capture_print_engine_node(struct drm_i915_error_state_buf *m, + const struct intel_engine_coredump *ee); +void intel_guc_capture_get_matching_node(struct intel_gt *gt, struct intel_engine_coredump *ee, + struct intel_context *ce); void intel_guc_capture_process(struct intel_guc *guc); int intel_guc_capture_output_min_size_est(struct intel_guc *guc); int intel_guc_capture_getlist(struct intel_guc *guc, u32 owner, u32 type, u32 classid, diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 870b48456e9c..5d41dc95f066 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -4005,7 +4005,7 @@ static void capture_error_state(struct intel_guc *guc, intel_engine_set_hung_context(engine, ce); with_intel_runtime_pm(&i915->runtime_pm, wakeref) - i915_capture_error_state(gt, engine->mask); + i915_capture_error_state(gt, engine->mask, CORE_DUMP_FLAG_IS_GUC_CAPTURE); atomic_inc(&i915->gpu_error.reset_engine_count[engine->uabi_class]); } diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 946bbe57bfe5..274abf267f35 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -307,7 +307,7 @@ static int i915_gpu_info_open(struct inode *inode, struct file *file) gpu = NULL; with_intel_runtime_pm(&i915->runtime_pm, wakeref) - gpu = i915_gpu_coredump(to_gt(i915), ALL_ENGINES); + gpu = i915_gpu_coredump(to_gt(i915), ALL_ENGINES, CORE_DUMP_FLAG_NONE); if (IS_ERR(gpu)) return PTR_ERR(gpu); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 1d042551619e..3d566bbe228d 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -46,6 +46,7 @@ #include "gt/intel_gt.h" #include "gt/intel_gt_pm.h" #include "gt/intel_gt_regs.h" +#include "gt/uc/intel_guc_capture.h" #include "i915_driver.h" #include "i915_drv.h" @@ -593,15 +594,11 @@ static void error_print_engine(struct drm_i915_error_state_buf *m, ee->vm_info.pp_dir_base); } } - err_printf(m, " hung: %u\n", ee->hung); - err_printf(m, " engine reset count: %u\n", ee->reset_count); for (n = 0; n < ee->num_ports; n++) { err_printf(m, " ELSP[%d]:", n); error_print_request(m, " ", &ee->execlist[n]); } - - error_print_context(m, " Active context: ", &ee->context); } void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...) @@ -713,23 +710,30 @@ static void err_print_gt_info(struct drm_i915_error_state_buf *m, intel_sseu_print_topology(>->info.sseu, &p); } -static void err_print_gt(struct drm_i915_error_state_buf *m, - struct intel_gt_coredump *gt) +static void err_print_gt_display(struct drm_i915_error_state_buf *m, + struct intel_gt_coredump *gt) +{ + err_printf(m, "IER: 0x%08x\n", gt->ier); + err_printf(m, "DERRMR: 0x%08x\n", gt->derrmr); +} + +static void err_print_gt_global_nonguc(struct drm_i915_error_state_buf *m, + struct intel_gt_coredump *gt) { - const struct intel_engine_coredump *ee; int i; err_printf(m, "GT awake: %s\n", yesno(gt->awake)); err_printf(m, "EIR: 0x%08x\n", gt->eir); - err_printf(m, "IER: 0x%08x\n", gt->ier); + err_printf(m, "PGTBL_ER: 0x%08x\n", gt->pgtbl_er); + for (i = 0; i < gt->ngtier; i++) err_printf(m, "GTIER[%d]: 0x%08x\n", i, gt->gtier[i]); - err_printf(m, "PGTBL_ER: 0x%08x\n", gt->pgtbl_er); - err_printf(m, "FORCEWAKE: 0x%08x\n", gt->forcewake); - err_printf(m, "DERRMR: 0x%08x\n", gt->derrmr); +} - for (i = 0; i < gt->nfence; i++) - err_printf(m, " fence[%d] = %08llx\n", i, gt->fence[i]); +static void err_print_gt_global(struct drm_i915_error_state_buf *m, + struct intel_gt_coredump *gt) +{ + err_printf(m, "FORCEWAKE: 0x%08x\n", gt->forcewake); if (IS_GRAPHICS_VER(m->i915, 6, 11)) { err_printf(m, "ERROR: 0x%08x\n", gt->error); @@ -768,19 +772,38 @@ static void err_print_gt(struct drm_i915_error_state_buf *m, err_printf(m, " GAM_DONE: 0x%08x\n", gt->gam_done); } +} + +static void err_print_gt_fences(struct drm_i915_error_state_buf *m, + struct intel_gt_coredump *gt) +{ + int i; + + for (i = 0; i < gt->nfence; i++) + err_printf(m, " fence[%d] = %08llx\n", i, gt->fence[i]); +} + +static void err_print_gt_engines(struct drm_i915_error_state_buf *m, + struct intel_gt_coredump *gt) +{ + const struct intel_engine_coredump *ee; for (ee = gt->engine; ee; ee = ee->next) { const struct i915_vma_coredump *vma; - error_print_engine(m, ee); + if (ee->guc_capture_node) + intel_guc_capture_print_engine_node(m, ee); + else + error_print_engine(m, ee); + + err_printf(m, " hung: %u\n", ee->hung); + err_printf(m, " engine reset count: %u\n", ee->reset_count); + error_print_context(m, " Active context: ", &ee->context); + for (vma = ee->vma; vma; vma = vma->next) print_error_vma(m, ee->engine, vma); } - if (gt->uc) - err_print_uc(m, gt->uc); - - err_print_gt_info(m, gt); } static void __err_print_to_sgl(struct drm_i915_error_state_buf *m, @@ -836,8 +859,30 @@ static void __err_print_to_sgl(struct drm_i915_error_state_buf *m, err_printf(m, "RPM wakelock: %s\n", yesno(error->wakelock)); err_printf(m, "PM suspended: %s\n", yesno(error->suspended)); - if (error->gt) - err_print_gt(m, error->gt); + if (error->gt) { + bool print_guc_capture = false; + + if (error->gt->uc && error->gt->uc->is_guc_capture) + print_guc_capture = true; + + err_print_gt_display(m, error->gt); + err_print_gt_global_nonguc(m, error->gt); + err_print_gt_fences(m, error->gt); + + /* + * GuC dumped global, eng-class and eng-instance registers together + * as part of engine state dump so we print in err_print_gt_engines + */ + if (!print_guc_capture) + err_print_gt_global(m, error->gt); + + err_print_gt_engines(m, error->gt); + + if (error->gt->uc) + err_print_uc(m, error->gt->uc); + + err_print_gt_info(m, error->gt); + } if (error->overlay) intel_overlay_print_error_state(m, error->overlay); @@ -985,6 +1030,7 @@ static void cleanup_gt(struct intel_gt_coredump *gt) gt->engine = ee->next; i915_vma_coredump_free(ee->vma); + intel_guc_capture_free_node(ee); kfree(ee); } @@ -1436,7 +1482,7 @@ static void add_vma_coredump(struct intel_engine_coredump *ee, } struct intel_engine_coredump * -intel_engine_coredump_alloc(struct intel_engine_cs *engine, gfp_t gfp) +intel_engine_coredump_alloc(struct intel_engine_cs *engine, gfp_t gfp, u32 dump_flags) { struct intel_engine_coredump *ee; @@ -1446,8 +1492,10 @@ intel_engine_coredump_alloc(struct intel_engine_cs *engine, gfp_t gfp) ee->engine = engine; - engine_record_registers(ee); - engine_record_execlists(ee); + if (!(dump_flags & CORE_DUMP_FLAG_IS_GUC_CAPTURE)) { + engine_record_registers(ee); + engine_record_execlists(ee); + } return ee; } @@ -1511,7 +1559,8 @@ intel_engine_coredump_add_vma(struct intel_engine_coredump *ee, static struct intel_engine_coredump * capture_engine(struct intel_engine_cs *engine, - struct i915_vma_compress *compress) + struct i915_vma_compress *compress, + u32 dump_flags) { struct intel_engine_capture_vma *capture = NULL; struct intel_engine_coredump *ee; @@ -1519,7 +1568,7 @@ capture_engine(struct intel_engine_cs *engine, struct i915_request *rq = NULL; unsigned long flags; - ee = intel_engine_coredump_alloc(engine, ALLOW_FAIL); + ee = intel_engine_coredump_alloc(engine, ALLOW_FAIL, dump_flags); if (!ee) return NULL; @@ -1552,6 +1601,8 @@ capture_engine(struct intel_engine_cs *engine, i915_request_put(rq); goto no_request_capture; } + if (dump_flags & CORE_DUMP_FLAG_IS_GUC_CAPTURE) + intel_guc_capture_get_matching_node(engine->gt, ee, ce); intel_engine_coredump_add_vma(ee, capture, compress); i915_request_put(rq); @@ -1566,7 +1617,8 @@ capture_engine(struct intel_engine_cs *engine, static void gt_record_engines(struct intel_gt_coredump *gt, intel_engine_mask_t engine_mask, - struct i915_vma_compress *compress) + struct i915_vma_compress *compress, + u32 dump_flags) { struct intel_engine_cs *engine; enum intel_engine_id id; @@ -1577,7 +1629,7 @@ gt_record_engines(struct intel_gt_coredump *gt, /* Refill our page pool before entering atomic section */ pool_refill(&compress->pool, ALLOW_FAIL); - ee = capture_engine(engine, compress); + ee = capture_engine(engine, compress, dump_flags); if (!ee) continue; @@ -1585,6 +1637,8 @@ gt_record_engines(struct intel_gt_coredump *gt, gt->simulated |= ee->simulated; if (ee->simulated) { + if (dump_flags & CORE_DUMP_FLAG_IS_GUC_CAPTURE) + intel_guc_capture_free_node(ee); kfree(ee); continue; } @@ -1620,8 +1674,74 @@ gt_record_uc(struct intel_gt_coredump *gt, return error_uc; } -/* Capture all registers which don't fit into another category. */ -static void gt_record_regs(struct intel_gt_coredump *gt) +/* Capture display registers. */ +static void gt_record_display_regs(struct intel_gt_coredump *gt) +{ + struct intel_uncore *uncore = gt->_gt->uncore; + struct drm_i915_private *i915 = uncore->i915; + + if (GRAPHICS_VER(i915) >= 6) + gt->derrmr = intel_uncore_read(uncore, DERRMR); + + if (GRAPHICS_VER(i915) >= 8) + gt->ier = intel_uncore_read(uncore, GEN8_DE_MISC_IER); + else if (IS_VALLEYVIEW(i915)) + gt->ier = intel_uncore_read(uncore, VLV_IER); + else if (HAS_PCH_SPLIT(i915)) + gt->ier = intel_uncore_read(uncore, DEIER); + else if (GRAPHICS_VER(i915) == 2) + gt->ier = intel_uncore_read16(uncore, GEN2_IER); + else + gt->ier = intel_uncore_read(uncore, GEN2_IER); +} + +/* Capture all other registers that GuC doesn't capture. */ +static void gt_record_global_nonguc_regs(struct intel_gt_coredump *gt) +{ + struct intel_uncore *uncore = gt->_gt->uncore; + struct drm_i915_private *i915 = uncore->i915; + int i; + + if (IS_VALLEYVIEW(i915)) { + gt->gtier[0] = intel_uncore_read(uncore, GTIER); + gt->ngtier = 1; + } else if (GRAPHICS_VER(i915) >= 11) { + gt->gtier[0] = + intel_uncore_read(uncore, + GEN11_RENDER_COPY_INTR_ENABLE); + gt->gtier[1] = + intel_uncore_read(uncore, GEN11_VCS_VECS_INTR_ENABLE); + gt->gtier[2] = + intel_uncore_read(uncore, GEN11_GUC_SG_INTR_ENABLE); + gt->gtier[3] = + intel_uncore_read(uncore, + GEN11_GPM_WGBOXPERF_INTR_ENABLE); + gt->gtier[4] = + intel_uncore_read(uncore, + GEN11_CRYPTO_RSVD_INTR_ENABLE); + gt->gtier[5] = + intel_uncore_read(uncore, + GEN11_GUNIT_CSME_INTR_ENABLE); + gt->ngtier = 6; + } else if (GRAPHICS_VER(i915) >= 8) { + for (i = 0; i < 4; i++) + gt->gtier[i] = + intel_uncore_read(uncore, GEN8_GT_IER(i)); + gt->ngtier = 4; + } else if (HAS_PCH_SPLIT(i915)) { + gt->gtier[0] = intel_uncore_read(uncore, GTIER); + gt->ngtier = 1; + } + + gt->eir = intel_uncore_read(uncore, EIR); + gt->pgtbl_er = intel_uncore_read(uncore, PGTBL_ER); +} + +/* + * Capture all registers that relate to workload submission. + * NOTE: In GuC submission, when GuC resets an engine, it can dump these for us + */ +static void gt_record_global_regs(struct intel_gt_coredump *gt) { struct intel_uncore *uncore = gt->_gt->uncore; struct drm_i915_private *i915 = uncore->i915; @@ -1637,11 +1757,8 @@ static void gt_record_regs(struct intel_gt_coredump *gt) */ /* 1: Registers specific to a single generation */ - if (IS_VALLEYVIEW(i915)) { - gt->gtier[0] = intel_uncore_read(uncore, GTIER); - gt->ier = intel_uncore_read(uncore, VLV_IER); + if (IS_VALLEYVIEW(i915)) gt->forcewake = intel_uncore_read_fw(uncore, FORCEWAKE_VLV); - } if (GRAPHICS_VER(i915) == 7) gt->err_int = intel_uncore_read(uncore, GEN7_ERR_INT); @@ -1669,7 +1786,6 @@ static void gt_record_regs(struct intel_gt_coredump *gt) gt->forcewake = intel_uncore_read_fw(uncore, FORCEWAKE_MT); if (GRAPHICS_VER(i915) >= 6) { - gt->derrmr = intel_uncore_read(uncore, DERRMR); if (GRAPHICS_VER(i915) < 12) { gt->error = intel_uncore_read(uncore, ERROR_GEN6); gt->done_reg = intel_uncore_read(uncore, DONE_REG); @@ -1705,44 +1821,6 @@ static void gt_record_regs(struct intel_gt_coredump *gt) gt->gam_done = intel_uncore_read(uncore, GEN12_GAM_DONE); } - - /* 4: Everything else */ - if (GRAPHICS_VER(i915) >= 11) { - gt->ier = intel_uncore_read(uncore, GEN8_DE_MISC_IER); - gt->gtier[0] = - intel_uncore_read(uncore, - GEN11_RENDER_COPY_INTR_ENABLE); - gt->gtier[1] = - intel_uncore_read(uncore, GEN11_VCS_VECS_INTR_ENABLE); - gt->gtier[2] = - intel_uncore_read(uncore, GEN11_GUC_SG_INTR_ENABLE); - gt->gtier[3] = - intel_uncore_read(uncore, - GEN11_GPM_WGBOXPERF_INTR_ENABLE); - gt->gtier[4] = - intel_uncore_read(uncore, - GEN11_CRYPTO_RSVD_INTR_ENABLE); - gt->gtier[5] = - intel_uncore_read(uncore, - GEN11_GUNIT_CSME_INTR_ENABLE); - gt->ngtier = 6; - } else if (GRAPHICS_VER(i915) >= 8) { - gt->ier = intel_uncore_read(uncore, GEN8_DE_MISC_IER); - for (i = 0; i < 4; i++) - gt->gtier[i] = - intel_uncore_read(uncore, GEN8_GT_IER(i)); - gt->ngtier = 4; - } else if (HAS_PCH_SPLIT(i915)) { - gt->ier = intel_uncore_read(uncore, DEIER); - gt->gtier[0] = intel_uncore_read(uncore, GTIER); - gt->ngtier = 1; - } else if (GRAPHICS_VER(i915) == 2) { - gt->ier = intel_uncore_read16(uncore, GEN2_IER); - } else if (!IS_VALLEYVIEW(i915)) { - gt->ier = intel_uncore_read(uncore, GEN2_IER); - } - gt->eir = intel_uncore_read(uncore, EIR); - gt->pgtbl_er = intel_uncore_read(uncore, PGTBL_ER); } static void gt_record_info(struct intel_gt_coredump *gt) @@ -1854,7 +1932,7 @@ i915_gpu_coredump_alloc(struct drm_i915_private *i915, gfp_t gfp) #define DAY_AS_SECONDS(x) (24 * 60 * 60 * (x)) struct intel_gt_coredump * -intel_gt_coredump_alloc(struct intel_gt *gt, gfp_t gfp) +intel_gt_coredump_alloc(struct intel_gt *gt, gfp_t gfp, u32 dump_flags) { struct intel_gt_coredump *gc; @@ -1865,7 +1943,21 @@ intel_gt_coredump_alloc(struct intel_gt *gt, gfp_t gfp) gc->_gt = gt; gc->awake = intel_gt_pm_is_awake(gt); - gt_record_regs(gc); + gt_record_display_regs(gc); + gt_record_global_nonguc_regs(gc); + + /* + * GuC dumps global, eng-class and eng-instance registers + * (that can change as part of engine state during execution) + * before an engine is reset due to a hung context. + * GuC captures and reports all three groups of registers + * together as a single set before the engine is reset. + * Thus, if GuC triggered the context reset we retrieve + * the register values as part of gt_record_engines. + */ + if (!(dump_flags & CORE_DUMP_FLAG_IS_GUC_CAPTURE)) + gt_record_global_regs(gc); + gt_record_fences(gc); return gc; @@ -1899,7 +1991,7 @@ void i915_vma_capture_finish(struct intel_gt_coredump *gt, } static struct i915_gpu_coredump * -__i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask) +__i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask, u32 dump_flags) { struct drm_i915_private *i915 = gt->i915; struct i915_gpu_coredump *error; @@ -1913,7 +2005,7 @@ __i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask) if (!error) return ERR_PTR(-ENOMEM); - error->gt = intel_gt_coredump_alloc(gt, ALLOW_FAIL); + error->gt = intel_gt_coredump_alloc(gt, ALLOW_FAIL, dump_flags); if (error->gt) { struct i915_vma_compress *compress; @@ -1924,11 +2016,19 @@ __i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask) return ERR_PTR(-ENOMEM); } + if (INTEL_INFO(i915)->has_gt_uc) { + error->gt->uc = gt_record_uc(error->gt, compress); + if (error->gt->uc) { + if (dump_flags & CORE_DUMP_FLAG_IS_GUC_CAPTURE) + error->gt->uc->is_guc_capture = true; + else + GEM_BUG_ON(error->gt->uc->is_guc_capture); + } + } + gt_record_info(error->gt); - gt_record_engines(error->gt, engine_mask, compress); + gt_record_engines(error->gt, engine_mask, compress, dump_flags); - if (INTEL_INFO(i915)->has_gt_uc) - error->gt->uc = gt_record_uc(error->gt, compress); i915_vma_capture_finish(error->gt, compress); @@ -1941,7 +2041,7 @@ __i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask) } struct i915_gpu_coredump * -i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask) +i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask, u32 dump_flags) { static DEFINE_MUTEX(capture_mutex); int ret = mutex_lock_interruptible(&capture_mutex); @@ -1950,7 +2050,7 @@ i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask) if (ret) return ERR_PTR(ret); - dump = __i915_gpu_coredump(gt, engine_mask); + dump = __i915_gpu_coredump(gt, engine_mask, dump_flags); mutex_unlock(&capture_mutex); return dump; @@ -1997,11 +2097,11 @@ void i915_error_state_store(struct i915_gpu_coredump *error) * to pick up. */ void i915_capture_error_state(struct intel_gt *gt, - intel_engine_mask_t engine_mask) + intel_engine_mask_t engine_mask, u32 dump_flags) { struct i915_gpu_coredump *error; - error = i915_gpu_coredump(gt, engine_mask); + error = i915_gpu_coredump(gt, engine_mask, dump_flags); if (IS_ERR(error)) { cmpxchg(>->i915->gpu_error.first_error, NULL, error); return; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.h b/drivers/gpu/drm/i915/i915_gpu_error.h index 903d838e2e63..64b999d8ac27 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.h +++ b/drivers/gpu/drm/i915/i915_gpu_error.h @@ -53,6 +53,8 @@ struct i915_request_coredump { struct i915_sched_attr sched_attr; }; +struct __guc_capture_parsed_output; + struct intel_engine_coredump { const struct intel_engine_cs *engine; @@ -84,6 +86,10 @@ struct intel_engine_coredump { u32 rc_psmi; /* sleep state */ struct intel_instdone instdone; + /* GuC matched capture-lists info */ + struct intel_guc_state_capture *capture; + struct __guc_capture_parsed_output *guc_capture_node; + struct i915_gem_context_coredump { char comm[TASK_COMM_LEN]; @@ -124,7 +130,6 @@ struct intel_gt_coredump { u32 pgtbl_er; u32 ier; u32 gtier[6], ngtier; - u32 derrmr; u32 forcewake; u32 error; /* gen6+ */ u32 err_int; /* gen7 */ @@ -137,9 +142,12 @@ struct intel_gt_coredump { u32 gfx_mode; u32 gtt_cache; u32 aux_err; /* gen12 */ - u32 sfc_done[GEN12_SFC_DONE_MAX]; /* gen12 */ u32 gam_done; /* gen12 */ + /* Display related */ + u32 derrmr; + u32 sfc_done[GEN12_SFC_DONE_MAX]; /* gen12 */ + u32 nfence; u64 fence[I915_MAX_NUM_FENCES]; @@ -149,6 +157,7 @@ struct intel_gt_coredump { struct intel_uc_fw guc_fw; struct intel_uc_fw huc_fw; struct i915_vma_coredump *guc_log; + bool is_guc_capture; } *uc; struct intel_gt_coredump *next; @@ -221,24 +230,27 @@ static inline u32 i915_reset_engine_count(struct i915_gpu_error *error, return atomic_read(&error->reset_engine_count[engine->uabi_class]); } +#define CORE_DUMP_FLAG_NONE 0x0 +#define CORE_DUMP_FLAG_IS_GUC_CAPTURE BIT(0) + #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) __printf(2, 3) void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...); struct i915_gpu_coredump *i915_gpu_coredump(struct intel_gt *gt, - intel_engine_mask_t engine_mask); + intel_engine_mask_t engine_mask, u32 dump_flags); void i915_capture_error_state(struct intel_gt *gt, - intel_engine_mask_t engine_mask); + intel_engine_mask_t engine_mask, u32 dump_flags); struct i915_gpu_coredump * i915_gpu_coredump_alloc(struct drm_i915_private *i915, gfp_t gfp); struct intel_gt_coredump * -intel_gt_coredump_alloc(struct intel_gt *gt, gfp_t gfp); +intel_gt_coredump_alloc(struct intel_gt *gt, gfp_t gfp, u32 dump_flags); struct intel_engine_coredump * -intel_engine_coredump_alloc(struct intel_engine_cs *engine, gfp_t gfp); +intel_engine_coredump_alloc(struct intel_engine_cs *engine, gfp_t gfp, u32 dump_flags); struct intel_engine_capture_vma * intel_engine_coredump_add_request(struct intel_engine_coredump *ee, @@ -282,7 +294,7 @@ void i915_disable_error_state(struct drm_i915_private *i915, int err); #else static inline void -i915_capture_error_state(struct intel_gt *gt, intel_engine_mask_t engine_mask) +i915_capture_error_state(struct intel_gt *gt, intel_engine_mask_t engine_mask, u32 dump_flags) { } @@ -293,13 +305,13 @@ i915_gpu_coredump_alloc(struct drm_i915_private *i915, gfp_t gfp) } static inline struct intel_gt_coredump * -intel_gt_coredump_alloc(struct intel_gt *gt, gfp_t gfp) +intel_gt_coredump_alloc(struct intel_gt *gt, gfp_t gfp, u32 dump_flags) { return NULL; } static inline struct intel_engine_coredump * -intel_engine_coredump_alloc(struct intel_engine_cs *engine, gfp_t gfp) +intel_engine_coredump_alloc(struct intel_engine_cs *engine, gfp_t gfp, u32 dump_flags) { return NULL; } From patchwork Sat Feb 26 09:55:41 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Previn X-Patchwork-Id: 12761257 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A1EA1C433F5 for ; Sat, 26 Feb 2022 09:53:56 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 8D35D10E839; Sat, 26 Feb 2022 09:53:38 +0000 (UTC) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTPS id 5F40810E46D for ; Sat, 26 Feb 2022 09:53:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1645869216; x=1677405216; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=53QdNFmSNZMVClVDZoAS8Q4yI1C1O03oxlFvhCaOFzg=; b=fFE3bS4/Hv7kNtwBCCnYl0qAa70i7RYPSO9+CrgDOeXlpLpQNUf4GH6/ lglw2x/ItDSUNe+PhuBLFimasqc5DKcZ1z9riJ6E6Ioerg8zGXIVvYA85 39vSYrYzcfZi6ooecm63OVt0I59SH1cZU8fymFD7o6ZDNUsl8u9Hy+CnF LD8HTsdPDzZsDuLgQ75A3VgSS+mKUj6j95ReOL6u/sDheiA22EGBLDzkw XAVEYvzBJk1H+pW96N3n3IRoE/dDxMpqKE9dd6UkA9mH/aqC8xSOUxhzK hNKb1j0liClVJ7rvngbuI40eOWOZykt9co7UVDxFgsDsWGUZi83BoAqyN Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10269"; a="277288189" X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="277288189" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Feb 2022 01:53:35 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,139,1643702400"; d="scan'208";a="506953256" Received: from aalteres-desk.fm.intel.com ([10.80.57.53]) by orsmga002.jf.intel.com with ESMTP; 26 Feb 2022 01:53:35 -0800 From: Alan Previn To: intel-gfx@lists.freedesktop.org Date: Sat, 26 Feb 2022 01:55:41 -0800 Message-Id: <20220226095541.1010534-14-alan.previn.teres.alexis@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> References: <20220226095541.1010534-1-alan.previn.teres.alexis@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v7 13/13] drm/i915/guc: Print the GuC error capture output register list. X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alan Previn Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Print the GuC captured error state register list (string names and values) when gpu_coredump_state printout is invoked via the i915 debugfs for flushing the gpu error-state that was captured prior. Since GuC could have reported multiple engine register dumps in a single notification event, parse the captured data (appearing as a stream of structures) to identify each dump as a different 'engine-capture-group-output'. Finally, for each 'engine-capture-group-output' that is found, verify if the engine register dump corresponds to the engine_coredump content that was previously populated by the i915_gpu_coredump function. That function would have copied the context's vma's including the bacth buffer during the G2H-context-reset notification that occurred earlier. Perform this verification check by comparing guc_id, lrca and engine- instance obtained from the 'engine-capture-group-output' vs a copy of that same info taken during i915_gpu_coredump. If they match, then print those vma's as well (such as the batch buffers). Signed-off-by: Alan Previn Reviewed-by: Umesh Nerlige Ramappa --- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 4 +- drivers/gpu/drm/i915/gt/uc/intel_guc.h | 3 + .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 162 ++++++++++++++++++ .../gpu/drm/i915/gt/uc/intel_guc_capture.h | 2 +- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 6 +- drivers/gpu/drm/i915/i915_debugfs.c | 1 + drivers/gpu/drm/i915/i915_gpu_error.c | 16 +- drivers/gpu/drm/i915/i915_gpu_error.h | 5 + 8 files changed, 184 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index e855c801ba28..4643745e5d09 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -1629,9 +1629,7 @@ static void intel_engine_print_registers(struct intel_engine_cs *engine, drm_printf(m, "\tIPEHR: 0x%08x\n", ENGINE_READ(engine, IPEHR)); } - if (intel_engine_uses_guc(engine)) { - /* nothing to print yet */ - } else if (HAS_EXECLISTS(dev_priv)) { + if (HAS_EXECLISTS(dev_priv) && !intel_engine_uses_guc(engine)) { struct i915_request * const *port, *rq; const u32 *hws = &engine->status_page.addr[I915_HWS_CSB_BUF0_INDEX]; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index 908c6b1dd51a..08327294c1e3 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -438,6 +438,9 @@ int intel_guc_engine_failure_process_msg(struct intel_guc *guc, int intel_guc_error_capture_process_msg(struct intel_guc *guc, const u32 *msg, u32 len); +struct intel_engine_cs * +intel_guc_lookup_engine(struct intel_guc *guc, u8 guc_class, u8 instance); + void intel_guc_find_hung_context(struct intel_engine_cs *engine); int intel_guc_global_policies_update(struct intel_guc *guc); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index 621c0b4537a9..2f96bdf2b90f 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -746,6 +746,21 @@ int intel_guc_capture_output_min_size_est(struct intel_guc *guc) * intel_engine_coredump struct (if the context and * engine of the event notification matches a node * in the link list). + * + * User Sysfs / Debugfs + * -------------------- + * --> i915_gpu_coredump_copy_to_buffer-> + * L--> err_print_to_sgl --> err_print_gt + * L--> error_print_guc_captures + * L--> intel_guc_capture_print_node prints the + * register lists values of the attached node + * on the error-engine-dump being reported. + * L--> i915_reset_error_state ... -->__i915_gpu_coredump_free + * L--> ... cleanup_gt --> + * L--> intel_guc_capture_free_node returns the + * capture-output-node back to the internal + * cachelist for reuse. + * */ static int guc_capture_buf_cnt(struct __guc_capture_bufstate *buf) @@ -1346,9 +1361,156 @@ static void __guc_capture_process_output(struct intel_guc *guc) #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) +static const char * +guc_capture_reg_to_str(const struct intel_guc *guc, u32 owner, u32 type, + u32 class, u32 id, u32 offset, u32 *is_ext) +{ + const struct __guc_mmio_reg_descr_group *reglists = guc->capture.priv->reglists; + struct __guc_mmio_reg_descr_group *extlists = guc->capture.priv->extlists; + const struct __guc_mmio_reg_descr_group *match; + struct __guc_mmio_reg_descr_group *matchext; + int j; + + *is_ext = 0; + if (!reglists) + return NULL; + + match = guc_capture_get_one_list(reglists, owner, type, id); + if (!match) + return NULL; + + for (j = 0; j < match->num_regs; ++j) { + if (offset == match->list[j].reg.reg) + return match->list[j].regname; + } + if (extlists) { + matchext = guc_capture_get_one_ext_list(extlists, owner, type, id); + if (!matchext) + return NULL; + for (j = 0; j < matchext->num_regs; ++j) { + if (offset == matchext->extlist[j].reg.reg) { + *is_ext = 1; + return matchext->extlist[j].regname; + } + } + } + + return NULL; +} + +#ifdef CONFIG_DRM_I915_DEBUG_GUC +#define __out(a, ...) \ + do { \ + drm_warn((&(a)->drm), __VA_ARGS__); \ + i915_error_printf((a), __VA_ARGS__); \ + } while (0) +#else +#define __out(a, ...) \ + i915_error_printf(a, __VA_ARGS__) +#endif + +#define GCAP_PRINT_INTEL_ENG_INFO(ebuf, eng) \ + do { \ + __out(ebuf, " i915-Eng-Name: %s command stream\n", \ + (eng)->name); \ + __out(ebuf, " i915-Eng-Inst-Class: 0x%02x\n", (eng)->class); \ + __out(ebuf, " i915-Eng-Inst-Id: 0x%02x\n", (eng)->instance); \ + __out(ebuf, " i915-Eng-LogicalMask: 0x%08x\n", \ + (eng)->logical_mask); \ + } while (0) + +#define GCAP_PRINT_GUC_INST_INFO(ebuf, node) \ + do { \ + __out(ebuf, " GuC-Engine-Inst-Id: 0x%08x\n", \ + (node)->eng_inst); \ + __out(ebuf, " GuC-Context-Id: 0x%08x\n", (node)->guc_id); \ + __out(ebuf, " LRCA: 0x%08x\n", (node)->lrca); \ + } while (0) + int intel_guc_capture_print_engine_node(struct drm_i915_error_state_buf *ebuf, const struct intel_engine_coredump *ee) { + const char *grptype[GUC_STATE_CAPTURE_GROUP_TYPE_MAX] = { + "full-capture", + "partial-capture" + }; + const char *datatype[GUC_CAPTURE_LIST_TYPE_MAX] = { + "Global", + "Engine-Class", + "Engine-Instance" + }; + struct intel_guc_state_capture *cap; + struct __guc_capture_parsed_output *node; + struct drm_i915_private *i915; + struct guc_mmio_reg *regs; + struct intel_guc *guc; + struct intel_engine_cs *eng; + const char *str; + int numregs, i, j; + u32 is_ext; + + if (!ebuf || !ee) + return -EINVAL; + cap = ee->capture; + if (!cap->priv || !ee->engine) + return -ENODEV; + + guc = container_of(cap, struct intel_guc, capture); + i915 = (container_of(guc, struct intel_gt, uc.guc))->i915; + __out(ebuf, "global --- GuC Error Capture on %s command stream:\n", + ee->engine->name); + + node = ee->guc_capture_node; + if (!node) { + __out(ebuf, " No matching ee-node\n"); + return 0; + } + + __out(ebuf, "Coverage: %s\n", grptype[node->is_partial]); + + for (i = GUC_CAPTURE_LIST_TYPE_GLOBAL; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { + __out(ebuf, " RegListType: %s\n", + datatype[i % GUC_CAPTURE_LIST_TYPE_MAX]); + __out(ebuf, " Owner-Id: %d\n", node->reginfo[i].vfid); + + switch (i) { + case GUC_CAPTURE_LIST_TYPE_GLOBAL: + default: + break; + case GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS: + __out(ebuf, " GuC-Eng-Class: %d\n", node->eng_class); + __out(ebuf, " i915-Eng-Class: %d\n", + guc_class_to_engine_class(node->eng_class)); + break; + case GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE: + eng = intel_guc_lookup_engine(guc, node->eng_class, node->eng_inst); + if (eng) + GCAP_PRINT_INTEL_ENG_INFO(ebuf, eng); + else + __out(ebuf, " i915-Eng-Lookup Fail!\n"); + GCAP_PRINT_GUC_INST_INFO(ebuf, node); + break; + } + + numregs = node->reginfo[i].num_regs; + __out(ebuf, " NumRegs: %d\n", numregs); + j = 0; + while (numregs--) { + regs = node->reginfo[i].regs; + str = guc_capture_reg_to_str(guc, GUC_CAPTURE_LIST_INDEX_PF, i, + node->eng_class, 0, regs[j].offset, &is_ext); + if (!str) + __out(ebuf, " REG-0x%08x", regs[j].offset); + else + __out(ebuf, " %s", str); + if (is_ext) + __out(ebuf, "[%ld][%ld]", + FIELD_GET(GUC_REGSET_STEERING_GROUP, regs[j].flags), + FIELD_GET(GUC_REGSET_STEERING_INSTANCE, regs[j].flags)); + __out(ebuf, ": 0x%08x\n", regs[j].value); + ++j; + } + } return 0; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h index ae527c98e2f6..d544efcf0e9f 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h @@ -12,8 +12,8 @@ struct drm_i915_error_state_buf; struct file; struct guc_ads; struct guc_gt_system_info; -struct intel_context; struct intel_engine_coredump; +struct intel_context; struct intel_gt; struct intel_guc; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 5d41dc95f066..29f35f9f3c6d 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -4087,8 +4087,8 @@ int intel_guc_error_capture_process_msg(struct intel_guc *guc, return 0; } -static struct intel_engine_cs * -guc_lookup_engine(struct intel_guc *guc, u8 guc_class, u8 instance) +struct intel_engine_cs * +intel_guc_lookup_engine(struct intel_guc *guc, u8 guc_class, u8 instance) { struct intel_gt *gt = guc_to_gt(guc); u8 engine_class = guc_class_to_engine_class(guc_class); @@ -4137,7 +4137,7 @@ int intel_guc_engine_failure_process_msg(struct intel_guc *guc, instance = msg[1]; reason = msg[2]; - engine = guc_lookup_engine(guc, guc_class, instance); + engine = intel_guc_lookup_engine(guc, guc_class, instance); if (unlikely(!engine)) { drm_err(>->i915->drm, "Invalid engine %d:%d", guc_class, instance); diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 274abf267f35..71489ce52746 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -308,6 +308,7 @@ static int i915_gpu_info_open(struct inode *inode, struct file *file) gpu = NULL; with_intel_runtime_pm(&i915->runtime_pm, wakeref) gpu = i915_gpu_coredump(to_gt(i915), ALL_ENGINES, CORE_DUMP_FLAG_NONE); + if (IS_ERR(gpu)) return PTR_ERR(gpu); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 3d566bbe228d..3c7b9d0e8627 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -530,8 +530,8 @@ __find_vma(struct i915_vma_coredump *vma, const char *name) return NULL; } -static struct i915_vma_coredump * -find_batch(const struct intel_engine_coredump *ee) +struct i915_vma_coredump * +intel_gpu_error_find_batch(const struct intel_engine_coredump *ee) { return __find_vma(ee->vma, "batch"); } @@ -559,7 +559,7 @@ static void error_print_engine(struct drm_i915_error_state_buf *m, error_print_instdone(m, ee); - batch = find_batch(ee); + batch = intel_gpu_error_find_batch(ee); if (batch) { u64 start = batch->gtt_offset; u64 end = start + batch->gtt_size; @@ -610,9 +610,9 @@ void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...) va_end(args); } -static void print_error_vma(struct drm_i915_error_state_buf *m, - const struct intel_engine_cs *engine, - const struct i915_vma_coredump *vma) +void intel_gpu_error_print_vma(struct drm_i915_error_state_buf *m, + const struct intel_engine_cs *engine, + const struct i915_vma_coredump *vma) { char out[ASCII85_BUFSZ]; struct page *page; @@ -681,7 +681,7 @@ static void err_print_uc(struct drm_i915_error_state_buf *m, intel_uc_fw_dump(&error_uc->guc_fw, &p); intel_uc_fw_dump(&error_uc->huc_fw, &p); - print_error_vma(m, NULL, error_uc->guc_log); + intel_gpu_error_print_vma(m, NULL, error_uc->guc_log); } static void err_free_sgl(struct scatterlist *sgl) @@ -801,7 +801,7 @@ static void err_print_gt_engines(struct drm_i915_error_state_buf *m, error_print_context(m, " Active context: ", &ee->context); for (vma = ee->vma; vma; vma = vma->next) - print_error_vma(m, ee->engine, vma); + intel_gpu_error_print_vma(m, ee->engine, vma); } } diff --git a/drivers/gpu/drm/i915/i915_gpu_error.h b/drivers/gpu/drm/i915/i915_gpu_error.h index 64b999d8ac27..9554ce7a71ef 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.h +++ b/drivers/gpu/drm/i915/i915_gpu_error.h @@ -237,6 +237,11 @@ static inline u32 i915_reset_engine_count(struct i915_gpu_error *error, __printf(2, 3) void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...); +void intel_gpu_error_print_vma(struct drm_i915_error_state_buf *m, + const struct intel_engine_cs *engine, + const struct i915_vma_coredump *vma); +struct i915_vma_coredump * +intel_gpu_error_find_batch(const struct intel_engine_coredump *ee); struct i915_gpu_coredump *i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask, u32 dump_flags);