Skip to content

Commit 0ddc1e0

Browse files
committed
drm/xe/guc: Add helpers for GuC KLVs
Many of the GuC actions use KLVs to pass additional parameters or configuration data. Add few helper functions for better reporting any information related to KLVs. Cc: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com> Reviewed-by: Piotr Piórkowski <piotr.piorkowski@intel.com> Acked-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com> Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20240410170338.1199-5-michal.wajdeczko@intel.com
1 parent bbc8a6f commit 0ddc1e0

File tree

3 files changed

+186
-0
lines changed

3 files changed

+186
-0
lines changed

drivers/gpu/drm/xe/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ xe-y += xe_bb.o \
9999
xe_guc_debugfs.o \
100100
xe_guc_hwconfig.o \
101101
xe_guc_id_mgr.o \
102+
xe_guc_klv_helpers.o \
102103
xe_guc_log.o \
103104
xe_guc_pc.o \
104105
xe_guc_submit.o \
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
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+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/* SPDX-License-Identifier: MIT */
2+
/*
3+
* Copyright © 2024 Intel Corporation
4+
*/
5+
6+
#ifndef _XE_GUC_KLV_HELPERS_H_
7+
#define _XE_GUC_KLV_HELPERS_H_
8+
9+
#include <linux/types.h>
10+
11+
struct drm_printer;
12+
13+
const char *xe_guc_klv_key_to_string(u16 key);
14+
15+
void xe_guc_klv_print(const u32 *klvs, u32 num_dwords, struct drm_printer *p);
16+
int xe_guc_klv_count(const u32 *klvs, u32 num_dwords);
17+
18+
/**
19+
* PREP_GUC_KLV - Prepare KLV header value based on provided key and len.
20+
* @key: KLV key
21+
* @len: KLV length
22+
*
23+
* Return: value of the KLV header (u32).
24+
*/
25+
#define PREP_GUC_KLV(key, len) \
26+
(FIELD_PREP(GUC_KLV_0_KEY, (key)) | \
27+
FIELD_PREP(GUC_KLV_0_LEN, (len)))
28+
29+
/**
30+
* PREP_GUC_KLV_CONST - Prepare KLV header value based on const key and len.
31+
* @key: const KLV key
32+
* @len: const KLV length
33+
*
34+
* Return: value of the KLV header (u32).
35+
*/
36+
#define PREP_GUC_KLV_CONST(key, len) \
37+
(FIELD_PREP_CONST(GUC_KLV_0_KEY, (key)) | \
38+
FIELD_PREP_CONST(GUC_KLV_0_LEN, (len)))
39+
40+
/**
41+
* PREP_GUC_KLV_TAG - Prepare KLV header value based on unique KLV definition tag.
42+
* @TAG: unique tag of the KLV definition
43+
*
44+
* Combine separate KEY and LEN definitions of the KLV identified by the TAG.
45+
*
46+
* Return: value of the KLV header (u32).
47+
*/
48+
#define PREP_GUC_KLV_TAG(TAG) \
49+
PREP_GUC_KLV_CONST(GUC_KLV_##TAG##_KEY, GUC_KLV_##TAG##_LEN)
50+
51+
#endif

0 commit comments

Comments
 (0)