aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_pm.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2017-08-17 08:37:06 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2017-08-22 12:08:06 -0400
commit74d290f845d0736bf6b9dd22cd28dd87b270c65f (patch)
tree19a439d5ebd7d20f475aeaa59a3b3e26d7122767 /drivers/gpu/drm/i915/intel_pm.c
parent5f88a9c61978b20acba4b5a76555eb3a4a03ab73 (diff)
drm/i915: Boost GPU clocks if we miss the pageflip's vblank
If we miss the current vblank because the gpu was busy, that may cause a jitter as the frame rate temporarily drops. We try to limit the impact of this by then boosting the GPU clock to deliver the frame as quickly as possible. Originally done in commit 6ad790c0f5ac ("drm/i915: Boost GPU frequency if we detect outstanding pageflips") but was never forward ported to atomic and finally dropped in commit fd3a40242e87 ("drm/i915: Rip out legacy page_flip completion/irq handling"). One of the most typical use-cases for this is a mostly idle desktop. Rendering one frame of the desktop's frontbuffer can easily be accomplished by the GPU running at low frequency, but often exceeds the time budget of the desktop compositor. The result is that animations such as opening the menu, doing a fullscreen switch, or even just trying to move a window around are slow and jerky. We need to respond within a frame to give the best impression of a smooth UX, as a compromise we instead respond if that first frame misses its goal. The result should be a near-imperceivable initial delay and a smooth animation even starting from idle. The cost, as ever, is that we spend more power than is strictly necessary as we overestimate the required GPU frequency and then try to ramp down. This of course is reactionary, too little, too late; nevertheless it is surprisingly effective. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=102199 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Daniel Vetter <daniel.vetter@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20170817123706.6777-1-chris@chris-wilson.co.uk Tested-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Radoslaw Szwichtenberg <radoslaw.szwichtenberg@intel.com>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_pm.c')
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c42
1 files changed, 3 insertions, 39 deletions
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 68187bcfded4..d5ff0b9f999f 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -6169,6 +6169,7 @@ void gen6_rps_boost(struct drm_i915_gem_request *rq,
6169 struct intel_rps_client *rps) 6169 struct intel_rps_client *rps)
6170{ 6170{
6171 struct drm_i915_private *i915 = rq->i915; 6171 struct drm_i915_private *i915 = rq->i915;
6172 unsigned long flags;
6172 bool boost; 6173 bool boost;
6173 6174
6174 /* This is intentionally racy! We peek at the state here, then 6175 /* This is intentionally racy! We peek at the state here, then
@@ -6178,13 +6179,13 @@ void gen6_rps_boost(struct drm_i915_gem_request *rq,
6178 return; 6179 return;
6179 6180
6180 boost = false; 6181 boost = false;
6181 spin_lock_irq(&rq->lock); 6182 spin_lock_irqsave(&rq->lock, flags);
6182 if (!rq->waitboost && !i915_gem_request_completed(rq)) { 6183 if (!rq->waitboost && !i915_gem_request_completed(rq)) {
6183 atomic_inc(&i915->rps.num_waiters); 6184 atomic_inc(&i915->rps.num_waiters);
6184 rq->waitboost = true; 6185 rq->waitboost = true;
6185 boost = true; 6186 boost = true;
6186 } 6187 }
6187 spin_unlock_irq(&rq->lock); 6188 spin_unlock_irqrestore(&rq->lock, flags);
6188 if (!boost) 6189 if (!boost)
6189 return; 6190 return;
6190 6191
@@ -9155,43 +9156,6 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val)
9155 return DIV_ROUND_CLOSEST(val, GT_FREQUENCY_MULTIPLIER); 9156 return DIV_ROUND_CLOSEST(val, GT_FREQUENCY_MULTIPLIER);
9156} 9157}
9157 9158
9158struct request_boost {
9159 struct work_struct work;
9160 struct drm_i915_gem_request *req;
9161};
9162
9163static void __intel_rps_boost_work(struct work_struct *work)
9164{
9165 struct request_boost *boost = container_of(work, struct request_boost, work);
9166 struct drm_i915_gem_request *req = boost->req;
9167
9168 if (!i915_gem_request_completed(req))
9169 gen6_rps_boost(req, NULL);
9170
9171 i915_gem_request_put(req);
9172 kfree(boost);
9173}
9174
9175void intel_queue_rps_boost_for_request(struct drm_i915_gem_request *req)
9176{
9177 struct request_boost *boost;
9178
9179 if (req == NULL || INTEL_GEN(req->i915) < 6)
9180 return;
9181
9182 if (i915_gem_request_completed(req))
9183 return;
9184
9185 boost = kmalloc(sizeof(*boost), GFP_ATOMIC);
9186 if (boost == NULL)
9187 return;
9188
9189 boost->req = i915_gem_request_get(req);
9190
9191 INIT_WORK(&boost->work, __intel_rps_boost_work);
9192 queue_work(req->i915->wq, &boost->work);
9193}
9194
9195void intel_pm_setup(struct drm_i915_private *dev_priv) 9159void intel_pm_setup(struct drm_i915_private *dev_priv)
9196{ 9160{
9197 mutex_init(&dev_priv->rps.hw_lock); 9161 mutex_init(&dev_priv->rps.hw_lock);