Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: MIT
  2/*
  3 * Copyright © 2024 Intel Corporation
  4 */
  5
  6#include <linux/bitfield.h>
  7#include <drm/drm_print.h>
  8
  9#include "abi/guc_klvs_abi.h"
 10#include "xe_guc_klv_helpers.h"
 11#include "xe_guc_klv_thresholds_set.h"
 12
 13#define make_u64(hi, lo) ((u64)((u64)(u32)(hi) << 32 | (u32)(lo)))
 14
 15/**
 16 * xe_guc_klv_key_to_string - Convert KLV key into friendly name.
 17 * @key: the `GuC KLV`_ key
 18 *
 19 * Return: name of the KLV key.
 20 */
 21const char *xe_guc_klv_key_to_string(u16 key)
 22{
 23	switch (key) {
 24	/* VGT POLICY keys */
 25	case GUC_KLV_VGT_POLICY_SCHED_IF_IDLE_KEY:
 26		return "sched_if_idle";
 27	case GUC_KLV_VGT_POLICY_ADVERSE_SAMPLE_PERIOD_KEY:
 28		return "sample_period";
 29	case GUC_KLV_VGT_POLICY_RESET_AFTER_VF_SWITCH_KEY:
 30		return "reset_engine";
 31	/* VF CFG keys */
 32	case GUC_KLV_VF_CFG_GGTT_START_KEY:
 33		return "ggtt_start";
 34	case GUC_KLV_VF_CFG_GGTT_SIZE_KEY:
 35		return "ggtt_size";
 36	case GUC_KLV_VF_CFG_LMEM_SIZE_KEY:
 37		return "lmem_size";
 38	case GUC_KLV_VF_CFG_NUM_CONTEXTS_KEY:
 39		return "num_contexts";
 40	case GUC_KLV_VF_CFG_TILE_MASK_KEY:
 41		return "tile_mask";
 42	case GUC_KLV_VF_CFG_NUM_DOORBELLS_KEY:
 43		return "num_doorbells";
 44	case GUC_KLV_VF_CFG_EXEC_QUANTUM_KEY:
 45		return "exec_quantum";
 46	case GUC_KLV_VF_CFG_PREEMPT_TIMEOUT_KEY:
 47		return "preempt_timeout";
 48	case GUC_KLV_VF_CFG_BEGIN_DOORBELL_ID_KEY:
 49		return "begin_db_id";
 50	case GUC_KLV_VF_CFG_BEGIN_CONTEXT_ID_KEY:
 51		return "begin_ctx_id";
 52
 53	/* VF CFG threshold keys */
 54#define define_threshold_key_to_string_case(TAG, NAME, ...)	\
 55								\
 56	case MAKE_GUC_KLV_VF_CFG_THRESHOLD_KEY(TAG):		\
 57		return #NAME;
 58
 59	/* private: auto-generated case statements */
 60	MAKE_XE_GUC_KLV_THRESHOLDS_SET(define_threshold_key_to_string_case)
 61#undef define_threshold_key_to_string_case
 62
 63	default:
 64		return "(unknown)";
 65	}
 66}
 67
 68/**
 69 * xe_guc_klv_print - Print content of the buffer with `GuC KLV`_.
 70 * @klvs: the buffer with KLVs
 71 * @num_dwords: number of dwords (u32) available in the buffer
 72 * @p: the &drm_printer
 73 *
 74 * The buffer may contain more than one KLV.
 75 */
 76void xe_guc_klv_print(const u32 *klvs, u32 num_dwords, struct drm_printer *p)
 77{
 78	while (num_dwords >= GUC_KLV_LEN_MIN) {
 79		u32 key = FIELD_GET(GUC_KLV_0_KEY, klvs[0]);
 80		u32 len = FIELD_GET(GUC_KLV_0_LEN, klvs[0]);
 81
 82		klvs += GUC_KLV_LEN_MIN;
 83		num_dwords -= GUC_KLV_LEN_MIN;
 84
 85		if (num_dwords < len) {
 86			drm_printf(p, "{ key %#06x : truncated %zu of %zu bytes %*ph } # %s\n",
 87				   key, num_dwords * sizeof(u32), len * sizeof(u32),
 88				   (int)(num_dwords * sizeof(u32)), klvs,
 89				   xe_guc_klv_key_to_string(key));
 90			return;
 91		}
 92
 93		switch (len) {
 94		case 0:
 95			drm_printf(p, "{ key %#06x : no value } # %s\n",
 96				   key, xe_guc_klv_key_to_string(key));
 97			break;
 98		case 1:
 99			drm_printf(p, "{ key %#06x : 32b value %u } # %s\n",
100				   key, klvs[0], xe_guc_klv_key_to_string(key));
101			break;
102		case 2:
103			drm_printf(p, "{ key %#06x : 64b value %#llx } # %s\n",
104				   key, make_u64(klvs[1], klvs[0]),
105				   xe_guc_klv_key_to_string(key));
106			break;
107		default:
108			drm_printf(p, "{ key %#06x : %zu bytes %*ph } # %s\n",
109				   key, len * sizeof(u32), (int)(len * sizeof(u32)),
110				   klvs, xe_guc_klv_key_to_string(key));
111			break;
112		}
113
114		klvs += len;
115		num_dwords -= len;
116	}
117
118	/* we don't expect any leftovers, fix if KLV header is ever changed */
119	BUILD_BUG_ON(GUC_KLV_LEN_MIN > 1);
120}
121
122/**
123 * xe_guc_klv_count - Count KLVs present in the buffer.
124 * @klvs: the buffer with KLVs
125 * @num_dwords: number of dwords (u32) in the buffer
126 *
127 * Return: number of recognized KLVs or
128 *         a negative error code if KLV buffer is truncated.
129 */
130int xe_guc_klv_count(const u32 *klvs, u32 num_dwords)
131{
132	int num_klvs = 0;
133
134	while (num_dwords >= GUC_KLV_LEN_MIN) {
135		u32 len = FIELD_GET(GUC_KLV_0_LEN, klvs[0]);
136
137		if (num_dwords < len + GUC_KLV_LEN_MIN)
138			break;
139
140		klvs += GUC_KLV_LEN_MIN + len;
141		num_dwords -= GUC_KLV_LEN_MIN + len;
142		num_klvs++;
143	}
144
145	return num_dwords ? -ENODATA : num_klvs;
146}