From patchwork Tue Jan 16 15:21:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Kuoppala X-Patchwork-Id: 10167441 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 15EC560325 for ; Tue, 16 Jan 2018 15:21:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 087D0285F9 for ; Tue, 16 Jan 2018 15:21:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F14A528620; Tue, 16 Jan 2018 15:21:41 +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 594F7285F9 for ; Tue, 16 Jan 2018 15:21:41 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id B26676E177; Tue, 16 Jan 2018 15:21:40 +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 AA6506E177 for ; Tue, 16 Jan 2018 15:21:39 +0000 (UTC) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 16 Jan 2018 07:21:35 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.46,368,1511856000"; d="scan'208";a="10543058" Received: from rosetta.fi.intel.com ([10.237.72.186]) by orsmga008.jf.intel.com with ESMTP; 16 Jan 2018 07:21:33 -0800 Received: by rosetta.fi.intel.com (Postfix, from userid 1000) id 98D62840159; Tue, 16 Jan 2018 17:21:31 +0200 (EET) From: Mika Kuoppala To: intel-gfx@lists.freedesktop.org Date: Tue, 16 Jan 2018 17:21:16 +0200 Message-Id: <20180116152116.17900-1-mika.kuoppala@linux.intel.com> X-Mailer: git-send-email 2.14.1 Cc: Hans de Goede Subject: [Intel-gfx] [PATCH RFC] drm/i915/vlv: Ramp up gpu freq gradually 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 There is a suspicion that with aggressive upclocking, power rail voltage fluctuations can disrupt c state transition, leading to system hang. When upclocking with 4 cpu Baytrails, bring up cpus to c1 and then go through bins gradually towards target frequency to give leeway for hw. We go towards requested frequency on 1 millisecond intervals. For each 1 millisecond, we increase the frequency by half of bins that are in between current frequency and target. This will have an adverse effect on client boosting, delaying reaching full frequency by about 8ms. References: https://bugzilla.kernel.org/show_bug.cgi?id=109051 References: https://bugs.freedesktop.org/show_bug.cgi?id=102657 Cc: Chris Wilson Cc: Hans de Goede Signed-off-by: Mika Kuoppala --- drivers/gpu/drm/i915/i915_debugfs.c | 7 ++++ drivers/gpu/drm/i915/i915_drv.c | 5 +++ drivers/gpu/drm/i915/i915_drv.h | 4 +++ drivers/gpu/drm/i915/intel_pm.c | 72 +++++++++++++++++++++++++++++++++++-- 4 files changed, 86 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index cc659b4b2a45..9c718c2811b8 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1043,6 +1043,13 @@ static int i915_frequency_info(struct seq_file *m, void *unused) seq_printf(m, "current GPU freq: %d MHz\n", intel_gpu_freq(dev_priv, rps->cur_freq)); + if (IS_VALLEYVIEW(dev_priv)) { + seq_printf(m, "target GPU freq: %d MHz\n", + intel_gpu_freq(dev_priv, rps->target_freq)); + seq_printf(m, "QOS CPU DMA Latency %d usecs\n", + pm_qos_request(PM_QOS_CPU_DMA_LATENCY)); + } + seq_printf(m, "max GPU freq: %d MHz\n", intel_gpu_freq(dev_priv, rps->max_freq)); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 6c8da9d20c33..9718afacfa30 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -896,6 +896,10 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, BUG_ON(device_info->gen > sizeof(device_info->gen_mask) * BITS_PER_BYTE); device_info->gen_mask = BIT(device_info->gen - 1); + pm_qos_add_request(&dev_priv->gt_pm.rps.qos, + PM_QOS_CPU_DMA_LATENCY, + PM_QOS_DEFAULT_VALUE); + spin_lock_init(&dev_priv->irq_lock); spin_lock_init(&dev_priv->gpu_error.lock); mutex_init(&dev_priv->backlight_lock); @@ -953,6 +957,7 @@ static void i915_driver_cleanup_early(struct drm_i915_private *dev_priv) intel_irq_fini(dev_priv); i915_workqueues_cleanup(dev_priv); i915_engines_cleanup(dev_priv); + pm_qos_remove_request(&dev_priv->gt_pm.rps.qos); } static int i915_mmio_setup(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c42015b05b47..90cc2788fbbb 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -936,6 +936,10 @@ struct intel_rps { /* manual wa residency calculations */ struct intel_rps_ei ei; + + u8 target_freq; /* vlv target to reach */ + struct pm_qos_request qos; + struct delayed_work vlv_rps_work; }; struct intel_rc6 { diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 1db79a860b96..00ef4cb7bd8f 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6200,7 +6200,7 @@ static int gen6_set_rps(struct drm_i915_private *dev_priv, u8 val) return 0; } -static int valleyview_set_rps(struct drm_i915_private *dev_priv, u8 val) +static int valleyview_set_hw_rps(struct drm_i915_private *dev_priv, u8 val) { int err; @@ -6224,6 +6224,69 @@ static int valleyview_set_rps(struct drm_i915_private *dev_priv, u8 val) return 0; } +static void valleyview_queue_rps_change(struct drm_i915_private *dev_priv) +{ + struct intel_rps * const rps = &dev_priv->gt_pm.rps; + unsigned long delay; + + delay = 1 + msecs_to_jiffies(1); + queue_delayed_work(system_wq, &rps->vlv_rps_work, delay); +} + +static int valleyview_set_rps(struct drm_i915_private *dev_priv, u8 val) +{ + struct intel_rps * const rps = &dev_priv->gt_pm.rps; + + /* 2 cpu Baytrails seems to be safe */ + if (IS_CHERRYVIEW(dev_priv) || num_online_cpus() <= 2) + return valleyview_set_hw_rps(dev_priv, val); + + /* + * For >2 cpu Baytrails we need to get cpus to C1 + * and limit the freq rampup. + */ + rps->target_freq = val; + pm_qos_update_request(&dev_priv->gt_pm.rps.qos, 0); + + valleyview_queue_rps_change(dev_priv); + + return 0; +} + +static void vlv_rps_write_work(struct work_struct *work) +{ + struct drm_i915_private *dev_priv = + container_of(work, typeof(*dev_priv), + gt_pm.rps.vlv_rps_work.work); + struct intel_rps * const rps = &dev_priv->gt_pm.rps; + u8 next; + + mutex_lock(&dev_priv->pcu_lock); + + if (rps->target_freq == rps->cur_freq) { + pm_qos_update_request(&dev_priv->gt_pm.rps.qos, + PM_QOS_DEFAULT_VALUE); + mutex_unlock(&dev_priv->pcu_lock); + return; + } + + if (rps->target_freq > rps->cur_freq) { + u8 diff = rps->target_freq - rps->cur_freq; + + if (diff > 1) + diff = diff >> 1; + + next = rps->cur_freq + diff; + } else { + next = rps->target_freq; + } + + valleyview_set_hw_rps(dev_priv, next); + mutex_unlock(&dev_priv->pcu_lock); + + valleyview_queue_rps_change(dev_priv); +} + /* vlv_set_rps_idle: Set the frequency to idle, if Gfx clocks are down * * * If Gfx is Idle, then @@ -6237,9 +6300,11 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv) u32 val = rps->idle_freq; int err; - if (rps->cur_freq <= val) + if (IS_CHERRYVIEW(dev_priv) && rps->cur_freq <= val) return; + rps->target_freq = val; + /* The punit delays the write of the frequency and voltage until it * determines the GPU is awake. During normal usage we don't want to * waste power changing the frequency if the GPU is sleeping (rc6). @@ -9336,6 +9401,9 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val) void intel_pm_setup(struct drm_i915_private *dev_priv) { + INIT_DELAYED_WORK(&dev_priv->gt_pm.rps.vlv_rps_work, + vlv_rps_write_work); + mutex_init(&dev_priv->pcu_lock); atomic_set(&dev_priv->gt_pm.rps.num_waiters, 0);