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 */ 21 const 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 case GUC_KLV_VF_CFG_SCHED_PRIORITY_KEY: 53 return "sched_priority"; 54 55 /* VF CFG threshold keys */ 56 #define define_threshold_key_to_string_case(TAG, NAME, ...) \ 57 \ 58 case MAKE_GUC_KLV_VF_CFG_THRESHOLD_KEY(TAG): \ 59 return #NAME; 60 61 /* private: auto-generated case statements */ 62 MAKE_XE_GUC_KLV_THRESHOLDS_SET(define_threshold_key_to_string_case) 63 #undef define_threshold_key_to_string_case 64 65 default: 66 return "(unknown)"; 67 } 68 } 69 70 /** 71 * xe_guc_klv_print - Print content of the buffer with `GuC KLV`_. 72 * @klvs: the buffer with KLVs 73 * @num_dwords: number of dwords (u32) available in the buffer 74 * @p: the &drm_printer 75 * 76 * The buffer may contain more than one KLV. 77 */ 78 void xe_guc_klv_print(const u32 *klvs, u32 num_dwords, struct drm_printer *p) 79 { 80 while (num_dwords >= GUC_KLV_LEN_MIN) { 81 u32 key = FIELD_GET(GUC_KLV_0_KEY, klvs[0]); 82 u32 len = FIELD_GET(GUC_KLV_0_LEN, klvs[0]); 83 84 klvs += GUC_KLV_LEN_MIN; 85 num_dwords -= GUC_KLV_LEN_MIN; 86 87 if (num_dwords < len) { 88 drm_printf(p, "{ key %#06x : truncated %zu of %zu bytes %*ph } # %s\n", 89 key, num_dwords * sizeof(u32), len * sizeof(u32), 90 (int)(num_dwords * sizeof(u32)), klvs, 91 xe_guc_klv_key_to_string(key)); 92 return; 93 } 94 95 switch (len) { 96 case 0: 97 drm_printf(p, "{ key %#06x : no value } # %s\n", 98 key, xe_guc_klv_key_to_string(key)); 99 break; 100 case 1: 101 drm_printf(p, "{ key %#06x : 32b value %u } # %s\n", 102 key, klvs[0], xe_guc_klv_key_to_string(key)); 103 break; 104 case 2: 105 drm_printf(p, "{ key %#06x : 64b value %#llx } # %s\n", 106 key, make_u64(klvs[1], klvs[0]), 107 xe_guc_klv_key_to_string(key)); 108 break; 109 default: 110 drm_printf(p, "{ key %#06x : %zu bytes %*ph } # %s\n", 111 key, len * sizeof(u32), (int)(len * sizeof(u32)), 112 klvs, xe_guc_klv_key_to_string(key)); 113 break; 114 } 115 116 klvs += len; 117 num_dwords -= len; 118 } 119 120 /* we don't expect any leftovers, fix if KLV header is ever changed */ 121 BUILD_BUG_ON(GUC_KLV_LEN_MIN > 1); 122 } 123 124 /** 125 * xe_guc_klv_count - Count KLVs present in the buffer. 126 * @klvs: the buffer with KLVs 127 * @num_dwords: number of dwords (u32) in the buffer 128 * 129 * Return: number of recognized KLVs or 130 * a negative error code if KLV buffer is truncated. 131 */ 132 int xe_guc_klv_count(const u32 *klvs, u32 num_dwords) 133 { 134 int num_klvs = 0; 135 136 while (num_dwords >= GUC_KLV_LEN_MIN) { 137 u32 len = FIELD_GET(GUC_KLV_0_LEN, klvs[0]); 138 139 if (num_dwords < len + GUC_KLV_LEN_MIN) 140 break; 141 142 klvs += GUC_KLV_LEN_MIN + len; 143 num_dwords -= GUC_KLV_LEN_MIN + len; 144 num_klvs++; 145 } 146 147 return num_dwords ? -ENODATA : num_klvs; 148 } 149