diff options
author | Dave Gordon <david.s.gordon@intel.com> | 2016-05-20 06:42:42 -0400 |
---|---|---|
committer | Tvrtko Ursulin <tvrtko.ursulin@intel.com> | 2016-05-23 09:21:52 -0400 |
commit | fce91f22ff31601a03bdeb5f09b525b035021259 (patch) | |
tree | 057ed4f25007af144c956bbf5389fcfce3db13a2 | |
parent | 1a3d1898375224f02a3e257cff4619d5a2492f1f (diff) |
drm/i915/guc: add enable_guc_loading parameter
Split the function of "enable_guc_submission" into two separate
options. The new one ("enable_guc_loading") controls only the
*fetching and loading* of the GuC firmware image. The existing
one is redefined to control only the *use* of the GuC for batch
submission once the firmware is loaded.
In addition, the degree of control has been refined from a simple
bool to an integer key, allowing several options:
-1 (default) whatever the platform default is
0 DISABLE don't load/use the GuC
1 BEST EFFORT try to load/use the GuC, fallback if not available
2 REQUIRE must load/use the GuC, else leave the GPU wedged
The new platform default (as coded here) will be to attempt to
load the GuC iff the device has a GuC that requires firmware,
but not yet to use it for submission. A later patch will change
to enable it if appropriate.
v4:
Changed some error-message levels, mostly ERROR->INFO, per
review comments by Tvrtko Ursulin.
v5:
Dropped one more error message, disabled GuC submission on
hypothetical firmware-free devices [Tvrtko Ursulin].
v6:
Logging tidy by Tvrtko Ursulin:
* Do not log falling back to execlists when wedging the GPU.
* Do not log fw load errors when load was disabled by user.
* Pass down some error code from fw load for log message to
make more sense.
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> (v5)
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Tested-by: Fiedorowicz, Lukasz <lukasz.fiedorowicz@intel.com>
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> (v5)
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: Nick Hoath <nicholas.hoath@intel.com> (v6)
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_guc_submission.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_params.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_params.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_guc_loader.c | 123 |
5 files changed, 89 insertions, 60 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 963f0318d4de..f78d4caf4b7f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -4885,11 +4885,8 @@ i915_gem_init_hw(struct drm_device *dev) | |||
4885 | /* We can't enable contexts until all firmware is loaded */ | 4885 | /* We can't enable contexts until all firmware is loaded */ |
4886 | if (HAS_GUC(dev)) { | 4886 | if (HAS_GUC(dev)) { |
4887 | ret = intel_guc_setup(dev); | 4887 | ret = intel_guc_setup(dev); |
4888 | if (ret) { | 4888 | if (ret) |
4889 | DRM_ERROR("Failed to initialize GuC, error %d\n", ret); | ||
4890 | ret = -EIO; | ||
4891 | goto out; | 4889 | goto out; |
4892 | } | ||
4893 | } | 4890 | } |
4894 | 4891 | ||
4895 | /* | 4892 | /* |
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 169242a8adff..916cd6778cf3 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c | |||
@@ -969,7 +969,7 @@ int intel_guc_suspend(struct drm_device *dev) | |||
969 | struct intel_context *ctx; | 969 | struct intel_context *ctx; |
970 | u32 data[3]; | 970 | u32 data[3]; |
971 | 971 | ||
972 | if (!i915.enable_guc_submission) | 972 | if (guc->guc_fw.guc_fw_load_status != GUC_FIRMWARE_SUCCESS) |
973 | return 0; | 973 | return 0; |
974 | 974 | ||
975 | ctx = dev_priv->kernel_context; | 975 | ctx = dev_priv->kernel_context; |
@@ -995,7 +995,7 @@ int intel_guc_resume(struct drm_device *dev) | |||
995 | struct intel_context *ctx; | 995 | struct intel_context *ctx; |
996 | u32 data[3]; | 996 | u32 data[3]; |
997 | 997 | ||
998 | if (!i915.enable_guc_submission) | 998 | if (guc->guc_fw.guc_fw_load_status != GUC_FIRMWARE_SUCCESS) |
999 | return 0; | 999 | return 0; |
1000 | 1000 | ||
1001 | ctx = dev_priv->kernel_context; | 1001 | ctx = dev_priv->kernel_context; |
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index cd74fb8e9387..21a323c01cdb 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c | |||
@@ -53,7 +53,8 @@ struct i915_params i915 __read_mostly = { | |||
53 | .verbose_state_checks = 1, | 53 | .verbose_state_checks = 1, |
54 | .nuclear_pageflip = 0, | 54 | .nuclear_pageflip = 0, |
55 | .edp_vswing = 0, | 55 | .edp_vswing = 0, |
56 | .enable_guc_submission = false, | 56 | .enable_guc_loading = -1, |
57 | .enable_guc_submission = 0, | ||
57 | .guc_log_level = -1, | 58 | .guc_log_level = -1, |
58 | .enable_dp_mst = true, | 59 | .enable_dp_mst = true, |
59 | .inject_load_failure = 0, | 60 | .inject_load_failure = 0, |
@@ -193,8 +194,15 @@ MODULE_PARM_DESC(edp_vswing, | |||
193 | "(0=use value from vbt [default], 1=low power swing(200mV)," | 194 | "(0=use value from vbt [default], 1=low power swing(200mV)," |
194 | "2=default swing(400mV))"); | 195 | "2=default swing(400mV))"); |
195 | 196 | ||
196 | module_param_named_unsafe(enable_guc_submission, i915.enable_guc_submission, bool, 0400); | 197 | module_param_named_unsafe(enable_guc_loading, i915.enable_guc_loading, int, 0400); |
197 | MODULE_PARM_DESC(enable_guc_submission, "Enable GuC submission (default:false)"); | 198 | MODULE_PARM_DESC(enable_guc_loading, |
199 | "Enable GuC firmware loading " | ||
200 | "(-1=auto [default], 0=never, 1=if available, 2=required)"); | ||
201 | |||
202 | module_param_named_unsafe(enable_guc_submission, i915.enable_guc_submission, int, 0400); | ||
203 | MODULE_PARM_DESC(enable_guc_submission, | ||
204 | "Enable GuC submission " | ||
205 | "(-1=auto, 0=never [default], 1=if available, 2=required)"); | ||
198 | 206 | ||
199 | module_param_named(guc_log_level, i915.guc_log_level, int, 0400); | 207 | module_param_named(guc_log_level, i915.guc_log_level, int, 0400); |
200 | MODULE_PARM_DESC(guc_log_level, | 208 | MODULE_PARM_DESC(guc_log_level, |
diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index dd0d0bbcc05b..658ce7379671 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h | |||
@@ -45,6 +45,8 @@ struct i915_params { | |||
45 | int enable_ips; | 45 | int enable_ips; |
46 | int invert_brightness; | 46 | int invert_brightness; |
47 | int enable_cmd_parser; | 47 | int enable_cmd_parser; |
48 | int enable_guc_loading; | ||
49 | int enable_guc_submission; | ||
48 | int guc_log_level; | 50 | int guc_log_level; |
49 | int mmio_debug; | 51 | int mmio_debug; |
50 | int edp_vswing; | 52 | int edp_vswing; |
@@ -56,7 +58,6 @@ struct i915_params { | |||
56 | bool load_detect_test; | 58 | bool load_detect_test; |
57 | bool reset; | 59 | bool reset; |
58 | bool disable_display; | 60 | bool disable_display; |
59 | bool enable_guc_submission; | ||
60 | bool verbose_state_checks; | 61 | bool verbose_state_checks; |
61 | bool nuclear_pageflip; | 62 | bool nuclear_pageflip; |
62 | bool enable_dp_mst; | 63 | bool enable_dp_mst; |
diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 30ec8208dbbc..29273e5fee22 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c | |||
@@ -402,50 +402,42 @@ int intel_guc_setup(struct drm_device *dev) | |||
402 | { | 402 | { |
403 | struct drm_i915_private *dev_priv = dev->dev_private; | 403 | struct drm_i915_private *dev_priv = dev->dev_private; |
404 | struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw; | 404 | struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw; |
405 | int retries, err = 0; | 405 | const char *fw_path = guc_fw->guc_fw_path; |
406 | int retries, ret, err; | ||
406 | 407 | ||
407 | if (!i915.enable_guc_submission) | 408 | DRM_DEBUG_DRIVER("GuC fw status: path %s, fetch %s, load %s\n", |
408 | return 0; | 409 | fw_path, |
409 | |||
410 | DRM_DEBUG_DRIVER("GuC fw status: fetch %s, load %s\n", | ||
411 | intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status), | 410 | intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status), |
412 | intel_guc_fw_status_repr(guc_fw->guc_fw_load_status)); | 411 | intel_guc_fw_status_repr(guc_fw->guc_fw_load_status)); |
413 | 412 | ||
414 | direct_interrupts_to_host(dev_priv); | 413 | /* Loading forbidden, or no firmware to load? */ |
415 | 414 | if (!i915.enable_guc_loading) { | |
416 | if (guc_fw->guc_fw_fetch_status == GUC_FIRMWARE_NONE) | 415 | err = 0; |
417 | return 0; | 416 | goto fail; |
418 | 417 | } else if (fw_path == NULL || *fw_path == '\0') { | |
419 | if (guc_fw->guc_fw_fetch_status == GUC_FIRMWARE_SUCCESS && | 418 | if (*fw_path == '\0') |
420 | guc_fw->guc_fw_load_status == GUC_FIRMWARE_FAIL) | 419 | DRM_INFO("No GuC firmware known for this platform\n"); |
421 | return -ENOEXEC; | 420 | err = -ENODEV; |
422 | 421 | goto fail; | |
423 | guc_fw->guc_fw_load_status = GUC_FIRMWARE_PENDING; | 422 | } |
424 | |||
425 | DRM_DEBUG_DRIVER("GuC fw fetch status %s\n", | ||
426 | intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status)); | ||
427 | 423 | ||
428 | switch (guc_fw->guc_fw_fetch_status) { | 424 | /* Fetch failed, or already fetched but failed to load? */ |
429 | case GUC_FIRMWARE_FAIL: | 425 | if (guc_fw->guc_fw_fetch_status != GUC_FIRMWARE_SUCCESS) { |
430 | /* something went wrong :( */ | ||
431 | err = -EIO; | 426 | err = -EIO; |
432 | goto fail; | 427 | goto fail; |
433 | 428 | } else if (guc_fw->guc_fw_load_status == GUC_FIRMWARE_FAIL) { | |
434 | case GUC_FIRMWARE_NONE: | 429 | err = -ENOEXEC; |
435 | case GUC_FIRMWARE_PENDING: | ||
436 | default: | ||
437 | /* "can't happen" */ | ||
438 | WARN_ONCE(1, "GuC fw %s invalid guc_fw_fetch_status %s [%d]\n", | ||
439 | guc_fw->guc_fw_path, | ||
440 | intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status), | ||
441 | guc_fw->guc_fw_fetch_status); | ||
442 | err = -ENXIO; | ||
443 | goto fail; | 430 | goto fail; |
444 | |||
445 | case GUC_FIRMWARE_SUCCESS: | ||
446 | break; | ||
447 | } | 431 | } |
448 | 432 | ||
433 | direct_interrupts_to_host(dev_priv); | ||
434 | |||
435 | guc_fw->guc_fw_load_status = GUC_FIRMWARE_PENDING; | ||
436 | |||
437 | DRM_DEBUG_DRIVER("GuC fw status: fetch %s, load %s\n", | ||
438 | intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status), | ||
439 | intel_guc_fw_status_repr(guc_fw->guc_fw_load_status)); | ||
440 | |||
449 | err = i915_guc_submission_init(dev); | 441 | err = i915_guc_submission_init(dev); |
450 | if (err) | 442 | if (err) |
451 | goto fail; | 443 | goto fail; |
@@ -463,7 +455,7 @@ int intel_guc_setup(struct drm_device *dev) | |||
463 | */ | 455 | */ |
464 | err = i915_reset_guc(dev_priv); | 456 | err = i915_reset_guc(dev_priv); |
465 | if (err) { | 457 | if (err) { |
466 | DRM_ERROR("GuC reset failed, err %d\n", err); | 458 | DRM_ERROR("GuC reset failed: %d\n", err); |
467 | goto fail; | 459 | goto fail; |
468 | } | 460 | } |
469 | 461 | ||
@@ -474,8 +466,8 @@ int intel_guc_setup(struct drm_device *dev) | |||
474 | if (--retries == 0) | 466 | if (--retries == 0) |
475 | goto fail; | 467 | goto fail; |
476 | 468 | ||
477 | DRM_INFO("GuC fw load failed, err %d; will reset and " | 469 | DRM_INFO("GuC fw load failed: %d; will reset and " |
478 | "retry %d more time(s)\n", err, retries); | 470 | "retry %d more time(s)\n", err, retries); |
479 | } | 471 | } |
480 | 472 | ||
481 | guc_fw->guc_fw_load_status = GUC_FIRMWARE_SUCCESS; | 473 | guc_fw->guc_fw_load_status = GUC_FIRMWARE_SUCCESS; |
@@ -497,7 +489,6 @@ int intel_guc_setup(struct drm_device *dev) | |||
497 | return 0; | 489 | return 0; |
498 | 490 | ||
499 | fail: | 491 | fail: |
500 | DRM_ERROR("GuC firmware load failed, err %d\n", err); | ||
501 | if (guc_fw->guc_fw_load_status == GUC_FIRMWARE_PENDING) | 492 | if (guc_fw->guc_fw_load_status == GUC_FIRMWARE_PENDING) |
502 | guc_fw->guc_fw_load_status = GUC_FIRMWARE_FAIL; | 493 | guc_fw->guc_fw_load_status = GUC_FIRMWARE_FAIL; |
503 | 494 | ||
@@ -505,7 +496,41 @@ fail: | |||
505 | i915_guc_submission_disable(dev); | 496 | i915_guc_submission_disable(dev); |
506 | i915_guc_submission_fini(dev); | 497 | i915_guc_submission_fini(dev); |
507 | 498 | ||
508 | return err; | 499 | /* |
500 | * We've failed to load the firmware :( | ||
501 | * | ||
502 | * Decide whether to disable GuC submission and fall back to | ||
503 | * execlist mode, and whether to hide the error by returning | ||
504 | * zero or to return -EIO, which the caller will treat as a | ||
505 | * nonfatal error (i.e. it doesn't prevent driver load, but | ||
506 | * marks the GPU as wedged until reset). | ||
507 | */ | ||
508 | if (i915.enable_guc_loading > 1) { | ||
509 | ret = -EIO; | ||
510 | } else if (i915.enable_guc_submission > 1) { | ||
511 | ret = -EIO; | ||
512 | } else { | ||
513 | ret = 0; | ||
514 | } | ||
515 | |||
516 | if (err == 0) | ||
517 | DRM_INFO("GuC firmware load skipped\n"); | ||
518 | else if (ret == -EIO) | ||
519 | DRM_ERROR("GuC firmware load failed: %d\n", err); | ||
520 | else | ||
521 | DRM_INFO("GuC firmware load failed: %d\n", err); | ||
522 | |||
523 | if (i915.enable_guc_submission) { | ||
524 | if (fw_path == NULL) | ||
525 | DRM_INFO("GuC submission without firmware not supported\n"); | ||
526 | if (ret == 0) | ||
527 | DRM_INFO("Falling back to execlist mode\n"); | ||
528 | else | ||
529 | DRM_ERROR("GuC init failed: %d\n", ret); | ||
530 | } | ||
531 | i915.enable_guc_submission = 0; | ||
532 | |||
533 | return ret; | ||
509 | } | 534 | } |
510 | 535 | ||
511 | static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw) | 536 | static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw) |
@@ -644,8 +669,11 @@ void intel_guc_init(struct drm_device *dev) | |||
644 | struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw; | 669 | struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw; |
645 | const char *fw_path; | 670 | const char *fw_path; |
646 | 671 | ||
647 | if (!HAS_GUC_SCHED(dev)) | 672 | /* A negative value means "use platform default" */ |
648 | i915.enable_guc_submission = false; | 673 | if (i915.enable_guc_loading < 0) |
674 | i915.enable_guc_loading = HAS_GUC_UCODE(dev); | ||
675 | if (i915.enable_guc_submission < 0) | ||
676 | i915.enable_guc_submission = HAS_GUC_SCHED(dev); | ||
649 | 677 | ||
650 | if (!HAS_GUC_UCODE(dev)) { | 678 | if (!HAS_GUC_UCODE(dev)) { |
651 | fw_path = NULL; | 679 | fw_path = NULL; |
@@ -658,26 +686,21 @@ void intel_guc_init(struct drm_device *dev) | |||
658 | guc_fw->guc_fw_major_wanted = 8; | 686 | guc_fw->guc_fw_major_wanted = 8; |
659 | guc_fw->guc_fw_minor_wanted = 7; | 687 | guc_fw->guc_fw_minor_wanted = 7; |
660 | } else { | 688 | } else { |
661 | i915.enable_guc_submission = false; | ||
662 | fw_path = ""; /* unknown device */ | 689 | fw_path = ""; /* unknown device */ |
663 | } | 690 | } |
664 | 691 | ||
665 | if (!i915.enable_guc_submission) | ||
666 | return; | ||
667 | |||
668 | guc_fw->guc_dev = dev; | 692 | guc_fw->guc_dev = dev; |
669 | guc_fw->guc_fw_path = fw_path; | 693 | guc_fw->guc_fw_path = fw_path; |
670 | guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_NONE; | 694 | guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_NONE; |
671 | guc_fw->guc_fw_load_status = GUC_FIRMWARE_NONE; | 695 | guc_fw->guc_fw_load_status = GUC_FIRMWARE_NONE; |
672 | 696 | ||
697 | /* Early (and silent) return if GuC loading is disabled */ | ||
698 | if (!i915.enable_guc_loading) | ||
699 | return; | ||
673 | if (fw_path == NULL) | 700 | if (fw_path == NULL) |
674 | return; | 701 | return; |
675 | 702 | if (*fw_path == '\0') | |
676 | if (*fw_path == '\0') { | ||
677 | DRM_ERROR("No GuC firmware known for this platform\n"); | ||
678 | guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_FAIL; | ||
679 | return; | 703 | return; |
680 | } | ||
681 | 704 | ||
682 | guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_PENDING; | 705 | guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_PENDING; |
683 | DRM_DEBUG_DRIVER("GuC firmware pending, path %s\n", fw_path); | 706 | DRM_DEBUG_DRIVER("GuC firmware pending, path %s\n", fw_path); |