[PATCH 64/64] ctx-freq
Chris Wilson
chris at chris-wilson.co.uk
Fri Jan 19 00:22:57 UTC 2018
---
drivers/gpu/drm/i915/i915_debugfs.c | 4 ++-
drivers/gpu/drm/i915/i915_drv.h | 2 ++
drivers/gpu/drm/i915/i915_gem_context.c | 46 +++++++++++++++++++++++++++++
drivers/gpu/drm/i915/i915_gem_context.h | 3 ++
drivers/gpu/drm/i915/intel_gt_pm.c | 34 +++++++++++++++++++--
drivers/gpu/drm/i915/intel_gt_pm.h | 7 +++++
drivers/gpu/drm/i915/intel_guc_submission.c | 9 ++++++
drivers/gpu/drm/i915/intel_lrc.c | 8 +++++
include/uapi/drm/i915_drm.h | 4 +++
9 files changed, 113 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 73dbb5be3930..e4ae35df1322 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2158,9 +2158,11 @@ static int i915_rps_boost_info(struct seq_file *m, void *data)
intel_gpu_freq(dev_priv, rps->freq),
intel_gpu_freq(dev_priv, rps->min),
intel_gpu_freq(dev_priv, rps->max));
- seq_printf(m, " min hard:%d, user:%d; max user:%d, hard:%d\n",
+ seq_printf(m, " min hard:%d, user:%d, ctx:%d; max ctx:%d, user:%d, hard:%d\n",
intel_gpu_freq(dev_priv, rps->min_freq_hw),
intel_gpu_freq(dev_priv, rps->min_freq_user),
+ intel_gpu_freq(dev_priv, rps->min_freq_context),
+ intel_gpu_freq(dev_priv, rps->max_freq_context),
intel_gpu_freq(dev_priv, rps->max_freq_user),
intel_gpu_freq(dev_priv, rps->max_freq_hw));
seq_printf(m, " idle:%d, efficient:%d, boost:%d\n",
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index a193da6c10c0..e30947457d7b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -920,6 +920,8 @@ struct intel_rps {
u8 max_freq_user; /* Max frequency permitted by the driver */
u8 min_freq_soft;
u8 max_freq_soft;
+ u8 min_freq_context; /* Minimum frequency permitted by the context */
+ u8 max_freq_context; /* Max frequency permitted by the context */
u8 idle_freq; /* Frequency to request when we are idle */
u8 efficient_freq; /* AKA RPe. Pre-determined balanced frequency */
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index fcbcb7b9eea9..dec5ece0b54c 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -88,8 +88,10 @@
#include <linux/log2.h>
#include <drm/drmP.h>
#include <drm/i915_drm.h>
+
#include "i915_drv.h"
#include "i915_trace.h"
+#include "intel_gt_pm.h"
#define ALL_L3_SLICES(dev) (1 << NUM_L3_SLICES(dev)) - 1
@@ -250,6 +252,8 @@ __create_hw_context(struct drm_i915_private *dev_priv,
list_add_tail(&ctx->link, &dev_priv->contexts.list);
ctx->i915 = dev_priv;
ctx->priority = I915_PRIORITY_NORMAL;
+ ctx->min_freq = dev_priv->gt_pm.rps.min_freq_hw;
+ ctx->max_freq = dev_priv->gt_pm.rps.max_freq_hw;
INIT_RADIX_TREE(&ctx->handles_vma, GFP_KERNEL);
INIT_LIST_HEAD(&ctx->handles_list);
@@ -742,6 +746,7 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
{
struct drm_i915_file_private *file_priv = file->driver_priv;
struct drm_i915_gem_context_param *args = data;
+ struct drm_i915_private *i915 = to_i915(dev);
struct i915_gem_context *ctx;
int ret = 0;
@@ -774,6 +779,18 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
case I915_CONTEXT_PARAM_PRIORITY:
args->value = ctx->priority >> I915_PRIORITY_SHIFT;
break;
+ case I915_CONTEXT_PARAM_FREQUENCY:
+ if (!HAS_RPS(i915) || !HAS_EXECLISTS(i915)) {
+ ret = -ENODEV;
+ } else if (args->size) {
+ ret = -EINVAL;
+ } else {
+ u32 min = intel_gpu_freq(i915, ctx->min_freq);
+ u32 max = intel_gpu_freq(i915, ctx->max_freq);
+ args->value = I915_CONTEXT_SET_FREQUENCY(min, max);
+ }
+ break;
+
default:
ret = -EINVAL;
break;
@@ -788,6 +805,7 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
{
struct drm_i915_file_private *file_priv = file->driver_priv;
struct drm_i915_gem_context_param *args = data;
+ struct drm_i915_private *i915 = to_i915(dev);
struct i915_gem_context *ctx;
int ret;
@@ -848,6 +866,34 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
ctx->priority = priority << I915_PRIORITY_SHIFT;
}
break;
+ case I915_CONTEXT_PARAM_FREQUENCY:
+ if (!HAS_RPS(i915) || !HAS_EXECLISTS(i915)) {
+ ret = -ENODEV;
+ } else if (args->size) {
+ ret = -EINVAL;
+ } else {
+ struct intel_rps *rps = &i915->gt_pm.rps;
+ u32 min, max;
+
+ min = intel_freq_opcode(i915,
+ I915_CONTEXT_MIN_FREQUENCY(args->value));
+ max = intel_freq_opcode(i915,
+ I915_CONTEXT_MAX_FREQUENCY(args->value));
+ if (max < min) {
+ ret = -EINVAL;
+ } else if (min < rps->min_freq_hw ||
+ max > rps->max_freq_hw) {
+ ret = -EINVAL;
+ } else if ((min > ctx->min_freq ||
+ max > ctx->max_freq) &&
+ !capable(CAP_SYS_NICE)) {
+ ret = -EPERM;
+ } else {
+ ctx->min_freq = min;
+ ctx->max_freq = max;
+ }
+ }
+ break;
default:
ret = -EINVAL;
diff --git a/drivers/gpu/drm/i915/i915_gem_context.h b/drivers/gpu/drm/i915/i915_gem_context.h
index c49c5f0cd4a0..9cb28d32805a 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.h
+++ b/drivers/gpu/drm/i915/i915_gem_context.h
@@ -150,6 +150,9 @@ struct i915_gem_context {
*/
int priority;
+ u32 min_freq;
+ u32 max_freq;
+
/** ggtt_offset_bias: placement restriction for context objects */
u32 ggtt_offset_bias;
diff --git a/drivers/gpu/drm/i915/intel_gt_pm.c b/drivers/gpu/drm/i915/intel_gt_pm.c
index d7bc47cf5c98..b2962c0d737b 100644
--- a/drivers/gpu/drm/i915/intel_gt_pm.c
+++ b/drivers/gpu/drm/i915/intel_gt_pm.c
@@ -418,7 +418,6 @@ static int intel_set_rps(struct drm_i915_private *dev_priv, int freq)
return 0;
}
-
static void vlv_c0_read(struct drm_i915_private *dev_priv,
struct intel_rps_ei *ei)
{
@@ -516,10 +515,10 @@ static void intel_rps_work(struct work_struct *work)
mutex_lock(&rps->lock);
min = clamp_t(int,
- rps->min_freq_soft,
+ max(rps->min_freq_soft, rps->min_freq_context),
rps->min_freq_user, rps->max_freq_user);
max = clamp_t(int,
- rps->max_freq_soft,
+ min(rps->max_freq_soft, rps->max_freq_context),
rps->min_freq_user, rps->max_freq_user);
if (client_boost && max < rps->boost_freq)
max = rps->boost_freq;
@@ -685,6 +684,32 @@ void intel_rps_boost(struct drm_i915_gem_request *rq,
atomic_inc(rps_client ? &rps_client->boosts : &rps->boosts);
}
+void intel_rps_update_context(struct drm_i915_private *i915,
+ const struct i915_gem_context *ctx)
+{
+ struct intel_rps *rps = &i915->gt_pm.rps;
+ u32 cur;
+
+ if (!HAS_RPS(i915))
+ return;
+
+ /*
+ * A race here has no effect as we will pick up the change on the next
+ * cycle.
+ */
+ rps->min_freq_context = ctx->min_freq;
+ rps->max_freq_context = ctx->max_freq;
+
+ /*
+ * If we are running below the request frequested, kick the worker to
+ * jump to the new frequency. Otherwise, we let the frequency decay
+ * naturally.
+ */
+ cur = READ_ONCE(rps->freq);
+ if (cur < ctx->min_freq)
+ schedule_work(&rps->work);
+}
+
static void gen9_disable_rc6(struct drm_i915_private *dev_priv)
{
I915_WRITE(GEN6_RC_CONTROL, 0);
@@ -2262,6 +2287,9 @@ void intel_gt_pm_init(struct drm_i915_private *dev_priv)
rps->max_freq_soft = rps->max_freq_hw;
rps->min_freq_soft = rps->min_freq_hw;
+ rps->max_freq_context = rps->max_freq_hw;
+ rps->min_freq_context = rps->min_freq_hw;
+
/* Finally allow us to boost to max by default */
rps->boost_freq = rps->max_freq_hw;
diff --git a/drivers/gpu/drm/i915/intel_gt_pm.h b/drivers/gpu/drm/i915/intel_gt_pm.h
index fd2dbe381f32..5c318605c7d8 100644
--- a/drivers/gpu/drm/i915/intel_gt_pm.h
+++ b/drivers/gpu/drm/i915/intel_gt_pm.h
@@ -24,6 +24,11 @@
#ifndef __INTEL_GT_PM_H__
#define __INTEL_GT_PM_H__
+struct drm_i915_private;
+struct drm_i915_gem_request;
+struct i915_gem_context;
+struct intel_rps_client;
+
void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
void intel_gpu_ips_teardown(void);
@@ -40,6 +45,8 @@ void intel_gt_disable_rc6(struct drm_i915_private *dev_priv);
void intel_rps_busy(struct drm_i915_private *dev_priv);
void intel_rps_idle(struct drm_i915_private *dev_priv);
+void intel_rps_update_context(struct drm_i915_private *i915,
+ const struct i915_gem_context *ctx);
void intel_rps_boost(struct drm_i915_gem_request *rq,
struct intel_rps_client *rps);
diff --git a/drivers/gpu/drm/i915/intel_guc_submission.c b/drivers/gpu/drm/i915/intel_guc_submission.c
index 528529c3abcf..d5544b573e11 100644
--- a/drivers/gpu/drm/i915/intel_guc_submission.c
+++ b/drivers/gpu/drm/i915/intel_guc_submission.c
@@ -26,6 +26,8 @@
#include <trace/events/dma_fence.h>
#include "intel_guc_submission.h"
+
+#include "intel_gt_pm.h"
#include "i915_drv.h"
/**
@@ -662,6 +664,12 @@ static void guc_submit(struct intel_engine_cs *engine)
}
}
+static void update_rps(struct intel_engine_cs *engine)
+{
+ intel_rps_update_context(engine->i915,
+ port_request(engine->execlists.port)->ctx);
+}
+
static void port_assign(struct execlist_port *port,
struct drm_i915_gem_request *rq)
{
@@ -740,6 +748,7 @@ static void guc_dequeue(struct intel_engine_cs *engine)
done:
if (submit) {
port_assign(port, last);
+ update_rps(engine);
execlists_set_active(execlists, EXECLISTS_ACTIVE_USER);
guc_submit(engine);
}
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index e1995e8e6d1d..9db495c6bfc1 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -137,6 +137,7 @@
#include <drm/i915_drm.h>
#include "i915_drv.h"
#include "i915_gem_render_state.h"
+#include "intel_gt_pm.h"
#include "intel_mocs.h"
#define RING_EXECLIST_QFULL (1 << 0x2)
@@ -509,6 +510,12 @@ static void inject_preempt_context(struct intel_engine_cs *engine)
execlists_clear_active(&engine->execlists, EXECLISTS_ACTIVE_HWACK);
}
+static void update_rps(struct intel_engine_cs *engine)
+{
+ intel_rps_update_context(engine->i915,
+ port_request(engine->execlists.port)->ctx);
+}
+
static void execlists_dequeue(struct intel_engine_cs *engine)
{
struct intel_engine_execlists * const execlists = &engine->execlists;
@@ -682,6 +689,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
spin_unlock_irq(&engine->timeline->lock);
if (submit) {
+ update_rps(engine);
execlists_set_active(execlists, EXECLISTS_ACTIVE_USER);
execlists_submit_ports(engine);
}
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 3f7c9702a913..866ef066c40d 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -1461,6 +1461,10 @@ struct drm_i915_gem_context_param {
#define I915_CONTEXT_MAX_USER_PRIORITY 1023 /* inclusive */
#define I915_CONTEXT_DEFAULT_PRIORITY 0
#define I915_CONTEXT_MIN_USER_PRIORITY -1023 /* inclusive */
+#define I915_CONTEXT_PARAM_FREQUENCY 0x7
+#define I915_CONTEXT_MIN_FREQUENCY(x) ((x) & 0xffffffff)
+#define I915_CONTEXT_MAX_FREQUENCY(x) ((x) >> 32)
+#define I915_CONTEXT_SET_FREQUENCY(min, max) ((u64)(max) << 32 | (min))
__u64 value;
};
--
2.15.1
More information about the Intel-gfx-trybot
mailing list