aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_guc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_guc.c')
-rw-r--r--drivers/gpu/drm/i915/intel_guc.c45
1 files changed, 42 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/intel_guc.c b/drivers/gpu/drm/i915/intel_guc.c
index 230aea69385d..8660af3fd755 100644
--- a/drivers/gpu/drm/i915/intel_guc.c
+++ b/drivers/gpu/drm/i915/intel_guc.c
@@ -50,7 +50,8 @@ void intel_guc_init_send_regs(struct intel_guc *guc)
50 unsigned int i; 50 unsigned int i;
51 51
52 guc->send_regs.base = i915_mmio_reg_offset(SOFT_SCRATCH(0)); 52 guc->send_regs.base = i915_mmio_reg_offset(SOFT_SCRATCH(0));
53 guc->send_regs.count = SOFT_SCRATCH_COUNT - 1; 53 guc->send_regs.count = GUC_MAX_MMIO_MSG_LEN;
54 BUILD_BUG_ON(GUC_MAX_MMIO_MSG_LEN > SOFT_SCRATCH_COUNT);
54 55
55 for (i = 0; i < guc->send_regs.count; i++) { 56 for (i = 0; i < guc->send_regs.count; i++) {
56 fw_domains |= intel_uncore_forcewake_for_reg(dev_priv, 57 fw_domains |= intel_uncore_forcewake_for_reg(dev_priv,
@@ -521,6 +522,44 @@ int intel_guc_auth_huc(struct intel_guc *guc, u32 rsa_offset)
521 return intel_guc_send(guc, action, ARRAY_SIZE(action)); 522 return intel_guc_send(guc, action, ARRAY_SIZE(action));
522} 523}
523 524
525/*
526 * The ENTER/EXIT_S_STATE actions queue the save/restore operation in GuC FW and
527 * then return, so waiting on the H2G is not enough to guarantee GuC is done.
528 * When all the processing is done, GuC writes INTEL_GUC_SLEEP_STATE_SUCCESS to
529 * scratch register 14, so we can poll on that. Note that GuC does not ensure
530 * that the value in the register is different from
531 * INTEL_GUC_SLEEP_STATE_SUCCESS while the action is in progress so we need to
532 * take care of that ourselves as well.
533 */
534static int guc_sleep_state_action(struct intel_guc *guc,
535 const u32 *action, u32 len)
536{
537 struct drm_i915_private *dev_priv = guc_to_i915(guc);
538 int ret;
539 u32 status;
540
541 I915_WRITE(SOFT_SCRATCH(14), INTEL_GUC_SLEEP_STATE_INVALID_MASK);
542
543 ret = intel_guc_send(guc, action, len);
544 if (ret)
545 return ret;
546
547 ret = __intel_wait_for_register(dev_priv, SOFT_SCRATCH(14),
548 INTEL_GUC_SLEEP_STATE_INVALID_MASK,
549 0, 0, 10, &status);
550 if (ret)
551 return ret;
552
553 if (status != INTEL_GUC_SLEEP_STATE_SUCCESS) {
554 DRM_ERROR("GuC failed to change sleep state. "
555 "action=0x%x, err=%u\n",
556 action[0], status);
557 return -EIO;
558 }
559
560 return 0;
561}
562
524/** 563/**
525 * intel_guc_suspend() - notify GuC entering suspend state 564 * intel_guc_suspend() - notify GuC entering suspend state
526 * @guc: the guc 565 * @guc: the guc
@@ -533,7 +572,7 @@ int intel_guc_suspend(struct intel_guc *guc)
533 intel_guc_ggtt_offset(guc, guc->shared_data) 572 intel_guc_ggtt_offset(guc, guc->shared_data)
534 }; 573 };
535 574
536 return intel_guc_send(guc, data, ARRAY_SIZE(data)); 575 return guc_sleep_state_action(guc, data, ARRAY_SIZE(data));
537} 576}
538 577
539/** 578/**
@@ -571,7 +610,7 @@ int intel_guc_resume(struct intel_guc *guc)
571 intel_guc_ggtt_offset(guc, guc->shared_data) 610 intel_guc_ggtt_offset(guc, guc->shared_data)
572 }; 611 };
573 612
574 return intel_guc_send(guc, data, ARRAY_SIZE(data)); 613 return guc_sleep_state_action(guc, data, ARRAY_SIZE(data));
575} 614}
576 615
577/** 616/**