[PATCH v4 5/6] drm/xe/guc: Add GuC log event buffer output in LFD format
Michal Wajdeczko
michal.wajdeczko at intel.com
Sat Jun 28 14:46:28 UTC 2025
On 23.04.2025 23:58, Zhanjun Dong wrote:
> Add GuC log event buffer output in LFD format.
>
> Signed-off-by: Zhanjun Dong <zhanjun.dong at intel.com>
> ---
> drivers/gpu/drm/xe/xe_guc_log.c | 87 +++++++++++++++++++++++++++++++--
> 1 file changed, 84 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_guc_log.c b/drivers/gpu/drm/xe/xe_guc_log.c
> index 3fdf3823e2d0..5aa9b9dbe3f3 100644
> --- a/drivers/gpu/drm/xe/xe_guc_log.c
> +++ b/drivers/gpu/drm/xe/xe_guc_log.c
> @@ -33,6 +33,7 @@ struct guc_log_buffer_entry_list {
> };
>
> struct guc_log_init_config_save {
> + u32 version;
> /*
> * Array of init config KLVs.
> * Range from GUC_LOG_LIC_TYPE_FIRST to GUC_LOG_LIC_TYPE_LAST
> @@ -336,7 +337,6 @@ static int xe_guc_log_add_os_id(void *buf, int buf_size, u32 id)
> return -ENOMEM;
>
> strscpy(os_id->build_version, version, info_len);
> -
unrelated change
> return xe_guc_log_add_typed_payload(buf, buf_size, GUC_LFD_TYPE_OS_ID,
> info_len + sizeof(*os_id), os_id);
> }
> @@ -366,6 +366,7 @@ static void xe_guc_log_load_lic(void *guc_log, struct guc_log_init_config_save *
> int i = 0;
>
> memset(config, 0, sizeof(struct guc_log_init_config_save));
> + config->version = p->version;
> while (p) {
> for (i = 0; i < GUC_LOG_BUFFER_STATE_HEADER_ENTRY_COUNT; i++) {
> if (p->marker[0] == entry_markers[i].key[0] &&
> @@ -380,8 +381,7 @@ static void xe_guc_log_load_lic(void *guc_log, struct guc_log_init_config_save *
> p++;
> } else {
> /* Load log init config */
> - xe_guc_log_loop_log_init((void *)p,
> - config);
> + xe_guc_log_loop_log_init((void *)p, config);
unrelated change
>
> /* Init config is the last */
> return;
> @@ -417,6 +417,86 @@ xe_guc_log_output_lfd_init(char *buf, struct xe_guc_log_snapshot *snapshot,
> return index;
> }
>
> +static void
> +xe_guc_log_print_over_chunks(struct drm_printer *p, struct xe_guc_log_snapshot *snapshot,
> + u32 from, u32 to)
guc_log_snapshot_print_chunks(
struct xe_guc_log_snapshot *snapshot,
u32 from, u32 to,
struct drm_printer *p)
> +{
> + int chunk_from = from % GUC_LOG_CHUNK_SIZE;
> + int chunk_id = from / GUC_LOG_CHUNK_SIZE;
> + int to_chunk_id = to / GUC_LOG_CHUNK_SIZE;
> + int chunk_to = to % GUC_LOG_CHUNK_SIZE;
> + int pos = from;
> +
> + do {
> + size_t size = (to_chunk_id > chunk_id ? GUC_LOG_CHUNK_SIZE : chunk_to) - chunk_from;
> +
> + xe_print_blob_ascii85(p, NULL, 0, snapshot->copy[chunk_id], chunk_from, size);
> + pos += size;
> + chunk_id++;
> + chunk_from = 0;
> + } while (pos < to);
> +}
> +
> +static void
> +xe_guc_log_lfd_print_from_chunks(struct drm_printer *p, struct xe_guc_log_snapshot *snapshot,
> + struct guc_log_buffer_entry_list *entry)
I'm not sure if having this function helps,
IMO better to keep this code at the caller, where you are already
accessing the data from the 'entry' in "Calculate data length"
> +{
> + /* Output data from guc log chunks directly */
> + if (entry->rd_ptr < entry->wr_ptr) {
> + xe_guc_log_print_over_chunks(p, snapshot,
> + entry->offset + entry->rd_ptr,
> + entry->offset + entry->wr_ptr);
> + } else {
> + /* print from rd to buf end 1st */
> + xe_guc_log_print_over_chunks(p, snapshot,
> + entry->offset + entry->rd_ptr,
> + entry->offset + entry->buf_size);
> +
> + /* print from buf start to wr */
> + xe_guc_log_print_over_chunks(p, snapshot, entry->offset,
> + entry->offset + entry->wr_ptr);
> + }
> +}
> +
> +static inline int
> +xe_guc_log_add_log_event(struct drm_printer *p, char *buf, struct xe_guc_log_snapshot *snapshot,
> + struct guc_log_init_config_save *config)
guc_log_snapshot_print_events(
struct xe_guc_log_snapshot *snapshot,
const struct guc_log_init_config_save *config,
char *buf,
struct drm_printer *p)
but do we really need this 'buf' ?
those lfd headers are quite small and could be defined on stack
> +{
> + struct guc_logfile_lfd_data *lfd = (void *)buf;
> + struct guc_lfd_data_log_events_buf *events_buf;
> + struct guc_log_buffer_entry_list *entry;
> + u32 data_len;
> + int index;
> +
> + memset(buf, 0, GUC_LOG_CHUNK_SIZE);
> + entry = &config->entry[GUC_LOG_BUFFER_STATE_HEADER_ENTRY_LOG];
> +
> + /* Skip empty log */
> + if (entry->rd_ptr == entry->wr_ptr)
> + return 0;
> +
> + index = xe_guc_log_add_lfd_header(buf, GUC_LOG_CHUNK_SIZE);
> + lfd->dw0 |= FIELD_PREP(GUC_LOGFILE_LFD_DESC_TYPE, GUC_LFD_TYPE_LOG_EVENTS_BUFFER);
> + events_buf = (void *)&lfd->data;
> + events_buf->log_events_format_version = config->version;
> +
> + /* Adjust to log_format_buf */
> + data_len = offsetof(struct guc_lfd_data_log_events_buf, log_format_buf);
> + index += data_len;
> +
> + /* Calculate data length */
> + data_len += (entry->wr_ptr + entry->buf_size - entry->rd_ptr) % entry->buf_size;
> + /* make length u32 aligned */
> + lfd->desc_dw_size = DIV_ROUND_UP(data_len, sizeof(u32));
> +
> + /* Output GUC_LFD_TYPE_LOG_EVENTS_BUFFER header */
> + xe_print_blob_ascii85(p, NULL, 0, buf, 0, (size_t)index);
> +
> + xe_guc_log_lfd_print_from_chunks(p, snapshot, entry);
> + /* log event buffer content did not use buf, exclude from size count */
> + return index;
> +}
> +
> static void
> xe_guc_log_snapshot_print_lfd(struct xe_guc_log_snapshot *snapshot, struct drm_printer *p,
> struct xe_guc_log *log)
> @@ -441,6 +521,7 @@ xe_guc_log_snapshot_print_lfd(struct xe_guc_log_snapshot *snapshot, struct drm_p
> goto lfd_out;
>
> xe_print_blob_ascii85(p, "[LOG].data", 0, lfd_buf, 0, (size_t)index);
> + index = xe_guc_log_add_log_event(p, lfd_buf, snapshot, &config);
>
> lfd_out:
> drm_printf(p, "\n");
More information about the Intel-xe
mailing list