diff --git a/drivers/gpu/drm/xe/abi/guc_actions_abi.h b/drivers/gpu/drm/xe/abi/guc_actions_abi.h index 83a6e7794982..f5c9b37038d4 100644 --- a/drivers/gpu/drm/xe/abi/guc_actions_abi.h +++ b/drivers/gpu/drm/xe/abi/guc_actions_abi.h @@ -152,6 +152,7 @@ enum xe_guc_action { XE_GUC_ACTION_REPORT_PAGE_FAULT_REQ_DESC = 0x6002, XE_GUC_ACTION_PAGE_FAULT_RES_DESC = 0x6003, XE_GUC_ACTION_ACCESS_COUNTER_NOTIFY = 0x6004, + XE_GUC_ACTION_NOTIFY_UNCORRECTABLE_LOCAL_ERROR = 0x6005, XE_GUC_ACTION_TLB_INVALIDATION = 0x7000, XE_GUC_ACTION_TLB_INVALIDATION_DONE = 0x7001, XE_GUC_ACTION_TLB_INVALIDATION_ALL = 0x7002, diff --git a/drivers/gpu/drm/xe/abi/guc_klvs_abi.h b/drivers/gpu/drm/xe/abi/guc_klvs_abi.h index 644f5a4226d7..5c428f02a642 100644 --- a/drivers/gpu/drm/xe/abi/guc_klvs_abi.h +++ b/drivers/gpu/drm/xe/abi/guc_klvs_abi.h @@ -154,6 +154,11 @@ enum { * (instead of waiting the full timeslice duration). The bit is instead set * to one if a single context is queued on the engine, to avoid it being * switched out if there isn't another context that can run in its place. + * + * _`GUC_KLV_OPT_IN_FEATURE_UNCORRECTABLE_LOCAL_ERROR_NOTIFICATION` : 0x4004 + * This flag will enable notification from GuC to KMD via G2H message + * GUC_ACTION_GUC2HOST_NOTIFY_UNCORRECTABLE_LOCAL_ERROR upon receiving the + * same interrupt from the CS. */ #define GUC_KLV_OPT_IN_FEATURE_EXT_CAT_ERR_TYPE_KEY 0x4001 @@ -162,6 +167,9 @@ enum { #define GUC_KLV_OPT_IN_FEATURE_DYNAMIC_INHIBIT_CONTEXT_SWITCH_KEY 0x4003 #define GUC_KLV_OPT_IN_FEATURE_DYNAMIC_INHIBIT_CONTEXT_SWITCH_LEN 0u +#define GUC_KLV_OPT_IN_FEATURE_UNCORRECTABLE_LOCAL_ERROR_NOTIFICATION_KEY 0x4004 +#define GUC_KLV_OPT_IN_FEATURE_UNCORRECTABLE_LOCAL_ERROR_NOTIFICATION_LEN 0u + /** * DOC: GuC Scheduling Policies KLVs * diff --git a/drivers/gpu/drm/xe/xe_gt_types.h b/drivers/gpu/drm/xe/xe_gt_types.h index e5588c88800a..0d234160ee3a 100644 --- a/drivers/gpu/drm/xe/xe_gt_types.h +++ b/drivers/gpu/drm/xe/xe_gt_types.h @@ -144,6 +144,11 @@ struct xe_gt { u8 id; /** @info.has_indirect_ring_state: GT has indirect ring state support */ u8 has_indirect_ring_state:1; + /** + * @info.has_uncorrectable_error_reporting: GT has uncorrectable + * error reporting support + */ + u8 has_uncorrectable_error_reporting:1; /** * @info.has_xe2_blt_instructions: GT supports Xe2-style MEM_SET * and MEM_COPY blitter functionality. Note that despite the diff --git a/drivers/gpu/drm/xe/xe_guc.c b/drivers/gpu/drm/xe/xe_guc.c index 4023700ff2a9..543f3992bccd 100644 --- a/drivers/gpu/drm/xe/xe_guc.c +++ b/drivers/gpu/drm/xe/xe_guc.c @@ -12,6 +12,7 @@ #include "abi/guc_actions_abi.h" #include "abi/guc_errors_abi.h" +#include "abi/guc_klvs_abi.h" #include "regs/xe_gt_regs.h" #include "regs/xe_gtt_defs.h" #include "regs/xe_guc_regs.h" @@ -641,6 +642,15 @@ int xe_guc_opt_in_features_enable(struct xe_guc *guc) if (GUC_SUBMIT_VER(guc) >= MAKE_GUC_VER(1, 7, 0)) klvs[count++] = PREP_GUC_KLV_TAG(OPT_IN_FEATURE_EXT_CAT_ERR_TYPE); + /* + * The uncorrectable local error notification opt-in was added in + * GuC v70.38.0, which maps to compatibility version v1.18.0. + */ + if (GUC_SUBMIT_VER(guc) >= MAKE_GUC_VER(1, 18, 0) && + guc_to_gt(guc)->info.has_uncorrectable_error_reporting) + klvs[count++] = + PREP_GUC_KLV_TAG(OPT_IN_FEATURE_UNCORRECTABLE_LOCAL_ERROR_NOTIFICATION); + if (supports_dynamic_ics(guc)) klvs[count++] = PREP_GUC_KLV_TAG(OPT_IN_FEATURE_DYNAMIC_INHIBIT_CONTEXT_SWITCH); diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c index 8ca7d37c79b6..fe70c0fd85c5 100644 --- a/drivers/gpu/drm/xe/xe_guc_ct.c +++ b/drivers/gpu/drm/xe/xe_guc_ct.c @@ -1696,6 +1696,9 @@ static int process_g2h_msg(struct xe_guc_ct *ct, u32 *msg, u32 len) ret = xe_guc_exec_queue_memory_cat_error_handler(guc, payload, adj_len); break; + case XE_GUC_ACTION_NOTIFY_UNCORRECTABLE_LOCAL_ERROR: + ret = xe_guc_uncorrectable_error_handler(guc, payload, adj_len); + break; case XE_GUC_ACTION_REPORT_PAGE_FAULT_REQ_DESC: ret = xe_guc_pagefault_handler(guc, payload, adj_len); break; diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c index 12416bfa3255..e5fcb1f21115 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit.c +++ b/drivers/gpu/drm/xe/xe_guc_submit.c @@ -3022,6 +3022,38 @@ int xe_guc_exec_queue_memory_cat_error_handler(struct xe_guc *guc, u32 *msg, return 0; } +int xe_guc_uncorrectable_error_handler(struct xe_guc *guc, u32 *msg, u32 len) +{ + struct xe_gt *gt = guc_to_gt(guc); + struct xe_exec_queue *q; + u32 guc_id; + + if (unlikely(!len || len > 1)) + return -EPROTO; + + guc_id = msg[0]; + + if (guc_id == GUC_ID_UNKNOWN) { + xe_gt_err(gt, "GuC: Uncorrectable local error with unknown GuC id\n"); + return 0; + } + + q = g2h_exec_queue_lookup(guc, guc_id); + if (unlikely(!q)) + return -EPROTO; + + xe_gt_err(gt, + "GuC: Uncorrectable local error! guc_id=%d class=%s, logical_mask=0x%x", + guc_id, xe_hw_engine_class_to_str(q->class), q->logical_mask); + + trace_xe_guc_uncorrectable_error(q); + + /* Treat the same as engine reset */ + xe_guc_exec_queue_reset_trigger_cleanup(q); + + return 0; +} + int xe_guc_exec_queue_reset_failure_handler(struct xe_guc *guc, u32 *msg, u32 len) { struct xe_gt *gt = guc_to_gt(guc); diff --git a/drivers/gpu/drm/xe/xe_guc_submit.h b/drivers/gpu/drm/xe/xe_guc_submit.h index b3839a90c142..ccade320dc69 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit.h +++ b/drivers/gpu/drm/xe/xe_guc_submit.h @@ -34,6 +34,7 @@ int xe_guc_deregister_done_handler(struct xe_guc *guc, u32 *msg, u32 len); int xe_guc_exec_queue_reset_handler(struct xe_guc *guc, u32 *msg, u32 len); int xe_guc_exec_queue_memory_cat_error_handler(struct xe_guc *guc, u32 *msg, u32 len); +int xe_guc_uncorrectable_error_handler(struct xe_guc *guc, u32 *msg, u32 len); int xe_guc_exec_queue_reset_failure_handler(struct xe_guc *guc, u32 *msg, u32 len); int xe_guc_error_capture_handler(struct xe_guc *guc, u32 *msg, u32 len); int xe_guc_exec_queue_cgp_sync_done_handler(struct xe_guc *guc, u32 *msg, u32 len); diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c index 91af603e9431..11a69dffdce7 100644 --- a/drivers/gpu/drm/xe/xe_pci.c +++ b/drivers/gpu/drm/xe/xe_pci.c @@ -120,6 +120,7 @@ static const struct xe_graphics_desc graphics_xe2 = { static const struct xe_graphics_desc graphics_xe3p_lpg = { XE2_GFX_FEATURES, .has_indirect_ring_state = 1, + .has_uncorrectable_error_reporting = 1, .multi_queue_engine_class_mask = BIT(XE_ENGINE_CLASS_COPY) | BIT(XE_ENGINE_CLASS_COMPUTE), .num_geometry_xecore_fuse_regs = 3, .num_compute_xecore_fuse_regs = 3, @@ -129,6 +130,7 @@ static const struct xe_graphics_desc graphics_xe3p_xpc = { XE2_GFX_FEATURES, .has_access_counter = 0, .has_indirect_ring_state = 1, + .has_uncorrectable_error_reporting = 1, .hw_engine_mask = GENMASK(XE_HW_ENGINE_BCS8, XE_HW_ENGINE_BCS1) | GENMASK(XE_HW_ENGINE_CCS3, XE_HW_ENGINE_CCS0), @@ -151,6 +153,14 @@ static const struct xe_media_desc media_xelpmp = { BIT(XE_HW_ENGINE_GSCCS0) }; +static const struct xe_media_desc media_xe3p_hpm = { + .has_uncorrectable_error_reporting = 1, + .hw_engine_mask = + GENMASK(XE_HW_ENGINE_VCS7, XE_HW_ENGINE_VCS0) | + GENMASK(XE_HW_ENGINE_VECS3, XE_HW_ENGINE_VECS0) | + BIT(XE_HW_ENGINE_GSCCS0) +}; + /* Pre-GMDID Graphics IPs */ static const struct xe_ip graphics_ip_xelp = { 1200, "Xe_LP", &graphics_xelp }; static const struct xe_ip graphics_ip_xelpp = { 1210, "Xe_LP+", &graphics_xelp }; @@ -186,7 +196,7 @@ static const struct xe_ip media_ips[] = { { 3000, "Xe3_LPM", &media_xelpmp }, { 3002, "Xe3_LPM", &media_xelpmp }, { 3500, "Xe3p_LPM", &media_xelpmp }, - { 3503, "Xe3p_HPM", &media_xelpmp }, + { 3503, "Xe3p_HPM", &media_xe3p_hpm }, }; #define MULTI_LRC_MASK \ @@ -875,6 +885,8 @@ static struct xe_gt *alloc_primary_gt(struct xe_tile *tile, gt->info.type = XE_GT_TYPE_MAIN; gt->info.id = tile->id * xe->info.max_gt_per_tile; gt->info.has_indirect_ring_state = graphics_desc->has_indirect_ring_state; + gt->info.has_uncorrectable_error_reporting = + graphics_desc->has_uncorrectable_error_reporting; gt->info.multi_queue_engine_class_mask = graphics_desc->multi_queue_engine_class_mask; gt->info.engine_mask = graphics_desc->hw_engine_mask; gt->info.num_geometry_xecore_fuse_regs = graphics_desc->num_geometry_xecore_fuse_regs; @@ -920,6 +932,7 @@ static struct xe_gt *alloc_media_gt(struct xe_tile *tile, gt->info.type = XE_GT_TYPE_MEDIA; gt->info.id = tile->id * xe->info.max_gt_per_tile + 1; gt->info.has_indirect_ring_state = media_desc->has_indirect_ring_state; + gt->info.has_uncorrectable_error_reporting = media_desc->has_uncorrectable_error_reporting; gt->info.engine_mask = media_desc->hw_engine_mask; return gt; diff --git a/drivers/gpu/drm/xe/xe_pci_types.h b/drivers/gpu/drm/xe/xe_pci_types.h index 24d4a3d00517..fed509ff601e 100644 --- a/drivers/gpu/drm/xe/xe_pci_types.h +++ b/drivers/gpu/drm/xe/xe_pci_types.h @@ -79,12 +79,14 @@ struct xe_graphics_desc { u8 has_ctx_tlb_inval:1; u8 has_usm:1; u8 has_64bit_timestamp:1; + u8 has_uncorrectable_error_reporting:1; }; struct xe_media_desc { u64 hw_engine_mask; /* hardware engines provided by media IP */ u8 has_indirect_ring_state:1; + u8 has_uncorrectable_error_reporting:1; }; struct xe_ip { diff --git a/drivers/gpu/drm/xe/xe_trace.h b/drivers/gpu/drm/xe/xe_trace.h index 750fa32c13b2..2fe8f89a1e34 100644 --- a/drivers/gpu/drm/xe/xe_trace.h +++ b/drivers/gpu/drm/xe/xe_trace.h @@ -213,6 +213,11 @@ DEFINE_EVENT(xe_exec_queue, xe_exec_queue_memory_cat_error, TP_ARGS(q) ); +DEFINE_EVENT(xe_exec_queue, xe_guc_uncorrectable_error, + TP_PROTO(struct xe_exec_queue *q), + TP_ARGS(q) +); + DEFINE_EVENT(xe_exec_queue, xe_exec_queue_cgp_context_error, TP_PROTO(struct xe_exec_queue *q), TP_ARGS(q)