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