mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 10:31:33 -04:00
drm/xe/guc: Handle GuC local uncorrectable error notifications
Add support for the GuC uncorrectable local error G2H notification and opt in to the feature when the submission ABI exposes it. When the notification targets a known exec queue, treat it like an engine reset request and route it through the existing timeout cleanup path. This keeps the queue teardown, pending job cancellation and error capture in one place instead of open-coding a parallel recovery flow. Signed-off-by: Zhanjun Dong <zhanjun.dong@intel.com> Reviewed-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com> Link: https://patch.msgid.link/20260706234353.3874355-1-zhanjun.dong@intel.com
This commit is contained in:
committed by
Daniele Ceraolo Spurio
parent
d72d2706b2
commit
4e57574fa3
@@ -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,
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user