From patchwork Wed Oct 11 08:54:08 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: sagar.a.kamble@intel.com X-Patchwork-Id: 9999051 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 6D83B602BF for ; Wed, 11 Oct 2017 08:51:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5D9A52896F for ; Wed, 11 Oct 2017 08:51:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 528C628972; Wed, 11 Oct 2017 08:51:30 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id B6A7D2896F for ; Wed, 11 Oct 2017 08:51:29 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id A854C6E611; Wed, 11 Oct 2017 08:51:26 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by gabe.freedesktop.org (Postfix) with ESMTPS id 9B33A6E611 for ; Wed, 11 Oct 2017 08:51:25 +0000 (UTC) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 11 Oct 2017 01:51:25 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos; i="5.43,360,1503385200"; d="scan'208"; a="1204581508" Received: from sakamble-desktop.iind.intel.com ([10.223.26.118]) by fmsmga001.fm.intel.com with ESMTP; 11 Oct 2017 01:51:23 -0700 From: Sagar Arun Kamble To: intel-gfx@lists.freedesktop.org Date: Wed, 11 Oct 2017 14:24:08 +0530 Message-Id: <1507712056-25030-14-git-send-email-sagar.a.kamble@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1507712056-25030-1-git-send-email-sagar.a.kamble@intel.com> References: <1507712056-25030-1-git-send-email-sagar.a.kamble@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v13 13/21] drm/i915/uc: Support resume from sleep w/ and w/o GuC/HuC reload X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP GuC/HuC resume operation depends on whether firmwares are available in the WOPCM region. This is known through register WOPCM_SIZE BIT(0). If it indicates WOPCM is locked (bit is set) we just need to send action to GuC to resume and enable other related GuC functionality such as communication, interrupts and submission. If it indicates WOPCM is not locked then we need to first reload the GuC/HuC and then do all resume tasks. Currently on resume from sleep, GuC/HuC are not loaded as GPU is reset at the end of suspend/early resume. So we will have to reload the firmware and send action to resume. Resume will be done through uc_init_hw from gem_init_hw based on newly introduced state "guc->suspended". During gem_init_hw firmware load will be skipped based on resume status during intel_uc_resume. Also updated the accesses to dev_priv->guc and dev_priv->huc structure by reusing initial declared pointer. Signed-off-by: Sagar Arun Kamble Cc: Chris Wilson Cc: Michal Wajdeczko Cc: MichaƂ Winiarski Cc: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_guc_reg.h | 1 + drivers/gpu/drm/i915/intel_guc.c | 2 + drivers/gpu/drm/i915/intel_guc.h | 3 ++ drivers/gpu/drm/i915/intel_uc.c | 99 +++++++++++++++++++++++++++++-------- 4 files changed, 85 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_guc_reg.h b/drivers/gpu/drm/i915/i915_guc_reg.h index 35cf991..532296b 100644 --- a/drivers/gpu/drm/i915/i915_guc_reg.h +++ b/drivers/gpu/drm/i915/i915_guc_reg.h @@ -75,6 +75,7 @@ /* Defines WOPCM space available to GuC firmware */ #define GUC_WOPCM_SIZE _MMIO(0xc050) +#define GUC_WOPCM_LOCKED BIT(0) /* GuC addresses below GUC_WOPCM_TOP don't map through the GTT */ #define GUC_WOPCM_TOP (0x80 << 12) /* 512KB */ #define BXT_GUC_WOPCM_RC6_RESERVED (0x10 << 12) /* 64KB */ diff --git a/drivers/gpu/drm/i915/intel_guc.c b/drivers/gpu/drm/i915/intel_guc.c index 55a0158..73be382 100644 --- a/drivers/gpu/drm/i915/intel_guc.c +++ b/drivers/gpu/drm/i915/intel_guc.c @@ -65,6 +65,8 @@ void intel_guc_init_early(struct intel_guc *guc) mutex_init(&guc->send_mutex); guc->send = intel_guc_send_nop; guc->notify = gen8_guc_raise_irq; + guc->suspended = false; + guc->skip_load_on_resume = false; } int intel_guc_send_nop(struct intel_guc *guc, const u32 *action, u32 len) diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index a587210..9f84033 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -38,6 +38,9 @@ struct intel_guc { struct intel_guc_log log; struct intel_guc_ct ct; + bool suspended; + bool skip_load_on_resume; + /* Log snapshot if GuC errors during load */ struct drm_i915_gem_object *load_err_log; diff --git a/drivers/gpu/drm/i915/intel_uc.c b/drivers/gpu/drm/i915/intel_uc.c index 1365724..f641872 100644 --- a/drivers/gpu/drm/i915/intel_uc.c +++ b/drivers/gpu/drm/i915/intel_uc.c @@ -152,14 +152,35 @@ static void guc_disable_communication(struct intel_guc *guc) guc->send = intel_guc_send_nop; } +static inline bool guc_wopcm_locked(struct intel_guc *guc) +{ + struct drm_i915_private *dev_priv = guc_to_i915(guc); + + return I915_READ(GUC_WOPCM_SIZE) & GUC_WOPCM_LOCKED; +} + int intel_uc_init_hw(struct drm_i915_private *dev_priv) { struct intel_guc *guc = &dev_priv->guc; + struct intel_huc *huc = &dev_priv->huc; int ret, attempts; if (!i915_modparams.enable_guc_loading) return 0; + /* + * If on resume from sleep GuC was available we resumed GuC during + * i915_gem_resume. We need to skip load here. Reset skip_load_on_resume + * to allow load during module reload/reset/next resume behavior. + */ + if (guc->skip_load_on_resume) { + guc->skip_load_on_resume = false; + return 0; + } + + WARN_ON_ONCE(guc->fw.load_status == INTEL_UC_FIRMWARE_SUCCESS); + WARN_ON_ONCE(huc->fw.load_status == INTEL_UC_FIRMWARE_SUCCESS); + guc_disable_communication(guc); gen9_reset_guc_interrupts(dev_priv); @@ -197,8 +218,8 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv) if (ret) goto err_submission; - intel_huc_init_hw(&dev_priv->huc); - ret = intel_guc_init_hw(&dev_priv->guc); + intel_huc_init_hw(huc); + ret = intel_guc_init_hw(guc); if (ret == 0 || ret != -EAGAIN) break; @@ -214,7 +235,21 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv) if (ret) goto err_log_capture; - intel_huc_auth(&dev_priv->huc); + /* + * If WOPCM was not locked during resume from sleep, GuC/HuC need to + * be reloaded. For this we are using intel_uc_init_hw path as we want + * to handle HuC/GuC reload, GuC resume, HuC authentication and + * submission enabling etc. all here. + */ + if (guc->suspended) { + ret = intel_guc_resume(guc); + if (ret) + DRM_ERROR("GuC resume failed (%d)." + " GuC functions may not work\n", ret); + guc->suspended = false; + } + + intel_huc_auth(huc); if (i915_guc_submission_initialized(guc)) { if (i915_modparams.guc_log_level >= 0) gen9_enable_guc_interrupts(dev_priv); @@ -305,6 +340,8 @@ int intel_uc_suspend(struct drm_i915_private *dev_priv) gen9_disable_guc_interrupts(dev_priv); guc_disable_communication(guc); + guc->suspended = true; + goto out; out_suspend: @@ -326,28 +363,50 @@ int intel_uc_suspend(struct drm_i915_private *dev_priv) void intel_uc_resume(struct drm_i915_private *dev_priv) { struct intel_guc *guc = &dev_priv->guc; + struct intel_huc *huc = &dev_priv->huc; int ret; - if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS) - return; - - ret = guc_enable_communication(guc); - if (ret) { - DRM_DEBUG_DRIVER("GuC communication enable failed (%d)\n", ret); + if (!guc->suspended) return; - } - if (i915_modparams.guc_log_level >= 0) - gen9_enable_guc_interrupts(dev_priv); + /* + * If WOPCM is locked then GuC and HuC are still loaded. We just + * need to enable communication with GuC, enable interrupts, + * invoke GuC action to resume from sleep and enable submission. + * If WOPCM is not locked it is similar to fresh boot and we need + * reload the GuC/HuC firmwares and enable other GuC related + * mechanisms. Post reloading GuC we need to send action to resume + * from sleep for GuC to restore its state prior to suspend. + */ + if (guc_wopcm_locked(guc)) { + huc->fw.load_status = INTEL_UC_FIRMWARE_SUCCESS; + guc->fw.load_status = INTEL_UC_FIRMWARE_SUCCESS; - ret = intel_guc_resume(guc); - if (ret) - DRM_ERROR("GuC resume failed (%d)." - "GuC functions may not work\n", ret); + ret = guc_enable_communication(guc); + if (ret) { + DRM_DEBUG_DRIVER("GuC communication enable failed" + " (%d)\n", ret); + return; + } - i915_guc_submission_enable(dev_priv); + if (i915_modparams.guc_log_level >= 0) + gen9_enable_guc_interrupts(dev_priv); - DRM_DEBUG_DRIVER("GuC submission %s\n", - i915_guc_submission_enabled(guc) ? - "enabled" : "disabled"); + ret = intel_guc_resume(guc); + if (ret) + DRM_ERROR("GuC resume failed (%d)." + " GuC functions may not work\n", ret); + + i915_guc_submission_enable(dev_priv); + + DRM_DEBUG_DRIVER("GuC submission %s\n", + i915_guc_submission_enabled(guc) ? + "enabled" : "disabled"); + guc->suspended = false; + guc->skip_load_on_resume = true; + } else { + DRM_DEBUG_DRIVER("GuC not available. Resume will be done" + " during i915_gem_init_hw\n"); + guc->skip_load_on_resume = false; + } }