summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Wajdeczko <michal.wajdeczko@intel.com>2026-07-10 21:59:45 +0200
committerMichal Wajdeczko <michal.wajdeczko@intel.com>2026-07-11 16:15:31 +0200
commite05f612ce70f7199de0366c533f66be6417faebd (patch)
tree977daad75d3e1a0d3111c926408f5c4316c1f526
parentcca4cd467495da29e056b7bba7a6bb22ab3fd488 (diff)
drm/xe/tests: Add object encoding helper test
We will soon be encoding complex objects as KLVs using our helper function. Add few simple tests to make sure this helper function works as expected. Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com> Reviewed-by: MichaƂ Winiarski <michal.winiarski@intel.com> Link: https://patch.msgid.link/20260710195945.7316-1-michal.wajdeczko@intel.com
-rw-r--r--drivers/gpu/drm/xe/tests/xe_guc_klv_helpers_kunit.c205
1 files changed, 205 insertions, 0 deletions
diff --git a/drivers/gpu/drm/xe/tests/xe_guc_klv_helpers_kunit.c b/drivers/gpu/drm/xe/tests/xe_guc_klv_helpers_kunit.c
index cb4b182d88d0..33d7a52f6bf8 100644
--- a/drivers/gpu/drm/xe/tests/xe_guc_klv_helpers_kunit.c
+++ b/drivers/gpu/drm/xe/tests/xe_guc_klv_helpers_kunit.c
@@ -7,6 +7,7 @@
#include <kunit/test-bug.h>
#define TEST_KEY (GUC_KLV_RESERVED_RANGE_START + 0x3de)
+#define TEST_GROUP_KEY (GUC_KLV_RESERVED_RANGE_START + 0x3f0)
#define TEST_PAD 0xdeadbeef
static void test_count(struct kunit *test)
@@ -167,11 +168,215 @@ static void test_encode_string(struct kunit *test)
xe_guc_klv_encode_string(klvs, avail, key, buf));
}
+struct some_object {
+ u32 value1;
+ u64 value2;
+} __packed;
+
+static u32 *obj_raw_encoder(u32 *klvs, u32 avail, const void *arg)
+{
+ const struct some_object *obj = arg;
+ size_t sz = sizeof(*obj);
+ u32 dwords = to_num_dwords(sz);
+
+ if (IS_ERR(klvs))
+ return klvs;
+ if (dwords > avail)
+ return ERR_PTR(-ENOSPC);
+ memcpy(klvs, obj, sz);
+ return klvs + dwords;
+}
+
+static u32 *obj_klv_encoder(u32 *klvs, u32 avail, const void *arg)
+{
+ const struct some_object *obj = arg;
+ u32 *end = klvs + avail;
+
+ klvs = xe_guc_klv_encode_u32(klvs, end - klvs, TEST_KEY + 1, obj->value1);
+ klvs = xe_guc_klv_encode_u64(klvs, end - klvs, TEST_KEY + 2, obj->value2);
+ return klvs;
+}
+
+static u32 *obj_nested_encoder(u32 *klvs, u32 avail, const void *arg)
+{
+ u32 *end = klvs + avail;
+
+ klvs = xe_guc_klv_encode_object(klvs, end - klvs, TEST_GROUP_KEY + 1,
+ arg, obj_klv_encoder);
+ klvs = xe_guc_klv_encode_object(klvs, end - klvs, TEST_GROUP_KEY + 2,
+ arg, obj_klv_encoder);
+ return klvs;
+}
+
+static void test_encode_object_raw(struct kunit *test)
+{
+ const struct some_object obj = {
+ .value1 = 0xdead1234,
+ .value2 = 0xdead87654321dead,
+ };
+ u32 payload = to_num_dwords(sizeof(obj));
+ u32 *err = ERR_PTR(-ENOSPC);
+ u16 key = TEST_KEY;
+ u32 klvs[16];
+ u32 n;
+
+ /* too small, must fail */
+ for (n = 0; n < GUC_KLV_LEN_MIN + payload; n++) {
+ memset32(klvs, TEST_PAD, ARRAY_SIZE(klvs));
+ KUNIT_EXPECT_PTR_EQ_MSG(test, ERR_PTR(-ENOSPC),
+ xe_guc_klv_encode_object(klvs, n, key, &obj,
+ obj_raw_encoder),
+ "buf size=%u dwords", n);
+ }
+
+ /* must pass */
+ memset32(klvs, TEST_PAD, ARRAY_SIZE(klvs));
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test,
+ xe_guc_klv_encode_object(klvs, GUC_KLV_LEN_MIN + payload,
+ key, &obj, obj_raw_encoder));
+ KUNIT_EXPECT_EQ(test, klvs[0], PREP_GUC_KLV(key, payload));
+ KUNIT_EXPECT_MEMEQ(test, &klvs[1], &obj, sizeof(obj));
+
+ /* already failed, must fail */
+ KUNIT_ASSERT_PTR_EQ(test, err,
+ xe_guc_klv_encode_object(err, ARRAY_SIZE(klvs), key,
+ &obj, obj_raw_encoder));
+}
+
+static void test_encode_object_klv(struct kunit *test)
+{
+ const struct some_object obj = {
+ .value1 = 0xdead1234,
+ .value2 = 0xdead87654321dead,
+ };
+ u16 key = TEST_GROUP_KEY;
+ u32 payload = 0;
+ u32 klvs[16];
+ u32 n;
+
+ payload += GUC_KLV_LEN_MIN + to_num_dwords(sizeof(obj.value1));
+ payload += GUC_KLV_LEN_MIN + to_num_dwords(sizeof(obj.value2));
+
+ /* too small, must fail */
+ for (n = 0; n < GUC_KLV_LEN_MIN + payload; n++) {
+ memset32(klvs, TEST_PAD, ARRAY_SIZE(klvs));
+ KUNIT_EXPECT_PTR_EQ_MSG(test, ERR_PTR(-ENOSPC),
+ xe_guc_klv_encode_object(klvs, n, key, &obj,
+ obj_klv_encoder),
+ "buf size=%u dwords", n);
+ }
+
+ /* must pass */
+ memset32(klvs, TEST_PAD, ARRAY_SIZE(klvs));
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test,
+ xe_guc_klv_encode_object(klvs, GUC_KLV_LEN_MIN + payload,
+ key, &obj, obj_klv_encoder));
+ KUNIT_EXPECT_EQ(test, klvs[0], PREP_GUC_KLV(key, payload));
+ KUNIT_EXPECT_EQ(test, klvs[1], PREP_GUC_KLV(TEST_KEY + 1, 1));
+ KUNIT_EXPECT_EQ(test, klvs[2], obj.value1);
+ KUNIT_EXPECT_EQ(test, klvs[3], PREP_GUC_KLV(TEST_KEY + 2, 2));
+ KUNIT_EXPECT_EQ(test, klvs[4], lower_32_bits(obj.value2));
+ KUNIT_EXPECT_EQ(test, klvs[5], upper_32_bits(obj.value2));
+ KUNIT_EXPECT_EQ(test, klvs[6], TEST_PAD);
+}
+
+static void test_encode_object_nested(struct kunit *test)
+{
+ const struct some_object obj = {
+ .value1 = 0xdead1234,
+ .value2 = 0xdead87654321dead,
+ };
+ u16 key = TEST_GROUP_KEY;
+ u32 payload = 0;
+ u32 klvs[16];
+ u32 n;
+
+ payload += GUC_KLV_LEN_MIN;
+ payload += GUC_KLV_LEN_MIN + to_num_dwords(sizeof(obj.value1));
+ payload += GUC_KLV_LEN_MIN + to_num_dwords(sizeof(obj.value2));
+ payload *= 2;
+
+ /* too small, must fail */
+ for (n = 0; n < GUC_KLV_LEN_MIN + payload; n++) {
+ memset32(klvs, TEST_PAD, ARRAY_SIZE(klvs));
+ KUNIT_EXPECT_PTR_EQ_MSG(test, ERR_PTR(-ENOSPC),
+ xe_guc_klv_encode_object(klvs, n, key, &obj,
+ obj_nested_encoder),
+ "buf size=%u dwords", n);
+ }
+
+ /* must pass */
+ memset32(klvs, TEST_PAD, ARRAY_SIZE(klvs));
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test,
+ xe_guc_klv_encode_object(klvs, GUC_KLV_LEN_MIN + payload,
+ key, &obj, obj_nested_encoder));
+ KUNIT_EXPECT_EQ(test, klvs[0], PREP_GUC_KLV(key, payload));
+ KUNIT_EXPECT_EQ(test, klvs[1], PREP_GUC_KLV(TEST_GROUP_KEY + 1, 5));
+ KUNIT_EXPECT_EQ(test, klvs[2], PREP_GUC_KLV(TEST_KEY + 1, 1));
+ KUNIT_EXPECT_EQ(test, klvs[3], obj.value1);
+ KUNIT_EXPECT_EQ(test, klvs[4], PREP_GUC_KLV(TEST_KEY + 2, 2));
+ KUNIT_EXPECT_EQ(test, klvs[5], lower_32_bits(obj.value2));
+ KUNIT_EXPECT_EQ(test, klvs[6], upper_32_bits(obj.value2));
+ KUNIT_EXPECT_EQ(test, klvs[7], PREP_GUC_KLV(TEST_GROUP_KEY + 2, 5));
+ KUNIT_EXPECT_EQ(test, klvs[8], PREP_GUC_KLV(TEST_KEY + 1, 1));
+ KUNIT_EXPECT_EQ(test, klvs[9], obj.value1);
+ KUNIT_EXPECT_EQ(test, klvs[10], PREP_GUC_KLV(TEST_KEY + 2, 2));
+ KUNIT_EXPECT_EQ(test, klvs[11], lower_32_bits(obj.value2));
+ KUNIT_EXPECT_EQ(test, klvs[12], upper_32_bits(obj.value2));
+ KUNIT_EXPECT_EQ(test, klvs[13], TEST_PAD);
+}
+
+static u32 *obj_echo_encoder(u32 *klvs, u32 avail, const void *arg)
+{
+ return ERR_CAST(arg);
+}
+
+static void test_encode_object_basic(struct kunit *test)
+{
+ u32 longest = GUC_KLV_LEN_MIN + FIELD_MAX(GUC_KLV_0_LEN);
+ u32 avail = GUC_KLV_LEN_MIN + longest;
+ u16 key = TEST_GROUP_KEY;
+ u32 *klvs;
+
+ klvs = kunit_kcalloc(test, avail, sizeof(u32), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, klvs);
+
+ /* smallest */
+ KUNIT_EXPECT_PTR_EQ(test, klvs + GUC_KLV_LEN_MIN,
+ xe_guc_klv_encode_object(klvs, avail, key,
+ klvs + GUC_KLV_LEN_MIN,
+ obj_echo_encoder));
+ /* largest */
+ KUNIT_EXPECT_PTR_EQ(test, klvs + longest,
+ xe_guc_klv_encode_object(klvs, avail, key,
+ klvs + longest,
+ obj_echo_encoder));
+ /* already failed */
+ KUNIT_EXPECT_PTR_EQ(test, ERR_PTR(-EROFS),
+ xe_guc_klv_encode_object(ERR_PTR(-EROFS), avail, key,
+ klvs + GUC_KLV_LEN_MIN,
+ obj_echo_encoder));
+ /* encoding error */
+ KUNIT_EXPECT_PTR_EQ(test, ERR_PTR(-EUCLEAN),
+ xe_guc_klv_encode_object(klvs, avail, key,
+ ERR_PTR(-EUCLEAN),
+ obj_echo_encoder));
+ /* no space */
+ KUNIT_EXPECT_PTR_EQ(test, ERR_PTR(-ENOSPC),
+ xe_guc_klv_encode_object(klvs, 0, key,
+ klvs + GUC_KLV_LEN_MIN,
+ obj_echo_encoder));
+}
+
static struct kunit_case guc_klv_helpers_test_cases[] = {
KUNIT_CASE(test_count),
KUNIT_CASE(test_encode_u32),
KUNIT_CASE(test_encode_u64),
KUNIT_CASE(test_encode_string),
+ KUNIT_CASE(test_encode_object_raw),
+ KUNIT_CASE(test_encode_object_klv),
+ KUNIT_CASE(test_encode_object_nested),
+ KUNIT_CASE(test_encode_object_basic),
{}
};