.. | .. |
---|
23 | 23 | |
---|
24 | 24 | #include <linux/random.h> |
---|
25 | 25 | |
---|
26 | | -#include "../i915_drv.h" |
---|
27 | | -#include "../i915_selftest.h" |
---|
| 26 | +#include "gt/intel_gt_pm.h" |
---|
| 27 | +#include "i915_drv.h" |
---|
| 28 | +#include "i915_selftest.h" |
---|
| 29 | + |
---|
| 30 | +#include "igt_flush_test.h" |
---|
28 | 31 | |
---|
29 | 32 | struct i915_selftest i915_selftest __read_mostly = { |
---|
30 | | - .timeout_ms = 1000, |
---|
| 33 | + .timeout_ms = 500, |
---|
31 | 34 | }; |
---|
32 | 35 | |
---|
33 | 36 | int i915_mock_sanitycheck(void) |
---|
.. | .. |
---|
54 | 57 | #undef selftest |
---|
55 | 58 | }; |
---|
56 | 59 | |
---|
| 60 | +enum { |
---|
| 61 | +#define selftest(name, func) perf_##name, |
---|
| 62 | +#include "i915_perf_selftests.h" |
---|
| 63 | +#undef selftest |
---|
| 64 | +}; |
---|
| 65 | + |
---|
57 | 66 | struct selftest { |
---|
58 | 67 | bool enabled; |
---|
59 | 68 | const char *name; |
---|
.. | .. |
---|
75 | 84 | }; |
---|
76 | 85 | #undef selftest |
---|
77 | 86 | |
---|
| 87 | +#define selftest(n, f) [perf_##n] = { .name = #n, { .live = f } }, |
---|
| 88 | +static struct selftest perf_selftests[] = { |
---|
| 89 | +#include "i915_perf_selftests.h" |
---|
| 90 | +}; |
---|
| 91 | +#undef selftest |
---|
| 92 | + |
---|
78 | 93 | /* Embed the line number into the parameter name so that we can order tests */ |
---|
79 | 94 | #define selftest(n, func) selftest_0(n, func, param(n)) |
---|
80 | 95 | #define param(n) __PASTE(igt__, __PASTE(__LINE__, __mock_##n)) |
---|
.. | .. |
---|
88 | 103 | #define selftest_0(n, func, id) \ |
---|
89 | 104 | module_param_named(id, live_selftests[live_##n].enabled, bool, 0400); |
---|
90 | 105 | #include "i915_live_selftests.h" |
---|
| 106 | +#undef selftest_0 |
---|
| 107 | +#undef param |
---|
| 108 | + |
---|
| 109 | +#define param(n) __PASTE(igt__, __PASTE(__LINE__, __perf_##n)) |
---|
| 110 | +#define selftest_0(n, func, id) \ |
---|
| 111 | +module_param_named(id, perf_selftests[perf_##n].enabled, bool, 0400); |
---|
| 112 | +#include "i915_perf_selftests.h" |
---|
91 | 113 | #undef selftest_0 |
---|
92 | 114 | #undef param |
---|
93 | 115 | #undef selftest |
---|
.. | .. |
---|
133 | 155 | if (signal_pending(current)) |
---|
134 | 156 | return -EINTR; |
---|
135 | 157 | |
---|
136 | | - pr_debug(DRIVER_NAME ": Running %s\n", st->name); |
---|
| 158 | + pr_info(DRIVER_NAME ": Running %s\n", st->name); |
---|
137 | 159 | if (data) |
---|
138 | 160 | err = st->live(data); |
---|
139 | 161 | else |
---|
.. | .. |
---|
183 | 205 | if (!i915_selftest.live) |
---|
184 | 206 | return 0; |
---|
185 | 207 | |
---|
186 | | - err = run_selftests(live, to_i915(pci_get_drvdata(pdev))); |
---|
| 208 | + err = run_selftests(live, pdev_to_i915(pdev)); |
---|
187 | 209 | if (err) { |
---|
188 | 210 | i915_selftest.live = err; |
---|
189 | 211 | return err; |
---|
.. | .. |
---|
197 | 219 | return 0; |
---|
198 | 220 | } |
---|
199 | 221 | |
---|
| 222 | +int i915_perf_selftests(struct pci_dev *pdev) |
---|
| 223 | +{ |
---|
| 224 | + int err; |
---|
| 225 | + |
---|
| 226 | + if (!i915_selftest.perf) |
---|
| 227 | + return 0; |
---|
| 228 | + |
---|
| 229 | + err = run_selftests(perf, pdev_to_i915(pdev)); |
---|
| 230 | + if (err) { |
---|
| 231 | + i915_selftest.perf = err; |
---|
| 232 | + return err; |
---|
| 233 | + } |
---|
| 234 | + |
---|
| 235 | + if (i915_selftest.perf < 0) { |
---|
| 236 | + i915_selftest.perf = -ENOTTY; |
---|
| 237 | + return 1; |
---|
| 238 | + } |
---|
| 239 | + |
---|
| 240 | + return 0; |
---|
| 241 | +} |
---|
| 242 | + |
---|
| 243 | +static bool apply_subtest_filter(const char *caller, const char *name) |
---|
| 244 | +{ |
---|
| 245 | + char *filter, *sep, *tok; |
---|
| 246 | + bool result = true; |
---|
| 247 | + |
---|
| 248 | + filter = kstrdup(i915_selftest.filter, GFP_KERNEL); |
---|
| 249 | + for (sep = filter; (tok = strsep(&sep, ","));) { |
---|
| 250 | + bool allow = true; |
---|
| 251 | + char *sl; |
---|
| 252 | + |
---|
| 253 | + if (*tok == '!') { |
---|
| 254 | + allow = false; |
---|
| 255 | + tok++; |
---|
| 256 | + } |
---|
| 257 | + |
---|
| 258 | + if (*tok == '\0') |
---|
| 259 | + continue; |
---|
| 260 | + |
---|
| 261 | + sl = strchr(tok, '/'); |
---|
| 262 | + if (sl) { |
---|
| 263 | + *sl++ = '\0'; |
---|
| 264 | + if (strcmp(tok, caller)) { |
---|
| 265 | + if (allow) |
---|
| 266 | + result = false; |
---|
| 267 | + continue; |
---|
| 268 | + } |
---|
| 269 | + tok = sl; |
---|
| 270 | + } |
---|
| 271 | + |
---|
| 272 | + if (strcmp(tok, name)) { |
---|
| 273 | + if (allow) |
---|
| 274 | + result = false; |
---|
| 275 | + continue; |
---|
| 276 | + } |
---|
| 277 | + |
---|
| 278 | + result = allow; |
---|
| 279 | + break; |
---|
| 280 | + } |
---|
| 281 | + kfree(filter); |
---|
| 282 | + |
---|
| 283 | + return result; |
---|
| 284 | +} |
---|
| 285 | + |
---|
| 286 | +int __i915_nop_setup(void *data) |
---|
| 287 | +{ |
---|
| 288 | + return 0; |
---|
| 289 | +} |
---|
| 290 | + |
---|
| 291 | +int __i915_nop_teardown(int err, void *data) |
---|
| 292 | +{ |
---|
| 293 | + return err; |
---|
| 294 | +} |
---|
| 295 | + |
---|
| 296 | +int __i915_live_setup(void *data) |
---|
| 297 | +{ |
---|
| 298 | + struct drm_i915_private *i915 = data; |
---|
| 299 | + |
---|
| 300 | + /* The selftests expect an idle system */ |
---|
| 301 | + if (intel_gt_pm_wait_for_idle(&i915->gt)) |
---|
| 302 | + return -EIO; |
---|
| 303 | + |
---|
| 304 | + return intel_gt_terminally_wedged(&i915->gt); |
---|
| 305 | +} |
---|
| 306 | + |
---|
| 307 | +int __i915_live_teardown(int err, void *data) |
---|
| 308 | +{ |
---|
| 309 | + struct drm_i915_private *i915 = data; |
---|
| 310 | + |
---|
| 311 | + if (igt_flush_test(i915)) |
---|
| 312 | + err = -EIO; |
---|
| 313 | + |
---|
| 314 | + i915_gem_drain_freed_objects(i915); |
---|
| 315 | + |
---|
| 316 | + return err; |
---|
| 317 | +} |
---|
| 318 | + |
---|
| 319 | +int __intel_gt_live_setup(void *data) |
---|
| 320 | +{ |
---|
| 321 | + struct intel_gt *gt = data; |
---|
| 322 | + |
---|
| 323 | + /* The selftests expect an idle system */ |
---|
| 324 | + if (intel_gt_pm_wait_for_idle(gt)) |
---|
| 325 | + return -EIO; |
---|
| 326 | + |
---|
| 327 | + return intel_gt_terminally_wedged(gt); |
---|
| 328 | +} |
---|
| 329 | + |
---|
| 330 | +int __intel_gt_live_teardown(int err, void *data) |
---|
| 331 | +{ |
---|
| 332 | + struct intel_gt *gt = data; |
---|
| 333 | + |
---|
| 334 | + if (igt_flush_test(gt->i915)) |
---|
| 335 | + err = -EIO; |
---|
| 336 | + |
---|
| 337 | + i915_gem_drain_freed_objects(gt->i915); |
---|
| 338 | + |
---|
| 339 | + return err; |
---|
| 340 | +} |
---|
| 341 | + |
---|
200 | 342 | int __i915_subtests(const char *caller, |
---|
| 343 | + int (*setup)(void *data), |
---|
| 344 | + int (*teardown)(int err, void *data), |
---|
201 | 345 | const struct i915_subtest *st, |
---|
202 | 346 | unsigned int count, |
---|
203 | 347 | void *data) |
---|
.. | .. |
---|
209 | 353 | if (signal_pending(current)) |
---|
210 | 354 | return -EINTR; |
---|
211 | 355 | |
---|
212 | | - pr_debug(DRIVER_NAME ": Running %s/%s\n", caller, st->name); |
---|
| 356 | + if (!apply_subtest_filter(caller, st->name)) |
---|
| 357 | + continue; |
---|
| 358 | + |
---|
| 359 | + err = setup(data); |
---|
| 360 | + if (err) { |
---|
| 361 | + pr_err(DRIVER_NAME "/%s: setup failed for %s\n", |
---|
| 362 | + caller, st->name); |
---|
| 363 | + return err; |
---|
| 364 | + } |
---|
| 365 | + |
---|
| 366 | + pr_info(DRIVER_NAME ": Running %s/%s\n", caller, st->name); |
---|
213 | 367 | GEM_TRACE("Running %s/%s\n", caller, st->name); |
---|
214 | 368 | |
---|
215 | | - err = st->func(data); |
---|
| 369 | + err = teardown(st->func(data), data); |
---|
216 | 370 | if (err && err != -EINTR) { |
---|
217 | 371 | pr_err(DRIVER_NAME "/%s: %s failed with error %d\n", |
---|
218 | 372 | caller, st->name, err); |
---|
.. | .. |
---|
242 | 396 | return true; |
---|
243 | 397 | } |
---|
244 | 398 | |
---|
| 399 | +void igt_hexdump(const void *buf, size_t len) |
---|
| 400 | +{ |
---|
| 401 | + const size_t rowsize = 8 * sizeof(u32); |
---|
| 402 | + const void *prev = NULL; |
---|
| 403 | + bool skip = false; |
---|
| 404 | + size_t pos; |
---|
| 405 | + |
---|
| 406 | + for (pos = 0; pos < len; pos += rowsize) { |
---|
| 407 | + char line[128]; |
---|
| 408 | + |
---|
| 409 | + if (prev && !memcmp(prev, buf + pos, rowsize)) { |
---|
| 410 | + if (!skip) { |
---|
| 411 | + pr_info("*\n"); |
---|
| 412 | + skip = true; |
---|
| 413 | + } |
---|
| 414 | + continue; |
---|
| 415 | + } |
---|
| 416 | + |
---|
| 417 | + WARN_ON_ONCE(hex_dump_to_buffer(buf + pos, len - pos, |
---|
| 418 | + rowsize, sizeof(u32), |
---|
| 419 | + line, sizeof(line), |
---|
| 420 | + false) >= sizeof(line)); |
---|
| 421 | + pr_info("[%04zx] %s\n", pos, line); |
---|
| 422 | + |
---|
| 423 | + prev = buf + pos; |
---|
| 424 | + skip = false; |
---|
| 425 | + } |
---|
| 426 | +} |
---|
| 427 | + |
---|
245 | 428 | module_param_named(st_random_seed, i915_selftest.random_seed, uint, 0400); |
---|
246 | 429 | module_param_named(st_timeout, i915_selftest.timeout_ms, uint, 0400); |
---|
| 430 | +module_param_named(st_filter, i915_selftest.filter, charp, 0400); |
---|
247 | 431 | |
---|
248 | 432 | module_param_named_unsafe(mock_selftests, i915_selftest.mock, int, 0400); |
---|
249 | 433 | MODULE_PARM_DESC(mock_selftests, "Run selftests before loading, using mock hardware (0:disabled [default], 1:run tests then load driver, -1:run tests then exit module)"); |
---|
250 | 434 | |
---|
251 | 435 | module_param_named_unsafe(live_selftests, i915_selftest.live, int, 0400); |
---|
252 | 436 | MODULE_PARM_DESC(live_selftests, "Run selftests after driver initialisation on the live system (0:disabled [default], 1:run tests then continue, -1:run tests then exit module)"); |
---|
| 437 | + |
---|
| 438 | +module_param_named_unsafe(perf_selftests, i915_selftest.perf, int, 0400); |
---|
| 439 | +MODULE_PARM_DESC(perf_selftests, "Run performance orientated selftests after driver initialisation on the live system (0:disabled [default], 1:run tests then continue, -1:run tests then exit module)"); |
---|