@@ -1152,6 +1152,33 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_scheduler_priority_max_fops,
"0x%llx\n");
static int
+i915_scheduler_priority_bump_get(void *data, u64 *val)
+{
+ struct drm_device *dev = data;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct i915_scheduler *scheduler = dev_priv->scheduler;
+
+ *val = (u64) scheduler->priority_level_bump;
+ return 0;
+}
+
+static int
+i915_scheduler_priority_bump_set(void *data, u64 val)
+{
+ struct drm_device *dev = data;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct i915_scheduler *scheduler = dev_priv->scheduler;
+
+ scheduler->priority_level_bump = (u32) val;
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(i915_scheduler_priority_bump_fops,
+ i915_scheduler_priority_bump_get,
+ i915_scheduler_priority_bump_set,
+ "0x%llx\n");
+
+static int
i915_scheduler_priority_preempt_get(void *data, u64 *val)
{
struct drm_device *dev = data;
@@ -5349,6 +5376,7 @@ static const struct i915_debugfs_files {
{"i915_error_state", &i915_error_state_fops},
{"i915_next_seqno", &i915_next_seqno_fops},
{"i915_scheduler_priority_max", &i915_scheduler_priority_max_fops},
+ {"i915_scheduler_priority_bump", &i915_scheduler_priority_bump_fops},
{"i915_scheduler_priority_preempt", &i915_scheduler_priority_preempt_fops},
{"i915_scheduler_min_flying", &i915_scheduler_min_flying_fops},
{"i915_scheduler_file_queue_max", &i915_scheduler_file_queue_max_fops},
@@ -191,6 +191,7 @@ int i915_scheduler_init(struct drm_device *dev)
/* Default tuning values: */
scheduler->priority_level_max = ~0U;
+ scheduler->priority_level_bump = 50;
scheduler->priority_level_preempt = 900;
scheduler->min_flying = 2;
scheduler->file_queue_max = 64;
@@ -1568,6 +1569,19 @@ static int i915_scheduler_submit(struct intel_engine_cs *ring, bool was_locked)
ret = i915_scheduler_pop_from_queue_locked(ring, &node, &flags);
} while (ret == 0);
+ /*
+ * Bump the priority of everything that was not submitted to prevent
+ * starvation of low priority tasks by a spamming high priority task.
+ */
+ i915_scheduler_priority_bump_clear(scheduler);
+ list_for_each_entry(node, &scheduler->node_queue[ring->id], link) {
+ if (!I915_SQS_IS_QUEUED(node))
+ continue;
+
+ i915_scheduler_priority_bump(scheduler, node,
+ scheduler->priority_level_bump);
+ }
+
spin_unlock_irqrestore(&scheduler->lock, flags);
if (!was_locked)
@@ -119,6 +119,7 @@ struct i915_scheduler {
/* Tuning parameters: */
uint32_t priority_level_max;
+ uint32_t priority_level_bump;
uint32_t priority_level_preempt;
uint32_t min_flying;
uint32_t file_queue_max;