@@ -52,7 +52,8 @@ i915-y += i915_cmd_parser.o \
# general-purpose microcontroller (GuC) support
i915-y += intel_guc_loader.o \
- i915_guc_submission.o
+ i915_guc_submission.o \
+ intel_slpc.o
# autogenerated null render state
i915-y += intel_renderstate_gen6.o \
@@ -1692,6 +1692,10 @@ void chv_phy_powergate_lanes(struct intel_encoder *encoder,
bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
enum dpio_channel ch, bool override);
+static inline int intel_slpc_active(struct drm_i915_private *dev_priv)
+{
+ return 0;
+}
/* intel_pm.c */
void intel_init_clock_gating(struct drm_device *dev);
@@ -27,6 +27,7 @@
#include "intel_guc_fwif.h"
#include "i915_guc_reg.h"
#include "intel_ringbuffer.h"
+#include "intel_slpc.h"
struct drm_i915_gem_request;
@@ -5082,7 +5082,8 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv)
* our rpm wakeref. And then disable the interrupts to stop any
* futher RPS reclocking whilst we are asleep.
*/
- gen6_disable_rps_interrupts(dev_priv);
+ if (!intel_slpc_active(dev_priv))
+ gen6_disable_rps_interrupts(dev_priv);
mutex_lock(&dev_priv->rps.hw_lock);
if (dev_priv->rps.enabled) {
@@ -6733,6 +6734,9 @@ void intel_init_gt_powersave(struct drm_i915_private *dev_priv)
/* Finally allow us to boost to max by default */
dev_priv->rps.boost_freq = dev_priv->rps.max_freq;
+ if (intel_slpc_enabled())
+ intel_slpc_init(dev_priv);
+
mutex_unlock(&dev_priv->rps.hw_lock);
mutex_unlock(&dev_priv->drm.struct_mutex);
@@ -6741,7 +6745,9 @@ void intel_init_gt_powersave(struct drm_i915_private *dev_priv)
void intel_cleanup_gt_powersave(struct drm_i915_private *dev_priv)
{
- if (IS_VALLEYVIEW(dev_priv))
+ if (intel_slpc_enabled())
+ intel_slpc_cleanup(dev_priv);
+ else if (IS_VALLEYVIEW(dev_priv))
valleyview_cleanup_gt_powersave(dev_priv);
if (!i915.enable_rc6)
@@ -6761,28 +6767,42 @@ void intel_suspend_gt_powersave(struct drm_i915_private *dev_priv)
if (INTEL_GEN(dev_priv) < 6)
return;
- if (cancel_delayed_work_sync(&dev_priv->rps.autoenable_work))
+ if (cancel_delayed_work_sync(&dev_priv->rps.autoenable_work)) {
+ if (intel_slpc_active(dev_priv))
+ intel_slpc_suspend(dev_priv);
intel_runtime_pm_put(dev_priv);
+ }
/* gen6_rps_idle() will be called later to disable interrupts */
}
void intel_sanitize_gt_powersave(struct drm_i915_private *dev_priv)
{
- dev_priv->rps.enabled = true; /* force disabling */
- intel_disable_gt_powersave(dev_priv);
+ if (intel_slpc_enabled()) {
+ /* TODO: Set SLPC enabled forcefully */
+ intel_disable_gt_powersave(dev_priv);
+ } else {
+ dev_priv->rps.enabled = true; /* force disabling */
+ intel_disable_gt_powersave(dev_priv);
- gen6_reset_rps_interrupts(dev_priv);
+ gen6_reset_rps_interrupts(dev_priv);
+ }
}
void intel_disable_gt_powersave(struct drm_i915_private *dev_priv)
{
- if (!READ_ONCE(dev_priv->rps.enabled))
+ if (intel_slpc_enabled()) {
+ if (!intel_slpc_active(dev_priv))
+ return;
+ } else if (!READ_ONCE(dev_priv->rps.enabled))
return;
mutex_lock(&dev_priv->rps.hw_lock);
- if (INTEL_GEN(dev_priv) >= 9) {
+ if (intel_slpc_active(dev_priv)) {
+ gen9_disable_rc6(dev_priv);
+ intel_slpc_disable(dev_priv);
+ } else if (INTEL_GEN(dev_priv) >= 9) {
gen9_disable_rc6(dev_priv);
gen9_disable_rps(dev_priv);
} else if (IS_CHERRYVIEW(dev_priv)) {
@@ -6803,7 +6823,10 @@ void intel_enable_gt_powersave(struct drm_i915_private *dev_priv)
/* We shouldn't be disabling as we submit, so this should be less
* racy than it appears!
*/
- if (READ_ONCE(dev_priv->rps.enabled))
+ if (intel_slpc_enabled()) {
+ if (intel_slpc_active(dev_priv))
+ return;
+ } else if (READ_ONCE(dev_priv->rps.enabled))
return;
/* Powersaving is controlled by the host when inside a VM */
@@ -6812,31 +6835,38 @@ void intel_enable_gt_powersave(struct drm_i915_private *dev_priv)
mutex_lock(&dev_priv->rps.hw_lock);
- if (IS_CHERRYVIEW(dev_priv)) {
- cherryview_enable_rps(dev_priv);
- } else if (IS_VALLEYVIEW(dev_priv)) {
- valleyview_enable_rps(dev_priv);
- } else if (INTEL_GEN(dev_priv) >= 9) {
+ if (intel_slpc_enabled()) {
gen9_enable_rc6(dev_priv);
- gen9_enable_rps(dev_priv);
+ intel_slpc_enable(dev_priv);
if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
gen6_update_ring_freq(dev_priv);
- } else if (IS_BROADWELL(dev_priv)) {
- gen8_enable_rps(dev_priv);
- gen6_update_ring_freq(dev_priv);
- } else if (INTEL_GEN(dev_priv) >= 6) {
- gen6_enable_rps(dev_priv);
- gen6_update_ring_freq(dev_priv);
- } else if (IS_IRONLAKE_M(dev_priv)) {
- ironlake_enable_drps(dev_priv);
- intel_init_emon(dev_priv);
- }
+ } else {
+ if (IS_CHERRYVIEW(dev_priv)) {
+ cherryview_enable_rps(dev_priv);
+ } else if (IS_VALLEYVIEW(dev_priv)) {
+ valleyview_enable_rps(dev_priv);
+ } else if (INTEL_GEN(dev_priv) >= 9) {
+ gen9_enable_rc6(dev_priv);
+ gen9_enable_rps(dev_priv);
+ if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
+ gen6_update_ring_freq(dev_priv);
+ } else if (IS_BROADWELL(dev_priv)) {
+ gen8_enable_rps(dev_priv);
+ gen6_update_ring_freq(dev_priv);
+ } else if (INTEL_GEN(dev_priv) >= 6) {
+ gen6_enable_rps(dev_priv);
+ gen6_update_ring_freq(dev_priv);
+ } else if (IS_IRONLAKE_M(dev_priv)) {
+ ironlake_enable_drps(dev_priv);
+ intel_init_emon(dev_priv);
+ }
- WARN_ON(dev_priv->rps.max_freq < dev_priv->rps.min_freq);
- WARN_ON(dev_priv->rps.idle_freq > dev_priv->rps.max_freq);
+ WARN_ON(dev_priv->rps.max_freq < dev_priv->rps.min_freq);
+ WARN_ON(dev_priv->rps.idle_freq > dev_priv->rps.max_freq);
- WARN_ON(dev_priv->rps.efficient_freq < dev_priv->rps.min_freq);
- WARN_ON(dev_priv->rps.efficient_freq > dev_priv->rps.max_freq);
+ WARN_ON(dev_priv->rps.efficient_freq < dev_priv->rps.min_freq);
+ WARN_ON(dev_priv->rps.efficient_freq > dev_priv->rps.max_freq);
+ }
mutex_unlock(&dev_priv->rps.hw_lock);
}
@@ -6848,7 +6878,10 @@ static void __intel_autoenable_gt_powersave(struct work_struct *work)
struct intel_engine_cs *rcs;
struct drm_i915_gem_request *req;
- if (READ_ONCE(dev_priv->rps.enabled))
+ if (intel_slpc_enabled()) {
+ if (intel_slpc_active(dev_priv))
+ goto out;
+ } else if (READ_ONCE(dev_priv->rps.enabled))
goto out;
rcs = &dev_priv->engine[RCS];
@@ -6878,7 +6911,10 @@ out:
void intel_autoenable_gt_powersave(struct drm_i915_private *dev_priv)
{
- if (READ_ONCE(dev_priv->rps.enabled))
+ if (intel_slpc_enabled()) {
+ if (intel_slpc_active(dev_priv))
+ return;
+ } else if (READ_ONCE(dev_priv->rps.enabled))
return;
if (IS_IRONLAKE_M(dev_priv)) {
new file mode 100644
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2015 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+#include <linux/firmware.h>
+#include "i915_drv.h"
+#include "intel_guc.h"
+
+void intel_slpc_init(struct drm_i915_private *dev_priv)
+{
+}
+
+void intel_slpc_cleanup(struct drm_i915_private *dev_priv)
+{
+}
+
+void intel_slpc_suspend(struct drm_i915_private *dev_priv)
+{
+}
+
+void intel_slpc_disable(struct drm_i915_private *dev_priv)
+{
+}
+
+void intel_slpc_enable(struct drm_i915_private *dev_priv)
+{
+}
+
+void intel_slpc_reset(struct drm_i915_private *dev_priv)
+{
+}
new file mode 100644
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2015 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+#ifndef _INTEL_SLPC_H_
+#define _INTEL_SLPC_H_
+
+/* intel_slpc.c */
+void intel_slpc_init(struct drm_i915_private *dev_priv);
+void intel_slpc_cleanup(struct drm_i915_private *dev_priv);
+void intel_slpc_suspend(struct drm_i915_private *dev_priv);
+void intel_slpc_disable(struct drm_i915_private *dev_priv);
+void intel_slpc_enable(struct drm_i915_private *dev_priv);
+void intel_slpc_reset(struct drm_i915_private *dev_priv);
+
+#endif