drm/xe/guc: Add KLV parsing helper

We have already introduced a helper to encode larger objects. Now
add helper to parse the KLVs buffer. We will use it shortly.

Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Reviewed-by: Michał Winiarski <michal.winiarski@intel.com>
Link: https://patch.msgid.link/20260707220816.677-7-michal.wajdeczko@intel.com
This commit is contained in:
Michal Wajdeczko 2026-07-08 00:08:08 +02:00
parent b088da0303
commit 5598b9356c
2 changed files with 41 additions and 0 deletions

View File

@ -319,3 +319,41 @@ u32 *xe_guc_klv_encode_object(u32 *klvs, u32 avail, u16 key, const void *obj,
*klvs = PREP_GUC_KLV(key, end - (klvs + GUC_KLV_LEN_MIN));
return end;
}
/**
* xe_guc_klv_parser() - Parse and decode stream of KLVs.
* @klvs: the buffer with KLVs
* @num_dwords: number of dwords (u32) available in the buffer
* @obj: opaque pointer to be used by the @decoder function
* @decoder: pointer to the decoder function
*
* Return: The sum of all results returned by the decoder or
* an -errno on decoder or buffer failure.
*/
int xe_guc_klv_parser(const u32 *klvs, u32 num_dwords, void *obj,
int (*decoder)(void *obj, u16 key, u16 len, const u32 *value))
{
int total = 0;
int ret;
while (num_dwords >= GUC_KLV_LEN_MIN) {
u16 key = FIELD_GET(GUC_KLV_0_KEY, klvs[0]);
u16 len = FIELD_GET(GUC_KLV_0_LEN, klvs[0]);
klvs += GUC_KLV_LEN_MIN;
num_dwords -= GUC_KLV_LEN_MIN;
if (num_dwords < len)
return -ENODATA;
ret = decoder(obj, key, len, klvs);
if (ret < 0)
return ret;
total += ret;
klvs += len;
num_dwords -= len;
}
return total;
}

View File

@ -23,6 +23,9 @@ u32 *xe_guc_klv_encode_string(u32 *klvs, u32 avail, u16 key, const char *s);
u32 *xe_guc_klv_encode_object(u32 *klvs, u32 avail, u16 key, const void *obj,
u32 *(*encoder)(u32 *klvs, u32 avail, const void *obj));
int xe_guc_klv_parser(const u32 *klvs, u32 num_dwords, void *obj,
int (*decoder)(void *obj, u16 key, u16 len, const u32 *value));
/**
* PREP_GUC_KLV - Prepare KLV header value based on provided key and len.
* @key: KLV key