From patchwork Wed Mar 22 10:03:44 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: sagar.a.kamble@intel.com X-Patchwork-Id: 9638391 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 2DF44602CB for ; Wed, 22 Mar 2017 10:02:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 25CAB269A3 for ; Wed, 22 Mar 2017 10:02:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1AA60282E8; Wed, 22 Mar 2017 10:02:15 +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 923A7269A3 for ; Wed, 22 Mar 2017 10:02:14 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 6F7536E887; Wed, 22 Mar 2017 10:01:55 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by gabe.freedesktop.org (Postfix) with ESMTPS id 17EFB6E86A for ; Wed, 22 Mar 2017 10:01:43 +0000 (UTC) Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga105.fm.intel.com with ESMTP; 22 Mar 2017 03:01:42 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.36,204,1486454400"; d="scan'208";a="78121870" Received: from sakamble-desktop.iind.intel.com ([10.223.82.153]) by orsmga005.jf.intel.com with ESMTP; 22 Mar 2017 03:01:41 -0700 From: Sagar Arun Kamble To: intel-gfx@lists.freedesktop.org Date: Wed, 22 Mar 2017 15:33:44 +0530 Message-Id: <1490177034-6138-12-git-send-email-sagar.a.kamble@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1490177034-6138-1-git-send-email-sagar.a.kamble@intel.com> References: <1490177034-6138-1-git-send-email-sagar.a.kamble@intel.com> Cc: Tom O'Rourke Subject: [Intel-gfx] [PATCH v7 11/21] drm/i915/slpc: Send RESET event to enable SLPC 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-Virus-Scanned: ClamAV using ClamSMTP Send host2guc SLPC reset event to GuC post GuC load. Post this, i915 can ascertain if SLPC has started running successfully through shared data. This check is done during intel_init_gt_powersave. This allows to get initial configuration setup by SLPC and if needed move to Host RPS if SLPC runs into issues. v1: Extract host2guc_slpc to handle slpc status code coding style changes (Paulo) Removed WARN_ON for checking msb of gtt address of shared gem obj. (ChrisW) host2guc_action to i915_guc_action change.(Sagar) Updating SLPC enabled status. (Sagar) v2: Commit message update. (David) v3: Rebase. v4: Added DRM_INFO message when SLPC is enabled. v5: Updated patch as host2guc_slpc is moved to earlier patch. SLPC activation status message put after checking the state from shared data during intel_init_gt_powersave. v6: Added definition of host2guc_slpc and clflush the shared data only for required size. Setting state to NOT_RUNNING before sending RESET event. Output data for SLPC actions is to be retrieved during intel_guc_send with lock protection so created wrapper __intel_guc_send that outputs GuC output data if needed. Clearing pm_rps_events on confirming SLPC RUNNING status so that even if host touches any of the PM registers by mistake it should not have any effect. (Sagar) v7: Added save/restore_default_rps as Uncore sanitize will clear the RP_CONTROL setup by BIOS. s/i915_ggtt_offset/guc_ggtt_offset. Signed-off-by: Tom O'Rourke Signed-off-by: Sagar Arun Kamble --- drivers/gpu/drm/i915/i915_drv.c | 2 + drivers/gpu/drm/i915/intel_pm.c | 9 +++ drivers/gpu/drm/i915/intel_slpc.c | 128 ++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_slpc.h | 7 +++ 4 files changed, 146 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 474747d..addc71b 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1011,6 +1011,8 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) intel_sanitize_options(dev_priv); + intel_slpc_save_default_rps(dev_priv); + ret = i915_ggtt_probe_hw(dev_priv); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 798656b..297b959 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6918,6 +6918,15 @@ void intel_init_gt_powersave(struct drm_i915_private *dev_priv) intel_runtime_pm_get(dev_priv); } + if (i915.enable_slpc) { + dev_priv->guc.slpc.active = intel_slpc_get_status(dev_priv); + if (!dev_priv->guc.slpc.active) { + i915.enable_slpc = 0; + intel_sanitize_gt_powersave(dev_priv); + } else + dev_priv->pm_rps_events = 0; + } + mutex_lock(&dev_priv->drm.struct_mutex); mutex_lock(&dev_priv->rps.hw_lock); diff --git a/drivers/gpu/drm/i915/intel_slpc.c b/drivers/gpu/drm/i915/intel_slpc.c index 5df8793..61a44b2 100644 --- a/drivers/gpu/drm/i915/intel_slpc.c +++ b/drivers/gpu/drm/i915/intel_slpc.c @@ -387,6 +387,122 @@ static void slpc_shared_data_init(struct drm_i915_private *dev_priv) kunmap_atomic(data); } +static void host2guc_slpc_reset(struct drm_i915_private *dev_priv) +{ + struct slpc_event_input data = {0}; + u32 shared_data_gtt_offset = guc_ggtt_offset(dev_priv->guc.slpc.vma); + + data.header.value = SLPC_EVENT(SLPC_EVENT_RESET, 2); + data.args[0] = shared_data_gtt_offset; + data.args[1] = 0; + + host2guc_slpc(dev_priv, &data, 4); +} + +static void host2guc_slpc_query_task_state(struct drm_i915_private *dev_priv) +{ + struct slpc_event_input data = {0}; + u32 shared_data_gtt_offset = guc_ggtt_offset(dev_priv->guc.slpc.vma); + + data.header.value = SLPC_EVENT(SLPC_EVENT_QUERY_TASK_STATE, 2); + data.args[0] = shared_data_gtt_offset; + data.args[1] = 0; + + host2guc_slpc(dev_priv, &data, 4); +} + +void intel_slpc_query_task_state(struct drm_i915_private *dev_priv) +{ + if (dev_priv->guc.slpc.active) + host2guc_slpc_query_task_state(dev_priv); +} + +/* + * This function will reads the state updates from GuC SLPC into shared data + * by invoking H2G action. Returns current state of GuC SLPC. + */ +void intel_slpc_read_shared_data(struct drm_i915_private *dev_priv, + struct slpc_shared_data *data) +{ + struct page *page; + void *pv = NULL; + + intel_slpc_query_task_state(dev_priv); + + page = i915_vma_first_page(dev_priv->guc.slpc.vma); + pv = kmap_atomic(page); + + drm_clflush_virt_range(pv, sizeof(struct slpc_shared_data)); + memcpy(data, pv, sizeof(struct slpc_shared_data)); + + kunmap_atomic(pv); +} + +const char *intel_slpc_get_state_str(enum slpc_global_state state) +{ + if (state == SLPC_GLOBAL_STATE_NOT_RUNNING) + return "not running"; + else if (state == SLPC_GLOBAL_STATE_INITIALIZING) + return "initializing"; + else if (state == SLPC_GLOBAL_STATE_RESETTING) + return "resetting"; + else if (state == SLPC_GLOBAL_STATE_RUNNING) + return "running"; + else if (state == SLPC_GLOBAL_STATE_SHUTTING_DOWN) + return "shutting down"; + else if (state == SLPC_GLOBAL_STATE_ERROR) + return "error"; + else + return "unknown"; +} +bool intel_slpc_get_status(struct drm_i915_private *dev_priv) +{ + struct slpc_shared_data data; + bool ret = false; + + intel_slpc_read_shared_data(dev_priv, &data); + DRM_INFO("SLPC state: %s\n", + intel_slpc_get_state_str(data.global_state)); + + switch (data.global_state) { + case SLPC_GLOBAL_STATE_RUNNING: + /* Capture required state from SLPC here */ + ret = true; + break; + case SLPC_GLOBAL_STATE_ERROR: + DRM_ERROR("SLPC in error state.\n"); + break; + case SLPC_GLOBAL_STATE_RESETTING: + /* + * SLPC enabling in GuC should be completing fast. + * If SLPC is taking time to initialize (unlikely as we are + * sending reset event during GuC load itself). + * TODO: Need to wait till state changes to RUNNING. + */ + ret = true; + DRM_ERROR("SLPC not running yet.!!!"); + break; + default: + break; + } + return ret; +} + +/* + * Uncore sanitize clears RPS state in Host GTPM flows set by BIOS, Save the + * initial BIOS programmed RPS state that is needed by SLPC and not set by SLPC. + * Set this state while enabling SLPC. + */ +void intel_slpc_save_default_rps(struct drm_i915_private *dev_priv) +{ + dev_priv->guc.slpc.rp_control = I915_READ(GEN6_RP_CONTROL); +} + +static void intel_slpc_restore_default_rps(struct drm_i915_private *dev_priv) +{ + I915_WRITE(GEN6_RP_CONTROL, dev_priv->guc.slpc.rp_control); +} + void intel_slpc_init(struct drm_i915_private *dev_priv) { struct intel_guc *guc = &dev_priv->guc; @@ -424,6 +540,18 @@ void intel_slpc_cleanup(struct drm_i915_private *dev_priv) void intel_slpc_enable(struct drm_i915_private *dev_priv) { + struct page *page; + struct slpc_shared_data *data; + + intel_slpc_restore_default_rps(dev_priv); + + page = i915_vma_first_page(dev_priv->guc.slpc.vma); + data = kmap_atomic(page); + data->global_state = SLPC_GLOBAL_STATE_NOT_RUNNING; + kunmap_atomic(data); + + host2guc_slpc_reset(dev_priv); + dev_priv->guc.slpc.active = true; } void intel_slpc_disable(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/intel_slpc.h b/drivers/gpu/drm/i915/intel_slpc.h index 96e15a9..4b9de3f 100644 --- a/drivers/gpu/drm/i915/intel_slpc.h +++ b/drivers/gpu/drm/i915/intel_slpc.h @@ -27,6 +27,8 @@ struct intel_slpc { bool active; struct i915_vma *vma; + + u32 rp_control; }; enum slpc_status { @@ -245,6 +247,11 @@ int intel_slpc_task_control(struct drm_i915_private *dev_priv, u64 val, u32 enable_id, u32 disable_id); int intel_slpc_task_status(struct drm_i915_private *dev_priv, u64 *val, u32 enable_id, u32 disable_id); +void intel_slpc_read_shared_data(struct drm_i915_private *dev_priv, + struct slpc_shared_data *data); +const char *intel_slpc_get_state_str(enum slpc_global_state state); +bool intel_slpc_get_status(struct drm_i915_private *dev_priv); +void intel_slpc_save_default_rps(struct drm_i915_private *dev_priv); void intel_slpc_init(struct drm_i915_private *dev_priv); void intel_slpc_cleanup(struct drm_i915_private *dev_priv); void intel_slpc_enable(struct drm_i915_private *dev_priv);