Commit 8bfc4963 authored by Zhanjun Dong's avatar Zhanjun Dong Committed by Matt Roper
Browse files

drm/xe/guc: Extract GuC error capture lists



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 devcoredump, duplicate global and engine-class register
lists for each engine-instance register dump if we find
dependent-engine resets in a engine-capture-group.

To avoid dynamically allocate the output nodes during gt reset,
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: default avatarZhanjun Dong <zhanjun.dong@intel.com>
Reviewed-by: default avatarAlan Previn <alan.previn.teres.alexis@intel.com>
Signed-off-by: default avatarMatt Roper <matthew.d.roper@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241004193428.3311145-5-zhanjun.dong@intel.com
parent 84d15f42
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -176,6 +176,14 @@ enum xe_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 xe_guc_state_capture_event_status {
	XE_GUC_STATE_CAPTURE_EVENT_STATUS_SUCCESS = 0x0,
	XE_GUC_STATE_CAPTURE_EVENT_STATUS_NOSPACE = 0x1,
};

#define XE_GUC_STATE_CAPTURE_EVENT_STATUS_MASK      0x000000FF
#define XE_GUC_ACTION_STATE_CAPTURE_NOTIFICATION_DATA_LEN 1

#define XE_GUC_TLB_INVAL_TYPE_SHIFT 0
#define XE_GUC_TLB_INVAL_MODE_SHIFT 8
/* Flush PPC or SMRO caches along with TLB invalidation request */
+55 −0
Original line number Diff line number Diff line
@@ -17,4 +17,59 @@ enum guc_log_buffer_type {

#define GUC_LOG_BUFFER_TYPE_MAX		3

/**
 * struct guc_log_buffer_state - GuC log buffer state
 *
 * Below state structure is used for coordination of retrieval of GuC firmware
 * logs. Separate state is maintained for each log buffer type.
 * read_ptr points to the location where Xe read last in log buffer and
 * is read only for GuC firmware. write_ptr is incremented by GuC with number
 * of bytes written for each log entry and is read only for Xe.
 * When any type of log buffer becomes half full, GuC sends a flush interrupt.
 * GuC firmware expects that while it is writing to 2nd half of the buffer,
 * first half would get consumed by Host and then get a flush completed
 * acknowledgment from Host, so that it does not end up doing any overwrite
 * causing loss of logs. So when buffer gets half filled & Xe has requested
 * for interrupt, GuC will set flush_to_file field, set the sampled_write_ptr
 * to the value of write_ptr and raise the interrupt.
 * On receiving the interrupt Xe should read the buffer, clear flush_to_file
 * field and also update read_ptr with the value of sample_write_ptr, before
 * sending an acknowledgment to GuC. marker & version fields are for internal
 * usage of GuC and opaque to Xe. buffer_full_cnt field is incremented every
 * time GuC detects the log buffer overflow.
 */
struct guc_log_buffer_state {
	/** @marker: buffer state start marker */
	u32 marker[2];
	/** @read_ptr: the last byte offset that was read by KMD previously */
	u32 read_ptr;
	/**
	 * @write_ptr: the next byte offset location that will be written by
	 * GuC
	 */
	u32 write_ptr;
	/** @size: Log buffer size */
	u32 size;
	/**
	 * @sampled_write_ptr: Log buffer write pointer
	 * This is written by GuC to the byte offset of the next free entry in
	 * the buffer on log buffer half full or state capture notification
	 */
	u32 sampled_write_ptr;
	/**
	 * @wrap_offset: wraparound offset
	 * This is the byte offset of location 1 byte after last valid guc log
	 * event entry written by Guc firmware before there was a wraparound.
	 * This field is updated by guc firmware and should be used by Host
	 * when copying buffer contents to file.
	 */
	u32 wrap_offset;
	/** @flags: Flush to file flag and buffer full count */
	u32 flags;
#define	GUC_LOG_BUFFER_STATE_FLUSH_TO_FILE	GENMASK(0, 0)
#define	GUC_LOG_BUFFER_STATE_BUFFER_FULL_CNT	GENMASK(4, 1)
	/** @version: The Guc-Log-Entry format version */
	u32 version;
} __packed;

#endif
+722 −3

File changed.

Preview size limit exceeded, changes collapsed.

+1 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ xe_engine_class_to_guc_capture_class(enum xe_engine_class class)
	return xe_guc_class_to_capture_class(xe_engine_class_to_guc_class(class));
}

void xe_guc_capture_process(struct xe_guc *guc);
int xe_guc_capture_getlist(struct xe_guc *guc, u32 owner, u32 type,
			   enum guc_capture_list_class_type capture_class, void **outptr);
int xe_guc_capture_getlistsize(struct xe_guc *guc, u32 owner, u32 type,
+2 −0
Original line number Diff line number Diff line
@@ -1254,6 +1254,8 @@ static int process_g2h_msg(struct xe_guc_ct *ct, u32 *msg, u32 len)
		/* Selftest only at the moment */
		break;
	case XE_GUC_ACTION_STATE_CAPTURE_NOTIFICATION:
		ret = xe_guc_error_capture_handler(guc, payload, adj_len);
		break;
	case XE_GUC_ACTION_NOTIFY_FLUSH_LOG_BUFFER_TO_FILE:
		/* FIXME: Handle this */
		break;
Loading