From patchwork Mon Apr 13 10:26:23 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Manna, Animesh" X-Patchwork-Id: 6206911 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id BE599BF4A6 for ; Mon, 13 Apr 2015 09:30:42 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6FD1B201D3 for ; Mon, 13 Apr 2015 09:30:40 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id F0062201CE for ; Mon, 13 Apr 2015 09:30:38 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 7364A6E32B; Mon, 13 Apr 2015 02:30:38 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by gabe.freedesktop.org (Postfix) with ESMTP id 4717B6E2E6 for ; Mon, 13 Apr 2015 02:30:36 -0700 (PDT) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga102.jf.intel.com with ESMTP; 13 Apr 2015 02:30:36 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.11,568,1422950400"; d="scan'208";a="679221770" Received: from amanna-desktop.iind.intel.com ([10.223.25.39]) by orsmga001.jf.intel.com with ESMTP; 13 Apr 2015 02:30:34 -0700 From: Animesh Manna To: intel-gfx@lists.freedesktop.org Date: Mon, 13 Apr 2015 15:56:23 +0530 Message-Id: <1428920783-23802-1-git-send-email-animesh.manna@intel.com> X-Mailer: git-send-email 2.0.2 In-Reply-To: <1428678684-11326-1-git-send-email-animesh.manna@intel.com> References: <1428678684-11326-1-git-send-email-animesh.manna@intel.com> Cc: Suketu Shah Subject: [Intel-gfx] [PATCH v3 3/8] drm/i915/skl: Add DC5 Trigger Sequence 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: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Suketu Shah Add triggers as per expectations mentioned in gen9_enable_dc5 and gen9_disable_dc5 patch. Also call POSTING_READ for every write to a register to ensure that its written immediately. v1: Remove POSTING_READ calls as they've already been added in previous patches. v2: Rebase to move all runtime pm specific changes to intel_runtime_pm.c file. Modified as per review comments from Imre: 1] Change variable name 'dc5_allowed' to 'dc5_enabled' to correspond to relevant functions. 2] Move the check dc5_enabled in skl_set_power_well() to disable DC5 into gen9_disable_DC5 which is a more appropriate place. 3] Convert checks for 'pm.dc5_enabled' and 'pm.suspended' in skl_set_power_well() to warnings. However, removing them for now as they'll be included in a future patch asserting DC-state entry/exit criteria. 4] Enable DC5, only when CSR firmware is verified to be loaded. Create new structure to track 'enabled' and 'deferred' status of DC5. 5] Ensure runtime PM reference is obtained, if CSR is not loaded, to avoid entering runtime-suspend and release it when it's loaded. 6] Protect necessary CSR-related code with locks. 7] Move CSR-loading call to runtime PM initialization, as power domains needed to be accessed during deferred DC5-enabling, are not initialized earlier. v3: Rebase to latest. Modified as per review comments from Imre: 1] Use blocking wait for CSR-loading to finish to enable DC5 for simplicity, instead of deferring enabling DC5 until CSR is loaded. 2] Obtain runtime PM reference during CSR-loading initialization itself as deferred DC5- enabling is removed and release it at the end of CSR-loading functionality. 3] Revert calling CSR-loading functionality to the beginning of i915 driver-load functionality to avoid any delay in loading. 4] Define another variable to track whether CSR-loading failed and use it to avoid enabling DC5 if it's true. 5] Define CSR-load-status accessor functions for use later. v4: 1] Disable DC5 before enabling PG2 instead of after it. 2] DC5 was being mistaken enabled even when CSR-loading timed-out. Fix that. 3] Enable DC5-related functionality using a macro. 4] Remove dc5_enabled tracking variable and its use as it's not needed now. v5: 1] Mark CSR failed to load where necessary in finish_csr_load function. 2] Use mutex-protected accessor function to check if CSR loaded instead of directly accessing the variable. 3] Prefix csr_load_status_get/set function names with intel_. v6: rebase to latest. v7: Rebase on top of nightly (Damien) v8: Squashed the patch from Imre - added csr helper pointers to simplify the code. (Imre) v9: After adding dmc ver 1.0 support rebased on top of nightly. (Animesh) v10: Added a enum for different csr states, suggested by Imre. (Animesh) Issue: VIZ-2819 Signed-off-by: A.Sunil Kamath Signed-off-by: Suketu Shah Signed-off-by: Damien Lespiau Signed-off-by: Imre Deak Signed-off-by: Animesh Manna --- drivers/gpu/drm/i915/i915_drv.h | 7 +++++ drivers/gpu/drm/i915/intel_csr.c | 51 +++++++++++++++++++++++++++++++-- drivers/gpu/drm/i915/intel_drv.h | 2 ++ drivers/gpu/drm/i915/intel_runtime_pm.c | 29 +++++++++++++++++++ 4 files changed, 87 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 90e47a9..8d6deaa 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -667,6 +667,12 @@ struct intel_uncore { #define for_each_fw_domain(domain__, dev_priv__, i__) \ for_each_fw_domain_mask(domain__, FORCEWAKE_ALL, dev_priv__, i__) +enum csr_states { + FW_LOADED = 0, + FW_LOADING, + FW_FAILED +}; + struct intel_csr { const char *fw_path; __be32 *dmc_payload; @@ -674,6 +680,7 @@ struct intel_csr { uint32_t mmio_count; uint32_t mmioaddr[8]; uint32_t mmiodata[8]; + enum csr_states states; }; #define DEV_INFO_FOR_EACH_FLAG(func, sep) \ diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index ab9b16b..6d08a41 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -49,6 +49,25 @@ static char intel_get_substepping(struct drm_device *dev) else return -ENODATA; } + +bool intel_csr_load_status_get(struct drm_i915_private *dev_priv) +{ + bool val = false; + + mutex_lock(&dev_priv->csr_lock); + val = dev_priv->csr.states; + mutex_unlock(&dev_priv->csr_lock); + + return val; +} + +void intel_csr_load_status_set(struct drm_i915_private *dev_priv, bool val) +{ + mutex_lock(&dev_priv->csr_lock); + dev_priv->csr.states = val; + mutex_unlock(&dev_priv->csr_lock); +} + void intel_csr_load_program(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -71,6 +90,8 @@ void intel_csr_load_program(struct drm_device *dev) I915_WRITE(dev_priv->csr.mmioaddr[i], dev_priv->csr.mmiodata[i]); } + + intel_csr_load_status_set(dev_priv, FW_LOADED); mutex_unlock(&dev_priv->csr_lock); } @@ -90,11 +111,13 @@ static void finish_csr_load(const struct firmware *fw, void *context) if (!fw) { i915_firmware_load_error_print(csr->fw_path, 0); + intel_csr_load_status_set(dev_priv, FW_FAILED); goto out; } if ((stepping == -ENODATA) || (substepping == -ENODATA)) { DRM_ERROR("Unknown stepping info, firmware loading failed\n"); + intel_csr_load_status_set(dev_priv, FW_FAILED); goto out; } @@ -104,6 +127,7 @@ static void finish_csr_load(const struct firmware *fw, void *context) (css_header->header_len * 4)) { DRM_ERROR("Firmware has wrong CSS header length %u bytes\n", (css_header->header_len * 4)); + intel_csr_load_status_set(dev_priv, FW_FAILED); goto out; } readcount += sizeof(struct intel_css_header); @@ -115,6 +139,7 @@ static void finish_csr_load(const struct firmware *fw, void *context) (package_header->header_len * 4)) { DRM_ERROR("Firmware has wrong package header length %u bytes\n", (package_header->header_len * 4)); + intel_csr_load_status_set(dev_priv, FW_FAILED); goto out; } readcount += sizeof(struct intel_package_header); @@ -135,6 +160,7 @@ static void finish_csr_load(const struct firmware *fw, void *context) } if (dmc_offset == CSR_DEFAULT_FW_OFFSET) { DRM_ERROR("Firmware not supported for %c stepping\n", stepping); + intel_csr_load_status_set(dev_priv, FW_FAILED); goto out; } readcount += dmc_offset; @@ -144,6 +170,7 @@ static void finish_csr_load(const struct firmware *fw, void *context) if (sizeof(struct intel_dmc_header) != (dmc_header->header_len)) { DRM_ERROR("Firmware has wrong dmc header length %u bytes\n", (dmc_header->header_len)); + intel_csr_load_status_set(dev_priv, FW_FAILED); goto out; } readcount += sizeof(struct intel_dmc_header); @@ -152,6 +179,7 @@ static void finish_csr_load(const struct firmware *fw, void *context) if (dmc_header->mmio_count > ARRAY_SIZE(csr->mmioaddr)) { DRM_ERROR("Firmware has wrong mmio count %u\n", dmc_header->mmio_count); + intel_csr_load_status_set(dev_priv, FW_FAILED); goto out; } csr->mmio_count = dmc_header->mmio_count; @@ -160,6 +188,7 @@ static void finish_csr_load(const struct firmware *fw, void *context) dmc_header->mmioaddr[i] > CSR_MMIO_END_RANGE) { DRM_ERROR(" Firmware has wrong mmio address 0x%x\n", dmc_header->mmioaddr[i]); + intel_csr_load_status_set(dev_priv, FW_FAILED); goto out; } csr->mmioaddr[i] = dmc_header->mmioaddr[i]; @@ -170,6 +199,7 @@ static void finish_csr_load(const struct firmware *fw, void *context) nbytes = dmc_header->fw_size * 4; if (nbytes > CSR_MAX_FW_SIZE) { DRM_ERROR("CSR firmware too big (%u) bytes\n", nbytes); + intel_csr_load_status_set(dev_priv, FW_FAILED); goto out; } csr->dmc_fw_size = dmc_header->fw_size; @@ -177,6 +207,7 @@ static void finish_csr_load(const struct firmware *fw, void *context) csr->dmc_payload = kmalloc(nbytes, GFP_KERNEL); if (!csr->dmc_payload) { DRM_ERROR("Memory allocation failed for dmc payload\n"); + intel_csr_load_status_set(dev_priv, FW_FAILED); goto out; } @@ -194,6 +225,11 @@ static void finish_csr_load(const struct firmware *fw, void *context) /* load csr program during system boot, as needed for DC states */ intel_csr_load_program(dev); out: + /* + * Release the runtime pm reference obtained when + * CSR wasn't loaded. + */ + intel_runtime_pm_put(dev_priv); release_firmware(fw); } @@ -210,17 +246,27 @@ void intel_csr_ucode_init(struct drm_device *dev) csr->fw_path = I915_CSR_SKL; else { DRM_ERROR("Unexpected: no known CSR firmware for platform\n"); + intel_csr_load_status_set(dev_priv, FW_FAILED); return; } + /* + * Obtain a runtime pm reference, until CSR is loaded, + * to avoid entering runtime-suspend. + */ + intel_runtime_pm_get(dev_priv); + + intel_csr_load_status_set(dev_priv, FW_LOADING); + /* CSR supported for platform, load firmware */ ret = request_firmware_nowait(THIS_MODULE, true, csr->fw_path, &dev_priv->dev->pdev->dev, GFP_KERNEL, dev_priv, finish_csr_load); - if (ret) + if (ret) { i915_firmware_load_error_print(csr->fw_path, ret); - + intel_csr_load_status_set(dev_priv, FW_FAILED); + } } void intel_csr_ucode_fini(struct drm_device *dev) @@ -230,5 +276,6 @@ void intel_csr_ucode_fini(struct drm_device *dev) if (!HAS_CSR(dev)) return; + intel_csr_load_status_set(dev_priv, FW_FAILED); kfree(dev_priv->csr.dmc_payload); } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index f3a2d88..3fc2473 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1064,6 +1064,8 @@ unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane, /* intel_csr.c */ void intel_csr_ucode_init(struct drm_device *dev); +bool intel_csr_load_status_get(struct drm_i915_private *dev_priv); +void intel_csr_load_status_set(struct drm_i915_private *dev_priv, bool val); void intel_csr_load_program(struct drm_device *dev); void intel_csr_ucode_fini(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index bc6cee9..0750191 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -49,6 +49,8 @@ * present for a given platform. */ +#define GEN9_ENABLE_DC5(dev) (IS_SKYLAKE(dev)) + #define for_each_power_well(i, power_well, domain_mask, power_domains) \ for (i = 0; \ i < (power_domains)->power_well_count && \ @@ -369,6 +371,7 @@ static void gen9_disable_dc5(struct drm_i915_private *dev_priv) static void skl_set_power_well(struct drm_i915_private *dev_priv, struct i915_power_well *power_well, bool enable) { + struct drm_device *dev = dev_priv->dev; uint32_t tmp, fuse_status; uint32_t req_mask, state_mask; bool is_enabled, enable_requested, check_fuse_status = false; @@ -408,6 +411,13 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv, if (enable) { if (!enable_requested) { + WARN((tmp & state_mask) && + !I915_READ(HSW_PWR_WELL_BIOS), + "Invalid for power well status to be enabled, unless done by the BIOS, \ + when request is to disable!\n"); + if (GEN9_ENABLE_DC5(dev) && + power_well->data == SKL_DISP_PW_2) + gen9_disable_dc5(dev_priv); I915_WRITE(HSW_PWR_WELL_DRIVER, tmp | req_mask); } @@ -424,6 +434,25 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv, I915_WRITE(HSW_PWR_WELL_DRIVER, tmp & ~req_mask); POSTING_READ(HSW_PWR_WELL_DRIVER); DRM_DEBUG_KMS("Disabling %s\n", power_well->name); + + if (GEN9_ENABLE_DC5(dev) && + power_well->data == SKL_DISP_PW_2) { + if (dev_priv->csr.states <= FW_LOADING) { + /* + * TODO: wait for a completion event or + * similar here instead of busy + * waiting using wait_for function. + */ + if (wait_for( + intel_csr_load_status_get( + dev_priv), 1000)) + DRM_ERROR("Timed out waiting for CSR to be loaded!"); + else + gen9_enable_dc5(dev_priv); + } else { + DRM_ERROR("Cannot enable DC5 as CSR failed to load!"); + } + } } }