aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2015-04-07 11:20:32 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2015-04-10 02:56:02 -0400
commit1854d5ca0dd7a9fc11243ff220a3e93fce2b4d3e (patch)
tree6a83912410f343ae5abd1a03aa37a454b9ca2a24
parent6ad790c0f5ac55fd13f322c23519f0d6f0721864 (diff)
drm/i915: Deminish contribution of wait-boosting from clients
With boosting for missed pageflips, we have a much stronger indication of when we need to (temporarily) boost GPU frequency to ensure smooth delivery of frames. So now only allow each client to perform one RPS boost in each period of GPU activity due to stalling on results. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Deepak S <deepak.s@linux.intel.com> Reviewed-by: Deepak S <deepak.s@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c39
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h9
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c35
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h3
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c18
5 files changed, 70 insertions, 34 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 10ca5117fcee..9c23eec3277e 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2239,6 +2239,44 @@ static int i915_ppgtt_info(struct seq_file *m, void *data)
2239 return 0; 2239 return 0;
2240} 2240}
2241 2241
2242static int i915_rps_boost_info(struct seq_file *m, void *data)
2243{
2244 struct drm_info_node *node = m->private;
2245 struct drm_device *dev = node->minor->dev;
2246 struct drm_i915_private *dev_priv = dev->dev_private;
2247 struct drm_file *file;
2248 int ret;
2249
2250 ret = mutex_lock_interruptible(&dev->struct_mutex);
2251 if (ret)
2252 return ret;
2253
2254 ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
2255 if (ret)
2256 goto unlock;
2257
2258 list_for_each_entry_reverse(file, &dev->filelist, lhead) {
2259 struct drm_i915_file_private *file_priv = file->driver_priv;
2260 struct task_struct *task;
2261
2262 rcu_read_lock();
2263 task = pid_task(file->pid, PIDTYPE_PID);
2264 seq_printf(m, "%s [%d]: %d boosts%s\n",
2265 task ? task->comm : "<unknown>",
2266 task ? task->pid : -1,
2267 file_priv->rps_boosts,
2268 list_empty(&file_priv->rps_boost) ? "" : ", active");
2269 rcu_read_unlock();
2270 }
2271 seq_printf(m, "Kernel boosts: %d\n", dev_priv->rps.boosts);
2272
2273 mutex_unlock(&dev_priv->rps.hw_lock);
2274unlock:
2275 mutex_unlock(&dev->struct_mutex);
2276
2277 return ret;
2278}
2279
2242static int i915_llc(struct seq_file *m, void *data) 2280static int i915_llc(struct seq_file *m, void *data)
2243{ 2281{
2244 struct drm_info_node *node = m->private; 2282 struct drm_info_node *node = m->private;
@@ -4704,6 +4742,7 @@ static const struct drm_info_list i915_debugfs_list[] = {
4704 {"i915_ddb_info", i915_ddb_info, 0}, 4742 {"i915_ddb_info", i915_ddb_info, 0},
4705 {"i915_sseu_status", i915_sseu_status, 0}, 4743 {"i915_sseu_status", i915_sseu_status, 0},
4706 {"i915_drrs_status", i915_drrs_status, 0}, 4744 {"i915_drrs_status", i915_drrs_status, 0},
4745 {"i915_rps_boost_info", i915_rps_boost_info, 0},
4707}; 4746};
4708#define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list) 4747#define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
4709 4748
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index b4501647795e..3b6ddd74cd69 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1043,6 +1043,8 @@ struct intel_gen6_power_mgmt {
1043 1043
1044 bool enabled; 1044 bool enabled;
1045 struct delayed_work delayed_resume_work; 1045 struct delayed_work delayed_resume_work;
1046 struct list_head clients;
1047 unsigned boosts;
1046 1048
1047 /* manual wa residency calculations */ 1049 /* manual wa residency calculations */
1048 struct intel_rps_ei up_ei, down_ei; 1050 struct intel_rps_ei up_ei, down_ei;
@@ -2190,12 +2192,13 @@ struct drm_i915_file_private {
2190 struct { 2192 struct {
2191 spinlock_t lock; 2193 spinlock_t lock;
2192 struct list_head request_list; 2194 struct list_head request_list;
2193 struct delayed_work idle_work;
2194 } mm; 2195 } mm;
2195 struct idr context_idr; 2196 struct idr context_idr;
2196 2197
2197 atomic_t rps_wait_boost; 2198 struct list_head rps_boost;
2198 struct intel_engine_cs *bsd_ring; 2199 struct intel_engine_cs *bsd_ring;
2200
2201 unsigned rps_boosts;
2199}; 2202};
2200 2203
2201/* 2204/*
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 976d27a19192..4061b4ffe815 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1181,14 +1181,6 @@ static bool missed_irq(struct drm_i915_private *dev_priv,
1181 return test_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings); 1181 return test_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings);
1182} 1182}
1183 1183
1184static bool can_wait_boost(struct drm_i915_file_private *file_priv)
1185{
1186 if (file_priv == NULL)
1187 return true;
1188
1189 return !atomic_xchg(&file_priv->rps_wait_boost, true);
1190}
1191
1192/** 1184/**
1193 * __i915_wait_request - wait until execution of request has finished 1185 * __i915_wait_request - wait until execution of request has finished
1194 * @req: duh! 1186 * @req: duh!
@@ -1230,13 +1222,8 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
1230 timeout_expire = timeout ? 1222 timeout_expire = timeout ?
1231 jiffies + nsecs_to_jiffies_timeout((u64)*timeout) : 0; 1223 jiffies + nsecs_to_jiffies_timeout((u64)*timeout) : 0;
1232 1224
1233 if (INTEL_INFO(dev)->gen >= 6 && ring->id == RCS && can_wait_boost(file_priv)) { 1225 if (ring->id == RCS && INTEL_INFO(dev)->gen >= 6)
1234 gen6_rps_boost(dev_priv); 1226 gen6_rps_boost(dev_priv, file_priv);
1235 if (file_priv)
1236 mod_delayed_work(dev_priv->wq,
1237 &file_priv->mm.idle_work,
1238 msecs_to_jiffies(100));
1239 }
1240 1227
1241 if (!irq_test_in_progress && WARN_ON(!ring->irq_get(ring))) 1228 if (!irq_test_in_progress && WARN_ON(!ring->irq_get(ring)))
1242 return -ENODEV; 1229 return -ENODEV;
@@ -5043,8 +5030,6 @@ void i915_gem_release(struct drm_device *dev, struct drm_file *file)
5043{ 5030{
5044 struct drm_i915_file_private *file_priv = file->driver_priv; 5031 struct drm_i915_file_private *file_priv = file->driver_priv;
5045 5032
5046 cancel_delayed_work_sync(&file_priv->mm.idle_work);
5047
5048 /* Clean up our request list when the client is going away, so that 5033 /* Clean up our request list when the client is going away, so that
5049 * later retire_requests won't dereference our soon-to-be-gone 5034 * later retire_requests won't dereference our soon-to-be-gone
5050 * file_priv. 5035 * file_priv.
@@ -5060,15 +5045,12 @@ void i915_gem_release(struct drm_device *dev, struct drm_file *file)
5060 request->file_priv = NULL; 5045 request->file_priv = NULL;
5061 } 5046 }
5062 spin_unlock(&file_priv->mm.lock); 5047 spin_unlock(&file_priv->mm.lock);
5063}
5064
5065static void
5066i915_gem_file_idle_work_handler(struct work_struct *work)
5067{
5068 struct drm_i915_file_private *file_priv =
5069 container_of(work, typeof(*file_priv), mm.idle_work.work);
5070 5048
5071 atomic_set(&file_priv->rps_wait_boost, false); 5049 if (!list_empty(&file_priv->rps_boost)) {
5050 mutex_lock(&to_i915(dev)->rps.hw_lock);
5051 list_del(&file_priv->rps_boost);
5052 mutex_unlock(&to_i915(dev)->rps.hw_lock);
5053 }
5072} 5054}
5073 5055
5074int i915_gem_open(struct drm_device *dev, struct drm_file *file) 5056int i915_gem_open(struct drm_device *dev, struct drm_file *file)
@@ -5085,11 +5067,10 @@ int i915_gem_open(struct drm_device *dev, struct drm_file *file)
5085 file->driver_priv = file_priv; 5067 file->driver_priv = file_priv;
5086 file_priv->dev_priv = dev->dev_private; 5068 file_priv->dev_priv = dev->dev_private;
5087 file_priv->file = file; 5069 file_priv->file = file;
5070 INIT_LIST_HEAD(&file_priv->rps_boost);
5088 5071
5089 spin_lock_init(&file_priv->mm.lock); 5072 spin_lock_init(&file_priv->mm.lock);
5090 INIT_LIST_HEAD(&file_priv->mm.request_list); 5073 INIT_LIST_HEAD(&file_priv->mm.request_list);
5091 INIT_DELAYED_WORK(&file_priv->mm.idle_work,
5092 i915_gem_file_idle_work_handler);
5093 5074
5094 ret = i915_gem_context_open(dev, file); 5075 ret = i915_gem_context_open(dev, file);
5095 if (ret) 5076 if (ret)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 4771d319ac7b..efa53d57dd37 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1262,7 +1262,8 @@ void gen6_update_ring_freq(struct drm_device *dev);
1262void gen6_rps_busy(struct drm_i915_private *dev_priv); 1262void gen6_rps_busy(struct drm_i915_private *dev_priv);
1263void gen6_rps_reset_ei(struct drm_i915_private *dev_priv); 1263void gen6_rps_reset_ei(struct drm_i915_private *dev_priv);
1264void gen6_rps_idle(struct drm_i915_private *dev_priv); 1264void gen6_rps_idle(struct drm_i915_private *dev_priv);
1265void gen6_rps_boost(struct drm_i915_private *dev_priv); 1265void gen6_rps_boost(struct drm_i915_private *dev_priv,
1266 struct drm_i915_file_private *file_priv);
1266void intel_queue_rps_boost_for_request(struct drm_device *dev, 1267void intel_queue_rps_boost_for_request(struct drm_device *dev,
1267 struct drm_i915_gem_request *rq); 1268 struct drm_i915_gem_request *rq);
1268void ilk_wm_get_hw_state(struct drm_device *dev); 1269void ilk_wm_get_hw_state(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index acf1a318fda9..1ab9e897994a 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -4091,10 +4091,14 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv)
4091 dev_priv->rps.last_adj = 0; 4091 dev_priv->rps.last_adj = 0;
4092 I915_WRITE(GEN6_PMINTRMSK, 0xffffffff); 4092 I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
4093 } 4093 }
4094
4095 while (!list_empty(&dev_priv->rps.clients))
4096 list_del_init(dev_priv->rps.clients.next);
4094 mutex_unlock(&dev_priv->rps.hw_lock); 4097 mutex_unlock(&dev_priv->rps.hw_lock);
4095} 4098}
4096 4099
4097void gen6_rps_boost(struct drm_i915_private *dev_priv) 4100void gen6_rps_boost(struct drm_i915_private *dev_priv,
4101 struct drm_i915_file_private *file_priv)
4098{ 4102{
4099 u32 val; 4103 u32 val;
4100 4104
@@ -4102,9 +4106,16 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv)
4102 val = dev_priv->rps.max_freq_softlimit; 4106 val = dev_priv->rps.max_freq_softlimit;
4103 if (dev_priv->rps.enabled && 4107 if (dev_priv->rps.enabled &&
4104 dev_priv->mm.busy && 4108 dev_priv->mm.busy &&
4105 dev_priv->rps.cur_freq < val) { 4109 dev_priv->rps.cur_freq < val &&
4110 (file_priv == NULL || list_empty(&file_priv->rps_boost))) {
4106 intel_set_rps(dev_priv->dev, val); 4111 intel_set_rps(dev_priv->dev, val);
4107 dev_priv->rps.last_adj = 0; 4112 dev_priv->rps.last_adj = 0;
4113
4114 if (file_priv != NULL) {
4115 list_add(&file_priv->rps_boost, &dev_priv->rps.clients);
4116 file_priv->rps_boosts++;
4117 } else
4118 dev_priv->rps.boosts++;
4108 } 4119 }
4109 mutex_unlock(&dev_priv->rps.hw_lock); 4120 mutex_unlock(&dev_priv->rps.hw_lock);
4110} 4121}
@@ -6782,7 +6793,7 @@ static void __intel_rps_boost_work(struct work_struct *work)
6782 struct request_boost *boost = container_of(work, struct request_boost, work); 6793 struct request_boost *boost = container_of(work, struct request_boost, work);
6783 6794
6784 if (!i915_gem_request_completed(boost->rq, true)) 6795 if (!i915_gem_request_completed(boost->rq, true))
6785 gen6_rps_boost(to_i915(boost->rq->ring->dev)); 6796 gen6_rps_boost(to_i915(boost->rq->ring->dev), NULL);
6786 6797
6787 i915_gem_request_unreference__unlocked(boost->rq); 6798 i915_gem_request_unreference__unlocked(boost->rq);
6788 kfree(boost); 6799 kfree(boost);
@@ -6815,6 +6826,7 @@ void intel_pm_setup(struct drm_device *dev)
6815 6826
6816 INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work, 6827 INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work,
6817 intel_gen6_powersave_work); 6828 intel_gen6_powersave_work);
6829 INIT_LIST_HEAD(&dev_priv->rps.clients);
6818 6830
6819 dev_priv->pm.suspended = false; 6831 dev_priv->pm.suspended = false;
6820} 6832}