aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Gordon <david.s.gordon@intel.com>2016-05-20 06:42:42 -0400
committerTvrtko Ursulin <tvrtko.ursulin@intel.com>2016-05-23 09:21:52 -0400
commitfce91f22ff31601a03bdeb5f09b525b035021259 (patch)
tree057ed4f25007af144c956bbf5389fcfce3db13a2
parent1a3d1898375224f02a3e257cff4619d5a2492f1f (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.c5
-rw-r--r--drivers/gpu/drm/i915/i915_guc_submission.c4
-rw-r--r--drivers/gpu/drm/i915/i915_params.c14
-rw-r--r--drivers/gpu/drm/i915/i915_params.h3
-rw-r--r--drivers/gpu/drm/i915/intel_guc_loader.c123
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
196module_param_named_unsafe(enable_guc_submission, i915.enable_guc_submission, bool, 0400); 197module_param_named_unsafe(enable_guc_loading, i915.enable_guc_loading, int, 0400);
197MODULE_PARM_DESC(enable_guc_submission, "Enable GuC submission (default:false)"); 198MODULE_PARM_DESC(enable_guc_loading,
199 "Enable GuC firmware loading "
200 "(-1=auto [default], 0=never, 1=if available, 2=required)");
201
202module_param_named_unsafe(enable_guc_submission, i915.enable_guc_submission, int, 0400);
203MODULE_PARM_DESC(enable_guc_submission,
204 "Enable GuC submission "
205 "(-1=auto, 0=never [default], 1=if available, 2=required)");
198 206
199module_param_named(guc_log_level, i915.guc_log_level, int, 0400); 207module_param_named(guc_log_level, i915.guc_log_level, int, 0400);
200MODULE_PARM_DESC(guc_log_level, 208MODULE_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
499fail: 491fail:
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
511static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw) 536static 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);