xref: /linux/drivers/gpu/drm/xe/tests/xe_pci.c (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
1 // SPDX-License-Identifier: GPL-2.0 AND MIT
2 /*
3  * Copyright © 2023 Intel Corporation
4  */
5 
6 #include "tests/xe_pci_test.h"
7 
8 #include "tests/xe_test.h"
9 
10 #include <kunit/test-bug.h>
11 #include <kunit/test.h>
12 #include <kunit/visibility.h>
13 
14 #define PLATFORM_CASE(platform__, graphics_step__)					\
15 	{										\
16 		.platform = XE_ ## platform__,						\
17 		.subplatform = XE_SUBPLATFORM_NONE,					\
18 		.step = { .graphics = STEP_ ## graphics_step__ }			\
19 	}
20 
21 #define SUBPLATFORM_CASE(platform__, subplatform__, graphics_step__)			\
22 	{										\
23 		.platform = XE_ ## platform__,						\
24 		.subplatform = XE_SUBPLATFORM_ ## platform__ ## _ ## subplatform__,	\
25 		.step = { .graphics = STEP_ ## graphics_step__ }			\
26 	}
27 
28 #define GMDID_CASE(platform__, graphics_verx100__, graphics_step__,			\
29 		   media_verx100__, media_step__)					\
30 	{										\
31 		.platform = XE_ ## platform__,						\
32 		.subplatform = XE_SUBPLATFORM_NONE,					\
33 		.graphics_verx100 = graphics_verx100__,					\
34 		.media_verx100 = media_verx100__,					\
35 		.step = { .graphics = STEP_ ## graphics_step__,				\
36 			   .media = STEP_ ## media_step__ }				\
37 	}
38 
39 static const struct xe_pci_fake_data cases[] = {
40 	PLATFORM_CASE(TIGERLAKE, B0),
41 	PLATFORM_CASE(DG1, A0),
42 	PLATFORM_CASE(DG1, B0),
43 	PLATFORM_CASE(ALDERLAKE_S, A0),
44 	PLATFORM_CASE(ALDERLAKE_S, B0),
45 	PLATFORM_CASE(ALDERLAKE_S, C0),
46 	PLATFORM_CASE(ALDERLAKE_S, D0),
47 	PLATFORM_CASE(ALDERLAKE_P, A0),
48 	PLATFORM_CASE(ALDERLAKE_P, B0),
49 	PLATFORM_CASE(ALDERLAKE_P, C0),
50 	SUBPLATFORM_CASE(ALDERLAKE_S, RPLS, D0),
51 	SUBPLATFORM_CASE(ALDERLAKE_P, RPLU, E0),
52 	SUBPLATFORM_CASE(DG2, G10, C0),
53 	SUBPLATFORM_CASE(DG2, G11, B1),
54 	SUBPLATFORM_CASE(DG2, G12, A1),
55 	GMDID_CASE(METEORLAKE, 1270, A0, 1300, A0),
56 	GMDID_CASE(METEORLAKE, 1271, A0, 1300, A0),
57 	GMDID_CASE(METEORLAKE, 1274, A0, 1300, A0),
58 	GMDID_CASE(LUNARLAKE, 2004, A0, 2000, A0),
59 	GMDID_CASE(LUNARLAKE, 2004, B0, 2000, A0),
60 	GMDID_CASE(BATTLEMAGE, 2001, A0, 1301, A1),
61 	GMDID_CASE(PANTHERLAKE, 3000, A0, 3000, A0),
62 };
63 
64 KUNIT_ARRAY_PARAM(platform, cases, xe_pci_fake_data_desc);
65 
66 /**
67  * xe_pci_fake_data_gen_params - Generate struct xe_pci_fake_data parameters
68  * @test: test context object
69  * @prev: the pointer to the previous parameter to iterate from or NULL
70  * @desc: output buffer with minimum size of KUNIT_PARAM_DESC_SIZE
71  *
72  * This function prepares struct xe_pci_fake_data parameter.
73  *
74  * To be used only as a parameter generator function in &KUNIT_CASE_PARAM.
75  *
76  * Return: pointer to the next parameter or NULL if no more parameters
77  */
78 const void *xe_pci_fake_data_gen_params(struct kunit *test, const void *prev, char *desc)
79 {
80 	return platform_gen_params(test, prev, desc);
81 }
82 EXPORT_SYMBOL_IF_KUNIT(xe_pci_fake_data_gen_params);
83 
84 static const struct xe_device_desc *lookup_desc(enum xe_platform p)
85 {
86 	const struct xe_device_desc *desc;
87 	const struct pci_device_id *ids;
88 
89 	for (ids = pciidlist; ids->driver_data; ids++) {
90 		desc = (const void *)ids->driver_data;
91 		if (desc->platform == p)
92 			return desc;
93 	}
94 	return NULL;
95 }
96 
97 static const struct xe_subplatform_desc *lookup_sub_desc(enum xe_platform p, enum xe_subplatform s)
98 {
99 	const struct xe_device_desc *desc = lookup_desc(p);
100 	const struct xe_subplatform_desc *spd;
101 
102 	if (desc && desc->subplatforms)
103 		for (spd = desc->subplatforms; spd->subplatform; spd++)
104 			if (spd->subplatform == s)
105 				return spd;
106 	return NULL;
107 }
108 
109 static const char *lookup_platform_name(enum xe_platform p)
110 {
111 	const struct xe_device_desc *desc = lookup_desc(p);
112 
113 	return desc ? desc->platform_name : "INVALID";
114 }
115 
116 static const char *__lookup_subplatform_name(enum xe_platform p, enum xe_subplatform s)
117 {
118 	const struct xe_subplatform_desc *desc = lookup_sub_desc(p, s);
119 
120 	return desc ? desc->name : "INVALID";
121 }
122 
123 static const char *lookup_subplatform_name(enum xe_platform p, enum xe_subplatform s)
124 {
125 	return s == XE_SUBPLATFORM_NONE ? "" : __lookup_subplatform_name(p, s);
126 }
127 
128 static const char *subplatform_prefix(enum xe_subplatform s)
129 {
130 	return s == XE_SUBPLATFORM_NONE ? "" : " ";
131 }
132 
133 static const char *step_prefix(enum intel_step step)
134 {
135 	return step == STEP_NONE ? "" : " ";
136 }
137 
138 static const char *step_name(enum intel_step step)
139 {
140 	return step == STEP_NONE ? "" : xe_step_name(step);
141 }
142 
143 static const char *sriov_prefix(enum xe_sriov_mode mode)
144 {
145 	return mode <= XE_SRIOV_MODE_NONE ? "" : " ";
146 }
147 
148 static const char *sriov_name(enum xe_sriov_mode mode)
149 {
150 	return mode <= XE_SRIOV_MODE_NONE ? "" : xe_sriov_mode_to_string(mode);
151 }
152 
153 static const char *lookup_graphics_name(unsigned int verx100)
154 {
155 	const struct xe_ip *ip = find_graphics_ip(verx100);
156 
157 	return ip ? ip->name : "";
158 }
159 
160 static const char *lookup_media_name(unsigned int verx100)
161 {
162 	const struct xe_ip *ip = find_media_ip(verx100);
163 
164 	return ip ? ip->name : "";
165 }
166 
167 /**
168  * xe_pci_fake_data_desc - Describe struct xe_pci_fake_data parameter
169  * @param: the &struct xe_pci_fake_data parameter to describe
170  * @desc: output buffer with minimum size of KUNIT_PARAM_DESC_SIZE
171  *
172  * This function prepares description of the struct xe_pci_fake_data parameter.
173  *
174  * It is tailored for use in parameterized KUnit tests where parameter generator
175  * is based on the struct xe_pci_fake_data arrays.
176  */
177 void xe_pci_fake_data_desc(const struct xe_pci_fake_data *param, char *desc)
178 {
179 	if (param->graphics_verx100 || param->media_verx100)
180 		snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s%s%s %u.%02u(%s)%s%s %u.%02u(%s)%s%s%s%s",
181 			 lookup_platform_name(param->platform),
182 			 subplatform_prefix(param->subplatform),
183 			 lookup_subplatform_name(param->platform, param->subplatform),
184 			 param->graphics_verx100 / 100, param->graphics_verx100 % 100,
185 			 lookup_graphics_name(param->graphics_verx100),
186 			 step_prefix(param->step.graphics), step_name(param->step.graphics),
187 			 param->media_verx100 / 100, param->media_verx100 % 100,
188 			 lookup_media_name(param->media_verx100),
189 			 step_prefix(param->step.media), step_name(param->step.media),
190 			 sriov_prefix(param->sriov_mode), sriov_name(param->sriov_mode));
191 	else
192 		snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s%s%s%s%s%s%s",
193 			 lookup_platform_name(param->platform),
194 			 subplatform_prefix(param->subplatform),
195 			 lookup_subplatform_name(param->platform, param->subplatform),
196 			 step_prefix(param->step.graphics), step_name(param->step.graphics),
197 			 sriov_prefix(param->sriov_mode), sriov_name(param->sriov_mode));
198 }
199 EXPORT_SYMBOL_IF_KUNIT(xe_pci_fake_data_desc);
200 
201 static void xe_ip_kunit_desc(const struct xe_ip *param, char *desc)
202 {
203 	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%u.%02u %s",
204 		 param->verx100 / 100, param->verx100 % 100, param->name);
205 }
206 
207 /*
208  * Pre-GMDID Graphics and Media IPs definitions.
209  *
210  * Mimic the way GMDID IPs are declared so the same
211  * param generator can be used for both
212  */
213 static const struct xe_ip pre_gmdid_graphics_ips[] = {
214 	{ 1200, "Xe_LP", &graphics_xelp },
215 	{ 1210, "Xe_LP+", &graphics_xelp },
216 	{ 1255, "Xe_HPG", &graphics_xehpg },
217 	{ 1260, "Xe_HPC", &graphics_xehpc },
218 };
219 
220 static const struct xe_ip pre_gmdid_media_ips[] = {
221 	{ 1200, "Xe_M", &media_xem },
222 	{ 1255, "Xe_HPM", &media_xem },
223 };
224 
225 KUNIT_ARRAY_PARAM(pre_gmdid_graphics_ip, pre_gmdid_graphics_ips, xe_ip_kunit_desc);
226 KUNIT_ARRAY_PARAM(pre_gmdid_media_ip, pre_gmdid_media_ips, xe_ip_kunit_desc);
227 
228 KUNIT_ARRAY_PARAM(graphics_ip, graphics_ips, xe_ip_kunit_desc);
229 KUNIT_ARRAY_PARAM(media_ip, media_ips, xe_ip_kunit_desc);
230 
231 static void xe_pci_id_kunit_desc(const struct pci_device_id *param, char *desc)
232 {
233 	const struct xe_device_desc *dev_desc =
234 		(const struct xe_device_desc *)param->driver_data;
235 
236 	if (dev_desc)
237 		snprintf(desc, KUNIT_PARAM_DESC_SIZE, "0x%X (%s)",
238 			 param->device, dev_desc->platform_name);
239 }
240 
241 KUNIT_ARRAY_PARAM(pci_id, pciidlist, xe_pci_id_kunit_desc);
242 
243 /**
244  * xe_pci_graphics_ip_gen_param - Generate graphics struct xe_ip parameters
245  * @test: test context object
246  * @prev: the pointer to the previous parameter to iterate from or NULL
247  * @desc: output buffer with minimum size of KUNIT_PARAM_DESC_SIZE
248  *
249  * This function prepares struct xe_ip parameter.
250  *
251  * To be used only as a parameter generator function in &KUNIT_CASE_PARAM.
252  *
253  * Return: pointer to the next parameter or NULL if no more parameters
254  */
255 const void *xe_pci_graphics_ip_gen_param(struct kunit *test, const void *prev, char *desc)
256 {
257 	const void *next = pre_gmdid_graphics_ip_gen_params(test, prev, desc);
258 
259 	if (next)
260 		return next;
261 	if (is_insidevar(prev, pre_gmdid_graphics_ips))
262 		prev = NULL;
263 
264 	return graphics_ip_gen_params(test, prev, desc);
265 }
266 EXPORT_SYMBOL_IF_KUNIT(xe_pci_graphics_ip_gen_param);
267 
268 /**
269  * xe_pci_media_ip_gen_param - Generate media struct xe_ip parameters
270  * @test: test context object
271  * @prev: the pointer to the previous parameter to iterate from or NULL
272  * @desc: output buffer with minimum size of KUNIT_PARAM_DESC_SIZE
273  *
274  * This function prepares struct xe_ip parameter.
275  *
276  * To be used only as a parameter generator function in &KUNIT_CASE_PARAM.
277  *
278  * Return: pointer to the next parameter or NULL if no more parameters
279  */
280 const void *xe_pci_media_ip_gen_param(struct kunit *test, const void *prev, char *desc)
281 {
282 	const void *next = pre_gmdid_media_ip_gen_params(test, prev, desc);
283 
284 	if (next)
285 		return next;
286 	if (is_insidevar(prev, pre_gmdid_media_ips))
287 		prev = NULL;
288 
289 	return media_ip_gen_params(test, prev, desc);
290 }
291 EXPORT_SYMBOL_IF_KUNIT(xe_pci_media_ip_gen_param);
292 
293 /**
294  * xe_pci_id_gen_param - Generate struct pci_device_id parameters
295  * @test: test context object
296  * @prev: the pointer to the previous parameter to iterate from or NULL
297  * @desc: output buffer with minimum size of KUNIT_PARAM_DESC_SIZE
298  *
299  * This function prepares struct pci_device_id parameter.
300  *
301  * To be used only as a parameter generator function in &KUNIT_CASE_PARAM.
302  *
303  * Return: pointer to the next parameter or NULL if no more parameters
304  */
305 const void *xe_pci_id_gen_param(struct kunit *test, const void *prev, char *desc)
306 {
307 	const struct pci_device_id *pci = pci_id_gen_params(test, prev, desc);
308 
309 	return pci->driver_data ? pci : NULL;
310 }
311 EXPORT_SYMBOL_IF_KUNIT(xe_pci_id_gen_param);
312 
313 static int fake_probe_info(struct xe_device *xe,
314 			   const struct xe_device_desc *desc,
315 			   struct xe_pci_fake_data *data,
316 			   struct xe_probed_info *probed_info)
317 {
318 	probed_info->tile_count = 1 + desc->max_remote_tiles;
319 
320 	if (!data || desc->pre_gmdid_graphics_ip) {
321 		probed_info->graphics_ip = desc->pre_gmdid_graphics_ip;
322 		probed_info->media_ip = desc->pre_gmdid_media_ip;
323 	} else {
324 		probed_info->graphics_ip = find_graphics_ip(data->graphics_verx100);
325 
326 		if (data->media_verx100) {
327 			probed_info->media_ip = find_media_ip(data->media_verx100);
328 			xe_assert(xe, probed_info->media_ip);
329 		}
330 	}
331 
332 	xe_assert(xe, probed_info->graphics_ip);
333 	if (!probed_info->graphics_ip)
334 		return -ENODEV;
335 
336 	if (data)
337 		probed_info->step = data->step;
338 
339 	return 0;
340 }
341 
342 int xe_pci_fake_device_init(struct xe_device *xe)
343 {
344 	struct kunit *test = kunit_get_current_test();
345 	struct xe_pci_fake_data *data = test->priv;
346 	struct xe_probed_info probed_info = {};
347 	const struct pci_device_id *ent = pciidlist;
348 	const struct xe_device_desc *desc;
349 	const struct xe_subplatform_desc *subplatform_desc;
350 	int err;
351 
352 	if (!data) {
353 		desc = (const void *)ent->driver_data;
354 		subplatform_desc = NULL;
355 		goto done;
356 	}
357 
358 	for (ent = pciidlist; ent->device; ent++) {
359 		desc = (const void *)ent->driver_data;
360 		if (desc->platform == data->platform)
361 			break;
362 	}
363 
364 	if (!ent->device)
365 		return -ENODEV;
366 
367 	for (subplatform_desc = desc->subplatforms;
368 	     subplatform_desc && subplatform_desc->subplatform;
369 	     subplatform_desc++)
370 		if (subplatform_desc->subplatform == data->subplatform)
371 			break;
372 
373 	if (data->subplatform != XE_SUBPLATFORM_NONE && !subplatform_desc)
374 		return -ENODEV;
375 
376 done:
377 	xe->sriov.__mode = data && data->sriov_mode ?
378 			   data->sriov_mode : XE_SRIOV_MODE_NONE;
379 
380 	err = fake_probe_info(xe, desc, data, &probed_info);
381 	if (err)
382 		return err;
383 
384 	xe_info_init_early(xe, desc, subplatform_desc, &probed_info);
385 	xe_info_init(xe, desc, &probed_info);
386 
387 	return 0;
388 }
389 EXPORT_SYMBOL_IF_KUNIT(xe_pci_fake_device_init);
390 
391 /**
392  * xe_pci_live_device_gen_param - Helper to iterate Xe devices as KUnit parameters
393  * @test: test context object
394  * @prev: the previously returned value, or NULL for the first iteration
395  * @desc: the buffer for a parameter name
396  *
397  * Iterates over the available Xe devices on the system. Uses the device name
398  * as the parameter name.
399  *
400  * To be used only as a parameter generator function in &KUNIT_CASE_PARAM.
401  *
402  * Return: pointer to the next &struct xe_device ready to be used as a parameter
403  *         or NULL if there are no more Xe devices on the system.
404  */
405 const void *xe_pci_live_device_gen_param(struct kunit *test, const void *prev, char *desc)
406 {
407 	const struct xe_device *xe = prev;
408 	struct device *dev = xe ? xe->drm.dev : NULL;
409 	struct device *next;
410 
411 	next = driver_find_next_device(&xe_pci_driver.driver, dev);
412 	if (dev)
413 		put_device(dev);
414 	if (!next)
415 		return NULL;
416 
417 	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s", dev_name(next));
418 	return pdev_to_xe_device(to_pci_dev(next));
419 }
420 EXPORT_SYMBOL_IF_KUNIT(xe_pci_live_device_gen_param);
421