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