147 lines · c
1// SPDX-License-Identifier: MIT2/*3 * Copyright © 2024 Intel Corporation4 */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`_ key18 *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_case62 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 KLVs71 * @num_dwords: number of dwords (u32) available in the buffer72 * @p: the &drm_printer73 *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 KLVs125 * @num_dwords: number of dwords (u32) in the buffer126 *127 * Return: number of recognized KLVs or128 * 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}147