1// SPDX-License-Identifier: GPL-2.0 AND MIT
2/*
3 * Copyright © 2025 Intel Corporation
4 */
5
6#include <kunit/static_stub.h>
7#include <kunit/test.h>
8#include <kunit/test-bug.h>
9
10#include "xe_kunit_helpers.h"
11#include "xe_pci_test.h"
12
13#define TEST_MAX_VFS 63
14
15static void pf_set_admin_mode(struct xe_device *xe, bool enable)
16{
17 /* should match logic of xe_sriov_pf_admin_only() */
18 xe->info.probe_display = !enable;
19 KUNIT_EXPECT_EQ(kunit_get_current_test(), enable, xe_sriov_pf_admin_only(xe));
20}
21
22static const void *num_vfs_gen_param(struct kunit *test, const void *prev, char *desc)
23{
24 unsigned long next = 1 + (unsigned long)prev;
25
26 if (next > TEST_MAX_VFS)
27 return NULL;
28 snprintf(buf: desc, KUNIT_PARAM_DESC_SIZE, fmt: "%lu VF%s",
29 next, str_plural(next));
30 return (void *)next;
31}
32
33static int pf_gt_config_test_init(struct kunit *test)
34{
35 struct xe_pci_fake_data fake = {
36 .sriov_mode = XE_SRIOV_MODE_PF,
37 .platform = XE_TIGERLAKE, /* any random platform with SR-IOV */
38 .subplatform = XE_SUBPLATFORM_NONE,
39 };
40 struct xe_device *xe;
41 struct xe_gt *gt;
42
43 test->priv = &fake;
44 xe_kunit_helper_xe_device_test_init(test);
45
46 xe = test->priv;
47 KUNIT_ASSERT_TRUE(test, IS_SRIOV_PF(xe));
48
49 gt = xe_root_mmio_gt(xe);
50 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gt);
51 test->priv = gt;
52
53 /* pretend it can support up to 63 VFs */
54 xe->sriov.pf.device_total_vfs = TEST_MAX_VFS;
55 xe->sriov.pf.driver_max_vfs = TEST_MAX_VFS;
56 KUNIT_ASSERT_EQ(test, xe_sriov_pf_get_totalvfs(xe), 63);
57
58 pf_set_admin_mode(xe, enable: false);
59 KUNIT_ASSERT_EQ(test, xe_sriov_init(xe), 0);
60
61 /* more sanity checks */
62 KUNIT_EXPECT_EQ(test, GUC_ID_MAX + 1, SZ_64K);
63 KUNIT_EXPECT_EQ(test, GUC_NUM_DOORBELLS, SZ_256);
64
65 return 0;
66}
67
68static void fair_contexts_1vf(struct kunit *test)
69{
70 struct xe_gt *gt = test->priv;
71 struct xe_device *xe = gt_to_xe(gt);
72
73 pf_set_admin_mode(xe, enable: false);
74 KUNIT_ASSERT_FALSE(test, xe_sriov_pf_admin_only(xe));
75 KUNIT_EXPECT_EQ(test, SZ_32K, pf_profile_fair_ctxs(gt, 1));
76
77 pf_set_admin_mode(xe, enable: true);
78 KUNIT_ASSERT_TRUE(test, xe_sriov_pf_admin_only(xe));
79 KUNIT_EXPECT_EQ(test, SZ_64K - SZ_1K, pf_profile_fair_ctxs(gt, 1));
80}
81
82static void fair_contexts(struct kunit *test)
83{
84 unsigned int num_vfs = (unsigned long)test->param_value;
85 struct xe_gt *gt = test->priv;
86 struct xe_device *xe = gt_to_xe(gt);
87
88 pf_set_admin_mode(xe, enable: false);
89 KUNIT_ASSERT_FALSE(test, xe_sriov_pf_admin_only(xe));
90
91 KUNIT_EXPECT_TRUE(test, is_power_of_2(pf_profile_fair_ctxs(gt, num_vfs)));
92 KUNIT_EXPECT_GT(test, GUC_ID_MAX, num_vfs * pf_profile_fair_ctxs(gt, num_vfs));
93
94 if (num_vfs > 31)
95 KUNIT_ASSERT_EQ(test, SZ_1K, pf_profile_fair_ctxs(gt, num_vfs));
96 else if (num_vfs > 15)
97 KUNIT_ASSERT_EQ(test, SZ_2K, pf_profile_fair_ctxs(gt, num_vfs));
98 else if (num_vfs > 7)
99 KUNIT_ASSERT_EQ(test, SZ_4K, pf_profile_fair_ctxs(gt, num_vfs));
100 else if (num_vfs > 3)
101 KUNIT_ASSERT_EQ(test, SZ_8K, pf_profile_fair_ctxs(gt, num_vfs));
102 else if (num_vfs > 1)
103 KUNIT_ASSERT_EQ(test, SZ_16K, pf_profile_fair_ctxs(gt, num_vfs));
104 else
105 KUNIT_ASSERT_EQ(test, SZ_32K, pf_profile_fair_ctxs(gt, num_vfs));
106}
107
108static void fair_doorbells_1vf(struct kunit *test)
109{
110 struct xe_gt *gt = test->priv;
111 struct xe_device *xe = gt_to_xe(gt);
112
113 pf_set_admin_mode(xe, enable: false);
114 KUNIT_ASSERT_FALSE(test, xe_sriov_pf_admin_only(xe));
115 KUNIT_EXPECT_EQ(test, 128, pf_profile_fair_dbs(gt, 1));
116
117 pf_set_admin_mode(xe, enable: true);
118 KUNIT_ASSERT_TRUE(test, xe_sriov_pf_admin_only(xe));
119 KUNIT_EXPECT_EQ(test, 240, pf_profile_fair_dbs(gt, 1));
120}
121
122static void fair_doorbells(struct kunit *test)
123{
124 unsigned int num_vfs = (unsigned long)test->param_value;
125 struct xe_gt *gt = test->priv;
126 struct xe_device *xe = gt_to_xe(gt);
127
128 pf_set_admin_mode(xe, enable: false);
129 KUNIT_ASSERT_FALSE(test, xe_sriov_pf_admin_only(xe));
130
131 KUNIT_EXPECT_TRUE(test, is_power_of_2(pf_profile_fair_dbs(gt, num_vfs)));
132 KUNIT_EXPECT_GE(test, GUC_NUM_DOORBELLS, (num_vfs + 1) * pf_profile_fair_dbs(gt, num_vfs));
133
134 if (num_vfs > 31)
135 KUNIT_ASSERT_EQ(test, SZ_4, pf_profile_fair_dbs(gt, num_vfs));
136 else if (num_vfs > 15)
137 KUNIT_ASSERT_EQ(test, SZ_8, pf_profile_fair_dbs(gt, num_vfs));
138 else if (num_vfs > 7)
139 KUNIT_ASSERT_EQ(test, SZ_16, pf_profile_fair_dbs(gt, num_vfs));
140 else if (num_vfs > 3)
141 KUNIT_ASSERT_EQ(test, SZ_32, pf_profile_fair_dbs(gt, num_vfs));
142 else if (num_vfs > 1)
143 KUNIT_ASSERT_EQ(test, SZ_64, pf_profile_fair_dbs(gt, num_vfs));
144 else
145 KUNIT_ASSERT_EQ(test, SZ_128, pf_profile_fair_dbs(gt, num_vfs));
146}
147
148static void fair_ggtt_1vf(struct kunit *test)
149{
150 struct xe_gt *gt = test->priv;
151 struct xe_device *xe = gt_to_xe(gt);
152
153 pf_set_admin_mode(xe, enable: false);
154 KUNIT_ASSERT_FALSE(test, xe_sriov_pf_admin_only(xe));
155 KUNIT_EXPECT_EQ(test, SZ_2G, pf_profile_fair_ggtt(gt, 1));
156
157 pf_set_admin_mode(xe, enable: true);
158 KUNIT_ASSERT_TRUE(test, xe_sriov_pf_admin_only(xe));
159 KUNIT_EXPECT_EQ(test, SZ_2G + SZ_1G + SZ_512M, pf_profile_fair_ggtt(gt, 1));
160}
161
162static void fair_ggtt(struct kunit *test)
163{
164 unsigned int num_vfs = (unsigned long)test->param_value;
165 struct xe_gt *gt = test->priv;
166 struct xe_device *xe = gt_to_xe(gt);
167 u64 alignment = pf_get_ggtt_alignment(gt);
168 u64 shareable = SZ_2G + SZ_1G + SZ_512M;
169
170 pf_set_admin_mode(xe, enable: false);
171 KUNIT_ASSERT_FALSE(test, xe_sriov_pf_admin_only(xe));
172
173 KUNIT_EXPECT_TRUE(test, IS_ALIGNED(pf_profile_fair_ggtt(gt, num_vfs), alignment));
174 KUNIT_EXPECT_GE(test, shareable, num_vfs * pf_profile_fair_ggtt(gt, num_vfs));
175
176 if (num_vfs > 56)
177 KUNIT_ASSERT_EQ(test, SZ_64M - SZ_8M, pf_profile_fair_ggtt(gt, num_vfs));
178 else if (num_vfs > 28)
179 KUNIT_ASSERT_EQ(test, SZ_64M, pf_profile_fair_ggtt(gt, num_vfs));
180 else if (num_vfs > 14)
181 KUNIT_ASSERT_EQ(test, SZ_128M, pf_profile_fair_ggtt(gt, num_vfs));
182 else if (num_vfs > 7)
183 KUNIT_ASSERT_EQ(test, SZ_256M, pf_profile_fair_ggtt(gt, num_vfs));
184 else if (num_vfs > 3)
185 KUNIT_ASSERT_EQ(test, SZ_512M, pf_profile_fair_ggtt(gt, num_vfs));
186 else if (num_vfs > 1)
187 KUNIT_ASSERT_EQ(test, SZ_1G, pf_profile_fair_ggtt(gt, num_vfs));
188 else
189 KUNIT_ASSERT_EQ(test, SZ_2G, pf_profile_fair_ggtt(gt, num_vfs));
190}
191
192static struct kunit_case pf_gt_config_test_cases[] = {
193 KUNIT_CASE(fair_contexts_1vf),
194 KUNIT_CASE(fair_doorbells_1vf),
195 KUNIT_CASE(fair_ggtt_1vf),
196 KUNIT_CASE_PARAM(fair_contexts, num_vfs_gen_param),
197 KUNIT_CASE_PARAM(fair_doorbells, num_vfs_gen_param),
198 KUNIT_CASE_PARAM(fair_ggtt, num_vfs_gen_param),
199 {}
200};
201
202static struct kunit_suite pf_gt_config_suite = {
203 .name = "pf_gt_config",
204 .test_cases = pf_gt_config_test_cases,
205 .init = pf_gt_config_test_init,
206};
207
208kunit_test_suite(pf_gt_config_suite);
209

source code of linux/drivers/gpu/drm/xe/tests/xe_gt_sriov_pf_config_kunit.c